运营商显示流程分析之运营商信息的获取和赋值
一. SIM卡运营商和网络运营商
SIM卡运营商即SPN, 网络运营商即PLMN, 首先我们需要知道SIM卡运营商和网络运营商的获取方式, 如下:
private TelephonyManager mTelephonyManager;
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
// 获取SIM卡运营商名称及SIM卡运营商代码(MCCMNC码)
String simOperator = mTelephonyManager.getSimOperator();
String networkOperator = mTelephonyManager.getNetworkOperator();
// 获取网络运营商名称及网络运营商代码(MCCMNC码)
String simOperatorName = mTelephonyManager.getSimOperatorName();
String networkOperatorName = mTelephonyManager.getNetworkOperatorName();
二. 获取SIM卡和网络运营商信息的具体实现
我们通过TelephonyManager获取的SIM卡和网络运营商的相关信息, 因此首先我们到TelephonyManager中查看实现方式:
/**
* Returns the MCC+MNC (mobile country code + mobile network code) of the
* provider of the SIM. 5 or 6 decimal digits.
* <p>
* Availability: SIM state must be {@link #SIM_STATE_READY}
*
* @see #getSimState
*/
public String getSimOperator() {
return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC);
}
/**
* Returns the Service Provider Name (SPN).
* <p>
* Availability: SIM state must be {@link #SIM_STATE_READY}
*
* @see #getSimState
*/
public String getSimOperatorName() {
return SystemProperties.get(TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA);
}
/**
* Returns the alphabetic name of current registered operator.
* <p>
* Availability: Only when user is registered to a network. Result may be
* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
* on a CDMA network).
*/
public String getNetworkOperatorName() {
return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_ALPHA);
}
/**
* Returns the numeric name (MCC+MNC) of current registered operator.
* <p>
* Availability: Only when user is registered to a network. Result may be
* unreliable on CDMA networks (use {@link #getPhoneType()} to determine if
* on a CDMA network).
*/
public String getNetworkOperator() {
return SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC);
}
通过上面的TelephonyManager的源码我们可以发现, SIM卡和网络运营商的信息是通过获取系统的属性得到的, 因此我们只需要查询到上面的属性是在何处被赋值的, 就可以知道该信息的来源
需要查询的属性如下:
TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC,
TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA,
TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
TelephonyProperties.PROPERTY_OPERATOR_NUMERIC
通过全局搜索, 可以发现TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC和TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA是在SIMRecords中被赋值的
/**
* Finite State Machine to load Service Provider Name , which can be stored
* in either EF_SPN (3GPP), EF_SPN_CPHS, or EF_SPN_SHORT_CPHS (CPHS4.2)
*
* After starting, FSM will search SPN EFs in order and stop after finding
* the first valid SPN
*
* If the FSM gets restart while waiting for one of
* SPN EFs results (i.e. a SIM refresh occurs after issuing
* read EF_CPHS_SPN), it will re-initialize only after
* receiving and discarding the unfinished SPN EF result.
*
* @param start set true only for initialize loading
* @param ar the AsyncResult from loadEFTransparent
* ar.exception holds exception in error
* ar.result is byte[] for data in success
*/
private void getSpnFsm(boolean start, AsyncResult ar) {
...
switch(mSpnState){
...
case READ_SPN_3GPP:
if (ar != null && ar.exception == null) {
data = (byte[]) ar.result;
mSpnDisplayCondition = 0xff & data[0];
mSpn = IccUtils.adnStringFieldToString(data, 1, data.length - 1);
...
// 设置SIM卡运营商名称
SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, mSpn);
mSpnState = GetSpnFsmState.IDLE;
} else {
...
}
break;
case READ_SPN_CPHS:
if (ar != null && ar.exception == null) {
data = (byte[]) ar.result;
mSpn = IccUtils.adnStringFieldToString(data, 0, data.length);
...
// 设置SIM卡运营商名称
SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, mSpn);
mSpnState = GetSpnFsmState.IDLE;
} else {
...
}
break;
case READ_SPN_SHORT_CPHS:
if (ar != null && ar.exception == null) {
data = (byte[]) ar.result;
mSpn = IccUtils.adnStringFieldToString(data, 0, data.length);
...
// 设置SIM卡运营商名称
SystemProperties.set(PROPERTY_ICC_OPERATOR_ALPHA, mSpn);
}else {
...
}
...
}
}
@Override
protected void onAllRecordsLoaded() {
...
String operator = getOperatorNumeric();
if (!TextUtils.isEmpty(operator)) {
...
// 设置运营商代码
SystemProperties.set(PROPERTY_ICC_OPERATOR_NUMERIC, operator);
} else {
log("onAllRecordsLoaded empty 'gsm.sim.operator.numeric' skipping");
}
...
}
TelephonyProperties.PROPERTY_OPERATOR_ALPHA和TelephonyProperties.PROPERTY_OPERATOR_NUMERIC是在GsmServiceStateTracker中赋值的
private void pollStateDone() {
...
if (hasChanged) {
String operatorNumeric;
updateSpnDisplay();
// 设置网络运营商名称
mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ALPHA,
mSS.getOperatorAlphaLong());
String prevOperatorNumeric =
SystemProperties.get(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, "");
operatorNumeric = mSS.getOperatorNumeric();
// 设置网络运营商代码
mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_NUMERIC, operatorNumeric);
// 更新配置
updateCarrierMccMncConfiguration(operatorNumeric,
prevOperatorNumeric, mPhone.getContext());
...
// 是否是漫游
mPhone.setSystemProperty(TelephonyProperties.PROPERTY_OPERATOR_ISROAMING,
mSS.getRoaming() ? "true" : "false");
mPhone.notifyServiceStateChanged(mSS);
}
...
}
通过上面的步骤, 我们已经知道SIM卡和运营商信息的获取及是在何处被赋值, 接下来分析SIM卡运营商信息的读取和显示流程