UICC框架初识

UICC框架初识一 UICC 概念 UICC UniversalInt 通用集成电路卡

大家好,欢迎来到IT知识分享网。

一.UICC概念

UICC:Universal Integrated Circuit Card,通用集成电路卡。主要用于存储用户信息、鉴权密钥、短消、付费方式等信息。俗称电话卡,SIM卡。

二.UICC种类

UICC引入了多应用平台的概念,实现了多个逻辑应用(即逻辑模块)同时运行的多通道机制。一个UICC可同时包含多种不同的逻辑模块,根据当前终端所支持的无线接入网络的类型,来选择使用相应的逻辑模块。

UICC根据逻辑模块的不同,分为以下几种不同的电话卡:

1.SIM:如用户标识模块(Subscriber Identity Module)
早期的SIM卡类型,支持GSM网络。
2.USIM:通用用户标识模块(Universal Subscriber Identity Module,)
升级版的SIM卡,支持UMTS(WCMDA,TD-SCDMA)和GSM网络,(联通卡,移动卡)
3.RUIM:可移动用户身份模块(Removable User Identity Module)
在SIM卡基础上做了扩展,专门为网络而设计,不再只是针对GSM,比如:CDMA.R-UIM卡支持在CDMA和GSM网络之间的漫游。支持CDMA和GSM网络(电信卡)
4.ISIM:IP多媒体业务标识模块(IP Multi Media Service Identity Module,)
存储了IMS(IP多媒体系统)专用的用户数据,主要由IMS运营商所提供。
5.CSIM:CDMA用户识别模块(CDMA Subscriber Identity Module )

三.UICC框架

Android4.1之后的版本都使用了UICC框架来管理和控制SIM卡。

UICC的大体框架图如下:
UICC的大体框架图

UiccController 设计为单例模式。监听RIL中的SIM卡状态,并把SIM卡状态的变化通知给其他类。在UICC框架中,它属于核心部分,除了分发SIM卡状态变化,还对外提供接口用于获取UiccCard,IccFileHandler,IccRecords,UiccCardApplication的对象。
UiccCard 它代表了具体的卡,一个UiccCard对象就表示了一张SIM卡(PhoneID)。SIM卡中的状态或者数据都可以在这里获取,比如,属性mCardState保存了SIM卡状态,mUniversalPinState保存了PIN码状态,mCatService代表了STK应用信息,mUiccApplications中包含了SIM卡的具体数据。。。等等,总结起来,UiccCard是SIM卡的大管家,它既代表了SIM卡,又控制了UiccApplications,CatService的生命周期。
UiccCardApplication 顾名思义,这是SIM卡应用(不是STK)。应该是对应了上面说到的逻辑模块,一张SIM卡可以有多个逻辑模块,也就有多个UiccCardApplication对象。它控制了IccRecords和IccFileHandler的生命周期。而IccRecords和IccFileHandler都是读取和保存SIM卡中具体数据的操作类
IccFileHandler 读取SIM卡中(逻辑模块)的文件系统,也就是SIM卡中的具体数据。根据UICC卡的种类不同,衍生了几个对应的子类SIMFileHandler,UsimFileHandler,RuimFileHandler,CsimFileHandler,IsimFileHandler
IccRecords 模板类,通过IccFileHandler来操作SIM卡中的文件系统个,获取并保存SIM中的具体数据,根据UICC卡的种类不同,衍生了几个对应的子类SIMRecords,RuimRecords,IsimUiccRecords
IccCardProxy 封装了对UICC的一系列操作(状态和数据),并对外提供接口。一张卡(PhoneID)对应一个IccCardProxy对象。实际上,我们可以使用UiccController获取其他的对象从而实现对UICC的操作,但是需要传入一系列参数并保证卡状态正确,否则需要做判断处理,使用IccCardProxy操作只需要知道PhoneID。并发出ACTION_SIM_STATE_CHANGED广播,通知应用层以及没有监听UiccController得知SIM卡状态发生变化的其他类。
AdnRecordCache

UICC框架中主动读取SIM卡状态的时序图:

uicc的时序图

UICC框架中把SIM卡的状态分为以下几种:

IccCardStatus.java

public static enum CardState { CARDSTATE_ABSENT, CARDSTATE_PRESENT, CARDSTATE_ERROR; }

UiccController监听RIL中的状态变化,其中几个比较重要的监听事件如下:

EVENT_ICC_STATUS_CHANGED SIM卡状态
EVENT_GET_ICC_STATUS_DONE 主动查询SIM卡状态
EVENT_RADIO_UNAVAILABLE Modem没启动或者错误
EVENT_SIM_REFRESH SIM卡刷新

EVENT_ICC_STATUS_CHANGED,EVENT_RADIO_UNAVAILABLE,EVENT_SIM_REFRESH 都是RIL主动上报的事件消息。其中EVENT_ICC_STATUS_CHANGED这个事件消息的上报结果中并不会携带结果,也就是说得到这个状态,只能判断到当前SIM卡状态变化了,但是当前是CARDSTATE_ABSENT,CARDSTATE_PRESENT,CARDSTATE_ERROR中的哪一个,你还需要查询一遍,所以就有了以下的这个状态监听:
EVENT_GET_ICC_STATUS_DONE 主动查询SIM卡状态
这就是有了EVENT_ICC_STATUS_CHANGED事件消息后还需要设置EVENT_GET_ICC_STATUS_DONE事件消息的原因。

1.RIL.java

RIL中处理SIM卡状态相关的事件消息。其中,在处理EVENT_GET_ICC_STATUS_DONE 主动查询SIM卡状态的时候,查询结果被封装在IccCardStatus类中并交由其监听类UiccController中处理(ret):

case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: if (RILJ_LOGD) unsljLog(response); if (mIccStatusChangedRegistrants != null) { mIccStatusChangedRegistrants.notifyRegistrants(); } break; case RIL_UNSOL_SIM_REFRESH: if (RILJ_LOGD) unsljLogRet(response, ret); if (mIccRefreshRegistrants != null) { mIccRefreshRegistrants.notifyRegistrants( new AsyncResult (null, ret, null)); } break; case RIL_REQUEST_GET_ICC_APPLICATION_STATUS: ret = responseIccCardStatus(p); break; case RIL_REQUEST_GET_SIM_STATUS: ret = responseIccCardStatus(p); break; ...... private Object responseIccCardStatus(Parcel p) { IccCardApplicationStatus appStatus; IccCardStatus cardStatus = new IccCardStatus(); cardStatus.setCardState(p.readInt()); ...... return cardStatus; }

2.UiccController.java

UiccController中处理SIM卡状态相关的事件消息:

case EVENT_GET_ICC_STATUS_DONE: if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); onGetIccCardStatusDone(ar, index); break; case EVENT_RADIO_UNAVAILABLE: if (DBG) log("EVENT_RADIO_UNAVAILABLE, dispose card"); if (mUiccCards[index] != null) { mUiccCards[index].dispose(); } mUiccCards[index] = null; mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); break; case EVENT_SIM_REFRESH: if (DBG) log("Received EVENT_SIM_REFRESH"); onSimRefresh(ar, index); 

如时序图所示,主要分析主动查询SIM卡状态时的流程:为每一张SIM卡初始化一个UiccCards对象并赋初值。

private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) { ...... if(this.mUiccCards[index.intValue()] == null) { this.mUiccCards[index.intValue()] = new UiccCard(this.mContext, this.mCis[index.intValue()], status, index.intValue()); } else { this.mUiccCards[index.intValue()].update(this.mContext, this.mCis[index.intValue()], status); } ...... }

3.UiccCard.java

一个UiccCard对象就表示了一张SIM卡(PhoneID),其控制了UiccApplications,CatService的生命周期。参见UiccCard.java—->createAndUpdateCatService()和update()

4.UiccApplications.java

UiccApplications代表了SIM卡中的逻辑模块,根据当前SIM中的逻辑模块的多少产生多少个UiccApplications对象,上限为8个。控制着IccRecords和IccFileHandler的生命周期,此外还包含了一系列对SIM卡数据的操作,比如pin码,puk码,是否锁卡,是否支持FDN等等,系统文件的读取则交由IccFileHandler处理。

根据UICC卡的种类不同,创建相应的模板类IccRecords:

 if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) { return new SIMRecords(this, c, ci); } else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){ return new RuimRecords(this, c, ci); } else if (type == AppType.APPTYPE_ISIM) { return new IsimUiccRecords(this, c, ci); } else { // Unknown app type (maybe detection is still in progress) return null; }

根据UICC卡的种类不同,创建相应的系统文件读取类IccFileHandler:

 private IccFileHandler createIccFileHandler(AppType type) { switch (type) { case APPTYPE_SIM: return new SIMFileHandler(this, mAid, mCi); case APPTYPE_RUIM: return new RuimFileHandler(this, mAid, mCi); case APPTYPE_USIM: return new UsimFileHandler(this, mAid, mCi); case APPTYPE_CSIM: return new CsimFileHandler(this, mAid, mCi); case APPTYPE_ISIM: return new IsimFileHandler(this, mAid, mCi); default: return null; } }

这里忽略IccRecords和IccFileHandler中对SIM卡内存的数据操作……

5.IccCardProxy.java

IccCardProxy设计的初衷就是对外提供接口。因为UiccCards对象的创建跟卡状态相关,会动态创建和销毁,如果外部通过UiccCards来获取卡的状态以及其他信息,不可避免的会出现错误,因此,android就设计了IccCardProxy,无论卡状态如何变化,它的对象都存在,其初始化在TelephonyComponentFactory.java中:

public IccCardProxy makeIccCardProxy(Context context, CommandsInterface ci, int phoneId) { return new IccCardProxy(context, ci, phoneId); }

Phone对象创建时,先创建了UiccController对象,之后根据mPhoneId创建了IccCardProxy对象,意味着有几个卡槽就有几个IccCardProxy对象。

mIccCardProxy = mTelephonyComponentFactory.makeIccCardProxy(mContext, mCi, mPhoneId);

如果我们需要操作SIM卡相关,正确的姿势应该是通过Phone对象获取IccCardProxy对象,通过IccCardProxy暴露出的接口来实现对SIM卡相关的操作。

@Override public IccCard getIccCard() { return mIccCardProxy; }

Android对IccCardProxy的设计初衷的注释如下:
* The Phone App assumes that there is only one icc card, and one icc application
* available at a time. Moreover, it assumes such object (represented with IccCard)
* is available all the time (whether {@link RILConstants#RIL_REQUEST_GET_SIM_STATUS} returned
* or not, whether card has desired application or not, whether there really is a card in the
* slot or not).
*
* UiccController, however, can handle multiple instances of icc objects (multiple
* {@link UiccCardApplication}, multiple {@link IccFileHandler}, multiple {@link IccRecords})
* created and destroyed dynamically during phone operation.
*
* This class implements the IccCard interface that is always available (right after default
* phone object is constructed) to expose the current (based on voice radio technology)
* application on the uicc card, so that external apps won’t break.

以上就是对UICC框架的一些简单总结,细节方面待以后使用到的时候再去研究。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/141703.html

(0)
上一篇 2025-05-15 15:26
下一篇 2025-05-15 16:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信