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.
时区,小区
………