国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android4.X中SIM卡信息初始化過程詳解

2020-04-11 11:20:40
字體:
來源:轉載
供稿:網友

本文實例講述了Android4.X中SIM卡信息初始化過程詳解。分享給大家供大家參考,具體如下:

Phone 對象初始化的過程中,會加載SIM卡的部分數據信息,這些信息會保存在IccRecords 和 AdnRecordCache 中。SIM卡的數據信息的初始化過程主要分為如下幾個步驟

1.RIL 和 UiccController 建立監聽關系 ,SIM卡狀態發生變化時,UiccController 第一個去處理。

Phone 應用初始化 Phone 對象時會建立一個 RIL 和UiccController 的監聽關系:UiccController 監聽 RIL,相關代碼如下

sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);   UiccController.make(context, sCommandsInterface);UiccController 構造的過程private UiccController(Context c, CommandsInterface ci) { if (DBG) log("Creating UiccController"); mContext = c; mCi = ci; mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); // TODO remove this once modem correctly notifies the unsols mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);}

從代碼中可以看出,UiccController 對象被注冊為RIL對象的監聽者,當 RIL 檢測到 uicc card 狀態發生變化或者 radio on UiccController 都會處理對應的數據變化。UiccController 是 SIM卡狀態發生變化后的第一個處理者。

UiccController 處理 EVENT_ICC_STATUS_CHANGED

public void handleMessage (Message msg) {  synchronized (mLock) {  switch (msg.what) {   case EVENT_ICC_STATUS_CHANGED:   if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus");   mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE));   break;   case EVENT_GET_ICC_STATUS_DONE:   if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE");   AsyncResult ar = (AsyncResult)msg.obj;   onGetIccCardStatusDone(ar);   break;   default:   Rlog.e(LOG_TAG, " Unknown Event " + msg.what);  }  }}

從代碼中可以看出,RIL 上報 SIM卡狀態發生變化后,做了兩件事,一是獲取SIM卡的具體狀態,二是處理這個狀態。

UiccController 處理具體的SIM卡狀態

private synchronized void onGetIccCardStatusDone(AsyncResult ar) {  if (ar.exception != null) {  Rlog.e(LOG_TAG,"Error getting ICC status. "   + "RIL_REQUEST_GET_ICC_STATUS should "   + "never return an error", ar.exception);  return;  }  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();}

從代碼中可以看出,做了兩件事,
一是 創建或者 更新 UiccCard
二是 通知監聽 UiccController 的監聽者。

2.創建或者更新 UiccCard,UiccCard 創建或者更新與SIM卡類型對應的UiccCardApplication.

一個UiccCard 對象代表著一張SIM卡,UiccCard 根據獲取的SIM卡信息創建 UiccCardApplication,UiccCardApplication去讀取具體的SIM卡里的信息。

更新UiccCard

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;  }}

IccCardStatus,記錄了RIL 讀取的SIM卡的信息,UiccCard 根據 IccCardStatus 中記錄的應用程序信息,創建 UiccCardApplication.

UiccCard 還創建了 CatService,用于讀取 STK 的信息。

創建或者更新 UiccCardApplication

UiccCardApplication,會記錄對應的卡的狀態,類型,以及卡的記錄信息。

//創建 UiccCardApplicationUiccCardApplication(UiccCard uiccCard,    IccCardApplicationStatus as,    Context c,    CommandsInterface ci) {  if (DBG) log("Creating UiccApp: " + as);  mUiccCard = uiccCard;  mAppState = as.app_state;  mAppType = as.app_type;  mPersoSubState = as.perso_substate;  mAid = as.aid;  mAppLabel = as.app_label;  mPin1Replaced = (as.pin1_replaced != 0);  mPin1State = as.pin1;  mPin2State = as.pin2;  mContext = c;  mCi = ci;  mIccFh = createIccFileHandler(as.app_type);  mIccRecords = createIccRecords(as.app_type, mContext, mCi);  ///讀取 SIM卡上的 EF 文件信息  if (mAppState == AppState.APPSTATE_READY) {  queryFdn(); // FDN 信息  queryPin1State(); // Pin State  } } //更新UiccCardApplication void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) {  synchronized (mLock) {  if (mDestroyed) {   loge("Application updated after destroyed! Fix me!");   return;  }  if (DBG) log(mAppType + " update. New " + as);  mContext = c;  mCi = ci;  AppType oldAppType = mAppType;  AppState oldAppState = mAppState;  PersoSubState oldPersoSubState = mPersoSubState;  mAppType = as.app_type;  mAppState = as.app_state;  mPersoSubState = as.perso_substate;  mAid = as.aid;  mAppLabel = as.app_label;  mPin1Replaced = (as.pin1_replaced != 0);  mPin1State = as.pin1;  mPin2State = as.pin2;  if (mAppType != oldAppType) {   if (mIccFh != null) { mIccFh.dispose();}   if (mIccRecords != null) { mIccRecords.dispose();}   mIccFh = createIccFileHandler(as.app_type);   mIccRecords = createIccRecords(as.app_type, c, ci);  }  if (mPersoSubState != oldPersoSubState &&   mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) {   notifyNetworkLockedRegistrantsIfNeeded(null);  }  if (mAppState != oldAppState) {   if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState);   // If the app state turns to APPSTATE_READY, then query FDN status,   //as it might have failed in earlier attempt.   if (mAppState == AppState.APPSTATE_READY) {   queryFdn();// FDN 信息   queryPin1State();   }   notifyPinLockedRegistrantsIfNeeded(null);   notifyReadyRegistrantsIfNeeded(null);  }  }}

在更新和創建UiccCardApplication的過程中,有如下幾個重要的變量

IccRecords
記錄 SIM卡上的EF 文件信息,實現類有SIMRecords,RuimRecords,IsimUiccRecords,對應于不同的類型的SIM卡。

IccFileHandler
根據SIM卡的類型,去讀取SIM卡上的信息,實現類有SIMFileHandler,RuimFileHandler,UsimFileHandler,CsimFileHandler,IsimFileHandler,對應于不同的SIM卡。

創建 IccRecords 對象

正如前面所描述的,IccRecords 記錄SIM卡的EF文件信息,具體的讀取SIM卡EF文件信息的過程是由 IccFileHandler 來實現的,以 SIMRecords 為例。

public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) {  super(app, c, ci);  // 1.電話本的緩存  mAdnCache = new AdnRecordCache(mFh);  mVmConfig = new VoiceMailConstants();  mSpnOverride = new SpnOverride();  mRecordsRequested = false; // No load request is made till SIM ready  // recordsToLoad is set to 0 because no requests are made yet  mRecordsToLoad = 0;  mCi.setOnSmsOnSim(this, EVENT_SMS_ON_SIM, null);  mCi.registerForIccRefresh(this, EVENT_SIM_REFRESH, null);  // Start off by setting empty state  resetRecords();  //2. 讀取 SIM卡的所有重要的記錄信息  mParentApp.registerForReady(this, EVENT_APP_READY, null);  if (DBG) log("SIMRecords X ctor this=" + this);}

這個過程包含兩個重要的步驟

創建AdnRecordCache,用于保存電話本數據,根據EF的ID,可以分別讀取SIM卡和USIM卡的電話本數據。AdnRecordCache 中持有一個UsimPhoneBookManager,它就是用來讀取USIM卡電話本數據的。GSM的SIM卡和WCDMA的USIM卡都是對應的 SimRecords.
讀取SIM卡的所有重要記錄信息,在fetchSimRecords 方法中實現。

protected void fetchSimRecords() {  mRecordsRequested = true;  if (DBG) log("fetchSimRecords " + mRecordsToLoad);  mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));  mRecordsToLoad++;  mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));  mRecordsToLoad++;  // FIXME should examine EF[MSISDN]'s capability configuration  // to determine which is the voice/data/fax line  new AdnRecordLoader(mFh).loadFromEF(EF_MSISDN, EF_EXT1, 1,   obtainMessage(EVENT_GET_MSISDN_DONE));  mRecordsToLoad++;  // Record number is subscriber profile  mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE));  mRecordsToLoad++;  mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));  mRecordsToLoad++;  // Record number is subscriber profile  mFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE));  mRecordsToLoad++;  // Also load CPHS-style voice mail indicator, which stores  // the same info as EF[MWIS]. If both exist, both are updated  // but the EF[MWIS] data is preferred  // Please note this must be loaded after EF[MWIS]  mFh.loadEFTransparent(   EF_VOICE_MAIL_INDICATOR_CPHS,   obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE));  mRecordsToLoad++;  // Same goes for Call Forward Status indicator: fetch both  // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred.  mFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE));  mRecordsToLoad++;  mFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE));  mRecordsToLoad++;  getSpnFsm(true, null);  mFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE));  mRecordsToLoad++;  mFh.loadEFLinearFixed(EF_PNN, 1, obtainMessage(EVENT_GET_PNN_DONE));  mRecordsToLoad++;  mFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE));  mRecordsToLoad++;  mFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE));  mRecordsToLoad++;  mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE));  mRecordsToLoad++;  mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE));  mRecordsToLoad++;  // XXX should seek instead of examining them all  if (false) { // XXX  mFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE));  mRecordsToLoad++;  }  if (CRASH_RIL) {  String sms = "0107912160130310f20404d0110041007030208054832b0120"    + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"    + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"    + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"    + "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"    + "ffffffffffffffffffffffffffffff";  byte[] ba = IccUtils.hexStringToBytes(sms);  mFh.updateEFLinearFixed(EF_SMS, 1, ba, null,    obtainMessage(EVENT_MARK_SMS_READ_DONE, 1));  }  if (DBG) log("fetchSimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested);}

總的來說,創建 SimRecords 的過程就是讀取并且保存SIM卡重要信息的過程。其中,電話本的信息保存在 mAdnCache 中,其他信息保存在 SimRecords 中,但是在Phone對象完成初始化后,mAdnCache 里是空的,也就是說,在IccRecords 初始化的過程中,AdnRecordCache 并沒有主動去請求SIM卡聯系人的數據。

所有的IccRecords 是通過 IccFileHandler 向Modem 發命令讀取數據的。他們之間的交互圖如下

3.通知UiccController 的監聽者,與UiccCardApplication的相關信息可以更新了。根據分析源代碼,我們可以看到,PhoneBase ,ServiceStateTracker,IccCardProxy,DcTrackerBase,這些類是 UiccController 的監聽者。他們都會處理UiccController 的變化。我們可以這么理解,這些類是SIM卡狀態發生變化后,第二批處理SIM卡狀態變化的實體。第一個處理SIM卡狀態變化的是 UiccController.

希望本文所述對大家Android程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 饶河县| 依安县| 黑河市| 马鞍山市| 四子王旗| 莱西市| 海晏县| 东兴市| 抚顺市| 修水县| 天长市| 西华县| 阿拉善右旗| 南京市| 博罗县| 中西区| 东宁县| 东宁县| 滨海县| 木兰县| 丽江市| 嘉荫县| 望江县| 天祝| 华阴市| 梅州市| 新泰市| 惠水县| 昌黎县| 黎城县| 秭归县| 丹棱县| 长武县| 扎赉特旗| 高唐县| 邵东县| 武陟县| 全州县| 重庆市| 济宁市| 普兰店市|