ServiceStateTracker网络状态的处理

ServiceStateTracker.java主要处理一些与网络相关的状态和数据,它通过注册监听RIL层来获取网络状态的变化,注册监听UiccController 来获取SIM卡的变化情况及SIM卡数据,之后通知其他类网络状态的变更情况。这部分网络状态主要包括:
1.CS,PS域的注册情况。
2.漫游情况。
3.运营商名字。
4.网络模式。
5.信号格变化。
6.时区,注册小区的情况,等等
其中,CS,PS域的注册状态,漫游状态,运营商名字的显示,网络模式均使用了模板类ServiceState.java来保存。如下:

ServiceState.java:
 * <ul>
 *   <li>Service state: IN_SERVICE, OUT_OF_SERVICE, EMERGENCY_ONLY, POWER_OFF
 *   <li>Roaming indicator
 *   <li>Operator name, short name and numeric id
 *   <li>Network selection mode
 * </ul>

ServiceStateTracker.java的注册监听事件以及网络状态的主动获取方法:

//CS,PS注册状态:
mCi.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);
mCi.registerForPsNetworkStateChanged(this, EVENT_PS_NETWORK_STATE_CHANGED, null);
mCi.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS, mPollingContext));
mCi.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION,
        mPollingContext));

//网络模式:
mCi.getNetworkSelectionMode(obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE));

//SIM卡相关:
mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null);
mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR, mPollingContext));
mCi.registerForIccRefresh(this, EVENT_ICC_REFRESH, null);
mCi.registerForIMEILock(this, EVENT_IMEI_LOCK, null);

//时区:
mCi.setOnNITZTime(this, EVENT_NITZ_TIME, null);

//小区:位置更新
mCi.getCellInfoList(msg);
mCi.registerForCellInfoList(this, EVENT_UNSOL_CELL_INFO_LIST, null);
mCi.setLocationUpdates(true, obtainMessage(EVENT_LOCATION_UPDATES_ENABLED));
mCi.getVoiceRegistrationState(obtainMessage(EVENT_GET_LOC_DONE, null));

//IMS:
mCi.registerForImsNetworkStateChanged(this, EVENT_IMS_STATE_CHANGED, null);
mCi.getImsRegistrationState(this.obtainMessage(EVENT_IMS_STATE_DONE));
mCi.registerForImsRegistrationInfo(this, EVENT_IMS_REGISTRATION_INFO, null);

ServiceStateTracker.java 提供监听容器,让别的类注册,用来通知其他类网络状态的变更

    private RegistrantList mVoiceRoamingOnRegistrants = new RegistrantList();
    private RegistrantList mVoiceRoamingOffRegistrants = new RegistrantList();
    private RegistrantList mDataRoamingOnRegistrants = new RegistrantList();
    private RegistrantList mDataRoamingOffRegistrants = new RegistrantList();
    protected RegistrantList mAttachedRegistrants = new RegistrantList();
    protected RegistrantList mDetachedRegistrants = new RegistrantList();
    private RegistrantList mDataRegStateOrRatChangedRegistrants = new RegistrantList();
    private RegistrantList mNetworkAttachedRegistrants = new RegistrantList();
    private RegistrantList mPsRestrictEnabledRegistrants = new RegistrantList();
    private RegistrantList mPsRestrictDisabledRegistrants = new RegistrantList();
    protected RegistrantList mSignalStrengthChangedRegistrants = new RegistrantList();

监听后网络状态的处理,根据是否是模板类ServiceState.java中保存的状态,又分为两种情况:

一.由ServiceState.java保存处理的网络状态。

模板类ServiceState.java中保存的状态分别是:

 * <ul>
 *   <li>Service state: IN_SERVICE, OUT_OF_SERVICE, EMERGENCY_ONLY, POWER_OFF
 *   <li>Roaming indicator
 *   <li>Operator name, short name and numeric id
 *   <li>Network selection mode
 * </ul>

注册状态,漫游,运营商名字,网络模式。都在pollState()等相关方法中处理。时序图如下:
这里写图片描述

如时序图所示,ServiceStateTracker注册监听了以下的事件:
EVENT_SIM_READY
EVENT_RUIM_READY
EVENT_RUIM_RECORDS_LOADED
EVENT_ERI_FILE_LOADED
EVENT_PHONE_TYPE_SWITCHED
EVENT_NETWORK_STATE_CHANGED RIL主动上报消息
其监听的事件经由handleMessage()方法处理后都会走到pollState()方法中。
pollState():只要当前radio的状态不是RADIO_UNAVAILABLE和RADIO_OFF状态,就都会走到default中处理,default中通过RIL去主动获取CS,PS的注册状态,网络模式和运营商名字。如下:

mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR, mPollingContext));
mCi.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS, mPollingContext));
mCi.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION,
mPollingContext));
mCi.getNetworkSelectionMode(obtainMessage(EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext));

主动获取以上网络状态的结果在handlePollStateResult()和pollStateDone()方法中处理。

这里列出pollState()方法:

    @Override
    public void pollState(boolean modemTriggered) {
        log("pollState: modemTriggered=" + modemTriggered + ", mPollingContext="
                + (mPollingContext != null ? mPollingContext[0] : -1));

        // [ALPS03020226]
        if ((mPollingContext != null)
                && (mPollingContext[0] != 0)
                && (mCi.getRadioState() != CommandsInterface.RadioState.RADIO_UNAVAILABLE)) {
            hasPendingPollState = true;
            return;
        }

        mPollingContext = new int[1];
        mPollingContext[0] = 0;
        switch (mCi.getRadioState()) {
            case RADIO_UNAVAILABLE:
                mNewSS.setStateOutOfService();
                mNewCellLoc.setStateInvalid();
                setSignalStrengthDefaultValues();
                mGotCountryCode = false;
                mNitzUpdatedTime = false;
                //M: MTK added
                if (mPhone.isPhoneTypeGsm()) {
                    mPsRegStateRaw = ServiceState.RIL_REG_STATE_NOT_REG;
                }
                //M: MTK added end
                pollStateDone();
                break;
            case RADIO_OFF:
                mNewSS.setStateOff();
                mNewCellLoc.setStateInvalid();
                setSignalStrengthDefaultValues();
                mGotCountryCode = false;
                mNitzUpdatedTime = false;
                // don't poll for state when the radio is off
                // EXCEPT, if the poll was modemTrigged (they sent us new radio data)
                // or we're on IWLAN
                if (!modemTriggered && ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
                        != mSS.getRilDataRadioTechnology()) {
                    //M: MTK added
                    if (mPhone.isPhoneTypeGsm()) {
                        mPsRegStateRaw = ServiceState.RIL_REG_STATE_NOT_REG;
                    }
                    //M: MTK added end
                    pollStateDone();
                    break;
                }
            default:
                // Issue all poll-related commands at once then count down the responses, which
                // are allowed to arrive out-of-order
                mPollingContext[0]++;
                mCi.getOperator(obtainMessage(EVENT_POLL_STATE_OPERATOR, mPollingContext));

                mPollingContext[0]++;
                mCi.getDataRegistrationState(obtainMessage(EVENT_POLL_STATE_GPRS, mPollingContext));

                mPollingContext[0]++;
                mCi.getVoiceRegistrationState(obtainMessage(EVENT_POLL_STATE_REGISTRATION,
                        mPollingContext));

                if (mPhone.isPhoneTypeGsm()) {
                    mPollingContext[0]++;
                    mCi.getNetworkSelectionMode(obtainMessage(
                            EVENT_POLL_STATE_NETWORK_SELECTION_MODE, mPollingContext));
                }
                break;
        }
    }                                        

如果网络状态从RIL和UICC中都获取成功了,网络状态的数据需要更新和保存,pollStateDone()方法主要就是做这方面的工作,其主要处理有:

1.网络状态数据的初始化

这个不是pollStateDone()的工作,不过,需要在这里了解一下,ServiceStateTracker使用两个ServiceState 对象分别保存新旧两个状态:
在updatePhoneType()中初始化:

public ServiceState mSS; //保存上一次的网络状态
private ServiceState mNewSS;  //此次最新通知的网络状态
mSS = new ServiceState();
mNewSS = new ServiceState();

2.新旧网络状态的判定

根据两个新旧ServiceState 对象的属性,判定是否发生了哪些状态变化:

boolean hasRegistered = mSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE
                        && mNewSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE;
boolean hasDeregistered =mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE
                        && mNewSS.getVoiceRegState() != ServiceState.STATE_IN_SERVICE;
boolean hasGprsAttached = mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE
                        && mNewSS.getDataRegState() == ServiceState.STATE_IN_SERVICE;
boolean hasGprsDetached = mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
                        && mNewSS.getDataRegState() != ServiceState.STATE_IN_SERVICE;
boolean hasDataRegStateChanged = mSS.getDataRegState() != mNewSS.getDataRegState();
boolean hasVoiceRegStateChanged = mSS.getVoiceRegState() != mNewSS.getVoiceRegState();
boolean hasRilVoiceRadioTechnologyChanged = mSS.getRilVoiceRadioTechnology() != mNewSS.getRilVoiceRadioTechnology();
boolean hasRilDataRadioTechnologyChanged = mSS.getRilDataRadioTechnology() != mNewSS.getRilDataRadioTechnology();
boolean hasChanged = !mNewSS.equals(mSS) || mNeedNotify;
boolean hasVoiceRoamingOn = !mSS.getVoiceRoaming() && mNewSS.getVoiceRoaming();
boolean hasVoiceRoamingOff = mSS.getVoiceRoaming() && !mNewSS.getVoiceRoaming();
boolean hasDataRoamingOn = !mSS.getDataRoaming() && mNewSS.getDataRoaming();
boolean hasDataRoamingOff = mSS.getDataRoaming() && !mNewSS.getDataRoaming();
boolean hasLocationChanged = !mNewCellLoc.equals(mCellLoc);

3.交换新旧网络状态对象

把此次最新通知的ServiceState 对象赋值给上一次的ServiceState 对象。

ServiceState tss = mSS;
mSS = mNewSS;
mNewSS = tss;

4.通知其他类网络状态的变更

根据各个状态是否变更,相应的通知各个其他类。

        if (hasGprsAttached) {
            mAttachedRegistrants.notifyRegistrants();
        }

        if (hasGprsDetached) {
            mDetachedRegistrants.notifyRegistrants();
        }
.......

以下针对ServiceState 中保存的四大状态进行细致分析:


注册状态

注册状态在不同的层次有不同的划分,分为framework层和ril层。它们都在ServiceState 中定义了。

Ril层CS,PS注册状态的划分主要有:

    /**
     * RIL level registration state values from ril.h
     * ((const char **)response)[0] is registration state 0-6,
     *              0 - Not registered, MT is not currently searching
     *                  a new operator to register
     *              1 - Registered, home network
     *              2 - Not registered, but MT is currently searching
     *                  a new operator to register
     *              3 - Registration denied
     *              4 - Unknown
     *              5 - Registered, roaming
     *             10 - Same as 0, but indicates that emergency calls
     *                  are enabled.
     *             12 - Same as 2, but indicates that emergency calls
     *                  are enabled.
     *             13 - Same as 3, but indicates that emergency calls
     *                  are enabled.
     *             14 - Same as 4, but indicates that emergency calls
     *                  are enabled.
     * @hide
     */
    public static final int RIL_REG_STATE_NOT_REG = 0;
    public static final int RIL_REG_STATE_HOME = 1;
    public static final int RIL_REG_STATE_SEARCHING = 2;
    public static final int RIL_REG_STATE_DENIED = 3;
    public static final int RIL_REG_STATE_UNKNOWN = 4;
    public static final int RIL_REG_STATE_ROAMING = 5;
    public static final int RIL_REG_STATE_NOT_REG_EMERGENCY_CALL_ENABLED = 10;
    public static final int RIL_REG_STATE_SEARCHING_EMERGENCY_CALL_ENABLED = 12;
    public static final int RIL_REG_STATE_DENIED_EMERGENCY_CALL_ENABLED = 13;
    public static final int RIL_REG_STATE_UNKNOWN_EMERGENCY_CALL_ENABLED = 14;

RIL层提供了接口供外部获取CS,PS注册状态:

public void getDataRegistrationState(Message result)
public void getVoiceRegistrationState(Message result)

Framework层CS,PS注册状态的划分主要有四种:

(1).已注册上网络,无论注册上的是home network还是漫游到别的网络。

public static final int STATE_IN_SERVICE = 0;

(2).包括没有搜索到网络,正在搜索网络过程,被网络拒绝,无线信号弱导致的注册上网络的状态

public static final int STATE_OUT_OF_SERVICE = 1;

(3).已经注册上网络,但是网络被锁,只允许拨打紧急号码

public static final int STATE_EMERGENCY_ONLY = 2;

(4).关机状态或者modem没起来

public static final int STATE_POWER_OFF = 3;

RIL层划分了很多的注册状态,但是在framework层上不需要保存这么多状态,因此简化成了以上四个。ServiceStateTracker在获取RIL层的注册状态后,会使用regCodeToServiceState()和setStateOutOfService(),setStateOff()把RIL层的注册状态转换成framework层的四个状态,具体可以查看ServiceStateTracker代码:

ServiceStateTracker.java

    protected int regCodeToServiceState(int code) {
        switch (code) {
            case ServiceState.RIL_REG_STATE_HOME:
            case ServiceState.RIL_REG_STATE_ROAMING:
                return ServiceState.STATE_IN_SERVICE;
            default:
                return ServiceState.STATE_OUT_OF_SERVICE;
        }
    }

ServiceState.java

    public void setStateOutOfService() {
        setNullState(STATE_OUT_OF_SERVICE);
    }

    public void setStateOff() {
        setNullState(STATE_POWER_OFF);
    }

可以通过ServiceState提供的接口获取framework层的CS,PS注册状态:
ServiceState.java

getVoiceRegState()   
getDataRegState()

注册状态的DEBUG:

framework层的注册状态在log中的打印如下:

01-01 07:03:34.270982  1388  1388 D SST     : [GsmSST0] updateSpnDisplay mVoiceCapable=true mEmergencyOnly=false mCi.getRadioState().isOn()=true getVoiceRegState()=1 getDataRegState()1

Ril层的注册状态主要看AT指令,区分为CS,PS域。
CS域:

AT> AT+CREG?
AT< +CREG:<n><stat><lac><ci><act>

Stat:注册状态,数值见以上ServiceState.java的定义。
Act:当前注册的网络类型。

{0 GSM}
{2 UTRAN}
{3 GSM w/EGPRS}
{4 UTRAN w/HSDPA}
{5 UTRAN w/HSUPA}
{6 UTRAN w/HSDPA and HSUPA}
{7 E-UTRAN}

Ril层的打印如下:

01-01 07:03:34.425618  1388  1388 D RILJ    : [3781]> VOICE_REGISTRATION_STATE [SUB0]
01-01 07:03:34.439565   822   847 I AT      : AT> AT+CREG? (RIL_CMD_READER_1, tid:487617029200)
01-01 07:03:34.935065   822   864 I AT      : AT< +CREG: 3,1,"A82C","00B37776",6,0,0 (RIL_CMD_READER_1, tid:487617029200)
01-01 07:03:34.939999  1388  1476 D RILJ    : [3793]< VOICE_REGISTRATION_STATE {1, a82c, b37776, 11, , , , , , , , , , 0} [SUB0]

PS域:

AT> AT+CGREG?
AT< +CGREG:<n><stat><lac><ci><act><rac><cause_type><reject_cause>

Stat:同以上CS域
Act:同以上CS域
Ril层的打印如下:

01-01 07:03:35.129029  1388  1388 D RILJ    : [3805]> DATA_REGISTRATION_STATE [SUB0]
01-01 07:03:35.148115   822   847 I AT      : AT> AT+CGREG? (RIL_CMD_READER_1,tid:487617029200)
01-01 07:03:35.153160   822   864 I AT      : AT< +CGREG: 3,1,"A82C","00B37776",6,"2C",0,0 (RIL_CMD_READER_1, tid:487617029200)
01-01 07:03:35.161882  1388  1476 D RILJ    : [3805]< DATA_REGISTRATION_STATE {1, a82c, b37776, 11, 0, 6} [SUB0]

漫游

这里的漫游是指:本运营商的SIM卡注册上了另外运营商的网络。
漫游又分为CS漫游,PS漫游,它们的漫游类型定义如下:

public static final int ROAMING_TYPE_NOT_ROAMING = 0; //非漫游,注册的本卡运营商网络
public static final int ROAMING_TYPE_UNKNOWN = 1; //不能判断是国内漫游还是国际漫游
public static final int ROAMING_TYPE_DOMESTIC = 2;//国内漫游
public static final int ROAMING_TYPE_INTERNATIONAL = 3;//国际漫游

获取漫游类型:ServiceState.java

getVoiceRegState()
getDataRegState()

判断CS,PS域是否发生了漫游:

public boolean getVoiceRoaming() {
    return mVoiceRoamingType != ROAMING_TYPE_NOT_ROAMING;
}
public boolean getDataRoaming() {
    return mDataRoamingType != ROAMING_TYPE_NOT_ROAMING;
}
public boolean getRoaming() {
    return getVoiceRoaming() || getDataRoaming();
}

以上是根据AT获取的网络状态来判定是否是发生了漫游,但是,我们需要客制化漫游,还需要再定义一个变量来保存客制化的状态,因此,一般使用以下方法来判定当前的漫游状态:

public boolean getDataRoamingFromRegistration() {
    return mIsDataRoamingFromRegistration;
}
public void setDataRoamingFromRegistration(boolean dataRoaming) {
    mIsDataRoamingFromRegistration = dataRoaming;
}

有些运营商之间有漫游协议,因此本卡注册上了另外的运营商,不一定都是漫游的情况,以AT结果为准。在驻网成功后,CS,PS域的漫游信息经由AT指令携带返回framework层。如:

01-01 07:03:34.935065   822   864 I AT      : AT< +CREG: 3,5,"A82C","00B37776",6,0,0 (RIL_CMD_READER_1, tid:487617029200)
01-01 07:03:35.153160   822   864 I AT      : AT< +CGREG: 3,5,"A82C","00B37776",6,"2C",0,0 (RIL_CMD_READER_1, tid:487617029200)

此处注册状态Stat = 5,表明发生了漫游的情况。
获取RIL层上报的漫游状态后,漫游状态需要保存到ServiceState.java中,
handlePollStateResult() —> updateRoamingState() —>set…Roaming()
pollStateDone() —> updateRoamingState() —>set…Roaming()
根据其处理流程,我们可以在updateRoamingState()中客制化:

    @Override
    protected void updateRoamingState() {
        if (mPhone.isPhoneTypeGsm()) {
            boolean roaming = (mGsmRoaming || mDataRoaming);
            //客制化roaming
            if (mGsmRoaming && !isOperatorConsideredRoaming(mNewSS) &&
                    (isSameNamedOperators(mNewSS) || isOperatorConsideredNonRoaming(mNewSS))) {
                roaming = false;
            }

            // Save the roaming state before carrier config possibly overrides it.
            if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
                    == mNewSS.getRilDataRadioTechnology()) {
                mNewSS.setDataRoamingFromRegistration(mDataRoaming);
            } else {
                mNewSS.setDataRoamingFromRegistration(roaming);
            }

            CarrierConfigManager configLoader = (CarrierConfigManager)
                    mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
            mNewSS.setVoiceRoaming(roaming);
            if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
                    == mNewSS.getRilDataRadioTechnology()) {
                mNewSS.setDataRoaming(mDataRoaming);
            } else {
                mNewSS.setDataRoaming(roaming);
            }
        } else {
        ......
        }
   }    
   //保存一个数组,用于客制化roaming
    @Override
    protected boolean isOperatorConsideredRoaming(ServiceState s) {
        String simNumeric = ((TelephonyManager) mPhone.getContext().
                getSystemService(Context.TELEPHONY_SERVICE)).
                getSimOperatorNumericForPhone(getPhoneId());
        String operatorNumeric = s.getOperatorNumeric();
        int simOperatorIndex = mLastSameNamedOperatorConsideredRoamingIndex;

        if (TextUtils.isEmpty(operatorNumeric) || TextUtils.isEmpty(simNumeric)) return false;

        if (simOperatorIndex == -1 ||
                !simNumeric.equals(sameNamedOperatorConsideredRoaming[simOperatorIndex][0])) {
            for (int i = 0; i < sameNamedOperatorConsideredRoaming.length; i++) {
                if (simNumeric.startsWith(sameNamedOperatorConsideredRoaming[i][0])) {
                    mLastSameNamedOperatorConsideredRoamingIndex = i;
                    simOperatorIndex = i;
                    break;
                }
            }
        }

        if (simOperatorIndex == -1) return false;

        for (int i = 0; i < sameNamedOperatorConsideredRoaming[simOperatorIndex].length; i++) {
            if (operatorNumeric.startsWith(sameNamedOperatorConsideredRoaming[simOperatorIndex][i]))
            {
                return true;
            }
        }

        return false;
    }   
    private String [][] sameNamedOperatorConsideredRoaming = {
        {"310150","310110","310140","310400","310470","311170"},
        {"310170","310110","310140","310400","310470","311170"},
        {"310380","310110","310140","310400","310470","311170"},
        {"310410","310110","310140","310400","310470","311170"},
        {"404","404","405"},
        {"405","404","405"},        
        {"53024","53001"}
    };                        

应用层将会通过ServiceState.java的getRoaming()来获取漫游状态,因此,这里可以客制化是否显示漫游图标。


运营商名字

运营商的名字分为DisplayName和CarrierName,DisplayName主要用于除了锁屏运营商名字之外的其他地方显示。CarrierName主要就是显示锁屏运营商的名字,在没有插卡或者SIM卡无效或者不能用的时候,CarrierName的值为”No SIM card”,”No service”,”Emergency calls only”。
framework层为应用层提供两个接口:(SubscriptionInfo对象可由SubscriptionManager.java获取)
SubscriptionInfo.java —— getCarrierName()
SubscriptionInfo.java —— getDisplayName()

DisplayName的设置:
SubscriptionInfoUpdater.java —–> handleSimLoaded() :SIM卡加载过程中设置
CarrierName的设置:
ServiceStateTracker.java —->onReceive() —> updateSpnDisplay() 接收到ACTION_LOCALE_CHANGED广播是设置
ServiceStateTracker.java —-> pollStateDone() —> updateSpnDisplay() 网络状态变更的时候设置

                Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
                intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, showSpn);
                intent.putExtra(TelephonyIntents.EXTRA_SPN, spn);
                intent.putExtra(TelephonyIntents.EXTRA_DATA_SPN, dataSpn);
                intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn);
                intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn);
                mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);                

应用层(SystemUI)通过监听此SPN_STRINGS_UPDATED_ACTION类型的广播,动态更新锁屏运营商的名字。
一般我们客制化运营商名字都是在发送SPN_STRINGS_UPDATED_ACTION广播之前客制化。需要考虑DisplayName与CarrierName是否需要同步修改。

pollStateDone() —> updateSpnDisplay()
updateSpnDisplay()主要是处理运营商名字显示相关的工作,其显示规则遵从自3GPP协议的规定。可以参考spn-conf.xml 与运营商名字显示


网络模式

这里的网络模式跟网络制式有些区别。网络制式针对4G,3G,2G网络的设定,一般是4G/3G/2G auto,3G/2G auto,2G等等。但是网络模式更具体一些,比如3G下有WCDMA,CDMA2000,TD-SCDMA,而WCDMA下还有更具体的划分:HSPAP HSDPA HSPA等。网络模式就是这些更具体的网络。
ServiceState.java定义的网络模式如下:

    /**
     * Available radio technologies for GSM, UMTS and CDMA.
     * Duplicates the constants from hardware/radio/include/ril.h
     * This should only be used by agents working with the ril.  Others
     * should use the equivalent TelephonyManager.NETWORK_TYPE_*
     */
    public static final int RIL_RADIO_TECHNOLOGY_UNKNOWN = 0;
    public static final int RIL_RADIO_TECHNOLOGY_GPRS = 1;
    public static final int RIL_RADIO_TECHNOLOGY_EDGE = 2;
    public static final int RIL_RADIO_TECHNOLOGY_UMTS = 3;
    public static final int RIL_RADIO_TECHNOLOGY_IS95A = 4;
    public static final int RIL_RADIO_TECHNOLOGY_IS95B = 5;
    public static final int RIL_RADIO_TECHNOLOGY_1xRTT = 6;
    public static final int RIL_RADIO_TECHNOLOGY_EVDO_0 = 7;
    public static final int RIL_RADIO_TECHNOLOGY_EVDO_A = 8;
    /** @hide */
    public static final int RIL_RADIO_TECHNOLOGY_HSDPA = 9;
    public static final int RIL_RADIO_TECHNOLOGY_HSUPA = 10;
    public static final int RIL_RADIO_TECHNOLOGY_HSPA = 11;
    public static final int RIL_RADIO_TECHNOLOGY_EVDO_B = 12;
    public static final int RIL_RADIO_TECHNOLOGY_EHRPD = 13;
    public static final int RIL_RADIO_TECHNOLOGY_LTE = 14;
    public static final int RIL_RADIO_TECHNOLOGY_HSPAP = 15;
    public static final int RIL_RADIO_TECHNOLOGY_GSM = 16;
    public static final int RIL_RADIO_TECHNOLOGY_TD_SCDMA = 17;
    //提供接口获取网络模式
    /** @hide */
    public int getRilVoiceRadioTechnology() {
        return this.mRilVoiceRadioTechnology;
    }
    /** @hide */
    public int getRilDataRadioTechnology() {
        return this.mRilDataRadioTechnology;
    }

将int类型的网络模式打印为string类型:

   public static String rilRadioTechnologyToString(int rt) {
        String rtString;

        switch(rt) {
            case RIL_RADIO_TECHNOLOGY_UNKNOWN:
                rtString = "Unknown";
                break;
            case RIL_RADIO_TECHNOLOGY_GPRS:
                rtString = "GPRS";
                break;
            case RIL_RADIO_TECHNOLOGY_EDGE:
                rtString = "EDGE";
                break;
            case RIL_RADIO_TECHNOLOGY_UMTS:
                rtString = "UMTS";
                break;
             ....
         }
    }

这些网络模式也分为CS,PS域,其查询ril后返回的结果打印如下:

01-01 20:03:42.159099  1388  1892 D RILJ    : [3877]> QUERY_NETWORK_SELECTION_MODE [SUB0]
01-01 20:03:42.169268   822   847 I AT      : AT> AT+COPS? (RIL_CMD_READER_1, tid:487617029200)
01-01 20:03:42.177449   822   864 I AT      : AT< +COPS: 0,2,"46001",6 (RIL_CMD_READER_1, tid:487617029200)
01-01 20:03:42.179321  1388  1476 D RILJ    : [3877]< QUERY_NETWORK_SELECTION_MODE {0} [SUB0]

Framework中网络模式的打印:

03-20 16:49:55.698138  1400  1400 D SST     : [GsmSST0] Poll ServiceState done:  oldSS=[0 0 voice home data home CU CU-GSM 46001 CU CU-GSM 46001  LTE LTE CSS not supported -1

09-05 11:20:39.595273  2534  2534 D SST     : [GsmSST0] EVENT_POLL_STATE_REGISTRATION mSS getRilVoiceRadioTechnology:14, regState:1, NewSS RilVoiceRadioTechnology:14, lac:6338, cid:26228997

二.非ServiceState.java中处理的网络状态


网络制式

由于网络制式是由上层设置并下发到modem层,并不会随网络的变化而改变网络制式,因此,这里并不会像其他情况一样存在着监听。它只有主动请求操作。根据组网技术的不同,网络制式分为以下几种:
2G网络:GSM,CDMA,
3G网络:WCDMA,TD-SCDMA,EVDO
4G网络:TDD-LTE,FDD-LTE
根据这些组网技术的分类,对应上层的网络制式就分为了好多种。以下是AT层和framework层对网络制式的分类。可以明显看到,framework层的分类比AT层要多许多。比如3G only下,framework层有WCDMA,TD-SCDMA,EVDO,但是AT层并没有这些划分,只有一个UMTS,UMTS是指WCDMA+TD-SCDMA的总称。可见,对于当前SIM卡支持的网络制式,framework层不会做判断,而是由modem层来判断。
1.AT 指令

AT      : AT> AT+ERAT=3,0

AT+ERAT=<RAT mode>[,<prefer rat>]
OK/ERROR

RAT mode:
0:GSM only
1:UMTS only
2:GSM+UMTS
3:LTE  only
4:GSM+LTE
5:UMTS+LTE
6:GSM+UMTS+LTE
7:C2K only
11:LTE+c2K
14:GSM+UMTS+LTE+C2K

RILConstants.java

    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 */
    int NETWORK_MODE_CDMA           = 4; /* CDMA and EvDo */
    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*/
    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_CDMA_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 */
    int NETWORK_MODE_TDSCDMA_ONLY            = 13; /* TD-SCDMA only */
    int NETWORK_MODE_TDSCDMA_WCDMA           = 14; /* TD-SCDMA and WCDMA */
    int NETWORK_MODE_LTE_TDSCDMA             = 15; /* TD-SCDMA and LTE */
    int NETWORK_MODE_TDSCDMA_GSM             = 16; /* TD-SCDMA and GSM */
    int NETWORK_MODE_LTE_TDSCDMA_GSM         = 17; /* TD-SCDMA,GSM and LTE */
    int NETWORK_MODE_TDSCDMA_GSM_WCDMA       = 18; /* TD-SCDMA, GSM/WCDMA */
    int NETWORK_MODE_LTE_TDSCDMA_WCDMA       = 19; /* TD-SCDMA, WCDMA and LTE */
    int NETWORK_MODE_LTE_TDSCDMA_GSM_WCDMA   = 20; /* TD-SCDMA, GSM/WCDMA and LTE */
    int NETWORK_MODE_TDSCDMA_CDMA_EVDO_GSM_WCDMA  = 21; /*TD-SCDMA,EvDo,CDMA,GSM/WCDMA*/
    int NETWORK_MODE_LTE_TDSCDMA_CDMA_EVDO_GSM_WCDMA = 22; /* TD-SCDMA/LTE/GSM/WCDMA, CDMA, and EvDo */
    int NETWORK_MODE_LTE_GSM        = 30; /*LTE/GSM */
int NETWORK_MODE_LTE_TDD_ONLY   = 31; /* LTE TDD Only mode. */

网络制式变化的时序图如下:
这里写图片描述
网络制式的设置保存在android.provider.Settings.Global.PREFERRED_NETWORK_MODE中,如果需要修改默认的网络制式,可以追溯此值的初始化过程。

ServiceStateTracker.java中设置网络制式的方法:
    protected void setDeviceRatMode(int phoneId) {
        int networkType = -1;
        // log("[setDeviceRatMode]+");
        networkType = calculateDeviceRatMode(phoneId);
        log("[setDeviceRatMode]: " + networkType);
        if (networkType >= Phone.NT_MODE_WCDMA_PREF) {
            mPhone.setPreferredNetworkType(networkType, null);
        }
}

RIL.java中设置网络制式结束后,发出的广播:

    private Object responseSetPreferredNetworkType(Parcel p) {
        int count = getRequestCount(RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE);
        if (count == 0) {
            Intent intent = new Intent(
                    TelephonyIntents.ACTION_RAT_CHANGED);
            intent.putExtra(PhoneConstants.PHONE_KEY, mInstanceId);
            intent.putExtra(TelephonyIntents.EXTRA_RAT, mPreferredNetworkType);
            mContext.sendBroadcast(intent);
        }
        riljLog("SetRatRequestCount: " + count);

        return null;
}

网络制式DEBUG:

Phone   : setPreferredNetworkType: networkType = 11 modemRaf = 81930 rafFromType = 16384 filteredType = 11
RILJ    : [6783]> REQUEST_SET_PREFERRED_NETWORK_TYPE : 11 [SUB1]
RILJ    : [6783]< REQUEST_SET_PREFERRED_NETWORK_TYPE  [SUB1]
RIL-NW  : requestSetPreferredNetworkType: success

信号格

protected static final int EVENT_GET_SIGNAL_STRENGTH               = 3;
protected static final int EVENT_POLL_SIGNAL_STRENGTH              = 10;
protected static final int EVENT_SIGNAL_STRENGTH_UPDATE            = 12;
mCi.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));

ServiceStateTracker通过监听RIL来获取信号格的变化情况,主要分为两种情况:

一.RIL层的unsolicited消息(自动上报消息)

EVENT_SIGNAL_STRENGTH_UPDATE

RIL层在接收到信号格变化后,会主动上报ServiceStateTracker.java,通知信号的变化情况。

二.RIL层的solicited消息(主动请求消息)

 EVENT_GET_SIGNAL_STRENGTH

在RIL层没有接收到信号格变化,ServiceStateTracker.java有需求查询信号格信息的时候,通过mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH))发出查询请求,查询结束后,RIL层返回的结果在handleMessage的EVENT_GET_SIGNAL_STRENGTH中处理。
实际上,ServiceStateTracker.java会隔一个固定的时间去查询信号格的变化,避免RIL没有自动上报时,不能及时更新信号格的信息。这个时间的设置是10s,如下:
发出handler消息:

private static final int POLL_PERIOD_MILLIS = 10 * 1000;
    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);
    }

接收到handler消息并主动查询当前信号格的信息:

            case EVENT_POLL_SIGNAL_STRENGTH:
                // Just poll signal strength...not part of pollState()
                if (mPhone.isPhoneTypeGsm()) {
                    log("handle EVENT_POLL_SIGNAL_STRENGTH GSM " + mDontPollSignalStrength);
                    if (mDontPollSignalStrength) {
                        // The radio is telling us about signal strength changes
                        // we don't have to ask it
                        return;
                    }
                }
                mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
                break;

主动查询后RIL返回的查询信息,此时再调用queueNextSignalStrengthPoll(),构成了死循环。

            case EVENT_GET_SIGNAL_STRENGTH:
                log("handle EVENT_GET_SIGNAL_STRENGTH");
                // This callback is called when signal strength is polled
                // all by itself

                if (!(mCi.getRadioState().isOn())) {
                    // Polling will continue when radio turns back on
                    return;
                }
                ar = (AsyncResult) msg.obj;
                onSignalStrengthResult(ar);
                queueNextSignalStrengthPoll();
                break;

ServiceStateTracker.java在接收到信号格的变化后,通知应用层的过程:
这里写图片描述
其中,TelephonyRegistry使用了回调机制,各个应用层如果想实时监听信号格的变化,需要实现PhoneStateListener接口,并通过SubscriptionManager或者TelephonyManager
把PhoneStateListener实现类加到TelephonyRegistry的监听序列中,之后信号格变化时会回调PhoneStateListener实现类中的onSignalStrengthsChanged()方法。我们可以在onSignalStrengthsChanged()中实现具体的处理逻辑。可以参考MobileSignalController.java中对信号格的处理方式。

信号格DEBUG:

SignalStrength: getGsmLevel ndBm -81
GsmSST  : [GsmSST1] notifySignalStrength: mSignalStrength.getLevel=4

AT      : AT< +ECSQ: 14, 99, -288, -319, -29
AT      : RIL_CMD_READER_1 Enter processLine:+ECSQ: 14, 99, -288, -319, -29

关注后两个,rscp信号强度,ecno信号强度。除以4.


时区,小区

………

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值