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; 220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.util.Log; 230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.AdnRecord; 250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.AdnRecordCache; 260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccConstants; 270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccFileHandler; 280825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.IccUtils; 290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.PhoneBase; 300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 310825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.ArrayList; 320825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.HashMap; 330825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Map; 340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/** 360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * This class implements reading and parsing USIM records. 370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Refer to Spec 3GPP TS 31.102 for more details. 380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * 390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide} 400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */ 410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class UsimPhoneBookManager extends Handler implements IccConstants { 420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final String LOG_TAG = "GSM"; 430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final boolean DBG = true; 440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private PbrFile mPbrFile; 450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private Boolean mIsPbrPresent; 460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private IccFileHandler mFh; 470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private AdnRecordCache mAdnCache; 480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private Object mLock = new Object(); 490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private ArrayList<AdnRecord> mPhoneBookRecords; 500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mEmailPresentInIap = false; 510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private int mEmailTagNumberInIap = 0; 520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private ArrayList<byte[]> mIapFileRecord; 530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private ArrayList<byte[]> mEmailFileRecord; 540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private Map<Integer, ArrayList<String>> mEmailsForAdnRec; 550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private boolean mRefreshCache = false; 560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_PBR_LOAD_DONE = 1; 580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_USIM_ADN_LOAD_DONE = 2; 590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_IAP_LOAD_DONE = 3; 600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int EVENT_EMAIL_LOAD_DONE = 4; 610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_TYPE1_TAG = 0xA8; 630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_TYPE2_TAG = 0xA9; 640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_TYPE3_TAG = 0xAA; 650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFADN_TAG = 0xC0; 660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFIAP_TAG = 0xC1; 670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFEXT1_TAG = 0xC2; 680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFSNE_TAG = 0xC3; 690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFANR_TAG = 0xC4; 700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFPBC_TAG = 0xC5; 710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFGRP_TAG = 0xC6; 720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFAAS_TAG = 0xC7; 730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFGSD_TAG = 0xC8; 740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFUID_TAG = 0xC9; 750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFEMAIL_TAG = 0xCA; 760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private static final int USIM_EFCCP1_TAG = 0xCB; 770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public UsimPhoneBookManager(IccFileHandler fh, AdnRecordCache cache) { 790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFh = fh; 800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords = new ArrayList<AdnRecord>(); 810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPbrFile = null; 820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // We assume its present, after the first read this is updated. 830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // So we don't have to read from UICC if its not present on subsequent reads. 840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIsPbrPresent = true; 850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mAdnCache = cache; 860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void reset() { 890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords.clear(); 900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIapFileRecord = null; 910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEmailFileRecord = null; 920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPbrFile = null; 930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIsPbrPresent = true; 940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRefreshCache = false; 950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public ArrayList<AdnRecord> loadEfFilesFromUsim() { 980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (!mPhoneBookRecords.isEmpty()) { 1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mRefreshCache) { 1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRefreshCache = false; 1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville refreshCache(); 1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mPhoneBookRecords; 1050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (!mIsPbrPresent) return null; 1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Check if the PBR file is present in the cache, if not read it 1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // from the USIM. 1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mPbrFile == null) { 1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readPbrFileAndWait(); 1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mPbrFile == null) return null; 1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numRecs = mPbrFile.mFileIds.size(); 1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numRecs; i++) { 1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readAdnFileAndWait(i); 1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readEmailFileAndWait(i); 1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // All EF files are loaded, post the response. 1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return mPhoneBookRecords; 1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void refreshCache() { 1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mPbrFile == null) return; 1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords.clear(); 1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numRecs = mPbrFile.mFileIds.size(); 1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numRecs; i++) { 1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readAdnFileAndWait(i); 1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void invalidateCache() { 1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mRefreshCache = true; 1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void readPbrFileAndWait() { 1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFh.loadEFLinearFixedAll(EF_PBR, obtainMessage(EVENT_PBR_LOAD_DONE)); 1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.wait(); 1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (InterruptedException e) { 1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.e(LOG_TAG, "Interrupted Exception in readAdnFileAndWait"); 1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void readEmailFileAndWait(int recNum) { 1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Map <Integer,Integer> fileIds; 1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville fileIds = mPbrFile.mFileIds.get(recNum); 1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (fileIds == null) return; 1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (fileIds.containsKey(USIM_EFEMAIL_TAG)) { 1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int efid = fileIds.get(USIM_EFEMAIL_TAG); 1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Check if the EFEmail is a Type 1 file or a type 2 file. 1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // If mEmailPresentInIap is true, its a type 2 file. 1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // So we read the IAP file and then read the email records. 1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // instead of reading directly. 1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mEmailPresentInIap) { 1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville readIapFileAndWait(fileIds.get(USIM_EFIAP_TAG)); 1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mIapFileRecord == null) { 1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.e(LOG_TAG, "Error: IAP file is empty"); 1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Read the EFEmail file. 1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFh.loadEFLinearFixedAll(fileIds.get(USIM_EFEMAIL_TAG), 1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville obtainMessage(EVENT_EMAIL_LOAD_DONE)); 1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.wait(); 1730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (InterruptedException e) { 1740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.e(LOG_TAG, "Interrupted Exception in readEmailFileAndWait"); 1750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mEmailFileRecord == null) { 1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.e(LOG_TAG, "Error: Email file is empty"); 1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville updatePhoneAdnRecord(); 1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void readIapFileAndWait(int efid) { 1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFh.loadEFLinearFixedAll(efid, obtainMessage(EVENT_IAP_LOAD_DONE)); 1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.wait(); 1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (InterruptedException e) { 1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.e(LOG_TAG, "Interrupted Exception in readIapFileAndWait"); 1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void updatePhoneAdnRecord() { 1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mEmailFileRecord == null) return; 1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int numAdnRecs = mPhoneBookRecords.size(); 1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mIapFileRecord != null) { 1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // The number of records in the IAP file is same as the number of records in ADN file. 2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // The order of the pointers in an EFIAP shall be the same as the order of file IDs 2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // that appear in the TLV object indicated by Tag 'A9' in the reference file record. 2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // i.e value of mEmailTagNumberInIap 2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numAdnRecs; i++) { 2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] record = null; 2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville record = mIapFileRecord.get(i); 2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (IndexOutOfBoundsException e) { 2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.e(LOG_TAG, "Error: Improper ICC card: No IAP record for ADN, continuing"); 2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int recNum = record[mEmailTagNumberInIap]; 2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (recNum != -1) { 2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String[] emails = new String[1]; 2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // SIM record numbers are 1 based 2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville emails[0] = readEmailRecord(recNum - 1); 2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AdnRecord rec = mPhoneBookRecords.get(i); 2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (rec != null) { 2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville rec.setEmails(emails); 2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } else { 2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // might be a record with only email 2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville rec = new AdnRecord("", "", emails); 2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords.set(i, rec); 2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // ICC cards can be made such that they have an IAP file but all 2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // records are empty. So we read both type 1 and type 2 file 2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // email records, just to be sure. 2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int len = mPhoneBookRecords.size(); 2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Type 1 file, the number of records is the same as the number of 2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // records in the ADN file. 2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (mEmailsForAdnRec == null) { 2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville parseType1EmailFile(len); 2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numAdnRecs; i++) { 2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> emailList = null; 2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville emailList = mEmailsForAdnRec.get(i); 2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (IndexOutOfBoundsException e) { 2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (emailList == null) continue; 2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AdnRecord rec = mPhoneBookRecords.get(i); 2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String[] emails = new String[emailList.size()]; 2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville System.arraycopy(emailList.toArray(), 0, emails, 0, emailList.size()); 2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville rec.setEmails(emails); 2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords.set(i, rec); 2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void parseType1EmailFile(int numRecs) { 2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEmailsForAdnRec = new HashMap<Integer, ArrayList<String>>(); 2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] emailRec = null; 2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (int i = 0; i < numRecs; i++) { 2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville emailRec = mEmailFileRecord.get(i); 2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (IndexOutOfBoundsException e) { 2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.e(LOG_TAG, "Error: Improper ICC card: No email record for ADN, continuing"); 2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int adnRecNum = emailRec[emailRec.length - 1]; 2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (adnRecNum == -1) { 2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville continue; 2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String email = readEmailRecord(i); 2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (email == null || email.equals("")) { 2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville continue; 2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // SIM record numbers are 1 based. 2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ArrayList<String> val = mEmailsForAdnRec.get(adnRecNum - 1); 2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (val == null) { 2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville val = new ArrayList<String>(); 2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville val.add(email); 2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // SIM record numbers are 1 based. 2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEmailsForAdnRec.put(adnRecNum - 1, val); 2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private String readEmailRecord(int recNum) { 2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] emailRec = null; 2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville emailRec = mEmailFileRecord.get(recNum); 2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (IndexOutOfBoundsException e) { 2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return null; 2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // The length of the record is X+2 byte, where X bytes is the email address 3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville String email = IccUtils.adnStringFieldToString(emailRec, 0, emailRec.length - 2); 3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return email; 3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void readAdnFileAndWait(int recNum) { 3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Map <Integer,Integer> fileIds; 3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville fileIds = mPbrFile.mFileIds.get(recNum); 3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (fileIds == null || fileIds.isEmpty()) return; 3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int extEf = 0; 3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // Only call fileIds.get while EFEXT1_TAG is available 3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (fileIds.containsKey(USIM_EFEXT1_TAG)) { 3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville extEf = fileIds.get(USIM_EFEXT1_TAG); 3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mAdnCache.requestLoadAllAdnLike(fileIds.get(USIM_EFADN_TAG), 3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville extEf, obtainMessage(EVENT_USIM_ADN_LOAD_DONE)); 3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville try { 3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.wait(); 3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } catch (InterruptedException e) { 3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Log.e(LOG_TAG, "Interrupted Exception in readAdnFileAndWait"); 3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void createPbrFile(ArrayList<byte[]> records) { 3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (records == null) { 3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPbrFile = null; 3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIsPbrPresent = false; 3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville return; 3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPbrFile = new PbrFile(records); 3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville @Override 3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville public void handleMessage(Message msg) { 3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville AsyncResult ar; 3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch(msg.what) { 3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_PBR_LOAD_DONE: 3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ar = (AsyncResult) msg.obj; 3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville createPbrFile((ArrayList<byte[]>)ar.result); 3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.notify(); 3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_USIM_ADN_LOAD_DONE: 3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville log("Loading USIM ADN records done"); 3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ar = (AsyncResult) msg.obj; 3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mPhoneBookRecords.addAll((ArrayList<AdnRecord>)ar.result); 3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.notify(); 3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_IAP_LOAD_DONE: 3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville log("Loading USIM IAP records done"); 3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ar = (AsyncResult) msg.obj; 3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mIapFileRecord = ((ArrayList<byte[]>)ar.result); 3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.notify(); 3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case EVENT_EMAIL_LOAD_DONE: 3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville log("Loading USIM Email records done"); 3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville ar = (AsyncResult) msg.obj; 3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (ar.exception == null) { 3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEmailFileRecord = ((ArrayList<byte[]>)ar.result); 3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville synchronized (mLock) { 3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mLock.notify(); 3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private class PbrFile { 3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville // RecNum <EF Tag, efid> 3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville HashMap<Integer,Map<Integer,Integer>> mFileIds; 3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville PbrFile(ArrayList<byte[]> records) { 3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFileIds = new HashMap<Integer, Map<Integer, Integer>>(); 3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SimTlv recTlv; 3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int recNum = 0; 3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville for (byte[] record: records) { 3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville recTlv = new SimTlv(record, 0, record.length); 3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville parseTag(recTlv, recNum); 3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville recNum ++; 3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void parseTag(SimTlv tlv, int recNum) { 3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville SimTlv tlvEf; 3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tag; 4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data; 4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville Map<Integer, Integer> val = new HashMap<Integer, Integer>(); 4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville do { 4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tag = tlv.getTag(); 4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch(tag) { 4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_TYPE1_TAG: // A8 4060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_TYPE3_TAG: // AA 4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_TYPE2_TAG: // A9 4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville data = tlv.getData(); 4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tlvEf = new SimTlv(data, 0, data.length); 4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville parseEf(tlvEf, val, tag); 4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } while (tlv.nextObject()); 4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mFileIds.put(recNum, val); 4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville void parseEf(SimTlv tlv, Map<Integer, Integer> val, int parentTag) { 4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tag; 4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville byte[] data; 4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int tagNumberWithinParentTag = 0; 4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville do { 4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tag = tlv.getTag(); 4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if (parentTag == USIM_TYPE2_TAG && tag == USIM_EFEMAIL_TAG) { 4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEmailPresentInIap = true; 4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville mEmailTagNumberInIap = tagNumberWithinParentTag; 4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville switch(tag) { 4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFEMAIL_TAG: 4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFADN_TAG: 4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFEXT1_TAG: 4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFANR_TAG: 4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFPBC_TAG: 4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFGRP_TAG: 4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFAAS_TAG: 4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFGSD_TAG: 4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFUID_TAG: 4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFCCP1_TAG: 4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFIAP_TAG: 4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville case USIM_EFSNE_TAG: 4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville data = tlv.getData(); 4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville int efid = ((data[0] & 0xFF) << 8) | (data[1] & 0xFF); 4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville val.put(tag, efid); 4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville break; 4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville tagNumberWithinParentTag ++; 4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } while(tlv.nextObject()); 4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville 4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville private void log(String msg) { 4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville if(DBG) Log.d(LOG_TAG, msg); 4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville } 4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville} 454