android之Radio状态
android 5.1
在Java层,Radio只有三种状态:
enum RadioState { RADIO_OFF, /* Radio explicitly powered off (eg CFUN=0) */ RADIO_UNAVAILABLE, /* Radio unavailable (eg, resetting or not booted) */ RADIO_ON; /* Radio is on */ public boolean isOn() /* and available...*/ { return this == RADIO_ON; } public boolean isAvailable() { return this != RADIO_UNAVAILABLE; } }
在C层,radio有多个状态:
状态转换在RIL.java中的getRadioStateFromInt方法中
第一,在rild和RILJ中,radio初始状态都是UNAVAILABLE
rild进程启动时,radio的状态默认会设置为RADIO_STATE_UNAVAILABLE
reference-ril.c
static RIL_RadioState sState = RADIO_STATE_UNAVAILABLE;
RILJ初始化时,Radio状态为RADIO_UNAVAILABLE
BaseCommands.java
protected RadioState mState = RadioState.RADIO_UNAVAILABLE;
1. rild.cpp main()
rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");funcs = rilInit(&s_rilEnv, argc, rilArgv);
2. reference-ril.c
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);static void initializeCallback(void *param __unused)setRadioState (RADIO_STATE_OFF);
第三,rild中,radio状态切换为OFF后,会通知RILJ
RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0); // Sim state can change as result of radio state change RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);
第四,RILJ收到radio的新状态,会去通知关心RadioStateChange和RadioAvailable的订阅者
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: /* has bonus radio state int */ RadioState newState = getRadioStateFromInt(p.readInt()); if (RILJ_LOGD) unsljLogMore(response, newState.toString()); switchToRadioState(newState);private void switchToRadioState(RadioState newState) { setRadioState(newState);}protected void setRadioState(RadioState newState) { mRadioStateChangedRegistrants.notifyRegistrants(); if (mState.isAvailable() && !oldState.isAvailable()) { mAvailRegistrants.notifyRegistrants(); onRadioAvailable(); }}
第五,只有ServiceStateTracker关心RadioStateChange,它会请求RILJ去打开radio
忽略RadioAvailable的订阅者,同时也忽略CDMA,只关注GSM
GsmServiceStateTracker.java
public GsmServiceStateTracker(GSMPhone phone) { mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); // system setting property AIRPLANE_MODE_ON is set in Settings. int airplaneMode = Settings.Global.getInt( phone.getContext().getContentResolver(), Settings.Global.AIRPLANE_MODE_ON, 0); mDesiredPowerState = ! (airplaneMode > 0);}case EVENT_RADIO_STATE_CHANGED: // This will do nothing in the radio not // available case setPowerStateToDesired(); pollState(); break;protected void setPowerStateToDesired() { // If we want it on and it's off, turn it on if (mDesiredPowerState && mCi.getRadioState() == CommandsInterface.RadioState.RADIO_OFF) { mCi.setRadioPower(true, null); }}
第六,RILJ去和rild通信,请求打开radio:RIL_REQUEST_RADIO_POWER
注意:GSMSST虽然通过RILJ向rild发送request,但它并不关心返回的结果,所以Msg是null,它是通过订阅来得到相应的结果
setRadioPower(boolean on, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result); rr.mParcel.writeInt(1); rr.mParcel.writeInt(on ? 1 : 0); send(rr);}
第七,rild去打开radio
通过AT命令打开radio:AT+CFUN=1
检查radio当前的状态:AT+CFUN?
最重要的是setRadioState(RADIO_STATE_ON);
它会通知到RILJ,radio状态又改变啦
RILJ向rild的每个Request,rild都会发回RESPONSE_SOLICITED给RILJ,但对于radio,RILJ不关心SOLICITE,只关心RESPONSE_UNSOLICITED
reference-ril.cstatic void onRequest (int request, void *data, size_t datalen, RIL_Token t){case RIL_REQUEST_RADIO_POWER:requestRadioPower(data, datalen, t);break;}static void requestRadioPower(void *data, size_t datalen, RIL_Token t){ int onOff = ((int *)data)[0]; if (onOff > 0 && sState == RADIO_STATE_OFF) { err = at_send_command("AT+CFUN=1", &p_response); if (err < 0|| p_response->success == 0) { // Some stacks return an error when there is no SIM, // but they really turn the RF portion on // So, if we get an error, let's check to see if it // turned on anyway if (isRadioOn() != 1) { goto error; } } setRadioState(RADIO_STATE_ON); } at_response_free(p_response); RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); return;}/** returns 1 if on, 0 if off, and -1 on error */static int isRadioOn(){ err = at_send_command_singleline("AT+CFUN?", "+CFUN:", &p_response); line = p_response->p_intermediates->line; err = at_tok_start(&line); err = at_tok_nextbool(&line, &ret); return (int)ret;}
第八,rild又要去通知RILJ
于之前setradio OFF不同的是,此时可以去获取SIM卡的状态啦
static void setRadioState(RIL_RadioState newState){RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, NULL, 0);RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, NULL, 0);if (sState == RADIO_STATE_ON) {onRadioPowerOn();}}static void onRadioPowerOn(){pollSIMState(NULL);}
第九,RILJ要把事件发给订阅radostatechanged的和radioon的
protected void setRadioState(RadioState newState) { mRadioStateChangedRegistrants.notifyRegistrants(); if (mState.isOn() && !oldState.isOn()) { mOnRegistrants.notifyRegistrants(); }}
但这一回,GSMSST什么也没必要干了,除了再重新去pollState() 说说关心radio avaliable的吧:GSMPhone.java
在radio avaliable之后,去获取一些重要信息:BasebandVersion,IMEI,IMEISV,RadioCapability
mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);case EVENT_RADIO_AVAILABLE: { mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE)); mCi.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE)); mCi.getIMEISV(obtainMessage(EVENT_GET_IMEISV_DONE)); mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));}
说说关心radio on的吧:UiccController.java
这是SIM卡管理的核心类,看这注释你就直到它有多重要
* Following is class diagram for uicc classes: * * UiccController * # * | * UiccCard * # # * | ------------------ * UiccCardApplication CatService * # # * | | * IccRecords IccFileHandler * ^ ^ ^ ^ ^ ^ ^ ^ * SIMRecords---- | | | | | | ---SIMFileHandler * RuimRecords----- | | | | ----RuimFileHandler * IsimUiccRecords--- | | -----UsimFileHandler * | ------CsimFileHandler * ----IsimFileHandler
可以说,所有关于SIM相关的最重要的类,都在这里管理
更多相关文章
- Android(安卓)--- Activity生命周期
- Android设置通知栏/状态栏透明改变通知栏颜色和app最上部分颜色
- Android(安卓)热点开关状态的判断和获取热点ssid
- Android的网络状态判断
- Selector、shape详解(一)
- android 面试题集
- Android中获取屏幕相关信息(屏幕大小,状态栏、标题栏高度)
- Android电量和插拔电源状态广播监听
- Android(安卓)SDK自带教程之BluetoothChat