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卡 --- 状态变化的主要内容,如果未能解决你的问题,请参考以下文章

SIM卡 --- 状态变化

苹果手机sim卡插上显示无sim卡

手机显示无sim卡是怎么回事 手机显示无sim卡原因

android 判断是不是有sim卡及运营商

推荐:随身设备+流量卡,这才是外出上网/出差的最佳搭配!

SIM卡 --- IccCardProxy