您的位置:首页 > 移动开发 > Android开发

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

2015-12-03 17:43 836 查看
本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉。

本文主要介绍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卡)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: