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

Commit 67016a41 authored by Yincheng Zhao's avatar Yincheng Zhao Committed by Gerrit Code Review
Browse files

Merge changes from topic "setFplmn"

* changes:
  Unit test for Set FPLMNs
  Open an API for updating Fplmn
parents a5fbb5dd 7644cdce
Loading
Loading
Loading
Loading
+97 −35
Original line number Diff line number Diff line
@@ -94,6 +94,8 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
    static protected final int EVENT_READ_ICON_DONE = 10;
    /** Finished retrieving size of record for EFimg now. */
    static protected final int EVENT_GET_RECORD_SIZE_IMG_DONE = 11;
    /** Finished retriveing record size of transparent file. */
    protected static final int EVENT_GET_EF_TRANSPARENT_SIZE_DONE = 12;

     // member variables
    @UnsupportedAppUsage
@@ -222,14 +224,13 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
    }

    /**
     * get record size for a linear fixed EF
     * Get record size for a linear fixed EF
     *
     * @param fileid EF id
     * @param path Path of the EF on the card
     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]
     *        int[0] is the record length int[1] is the total length of the EF
     *        file int[3] is the number of records in the EF file So int[0] *
     *        int[3] = int[1]
     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[] int[0] is the
     *     record length int[1] is the total length of the EF file int[3] is the number of records
     *     in the EF file So int[0] * int[3] = int[1]
     */
    @UnsupportedAppUsage
    public void getEFLinearRecordSize(int fileid, String path, Message onLoaded) {
@@ -242,19 +243,51 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
    }

    /**
     * get record size for a linear fixed EF
     * Get record size for a linear fixed EF
     *
     * @param fileid EF id
     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[]
     *        int[0] is the record length int[1] is the total length of the EF
     *        file int[3] is the number of records in the EF file So int[0] *
     *        int[3] = int[1]
     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the recordSize[] int[0] is the
     *     record length int[1] is the total length of the EF file int[3] is the number of records
     *     in the EF file So int[0] * int[3] = int[1]
     */
    @UnsupportedAppUsage
    public void getEFLinearRecordSize(int fileid, Message onLoaded) {
        getEFLinearRecordSize(fileid, getEFPath(fileid), onLoaded);
    }

    /**
     * Get record size for a transparent EF
     *
     * @param fileid EF id
     * @param path Path of the EF on the card
     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the size of data int
     */
    public void getEFTransparentRecordSize(int fileid, String path, Message onLoaded) {
        String efPath = (path == null) ? getEFPath(fileid) : path;
        Message response = obtainMessage(EVENT_GET_EF_TRANSPARENT_SIZE_DONE, fileid, 0, onLoaded);
        mCi.iccIOForApp(
                COMMAND_GET_RESPONSE,
                fileid,
                getEFPath(fileid),
                0,
                0,
                GET_RESPONSE_EF_SIZE_BYTES,
                null,
                null,
                mAid,
                response);
    }

    /**
     * Get record size for a transparent EF
     *
     * @param fileid EF id
     * @param onLoaded ((AsnyncResult)(onLoaded.obj)).result is the size of the data int
     */
    public void getEFTransparentRecordSize(int fileid, Message onLoaded) {
        getEFTransparentRecordSize(fileid, getEFPath(fileid), onLoaded);
    }

    /**
     * Load all records from a SIM Linear Fixed EF
     *
@@ -263,7 +296,6 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
     * @param onLoaded
     *
     * ((AsyncResult)(onLoaded.obj)).result is an ArrayList<byte[]>
     *
     */
    @UnsupportedAppUsage
    public void loadEFLinearFixedAll(int fileid, String path, Message onLoaded) {
@@ -296,9 +328,7 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
     * @param onLoaded
     *
     * ((AsyncResult)(onLoaded.obj)).result is the byte[]
     *
     */

    @UnsupportedAppUsage
    public void loadEFTransparent(int fileid, Message onLoaded) {
        Message response = obtainMessage(EVENT_GET_BINARY_SIZE_DONE,
@@ -473,8 +503,7 @@ public abstract class IccFileHandler extends Handler implements IccConstants {

                recordSize = new int[3];
                recordSize[0] = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;
                recordSize[1] = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
                recordSize[1] = getDataFileSize(data);
                recordSize[2] = recordSize[1] / recordSize[0];

                sendResult(response, recordSize, null);
@@ -505,8 +534,7 @@ public abstract class IccFileHandler extends Handler implements IccConstants {

                lc.mRecordSize = data[RESPONSE_DATA_RECORD_LENGTH] & 0xFF;

                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
                size = getDataFileSize(data);

                lc.mCountRecords = size / lc.mRecordSize;

@@ -549,8 +577,7 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
                    throw new IccFileTypeMismatch();
                }

                size = ((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
                       + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff);
                size = getDataFileSize(data);

                mCi.iccIOForApp(COMMAND_READ_BINARY, fileid, getEFPath(fileid),
                                0, 0, size, null, null, mAid,
@@ -608,6 +635,31 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
                sendResult(response, result.payload, null);
            break;

            case EVENT_GET_EF_TRANSPARENT_SIZE_DONE:
                ar = (AsyncResult) msg.obj;
                response = (Message) ar.userObj;
                result = (IccIoResult) ar.result;

                if (processException(response, (AsyncResult) msg.obj)) {
                    break;
                }

                data = result.payload;

                fileid = msg.arg1;

                if (TYPE_EF != data[RESPONSE_DATA_FILE_TYPE]) {
                    throw new IccFileTypeMismatch();
                }

                if (EF_TYPE_TRANSPARENT != data[RESPONSE_DATA_STRUCTURE]) {
                    throw new IccFileTypeMismatch();
                }

                size = getDataFileSize(data);
                sendResult(response, size, null);
                break;

        }} catch (Exception exc) {
            if (response != null) {
                sendResult(response, null, exc);
@@ -656,4 +708,14 @@ public abstract class IccFileHandler extends Handler implements IccConstants {
    protected abstract void logd(String s);
    protected abstract void loge(String s);

    /**
     * Calculate the size of a data file
     *
     * @param data the raw file
     * @return the size of the file
     */
    private static int getDataFileSize(byte[] data) {
        return (((data[RESPONSE_DATA_FILE_SIZE_1] & 0xff) << 8)
                    + (data[RESPONSE_DATA_FILE_SIZE_2] & 0xff));
    }
}
+30 −12
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.telephony.Rlog;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Pair;

import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.MccTable;
@@ -180,8 +181,7 @@ public abstract class IccRecords extends Handler implements IccConstants {
    protected static final int HANDLER_ACTION_NONE = HANDLER_ACTION_BASE + 0;
    protected static final int HANDLER_ACTION_SEND_RESPONSE = HANDLER_ACTION_BASE + 1;
    protected static AtomicInteger sNextRequestId = new AtomicInteger(1);
    protected final HashMap<Integer, Message> mPendingResponses = new HashMap<>();

    protected final HashMap<Integer, Pair<Message, Object>> mPendingTransactions = new HashMap<>();
    // ***** Constants

    // Markers for mncLength
@@ -343,24 +343,42 @@ public abstract class IccRecords extends Handler implements IccConstants {
    }

    /**
     * Adds a message to the pending requests list by generating a unique
     * (integer) hash key and returning it. The message should never be null.
     * Adds a message to the pending requests list by generating a unique (integer)
     * hash key and returning it. The message should never be null.
     *
     * @param msg Message of the transaction to be stored
     * @return the unique (integer) hash key to retrieve the pending transaction
     */
    public int storePendingTransaction(Message msg) {
        return storePendingTransaction(msg, null);
    }

    /**
     * Adds a message and obj pair to the pending requests list by generating a unique (integer)
     * hash key and returning it. The message should never be null.
     *
     * @param msg Message of the transaction to be stored
     * @param obj Object of the transaction to be stored
     * @return the unique (integer) hash key to retrieve the pending transaction
     */
    public int storePendingResponseMessage(Message msg) {
    public int storePendingTransaction(Message msg, Object obj) {
        int key = sNextRequestId.getAndIncrement();
        synchronized (mPendingResponses) {
            mPendingResponses.put(key, msg);
        Pair<Message, Object> pair = new Pair<Message, Object>(msg, obj);
        synchronized (mPendingTransactions) {
            mPendingTransactions.put(key, pair);
        }
        return key;
    }

    /**
     * Returns the pending request, if any or null
     * Returns the pending transaction and free it from memory, if any or null
     *
     * @param key key of the entry to retrieve
     * @return The pending transaction.
     */
    public Message retrievePendingResponseMessage(Integer key) {
        Message m;
        synchronized (mPendingResponses) {
            return mPendingResponses.remove(key);
    public Pair<Message, Object> retrievePendingTransaction(Integer key) {
        synchronized (mPendingTransactions) {
            return mPendingTransactions.remove(key);
        }
    }

+78 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ import android.telephony.Rlog;
import android.telephony.SmsMessage;
import android.telephony.SubscriptionInfo;
import android.text.TextUtils;
import android.util.Pair;

import com.android.internal.telephony.CommandsInterface;
import com.android.internal.telephony.MccTable;
@@ -135,6 +136,10 @@ public class SIMRecords extends IccRecords {
    private static final int CFIS_ADN_CAPABILITY_ID_OFFSET = 14;
    private static final int CFIS_ADN_EXTENSION_ID_OFFSET = 15;

    // 3GPP specification constants
    // Spec reference TS 31.102 section 4.2.16
    private static final int FPLMN_BYTE_SIZE = 3;

    // ***** Event Constants
    private static final int SIM_RECORD_EVENT_BASE = 0x00;
    private static final int EVENT_GET_IMSI_DONE = 3 + SIM_RECORD_EVENT_BASE;
@@ -169,7 +174,8 @@ public class SIMRecords extends IccRecords {
    private static final int EVENT_GET_HPLMN_W_ACT_DONE = 39 + SIM_RECORD_EVENT_BASE;
    private static final int EVENT_GET_EHPLMN_DONE = 40 + SIM_RECORD_EVENT_BASE;
    private static final int EVENT_GET_FPLMN_DONE = 41 + SIM_RECORD_EVENT_BASE;

    private static final int EVENT_GET_FPLMN_SIZE_DONE = 42 + SIM_RECORD_EVENT_BASE;
    private static final int EVENT_SET_FPLMN_DONE = 43 + SIM_RECORD_EVENT_BASE;
    // ***** Constructor

    public SIMRecords(UiccCardApplication app, Context c, CommandsInterface ci) {
@@ -1194,7 +1200,8 @@ public class SIMRecords extends IccRecords {
                    if (msg.arg1 == HANDLER_ACTION_SEND_RESPONSE) {
                        if (VDBG) logv("getForbiddenPlmns(): send async response");
                        isRecordLoadResponse = false;
                        Message response = retrievePendingResponseMessage(msg.arg2);
                        int key = msg.arg2;
                        Message response = retrievePendingTransaction(key).first;
                        if (response != null) {
                            AsyncResult.forMessage(
                                    response, Arrays.copyOf(mFplmns, mFplmns.length), null);
@@ -1206,6 +1213,60 @@ public class SIMRecords extends IccRecords {
                    }
                    break;

                case EVENT_GET_FPLMN_SIZE_DONE:
                    ar = (AsyncResult) msg.obj;
                    if (ar.exception != null) {
                        Message response = (Message) ar.userObj;
                        AsyncResult.forMessage(response).exception = ar.exception;
                        response.sendToTarget();
                        break;
                    }
                    int key = msg.arg2;
                    Pair<Message, Object> transaction = retrievePendingTransaction(key);
                    Message response = transaction.first;
                    List<String> fplmns = (List<String>) transaction.second;
                    int dataLength = (int) ar.result;
                    if (dataLength < 0 || dataLength % FPLMN_BYTE_SIZE != 0) {
                        loge("Failed to retrieve a correct fplmn size: " + dataLength);
                        AsyncResult.forMessage(response, -1, null);
                        response.sendToTarget();
                        break;
                    }

                    int maxWritebaleFplmns = dataLength / FPLMN_BYTE_SIZE;
                    List<String> fplmnsToWrite;
                    if (fplmns.size() <= maxWritebaleFplmns) {
                        fplmnsToWrite = fplmns;
                    } else {
                        fplmnsToWrite = fplmns.subList(0, maxWritebaleFplmns);
                    }
                    key = storePendingTransaction(response, fplmnsToWrite);
                    byte[] encodededFplmns = IccUtils.encodeFplmns(fplmns, dataLength);
                    mFh.updateEFTransparent(
                            EF_FPLMN,
                            encodededFplmns,
                            obtainMessage(
                                    EVENT_SET_FPLMN_DONE,
                                    msg.arg1,
                                    key));
                    break;

                case EVENT_SET_FPLMN_DONE:
                    ar = (AsyncResult) msg.obj;
                    if (ar.exception != null) {
                        loge("Failed setting Forbidden PLMNs: " + ar.exception);
                    } else {
                        transaction = retrievePendingTransaction(msg.arg2);
                        response = transaction.first;
                        mFplmns = ((List<String>) transaction.second).toArray(new String[0]);
                        if (msg.arg1 == HANDLER_ACTION_SEND_RESPONSE) {
                            AsyncResult.forMessage(response, mFplmns.length, null);
                            response.sendToTarget();
                        }
                        log("Successfully setted fplmns " + ar.result);
                    }
                    break;

                default:
                    super.handleMessage(msg);   // IccRecords handles generic record load responses
            }
@@ -1457,11 +1518,25 @@ public class SIMRecords extends IccRecords {
     * in the result field of an AsyncResult in the response.obj.
     */
    public void getForbiddenPlmns(Message response) {
        int key = storePendingResponseMessage(response);
        int key = storePendingTransaction(response);
        mFh.loadEFTransparent(EF_FPLMN, obtainMessage(
                    EVENT_GET_FPLMN_DONE, HANDLER_ACTION_SEND_RESPONSE, key));
    }

    /**
     * Set the forbidden PLMNs on the sim
     *
     * @param response Response to be send back.
     * @param fplmns List of fplmns to be written to SIM.
     */
    public void setForbiddenPlmns(Message response, List<String> fplmns) {
        int key = storePendingTransaction(response, fplmns);
        mFh.getEFTransparentRecordSize(
                EF_FPLMN,
                obtainMessage(EVENT_GET_FPLMN_SIZE_DONE, HANDLER_ACTION_SEND_RESPONSE, key));
    }


    @Override
    public void onReady() {
        fetchSimRecords();
+18 −0
Original line number Diff line number Diff line
@@ -54,6 +54,11 @@ public class CellIdentityTest extends AndroidTestCase {
    // Latitude ranges from -1296000 to 1296000.
    private static final int LATITUDE = 1296000;

    private static final String PLMN_INVALID_SHORT = "1234";
    private static final String PLMN_INVALID_LONG = "1234567";
    private static final String PLMN_INVALID_NON_NUM = "12a45b";
    private static final String PLMN_VALID = "12345";

    private static final int MAX_LAC = 65535;
    private static final int MAX_CID = 65535;
    private static final int MAX_ARFCN = 65535;
@@ -84,6 +89,7 @@ public class CellIdentityTest extends AndroidTestCase {
        assertEquals(CellInfo.UNAVAILABLE, gsm.getBsic());
    }


    @SmallTest
    public void testEquals() {
        CellIdentity ciA = new CellIdentityLte(
@@ -130,4 +136,16 @@ public class CellIdentityTest extends AndroidTestCase {
        newCi = CellIdentity.CREATOR.createFromParcel(p);
        assertEquals(ci, newCi);
    }

    @SmallTest
    public void testIsValidPlmn() {
        assertTrue(CellIdentity.isValidPlmn(PLMN_VALID));
    }

    @SmallTest
    public void testIsValidPlmnInvalidPlmns() {
        assertFalse(CellIdentity.isValidPlmn(PLMN_INVALID_SHORT));
        assertFalse(CellIdentity.isValidPlmn(PLMN_INVALID_LONG));
        assertFalse(CellIdentity.isValidPlmn(PLMN_INVALID_NON_NUM));
    }
}
+15 −0
Original line number Diff line number Diff line
@@ -30,9 +30,12 @@
package com.android.internal.telephony.uicc;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.mockito.Mockito.*;

import android.os.HandlerThread;
import android.os.Message;
import android.util.Pair;

import com.android.internal.telephony.TelephonyTest;

@@ -92,4 +95,16 @@ public class IccRecordsTest extends TelephonyTest {
        mIccRecords.setImsi("123456ABCDEF");
        assertEquals(mIccRecords.getIMSI(), null);
    }

    @Test
    public void testPendingTansaction() {
        Message msg = Message.obtain();
        Object obj = new Object();
        int key = mIccRecords.storePendingTransaction(msg, obj);
        Pair<Message, Object> pair = mIccRecords.retrievePendingTransaction(key);
        assertEquals(msg, pair.first);
        assertEquals(obj, pair.second);
        pair = mIccRecords.retrievePendingTransaction(key);
        assertNull(pair);
    }
}
Loading