Telephony基础之DataCall业务(ServiceState.java)

本文介绍了ServiceState的概念及其在手机注册到电信运营商网络过程中的作用。详细解释了ServiceState的结构,包括服务状态和服务技术类型等关键信息,并阐述了其创建与更新机制。

 

                                                                                          开机注网流程图

                                                                                            信号更新流程图

一,什么是ServiceState
   Servicestate(服务状态),手机插入SIM卡并且开机成功之后,Modem会读取SIM卡的IMSI完成信息验证和电信运营商移动网络的注册,手机才能使用电信运营商的服务,如电话、短信等功能。
   Telephony Framework中,使用ServiceState实体类来保存SIM卡注册(即我们通常所说的注网)成功后电信运营商的一些基本服务信息。如服务状态、无线通信采用的技术类型和状态、是否漫游、无线网络信号强度等。

二,ServiceState的结构 (4个int+6个String+ 4个int):
 
Int   mVoiceRegState      (value: 0,1,2,3)
Int   mDataRegState       (value: 0,1,2,3)
Int   mVoiceRoamingType   (value: 0,1,2,3)
Int   mDataRoamingType    (value: 0,1,2,3)

String   mVoiceOperatorAlphaLong
String   mVoiceOperatorAlphaShort
String   mVoiceOperatorNumeric
String   mDataOperatorAlphaLong
String   mDataOperatorAlphaShort
String   mDataOperatorNumeric

Int    mIsManualNetworkSelection
Int    mRilVoiceRadioTechnology
Int    mRilDataRadioTechnology
Int    mCssIndicator
Int    mNetworkId
Int    mSystemId
Int    mCdmaRoamingIndicator
Int    mCdmaDefaultRoamingIndicator
Int    mCdmaEriIconIndex
Int    mCdmaEriIconMode
Int    mIsEmergencyOnly
Int    mIsDataRoamingFromRegistration
Int    mIsUsingCarrierAggregation
Int    mRilImsRadioTechnology
 

三,ServiceState的创建与更新
1,创建:在初始化ServiceStateTracker时创建
ServiceStateTracker(){
    updatePhoneType();
}

public void updatePhoneType() {
        mSS = new ServiceState();
        mNewSS = new ServiceState();
}


2,更新:在ServiceStateTracker.handlePollStateResult()-->handlePollStateResultMessage(what, ar)中取出RIL传过来的值,进而调用mNewSS一系列set方法赋值,
     之后进一步调用pollStateDone()-->pollStateDoneXXX()方法对比mSS(原先)与mNewSS(当前)的状态后,把mNewSS的内容交给mSS,并clean自身.
        // swap mSS and mNewSS to put new state in mSS
        ServiceState tss = mSS;
        mSS = mNewSS;
        mNewSS = tss;
        // clean slate for next time
        mNewSS.setStateOutOfService();    



VOICE_REGISTRATION_STATE与DATA_REGISTRATION_STATE流程差不多:
02-09 11:51:09.027  4974  5059 D RILJ    : [3759]< VOICE_REGISTRATION_STATE {1, f11b, 0a1ba01c, 3, null, null, null, 0, null, null, null, null, null, 0, 87} [SUB0]
02-09 11:51:09.057  4974  5059 D RILJ    : [3754]< DATA_REGISTRATION_STATE {2, null, null, null, 0, 20, null, null, null, null, null} [SUB0]
其中,RIL传过来的RegState有10种,通过regCodeToServiceState()转换:
    /** code is registration state 0-5 from TS 27.007 7.2 */
    private int regCodeToServiceState(int code) {
        switch (code) {
            case 0:
            case 2: // 2 is "searching"
            case 3: // 3 is "registration denied"
            case 4: // 4 is "unknown" no vaild in current baseband
            case 10:// same as 0, but indicates that emergency call is possible.
            case 12:// same as 2, but indicates that emergency call is possible.
            case 13:// same as 3, but indicates that emergency call is possible.
            case 14:// same as 4, but indicates that emergency call is possible.
                return ServiceState.STATE_OUT_OF_SERVICE;

            case 1:
            case 5: // 5 is "registered, roaming"
                return ServiceState.STATE_IN_SERVICE;

            default:
                loge("regCodeToServiceState: unexpected service state " + code);
                return ServiceState.STATE_OUT_OF_SERVICE;
        }
    }


Operator相关的几个参数更新:
02-09 11:51:09.023  4974  5059 D RILJ    : [3753]< OPERATOR {CHN-UNICOM, UNICOM, 46001} [SUB0]
String opNames[] = (String[]) ar.result
mNewSS.setOperatorName(brandOverride, brandOverride, opNames[2]);

    public void setOperatorName(String longName, String shortName, String numeric) {
        mVoiceOperatorAlphaLong = longName;
        mVoiceOperatorAlphaShort = shortName;
        mVoiceOperatorNumeric = numeric;
        mDataOperatorAlphaLong = longName;
        mDataOperatorAlphaShort = shortName;
        mDataOperatorNumeric = numeric;
    }


NETWORK_SELECTION_MODE比较简单:(1为手动,0为自动)
                ints = (int[])ar.result;
                mNewSS.setIsManualSelection(ints[0] == 1);
                if ((ints[0] == 1) && (!mPhone.isManualNetSelAllowed())) {
                        /*
                         * modem is currently in manual selection but manual
                         * selection is not allowed in the current mode so
                         * switch to automatic registration
                         */
                    mPhone.setNetworkSelectionModeAutomatic (null);
                    log(" Forcing Automatic Network Selection, " +
                            "manual selection is not allowed");
                }


 

### com.android.internal.telephony.CommandException: RADIO_NOT_AVAILABLE 错误的原因及解决方案 #### 错误原因分析 1. **RIL(Radio Interface Layer)服务不可用** 当设备的RIL服务因某些原因中断或未正常启动时,可能导致`RADIO_NOT_AVAILABLE`错误。例如,在日志中观察到`Disconnected from 'rild' socket`表明RIL守护进程与应用程序之间的通信已断开[^4]。 2. **调制解调器硬件问题** 如果设备的调制解调器硬件出现故障或处于关闭状态,也可能导致此错误。例如,用户可能手动关闭了飞行模式下的蜂窝数据功能,或者调制解调器本身存在硬件缺陷[^4]。 3. **网络选择命令异常** 在处理网络选择请求时,如果RIL层未能正确响应`RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL_EXT`命令,可能会返回`RADIO_NOT_AVAILABLE`错误。这通常发生在请求参数不正确或调制解调器未准备好处理该请求的情况下[^4]。 4. **系统资源不足** 如果设备的系统资源(如内存或CPU)不足,可能导致RIL服务无法正常运行,从而引发`RADIO_NOT_AVAILABLE`错误。这种情况在低内存设备或高负载环境下较为常见。 #### 解决方案 1. **检查RIL服务状态** 确保RIL服务正常运行。可以通过以下代码片段监控RIL服务的状态: ```java try { TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (tm != null && tm.getSimState() == TelephonyManager.SIM_STATE_READY) { Log.d("RILService", "RIL service is ready."); } else { Log.e("RILService", "RIL service is not available."); } } catch (Exception e) { Log.e("RILService", "Error checking RIL service: " + e.getMessage()); } ``` 2. **重启RIL服务** 如果发现RIL服务异常,可以尝试通过以下方法重启RIL服务: - 执行`adb shell setpropctl ril.restart true`以触发RIL服务重启。 - 或者通过重新启动设备来恢复RIL服务。 3. **验证调制解调器状态** 检查调制解调器是否处于活动状态,并确保其支持当前网络模式。可以通过以下代码片段获取调制解调器信息: ```java String modemStatus = SystemProperties.get("gsm.version.baseband"); Log.d("ModemStatus", "Current modem version: " + modemStatus); ``` 4. **优化网络选择逻辑** 在设置手动网络选择时,确保传递正确的参数,并添加适当的错误处理机制。例如: ```java try { ITelephony telephonyService = (ITelephony) m.invoke(tm); telephonyService.setNetworkSelectionModeManual("46001"); // 设置为特定PLMN } catch (Exception e) { Log.e("NetworkSelection", "Failed to set manual network selection: " + e.getMessage()); } ``` 5. **增加系统资源** 如果设备资源不足,可以通过清理后台任务、释放内存等方式优化系统性能,从而减少`RADIO_NOT_AVAILABLE`错误的发生概率。 ### 示例代码:检测并处理RADIO_NOT_AVAILABLE错误 ```java public void handleRadioNotAvailable() { try { TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); if (tm.getSimState() != TelephonyManager.SIM_STATE_READY) { Log.e("RadioState", "SIM card is not ready."); return; } ITelephony telephonyService = (ITelephony) m.invoke(tm); if (telephonyService == null) { Log.e("RadioState", "Telephony service is unavailable."); return; } boolean isRadioAvailable = telephonyService.isRadioOn(); if (!isRadioAvailable) { Log.w("RadioState", "Radio is off, attempting to turn it on."); telephonyService.setRadio(true); } } catch (Exception e) { Log.e("RadioState", "Error handling radio state: " + e.getMessage()); } } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值