本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉。
本文主要介绍GsmServiceStateTracker是怎么管理网络的?手机开机后,怎么去注册网络?网络状态是怎么变换传递的。
Android在ServiceState.java中定义了四种ServiceState状态和16中无线通信网络类型:
public class ServiceState implements Parcelable { /** * Normal operation condition, the phone is registered * with an operator either in home network or in roaming. */ public static final int STATE_IN_SERVICE = 0; /** * Phone is not registered with any operator, the phone * can be currently searching a new operator to register to, or not * searching to registration at all, or registration is denied, or radio * signal is not available. */ public static final int STATE_OUT_OF_SERVICE = 1; /** * The phone is registered and locked. Only emergency numbers are allowed. {@more} */ public static final int STATE_EMERGENCY_ONLY = 2; /** * Radio of telephony is explicitly powered off. */ public static final int STATE_POWER_OFF = 3; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_UNKNOWN = 0; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_GPRS = 1; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_EDGE = 2; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_UMTS = 3; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_IS95A = 4; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_IS95B = 5; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_1xRTT = 6; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_EVDO_0 = 7; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_EVDO_A = 8; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_HSDPA = 9; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_HSUPA = 10; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_HSPA = 11; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_EVDO_B = 12; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_EHRPD = 13; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_LTE = 14; /** @hide */ public static final int RIL_RADIO_TECHNOLOGY_HSPAP = 15; /** * GSM radio technology only supports voice. It does not support data. * @hide */ public static final int RIL_RADIO_TECHNOLOGY_GSM = 16; }
GsmServiceStateTracker继承自ServiceStateTracker,ServiceStateTracker里面定义了两个ServiceState对象mSS和mNewSS来记录新旧状态,GsmServiceStateTracker还侦听了很多与射频、SIM卡、网络注册等有关的事件:
mCi.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null); mCi.registerForPsNetworkStateChanged(this, EVENT_PS_NETWORK_STATE_CHANGED, null); mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null); mCi.registerForSimPlugOut(this, EVENT_SIM_PLUG_OUT, null); //MTK-START [ALPS415367]For MR1 Migration //mCi.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null); //MTK-END [ALPS415367]For MR1 Migration mCi.setOnRestrictedStateChanged(this, EVENT_RESTRICTED_STATE_CHANGED, null); mCi.registerForSIMReady(this, EVENT_SIM_READY, null);//Android原来的,MTK没用这个,用的是我们后面介绍的 mCi.setGprsDetach(this, EVENT_DATA_CONNECTION_DETACHED, null); mCi.setInvalidSimInfo(this, EVENT_INVALID_SIM_INFO, null);//ALPS00248788 if(mServiceStateExt.isImeiLocked()) mCi.registerForIMEILock(this, EVENT_IMEI_LOCK, null); mCi.registerForIccRefresh(this,EVENT_ICC_REFRESH,null);
我们从SIM卡的Ready状态开始查看,SIM卡处于ready状态,手机才可以开始注册网络,SIM卡ready状态的监听请查看Android4.4
Telephony流程分析——SIM卡开机时的初始化一文的step33,SIM卡Ready状态的通知请查看Android4.4 Telephony流程分析——SIM卡开机时的数据加载一文的step9,现在我们直接从GsmServiceStateTracker的handleMessage()处理EVENT_SIM_READY事件开始分析。
step2~step3,设置优先选择的网络类型,MTK提供了如下一些类型:
/* NETWORK_MODE_* See ril.h RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE */ int NETWORK_MODE_WCDMA_PREF = 0; /* GSM/WCDMA (WCDMA preferred) */ int NETWORK_MODE_GSM_ONLY = 1; /* GSM only */ int NETWORK_MODE_WCDMA_ONLY = 2; /* WCDMA only */ int NETWORK_MODE_GSM_UMTS = 3; /* GSM/WCDMA (auto mode, according to PRL) AVAILABLE Application Settings menu*/ int NETWORK_MODE_CDMA = 4; /* CDMA and EvDo (auto mode, according to PRL) AVAILABLE Application Settings menu*/ int NETWORK_MODE_CDMA_NO_EVDO = 5; /* CDMA only */ int NETWORK_MODE_EVDO_NO_CDMA = 6; /* EvDo only */ int NETWORK_MODE_GLOBAL = 7; /* GSM/WCDMA, CDMA, and EvDo (auto mode, according to PRL) AVAILABLE Application Settings menu*/ int NETWORK_MODE_LTE_CDMA_EVDO = 8; /* LTE, CDMA and EvDo */ int NETWORK_MODE_LTE_GSM_WCDMA = 9; /* LTE, GSM/WCDMA */ int NETWORK_MODE_LTE_CMDA_EVDO_GSM_WCDMA = 10; /* LTE, CDMA, EvDo, GSM/WCDMA */ int NETWORK_MODE_LTE_ONLY = 11; /* LTE Only mode. */ int NETWORK_MODE_LTE_WCDMA = 12; /* LTE/WCDMA */ //for LTE the preferred nw tyep is "4G preferred" int PREFERRED_NETWORK_MODE = FeatureOption.MTK_LTE_SUPPORT? NETWORK_MODE_LTE_GSM_WCDMA:NETWORK_MODE_WCDMA_PREF; //int PREFERRED_NETWORK_MODE = NETWORK_MODE_WCDMA_PREF; //MTK-START: add for LTE int NETWORK_MODE_MTK_BASE = 30; // GSM/WCDMA, LTE (for MMDSDC "3G or 2G Preferred" item) int NETWORK_MODE_GSM_WCDMA_LTE = NETWORK_MODE_MTK_BASE+1; int NETWORK_MODE_GSM_WCDMA_LTE_MMDC = NETWORK_MODE_MTK_BASE+2; // for MMDSDC mode = "2/3/4G(auto)" item int NETWORK_MODE_LTE_GSM_WCDMA_MMDC = NETWORK_MODE_MTK_BASE+3; // "4G/2G" item (only for EM mode) int NETWORK_MODE_LTE_GSM = NETWORK_MODE_MTK_BASE+4; int NETWORK_MODE_LTE_GSM_MMDC = NETWORK_MODE_MTK_BASE+5; //MTK-END: add for LTE //MTK-START [mtk04070][111117][ALPS00093395]MTK added int NETWORK_MODE_GEMINI = 20; /* Gemini Phone */ //ALPS01219851 value cannot conflict with other NETWORK_MODE_xxx
step4,直接发送at命令,来选择小区(这个具体作用不太清楚),
//ALPS00279048 public void setCRO(int mode, Message onComplete) { String cmdStr[] = {"AT+ECRO=0", ""}; /* ALPS00310187 add mode 2 and 3 support */ if(mode == 0){ cmdStr[0] = "AT+ECRO=0"; }else if(mode == 1){ cmdStr[0] = "AT+ECRO=1"; }else if(mode == 2){ cmdStr[0] = "AT+ECRO=2"; }else if(mode == 3){ cmdStr[0] = "AT+ECRO=3"; }else{ LOGD("Invalid parameter in setCRO:" + mode); return; } this.invokeOemRilRequestStrings(cmdStr,onComplete); }
step5,设置GPRS转接优先,是数据优先还是电话优先。
step6,设置GPRS连接类型。
我们这个过程是假设射频状态良好,SIM卡处于准备状态的,step8~step11向Modem查询入网状态:
default: // Issue all poll-related commands at once // then count down the responses, which // are allowed to arrive out-of-order mPollingContext[0]++;//待处理的事件+1 mCi.getOperator( obtainMessage( EVENT_POLL_STATE_OPERATOR, mPollingContext));//查询注册的运营商信息 //[MMDC] no need to check ps state in LteDcSST if (PhoneFactory.isLteDcSupport() && (this instanceof LteDcServiceStateTracker)){ if (DBG) log("LteDcSST ignore get data registerState"); } else { mPollingContext[0]++;//待处理的事件+1 mCi.getDataRegistrationState( obtainMessage( EVENT_POLL_STATE_GPRS, mPollingContext));//查询注册的数据连接状态 } mPollingContext[0]++;//待处理的事件+1 mCi.getVoiceRegistrationState( obtainMessage( EVENT_POLL_STATE_REGISTRATION, mPollingContext));//查询注册的语音通话网络类型 mPollingContext[0]++;//待处理的事件+1 mCi.getNetworkSelectionMode( obtainMessage( EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext));//查询网络选择状态 break;
查询信息的反馈都用step14处理。
step12,获取手机信号,每10s查一次。
private void queueNextSignalStrengthPoll() { if (mDontPollSignalStrength) { // The radio is telling us about signal strength changes // we don't have to ask it return; } Message msg; msg = obtainMessage(); msg.what = EVENT_POLL_SIGNAL_STRENGTH; long nextTime; // TODO Don't poll signal strength if screen is off sendMessageDelayed(msg, POLL_PERIOD_MILLIS);//POLL_PERIOD_MILLIS定义为10s }
handleMessage()发起于RIL交互:
case EVENT_POLL_SIGNAL_STRENGTH: // Just poll signal strength...not part of pollState() mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH)); break;
RIL反馈查询得到的信号:
case EVENT_GET_SIGNAL_STRENGTH: // This callback is called when signal strength is polled // all by itself //ALPS01035028 - start //if (!(mCi.getRadioState().isOn())) { if (!mRadioState.isOn()) { //ALPS01035028 - end // Polling will continue when radio turns back on return; } ar = (AsyncResult) msg.obj; //MTK-START [ALPS415367]For MR1 Migration ar = onGsmSignalStrengthResult(ar); //MTK-END [ALPS415367]For MR1 Migration onSignalStrengthResult(ar, true);//这里会将手机信号更新通知广播出去 queueNextSignalStrengthPoll();//隔10S后再一次查询信号,循环 break;
注意,Modem也会自己向上发送信号更新信息,对应的URC为RIL_UNSOL_SIGNAL_STRENGTH,在ServiceStateTracker初始化时注册监听。
step14,处理step8~step11查询的信息:
try { switch (what) { case EVENT_POLL_STATE_REGISTRATION: states = (String[])ar.result; int lac = -1; int cid = -1; int type = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; int regState = ServiceState.RIL_REG_STATE_UNKNOWN; int reasonRegStateDenied = -1; int psc = -1; if (states.length > 0) { try { regState = Integer.parseInt(states[0]); if (states.length >= 3) { if (states[1] != null && states[1].length() > 0) { //[ALPS00907900]-START int tempLac = Integer.parseInt(states[1], 16); if (tempLac < 0){ log("set Lac to previous value"); tempLac = mCellLoc.getLac(); } lac = tempLac; //[ALPS00907900]-END } if (states[2] != null && states[2].length() > 0) { //[ALPS00907900]-START int tempCid = Integer.parseInt(states[2], 16); if (tempCid < 0){ log("set Cid to previous value"); tempCid = mCellLoc.getCid(); } cid = tempCid; //[ALPS00907900]-END } if (states.length >=4 && states[3] != null && states[3].length() > 0) { //[ALPS01132085] for NetworkType display abnormal //update network type when screen is on or screen is off but not registered if (mIsScreenOn || (!mIsScreenOn &&((regState!=1)||(regState!=5)))){ type = Integer.parseInt(states[3]); mNewSS.setRilVoiceRadioTechnology(type); } } } } catch (NumberFormatException ex) { loge("error parsing RegistrationState: " + ex); } } mGsmRoaming = regCodeIsRoaming(regState);//是否漫游 mNewSS.setState (regCodeToServiceState(regState));//网络服务状态 mNewSS.setRegState(regState);// if (FeatureOption.MTK_GEMINI_SUPPORT) { if (IccCardConstants.INTENT_VALUE_ICC_LOCKED.equals(mSimState)|| IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(mSimState)) { log("SIM state is lock or absent, treat as OUT_OF_SERVICE"); mNewSS.setState(ServiceState.STATE_OUT_OF_SERVICE); //[ALPS01010930] to consistent RegState and ServcieState mNewSS.setRegState(ServiceState.REGISTRATION_STATE_NOT_REGISTERED_AND_NOT_SEARCHING); } } // LAC and CID are -1 if not avail. LAC and CID will be updated in onNetworkStateChangeResult() when in OUT_SERVICE if (states.length > 3) { log("states.length > 3"); /* ALPS00291583: ignore unknown lac or cid value */ if(lac==0xfffe || cid==0x0fffffff) { log("unknown lac:"+lac+"or cid:"+cid); } else { /* AT+CREG? result won't include <lac> and <cid> when in OUT_SERVICE */ if(regCodeToServiceState(regState) != ServiceState.STATE_OUT_OF_SERVICE){ mNewCellLoc.setLacAndCid(lac, cid);//小区广播信息更新 } } } mNewCellLoc.setPsc(psc);//小区广播信息更新 break; case EVENT_POLL_STATE_GPRS: case EVENT_POLL_STATE_GPRS_2G: case EVENT_POLL_STATE_GPRS_34G: states = (String[])ar.result; //[MMDC] for MMDC, in Ps switching state, don't update the service state PsArbitrator psArbitrator = mCi.getPsArbitrator(); if (PhoneFactory.isLteDcSupport() && LteModemSwitchHandler.getActiveModemType() == LteModemSwitchHandler.MD_TYPE_LTNG && PsArbitrator.getIsSwitching() ) { log("ignore pollstate GPRS when ps switching. psarbitrator"); log("newGPRSState/newps_networkType:" + newGPRSState + "/"+ newps_networkType); mNewSS.setDataRegState(newGPRSState); mNewSS.setRilDataRadioTechnology(newps_networkType); } else if (what == EVENT_POLL_STATE_GPRS_2G && psArbitrator.getCurrentPsMode() != PsArbitrator.PS_MODE_GSM && PhoneFactory.isLteDcSupport() && LteModemSwitchHandler.getActiveModemType() == LteModemSwitchHandler.MD_TYPE_LTNG) { log("EVENT_POLL_STATE_GPRS current mode is 34G but receivce 2G GPRS state, ignore"); mNewSS.setDataRegState(newGPRSState); mNewSS.setRilDataRadioTechnology(newps_networkType); } else if (what == EVENT_POLL_STATE_GPRS_34G && psArbitrator.getCurrentPsMode() == PsArbitrator.PS_MODE_GSM && PhoneFactory.isLteDcSupport() && LteModemSwitchHandler.getActiveModemType() == LteModemSwitchHandler.MD_TYPE_LTNG){ log("EVENT_POLL_STATE_GPRS current mode is 2G but receivce 34G GPRS state, ignore"); mNewSS.setDataRegState(newGPRSState); mNewSS.setRilDataRadioTechnology(newps_networkType); } else { regState = -1; mNewReasonDataDenied = -1; mNewMaxDataCalls = 1; if (states.length > 0) { try { regState = Integer.parseInt(states[0]); //MTK-ADD Start : for CS not registered , PS regsitered (ex: LTE PS only mode or 2/3G PS only SIM card or CS domain network registeration temporary failure if (states.length >= 3) { if (states[1] != null && states[1].length() > 0) { int tempLac = Integer.parseInt(states[1], 16); if (tempLac < 0){ log("set Lac to previous value"); tempLac = mCellLoc.getLac(); } psLac = tempLac; } if (states[2] != null && states[2].length() > 0) { int tempCid = Integer.parseInt(states[2], 16); if (tempCid < 0){ log("set Cid to previous value"); tempCid = mCellLoc.getCid(); } psCid = tempCid; } } //MTK-ADD END : for CS not registered , PS regsitered (ex: LTE PS only mode or 2/3G PS only SIM card or CS domain network registeration temporary failure // states[3] (if present) is the current radio technology if (states.length >= 4 && states[3] != null) { newps_networkType = Integer.parseInt(states[3]); } if (states.length >= 5 && states[4] != null) { log("<cell_data_speed_support> " + states[4]); } if (states.length >= 6 && states[5] != null) { log("<max_data_bearer_capability> " + states[5]); } if ((states.length >= 7 ) && (regState == 3)) { mNewReasonDataDenied = Integer.parseInt(states[6]); } if (states.length >= 8) { mNewMaxDataCalls = Integer.parseInt(states[7]); } } catch (NumberFormatException ex) { loge("error parsing GprsRegistrationState: " + ex); } } newGPRSState = regCodeToServiceState(regState); //for MR2 update Data Registration state mNewSS.setDataRegState(newGPRSState);//GPRS连接状态 mDataRoaming = regCodeIsRoaming(regState); //mNewRilRadioTechnology = newps_networkType; mNewSS.setRilDataRadioTechnology(newps_networkType);// } break; case EVENT_POLL_STATE_OPERATOR: String opNames[] = (String[])ar.result; if (opNames != null && opNames.length >= 3) { log("long:" +opNames[0] + " short:" + opNames[1] + " numeric:" + opNames[2]); mNewSS.setOperatorName (opNames[0], opNames[1], opNames[2]);//更新运营商名称 } break; case EVENT_POLL_STATE_NETWORK_SELECTION_MODE: ints = (int[])ar.result; mNewSS.setIsManualSelection(ints[0] == 1); if((mSS.getIsManualSelection() == true) && (mNewSS.getIsManualSelection() == false)){ log("Selection mode change from manual to auto");//手动选择网络 if (FeatureOption.MTK_GEMINI_SUPPORT) { if (mPhone instanceof GSMPhone){ boolean allPhoneInAutoMode = true; for(int simIdx=PhoneConstants.GEMINI_SIM_1;simIdx<PhoneConstants.GEMINI_SIM_NUM;simIdx++){ GSMPhone peerPhone = ((GSMPhone)mPhone).getPeerPhones(simIdx); if (peerPhone != null){ if(peerPhone.getServiceState().getIsManualSelection()== true){ log("Phone"+ (simIdx+1)+" is NOT in manual selection mode,shell keep reminder service"); allPhoneInAutoMode = false; break; } } } if(allPhoneInAutoMode == true){ log("All sim are NOT in manual selection mode,stop reminder service"); Intent sIntent = new Intent(); sIntent.setClassName("com.android.phone","com.mediatek.settings.NoNetworkPopUpService"); mPhone.getContext().stopService(sIntent); } } } else{ log("Stop manual selection mode reminder service"); Intent sIntent = new Intent(); sIntent.setClassName("com.android.phone","com.mediatek.settings.NoNetworkPopUpService"); mPhone.getContext().stopService(sIntent); } } else if((mSS.getIsManualSelection() == false) && (mNewSS.getIsManualSelection() == true)){ log("Selection mode change from auto to manual"); Intent sIntent = new Intent();//自动注册网络 sIntent.setClassName("com.android.phone","com.mediatek.settings.NoNetworkPopUpService"); mPhone.getContext().startService(sIntent); } break; } } catch (RuntimeException ex) { loge("Exception while polling service state. Probably malformed RIL response. " + ex); } mPollingContext[0]--;//待处理的事件-1 if (mPollingContext[0] == 0) {//所有待处理的事件都处理完成 /** * [ALPS00006527] * Only when CS in service, treat PS as in service */ if (mNewSS.getState() != ServiceState.STATE_IN_SERVICE) { //MTK-ADD START : for CS not registered , PS regsitered (ex: LTE PS only mode or 2/3G PS only SIM card or CS domain network registeration temporary failure if (mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE) { log("CS and PS are not registered"); /* Integrate ALPS00286197 with MR2 data only device state update */ if(mVoiceCapable){ newGPRSState = regCodeToServiceState(0); log("For Data only device newGPRSState=" +newGPRSState); } mDataRoaming = regCodeIsRoaming(0); } else { //when CS not registered, we update cellLoc by +CGREG log("update cellLoc by +CGREG"); mNewCellLoc.setLacAndCid(psLac, psCid); } //MTK-ADD END : for CS not registered , PS regsitered (ex: LTE PS only mode or 2/3G PS only SIM card or CS domain network registeration temporary failure } boolean roaming = mGsmRoaming; mNewSS.setRoaming(roaming); mNewSS.setEmergencyOnly(mEmergencyOnly); pollStateDone();
step15,新的网络信息获取完成,这里需要更新手机现有状态,这里是mSS和mNewSS比较更新的过程,该记录的记录,该发出通知的,发通知;并使用step16将要更新的信息通过DefaultPhoneNotifier通知给第三方注册用户。
右键复制图片地址,在浏览器中打开即可查看大图。
未完待续,有不对的地方,请指正。