Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34efc39f authored by Jaikumar Ganesh's avatar Jaikumar Ganesh
Browse files

Implement USIM and add support for importing emails from USIM.

Refer to 3GPP Spec 31.102 for more details.
We read and parse USIM records instead of the RIL doing it for us.
We only support reading of USIM Phonebook records.
parent 19d6f7ac
Loading
Loading
Loading
Loading
+39 −12
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@ import android.util.Log;

import com.android.internal.telephony.GsmAlphabet;

import java.util.Arrays;


/**
 *
@@ -38,6 +40,7 @@ public class AdnRecord implements Parcelable {

    String alphaTag = "";
    String number = "";
    String[] emails;
    int extRecord = 0xff;
    int efid;                   // or 0 if none
    int recordNumber;           // or 0 if none
@@ -74,13 +77,15 @@ public class AdnRecord implements Parcelable {
            int recordNumber;
            String alphaTag;
            String number;
            String[] emails;

            efid = source.readInt();
            recordNumber = source.readInt();
            alphaTag = source.readString();
            number = source.readString();
            emails = source.readStringArray();

            return new AdnRecord(efid, recordNumber, alphaTag, number);
            return new AdnRecord(efid, recordNumber, alphaTag, number, emails);
        }

        public AdnRecord[] newArray(int size) {
@@ -90,29 +95,38 @@ public class AdnRecord implements Parcelable {


    //***** Constructor
    public
    AdnRecord (byte[] record) {
    public AdnRecord (byte[] record) {
        this(0, 0, record);
    }

    public
    AdnRecord (int efid, int recordNumber, byte[] record) {
    public AdnRecord (int efid, int recordNumber, byte[] record) {
        this.efid = efid;
        this.recordNumber = recordNumber;
        parseRecord(record);
    }

    public
    AdnRecord (String alphaTag, String number) {
    public AdnRecord (String alphaTag, String number) {
        this(0, 0, alphaTag, number);
    }

    public
    AdnRecord (int efid, int recordNumber, String alphaTag, String number) {
    public AdnRecord (String alphaTag, String number, String[] emails) {
        this(0, 0, alphaTag, number, emails);
    }

    public AdnRecord (int efid, int recordNumber, String alphaTag, String number, String[] emails) {
        this.efid = efid;
        this.recordNumber = recordNumber;
        this.alphaTag = alphaTag;
        this.number = number;
        this.emails = emails;
    }

    public AdnRecord(int efid, int recordNumber, String alphaTag, String number) {
        this.efid = efid;
        this.recordNumber = recordNumber;
        this.alphaTag = alphaTag;
        this.number = number;
        this.emails = null;
    }

    //***** Instance Methods
@@ -125,12 +139,20 @@ public class AdnRecord implements Parcelable {
        return number;
    }

    public String[] getEmails() {
        return emails;
    }

    public void setEmails(String[] emails) {
        this.emails = emails;
    }

    public String toString() {
        return "ADN Record '" + alphaTag + "' '" + number + "'";
        return "ADN Record '" + alphaTag + "' '" + number + " " + emails + "'";
    }

    public boolean isEmpty() {
        return alphaTag.equals("") && number.equals("");
        return alphaTag.equals("") && number.equals("") && emails == null;
    }

    public boolean hasExtendedRecord() {
@@ -139,7 +161,8 @@ public class AdnRecord implements Parcelable {

    public boolean isEqual(AdnRecord adn) {
        return ( alphaTag.equals(adn.getAlphaTag()) &&
                number.equals(adn.getNumber()) );
                number.equals(adn.getNumber()) &&
                Arrays.equals(emails, adn.getEmails()));
    }
    //***** Parcelable Implementation

@@ -152,6 +175,7 @@ public class AdnRecord implements Parcelable {
        dest.writeInt(recordNumber);
        dest.writeString(alphaTag);
        dest.writeString(number);
        dest.writeStringArray(emails);
    }

    /**
@@ -274,10 +298,13 @@ public class AdnRecord implements Parcelable {

            extRecord = 0xff & record[record.length - 1];

            emails = null;

        } catch (RuntimeException ex) {
            Log.w(LOG_TAG, "Error parsing AdnRecord", ex);
            number = "";
            alphaTag = "";
            emails = null;
        }
    }
}
+21 −13
Original line number Diff line number Diff line
@@ -16,14 +16,16 @@

package com.android.internal.telephony;

import android.util.SparseArray;
import android.util.Log;
import android.os.Message;
import android.os.Handler;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.SparseArray;

import com.android.internal.telephony.gsm.UsimPhoneBookManager;

import java.util.ArrayList;
import java.util.Iterator;
import com.android.internal.telephony.IccConstants;

/**
 * {@hide}
@@ -32,6 +34,7 @@ public final class AdnRecordCache extends Handler implements IccConstants {
    //***** Instance Variables

    PhoneBase phone;
    private UsimPhoneBookManager mUsimPhoneBookManager;

    // Indexed by EF ID
    SparseArray<ArrayList<AdnRecord>> adnLikeFiles
@@ -55,6 +58,7 @@ public final class AdnRecordCache extends Handler implements IccConstants {

    public AdnRecordCache(PhoneBase phone) {
        this.phone = phone;
        mUsimPhoneBookManager = new UsimPhoneBookManager(phone, this);
    }

    //***** Called from SIMRecords
@@ -64,6 +68,7 @@ public final class AdnRecordCache extends Handler implements IccConstants {
     */
    public void reset() {
        adnLikeFiles.clear();
        mUsimPhoneBookManager.reset();

        clearWaiters();
        clearUserWriters();
@@ -103,14 +108,14 @@ public final class AdnRecordCache extends Handler implements IccConstants {
     *
     * See 3GPP TS 51.011 for this mapping
     */
    private int
    extensionEfForEf(int efid) {
    int extensionEfForEf(int efid) {
        switch (efid) {
            case EF_MBDN: return EF_EXT6;
            case EF_ADN: return EF_EXT1;
            case EF_SDN: return EF_EXT3;
            case EF_FDN: return EF_EXT2;
            case EF_MSISDN: return EF_EXT1;
            case EF_PBR: return 0; // The EF PBR doesn't have an extension record
            default: return -1;
        }
    }
@@ -223,11 +228,15 @@ public final class AdnRecordCache extends Handler implements IccConstants {
     * record
     */
    public void
    requestLoadAllAdnLike (int efid, Message response) {
    requestLoadAllAdnLike (int efid, int extensionEf, Message response) {
        ArrayList<Message> waiters;
        ArrayList<AdnRecord> result;

        if (efid == EF_PBR) {
            result = mUsimPhoneBookManager.loadEfFilesFromUsim();
        } else {
            result = getRecordsIfLoaded(efid);
        }

        // Have we already loaded this efid?
        if (result != null) {
@@ -258,9 +267,8 @@ public final class AdnRecordCache extends Handler implements IccConstants {

        adnLikeWaiters.put(efid, waiters);

        int extensionEF = extensionEfForEf(efid);

        if (extensionEF < 0) {
        if (extensionEf < 0) {
            // respond with error if not known ADN-like record

            if (response != null) {
@@ -272,7 +280,7 @@ public final class AdnRecordCache extends Handler implements IccConstants {
            return;
        }

        new AdnRecordLoader(phone).loadAllFromEF(efid, extensionEF,
        new AdnRecordLoader(phone).loadAllFromEF(efid, extensionEf,
            obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE, efid, 0));
    }

@@ -311,7 +319,7 @@ public final class AdnRecordCache extends Handler implements IccConstants {
                adnLikeWaiters.delete(efid);

                if (ar.exception == null) {
                    adnLikeFiles.put(efid, (ArrayList<AdnRecord>) (ar.result));
                    adnLikeFiles.put(efid, (ArrayList<AdnRecord>) ar.result);
                }
                notifyWaiters(waiters, ar);
                break;
+1 −1
Original line number Diff line number Diff line
@@ -655,7 +655,7 @@ public abstract class IccCard {
    }


    public boolean hasApplicationType(IccCardApplication.AppType type) {
    public boolean isApplicationOnIcc(IccCardApplication.AppType type) {
        if (mIccCardStatus == null) return false;

        for (int i = 0 ; i < mIccCardStatus.getNumApplications(); i++) {
+4 −0
Original line number Diff line number Diff line
@@ -42,6 +42,9 @@ public interface IccConstants {
    static final int EF_CFIS = 0x6FCB;
    static final int EF_IMG = 0x4f20;

    // USIM SIM file ids from TS 31.102
    public static final int EF_PBR = 0x4F30;

    // GSM SIM file ids from CPHS (phase 2, version 4.2) CPHS4_2.WW6
    static final int EF_MAILBOX_CPHS = 0x6F17;
    static final int EF_VOICE_MAIL_INDICATOR_CPHS = 0x6F11;
@@ -59,6 +62,7 @@ public interface IccConstants {

    static final String MF_SIM = "3F00";
    static final String DF_TELECOM = "7F10";
    static final String DF_PHONEBOOK = "5F3A";
    static final String DF_GRAPHICS = "5F50";
    static final String DF_GSM = "7F20";
    static final String DF_CDMA = "7F25";
+16 −3
Original line number Diff line number Diff line
@@ -115,7 +115,8 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
     * Replace oldAdn with newAdn in ADN-like record in EF
     *
     * getAdnRecordsInEf must be called at least once before this function,
     * otherwise an error will be returned
     * otherwise an error will be returned. Currently the email field
     * if set in the ADN record is ignored.
     * throws SecurityException if no WRITE_CONTACTS permission
     *
     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
@@ -167,7 +168,8 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
     * Update an ADN-like EF record by record index
     *
     * This is useful for iteration the whole ADN file, such as write the whole
     * phone book or erase/format the whole phonebook
     * phone book or erase/format the whole phonebook. Currently the email field
     * if set in the ADN record is ignored.
     * throws SecurityException if no WRITE_CONTACTS permission
     *
     * @param efid must be one among EF_ADN, EF_FDN, and EF_SDN
@@ -237,12 +239,13 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
                    "Requires android.permission.READ_CONTACTS permission");
        }

        efid = updateEfForIccType(efid);
        if (DBG) logd("getAdnRecordsInEF: efid=" + efid);

        synchronized(mLock) {
            checkThread();
            Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE);
            adnCache.requestLoadAllAdnLike(efid, response);
            adnCache.requestLoadAllAdnLike(efid, adnCache.extensionEfForEf(efid), response);
            try {
                mLock.wait();
            } catch (InterruptedException e) {
@@ -262,5 +265,15 @@ public abstract class IccPhoneBookInterfaceManager extends IIccPhoneBook.Stub {
            }
        }
    }

    private int updateEfForIccType(int efid) {
        // Check if we are trying to read ADN records
        if (efid == IccConstants.EF_ADN) {
            if (phone.getIccCard().isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) {
                return IccConstants.EF_PBR;
            }
        }
        return efid;
    }
}
Loading