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;


第二,rild进程初始化过程中,设置radio状态为OFF

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.c
static 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)