涉及的framework telephony类有:
frameworks/base/telephony/.../ServiceState.java
frameworks/opt/telephony/.../ServiceStateTracker.java
frameworks/opt/telephony/.../gsm/GsmServiceStateTracker.java
frameworks/opt/telephony/.../gsm/GSMPhone.java
frameworks/opt/telephony/.../RIL.java
一. ServiceState类
在Telephony Framework层中,使用ServiceState实体类来保存SIM卡注册成功后电信运营商网络的一些基本服务信息,其中的关键信息包括:
1. mVoiceRegState // 语音通话服务的注册状态,可能的状态包括,STATE_IN_SERVICE, STATE_OUT_OF_SERVICE, STATE_EMERGENCY_ONLY, STATE_POWER_OFF
2. mDataRegState // 数据服务的注册状态,可能的状态同上
3. mVoiceOperatorAlphaLong, mVoiceOperatorAlphaShort, mVoiceOperatorNumeric,mDataOperatorAlphaLong, mDataOperatorAlphaShort, mDataOperatorNumeric // 电信运营商的名字(完整),电信运营商的名字(简写),电信运营商编号
4. mRilVoiceRadioTechnology, mRilDataRadioTechnology // 注册上的radio技术。例如2G, 3G, 4G
二.ServiceStateTracker的运行机制
ServiceStateTracker按字面意思可以理解为网络服务状态管理的跟踪者。Phone对象将网络服务状态交给它来管理和维护,即管理,维护上面讲的ServiceState。
对于GSMPhone来说,使用ServiceStateTracker的子类GsmServiceStateTracker,下面具体讲解GsmServiceStateTracker
GsmServiceStateTracker的关键属性如下:
1. mSS // 当前ServiceState对象,调用new ServiceState()创建对象,此构造函数为空,所有的ServiceState的关键属性都是通过调用类似mSS.setState()函数设置的。
2. mNewSS // 最新ServiceState对象,构造方法同上。
3. mSignalStrength // 手机信号强度
GsmServiceStateTracker的关键方法如下:
1. pollState() // 连续向RIL对象发起4个查询请求, 分别是getOperator()获取电信运营商信息,getDataRegistrationState()获取数据服务注册状态,getVoiceRegistrationState()获取语音通话服务注册状态,getNetworkSelectionMode()选择接入电信网络的类型。
2. handlePollStateResult() // 处理RIL返回的查询结果,根据查询结果更新mSS, mNewSS等
3. pollStateDone() // 根据pollState()查询的结果,完成ServiceState对象mSS的更新以及发出服务信息变化对应的通知。
4. updateSpnDisplay() // 更新PLMN,SPN等运营商信息并发出广播
5. queueNextSignalStrengthPoll() // 定时查询手机信号强度,并发出消息通知
GsmServiceStateTracker pollState 流程图如下:
需要注意的是,在handlePollStateResult()中,只有4个查询都返回的时候才会去调用pollStateDone()。
下面具体解析一下pollStateDone(),抽取部分代码如下
private void pollStateDone() {
boolean hasChanged = !mNewSS.equals(mSS);
// swap mSS and mNewSS to put new state in mSS
ServiceState tss = mSS;
mSS = mNewSS;
mNewSS = tss;
// clean slate for next time
mNewSS.setStateOutOfService();
// radio technology changed, such as cdmaphone --> gsmphone
if (hasRilVoiceRadioTechnologyChanged) {
updatePhoneObject();
}
if (hasRilDataRadioTechnologyChanged) {
tm.setDataNetworkTypeForPhone(mPhone.getPhoneId(), mSS.getRilVoiceRadioTechnology());
if (ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN
== mSS.getRilDataRadioTechnology()) {
log("pollStateDone: IWLAN enabled");
}
}
if (hasChanged) {
String operatorNumeric;
// 后面有详细介绍
updateSpnDisplay();
tm.setNetworkRoamingForPhone(mPhone.getPhoneId(), mSS.getVoiceRoaming());
setRoamingType(mSS);
log("Broadcasting ServiceState : " + mSS);
// 通知service state发生变化
mPhone.notifyServiceStateChanged(mSS);
}
}
下面看一下updateSpnDisplay()的关键代码
@Override
protected void updateSpnDisplay() {
// The values of plmn/showPlmn change in different scenarios.
// 1) No service but emergency call allowed -> expected
// to show "Emergency call only"
// EXTRA_SHOW_PLMN = true
// EXTRA_PLMN = "Emergency call only"
// 2) No service at all --> expected to show "No service"
// EXTRA_SHOW_PLMN = true
// EXTRA_PLMN = "No service"
// 3) Normal operation in either home or roaming service
// EXTRA_SHOW_PLMN = depending on IccRecords rule
// EXTRA_PLMN = plmn
// 4) No service due to power off, aka airplane mode
// EXTRA_SHOW_PLMN = false
// EXTRA_PLMN = null
Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
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);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
从上面代码可知,这个函数的主要作用就是把RIL返上来的运营商信息plmn, spn构造广播发出去,
广播类型是SPN_STRINGS_UPDATED_ACTION。锁屏界面会接受这个广播,然后更新锁屏界面的运营商信息。