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