本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉。
本文主要介绍MTK Android开机时,SIM卡的Framework部分初始化过程。
先看一段注释:
- /* 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
- */
这是UiccController.Java文件开头对UiccController的注释,意思很明显UiccController是对Android SIM卡管理的控制器。
下面是SIM卡初始化序列图:
UiccController的初始化是在phone进程启动的时候,PhoneFactory调用makeDefaultPhone()创建默认的Phone,然后走MTK双卡流程中,调用MTKPhoneFactory.makeDefaultPhone()创建的,
- {
- for (int l2 = 0; l2 < PhoneConstants.GEMINI_SIM_NUM; l2++)
- if (j1 == l2)
- ai[l2] = j;
- else
- ai[l2] = 1;
- I = new RIL(context, ai[0], l, 0);
- J = new RIL(context, ai[1], l, 1);
- }
- UiccController.make(context, I, 0);
- UiccController.make(context, J, 1);
- GSMPhone agsmphone[] = new GSMPhone[PhoneConstants.GEMINI_SIM_NUM];
上面是反编译MTK的static_gemini_intermediates库看到的,在RIL创建完成时,使用UiccController.make()初始化:
- public static UiccController make(Context c, CommandsInterface ci, int simId) {
- synchronized (mLock) {
- if (FeatureOption.MTK_GEMINI_SUPPORT) {
- if(mInstance[simId] != null) {
- throw new RuntimeException("UiccController.make() should only be called once");
- }
- mInstance[simId] = new UiccController(c, ci, simId);
- return mInstance[simId];
- } else {
- if (mInstance[0] != null) {
- throw new RuntimeException("UiccController.make() should only be called once");
- }
- mInstance[0] = new UiccController(c, ci);
- return mInstance[0];
- }
- }
- }
UiccController的创建使用了单例模式,使用时调用getInstance()获取,
- public static UiccController getInstance(int simId) {
- synchronized (mLock) {
- if (FeatureOption.MTK_GEMINI_SUPPORT) {
- if(mInstance[simId] == null) {
- throw new RuntimeException(
- "UiccController.getInstance can't be called before make()");
- }
- return mInstance[simId];
- } else {
- if (mInstance[0] == null) {
- throw new RuntimeException(
- "UiccController.getInstance can't be called before make()");
- }
- return mInstance[0];
- }
- }
- }
- private UiccController(Context c, CommandsInterface ci, int simId) {
- if (DBG) log("Creating UiccController simId " + simId);
- mContext = c;
- mCi = ci;
- mSimId = simId;
- 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);
- mCi.registerForVirtualSimOn(this, EVENT_VIRTUAL_SIM_ON, null);
- mCi.registerForVirtualSimOff(this, EVENT_VIRTUAL_SIM_OFF, null);
- mCi.registerForSimMissing(this, EVENT_SIM_MISSING, null);
- mCi.registerForSimRecovery(this, EVENT_SIM_RECOVERY, null);
- mCi.registerForSimPlugOut(this, EVENT_SIM_PLUG_OUT, null);
- mCi.registerForSimPlugIn(this, EVENT_SIM_PLUG_IN, null);
- mCi.registerForInvalidSimDetected(this, EVENT_INVALID_SIM_DETECTED, null);
- IntentFilter filter = new IntentFilter();
- filter.addAction("android.intent.action.ACTION_SHUTDOWN_IPO");
- filter.addAction(GeminiPhone.EVENT_INITIALIZATION_FRAMEWORK_DONE);
- filter.addAction(TelephonyIntents.ACTION_SIM_INFO_UPDATE);
- filter.addAction(ACTION_RESET_MODEM);
- mContext.registerReceiver(mIntentReceiver, filter);
- }
下面开始解析上面序列图:
step1,rild主动上报射频信号状态RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED。
step4,对信号进行判断,看看返回当前射频状态:
- private RadioState getRadioStateFromInt(int stateInt) {
- RadioState state;
- /* RIL_RadioState ril.h */
- switch(stateInt) {
- case 0: state = RadioState.RADIO_OFF; break;
- case 1: state = RadioState.RADIO_UNAVAILABLE; break;
- case 2: state = RadioState.SIM_NOT_READY; break;
- case 3: state = RadioState.SIM_LOCKED_OR_ABSENT; break;
- case 4: state = RadioState.SIM_READY; break;
- case 5: state = RadioState.RUIM_NOT_READY; break;
- case 6: state = RadioState.RUIM_READY; break;
- case 7: state = RadioState.RUIM_LOCKED_OR_ABSENT; break;
- case 8: state = RadioState.NV_NOT_READY; break;
- case 9: state = RadioState.NV_READY; break;
- case 10: state = RadioState.RADIO_ON; break;
- case 15: state = RadioState.RADIO_OFF; break;
- default:
- throw new RuntimeException(
- "Unrecognized RIL_RadioState: " + stateInt);
- }
- return state;
- }
一般刚开机射频是RADIO_OFF的,之后转为RADIO_ON。
step6,设置射频的新状态,比较新状态和旧状态对比,看看发生了什么变化,step9~step13(还有其他的,没有列出)对变化作出响应,具体看下面的源码:
- /**
- * Store new RadioState and send notification based on the changes
- *
- * This function is called only by RIL.java when receiving unsolicited
- * RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
- *
- * RadioState has 5 values : RADIO_OFF, RADIO_UNAVAILABLE, SIM_NOT_READY,
- * SIM_LOCKED_OR_ABSENT, and SIM_READY.
- *
- * @param newState new RadioState decoded from RIL_UNSOL_RADIO_STATE_CHANGED
- */
- protected void setRadioState(RadioState newState) {
- RadioState oldState;
- synchronized (mStateMonitor) {
- Rlog.v(LOG_TAG, "setRadioState old: " + mState + " new " + newState);
- oldState = mState;
- mState = newState;
- // For CTA feature, sim1 is radio on if no sim card inserted.
- // In rild, it is in the state of SIM_LOCKED_OR_ABSENT.
- // if the sim card is pin locked, then after turn on radio of sim, it still the state of SIM_LOCKED_OR_ABSENT
- // special handle for this scenario, always notify radio changed if the state is SIM_LOCKED_OR_ABSENT
- if (oldState == mState && mState != RadioState.SIM_LOCKED_OR_ABSENT) {
- // no state transition
- return;
- }
- // FIXME: Use Constants or Enums
- if(mState.getType() == 0) {
- mSimState = mState;
- mRuimState = mState;
- mNvState = mState;
- }
- else if (mState.getType() == 1) {
- if(mSimState != mState) {
- mIccStatusChangedRegistrants.notifyRegistrants();
- }
- mSimState = mState;
- }
- else if (mState.getType() == 2) {
- if(mRuimState != mState) {
- mIccStatusChangedRegistrants.notifyRegistrants();
- }
- mRuimState = mState;
- }
- else if (mState.getType() == 3) {
- mNvState = mState;
- }
- mRadioStateChangedRegistrants.notifyRegistrants(new AsyncResult(null, mState, null));
- if (mState.isAvailable() && !oldState.isAvailable()) {
- Rlog.d(LOG_TAG,"Notifying: radio available");
- mAvailRegistrants.notifyRegistrants();
- onRadioAvailable();
- }
- if (!mState.isAvailable() && oldState.isAvailable()) {
- Rlog.d(LOG_TAG,"Notifying: radio not available");
- mNotAvailRegistrants.notifyRegistrants();
- }
- if (mState.isOn() && !oldState.isOn()) {
- Rlog.d(LOG_TAG,"Notifying: Radio On");
- mOnRegistrants.notifyRegistrants();
- }
- if ((!mState.isOn() || !mState.isAvailable())
- && !((!oldState.isOn() || !oldState.isAvailable()))
- ) {
- Rlog.d(LOG_TAG,"Notifying: radio off or not available");
- mOffOrNotAvailRegistrants.notifyRegistrants();
- }
- /* Radio Technology Change events
- * NOTE: isGsm and isCdma have no common states in RADIO_OFF or RADIO_UNAVAILABLE; the
- * current phone is determined by mPhoneType
- * NOTE: at startup no phone have been created and the RIL determines the mPhoneType
- * looking based on the networkMode set by the PhoneFactory in the constructor
- */
- if (mState.isGsm() && oldState.isCdma()) {
- Rlog.d(LOG_TAG,"Notifying: radio technology change CDMA to GSM");
- mVoiceRadioTechChangedRegistrants.notifyRegistrants();
- }
- if (mState.isGsm() && !oldState.isOn() && (mPhoneType == PhoneConstants.PHONE_TYPE_CDMA)) {
- Rlog.d(LOG_TAG,"Notifying: radio technology change CDMA OFF to GSM");
- mVoiceRadioTechChangedRegistrants.notifyRegistrants();
- }
- if (mState.isCdma() && oldState.isGsm()) {
- Rlog.d(LOG_TAG,"Notifying: radio technology change GSM to CDMA");
- mVoiceRadioTechChangedRegistrants.notifyRegistrants();
- }
- if (mState.isCdma() && !oldState.isOn() && (mPhoneType == PhoneConstants.PHONE_TYPE_GSM)) {
- Rlog.d(LOG_TAG,"Notifying: radio technology change GSM OFF to CDMA");
- mVoiceRadioTechChangedRegistrants.notifyRegistrants();
- }
- }
- }
step7,通知注册了 mIccStatusChangedRegistrants的观察者,SIM卡(GSM卡和USIM卡)状态改变了,SIM卡准备好了。UiccController注册了它,看前面UiccController的构造函数,这里EVENT_ICC_STATUS_CHANGED关联了两个RIL URC事件,除了这里说的这个,还有 RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED 。所以,当Radio或者SIM卡状态发生变化时,都会第一时间通知 UiccController。
step8,对它感兴趣的有,GsmServiceStateTracker(更新网络状态)、SIMRecords(用IccFileHandler读取SIM卡内置紧急号码)和SIMRecordsEx(向RILD查询20位的Iccid)。
step14,处理step7中mIccStatusChangedRegistrants发出的通知。
step15~step16,请求查询现在SIM卡的状态,请求id位RIL_REQUEST_GET_SIM_STATUS。
step17~step20,Rild反馈RIL_REQUEST_GET_SIM_STATUS请求。step19,responseIccCardStatus()方法中会对SIM卡状态进行解析:
- private Object
- responseIccCardStatus(Parcel p) {
- IccCardApplicationStatus appStatus;
- IccCardStatus cardStatus = new IccCardStatus();
- cardStatus.setCardState(p.readInt());
- cardStatus.setUniversalPinState(p.readInt());
- cardStatus.mGsmUmtsSubscriptionAppIndex = p.readInt();
- cardStatus.mCdmaSubscriptionAppIndex = p.readInt();
- cardStatus.mImsSubscriptionAppIndex = p.readInt();
- int numApplications = p.readInt();
- // limit to maximum allowed applications
- if (numApplications > IccCardStatus.CARD_MAX_APPS) {
- numApplications = IccCardStatus.CARD_MAX_APPS;
- }
- cardStatus.mApplications = new IccCardApplicationStatus[numApplications];
- for (int i = 0 ; i < numApplications ; i++) {
- appStatus = new IccCardApplicationStatus();
- appStatus.app_type = appStatus.AppTypeFromRILInt(p.readInt());
- appStatus.app_state = appStatus.AppStateFromRILInt(p.readInt());
- appStatus.perso_substate = appStatus.PersoSubstateFromRILInt(p.readInt());
- appStatus.aid = p.readString();
- appStatus.app_label = p.readString();
- appStatus.pin1_replaced = p.readInt();
- appStatus.pin1 = appStatus.PinStateFromRILInt(p.readInt());
- appStatus.pin2 = appStatus.PinStateFromRILInt(p.readInt());
- cardStatus.mApplications[i] = appStatus;
- }
- return cardStatus;
- }
step21,onGetIccCardStatusDone()中更新SIM卡状态mUiccCard.update(),如果第一次运行,mUiccCard对象还没有创建,则先创建,再更新。
- private synchronized void onGetIccCardStatusDone(AsyncResult ar, boolean isUpdateSiminfo) {
- if (ar.exception != null) {
- Rlog.e(LOG_TAG,"[SIM " + mSimId + "] Error getting ICC status. "
- + "RIL_REQUEST_GET_ICC_STATUS should "
- + "never return an error", ar.exception);
- return;
- }
- IccCardStatus status = (IccCardStatus)ar.result;
- if (status.mCardState == IccCardStatus.CardState.CARDSTATE_PRESENT) {
- if (DBG) log("onGetIccCardStatusDone, disableSimMissingNotification because card is present");
- disableSimMissingNotification();
- }
- if (mUiccCard == null) {
- //Create new card
- //ALPS01311133: We also need to update SIM Info when SIM hot plug.
- mUiccCard = new UiccCard(mContext, mCi, status, mSimId, isUpdateSiminfo);
- } else {
- //Update already existing card
- mUiccCard.update(mContext, mCi , status, isUpdateSiminfo);
- }
- if (DBG) log("Notifying IccChangedRegistrants, isUpdateSiminfo:" + isUpdateSiminfo);
- mIccChangedRegistrants.notifyRegistrants();
- }
step23,更新时,如果 UiccCardApplication还没有创建,则先创建,同时需要根据SIM类型创建IccFileHandler具体子类对象(用来读取SIM数据)和IccRecords具体子类对象(记录SIM数据),否则直接更新。
- public void update(Context c, CommandsInterface ci, IccCardStatus ics, boolean isUpdateSimInfo) {
- 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);
- mIccRecords = mUiccApplications[i].getIccRecords();
- mIccFileHandler = mUiccApplications[i].getIccFileHandler();
- }
- } else if (i >= ics.mApplications.length) {
- //Delete removed applications
- if (DBG) log("update mUiccApplications[" + i + "] dispose");
- mUiccApplications[i].dispose();
- mUiccApplications[i] = null;
- } else {
- //Update the rest
- if (DBG) log("update mUiccApplications[" + i + "] update");
- mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
- }
- }
- //if (!mIccRecordsList.isEmpty()){
- // for (IccRecords mIccRecords: mIccRecordsList)
- if (mIccRecords != null)
- mIccRecords.registerForImsiReady(mHandler, EVENT_IMSI_READY, null);
- if (DBG) log("update mUiccApplications.length: " + mUiccApplications.length);
- 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);
- if(isUpdateSimInfo) { //SIM卡热插拔会用到这里
- // No notifications while radio is off or we just powering up
- //if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
- if (radioState != RadioState.RADIO_UNAVAILABLE) {
- if (mCardState == CardState.CARDSTATE_ABSENT) {
- if (DBG) log("update: notify card removed");
- mAbsentRegistrants.notifyRegistrants();
- mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
- //Update SIM inserted state
- if (FeatureOption.MTK_GEMINI_SUPPORT) {
- Phone defaultPhone = PhoneFactory.getDefaultPhone();
- ((GeminiPhone)defaultPhone).setSimInsertedState(getMySimId(), false);
- }
- } 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;
- }
- }
- 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();//查询pin状态
- }
- notifyPinLockedRegistrantsIfNeeded(null);
- notifyReadyRegistrantsIfNeeded(null);
- }
step31,通知去读取SIM卡的IMSI。
step32,创建SIM Toolkit Telephony Service。
step33,通知所有关注mIccChangedRegistrants变化的观察者,如IccCardProxy(代理各种类型的SIM卡)、ServiceStateTracker。这里说一下ServiceStateTracker收到mIccChangedRegistrants变化通知后做的事件:
- case EVENT_ICC_CHANGED:
- onUpdateIccAvailability();
- break;
onUpdateIccAvailability()方法是在 ServiceStateTracker中定义,在其子类中实现的,我们看看GsmServiceStateTracker中的实现:
- @Override
- 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 = mUiccApplcation.getIccRecords();//When the app state turns to APPSTATE_READY
- mUiccApplcation.registerForReady(this, EVENT_SIM_READY, null);//sim卡联系人读取后发出
接下来还有很多状态变化,各种状态变化太复杂了,先说到这吧。。。