首页 > 代码库 > Android4.4 Telephony流程分析——GsmServiceStateTracker管理网络服务状态

Android4.4 Telephony流程分析——GsmServiceStateTracker管理网络服务状态

      本文代码以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通知给第三方注册用户。


右键复制图片地址,在浏览器中打开即可查看大图。

未完待续,有不对的地方,请指正。


Android4.4 Telephony流程分析——GsmServiceStateTracker管理网络服务状态