1.RIL從modem收到主動上報的消息
RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED
2.UiccController監聽了這條消息,mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
===========================UICC架構結構=================================
===========================UICC架構結構=================================
看一下在UiccController中的處理過程
case EVENT_ICC_STATUS_CHANGED:
->mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index));
請求卡的狀态,并回調EVENT_GET_ICC_STATUS_DONE
case EVENT_GET_ICC_STATUS_DONE:
->onGetIccCardStatusDone(ar, index);
卡的狀态放在了ar裡,開始處理ar。
在onGetIccCardStatusDone中,卡的處理分成兩種,如果mUiccCards[index]已經被執行個體化,就會更新狀态,否則建立新的mUiccCards[index]。
if (mUiccCards[index] == null) {
//Create new card
mUiccCards[index] = new UiccCard(mContext, mCis[index], status, index);
} else {
//Update already existing card
mUiccCards[index].update(mContext, mCis[index] , status);
}
最後要通知卡變化了mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null));
a.建立新的mUiccCard[index]的過程。
new UiccCard(mContext, mCis[index], status, index);
->update(c, ci, ics);
-->createAndUpdateCatService(); // CatService 應該是在這裡建立的。
update方法裡最複雜的邏輯應該是下面這段代碼
//update applications
if (DBG) log(ics.mApplications.length + " applications");
for ( int i = 0; i < mUiccApplications.length; i++) {//根據卡應用的**最大**長度來周遊
if (mUiccApplications[i] == null) {//mUiccApplications需要通過ics來獲得
//Create newly added Applications
if (i < ics.mApplications.length) {//ics來獲得卡應用沒有那麼多就不會建立了
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);
}
}
到了UiccCardApplication這以後又會分成兩路new & update,看代碼其實構造方法和update方法沒差的特别多。
new:
mUiccApplications[i] = new UiccCardApplication(this,
ics.mApplications[i], mContext, mCi);
->mIccFh = createIccFileHandler(as.app_type);//根據app type建立檔案處理類
mIccRecords = createIccRecords(as.app_type, mContext, mCi);//建立IccRecord
if (mAppState == AppState.APPSTATE_READY) {
queryFdn();
queryPin1State();//這兩個函數查完之後就把狀态更新到本地
}
update:
mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);//沒多大差別,邏輯簡單
->notifyReadyRegistrantsIfNeeded(null);//這句代碼會引起識卡。
看一下識卡的具體過程。
假如執行個體化SIMRecord
SIMRecords
protected IccFileHandler mFh;
protected UiccCardApplication mParentApp;
protected int mRecordsToLoad; // number of pending load request
// recordsRequested is set to false indicating that the SIM
// read requests made so far are not valid. This is set to
// true only when fresh set of read requests are made.
protected boolean mRecordsRequested = false; // true if we've made requests for the sim records
protected String mIccId;
SIMRecords 構造函數更新了成員變量
mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);
mCi.registerForIccRefresh(this, EVENT_SIM_REFRESH, null);
// Start off by setting empty state
resetRecords(); // 重置屬性 mIccId = null; mRecordsRequested = false;
mParentApp.registerForReady(this, EVENT_APP_READY, null);
mParentApp.registerForLocked(this, EVENT_APP_LOCKED, null);
EVENT_APP_READY -> onReady() -> fetchSimRecords()
mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));
mRecordsToLoad++;
mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
mRecordsToLoad++;
...
向RIL請求一些 IMSI ICCID ... , 每加一個請求 mRecordsToLoad++
每次消息回來 handleMessage(Message msg) 中都會 boolean isRecordLoadResponse = false;
在具體的 case 中會将 isRecordLoadResponse = true;
最後在 finally 中 if (isRecordLoadResponse) { onRecordLoaded(); }
onRecordLoaded() if (mRecordsToLoad == 0 && mRecordsRequested == true) {onAllRecordsLoaded();}
onAllRecordsLoaded() 更新一些東西,然後會發一消息
mRecordsLoadedRegistrants.notifyRegistrants(
new AsyncResult(null, null, null));
IccCardProxy監聽了這條消息
mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
->onRecordsLoaded()
->broadcastInternalIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
-->Intent intent = new Intent(ACTION_INTERNAL_SIM_STATE_CHANGED);
ActivityManagerNative.broadcastStickyIntent(intent, null, UserHandle.USER_ALL);
接收這條廣播類是SubscriptionInfoUpdater
OnReceive -> sendMessage(obtainMessage(EVENT_SIM_LOADED, slotId, -1));
->handleSimLoaded(msg.arg1);
->updateSubscriptionInfoByIccId()//這個方法相當的複雜,我們還是隻貼影響卡識别的關鍵代碼
->mSubscriptionManager.addSubscriptionInfoRecord(mIccId[i], i);
->iSub.addSubInfoRecord(iccId, slotId);
SubscriptionController
->addSubInfoRecord // 這個方法也超級長,說一下邏輯
如果這張卡之前沒有被存到資料庫
value.put(SubscriptionManager.ICC_ID, iccId);
// default SIM color differs between slots
value.put(SubscriptionManager.COLOR, color);
value.put(SubscriptionManager.SIM_SLOT_INDEX, slotId);
value.put(SubscriptionManager.CARRIER_NAME, "");
Uri uri = resolver.insert(SubscriptionManager.CONTENT_URI, value);//卡的資訊更新到資料庫
public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo");
如果已經存過了就更新一下就好,slotId...
// FIXME: Currently we assume phoneId == slotId which in the future
// may not be true, for instance with multiple subs per slot.
// But is true at the moment.
這個也比較重要sSlotIdxToSubId.put(slotId, subId);
擷取目前插入卡的接口為List<SubscriptionInfo> getActiveSubscriptionInfoList
List<SubscriptionInfo> subList = getSubInfo(
SubscriptionManager.SIM_SLOT_INDEX + ">=0", null);
->Cursor cursor = mContext.getContentResolver().query(SubscriptionManager.CONTENT_URI,
null, selection, selectionArgs, null);
while (cursor.moveToNext())
SubscriptionInfo subInfo = getSubInfoRecord(cursor);
subList.add(subInfo);
卡的資訊是從資料庫取的。