SIM卡 --- 状态变化
Posted Achillisjack
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SIM卡 --- 状态变化相关的知识,希望对你有一定的参考价值。
6,SIM卡
SIM卡主要的内容包括,SIM卡信息的状态的变化。其中,状态的变化主要是从Modem到RIL守护进程最后上报给phone进程的RIL.java的。
6.1 状态变化
SIM卡状态的变化主要通过UiccController,这个类在phone进程初始化的时候会进行初始化。
UiccController的构造方法如下,
mContext = c; //进程上下文
mCis = ci;// RIL对象
for (int i = 0; i < mCis.length; i++)
Integer index = new Integer(i);
mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, index);
mCis[i].registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, index);
mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, index);
mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, index);
当插卡开机或热插拔时,当 Modem 检卡成功后会主动上报 RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED消息,通过 RIL 通知上层监听者 UiccController,后者在收到通知后会调用 getIccCardStatus 通过 RIL 向 Modem 主动获取SIM卡相关信息,在得到 RIL_REQUEST_GET_SIM_STATUS 返回后,调用 onGetIccCardStatusDone 进行后续处理。详细的调用流程图如下,
RIL中的processUnsolicited方法对RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED消息处理如下,
1,首先调用
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: ret = responseVoid(p); break;
responseVoid方法直接返回null。
2,然后对该消息进行处理,
case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:
if (RILJ_LOGD) unsljLog(response); //输出log
if (mIccStatusChangedRegistrants != null)
mIccStatusChangedRegistrants.notifyRegistrants();
break;
在RIL的父类BaseCommands中, mIccStatusChangedRegistrants定义如下,
protected RegistrantList mIccStatusChangedRegistrants = new RegistrantList();
也是RegistrantList对象。
UiccController的构造方法会调用BaseCommands的registerForIccStatusChanged方法,该方法如下,
Registrant r = new Registrant (h, what, obj);
mIccStatusChangedRegistrants.add(r);
当然,在unregisterForIccStatusChanged方法中会取消注册,
mIccStatusChangedRegistrants.remove(h);
根据谁注册就调用谁的规则,当ril守护进程上报RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED消息时,就会给UiccController发送EVENT_ICC_STATUS_CHANGED消息, UiccController继承于Handler, handleMessage方法对EVENT_ICC_STATUS_CHANGED消息处理如下,
mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index));
调用RIL的getIccCardStatus方法获取当前SIM卡的状态。这个步骤和通话的状态变化时完全相同。并且在RIL获取结果之后,会回调给UiccController发送EVENT_GET_ICC_STATUS_DONE消息。
RIL的getIccCardStatus方法如下,
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_SIM_STATUS, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
RIL会向ril守护进程发送RIL_REQUEST_GET_SIM_STATUS消息,当获取消息之后,
processSolicited对该消息处理如下,
case RIL_REQUEST_GET_SIM_STATUS: ret = responseIccCardStatus(p); break;
responseIccCardStatus方法会将SIM卡当前的状态信息封装在IccCardStatus对象中,
IccCardStatus cardStatus = new IccCardStatus();
cardStatus.setCardState(p.readInt());
cardStatus.setUniversalPinState(p.readInt());
•••
cardStatus.mApplications = new IccCardApplicationStatus[numApplications];
for (int i = 0 ; i < numApplications ; i++)
appStatus = new IccCardApplicationStatus();
•••
最后回看UiccController的handleMessage方法对EVENT_GET_ICC_STATUS_DONE消息的处理,
onGetIccCardStatusDone(ar, index);
调用onGetIccCardStatusDone方法进行处理。
onGetIccCardStatusDone方法主要逻辑如下,
1,获取返回的结果,也就是封装的IccCardStatus对象,
IccCardStatus status = (IccCardStatus)ar.result;
2,如果是第一次读到卡,就利用IccCardStatus对象构造UiccCard对象,
if (mUiccCards[index] == null)
//Create new card
mUiccCards[index] = new UiccCard(mContext, mCis[index], status, index);
•••
3,否则就调用UiccCard的update方法更新信息,
mUiccCards[index].update(mContext, mCis[index] , status);
4,最后将更新SIM卡信息的消息进行通知,
mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null));
当然,在UiccCard的构造方法中,也会update方法,
public UiccCard(Context c, CommandsInterface ci, IccCardStatus ics)
if (DBG) log("Creating");
mCardState = ics.mCardState;
update(c, ci, ics);
update方法的主要逻辑如下,
1,利用IccCardStatus 对象为UiccCard变量赋值,
CardState oldState = mCardState;
mCardState = ics.mCardState;
mUniversalPinState = ics.mUniversalPinState;
mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
•••
2,更新mUiccApplications变量,
if (i < ics.mApplications.length)
mUiccApplications[i] = new UiccCardApplication(this, ics.mApplications[i], mContext, mCi);
•••
mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
3, 创建/更新 CatService
createAndUpdateCatService();
4,根据SIM和Radio的状态,删除/添加一个card,最后会弹出一个选择框和用户交互,
if (radiostate == RadioState.RADIO_ON && mLastRadioState == RadioState.RADIO_ON)
if (oldState != CardState.CARDSTATE_ABSENT &&
mCardState == CardState.CARDSTATE_ABSENT)
if (DBG) log("update: notify card removed");
mAbsentRegistrants.notifyRegistrants();
mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARD_REMOVED, null));
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));
主要分析步骤2.
UiccCardApplication的构造方法逻辑如下,
1,根据不同的类型,创建IccRecords对象,
mIccRecords = createIccRecords(as.app_type, mContext, mCi);
2,如果SIM卡已加载完成,则调用queryFdn方法查询Fdn数据,调用queryPin1State方法查询PIN状态,
if (mAppState == AppState.APPSTATE_READY)
queryFdn();
queryPin1State();
当然这2个方法分别调用RIL的queryFacilityLockForApp和queryFacilityLockForApp方法。
createIccRecords方法会new一个IccRecords子对象, IccRecords的构造方法如下,
mCi.registerForIccRefresh(this, EVENT_REFRESH, null);
BaseCommands 的registerForIccRefresh方法如下,
Registrant r = new Registrant (h, what, obj);
mIccRefreshRegistrants.add(r);
RIL中有关的mIccRefreshRegistrants调用如下,
case RIL_UNSOL_SIM_REFRESH:
if (RILJ_LOGD) unsljLogRet(response, ret);
if (mIccRefreshRegistrants != null)
mIccRefreshRegistrants.notifyRegistrants(new AsyncResult (null, ret, null));
break;
也就是说当ril守护进程上报RIL_UNSOL_SIM_REFRESH消息之后,会给IccRecords发送EVENT_REFRESH消息, IccRecords也是继承Handler,handleMessage对象EVENT_REFRESH消息处理的如下,
case EVENT_REFRESH:
•••
broadcastRefresh();
handleRefresh((IccRefreshResponse)ar.result);
子类IsimUiccRecords的broadcastRefresh方法实现如下,
Intent intent = new Intent(INTENT_ISIM_REFRESH);
log("send ISim REFRESH: " + INTENT_ISIM_REFRESH);
mContext.sendBroadcast(intent);
直接发送更新的广播。
以上是关于SIM卡 --- 状态变化的主要内容,如果未能解决你的问题,请参考以下文章