UiccController 是對SIM卡管理的控制器,它通過 UiccCard 來更新SIM卡的資訊。
1.UiccController 注冊了兩個監聽器,來監聽RIL的消息。分别監聽 UNSOL_RESPONSE_RADIO_STATE_CHANGED 和 RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED,當radio 和 sim卡狀态發生變化時,它會第一時間得到消息。
2. 開機後,RIL 會上報 Radio off,然後上報 radio on,一旦 radio on ,mOnRegistrants.notifyRegistrants(),這個語句就會被調用,具體實作如下,
protected void setRadioState(RadioState newState) {
.....
mRadioStateChangedRegistrants.notifyRegistrants();
if (mState.isAvailable() && !oldState.isAvailable()) {
Log.d(LOG_TAG,"Notifying: radio available");
mAvailRegistrants.notifyRegistrants();
onRadioAvailable();
}
if (!mState.isAvailable() && oldState.isAvailable()) {
Log.d(LOG_TAG,"Notifying: radio not available");
mNotAvailRegistrants.notifyRegistrants();
}
if (mState.isOn() && !oldState.isOn()) {
Log.d(LOG_TAG,"Notifying: Radio On");
mOnRegistrants.notifyRegistrants();
}
if ((!mState.isOn() || !mState.isAvailable())
&& !((!oldState.isOn() || !oldState.isAvailable()))
) {
Log.d(LOG_TAG,"Notifying: radio off or not available");
mOffOrNotAvailRegistrants.notifyRegistrants();
}
}
}
notify 後,會通知相關對象,相關對象就會進行處理,UiccController 就是其中一個對象,處理事件 EVENT_ICC_STATUS_CHANGED.
因為 UiccController的構造方法中存在如下代碼。
private UiccController(Context c, CommandsInterface[] ci) {
if (DBG) log("Creating UiccController");
mContext = c;
mCi = ci;
for (int i = 0; i < mCi.length; i++) {
Integer index = new Integer(i);
//意思是說 RIL 中收到 RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED 消息,notify 所有監聽器後,UiccController 就會處理 EVENT_ICC_STATUS_CHANGED 事件
mCi[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
mCi[i].registerForOff(this, EVENT_RADIO_OFF, index);
// TODO remove this once modem correctly notifies the unsols
// 意思是說 RIL 中收到 Radio ON 消息,notify 所有的監聽器後,UiccController 就會處理 EVENT_ICC_STATUS_CHANGED 事件。
mCi[i].registerForOn(this, EVENT_ICC_STATUS_CHANGED, index);
}
}
同樣 當SIM卡狀态發生變化後,上報RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED後,UiccController 也将處理事件 Event_ICC_STATUS_CHANGED,是以當手機信号不好或者SIM卡本身的狀态發生變化的時候,消息都會集中到UiccConroller這裡進行處理,然後傳播到所有對SIM卡資料感興趣的地方。UiccController 就是SIM卡管理的最為核心的類。
<1> 通知 UiccController,UiccControl 處理EVENT_ICC_STATUS_CHANGED的消息
case EVENT_ICC_STATUS_CHANGED:
if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");
mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));
break;
<2> UiccControl 發出 RIL_REQUEST_GET_SIM_STATUS的請求,擷取SIM卡的狀态資訊。
case EVENT_GET_ICC_STATUS_DONE:
if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");
AsyncResult ar = (AsyncResult)msg.obj;
onGetIccCardStatusDone(ar);
break;
onGetIccCardStatusDone:
IccCardStatus status = (IccCardStatus)ar.result;
if (mUiccCard == null) {
//Create new card
mUiccCard = new UiccCard(mContext, mCi, status);
} else {
//Update already existing card
mUiccCard.update(mContext, mCi , status);
}
if (DBG) log("Notifying IccChangedRegistrants");
mIccChangedRegistrants.notifyRegistrants();
<3> RIL 傳回SIM卡的狀态資訊,UiccControl 處理傳回的SIM卡的資訊,建立 UiccCard和 UiccCardApplication 對象。具體的實作過程如下
主要是在 UiccCard 的update 方法當中
public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
synchronized (mLock) {
if (mDestroyed) {
loge("Updated after destroyed! Fix me!");
return;
}
CardState oldState = mCardState;
mCardState = ics.mCardState;
mUniversalPinState = ics.mUniversalPinState;
mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex;
mContext = c;
mCi = ci;
//update applications
if (DBG) log(ics.mApplications.length + " applications");
for ( int i = 0; i < mUiccApplications.length; i++) {
if (mUiccApplications[i] == null) {
//Create newly added Applications
if (i < ics.mApplications.length) {
mUiccApplications[i] = new UiccCardApplication(this,
ics.mApplications[i], mContext, mCi);
}
} else if (i >= ics.mApplications.length) {
//Delete removed applications
mUiccApplications[i].dispose();
mUiccApplications[i] = null;
} else {
//Update the rest
mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
}
}
if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
// Initialize or Reinitialize CatService
mCatService = CatService.getInstance(mCi,
mContext,
this);
} else {
if (mCatService != null) {
mCatService.dispose();
}
mCatService = null;
}
sanitizeApplicationIndexes();
RadioState radioState = mCi.getRadioState();
if (DBG) log("update: radioState=" + radioState + " mLastRadioState="
+ mLastRadioState);
// No notifications while radio is off or we just powering up
if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
if (oldState != CardState.CARDSTATE_ABSENT &&
mCardState == CardState.CARDSTATE_ABSENT) {
if (DBG) log("update: notify card removed");
mAbsentRegistrants.notifyRegistrants();
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
} else if (oldState == CardState.CARDSTATE_ABSENT &&
mCardState != CardState.CARDSTATE_ABSENT) {
if (DBG) log("update: notify card added");
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
}
}
mLastRadioState = radioState;
}
}
3.系統中其他對象對SIM卡的狀态,SIM卡的資料資訊很感興趣,他們通過UiccController來監聽SIM卡的狀态變化。是以當UiccCard更新完成後,它就通知 ServiceStateTracker(Gsm or Cdma),IccCardProxy,DataConnectionTracker,PhoneBase,SIM卡的狀态已經發生了變化。
DataConnectionTracker
GsmDataConnectionTracker
protected void onUpdateIcc() {
if (mUiccController == null ) {
return;
}
IccRecords newIccRecords = mUiccController.getIccRecords(UiccController.APP_FAM_3GPP);
IccRecords r = mIccRecords.get();
if (r != newIccRecords) {
if (r != null) {
log("Removing stale icc objects.");
r.unregisterForRecordsLoaded(this);
mIccRecords.set(null);
}
if (newIccRecords != null) {
log("New records found");
mIccRecords.set(newIccRecords);
newIccRecords.registerForRecordsLoaded(
this, DctConstants.EVENT_RECORDS_LOADED, null);
}
}
}
更新所持有的mIccRecords 對象的資料
IccCardProxy
private void updateIccAvailability() {
synchronized (mLock) {
UiccCard newCard = mUiccController.getUiccCard();
CardState state = CardState.CARDSTATE_ABSENT;
UiccCardApplication newApp = null;
IccRecords newRecords = null;
if (newCard != null) {
state = newCard.getCardState();
newApp = newCard.getApplication(mCurrentAppType);
if (newApp != null) {
newRecords = newApp.getIccRecords();
}
}
if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) {
if (DBG) log("Icc changed. Reregestering.");
unregisterUiccCardEvents();
mUiccCard = newCard;
mUiccApplication = newApp;
mIccRecords = newRecords;
registerUiccCardEvents();
}
updateExternalState();
}
}
更新所持有的 mUiccCard,mUiccApplication,mIccRecords 對象。
當sim卡狀态變化時,會發出廣播
private void broadcastIccStateChangedIntent(String value, String reason) {
synchronized (mLock) {
if (mQuietMode) {
log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " + value
+ " reason " + reason);
return;
}
Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " + value
+ " reason " + reason);
ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE,
UserHandle.USER_ALL);
}
}
如果應用程式或者系統服務對SIM卡的狀态有興趣,那麼可以監聽這個廣播
PhoneBase
GsmPhone
protected void onUpdateIccAvailability() {
if (mUiccController == null ) {
return;
}
UiccCardApplication newUiccApplication =
mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
UiccCardApplication app = mUiccApplication.get();
if (app != newUiccApplication) {
if (app != null) {
if (LOCAL_DEBUG) log("Removing stale icc objects.");
if (mIccRecords.get() != null) {
unregisterForSimRecordEvents();
mSimPhoneBookIntManager.updateIccRecords(null);
}
mIccRecords.set(null);
mUiccApplication.set(null);
}
if (newUiccApplication != null) {
if (LOCAL_DEBUG) log("New Uicc application found");
mUiccApplication.set(newUiccApplication);
mIccRecords.set(newUiccApplication.getIccRecords());
registerForSimRecordEvents();
mSimPhoneBookIntManager.updateIccRecords(mIccRecords.get());
}
}
}
更新所持有的mUiccApplication,mIccRecords,mSimPhoneBookIntManager 對象。
ServiceStateTracker
GsmServiceStateTracker
protected void onUpdateIccAvailability() {
if (mUiccController == null ) {
return;
}
UiccCardApplication newUiccApplication =
mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP);
if (mUiccApplcation != newUiccApplication) {
if (mUiccApplcation != null) {
log("Removing stale icc objects.");
mUiccApplcation.unregisterForReady(this);
if (mIccRecords != null) {
mIccRecords.unregisterForRecordsLoaded(this);
}
mIccRecords = null;
mUiccApplcation = null;
}
if (newUiccApplication != null) {
log("New card found");
mUiccApplcation = newUiccApplication;
mIccRecords = mUiccApplcation.getIccRecords();
mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null);
if (mIccRecords != null) {
mIccRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
}
}
}
}
更新 所持有的mIccRecords,mUiccApplication,等對象。
與UiccController 相關的資料流程如下圖所示
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISNyEjNzAjM2ETOwYDMzEDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)