Android网络服务状态运行机制

主要介绍ServiceStateTracker对ServiceState管理的机制和流程

       IMSI(International Mobile Subscriber Identification Number,国际移动用户识别码)

       ServiceState:保存SIM卡注册成功后电信运行商网络的一些基本服务信息,关键信息包括:电信运行商编号、Radio无线通信模块使用的技术类型和状态、电信运营商网络是否处于漫游状态、无线网络信号强度等电信服务基本信息;ServiceState服务状态的管理和更新是通过ServiceStateTracker对象完成的,主要维护ServiceState类的ss和newSS两个实体对象,从而完成ServiceState服务状态的管理和更新。

一、ServiceState实体类的关键信息:

        1.类的实质

               ServiceState类实现了Parcelable[可以了解下原理]接口, 主要有以下两个过程组成:

               writeToParcel序列化过程,将对象数据写入外部提供的Parcel中;

               createFromParcel反序列化过程,通过外部提供的Parcel获取基本数据来创建数据对象。

           2.类的关键常量及属性

              ServiceState类的关键常量主要是管理和保存4种服务状态和一些无线通信模块的标准技术。无线通信网络类型覆盖GSM、CDMA和UMTS等全球主流的无线通信技术。

              ServiceState类的关键属性定义如下:(Android7.0)

private int mVoiceRegState = STATE_OUT_OF_SERVICE;
private int mDataRegState = STATE_OUT_OF_SERVICE; // 服务状态,0~3共4种状态可选,默认取值为1。

private int mVoiceRoamingType;
private int mDataRoamingType; // 是否进入漫游网络标志

private String mVoiceOperatorAlphaLong; // 电信运营商名称(完整)
private String mVoiceOperatorAlphaShort; // 电信运营商名称(简写)
private String mVoiceOperatorNumeric; // 电信运营商编号
private String mDataOperatorAlphaLong;
private String mDataOperatorAlphaShort;
private String mDataOperatorNumeric;

private boolean mIsManualNetworkSelection; // 手动选择电信运营商标志
private boolean mIsEmergencyOnly; // 仅紧急呼叫标志

        3.类的关键方法

             主要体现在以下三个方面:

  •  ServiceState类的序列化和反序列化的过程;
  •  radioTechnologyToString方法获取手机网络类型对应关系;
  •  toString方法

二、ServiceStateTracker的运行机制:

        android.telephony包路径下定义了ServiceState和SignalStrength两个实体类,这两个类不用区分GSM/CDMA手机网络制式类型;CellLocation抽象类定义在android.telephony包路径下,而在子包gsm和cdma下分别实现了GsmCellLocation和CdmaCellLocation类;com.android.internal.telephony包路径下定义ServiceStateTracker抽象类,同时在子包gsm和cdma下分别继承和实现了GsmServiceStateTracker和CdmaServiceStateTracker类。

          ServiceStateTracker类与CallTracker相同,共同继承了Handle类,其实质是自定义的Handle消息处理类,主要两方面的处理逻辑:

  • 负责网络服务状态的管理;
  • 提供网络服务状态控制的能力。

1.ServiceStateTracker代码结构:

        关键属性:

    private CommandsInterface mCi; // RIL的Java对象,此对象与GSMPhone对象一样,mCi对象具备与RIL层交互的能力
    public ServiceState mSS;
    private ServiceState mNewSS;
    private SignalStrength mSignalStrength; // 保存手机接入电信运营商无线网络后的信号量
    public CellLocation mCellLoc; // 小区信息,国内电信运营商基本没有使用
    public CellLocation mNewCellLoc;
    private GsmCdmaPhone mPhone; // GSMPhone对象

        关键方法:

Android网络服务状态运行机制_第1张图片

由以上可知,ServiceStateTracker对象主要通过更新mSS和mSignalStrength对象来完成服务信息的更新。对于服务状态的控制,Phone对外提供统一的方法,最终通过调用mSST对象响应的方法来实现,及ServiceStateTracker对象。

2.ServiceStateTracker的Handler消息处理机制

Handler有三种处理方式,在ServiceStateTracker类中使用其中两种运行和处理机制:

       1).基本的Handler消息注册和响应处理机制

        在ServiceStateTracker类的构造方法中找到Handler消息注册的代码逻辑,GsmServiceStateTracker对象会被动接收并相应RIL对象发出的7种类型的Handler消息,最关键的是以下5钟:

                EVENT_RADIO_AVAILABLE(无线通信模块Modem或Radio开启状态)

                EVENT_RADIO_STATE_CHANGED(无线通信模块状态变化)

                EVENT_NETWORK_STATE_CHANGED(无线网络状态变化)

                EVENT_SIGNAL_STRENGTH_UPDATE(无线网络信号量变化)

                EVENT_SIM_READY(手机中的SIM卡已经准备完成)

[这几种服务状态变化的Handler消息都定义在ServiceStateTracker抽象类中,并且仅在该类中产生相应,也就是说,有且仅有ServiceStateTracker对象会接收和响应RIL对象发出的这几种与网络服务状态相关的Handler消息通知。]

        对上面5种Handler消息的响应在handleMessage方法中。处理如下:

            case EVENT_RADIO_AVAILABLE: // Radio状态可用,没有处理逻辑
                break;
            case EVENT_SIM_READY:
                ......
                pollState();
                queueNextSignalStrengthPoll(); [1]
                break;
            case EVENT_RADIO_STATE_CHANGED:
                ......
                pollState();
                break;
            case EVENT_NETWORK_STATE_CHANGED:
                pollState();
                break;
            case EVENT_GET_SIGNAL_STRENGTH:
                ......
                onSignalStrengthResult(ar); // 响应接入的无线网络信号量变化
                queueNextSignalStrengthPoll();
                break;

        pollState():查询当前最新网络服务状态,其逻辑主要分为两个部分:

  • Radio无线通信模块异常的情况
  • Radio无线通信模块正常的情况

        通过mCi.getRadioState()判断Riadio无线通信模块是否正常

    switch (mCi.getRadioState()) {
        case RADIO_UNAVAILABLE:
            mNewSS.setStateOutOfService(); // STATE_OUT_OF_SERVICE
            mNewCellLoc.setStateInvalid(); // 设置小区广播不可用
            setSignalStrengthDefaultValues(); //设置无线信号量为默认值
            mGotCountryCode = false; // 未获取国家代码
            pollStateDone();
            break;
        case RADIO_OFF:
            mNewSS.setStateOff();
            mNewCellLoc.setStateInvalid();
            setSignalStrengthDefaultValues();
            mGotCountryCode = false;
            pollStateDone();
            break;
        default: // 正常
            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));// 获取网络类型
            break;
    }

       2).Handler消息Callback回调处理方式

        这种Handler消息处理机制的实现逻辑代码框架基本一致,主要分为两步完成:

        (1)调用ObtainMessage方法创建Message对象;

        (2)通过mCi对象向RIL对象发起网络服务信息查询方法的调用

    case EVENT_POLL_STATE_REGISTRATION:
    case EVENT_POLL_STATE_GPRS:
    case EVENT_POLL_STATE_OPERATOR:
    case EVENT_POLL_STATE_NETWORK_SELECTION_MODE:
         ar = (AsyncResult) msg.obj;
         handlePollStateResult(msg.what, ar);
         break;

        ServiceStateTracker与RIL对象的交互根据这两个对象谁主动发起分为两大类:

        1)ServiceStateTracker对象被动接收:ServiceStateTracker对象的消息处理机制,它会被动的接收和处理RIL对象上报的7个类型的Handle消息。

        2)ServiceStateTracker对象主动发起:最重要的是调用setRadioPower方法打开或关闭Radio无线通信模块。

3.handlePollStateResult方法处理逻辑

        其处理逻辑可以分为三部分,分别如下:

        1)RIL返回查询结果的异常判断和处理

    // Ignore stale requests from last poll
    if (ar.userObj != mPollingContext) return; // 请求与返回的消息不匹配,直接返回不处理
    if (ar.exception != null)

    { // RIL对象返回Message对象,其中产生了异常
        CommandException.Error err = null;

        if (ar.exception instanceof CommandException) {
            err = ((CommandException) (ar.exception)).getCommandError();
        }

        if (err == CommandException.Error.RADIO_NOT_AVAILABLE) {
            // Radio has crashed or turned off
            cancelPollState();
            loge("handlePollStateResult cancelPollState due to RADIO_NOT_AVAILABLE");
            // Clear status and invoke pollStateDone to notify other module
            if (mCi.getRadioState() != CommandsInterface.RadioState.RADIO_ON) {
                mNewSS.setStateOff();
                mNewCellLoc.setStateInvalid();
                setSignalStrengthDefaultValues();
                mGotCountryCode = false;
                pollStateDone();
            }
            return;
        }
    }

        2)分别处理4个不同网络服务查询返回的结果 handlePollStateResultMessage方法中

    case EVENT_POLL_STATE_REGISTRATION: {
        if (mPhone.isPhoneTypeGsm()) {
            states = (String[]) ar.result; // 获取查询结果基本信息
            int regState = ServiceState.RIL_REG_STATE_UNKNOWN;
            if (states.length > 0) {
                try {
                    regState = Integer.parseInt(states[0]); // 获取网络注册状态编号
                    ...... // 获取小区广播相关状态信息lac、cid、和psc
                } catch (NumberFormatException ex) {
                    loge("error parsing RegistrationState: " + ex);
                }
            }

            mGsmRoaming = regCodeIsRoaming(regState); // 根据网络注册状态编号获取并设置漫游标志
            mNewSS.setVoiceRegState(regCodeToServiceState(regState)); // 根据网络注册状态编号获取并设置服务状态

            boolean isVoiceCapable = mPhone.getContext().getResources()
                    .getBoolean(com.android.internal.R.bool.config_voice_capable);
            if ((regState == ServiceState.RIL_REG_STATE_DENIED_EMERGENCY_CALL_ENABLED
                    || regState == ServiceState.RIL_REG_STATE_NOT_REG_EMERGENCY_CALL_ENABLED
                    || regState == ServiceState.RIL_REG_STATE_SEARCHING_EMERGENCY_CALL_ENABLED
                    || regState == ServiceState.RIL_REG_STATE_UNKNOWN_EMERGENCY_CALL_ENABLED)
                    && isVoiceCapable) {
                mEmergencyOnly = true;
            } else {
                mEmergencyOnly = false;
            }
            ...... // 处理小区信息的逻辑
        }
        break;
http://www.3gpp.org/ftp/Specs/html-info/

从上面的网络摘录的关键信息·[实际上好像打不开]

0 not registered, MT is not currently searching a new operator to register to

1 registerede, home network // 本地网络

2 not  registered, but MT is currently searching a new operator to register to

3 registration denied

4 unknow (e.g. out of GERAN/UTRAN/E-UTRAN coverage)

5 registered, roaming // 漫游网络

6 registered for "SMS only", home network (applicable only when indicates E-UTRAN)

7 registered for "SMS only", roaming (applicable only when 8 attached for emergency bearer services only (see NOTE2) (not applicable)


    case EVENT_POLL_STATE_GPRS: {
        if (mPhone.isPhoneTypeGsm()) {
            states = (String[]) ar.result;

            int type = 0; // 数据连接的类型
            int regState = ServiceState.RIL_REG_STATE_UNKNOWN; // 服务状态编号
            mNewReasonDataDenied = -1;
            mNewMaxDataCalls = 1; // 最大支持的数据连接
            if (states.length > 0) {
                try {
                    ...... // type、mNewReasonDataDenied和mNewMaxDataCalls变量取值
                } catch (NumberFormatException ex) {
                    loge("error parsing GprsRegistrationState: " + ex);
                }
            }
            int dataRegState = regCodeToServiceState(regState);
            mNewSS.setRilDataRegState(regState);
            mNewSS.setDataRegState(dataRegState);
            mDataRoaming = regCodeIsRoaming(regState);
            mNewSS.setRilDataRadioTechnology(type);

            //carrier aggregation
            mNewSS.setProprietaryDataRadioTechnology(type);
            //mNewSS.setRilDataRadioTechnology(type);
        }
        break;

regCodeToServiceState与regCodeIsRoaming与EVENT_POLL_STATE_REGISTRATION保持一致

        case EVENT_POLL_STATE_OPERATOR: {
            if (mPhone.isPhoneTypeGsm()) {
                 String opNames[] = (String[]) ar.result;

                 if (opNames != null && opNames.length >= 3) {
                     String brandOverride = mUiccController.getUiccCard(getPhoneId()) != null ?
                     mUiccController.getUiccCard(getPhoneId()).getOperatorBrandOverride() : null;
                     if (brandOverride != null) {
                         log("EVENT_POLL_STATE_OPERATOR: use brandOverride=" + brandOverride);
                         mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]);
                     }
                 }
            }
            break;


    case EVENT_POLL_STATE_NETWORK_SELECTION_MODE: {
        ints = (int[])ar.result;
        mNewSS.setIsManualSelection(ints[0] == 1); // 设置选择网络类型手动还是自动
        if ((ints[0] == 1) && (!mPhone.isManualNetSelAllowed())) {
            mPhone.setNetworkSelectionModeAutomatic (null);
        }
        break;

        3)调用pollStateDone方法完成收尾工作

        pollStateDone主要分为三个处理逻辑:

        (1)通过当前状态和新的状态获取服务信息改变的标志

Android网络服务状态运行机制_第2张图片

        这写服务状态信息变化的标志都是通过ServiceStateTracker对象中多个XX与newXX属性做比较得出的。

        (2)更新对象信息

        。。。一些变量的更新,不做说明

        (3)发出网络服务状态信息变化的消息通知

        发出SPN_STRINGS_UPDATED_ACTION广播,更新SPN的显示,设置运营商参数,通过phone对象的方法调用,发出ServiceState变化的通知

三、ServiceState最佳实践与飞行模式的实现
        1.获取运营商信息

        手机成功注册并接入运营商网络后,一般情况下会在home界面显示运营商名称,运营商名称主要有以下两种:

  • PLMN(Public Land Mobile Network, 公共陆地移动网络),当前手机注册的网络提供商名称,是通过注册成功的网络获取的,如中国移动、中国联通等。
  • SPN(Service Provider Network, 服务提供商名称),预置在SIM卡中;统一运营商发行的SIM卡中,SPN可能都不同,比如中国移动发行的SIM卡,其SPN可能有全球通、动感地带或神州行等内容。

        重点可分析updateSpnDisplay()方法,其发出的SPN_STRINGS_UPDATED_ACTION的系统广播,主要有三个定义的Broadcast广播接收过滤器会接收此广播,分别是:

  • KeyguardUpdateMonitor:锁屏界面会更新和显示运营商信息
  • CarrierLabel:时钟界面
  • NetworkController:通知栏,默认仅显示PLMN名称

        2.通知栏手机信号实时变化

        手机信号的实时变化准确说是准实时变化,是由ServiceStateTracker对象调用queueNextSignalStrengthPoll定时向RIL对象发起查询手机接入无线网络的信号量,然后发起信号量变化的通知。

        queueNextSignalStrengthPoll代码如下:

    private void queueNextSignalStrengthPoll() {
        if (mDontPollSignalStrength) {
            return;
        }

        Message msg;
        msg = obtainMessage();
        msg.what = EVENT_POLL_SIGNAL_STRENGTH;

        // TODO Don't poll signal strength if screen is off
        sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
    }
        handleMessage的响应如下:

    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));//向RIL对象查询最新的网络信号量,obtainMessage穿件查询信号量成功后的callback消息对象
    break;
        查询完成后,响应如下:

    case EVENT_GET_SIGNAL_STRENGTH:

        if (!(mCi.getRadioState().isOn())) {
        // Polling will continue when radio turns back on
        return;
        }
        ar = (AsyncResult) msg.obj;
        onSignalStrengthResult(ar); // 保存和更新无线网络信号量
        queueNextSignalStrengthPoll(); // 循环调用该方法

        break;

        3.飞行模式的实现

        飞行模式打开或关闭都是通过发送广播Intent.ACTION_AIRPLANE_MODE_CHANGED,广播接收端的处理:主要是通过Phone对象调用setRadioPower方法



 

你可能感兴趣的:(Telephony通信功能)