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);
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);
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();
}
}
忽略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);
}
}
注意: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);
}
通过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;
}
于之前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);
}
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));
}
这是SIM卡管理的核心类,看这注释你就直到它有多重要
* Following is class diagram for uicc classes:
*
* UiccController
* #
* |
* UiccCard
* # #
* | ------------------
* UiccCardApplication CatService
* # #
* | |
* IccRecords IccFileHandler
* ^ ^ ^ ^ ^ ^ ^ ^
* SIMRecords---- | | | | | | ---SIMFileHandler
* RuimRecords----- | | | | ----RuimFileHandler
* IsimUiccRecords--- | | -----UsimFileHandler
* | ------CsimFileHandler
* ----IsimFileHandler