Uicc之ICCFileHandler(转)
2015-10-27 16:35
639 查看
SIM卡的本质是一个文件系统,并且具备不同的分区,而IccFileHandler主要用于从SIM卡读取相应分区的数据。
我们来看其提供的public方法有哪些:
从这些方法可以看出,IccFileHandler的主要作用就是提供SIM卡文件系统的读写操作,当调用这些方法时,需要传递要读写的文件系统地址,以及读写完毕后的回调函数,IccFileHandler会在读取完数据之后通知到调用者,并把返回值传递过去。
由于不同类型的SIM卡分区信息不同,因此在UiccCardApplication中要根据当前的SIM类型创建不同的IccFileHandler对象:
而UsimFileHandler的getEFPath()是这样的:
可以看到,SIMFileHandler与UsimFileHandler的区别就在于分区的地址上。
然后来看IccFileHandler的构造方法流程:
由于IccFileHandler的主要作用是被动的查询SIM分区信息,因此在构造方法中,只是将重要的上下文信息保存起来以备使用。
既然IccFileHandler的主要作用是读取文件信息,那么我们就来跟踪一下他是如何实现信息的读取的。
我们来看最常用的读取线性固定长度的文件信息时的流程。
在这个读取过程中,并不是直接去读取相应的分区内容,而是先读取当前分区记录的长度,当拿到长度之后再去读取当前记录的具体内容:
我们看到,在读取记录过程中仍然是循环读取的过程,直到记录完全读取完毕(lc.mRecordNum > lc.mCountRecords)后,才调用sendResult()方法将记录数据发送给当初的请求者。
这种先读取长度再读取内容的方式,同样适用于调用loadEFLinearFixed()、loadEFImgLinearFixed()、loadEFTransparent()这三个方法。
这就是IccFileHandler的读取机制。
下一章将介绍IccRecords相关流程。
原博文地址:http://blog.csdn.net/u010961631/article/details/38373967
handleMessage()为处理函数,处理obtainMessage()中的情况。
一、IccFileHandler的功能
我们来看其提供的public方法有哪些:public void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded) {} public void loadEFImgLinearFixed(int recordNum, Message onLoaded) {} public void loadEFLinearFixedAll(int fileid, Message onLoaded) {} public void loadEFTransparent(int fileid, Message onLoaded) {} public void loadEFTransparent(int fileid, int size, Message onLoaded) {} public void loadEFImgTransparent(int fileid, int highOffset, int lowOffset, int length, Message onLoaded) {} public void getEFLinearRecordSize(int fileid, Message onLoaded) {} public void updateEFLinearFixed(int fileid, int recordNum, byte[] data, String pin2, Message onComplete) {} public void updateEFTransparent(int fileid, byte[] data, Message onComplete) {}
从这些方法可以看出,IccFileHandler的主要作用就是提供SIM卡文件系统的读写操作,当调用这些方法时,需要传递要读写的文件系统地址,以及读写完毕后的回调函数,IccFileHandler会在读取完数据之后通知到调用者,并把返回值传递过去。
二、IccFileHandler的创建过程
由于不同类型的SIM卡分区信息不同,因此在UiccCardApplication中要根据当前的SIM类型创建不同的IccFileHandler对象:@UiccCardApplication.java 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; } }这几个类都继承自IccFileHandler。因为不同的SIM卡只是在分区的地址信息上有所差异,所以这几个类的唯一区别就是重写了父类的getEFPath()方法,比如SIMFileHandler:
@SIMFileHandler.java protected String getEFPath(int efid) { switch(efid) { case EF_SMS: return MF_SIM + DF_TELECOM; case EF_EXT6: case EF_MWIS: case EF_MBI: case EF_SPN: case EF_AD: case EF_MBDN: case EF_PNN: case EF_SPDI: case EF_SST: case EF_CFIS: case EF_GID1: return MF_SIM + DF_GSM; case EF_MAILBOX_CPHS: case EF_VOICE_MAIL_INDICATOR_CPHS: case EF_CFF_CPHS: case EF_SPN_CPHS: case EF_SPN_SHORT_CPHS: case EF_INFO_CPHS: case EF_CSP_CPHS: return MF_SIM + DF_GSM; } String path = getCommonIccEFPath(efid); if (path == null) { Rlog.e(LOG_TAG, "Error: EF Path being returned in null"); } return path; }
而UsimFileHandler的getEFPath()是这样的:
@UsimFileHandler.java protected String getEFPath(int efid) { switch(efid) { case EF_SMS: case EF_EXT6: case EF_MWIS: case EF_MBI: case EF_SPN: case EF_AD: case EF_MBDN: case EF_PNN: case EF_OPL: case EF_SPDI: case EF_SST: case EF_CFIS: case EF_MAILBOX_CPHS: case EF_VOICE_MAIL_INDICATOR_CPHS: case EF_CFF_CPHS: case EF_SPN_CPHS: case EF_SPN_SHORT_CPHS: case EF_FDN: case EF_MSISDN: case EF_EXT2: case EF_INFO_CPHS: case EF_CSP_CPHS: case EF_GID1: return MF_SIM + DF_ADF; case EF_PBR: return MF_SIM + DF_TELECOM + DF_PHONEBOOK; } String path = getCommonIccEFPath(efid); if (path == null) { return MF_SIM + DF_TELECOM + DF_PHONEBOOK; } return path; }
可以看到,SIMFileHandler与UsimFileHandler的区别就在于分区的地址上。
然后来看IccFileHandler的构造方法流程:
@IccFileHandler.java protected IccFileHandler(UiccCardApplication app, String aid, CommandsInterface ci) { mParentApp = app; mAid = aid; mCi = ci; }
由于IccFileHandler的主要作用是被动的查询SIM分区信息,因此在构造方法中,只是将重要的上下文信息保存起来以备使用。
三、IccFileHandler读取文件的流程
既然IccFileHandler的主要作用是读取文件信息,那么我们就来跟踪一下他是如何实现信息的读取的。我们来看最常用的读取线性固定长度的文件信息时的流程。
<span style="color:#333333;"> @IccFileHandler.java public void loadEFLinearFixed(int fileid, int recordNum, Message onLoaded) { //先去读取Record的Size Message response = </span><span style="color:#3333ff;background-color: rgb(255, 255, 255);">obtainMessage</span><span style="color:#333333;">(<span style="background-color: rgb(255, 0, 0);">EVENT_GET_RECORD_SIZE_DONE</span>, new LoadLinearFixedContext(fileid, recordNum, onLoaded)); //调用RILJ向Modem读取SIM卡当前分区的长度 mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid), 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response); } </span>
在这个读取过程中,并不是直接去读取相应的分区内容,而是先读取当前分区记录的长度,当拿到长度之后再去读取当前记录的具体内容:
<span style="color:#333333;"> public void<span style="background-color: rgb(255, 255, 255);"> </span></span><span style="color:#3366ff;background-color: rgb(255, 255, 255);">handleMessage</span><span style="color:#333333;">(Message msg) { AsyncResult ar; IccIoResult result; Message response = null; String str; LoadLinearFixedContext lc; byte data[]; int size; int fileid; int recordSize[]; try { switch (msg.what) { case EVENT_GET_RECORD_SIZE_IMG_DONE: case <span style="background-color: rgb(255, 0, 0);">EVENT_GET_RECORD_SIZE_DONE</span>: //得到从Modem拿到的原始数据 ar = (AsyncResult)msg.obj; lc = (LoadLinearFixedContext) ar.userObj; result = (IccIoResult) ar.result; response = lc.mOnLoaded; if (processException(response, (AsyncResult) msg.obj)) { break; } data = result.payload; if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) { throw new IccFileTypeMismatch(); } if (EF_TYPE_LINEAR_FIXED != data[RESPONSE_DATA_STRUCTURE]) { throw new IccFileTypeMismatch(); } //得到当前记录的长度 lc.mRecordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF; size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8) + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff); lc.mCountRecords = size / lc.mRecordSize; if (lc.mLoadAll) { lc.results = new ArrayList<byte[]>(lc.mCountRecords); } //加上要读取的记录长度再次读取数据 mCi.iccIOForApp(COMMAND_READ_RECORD, lc.mEfid, getEFPath(lc.mEfid), lc.mRecordNum, READ_RECORD_MODE_ABSOLUTE, lc.mRecordSize, null, null, mAid, obtainMessage(EVENT_READ_RECORD_DONE, lc)); break; }} catch (Exception exc) { } } </span>这里看到,IccFileHandler拿到记录的长度后,再次通过iccIOForApp()去读取记录的数据,然后就可以拿到真正需要的数据了
public void handleMessage(Message msg) { AsyncResult ar; IccIoResult result; Message response = null; String str; LoadLinearFixedContext lc; byte data[]; int size; int fileid; int recordSize[]; try { switch (msg.what) { case EVENT_READ_IMG_DONE: case EVENT_READ_RECORD_DONE: ar = (AsyncResult)msg.obj; lc = (LoadLinearFixedContext) ar.userObj; result = (IccIoResult) ar.result; response = lc.mOnLoaded; if (processException(response, (AsyncResult) msg.obj)) { break; } if (!lc.mLoadAll) { sendResult(response, result.payload, null); } else { lc.results.add(result.payload); lc.mRecordNum++; //循环读取记录 if (lc.mRecordNum > lc.mCountRecords) { sendResult(response, lc.results, null); } else { mCi.iccIOForApp(COMMAND_READ_RECORD, lc.mEfid, getEFPath(lc.mEfid), lc.mRecordNum, READ_RECORD_MODE_ABSOLUTE, lc.mRecordSize, null, null, mAid, obtainMessage(EVENT_READ_RECORD_DONE, lc)); } } break; }} catch (Exception exc) { } }
我们看到,在读取记录过程中仍然是循环读取的过程,直到记录完全读取完毕(lc.mRecordNum > lc.mCountRecords)后,才调用sendResult()方法将记录数据发送给当初的请求者。
这种先读取长度再读取内容的方式,同样适用于调用loadEFLinearFixed()、loadEFImgLinearFixed()、loadEFTransparent()这三个方法。
这就是IccFileHandler的读取机制。
下一章将介绍IccRecords相关流程。
原博文地址:http://blog.csdn.net/u010961631/article/details/38373967
handleMessage()为处理函数,处理obtainMessage()中的情况。
相关文章推荐
- iOS开发UI篇—Quartz2D使用(图片剪切)
- Carrier frequency 和 EARFCN的关系
- 032.NSValue NSNumber 包装类
- MQTT学习笔记-让Mosquitto支持Websocket
- 虚幻4 build.cs文件里面的每个字符串List的意义
- 浅谈NGUI的NGUITools类
- 【mongdb报错】Failed global initialization: BadValue Invalid or no user locale set.
- MQTT学习笔记-Mosquitto的安装与启动
- LeetCode 95: Unique Binary Search Trees II
- UIScrollView 和自动布局结合
- No resource found that matches the given name (at 'layout_toLeftOf' with value '@id/tx_search_friend
- LeetCode 96: Unique Binary Search Trees
- Java:字符串缓冲区StringBuffer和StringBuilder的使用
- npm WARN install Refusing to install vue-router as a dependency of itself
- 033.Continue 结束本次循环
- 037.Goto 代替 Continue 结束本次循环
- iOS中UITextField 使用全面解析
- UIButton
- How repair disk issue when "Fsck Failed please repair manually and reboot"
- UITableView