Android 4.4Telephony流程分析SIM卡开机时的初始化

本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉。

本文主要介绍MTK Android开机时,SIM卡的Framework部分初始化过程。

先看一段注释:

01. /* Once created UiccController registers with RIL for "on" and "unsol_sim_status_changed"
02. * notifications. When such notification arrives UiccController will call
03. * getIccCardStatus (GET_SIM_STATUS). Based on the response of GET_SIM_STATUS
04. * request appropriate tree of uicc objects will be created.
05. *
06. * Following is class diagram for uicc classes:
07. *
08. *                       UiccController
09. *                            #
10. *                            |
11. *                        UiccCard
12. *                          #   #
13. *                          |   ------------------
14. *                    UiccCardApplication    CatService
15. *                      #            #
16. *                      |            |
17. *                 IccRecords    IccFileHandler
18. *                 ^ ^ ^           ^ ^ ^ ^ ^
19. *    SIMRecords---- | |           | | | | ---SIMFileHandler
20. *    RuimRecords----- |           | | | ----RuimFileHandler
21. *    IsimUiccRecords---           | | -----UsimFileHandler
22. *                                 | ------CsimFileHandler
23. *                                 ----IsimFileHandler
24. *
25. * Legend: # stands for Composition
26. *         ^ stands for Generalization
27. */

这是UiccController.java文件开头对UiccController的注释,意思很明显UiccController是对Android SIM卡管理的控制器。

下面是SIM卡初始化序列图:

\

UiccController的初始化是在phone进程启动的时候,PhoneFactory调用makeDefaultPhone()创建默认的Phone,然后走MTK双卡流程中,调用MTKPhoneFactory.makeDefaultPhone()创建的,

01. {
02. for (int l2 = 0; l2 < PhoneConstants.GEMINI_SIM_NUM; l2++)
03. if (j1 == l2)
04. ai[l2] = j;
05. else
06. ai[l2] = 1;
07.  
08. I = new RIL(context, ai[0], l, 0);
09. J = new RIL(context, ai[1], l, 1);
10. }
11. UiccController.make(context, I, 0);
12. UiccController.make(context, J, 1);
13. GSMPhone agsmphone[] = new GSMPhone[PhoneConstants.GEMINI_SIM_NUM];

上面是反编译MTK的static_gemini_intermediates库看到的,在RIL创建完成时,使用UiccController.make()初始化:

01. public static UiccController make(Context c, CommandsInterface ci, int simId) {
02. synchronized (mLock) {
03. if (FeatureOption.MTK_GEMINI_SUPPORT) {
04. if(mInstance[simId] != null) {
05. throw new RuntimeException("UiccController.make() should only be called once");
06. }
07. mInstance[simId] = new UiccController(c, ci, simId);
08. return mInstance[simId];
09. else {
10. if (mInstance[0] != null) {
11. throw new RuntimeException("UiccController.make() should only be called once");
12. }
13. mInstance[0] = new UiccController(c, ci);
14. return mInstance[0];
15. }
16. }
17. }

UiccController的创建使用了单例模式,使用时调用getInstance()获取,

01. public static UiccController getInstance(int simId) {
02. synchronized (mLock) {
03. if (FeatureOption.MTK_GEMINI_SUPPORT) {
04. if(mInstance[simId] == null) {
05. throw new RuntimeException(
06. "UiccController.getInstance can't be called before make()");
07. }
08. return mInstance[simId];
09. else {
10. if (mInstance[0] == null) {
11. throw new RuntimeException(
12. "UiccController.getInstance can't be called before make()");
13. }
14. return mInstance[0];
15. }
16. }
17. }
18.  
19. private UiccController(Context c, CommandsInterface ci, int simId) {
20. if (DBG) log("Creating UiccController simId " + simId);
21. mContext = c;
22. mCi = ci;
23. mSimId = simId;
24. mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null);
25. // TODO remove this once modem correctly notifies the unsols
26. mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null);
27. mCi.registerForVirtualSimOn(this, EVENT_VIRTUAL_SIM_ON, null);
28. mCi.registerForVirtualSimOff(this, EVENT_VIRTUAL_SIM_OFF, null);
29. mCi.registerForSimMissing(this, EVENT_SIM_MISSING, null);
30. mCi.registerForSimRecovery(this, EVENT_SIM_RECOVERY, null);
31. mCi.registerForSimPlugOut(this, EVENT_SIM_PLUG_OUT, null);
32. mCi.registerForSimPlugIn(this, EVENT_SIM_PLUG_IN, null);
33. mCi.registerForInvalidSimDetected(this, EVENT_INVALID_SIM_DETECTED, null);
34.  
35. IntentFilter filter = new IntentFilter();
36. filter.addAction("android.intent.action.ACTION_SHUTDOWN_IPO");
37. filter.addAction(GeminiPhone.EVENT_INITIALIZATION_FRAMEWORK_DONE);
38. filter.addAction(TelephonyIntents.ACTION_SIM_INFO_UPDATE);
39. filter.addAction(ACTION_RESET_MODEM);
40. mContext.registerReceiver(mIntentReceiver, filter);
41. }

下面开始解析上面序列图:

step1,rild主动上报射频信号状态RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED。

step4,对信号进行判断,看看返回当前射频状态:

01. private RadioState getRadioStateFromInt(int stateInt) {
02. RadioState state;
03.  
04. /* RIL_RadioState ril.h */
05. switch(stateInt) {
06. case 0: state = RadioState.RADIO_OFF; break;
07. case 1: state = RadioState.RADIO_UNAVAILABLE; break;
08. case 2: state = RadioState.SIM_NOT_READY; break;
09. case 3: state = RadioState.SIM_LOCKED_OR_ABSENT; break;
10. case 4: state = RadioState.SIM_READY; break;
11. case 5: state = RadioState.RUIM_NOT_READY; break;
12. case 6: state = RadioState.RUIM_READY; break;
13. case 7: state = RadioState.RUIM_LOCKED_OR_ABSENT; break;
14. case 8: state = RadioState.NV_NOT_READY; break;
15. case 9: state = RadioState.NV_READY; break;
16. case 10: state = RadioState.RADIO_ON; break;
17. case 15: state = RadioState.RADIO_OFF; break;
18.  
19. default:
20. throw new RuntimeException(
21. "Unrecognized RIL_RadioState: " + stateInt);
22. }
23. return state;
24. }

一般刚开机射频是RADIO_OFF的,之后转为RADIO_ON。

step6,设置射频的新状态,比较新状态和旧状态对比,看看发生了什么变化,step9~step13(还有其他的,没有列出)对变化作出响应,具体看下面的源码:

001. /**
002. * Store new RadioState and send notification based on the changes
003. *
004. * This function is called only by RIL.java when receiving unsolicited
005. * RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED
006. *
007. * RadioState has 5 values : RADIO_OFF, RADIO_UNAVAILABLE, SIM_NOT_READY,
008. * SIM_LOCKED_OR_ABSENT, and SIM_READY.
009. *
010. * @param newState new RadioState decoded from RIL_UNSOL_RADIO_STATE_CHANGED
011. */
012. protected void setRadioState(RadioState newState) {
013. RadioState oldState;
014.  
015. synchronized (mStateMonitor) {
016. Rlog.v(LOG_TAG, "setRadioState old: " + mState + " new " + newState);
017.  
018. oldState = mState;
019. mState = newState;
020.  
021. // For CTA feature, sim1 is radio on if no sim card inserted.
022. // In rild, it is in the state of SIM_LOCKED_OR_ABSENT.
023. // if the sim card is pin locked, then after turn on radio of sim, it still the state of SIM_LOCKED_OR_ABSENT
024. // special handle for this scenario, always notify radio changed if the state is SIM_LOCKED_OR_ABSENT
025. if (oldState == mState && mState != RadioState.SIM_LOCKED_OR_ABSENT) {
026. // no state transition
027. return;
028. }
029.  
030. // FIXME: Use Constants or Enums
031. if(mState.getType() == 0) {
032. mSimState = mState;
033. mRuimState = mState;
034. mNvState = mState;
035. }
036. else if (mState.getType() == 1) {
037. if(mSimState != mState) {
038. mIccStatusChangedRegistrants.notifyRegistrants();
039. }
040. mSimState = mState;
041. }
042. else if (mState.getType() == 2) {
043. if(mRuimState != mState) {
044. mIccStatusChangedRegistrants.notifyRegistrants();
045. }
046. mRuimState = mState;
047. }
048. else if (mState.getType() == 3) {
049. mNvState = mState;
050. }
051.  
052. mRadioStateChangedRegistrants.notifyRegistrants(new AsyncResult(null, mState, null));
053.  
054. if (mState.isAvailable() && !oldState.isAvailable()) {
055. Rlog.d(LOG_TAG,"Notifying: radio available");
056. mAvailRegistrants.notifyRegistrants();
057. onRadioAvailable();
058. }
059.  
060. if (!mState.isAvailable() && oldState.isAvailable()) {
061. Rlog.d(LOG_TAG,"Notifying: radio not available");
062. mNotAvailRegistrants.notifyRegistrants();
063. }
064.  
065. if (mState.isOn() && !oldState.isOn()) {
066. Rlog.d(LOG_TAG,"Notifying: Radio On");
067. mOnRegistrants.notifyRegistrants();
068. }
069.  
070. if ((!mState.isOn() || !mState.isAvailable())
071. && !((!oldState.isOn() || !oldState.isAvailable()))
072. ) {
073. Rlog.d(LOG_TAG,"Notifying: radio off or not available");
074. mOffOrNotAvailRegistrants.notifyRegistrants();
075. }
076.  
077. /* Radio Technology Change events
078. * NOTE: isGsm and isCdma have no common states in RADIO_OFF or RADIO_UNAVAILABLE; the
079. *   current phone is determined by mPhoneType
080. * NOTE: at startup no phone have been created and the RIL determines the mPhoneType
081. *   looking based on the networkMode set by the PhoneFactory in the constructor
082. */
083.  
084. if (mState.isGsm() && oldState.isCdma()) {
085. Rlog.d(LOG_TAG,"Notifying: radio technology change CDMA to GSM");
086. mVoiceRadioTechChangedRegistrants.notifyRegistrants();
087. }
088.  
089. if (mState.isGsm() && !oldState.isOn() && (mPhoneType == PhoneConstants.PHONE_TYPE_CDMA)) {
090. Rlog.d(LOG_TAG,"Notifying: radio technology change CDMA OFF to GSM");
091. mVoiceRadioTechChangedRegistrants.notifyRegistrants();
092. }
093.  
094. if (mState.isCdma() && oldState.isGsm()) {
095. Rlog.d(LOG_TAG,"Notifying: radio technology change GSM to CDMA");
096. mVoiceRadioTechChangedRegistrants.notifyRegistrants();
097. }
098.  
099. if (mState.isCdma() && !oldState.isOn() && (mPhoneType == PhoneConstants.PHONE_TYPE_GSM)) {
100. Rlog.d(LOG_TAG,"Notifying: radio technology change GSM OFF to CDMA");
101. mVoiceRadioTechChangedRegistrants.notifyRegistrants();
102. }
103. }
104. }

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卡状态进行解析:

01. private Object
02. responseIccCardStatus(Parcel p) {
03. IccCardApplicationStatus appStatus;
04.  
05. IccCardStatus cardStatus = new IccCardStatus();
06. cardStatus.setCardState(p.readInt());
07. cardStatus.setUniversalPinState(p.readInt());
08. cardStatus.mGsmUmtsSubscriptionAppIndex = p.readInt();
09. cardStatus.mCdmaSubscriptionAppIndex = p.readInt();
10. cardStatus.mImsSubscriptionAppIndex = p.readInt();
11. int numApplications = p.readInt();
12.  
13. // limit to maximum allowed applications
14. if (numApplications > IccCardStatus.CARD_MAX_APPS) {
15. numApplications = IccCardStatus.CARD_MAX_APPS;
16. }
17. cardStatus.mApplications = new IccCardApplicationStatus[numApplications];
18. for (int i = 0 ; i < numApplications ; i++) {
19. appStatus = new IccCardApplicationStatus();
20. appStatus.app_type       = appStatus.AppTypeFromRILInt(p.readInt());
21. appStatus.app_state      = appStatus.AppStateFromRILInt(p.readInt());
22. appStatus.perso_substate = appStatus.PersoSubstateFromRILInt(p.readInt());
23. appStatus.aid            = p.readString();
24. appStatus.app_label      = p.readString();
25. appStatus.pin1_replaced  = p.readInt();
26. appStatus.pin1           = appStatus.PinStateFromRILInt(p.readInt());
27. appStatus.pin2           = appStatus.PinStateFromRILInt(p.readInt());
28. cardStatus.mApplications[i] = appStatus;
29. }
30. return cardStatus;
31. }

step21,onGetIccCardStatusDone()中更新SIM卡状态mUiccCard.update(),如果第一次运行,mUiccCard对象还没有创建,则先创建,再更新。

01. private synchronized void onGetIccCardStatusDone(AsyncResult ar, boolean isUpdateSiminfo) {
02. if (ar.exception != null) {
03. Rlog.e(LOG_TAG,"[SIM " + mSimId + "] Error getting ICC status. "
04. "RIL_REQUEST_GET_ICC_STATUS should "
05. "never return an error", ar.exception);
06. return;
07. }
08.  
09. IccCardStatus status = (IccCardStatus)ar.result;
10.  
11. if (status.mCardState == IccCardStatus.CardState.CARDSTATE_PRESENT) {
12. if (DBG) log("onGetIccCardStatusDone, disableSimMissingNotification because card is present");
13. disableSimMissingNotification();
14. }
15.  
16. if (mUiccCard == null) {
17. //Create new card
18. //ALPS01311133: We also need to update SIM Info when SIM hot plug.
19. mUiccCard = new UiccCard(mContext, mCi, status, mSimId, isUpdateSiminfo);
20. else {
21. //Update already existing card
22. mUiccCard.update(mContext, mCi , status, isUpdateSiminfo);
23. }
24.  
25. if (DBG) log("Notifying IccChangedRegistrants, isUpdateSiminfo:" + isUpdateSiminfo);
26. mIccChangedRegistrants.notifyRegistrants();
27. }

step23,更新时,如果UiccCardApplication还没有创建,则先创建,同时需要根据SIM类型创建IccFileHandler具体子类对象(用来读取SIM数据)和IccRecords具体子类对象(记录SIM数据),否则直接更新。

01. public void update(Context c, CommandsInterface ci, IccCardStatus ics, boolean isUpdateSimInfo) {
02. synchronized (mLock) {
03. if (mDestroyed) {
04. loge("Updated after destroyed! Fix me!");
05. return;
06. }
07. CardState oldState = mCardState;
08. mCardState = ics.mCardState;
09. mUniversalPinState = ics.mUniversalPinState;
10. mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
11. mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
12. mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex;
13. mContext = c;
14. mCi = ci;
15. //update applications
16. if (DBG) log(ics.mApplications.length + " applications");
17. for int i = 0; i < mUiccApplications.length; i++) {
18. if (mUiccApplications[i] == null) {
19. //Create newly added Applications
20. if (i < ics.mApplications.length) {
21. mUiccApplications[i] = new UiccCardApplication(this,
22. ics.mApplications[i], mContext, mCi);
23. mIccRecords = mUiccApplications[i].getIccRecords();
24. mIccFileHandler = mUiccApplications[i].getIccFileHandler();
25. }
26. else if (i >= ics.mApplications.length) {
27. //Delete removed applications
28. if (DBG) log("update mUiccApplications[" + i + "] dispose");
29. mUiccApplications[i].dispose();
30. mUiccApplications[i] = null;
31. else {
32. //Update the rest
33. if (DBG) log("update mUiccApplications[" + i + "] update");
34. mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
35. }
36. }
37. //if (!mIccRecordsList.isEmpty()){
38. //    for (IccRecords mIccRecords: mIccRecordsList)
39. if (mIccRecords != null)
40. mIccRecords.registerForImsiReady(mHandler, EVENT_IMSI_READY, null);
41.  
42. if (DBG) log("update mUiccApplications.length: " + mUiccApplications.length);
43. if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
44. // Initialize or Reinitialize CatService
45. mCatService = CatService.getInstance(mCi,
46. mContext,
47. this);
48. else {
49. if (mCatService != null) {
50. mCatService.dispose();
51. }
52. mCatService = null;
53. }
54.  
55. sanitizeApplicationIndexes();
56.  
57.  
58. RadioState radioState = mCi.getRadioState();
59. if (DBG) log("update: radioState=" + radioState + " mLastRadioState="
60. + mLastRadioState);
61. if(isUpdateSimInfo) { //SIM卡热插拔会用到这里
62. // No notifications while radio is off or we just powering up
63. //if (radioState == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON) {
64. if (radioState != RadioState.RADIO_UNAVAILABLE) {
65. if (mCardState == CardState.CARDSTATE_ABSENT) {
66. if (DBG) log("update: notify card removed");
67. mAbsentRegistrants.notifyRegistrants();
68. mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
69. //Update SIM inserted state
70. if (FeatureOption.MTK_GEMINI_SUPPORT) {
71. Phone defaultPhone = PhoneFactory.getDefaultPhone();
72. ((GeminiPhone)defaultPhone).setSimInsertedState(getMySimId(), false);
73. }
74. else if (oldState == CardState.CARDSTATE_ABSENT &&
75. mCardState != CardState.CARDSTATE_ABSENT) {
76. if (DBG) log("update: notify card added");
77. mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_ADDED, null));
78. }
79. }
80. }
81. mLastRadioState = radioState;
82. }
83. }
UiccCardApplication执行update()操作时,如果此时SIM卡应用的状态是APPSTATE_READY,这要进行如下操作:

01. if (mAppState != oldAppState) {
02. if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState);
03. // If the app state turns to APPSTATE_READY, then query FDN status,
04. //as it might have failed in earlier attempt.
05. if (mAppState == AppState.APPSTATE_READY) {
06. queryFdn();//读取FDN数据
07. queryPin1State();//查询pin状态
08. }
09. notifyPinLockedRegistrantsIfNeeded(null);
10. notifyReadyRegistrantsIfNeeded(null);
11. }
如果SIM卡被锁住了,则会通知弹出解锁框。

step31,通知去读取SIM卡的IMSI。

step32,创建SIM Toolkit Telephony Service。

step33,通知所有关注mIccChangedRegistrants变化的观察者,如IccCardProxy(代理各种类型的SIM卡)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值