Android 4.4Telephony流程分析SIM卡开机时的数据加载

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

本文主要介绍sim卡数据的读取过程,当射频状态处于准备状态时,此时UiccCardApplication应处于AppState.APPSTATE_READY状态,我们沿着这个信号跟踪下去。阅读本文时可先阅读Android4.4 Telephony流程分析——SIM卡开机时的初始化一文,了解Radio和sim卡状态更新过程。

先来看一下数据加载的序列图:

\

step1~step3,走的是更新过程,创建过程参考Android4.4 Telephony流程分析——SIM卡开机时的初始化一文step21之后的步骤。

step4,通过Modem查询sim卡的FDN(固定拨号)数据。

step5,通过Modem查询sim卡的pin1状态。

step6~step7,将pin1状态通知出去,IccCardProxy会注册mPinLockedRegistrants。

step8~step9,将sim卡ready状态发出去。

 

01. private void notifyReadyRegistrantsIfNeeded(Registrant r) {
02. if (mDestroyed) {
03. return;
04. }
05. if (mAppState == AppState.APPSTATE_READY) {
06. if (mPin1State == PinState.PINSTATE_ENABLED_NOT_VERIFIED ||
07. mPin1State == PinState.PINSTATE_ENABLED_BLOCKED ||
08. mPin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
09. loge("Sanity check failed! APPSTATE is ready while PIN1 is not verified!!!");
10. // Don't notify if application is in insane state
11. return;
12. }
13. if (r == null) {
14. if (DBG) log("Notifying registrants: READY");
15. mReadyRegistrants.notifyRegistrants();
16. else {
17. if (DBG) log("Notifying 1 registrant: READY");
18. r.notifyRegistrant(new AsyncResult(nullnullnull));
19. }
20. }
21. }

如果此时pin1是被激活的,也就是sim卡开启了pin1锁,sim卡ready状态就不会发出去。

 

监听mReadyRegistrants状态变化的对象很多,主要有:SIMRecords(同类的还有RuimRecords、IsimUiccRecords),IccCardProxy(会将SIM卡状态广播出去),GsmServiceStateTracker(会根据SIM状态去注册网络),这里主要说一下SIMRecords,读取SIM的数据。

step12,fetchSimRecords()方法:

 

001. //MTK-END [mtk80601][111215][ALPS00093395]
002. protected void fetchSimRecords() {
003. mRecordsRequested = true;
004.  
005. if (DBG) log("fetchSimRecords " + mRecordsToLoad);
006.  
007. mCi.getIMSIForApp(mParentApp.getAid(), obtainMessage(EVENT_GET_IMSI_DONE));//读IMSI
008. mRecordsToLoad++;
009.  
010. //iccFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE));
011. //mRecordsToLoad++;
012.  
013. // FIXME should examine EF[MSISDN]'s capability configuration
014. // to determine which is the voice/data/fax line
015. //new AdnRecordLoader(phone).loadFromEF(EF_MSISDN, EF_EXT1, 1,
016. //obtainMessage(EVENT_GET_MSISDN_DONE));
017. //recordsToLoad++;
018.  
019. // Record number is subscriber profile
020. mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE));
021. mRecordsToLoad++;
022.  
023. mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE));
024. mRecordsToLoad++;
025.  
026. // Record number is subscriber profile
027. mFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE));
028. mRecordsToLoad++;
029.  
030.  
031. // Also load CPHS-style voice mail indicator, which stores
032. // the same info as EF[MWIS]. If both exist, both are updated
033. // but the EF[MWIS] data is preferred
034. // Please note this must be loaded after EF[MWIS]
035. mFh.loadEFTransparent(
036. EF_VOICE_MAIL_INDICATOR_CPHS,
037. obtainMessage(EVENT_GET_VOICE_MAIL_INDICATOR_CPHS_DONE));
038. mRecordsToLoad++;
039.  
040. // Same goes for Call Forward Status indicator: fetch both
041. // EF[CFIS] and CPHS-EF, with EF[CFIS] preferred.
042. mFh.loadEFLinearFixed(EF_CFIS, 1, obtainMessage(EVENT_GET_CFIS_DONE));
043. mRecordsToLoad++;
044. mFh.loadEFTransparent(EF_CFF_CPHS, obtainMessage(EVENT_GET_CFF_DONE));
045. mRecordsToLoad++;
046.  
047.  
048. //getSpnFsm(true, null);
049.  
050. mFh.loadEFTransparent(EF_SPDI, obtainMessage(EVENT_GET_SPDI_DONE));
051. mRecordsToLoad++;
052.  
053. //mFh.loadEFLinearFixed(EF_PNN, 1, obtainMessage(EVENT_GET_PNN_DONE));
054. //recordsToLoad++;
055.  
056. mFh.loadEFTransparent(EF_SST, obtainMessage(EVENT_GET_SST_DONE));
057. mRecordsToLoad++;
058.  
059. mFh.loadEFTransparent(EF_INFO_CPHS, obtainMessage(EVENT_GET_INFO_CPHS_DONE));
060. mRecordsToLoad++;
061.  
062. mFh.loadEFTransparent(EF_CSP_CPHS,obtainMessage(EVENT_GET_CSP_CPHS_DONE));
063. mRecordsToLoad++;
064.  
065. mFh.loadEFTransparent(EF_GID1, obtainMessage(EVENT_GET_GID1_DONE));
066. mRecordsToLoad++;
067.  
068. /*
069. Detail description:
070. This feature provides a interface to get menu title string from EF_SUME
071. */
072. if (mTelephonyExt != null) {
073. if (mTelephonyExt.isSetLanguageBySIM()) {
074. mFh.loadEFTransparent(EF_SUME, obtainMessage(EVENT_QUERY_MENU_TITLE_DONE));
075. mRecordsToLoad++;
076. }
077. else {
078. loge("fetchSimRecords(): mTelephonyExt is null!!!");
079. }
080.  
081. fetchCPHSOns();
082.  
083. // XXX should seek instead of examining them all
084. if (false) { // XXX
085. mFh.loadEFLinearFixedAll(EF_SMS, obtainMessage(EVENT_GET_ALL_SMS_DONE));
086. mRecordsToLoad++;
087. }
088.  
089. if (CRASH_RIL) {
090. String sms = "0107912160130310f20404d0110041007030208054832b0120"
091. "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
092. "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
093. "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
094. "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
095. "ffffffffffffffffffffffffffffff";
096. byte[] ba = IccUtils.hexStringToBytes(sms);
097.  
098. mFh.updateEFLinearFixed(EF_SMS, 1, ba, null,
099. obtainMessage(EVENT_MARK_SMS_READ_DONE, 1));
100. }
101. if (DBG) log("fetchSimRecords " + mRecordsToLoad + " requested: " + mRecordsRequested);
102. /*
103. * Here, we assume that PHB is ready and try to read the entries.
104. * If it is not, we will receive the event EVENT_PHB_READY later.
105. * Then, we will ready the PHB entries again.
106. */
107. fetchPhbRecords();//读adn联系人
108.  
109. fetchRatBalancing();
110. }

读SIM卡是要通过Modem的,上层读Modem就得通过RIL,我们以读ADN联系人fetchPhbRecords()为例,来看看读取过程step13~step22,主要是通过IccFileHandler实现,先请求adn的长度(step16~step19),然后再请求具体的adn联系人数据step20~step22,这个过程就是与Modem交互的过程,读者可以先了解一下SIM卡的文件结构,才能更好的理解为什么这样读,我也不甚熟悉。

 

step23,获取SIM卡内置的紧急号码,这个是由运营商定制的。

step24~step26,当需要load的数据都load完成,才会执行,再在onAllRecordsLoaded中发布mRecordsLoadedRegistrants通知。

 

01. protected void onRecordLoaded() {
02. // One record loaded successfully or failed, In either case
03. // we need to update the recordsToLoad count
04. mRecordsToLoad -= 1;
05. if (DBG) log("onRecordLoaded " + mRecordsToLoad + " requested: " + mRecordsRequested);
06.  
07. if (mRecordsToLoad == 0 && mRecordsRequested == true) {
08. onAllRecordsLoaded();
09. else if (mRecordsToLoad < 0) {
10. loge("recordsToLoad <0, programmer error suspected");
11. mRecordsToLoad = 0;
12. }
13. }

step27之后的步骤,都是对mRecordsLoadedRegistrants侦听的响应,IccCardProxy侦听到后,会发广播给外界:

 

 

01. private void broadcastIccStateChangedIntent(String value, String reason) {
02. synchronized (mLock) {
03. if (mQuietMode) {
04. log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " +  value
05. " reason " + reason);
06. return;
07. }
08.  
09. Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
10. //intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
11. intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
12. intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
13. intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
14. intent.putExtra(PhoneConstants.GEMINI_SIM_ID_KEY, mSimId);
15. if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " +  value
16. " reason " + reason + " sim id " + mSimId);
17. ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE,
18. UserHandle.USER_ALL);
19. }
20. }
21.  
22. public void broadcastIccStateChangedExtendIntent(String value, String reason) {
23. synchronized (mLock) {
24. if (mQuietMode) {
25. log("QuietMode: NOT Broadcasting extend intent ACTION_SIM_STATE_CHANGED " +  value
26. " reason " + reason);
27. return;
28. }
29.  
30. Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED_EXTEND);
31. //intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
32. intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
33. intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value);
34. intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
35. intent.putExtra(PhoneConstants.GEMINI_SIM_ID_KEY, mSimId);
36. if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED_EXTEND " +  value
37. " reason " + reason + " sim id " + mSimId);
38. ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE,
39. UserHandle.USER_ALL);
40. }
41. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值