現有的手機中使用的卡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:Individual recZ喎?http://www.bkjia.com/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"http://www.bkjia.com/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) { mUiccApplications[i] = new UiccCardApplication(this, ics.mApplications[i], mContext, mCi); } } else 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.