現有的手機中使用的卡SIM, USIM,UIM等統稱為:UICC——Universal Integrated Circuit Card;
這些卡之間數據結構是有些區別的,先來看看SIM卡的文件結構。
一 Sim文件系統數據結構
1 sim卡文件系統
SIM card file system structure:
2 文件結構
MF:The root level of the file system is known as the Master file.
DF:Directories are known as Dedicated files and are of a fixed size.
EF:Inpidual recZ喎?/kf/ware/vc/” target=”_blank” class=”keylink”>vcmRzIChvciBmaWxlcykgYXJlIGtub3duIGFzIEVsZW1lbnRhcnkgZmlsZXMuPC9wPgo8cD4gPC9wPgo8cD6hoaGhQWxsIGZpbGVzIGFyZSBpZGVudGlmaWVkIGFzIGFuIGFkZHJlc3MgKGEgRFdPUkQgdmFsdWUpLCByYXRoZXIgdGhhbiBhIGZpbGVuYW1lLjwvcD4KPHA+IDwvcD4KPGgyPjMgzsS8/sDg0M08L2gyPgo8cD48c3Ryb25nPlRyYW5zcGFyZW50PC9zdHJvbmc+o7o8L3A+CjxwPqGhoaHNuMP3veG5ubXERUYg08nSu7j219a92tDywdDX6bPJoaO1sc7EvP62wbvyuPzQwqOs19a92tDywdC77ravyseyztXVz+C21LXYPC9wPgo8cD7Wt6OoT0ZGU0VUo6m9+NDQtcSjrM/gttS12Na3v8mx7cq+s/bG8Mq8stnX97XEtdjWt6Oo08PX1r3ase3KvqOpus22wbP2oaK4/NDCtcQ8L3A+CjxwPtfWvdrK/aGjzbjD90VGILXEtdrSu7j219a92tPQ0ru49s/gttS12Na3oa4wMDAwoa+ho0VGINb3zOW1xMr9vt2zpLbI1NpFRiC1xM7EvP48L3A+CjxwPs231tChozwvcD4KPHA+PHN0cm9uZz5MaW5lYXIgRml4ZWQgRmlsZaO6PC9zdHJvbmc+PC9wPgo8cD6hoaGhz9/Q1LnMtqhFRiDOxLz+08nSu7j2vMfCvLOktsi5zLaotcS8x8K80PLB0Nfps8mho7Xa0ru49rzHwry8x8K8usXKxzGho7zHwrw8L3A+CjxwPrXEs6S2yLrNvMfCvLOktsjT67zHwry49sr9tcSzy7v9tOa3xdTaRUYgzsS8/s231tChozwvcD4KPHA+PHN0cm9uZz5DeWNsaWOjujwvc3Ryb25nPjwvcD4KPHA+oaGhodGtu7fOxLz+08PT2tLUyrG85Muz0PK05rSitcS8x8K8o6y1scv509C1xLzHwry/1bzktrzVvNPDyrGjrNDCtcS05rSiyv2+3b2rPC9wPgo8cD64srjH1+6+ybXE0MXPoqGjPC9wPgo8cD6hoaGht8POyrK7zay1xM7EvP7A4NDNo6zKudPDtcS3vcq90rK9q7K7zayho7bU09pVU0lNo6xSVUlNtci/qLv5sb7OxLz+veG5udOmuMPKx9K71sK1xKOsvtayv7TmtKLQxc+itcS1pdSqo6zOu9bDsrvNrLb40tGhozwvcD4KPHA+IDwvcD4KPGgxPrb+IFVJQ0O/qMr9vt22wdC0PC9oMT4KPGgyPjEgVUlDQ7/yvNzA4L3hubk8L2gyPgo8cD6hoaGhyta7+tDo0qq52NeitcRVSUNDsPzAqKO6yv2+3bbB0LS8x8K8o6zXtMysseS7r7ncwO2ju0FuZHJvaWTW0MrHudzA7VVJQ0O1xL/yvNy0+sLrzrvT2qO6PC9wPgo8cD5mcmFtZXdvcmtzXG9wdFx0ZWxlcGhvbnlcc3JjXGphdmFcY29tXGFuZHJvaWRcaW50ZXJuYWxcdGVsZXBob255XHVpY2NcPC9wPgo8cD48c3Ryb25nPrv5sb6/8rzcwOC1w73hubnNvKO6PC9zdHJvbmc+PC9wPgo8cD6hoaGhoaGhoSAgICAgICAgPGltZyBzcmM9″/uploadfile/Collfiles/20140111/2014011114104238.jpg” alt=”\”>
對於不同的卡會有不同的類與之對應,這些類的作用:
UiccController:整個UICC相關信息的控制接口;監控SIM狀態變化;
UiccCard:UICC卡代碼中對應的抽象;
IccCardStatus:維護UICC卡的狀態:CardState & PinState;
UiccCardApplication:UICC具體的一個應用;負責Pin Puk密碼設置解鎖,數據的讀取,存儲;
CatService:負責SIM Toolkit相關;
IccConstants:SIM File Address;存儲不同數據在Sim卡上的字段地址;SIMRecords等基類;
SIMRecords /RuimRecords:記錄SIM卡上的數據;
IccFileHandler:讀取SIM數據以及接收讀取的結果;
2 UICC 框架執行流程
UICC的狀態監控是在UiccController中進行的;
UiccController構造函數:
private UiccController(Context c, CommandsInterface ci) { mCi = ci; //註冊UICC卡狀態變化監聽 mCi.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); //註冊RADIO狀態變化監聽 mCi.registerForOn(this, EVENT_ICC_STATUS_CHANGED, null); mCi.registerForAvailable(this, EVENT_ICC_STATUS_CHANGED, null); mCi.registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, null); }
UICC Card狀態有變化處理:
public void handleMessage (Message msg) { switch (msg.what) { case EVENT_ICC_STATUS_CHANGED: //UICC狀態變化,獲取UICC狀態 mCi.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE)); break; case EVENT_GET_ICC_STATUS_DONE: //UICC狀態變化,獲取UICC狀態返回處理 AsyncResult ar = (AsyncResult)msg.obj; onGetIccCardStatusDone(ar); break; } }
UICC Card處理狀態變化:
private synchronized void onGetIccCardStatusDone(AsyncResult ar) { //返回的數據結構IccCardStatus IccCardStatus status = (IccCardStatus)ar.result; //更新Uicc Card狀態 ,若UiccCard未創建則新創建 //新創建也是一樣調用UiccCard@update if (mUiccCard == null) { //Create new card mUiccCard = new UiccCard(mContext, mCi, status); } else { //Update already existing card mUiccCard.update(mContext, mCi , status); } }
UICC Card狀態更新:
public void update(Context c, CommandsInterface ci, IccCardStatus ics) { synchronized (mLock) { mCardState = ics.mCardState; mUniversalPinState = ics.mUniversalPinState; //update applications UiccApplications構造則新創建 //新創建跟update流程一致 for ( int i = 0; i < mUiccApplications.length; i++) { if (mUiccApplications[i] == null) { //Create newly added Applications if (i = ics.mApplications.length) { //Delete removed applications mUiccApplications[i].dispose(); mUiccApplications[i] = null; } else { //Update the rest mUiccApplications[i].update(ics.mApplications[i], mContext, mCi); } } //STK相關 createAndUpdateCatService(); } }
Uicc Applications更新:
void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) { synchronized (mLock) { //更新type state pin …… AppType oldAppType = mAppType; AppState oldAppState = mAppState; mAppType = as.app_type; mAppState = as.app_state; …… //APP Type變化更新 if (mAppType != oldAppType) { if (mIccFh != null) { mIccFh.dispose();} if (mIccRecords != null) { mIccRecords.dispose();} mIccFh = createIccFileHandler(as.app_type); mIccRecords = createIccRecords(as.app_type, c, ci); } //APP State變化更新 if (mAppState != oldAppState) { // If the app state turns to APPSTATE_READY, then query FDN status, //as it might have failed in earlier attempt. if (mAppState == AppState.APPSTATE_READY) { //FDN查詢 queryFdn(); //PIN查詢 queryPin1State(); } //PIN狀態通知 notifyPinLockedRegistrantsIfNeeded(null); //UICC Ready否狀態通知 notifyReadyRegistrantsIfNeeded(null); } } }
這裡會根據UICC的狀態繼續下一步的操作:
如果UICC需要PIN解鎖,則會發出需要Pin碼鎖通知;進行UICC pin碼輸入解鎖,然後狀態變化,
繼續更新UICC Card,Uicc Applications直到UICC狀態Ready;
如果UICC已經ready,則發出UICC Ready通知;
狀態更新流程如下:
3 UICC數據讀取過程
發出UICC Ready的通知是在UiccApplications中,
在接收到UICC Ready的通知後,就可以進行UICC中相關數據的讀寫;
這個有在IccRecords類中進行,以SimRecors為例:
public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) { super(app, c, ci); //電話號碼 adnCache = new AdnRecordCache(mFh); //監聽UiccApplications 發出Sim Ready通知 mParentApp.registerForReady(this, EVENT_APP_READY, null); }
SIMRecords消息處理:
public void handleMessage(Message msg) { switch (msg.what) { case EVENT_APP_READY: onReady(); break; //IO events 通過IccFileHandler數據讀取SIM數據,返回結果處理 case EVENT_GET_IMSI_DONE: …… break; case EVENT_GET_MBI_DONE: …… break; case EVENT_GET_AD_DONE: case EVENT_GET_SPN_DONE: break; …… } }
監聽到SIM Ready消息:
public void onReady() { fetchSimRecords(); } protected void fetchSimRecords() { //通過IccFileHandler向 RIL發送讀取數據的消息 mFh.loadEFTransparent(EF_ICCID, obtainMessage(EVENT_GET_ICCID_DONE)); recordsToLoad++; // Record number is subscriber profile mFh.loadEFLinearFixed(EF_MBI, 1, obtainMessage(EVENT_GET_MBI_DONE)); recordsToLoad++; mFh.loadEFTransparent(EF_AD, obtainMessage(EVENT_GET_AD_DONE)); recordsToLoad++; // Record number is subscriber profile mFh.loadEFLinearFixed(EF_MWIS, 1, obtainMessage(EVENT_GET_MWIS_DONE)); recordsToLoad++; …… }
IccFileHandler數據讀取:
public void loadEFTransparent(int fileid, Message onLoaded) { Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE, fileid, 0, onLoaded); mCi.iccIOForApp(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid), 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, mAid, response); }
loadEFTransparent和loadEFLinearFixed,就是針對不同的文件格式,
實際都是調用RIL_JAVA:
void iccIOForApp (int command, int fileid, String path, int p1, int p2, int p3, String data, String pin2, String aid, Message result) { …… }
RIL_iccIOForApp函數的參數含義:
command:讀寫更新……操作命令
final int COMMAND_READ_BINARY = 0xb0;
final int COMMAND_UPDATE_BINARY = 0xd6;
final int COMMAND_READ_RECORD = 0xb2;
final int COMMAND_UPDATE_RECORD = 0xdc;
final int COMMAND_SEEK = 0xa2;
final int COMMAND_GET_RESPONSE = 0xc0;
……
fileid:數據字段在SIM文件系統中的地址 :例如Plmn:0x6F30
path: 此數據字段上級所有目錄地址:
例如Plmn的Path:MF + DF_GSM = “0x3F000x7F20”
地址字段都需要根據UICC文件系統結構,地址決定
p1:
p2:
p3:
data:
pin2:
aid: 由UICC傳遞上來的
result:回調Message
從3GPP SIM相關協議可以看到,P1,P2,P3等這些參數的含義:
S:stands for data sent by the ME
R:stands for data received by the ME
Offset is coded on 2 bytes where P1 gives thehigh order byte and P2 the low order byte.
’00 00′ means no offset and reading/updating starts with the first byte
’00 01′ means that reading/updating starts with the second byte.