10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/* 20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2009 The Android Open Source Project 30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License"); 50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License. 60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at 70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * http://www.apache.org/licenses/LICENSE-2.0 90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software 110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS, 120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and 140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License. 150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.gsm; 180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult; 200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler; 210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message; 22ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Savilleimport android.telephony.Rlog; 23a62d723815dad650884714e801421b6d7cb34f91Jack Yuimport android.util.SparseArray; 24a62d723815dad650884714e801421b6d7cb34f91Jack Yuimport android.util.SparseIntArray; 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 26d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.AdnRecord; 27d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.AdnRecordCache; 28d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccConstants; 29d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccFileHandler; 30d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils; 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** 340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * This class implements reading and parsing USIM records. 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Refer to Spec 3GPP TS 31.102 for more details. 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide} 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class UsimPhoneBookManager extends Handler implements IccConstants { 40cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville private static final String LOG_TAG = "UsimPhoneBookManager"; 410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final boolean DBG = true; 42a62d723815dad650884714e801421b6d7cb34f91Jack Yu private ArrayList<PbrRecord> mPbrRecords; 430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private Boolean mIsPbrPresent; 440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private IccFileHandler mFh; 450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private AdnRecordCache mAdnCache; 460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private Object mLock = new Object(); 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private ArrayList<AdnRecord> mPhoneBookRecords; 480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private ArrayList<byte[]> mIapFileRecord; 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private ArrayList<byte[]> mEmailFileRecord; 50a62d723815dad650884714e801421b6d7cb34f91Jack Yu 51a62d723815dad650884714e801421b6d7cb34f91Jack Yu // email list for each ADN record. The key would be 52a62d723815dad650884714e801421b6d7cb34f91Jack Yu // ADN's efid << 8 + record # 53a62d723815dad650884714e801421b6d7cb34f91Jack Yu private SparseArray<ArrayList<String>> mEmailsForAdnRec; 54a62d723815dad650884714e801421b6d7cb34f91Jack Yu 55a62d723815dad650884714e801421b6d7cb34f91Jack Yu // SFI to ADN Efid mapping table 56a62d723815dad650884714e801421b6d7cb34f91Jack Yu private SparseIntArray mSfiEfidTable; 57a62d723815dad650884714e801421b6d7cb34f91Jack Yu 580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mRefreshCache = false; 590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 60a62d723815dad650884714e801421b6d7cb34f91Jack Yu 610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_PBR_LOAD_DONE = 1; 620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_USIM_ADN_LOAD_DONE = 2; 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_IAP_LOAD_DONE = 3; 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_EMAIL_LOAD_DONE = 4; 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_TYPE1_TAG = 0xA8; 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_TYPE2_TAG = 0xA9; 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_TYPE3_TAG = 0xAA; 690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFADN_TAG = 0xC0; 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFIAP_TAG = 0xC1; 710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFEXT1_TAG = 0xC2; 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFSNE_TAG = 0xC3; 730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFANR_TAG = 0xC4; 740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFPBC_TAG = 0xC5; 750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFGRP_TAG = 0xC6; 760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFAAS_TAG = 0xC7; 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFGSD_TAG = 0xC8; 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFUID_TAG = 0xC9; 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFEMAIL_TAG = 0xCA; 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFCCP1_TAG = 0xCB; 810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 82a62d723815dad650884714e801421b6d7cb34f91Jack Yu private static final int INVALID_SFI = -1; 8396cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu private static final byte INVALID_BYTE = -1; 84a62d723815dad650884714e801421b6d7cb34f91Jack Yu 85a62d723815dad650884714e801421b6d7cb34f91Jack Yu // class File represent a PBR record TLV object which points to the rest of the phonebook EFs 86a62d723815dad650884714e801421b6d7cb34f91Jack Yu private class File { 87a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Phonebook reference file constructed tag defined in 3GPP TS 31.102 88a62d723815dad650884714e801421b6d7cb34f91Jack Yu // section 4.4.2.1 table 4.1 89a62d723815dad650884714e801421b6d7cb34f91Jack Yu private final int mParentTag; 90a62d723815dad650884714e801421b6d7cb34f91Jack Yu // EFID of the file 91a62d723815dad650884714e801421b6d7cb34f91Jack Yu private final int mEfid; 92a62d723815dad650884714e801421b6d7cb34f91Jack Yu // SFI (Short File Identification) of the file. 0xFF indicates invalid SFI. 93a62d723815dad650884714e801421b6d7cb34f91Jack Yu private final int mSfi; 94a62d723815dad650884714e801421b6d7cb34f91Jack Yu // The order of this tag showing in the PBR record. 95a62d723815dad650884714e801421b6d7cb34f91Jack Yu private final int mIndex; 96a62d723815dad650884714e801421b6d7cb34f91Jack Yu 97a62d723815dad650884714e801421b6d7cb34f91Jack Yu File(int parentTag, int efid, int sfi, int index) { 98a62d723815dad650884714e801421b6d7cb34f91Jack Yu mParentTag = parentTag; 99a62d723815dad650884714e801421b6d7cb34f91Jack Yu mEfid = efid; 100a62d723815dad650884714e801421b6d7cb34f91Jack Yu mSfi = sfi; 101a62d723815dad650884714e801421b6d7cb34f91Jack Yu mIndex = index; 102a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 103a62d723815dad650884714e801421b6d7cb34f91Jack Yu 104a62d723815dad650884714e801421b6d7cb34f91Jack Yu public int getParentTag() { return mParentTag; } 105a62d723815dad650884714e801421b6d7cb34f91Jack Yu public int getEfid() { return mEfid; } 106a62d723815dad650884714e801421b6d7cb34f91Jack Yu public int getSfi() { return mSfi; } 107a62d723815dad650884714e801421b6d7cb34f91Jack Yu public int getIndex() { return mIndex; } 108a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 109a62d723815dad650884714e801421b6d7cb34f91Jack Yu 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public UsimPhoneBookManager(IccFileHandler fh, AdnRecordCache cache) { 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFh = fh; 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords = new ArrayList<AdnRecord>(); 113a62d723815dad650884714e801421b6d7cb34f91Jack Yu mPbrRecords = null; 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // We assume its present, after the first read this is updated. 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // So we don't have to read from UICC if its not present on subsequent reads. 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIsPbrPresent = true; 1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mAdnCache = cache; 118a62d723815dad650884714e801421b6d7cb34f91Jack Yu mEmailsForAdnRec = new SparseArray<ArrayList<String>>(); 119a62d723815dad650884714e801421b6d7cb34f91Jack Yu mSfiEfidTable = new SparseIntArray(); 1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void reset() { 1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords.clear(); 1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIapFileRecord = null; 1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEmailFileRecord = null; 126a62d723815dad650884714e801421b6d7cb34f91Jack Yu mPbrRecords = null; 1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIsPbrPresent = true; 1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRefreshCache = false; 129a62d723815dad650884714e801421b6d7cb34f91Jack Yu mEmailsForAdnRec.clear(); 130a62d723815dad650884714e801421b6d7cb34f91Jack Yu mSfiEfidTable.clear(); 1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 133a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Load all phonebook related EFs from the SIM. 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public ArrayList<AdnRecord> loadEfFilesFromUsim() { 1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (!mPhoneBookRecords.isEmpty()) { 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mRefreshCache) { 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRefreshCache = false; 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville refreshCache(); 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mPhoneBookRecords; 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (!mIsPbrPresent) return null; 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Check if the PBR file is present in the cache, if not read it 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // from the USIM. 148a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (mPbrRecords == null) { 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readPbrFileAndWait(); 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 152a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (mPbrRecords == null) 153a62d723815dad650884714e801421b6d7cb34f91Jack Yu return null; 154a62d723815dad650884714e801421b6d7cb34f91Jack Yu 155a62d723815dad650884714e801421b6d7cb34f91Jack Yu int numRecs = mPbrRecords.size(); 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 157a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("loadEfFilesFromUsim: Loading adn and emails"); 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numRecs; i++) { 1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readAdnFileAndWait(i); 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readEmailFileAndWait(i); 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 162a62d723815dad650884714e801421b6d7cb34f91Jack Yu 163a62d723815dad650884714e801421b6d7cb34f91Jack Yu updatePhoneAdnRecord(); 164a62d723815dad650884714e801421b6d7cb34f91Jack Yu // All EF files are loaded, return all the records 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mPhoneBookRecords; 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 169a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Refresh the phonebook cache. 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void refreshCache() { 171a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (mPbrRecords == null) return; 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords.clear(); 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 174a62d723815dad650884714e801421b6d7cb34f91Jack Yu int numRecs = mPbrRecords.size(); 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numRecs; i++) { 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readAdnFileAndWait(i); 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 180a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Invalidate the phonebook cache. 1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void invalidateCache() { 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRefreshCache = true; 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 185a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Read the phonebook reference file EF_PBR. 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void readPbrFileAndWait() { 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFh.loadEFLinearFixedAll(EF_PBR, obtainMessage(EVENT_PBR_LOAD_DONE)); 1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.wait(); 1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (InterruptedException e) { 191ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "Interrupted Exception in readAdnFileAndWait"); 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 195a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Read EF_EMAIL which contains the email records. 196a62d723815dad650884714e801421b6d7cb34f91Jack Yu private void readEmailFileAndWait(int recId) { 197a62d723815dad650884714e801421b6d7cb34f91Jack Yu SparseArray<File> files; 198a62d723815dad650884714e801421b6d7cb34f91Jack Yu files = mPbrRecords.get(recId).mFileIds; 199a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (files == null) return; 200a62d723815dad650884714e801421b6d7cb34f91Jack Yu 201a62d723815dad650884714e801421b6d7cb34f91Jack Yu File email = files.get(USIM_EFEMAIL_TAG); 202a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (email != null) { 203a62d723815dad650884714e801421b6d7cb34f91Jack Yu 204a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 205a62d723815dad650884714e801421b6d7cb34f91Jack Yu * Check if the EF_EMAIL is a Type 1 file or a type 2 file. 206a62d723815dad650884714e801421b6d7cb34f91Jack Yu * If mEmailPresentInIap is true, its a type 2 file. 207a62d723815dad650884714e801421b6d7cb34f91Jack Yu * So we read the IAP file and then read the email records. 208a62d723815dad650884714e801421b6d7cb34f91Jack Yu * instead of reading directly. 209a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 210a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (email.getParentTag() == USIM_TYPE2_TAG) { 211a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (files.get(USIM_EFIAP_TAG) == null) { 212a62d723815dad650884714e801421b6d7cb34f91Jack Yu Rlog.e(LOG_TAG, "Can't locate EF_IAP in EF_PBR."); 213a62d723815dad650884714e801421b6d7cb34f91Jack Yu return; 214a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 215a62d723815dad650884714e801421b6d7cb34f91Jack Yu 216a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("EF_IAP exists. Loading EF_IAP to retrieve the index."); 217a62d723815dad650884714e801421b6d7cb34f91Jack Yu readIapFileAndWait(files.get(USIM_EFIAP_TAG).getEfid()); 2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mIapFileRecord == null) { 219ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "Error: IAP file is empty"); 2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 222a62d723815dad650884714e801421b6d7cb34f91Jack Yu 223a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("EF_EMAIL order in PBR record: " + email.getIndex()); 224a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 225a62d723815dad650884714e801421b6d7cb34f91Jack Yu 226a62d723815dad650884714e801421b6d7cb34f91Jack Yu int emailEfid = email.getEfid(); 227a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("EF_EMAIL exists in PBR. efid = 0x" + 228a62d723815dad650884714e801421b6d7cb34f91Jack Yu Integer.toHexString(emailEfid).toUpperCase()); 229a62d723815dad650884714e801421b6d7cb34f91Jack Yu 230a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 231a62d723815dad650884714e801421b6d7cb34f91Jack Yu * Make sure this EF_EMAIL was never read earlier. Sometimes two PBR record points 232a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 233a62d723815dad650884714e801421b6d7cb34f91Jack Yu // to the same EF_EMAIL 234a62d723815dad650884714e801421b6d7cb34f91Jack Yu for (int i = 0; i < recId; i++) { 235a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (mPbrRecords.get(i) != null) { 236a62d723815dad650884714e801421b6d7cb34f91Jack Yu SparseArray<File> previousFileIds = mPbrRecords.get(i).mFileIds; 237a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (previousFileIds != null) { 238a62d723815dad650884714e801421b6d7cb34f91Jack Yu File id = previousFileIds.get(USIM_EFEMAIL_TAG); 239a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (id != null && id.getEfid() == emailEfid) { 240a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("Skipped this EF_EMAIL which was loaded earlier"); 241a62d723815dad650884714e801421b6d7cb34f91Jack Yu return; 242a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 243a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 244a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 246a62d723815dad650884714e801421b6d7cb34f91Jack Yu 2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Read the EFEmail file. 248a62d723815dad650884714e801421b6d7cb34f91Jack Yu mFh.loadEFLinearFixedAll(emailEfid, 2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville obtainMessage(EVENT_EMAIL_LOAD_DONE)); 2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.wait(); 2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (InterruptedException e) { 253ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "Interrupted Exception in readEmailFileAndWait"); 2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mEmailFileRecord == null) { 257ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "Error: Email file is empty"); 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 260a62d723815dad650884714e801421b6d7cb34f91Jack Yu 261a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Build email list 262a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (email.getParentTag() == USIM_TYPE2_TAG && mIapFileRecord != null) { 263a62d723815dad650884714e801421b6d7cb34f91Jack Yu // If the tag is type 2 and EF_IAP exists, we need to build tpe 2 email list 264a62d723815dad650884714e801421b6d7cb34f91Jack Yu buildType2EmailList(recId); 265a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 266a62d723815dad650884714e801421b6d7cb34f91Jack Yu else { 267a62d723815dad650884714e801421b6d7cb34f91Jack Yu // If one the followings is true, we build type 1 email list 268a62d723815dad650884714e801421b6d7cb34f91Jack Yu // 1. EF_IAP does not exist or it is failed to load 269a62d723815dad650884714e801421b6d7cb34f91Jack Yu // 2. ICC cards can be made such that they have an IAP file but all 270a62d723815dad650884714e801421b6d7cb34f91Jack Yu // records are empty. In that case buildType2EmailList will fail and 271a62d723815dad650884714e801421b6d7cb34f91Jack Yu // we need to build type 1 email list. 272a62d723815dad650884714e801421b6d7cb34f91Jack Yu 273a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Build type 1 email list 274a62d723815dad650884714e801421b6d7cb34f91Jack Yu buildType1EmailList(recId); 275a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 277a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 278a62d723815dad650884714e801421b6d7cb34f91Jack Yu 279a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Build type 1 email list 280a62d723815dad650884714e801421b6d7cb34f91Jack Yu private void buildType1EmailList(int recId) { 281a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 282a62d723815dad650884714e801421b6d7cb34f91Jack Yu * If this is type 1, the number of records in EF_EMAIL would be same as the record number 283a62d723815dad650884714e801421b6d7cb34f91Jack Yu * in the master/reference file. 284a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 285a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (mPbrRecords.get(recId) == null) 286a62d723815dad650884714e801421b6d7cb34f91Jack Yu return; 287a62d723815dad650884714e801421b6d7cb34f91Jack Yu 288a62d723815dad650884714e801421b6d7cb34f91Jack Yu int numRecs = mPbrRecords.get(recId).mMasterFileRecordNum; 289a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("Building type 1 email list. recId = " 290a62d723815dad650884714e801421b6d7cb34f91Jack Yu + recId + ", numRecs = " + numRecs); 291a62d723815dad650884714e801421b6d7cb34f91Jack Yu 292a62d723815dad650884714e801421b6d7cb34f91Jack Yu byte[] emailRec; 293a62d723815dad650884714e801421b6d7cb34f91Jack Yu for (int i = 0; i < numRecs; i++) { 294a62d723815dad650884714e801421b6d7cb34f91Jack Yu try { 295a62d723815dad650884714e801421b6d7cb34f91Jack Yu emailRec = mEmailFileRecord.get(i); 296a62d723815dad650884714e801421b6d7cb34f91Jack Yu } catch (IndexOutOfBoundsException e) { 297a62d723815dad650884714e801421b6d7cb34f91Jack Yu Rlog.e(LOG_TAG, "Error: Improper ICC card: No email record for ADN, continuing"); 298a62d723815dad650884714e801421b6d7cb34f91Jack Yu break; 299a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 300a62d723815dad650884714e801421b6d7cb34f91Jack Yu 301a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 302a62d723815dad650884714e801421b6d7cb34f91Jack Yu * 3GPP TS 31.102 4.4.2.13 EF_EMAIL (e-mail address) 303a62d723815dad650884714e801421b6d7cb34f91Jack Yu * 304a62d723815dad650884714e801421b6d7cb34f91Jack Yu * The fields below are mandatory if and only if the file 305a62d723815dad650884714e801421b6d7cb34f91Jack Yu * is not type 1 (as specified in EF_PBR) 306a62d723815dad650884714e801421b6d7cb34f91Jack Yu * 307a62d723815dad650884714e801421b6d7cb34f91Jack Yu * Byte [X + 1]: ADN file SFI (Short File Identification) 308a62d723815dad650884714e801421b6d7cb34f91Jack Yu * Byte [X + 2]: ADN file Record Identifier 309a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 310a62d723815dad650884714e801421b6d7cb34f91Jack Yu int sfi = emailRec[emailRec.length - 2]; 311a62d723815dad650884714e801421b6d7cb34f91Jack Yu int adnRecId = emailRec[emailRec.length - 1]; 312a62d723815dad650884714e801421b6d7cb34f91Jack Yu 313a62d723815dad650884714e801421b6d7cb34f91Jack Yu String email = readEmailRecord(i); 314a62d723815dad650884714e801421b6d7cb34f91Jack Yu 315a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (email == null || email.equals("")) { 316a62d723815dad650884714e801421b6d7cb34f91Jack Yu continue; 317a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 318a62d723815dad650884714e801421b6d7cb34f91Jack Yu 319a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Get the associated ADN's efid first. 320a62d723815dad650884714e801421b6d7cb34f91Jack Yu int adnEfid = 0; 321a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (sfi == INVALID_SFI || mSfiEfidTable.get(sfi) == 0) { 322a62d723815dad650884714e801421b6d7cb34f91Jack Yu 323a62d723815dad650884714e801421b6d7cb34f91Jack Yu // If SFI is invalid or cannot be mapped to any ADN, use the ADN's efid 324a62d723815dad650884714e801421b6d7cb34f91Jack Yu // in the same PBR files. 325a62d723815dad650884714e801421b6d7cb34f91Jack Yu File file = mPbrRecords.get(recId).mFileIds.get(USIM_EFADN_TAG); 326a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (file == null) 327a62d723815dad650884714e801421b6d7cb34f91Jack Yu continue; 328a62d723815dad650884714e801421b6d7cb34f91Jack Yu adnEfid = file.getEfid(); 329a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 330a62d723815dad650884714e801421b6d7cb34f91Jack Yu else { 331a62d723815dad650884714e801421b6d7cb34f91Jack Yu adnEfid = mSfiEfidTable.get(sfi); 332a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 333a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 334a62d723815dad650884714e801421b6d7cb34f91Jack Yu * SIM record numbers are 1 based. 335a62d723815dad650884714e801421b6d7cb34f91Jack Yu * The key is constructed by efid and record index. 336a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 337a62d723815dad650884714e801421b6d7cb34f91Jack Yu int index = (((adnEfid & 0xFFFF) << 8) | ((adnRecId - 1) & 0xFF)); 338a62d723815dad650884714e801421b6d7cb34f91Jack Yu ArrayList<String> emailList = mEmailsForAdnRec.get(index); 339a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (emailList == null) { 340a62d723815dad650884714e801421b6d7cb34f91Jack Yu emailList = new ArrayList<String>(); 341a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 342a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("Adding email #" + i + " list to index 0x" + 343a62d723815dad650884714e801421b6d7cb34f91Jack Yu Integer.toHexString(index).toUpperCase()); 344a62d723815dad650884714e801421b6d7cb34f91Jack Yu emailList.add(email); 345a62d723815dad650884714e801421b6d7cb34f91Jack Yu mEmailsForAdnRec.put(index, emailList); 346a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 347a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 348a62d723815dad650884714e801421b6d7cb34f91Jack Yu 349a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Build type 2 email list 350a62d723815dad650884714e801421b6d7cb34f91Jack Yu private boolean buildType2EmailList(int recId) { 351a62d723815dad650884714e801421b6d7cb34f91Jack Yu 352a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (mPbrRecords.get(recId) == null) 353a62d723815dad650884714e801421b6d7cb34f91Jack Yu return false; 354a62d723815dad650884714e801421b6d7cb34f91Jack Yu 355a62d723815dad650884714e801421b6d7cb34f91Jack Yu int numRecs = mPbrRecords.get(recId).mMasterFileRecordNum; 356a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("Building type 2 email list. recId = " 357a62d723815dad650884714e801421b6d7cb34f91Jack Yu + recId + ", numRecs = " + numRecs); 358a62d723815dad650884714e801421b6d7cb34f91Jack Yu 359a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 360a62d723815dad650884714e801421b6d7cb34f91Jack Yu * 3GPP TS 31.102 4.4.2.1 EF_PBR (Phone Book Reference file) table 4.1 361a62d723815dad650884714e801421b6d7cb34f91Jack Yu 362a62d723815dad650884714e801421b6d7cb34f91Jack Yu * The number of records in the IAP file is same as the number of records in the master 363a62d723815dad650884714e801421b6d7cb34f91Jack Yu * file (e.g EF_ADN). The order of the pointers in an EF_IAP shall be the same as the 364a62d723815dad650884714e801421b6d7cb34f91Jack Yu * order of file IDs that appear in the TLV object indicated by Tag 'A9' in the 365a62d723815dad650884714e801421b6d7cb34f91Jack Yu * reference file record (e.g value of mEmailTagNumberInIap) 366a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 367a62d723815dad650884714e801421b6d7cb34f91Jack Yu 368a62d723815dad650884714e801421b6d7cb34f91Jack Yu File adnFile = mPbrRecords.get(recId).mFileIds.get(USIM_EFADN_TAG); 369a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (adnFile == null) { 370a62d723815dad650884714e801421b6d7cb34f91Jack Yu Rlog.e(LOG_TAG, "Error: Improper ICC card: EF_ADN does not exist in PBR files"); 371a62d723815dad650884714e801421b6d7cb34f91Jack Yu return false; 372a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 373a62d723815dad650884714e801421b6d7cb34f91Jack Yu int adnEfid = adnFile.getEfid(); 374a62d723815dad650884714e801421b6d7cb34f91Jack Yu 375a62d723815dad650884714e801421b6d7cb34f91Jack Yu for (int i = 0; i < numRecs; i++) { 376a62d723815dad650884714e801421b6d7cb34f91Jack Yu byte[] record; 377a62d723815dad650884714e801421b6d7cb34f91Jack Yu int emailRecId; 378a62d723815dad650884714e801421b6d7cb34f91Jack Yu try { 379a62d723815dad650884714e801421b6d7cb34f91Jack Yu record = mIapFileRecord.get(i); 380a62d723815dad650884714e801421b6d7cb34f91Jack Yu emailRecId = 381a62d723815dad650884714e801421b6d7cb34f91Jack Yu record[mPbrRecords.get(recId).mFileIds.get(USIM_EFEMAIL_TAG).getIndex()]; 382a62d723815dad650884714e801421b6d7cb34f91Jack Yu } catch (IndexOutOfBoundsException e) { 383a62d723815dad650884714e801421b6d7cb34f91Jack Yu Rlog.e(LOG_TAG, "Error: Improper ICC card: Corrupted EF_IAP"); 384a62d723815dad650884714e801421b6d7cb34f91Jack Yu continue; 385a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 387a62d723815dad650884714e801421b6d7cb34f91Jack Yu String email = readEmailRecord(emailRecId - 1); 388a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (email != null && !email.equals("")) { 389a62d723815dad650884714e801421b6d7cb34f91Jack Yu // The key is constructed by efid and record index. 390a62d723815dad650884714e801421b6d7cb34f91Jack Yu int index = (((adnEfid & 0xFFFF) << 8) | (i & 0xFF)); 391a62d723815dad650884714e801421b6d7cb34f91Jack Yu ArrayList<String> emailList = mEmailsForAdnRec.get(index); 392a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (emailList == null) { 393a62d723815dad650884714e801421b6d7cb34f91Jack Yu emailList = new ArrayList<String>(); 394a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 395a62d723815dad650884714e801421b6d7cb34f91Jack Yu emailList.add(email); 396a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("Adding email list to index 0x" + 397a62d723815dad650884714e801421b6d7cb34f91Jack Yu Integer.toHexString(index).toUpperCase()); 398a62d723815dad650884714e801421b6d7cb34f91Jack Yu mEmailsForAdnRec.put(index, emailList); 399a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 400a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 401a62d723815dad650884714e801421b6d7cb34f91Jack Yu return true; 4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 404a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Read Phonebook Index Admistration EF_IAP file 4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void readIapFileAndWait(int efid) { 4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFh.loadEFLinearFixedAll(efid, obtainMessage(EVENT_IAP_LOAD_DONE)); 4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.wait(); 4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (InterruptedException e) { 410ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "Interrupted Exception in readIapFileAndWait"); 4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void updatePhoneAdnRecord() { 4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 416a62d723815dad650884714e801421b6d7cb34f91Jack Yu int numAdnRecs = mPhoneBookRecords.size(); 4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numAdnRecs; i++) { 4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AdnRecord rec = mPhoneBookRecords.get(i); 4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 422a62d723815dad650884714e801421b6d7cb34f91Jack Yu int adnEfid = rec.getEfid(); 423a62d723815dad650884714e801421b6d7cb34f91Jack Yu int adnRecId = rec.getRecId(); 4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 425a62d723815dad650884714e801421b6d7cb34f91Jack Yu int index = (((adnEfid & 0xFFFF) << 8) | ((adnRecId - 1) & 0xFF)); 426a62d723815dad650884714e801421b6d7cb34f91Jack Yu 427a62d723815dad650884714e801421b6d7cb34f91Jack Yu ArrayList<String> emailList; 4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 429a62d723815dad650884714e801421b6d7cb34f91Jack Yu emailList = mEmailsForAdnRec.get(index); 4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (IndexOutOfBoundsException e) { 4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville continue; 4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 434a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (emailList == null) 4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville continue; 4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 437a62d723815dad650884714e801421b6d7cb34f91Jack Yu String[] emails = new String[emailList.size()]; 438a62d723815dad650884714e801421b6d7cb34f91Jack Yu System.arraycopy(emailList.toArray(), 0, emails, 0, emailList.size()); 439a62d723815dad650884714e801421b6d7cb34f91Jack Yu rec.setEmails(emails); 440a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("Adding email list to ADN (0x" + 441a62d723815dad650884714e801421b6d7cb34f91Jack Yu Integer.toHexString(mPhoneBookRecords.get(i).getEfid()).toUpperCase() + 442a62d723815dad650884714e801421b6d7cb34f91Jack Yu ") record #" + mPhoneBookRecords.get(i).getRecId()); 443a62d723815dad650884714e801421b6d7cb34f91Jack Yu mPhoneBookRecords.set(i, rec); 4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 447a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Read email from the record of EF_EMAIL 448a62d723815dad650884714e801421b6d7cb34f91Jack Yu private String readEmailRecord(int recId) { 449a62d723815dad650884714e801421b6d7cb34f91Jack Yu byte[] emailRec; 4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 451a62d723815dad650884714e801421b6d7cb34f91Jack Yu emailRec = mEmailFileRecord.get(recId); 4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (IndexOutOfBoundsException e) { 4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return null; 4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // The length of the record is X+2 byte, where X bytes is the email address 457a62d723815dad650884714e801421b6d7cb34f91Jack Yu return IccUtils.adnStringFieldToString(emailRec, 0, emailRec.length - 2); 4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 460a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Read EF_ADN file 461a62d723815dad650884714e801421b6d7cb34f91Jack Yu private void readAdnFileAndWait(int recId) { 462a62d723815dad650884714e801421b6d7cb34f91Jack Yu SparseArray<File> files; 463a62d723815dad650884714e801421b6d7cb34f91Jack Yu files = mPbrRecords.get(recId).mFileIds; 464a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (files == null || files.size() == 0) return; 4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int extEf = 0; 467a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Only call fileIds.get while EF_EXT1_TAG is available 468a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (files.get(USIM_EFEXT1_TAG) != null) { 469a62d723815dad650884714e801421b6d7cb34f91Jack Yu extEf = files.get(USIM_EFEXT1_TAG).getEfid(); 4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 472a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (files.get(USIM_EFADN_TAG) == null) 473a62d723815dad650884714e801421b6d7cb34f91Jack Yu return; 474a62d723815dad650884714e801421b6d7cb34f91Jack Yu 475a62d723815dad650884714e801421b6d7cb34f91Jack Yu int previousSize = mPhoneBookRecords.size(); 476a62d723815dad650884714e801421b6d7cb34f91Jack Yu mAdnCache.requestLoadAllAdnLike(files.get(USIM_EFADN_TAG).getEfid(), 4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville extEf, obtainMessage(EVENT_USIM_ADN_LOAD_DONE)); 4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.wait(); 4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (InterruptedException e) { 481ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville Rlog.e(LOG_TAG, "Interrupted Exception in readAdnFileAndWait"); 4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 483a62d723815dad650884714e801421b6d7cb34f91Jack Yu 484a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 485a62d723815dad650884714e801421b6d7cb34f91Jack Yu * The recent added ADN record # would be the reference record size 486a62d723815dad650884714e801421b6d7cb34f91Jack Yu * for the rest of EFs associated within this PBR. 487a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 488a62d723815dad650884714e801421b6d7cb34f91Jack Yu mPbrRecords.get(recId).mMasterFileRecordNum = mPhoneBookRecords.size() - previousSize; 4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 491a62d723815dad650884714e801421b6d7cb34f91Jack Yu // Create the phonebook reference file based on EF_PBR 4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void createPbrFile(ArrayList<byte[]> records) { 4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (records == null) { 494a62d723815dad650884714e801421b6d7cb34f91Jack Yu mPbrRecords = null; 4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIsPbrPresent = false; 4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 498a62d723815dad650884714e801421b6d7cb34f91Jack Yu 49996cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu mPbrRecords = new ArrayList<PbrRecord>(); 500a62d723815dad650884714e801421b6d7cb34f91Jack Yu for (int i = 0; i < records.size(); i++) { 50196cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu // Some cards have two records but the 2nd record is filled with all invalid char 0xff. 50296cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu // So we need to check if the record is valid or not before adding into the PBR records. 50396cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu if (records.get(i)[0] != INVALID_BYTE) { 50496cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu mPbrRecords.add(new PbrRecord(records.get(i))); 50596cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu } 506a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 507a62d723815dad650884714e801421b6d7cb34f91Jack Yu 508a62d723815dad650884714e801421b6d7cb34f91Jack Yu for (PbrRecord record : mPbrRecords) { 50996cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu File file = record.mFileIds.get(USIM_EFADN_TAG); 51096cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu // If the file does not contain EF_ADN, we'll just skip it. 51196cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu if (file != null) { 51296cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu int sfi = file.getSfi(); 51396cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu if (sfi != INVALID_SFI) { 51496cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu mSfiEfidTable.put(sfi, record.mFileIds.get(USIM_EFADN_TAG).getEfid()); 51596cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu } 51696cf37fcb4f67cbf52df84ca307c76ff9f463791Jack Yu } 517a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 5180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 5210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void handleMessage(Message msg) { 5220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AsyncResult ar; 5230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch(msg.what) { 5250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_PBR_LOAD_DONE: 5260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ar = (AsyncResult) msg.obj; 5270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 5280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville createPbrFile((ArrayList<byte[]>)ar.result); 5290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.notify(); 5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_USIM_ADN_LOAD_DONE: 5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville log("Loading USIM ADN records done"); 5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ar = (AsyncResult) msg.obj; 5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords.addAll((ArrayList<AdnRecord>)ar.result); 5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.notify(); 5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 5440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_IAP_LOAD_DONE: 5450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville log("Loading USIM IAP records done"); 5460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ar = (AsyncResult) msg.obj; 5470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 5480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIapFileRecord = ((ArrayList<byte[]>)ar.result); 5490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 5510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.notify(); 5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_EMAIL_LOAD_DONE: 5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville log("Loading USIM Email records done"); 5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ar = (AsyncResult) msg.obj; 5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEmailFileRecord = ((ArrayList<byte[]>)ar.result); 5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.notify(); 5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 568a62d723815dad650884714e801421b6d7cb34f91Jack Yu // PbrRecord represents a record in EF_PBR 569a62d723815dad650884714e801421b6d7cb34f91Jack Yu private class PbrRecord { 570a62d723815dad650884714e801421b6d7cb34f91Jack Yu // TLV tags 571a62d723815dad650884714e801421b6d7cb34f91Jack Yu private SparseArray<File> mFileIds; 572a62d723815dad650884714e801421b6d7cb34f91Jack Yu 573a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 574a62d723815dad650884714e801421b6d7cb34f91Jack Yu * 3GPP TS 31.102 4.4.2.1 EF_PBR (Phone Book Reference file) 575a62d723815dad650884714e801421b6d7cb34f91Jack Yu * If this is type 1 files, files that contain as many records as the 576a62d723815dad650884714e801421b6d7cb34f91Jack Yu * reference/master file (EF_ADN, EF_ADN1) and are linked on record number 577a62d723815dad650884714e801421b6d7cb34f91Jack Yu * bases (Rec1 -> Rec1). The master file record number is the reference. 578a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 579a62d723815dad650884714e801421b6d7cb34f91Jack Yu private int mMasterFileRecordNum; 580a62d723815dad650884714e801421b6d7cb34f91Jack Yu 581a62d723815dad650884714e801421b6d7cb34f91Jack Yu PbrRecord(byte[] record) { 582a62d723815dad650884714e801421b6d7cb34f91Jack Yu mFileIds = new SparseArray<File>(); 5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SimTlv recTlv; 584a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("PBR rec: " + IccUtils.bytesToHexString(record)); 585a62d723815dad650884714e801421b6d7cb34f91Jack Yu recTlv = new SimTlv(record, 0, record.length); 586a62d723815dad650884714e801421b6d7cb34f91Jack Yu parseTag(recTlv); 5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 589a62d723815dad650884714e801421b6d7cb34f91Jack Yu void parseTag(SimTlv tlv) { 590a62d723815dad650884714e801421b6d7cb34f91Jack Yu SimTlv tlvEfSfi; 5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tag; 5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data; 593a62d723815dad650884714e801421b6d7cb34f91Jack Yu 5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville do { 5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tag = tlv.getTag(); 5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch(tag) { 5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_TYPE1_TAG: // A8 5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_TYPE3_TAG: // AA 5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_TYPE2_TAG: // A9 6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville data = tlv.getData(); 601a62d723815dad650884714e801421b6d7cb34f91Jack Yu tlvEfSfi = new SimTlv(data, 0, data.length); 602a62d723815dad650884714e801421b6d7cb34f91Jack Yu parseEfAndSFI(tlvEfSfi, tag); 6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } while (tlv.nextObject()); 6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 608a62d723815dad650884714e801421b6d7cb34f91Jack Yu void parseEfAndSFI(SimTlv tlv, int parentTag) { 6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tag; 6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data; 6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tagNumberWithinParentTag = 0; 6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville do { 6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tag = tlv.getTag(); 6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch(tag) { 6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFEMAIL_TAG: 6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFADN_TAG: 6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFEXT1_TAG: 6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFANR_TAG: 6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFPBC_TAG: 6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFGRP_TAG: 6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFAAS_TAG: 6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFGSD_TAG: 6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFUID_TAG: 6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFCCP1_TAG: 6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFIAP_TAG: 6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFSNE_TAG: 627a62d723815dad650884714e801421b6d7cb34f91Jack Yu /** 3GPP TS 31.102, 4.4.2.1 EF_PBR (Phone Book Reference file) 628a62d723815dad650884714e801421b6d7cb34f91Jack Yu * 629a62d723815dad650884714e801421b6d7cb34f91Jack Yu * The SFI value assigned to an EF which is indicated in EF_PBR shall 630a62d723815dad650884714e801421b6d7cb34f91Jack Yu * correspond to the SFI indicated in the TLV object in EF_PBR. 631a62d723815dad650884714e801421b6d7cb34f91Jack Yu 632a62d723815dad650884714e801421b6d7cb34f91Jack Yu * The primitive tag identifies clearly the type of data, its value 633a62d723815dad650884714e801421b6d7cb34f91Jack Yu * field indicates the file identifier and, if applicable, the SFI 634a62d723815dad650884714e801421b6d7cb34f91Jack Yu * value of the specified EF. That is, the length value of a primitive 635a62d723815dad650884714e801421b6d7cb34f91Jack Yu * tag indicates if an SFI value is available for the EF or not: 636a62d723815dad650884714e801421b6d7cb34f91Jack Yu * - Length = '02' Value: 'EFID (2 bytes)' 637a62d723815dad650884714e801421b6d7cb34f91Jack Yu * - Length = '03' Value: 'EFID (2 bytes)', 'SFI (1 byte)' 638a62d723815dad650884714e801421b6d7cb34f91Jack Yu */ 639a62d723815dad650884714e801421b6d7cb34f91Jack Yu 640a62d723815dad650884714e801421b6d7cb34f91Jack Yu int sfi = INVALID_SFI; 6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville data = tlv.getData(); 642a62d723815dad650884714e801421b6d7cb34f91Jack Yu 643a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (data.length < 2 || data.length > 3) { 644a62d723815dad650884714e801421b6d7cb34f91Jack Yu log("Invalid TLV length: " + data.length); 645a62d723815dad650884714e801421b6d7cb34f91Jack Yu break; 646a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 647a62d723815dad650884714e801421b6d7cb34f91Jack Yu 648a62d723815dad650884714e801421b6d7cb34f91Jack Yu if (data.length == 3) { 649a62d723815dad650884714e801421b6d7cb34f91Jack Yu sfi = data[2] & 0xFF; 650a62d723815dad650884714e801421b6d7cb34f91Jack Yu } 651a62d723815dad650884714e801421b6d7cb34f91Jack Yu 6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int efid = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF); 653a62d723815dad650884714e801421b6d7cb34f91Jack Yu 654a62d723815dad650884714e801421b6d7cb34f91Jack Yu mFileIds.put(tag, new File(parentTag, efid, sfi, tagNumberWithinParentTag)); 6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 657a62d723815dad650884714e801421b6d7cb34f91Jack Yu tagNumberWithinParentTag++; 6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } while(tlv.nextObject()); 6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void log(String msg) { 663ded9c0af7fa49504c047275ed34c2d3b22bf0c3aWink Saville if(DBG) Rlog.d(LOG_TAG, msg); 6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 665a62d723815dad650884714e801421b6d7cb34f91Jack Yu}