Android 4.4Telephony流程分析SIM卡开机时的初始化
2015-12-03 17:43
836 查看
本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉。
本文主要介绍MTK Android开机时,SIM卡的Framework部分初始化过程。
先看一段注释:
view
sourceprint?
这是UiccController.java文件开头对UiccController的注释,意思很明显UiccController是对Android SIM卡管理的控制器。
下面是SIM卡初始化序列图:
UiccController的初始化是在phone进程启动的时候,PhoneFactory调用makeDefaultPhone()创建默认的Phone,然后走MTK双卡流程中,调用MTKPhoneFactory.makeDefaultPhone()创建的,
view
sourceprint?
上面是反编译MTK的static_gemini_intermediates库看到的,在RIL创建完成时,使用UiccController.make()初始化:
view
sourceprint?
UiccController的创建使用了单例模式,使用时调用getInstance()获取,
view
sourceprint?
下面开始解析上面序列图:
step1,rild主动上报射频信号状态RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED。
step4,对信号进行判断,看看返回当前射频状态:
view
sourceprint?
一般刚开机射频是RADIO_OFF的,之后转为RADIO_ON。
step6,设置射频的新状态,比较新状态和旧状态对比,看看发生了什么变化,step9~step13(还有其他的,没有列出)对变化作出响应,具体看下面的源码:
view
sourceprint?
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卡状态进行解析:
view
sourceprint?
step21,onGetIccCardStatusDone()中更新SIM卡状态mUiccCard.update(),如果第一次运行,mUiccCard对象还没有创建,则先创建,再更新。
view
sourceprint?
step23,更新时,如果UiccCardApplication还没有创建,则先创建,同时需要根据SIM类型创建IccFileHandler具体子类对象(用来读取SIM数据)和IccRecords具体子类对象(记录SIM数据),否则直接更新。
view
sourceprint?
UiccCardApplication执行update()操作时,如果此时SIM卡应用的状态是APPSTATE_READY,这要进行如下操作:
view
sourceprint?
如果SIM卡被锁住了,则会通知弹出解锁框。
step31,通知去读取SIM卡的IMSI。
step32,创建SIM Toolkit Telephony Service。
step33,通知所有关注mIccChangedRegistrants变化的观察者,如IccCardProxy(代理各种类型的SIM卡)。
本文主要介绍MTK Android开机时,SIM卡的Framework部分初始化过程。
先看一段注释:
view
sourceprint?
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()创建的,
view
sourceprint?
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()初始化:
view
sourceprint?
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()获取,
view
sourceprint?
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,对信号进行判断,看看返回当前射频状态:
view
sourceprint?
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(还有其他的,没有列出)对变化作出响应,具体看下面的源码:
view
sourceprint?
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卡状态进行解析:
view
sourceprint?
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对象还没有创建,则先创建,再更新。
view
sourceprint?
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数据),否则直接更新。
view
sourceprint?
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,这要进行如下操作:
view
sourceprint?
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卡)。
相关文章推荐
- Android Studio系列教程六--Gradle多渠道打包
- Android Crash日志抓取及保存
- android一款软件的反编译实现(APKtool)
- Android 4.4Telephony流程分析SIM卡开机时的数据加载
- Android Studio系列教程五--Gradle命令详解与导入第三方包
- Android Studio系列教程四--Gradle基础
- 对Android源码中常见的一些flag的运算的理解
- Android Studio系列教程三--快捷键
- Android设置Settings实现:PreferenceActivity【1】
- Android Studio Helloworld备忘
- Android Studio系列教程二--基本设置与运行
- android 长布局截图(listView ScrollView)
- android Widget 中读取SharedPreference 坑
- android.support.v7.internal.widget.ActionBarOverlayLayout
- Android笔记:android的适配
- Android 谷歌gcm推送所需要的端口
- Android 怎样控制电量百分比是否显示
- android样式style使用
- Android studio 安装README.md编辑插件
- Android Button 点击事件无效