Android(M) Telephony Framework SIM card recognization flow

1.RIL从modem收到主动上报的消息
RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED
2.UiccController监听了这条消息,mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
===========================UICC框架结构=================================
/**
 * This class is responsible for keeping all knowledge about
 * Universal Integrated Circuit Card (UICC), also know as SIM's,
 * in the system. It is also used as API to get appropriate
 * applications to pass them to phone and service trackers.
 *
 * UiccController is created with the call to make() function.
 * UiccController is a singleton and make() must only be called once
 * and throws an exception if called multiple times.
 *
 * Once created UiccController registers with RIL for "on" and "unsol_sim_status_changed"
 * notifications. When such notification arrives UiccController will call
 * getIccCardStatus (GET_SIM_STATUS). Based on the response of GET_SIM_STATUS
 * request appropriate tree of uicc objects will be created.
 *
 * Following is class diagram for uicc classes:
 *
 *                       UiccController
 *                            #
 *                            |
 *                        UiccCard
 *                          #   #
 *                          |   ------------------
 *                    UiccCardApplication    CatService
 *                      #            #
 *                      |            |
 *                 IccRecords    IccFileHandler
 *                 ^ ^ ^           ^ ^ ^ ^ ^
 *    SIMRecords---- | |           | | | | ---SIMFileHandler
 *    RuimRecords----- |           | | | ----RuimFileHandler
 *    IsimUiccRecords---           | | -----UsimFileHandler
 *                                 | ------CsimFileHandler
 *                                 ----IsimFileHandler
 *
 * Legend: # stands for Composition
 *         ^ stands for Generalization
 *
 * See also {@link com.android.internal.telephony.IccCard}
 * and {@link com.android.internal.telephony.uicc.IccCardProxy}
 */
===========================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 getActiveSubscriptionInfoList
List 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);
卡的信息是从数据库取的。























你可能感兴趣的:(Telephony)