本文主要關於usim卡上郵箱地址分析執行個體的,同時也附帶了一個連絡人號碼的例子,之前分別寫過讀取sim/usim卡上簡訊息和連絡人資訊的文章,偏向代碼調用流程,這次把重點放在具體解析過程。本文可以結合下面的連結一起看。
1.android
-- sim/usim卡導連絡人
2.android
資訊(mms)的故事(七)-- sim卡簡訊 3.關於sim/usim的一些概念
我們從這裡開始 UsimPhoneBookManager.java的內部類PbrFile.java,從卡上讀出來的位元組資料在這裡解析,代碼不算多,流程也還清晰,PbrFile.java的建構函式裡調用parseTag,parseTag中又調用parseEf,先看下代碼再一起分析。下面是具體的代碼,
[java]
view plaincopy
- private class PbrFile {
- HashMap<Integer,Map<Integer,Integer>> mFileIds;
-
- PbrFile(ArrayList<byte[]> records) {
- mFileIds = new HashMap<Integer, Map<Integer, Integer>>();
- SimTlv recTlv;
- int recNum = 0;
- for (byte[] record: records) {
- recTlv = new SimTlv(record, 0, record.length);
- parseTag(recTlv, recNum);
- recNum ++;
- }
- }
-
- void parseTag(SimTlv tlv, int recNum) {
- SimTlv tlvEf;
- int tag;
- byte[] data;
- Map<Integer, Integer> val = new HashMap<Integer, Integer>();
- do {
- tag = tlv.getTag();
- switch(tag) {
- case USIM_TYPE1_TAG: // A8
- case USIM_TYPE3_TAG: // AA
- case USIM_TYPE2_TAG: // A9
- data = tlv.getData();
- tlvEf = new SimTlv(data, 0, data.length);
- parseEf(tlvEf, val, tag);
- break;
- }
- } while (tlv.nextObject());
- mFileIds.put(recNum, val);
- }
-
- void parseEf(SimTlv tlv, Map<Integer, Integer> val, int parentTag) {
- int tag;
- byte[] data;
- int tagNumberWithinParentTag = 0;
- do {
- tag = tlv.getTag();
- if (parentTag == USIM_TYPE2_TAG && tag == USIM_EFEMAIL_TAG) {
- mEmailPresentInIap = true;
- mEmailTagNumberInIap = tagNumberWithinParentTag;
- }
- switch(tag) {
- case USIM_EFEMAIL_TAG:
- case USIM_EFADN_TAG:
- case USIM_EFEXT1_TAG:
- case USIM_EFANR_TAG:
- case USIM_EFPBC_TAG:
- case USIM_EFGRP_TAG:
- case USIM_EFAAS_TAG:
- case USIM_EFGSD_TAG:
- case USIM_EFUID_TAG:
- case USIM_EFCCP1_TAG:
- case USIM_EFIAP_TAG:
- case USIM_EFSNE_TAG:
- data = tlv.getData();
- int efid = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
- val.put(tag, efid);
- break;
- }
- tagNumberWithinParentTag ++;
- } while(tlv.nextObject());
- }
首先看到以new了一個simTlv(simTlv名稱來源,3gpp 31.102中 TLV:Tag length value)對象,將傳過來的位元組數組數組封裝了一下,繼續往下看在parseTag函數中的switch語句,A8、A9和AA是什麼意思呢?和我們讀取數組有什麼關係呢?讀取,清楚這三個tag是我們解析資料的基礎,規則如下,
1:USIM卡檔案系統內EF檔案主要分三類:標籤tag為A8的type1類型檔案、tag為A9的type2類型檔案以及tag為AA的type3類型檔案。
2:EFEMAIL(電子郵件)的存在方式只有type1和type2兩:當EFEMAIL以type1方式存在時,其中的記錄內容和電話本主檔案EFADN一對一映射,即EFADN中的第N條記錄與EFEMAIL檔案中第N條記錄一一對應;當EFEMAIL以type2方式存在時,EFADN與EFEMAIL中的記錄通過EFIAP檔案相關聯。EFIAP是type1類型檔案,與EFADN中的記錄一一對應,EFIAP在檔案系統內與type2類型檔案必同時存在。 PS:EFEMAIL在檔案系統內可能不止一個,且存在方式可能有多種組合。
再接下來在parseEf又出現幾個tag,這裡我們關注USIM_EFEMAIL_TAG(CA)、USIM_EFADN_TAG(C0)和USIM_EFIAP_TAG(C1),CA標識出電子郵件ID,C0標識的是電話號碼ID,C1的作用可以理解一個索引,根據這個索引再去找CA。規則說得差不多了,來看些例子。以標準AT命令(3gpp 27.007)為例
讀電子郵件:
1.利用AT命令AT+CRSM=178,20272(EF_PBR:4F30),記錄下標,4,0來讀取EFPBR檔案的記錄,擷取各個檔案的檔案ID以及短檔案標識SFI。下面是兩條USIM卡兩條真實的資料記錄。
A8 標識
1E 長度(16進位)
C0034F3A01C1034F3102C4034F5A0AC5034F4106C6034F5107C9034F6108
A9 標識
05 長度
CA034F7109
AA14C2034F4A03C7034F4B0BC8034F4C0CCB034F4F16FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
這段就不重複標註了,和上面的一樣。A8
28
C0034F3A04C1034F3105C4034F5A06C4034F6A07C4034F7A08C5034F4109C6034F510AC9034F610B
A9
05
CA034F710C
AA14
C2034F4A0DC7034F4B0EC8034F4C0FCB034F4F10
從此真實記錄中看出標識A9下有標識CA(電子郵件),EFEMAIL檔案ID為4F71。標識A8下有標識C0(EFADN檔案),EFADN檔案ID為4F3A,短檔案標識為04。標識C1(EFIAP檔案)檔案ID為4F31。 讀得過程中若電子郵件是type1類型檔案,則EFEMAIL與EFADN一對一映射,在對應下標處寫即可。 如果電子郵件是type2類型檔案則:
1)利用AT命令讀取此記錄對應EFEMAIL檔案中的記錄下標:
AT+CRSM=178,EFIAP檔案ID,對應EFADN檔案中的記錄下標,4,0
在返回的記錄中找到order次序的欄位值email_record_index。
2)利用AT命令讀取電子郵件檔案中email_record_index下標的記錄:
AT+CRSM=178,EFEMAIL檔案的ID,email_record_index,4,0
針對第二種給出一下例子
[java]
view plaincopy
- ===>>[Send AT cmd][5] AT+CRSM=178,(4F31)20273,2,4,1,,3F007F105F3A,
- <<====[Recv AT cmd][5] +CRSM: 144,0,01,
- ===>>[Send AT cmd][5] AT+CRSM=178, (4F71)20337,1,4,42,,3F007F105F3A,
- <<====[Recv AT cmd][5] +CRSM: 144,0,6775750074792E636F6DFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF,
到這裡故事還沒有結束,在上面串裡我們看到了EFADN,這傢伙指示著電話號碼,也許有時候我們還要在去這裡找找電話號碼,連絡人的號碼記錄是這樣[java]
view plaincopy
- ===>>[Send AT cmd][5] AT+CRSM=178,20282,1,4,28,,3F007F105F3A, time=Sat Jan 1 08:06:39 2000
- <<====[Recv AT cmd][5] +CRSM: 144,0,804E09FFFFFFFFFFFFFFFFFFFFFF0480333333FFFFFFFFFFFFFFFFFF
80、81編碼格式,後面緊跟著升序 連絡人名字4E09 :三, 號碼:3333333(相信聰明的你已經知道80,81代表什麼了)。
內容差不多就這些,主要的東西應該都寫出來了,導卡這部分給個人的感覺是如果想讀全讀卡上連絡人資訊(所有的號碼和郵箱)要考慮的東西還是挺多的,流程本身沒有多複雜,但是過程比較繞,如果想導卡時間短一些,只導主要的資訊就好了(比如忽略附加號碼,只找一個郵箱地址),這樣能快不少,有些手機確實就是這麼做的,不過這種導法從技術的角度是不應該的,對於這種時間與品質的取捨根據項目的具體要求來決定吧。
最後,上面對於 type1類型的電子郵件還沒有執行個體,如果你有歡迎分享一下,當然對文章寫得不對地方也歡迎拍磚。