運營商顯示流程分析之運營商信息的獲取和賦值
一. 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卡運營商信息的讀取和顯示流程