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

Commit 8dad2248 authored by Cassie's avatar Cassie
Browse files

Retrive and interpreted ODF, DODF and ACMF to find the correct path of

ACRF.

Bug: 30613668
Test: runtest frameworks-telephony
Change-Id: I4e24954b075b5a6cf008629efdb4b8e683c40106
parent a837de9a
Loading
Loading
Loading
Loading
+166 −11
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ public class UiccPkcs15 extends Handler {
    private class FileHandler extends Handler {
        // EF path for PKCS15 root, eg. "3F007F50"
        // null if logical channel is used for PKCS15 access.
        private final String mPkcs15Path;
        final String mPkcs15Path;
        // Message to send when file has been parsed.
        private Message mCallback;
        // File id to read data from, eg. "5031"
@@ -90,7 +90,7 @@ public class UiccPkcs15 extends Handler {
        private void readBinary() {
            if (mChannelId >=0 ) {
                mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, 0x00, 0xB0, 0x00, 0x00, 0x00,
                        "", obtainMessage(EVENT_READ_BINARY_DONE));
                        mFileId, obtainMessage(EVENT_READ_BINARY_DONE));
            } else {
                log("EF based");
            }
@@ -200,8 +200,8 @@ public class UiccPkcs15 extends Handler {
                    // ar.result is null if using logical channel,
                    // or string for pkcs15 path if using file access.
                    mFh = new FileHandler((String) ar.result);
                    if (!mFh.loadFile(ID_ACRF, obtainMessage(EVENT_LOAD_ACRF_DONE))) {
                        cleanUp();
                    if (!mFh.loadFile(EFODF_PATH, obtainMessage(EVENT_LOAD_ODF_DONE))) {
                        startFromAcrf();
                    }
                } else {
                    log("select pkcs15 failed: " + ar.exception);
@@ -210,15 +210,48 @@ public class UiccPkcs15 extends Handler {
                }
                break;

            case EVENT_LOAD_ODF_DONE:
                if (ar.exception == null && ar.result != null) {
                    String idDodf = parseOdf((String) ar.result);
                    if (!mFh.loadFile(idDodf, obtainMessage(EVENT_LOAD_DODF_DONE))) {
                        startFromAcrf();
                    }
                } else {
                    startFromAcrf();
                }
                break;

            case EVENT_LOAD_DODF_DONE:
                if (ar.exception == null && ar.result != null) {
                    String idAcmf = parseDodf((String) ar.result);
                    if (!mFh.loadFile(idAcmf, obtainMessage(EVENT_LOAD_ACMF_DONE))) {
                        startFromAcrf();
                    }
                } else {
                    startFromAcrf();
                }
                break;

            case EVENT_LOAD_ACMF_DONE:
                if (ar.exception == null && ar.result != null) {
                    String idAcrf = parseAcmf((String) ar.result);
                    if (!mFh.loadFile(idAcrf, obtainMessage(EVENT_LOAD_ACRF_DONE))) {
                        startFromAcrf();
                    }
                } else {
                    startFromAcrf();
                }
                break;

            case EVENT_LOAD_ACRF_DONE:
                if (ar.exception == null && ar.result != null) {
                    mRules = new ArrayList<String>();
                    mRules = new ArrayList<>();
                    String idAccf = parseAcrf((String) ar.result);
                    if (!mFh.loadFile(idAccf, obtainMessage(EVENT_LOAD_ACCF_DONE))) {
                        cleanUp();
                        startFromAcrf();
                    }
                } else {
                    cleanUp();
                    startFromAcrf();
                }
                break;

@@ -238,6 +271,13 @@ public class UiccPkcs15 extends Handler {
        }
    }

    private void startFromAcrf() {
        log("Fallback to use ACRF_PATH");
        if (!mFh.loadFile(ACRF_PATH, obtainMessage(EVENT_LOAD_ACRF_DONE))) {
            cleanUp();
        }
    }

    private void cleanUp() {
        log("cleanUp");
        if (mChannelId >= 0) {
@@ -250,10 +290,125 @@ public class UiccPkcs15 extends Handler {

    // Constants defined in specs, needed for parsing
    private static final String CARRIER_RULE_AID = "FFFFFFFFFFFF"; // AID for carrier privilege rule
    private static final String ID_ACRF = "4300";
    private static final String ACRF_PATH = "4300";
    private static final String EFODF_PATH = "5031";
    private static final String TAG_ASN_SEQUENCE = "30";
    private static final String TAG_ASN_OCTET_STRING = "04";
    private static final String TAG_ASN_OID = "06";
    private static final String TAG_TARGET_AID = "A0";
    private static final String TAG_ODF = "A7";
    private static final String TAG_DODF = "A1";
    private static final String REFRESH_TAG_LEN = "08";
    // OID defined by Global Platform for the "Access Control". The hexstring here can be converted
    // to OID string value 1.2.840.114283.200.1.1
    public static final String AC_OID = "060A2A864886FC6B81480101";


    // parse ODF file to get file id for DODF file
    // data is hex string, return file id if parse success, null otherwise
    private String parseOdf(String data) {
        // Example:
        // [A7] 06 [30] 04 [04] 02 52 07
        try {
            TLV tlvRule = new TLV(TAG_ODF); // A7
            tlvRule.parse(data, false);
            String ruleString = tlvRule.getValue();
            TLV tlvAsnPath = new TLV(TAG_ASN_SEQUENCE); // 30
            TLV tlvPath = new TLV(TAG_ASN_OCTET_STRING);  // 04
            tlvAsnPath.parse(ruleString, true);
            tlvPath.parse(tlvAsnPath.getValue(), true);
            return tlvPath.getValue();
        } catch (IllegalArgumentException | IndexOutOfBoundsException ex) {
            log("Error: " + ex);
            return null;
        }
    }

    // parse DODF file to get file id for ACMF file
    // data is hex string, return file id if parse success, null otherwise
    private String parseDodf(String data) {
        // Example:
        // [A1] 29 [30] 00 [30] 0F 0C 0D 47 50 20 53 45 20 41 63 63 20 43 74 6C [A1] 14 [30] 12
        // [06] 0A 2A 86 48 86 FC 6B 81 48 01 01 [30] 04 04 02 42 00
        String ret = null;
        String acRules = data;
        while (!acRules.isEmpty()) {
            TLV dodfTag = new TLV(TAG_DODF); // A1
            try {
                acRules = dodfTag.parse(acRules, false);
                String ruleString = dodfTag.getValue();
                // Skip the Common Object Attributes
                TLV commonObjectAttributes = new TLV(TAG_ASN_SEQUENCE); // 30
                ruleString = commonObjectAttributes.parse(ruleString, false);

                // Skip the Common Data Object Attributes
                TLV commonDataObjectAttributes = new TLV(TAG_ASN_SEQUENCE); // 30
                ruleString = commonDataObjectAttributes.parse(ruleString, false);

                if (ruleString.startsWith(TAG_TARGET_AID)) {
                    // Skip SubClassAttributes [Optional]
                    TLV subClassAttributes = new TLV(TAG_TARGET_AID); // A0
                    ruleString = subClassAttributes.parse(ruleString, false);
                }

                if (ruleString.startsWith(TAG_DODF)) {
                    TLV oidDoTag = new TLV(TAG_DODF); // A1
                    oidDoTag.parse(ruleString, true);
                    ruleString = oidDoTag.getValue();

                    TLV oidDo = new TLV(TAG_ASN_SEQUENCE); // 30
                    oidDo.parse(ruleString, true);
                    ruleString = oidDo.getValue();

                    TLV oidTag = new TLV(TAG_ASN_OID); // 06
                    oidTag.parse(ruleString, false);
                    // Example : [06] 0A 2A 86 48 86 FC 6B 81 48 01 01
                    String oid = oidTag.getValue();
                    if (oid.equals(AC_OID)) {
                        // Skip OID and get the AC to the ACCM
                        ruleString = oidTag.parse(ruleString, false);
                        TLV tlvAsnPath = new TLV(TAG_ASN_SEQUENCE); // 30
                        TLV tlvPath = new TLV(TAG_ASN_OCTET_STRING);  // 04
                        tlvAsnPath.parse(ruleString, true);
                        tlvPath.parse(tlvAsnPath.getValue(), true);
                        return tlvPath.getValue();
                    }
                }
                continue; // skip current rule as it doesn't have expected TAG
            } catch (IllegalArgumentException | IndexOutOfBoundsException ex) {
                log("Error: " + ex);
                break; // Bad data, ignore all remaining ACRules
            }
        }
        return ret;
    }

    // parse ACMF file to get file id for ACRF file
    // data is hex string, return file id if parse success, null otherwise
    private String parseAcmf(String data) {
        try {
            // [30] 10 [04] 08 01 02 03 04 05 06 07 08 [30] 04 [04] 02 43 00
            TLV acmfTag = new TLV(TAG_ASN_SEQUENCE); // 30
            acmfTag.parse(data, false);
            String ruleString = acmfTag.getValue();
            TLV refreshTag = new TLV(TAG_ASN_OCTET_STRING); // 04
            String refreshTagLength = refreshTag.parseLength(ruleString);
            if (!refreshTagLength.equals(REFRESH_TAG_LEN)) {
                log("Error: refresh tag in ACMF must be 8.");
                return null;
            }
            ruleString = refreshTag.parse(ruleString, false);
            TLV tlvAsnPath = new TLV(TAG_ASN_SEQUENCE); // 30
            TLV tlvPath = new TLV(TAG_ASN_OCTET_STRING);  // 04
            tlvAsnPath.parse(ruleString, true);
            tlvPath.parse(tlvAsnPath.getValue(), true);
            return tlvPath.getValue();
        } catch (IllegalArgumentException | IndexOutOfBoundsException ex) {
            log("Error: " + ex);
            return null;
        }

    }

    // parse ACRF file to get file id for ACCF file
    // data is hex string, return file id if parse success, null otherwise
@@ -262,14 +417,14 @@ public class UiccPkcs15 extends Handler {

        String acRules = data;
        while (!acRules.isEmpty()) {
            // Example:
            // [30] 10 [A0] 08 04 06 FF FF FF FF FF FF [30] 04 [04] 02 43 10
            // bytes in [] are tags for the data
            TLV tlvRule = new TLV(TAG_ASN_SEQUENCE);
            try {
                acRules = tlvRule.parse(acRules, false);
                String ruleString = tlvRule.getValue();
                if (ruleString.startsWith(TAG_TARGET_AID)) {
                    // rule string consists of target AID + path, example:
                    // [A0] 08 [04] 06 FF FF FF FF FF FF [30] 04 [04] 02 43 10
                    // bytes in [] are tags for the data
                    TLV tlvTarget = new TLV(TAG_TARGET_AID); // A0
                    TLV tlvAid = new TLV(TAG_ASN_OCTET_STRING); // 04
                    TLV tlvAsnPath = new TLV(TAG_ASN_SEQUENCE); // 30
+285 −5
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.doAnswer;
import android.content.pm.Signature;
import android.os.AsyncResult;
import android.os.Message;
import android.telephony.UiccAccessRule;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -41,11 +42,17 @@ import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;

import java.util.List;

@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {
    private UiccCarrierPrivilegeRules mUiccCarrierPrivilegeRules;

    private static final String ARAM = "A00000015141434C00";
    private static final String ARAD = "A00000015144414300";
    private static final String PKCS15_AID = "A000000063504B43532D3135";

    @Mock
    private UiccProfile mUiccProfile;

@@ -289,10 +296,6 @@ public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {
        assertTrue(!mUiccCarrierPrivilegeRules.shouldRetry(ar, 0));
    }

    private static final String ARAM = "A00000015141434C00";
    private static final String ARAD = "A00000015144414300";
    private static final String PKCS15_AID = "A000000063504B43532D3135";

    @Test
    @SmallTest
    public void testAID_OnlyARAM() {
@@ -476,7 +479,7 @@ public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {

    @Test
    @SmallTest
    public void testAID_NeitherARAMorARAD() {
    public void testAID_ARFFailed() {
        final String hexString =
                "FF4045E243E135C114ABCD92CBB156B280FA4E1429A6ECEEB6E5C1BFE4CA1D636F6D2E676F6F676"
                        + "C652E616E64726F69642E617070732E6D79617070E30ADB080000000000000001";
@@ -515,8 +518,285 @@ public class UiccCarrierPrivilegeRulesTest extends TelephonyTest {
        assertTrue(!mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
    }

    @Test
    @SmallTest
    public void testAID_ARFSucceed() {
        /**
         * PKCS#15 application (AID: A0 00 00 00 63 50 4B 43 53 2D 31 35)
         *   -ODF (5031)
         *       A7 06 30 04 04 02 52 07
         *   -DODF (5207)
         *       A1 29 30 00 30 0F 0C 0D 47 50 20 53 45 20 41 63 63 20 43 74 6C A1 14 30 12
         *       06 0A 2A 86 48 86 FC 6B 81 48 01 01 30 04 04 02 42 00
         *   -EF ACMain (4200)
         *       30 10 04 08 01 02 03 04 05 06 07 08 30 04 04 02 43 00
         *   -EF ACRules (4300)
         *       30 10 A0 08 04 06 A0 00 00 01 51 01 30 04 04 02 43 10
         *   -EF ACConditions1 (4310)
         *       30 22
         *          04 20
         *             B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51465350
         *       30 22
         *          04 20
         *             4C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859
         */
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                String aid = (String) invocation.getArguments()[0];
                Message message = (Message) invocation.getArguments()[2];
                AsyncResult ar = new AsyncResult(null, null, null);
                if (aid.equals(ARAM)) {
                    message.arg2 = 1;
                } else if (aid.equals(ARAD)) {
                    message.arg2 = 0;
                } else {
                    // PKCS15
                    ar = new AsyncResult(null, new int[]{2}, null);
                }
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccOpenLogicalChannel(anyString(), anyInt(), any(Message.class));

        // Select files
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                AsyncResult ar = new AsyncResult(null, new int[]{2}, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xA4), eq(0x00),
                eq(0x04), eq(0x02), anyString(), any(Message.class));

        // Read binary - ODF
        String odf = "A706300404025207";
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(odf));
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
                eq(0x00), eq(0x00), eq("5031"), any(Message.class));

        // Read binary - DODF
        String dodf =
                "A1293000300F0C0D4750205345204163632043746CA11"
                        + "43012060A2A864886FC6B81480101300404024200";
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(dodf));
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
                eq(0x00), eq(0x00), eq("5207"), any(Message.class));

        // Read binary - ACMF
        String acmf = "301004080102030405060708300404024300";
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(acmf));
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
                eq(0x00), eq(0x00), eq("4200"), any(Message.class));

        // Read binary - ACRF
        String acrf = "3010A0080406FFFFFFFFFFFF300404024310";
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(acrf));
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
                eq(0x00), eq(0x00), eq("4300"), any(Message.class));

        // Read binary - ACCF
        String accf =
                "30220420B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB514653503022042"
                        + "04C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859";
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(accf));
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
                eq(0x00), eq(0x00), eq("4310"), any(Message.class));


        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[1];
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccCloseLogicalChannel(anyInt(), any(Message.class));

        mUiccCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(mUiccProfile, null);
        processAllMessages();

        assertTrue(mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
        assertEquals(2, mUiccCarrierPrivilegeRules.getAccessRules().size());
        List<UiccAccessRule> accessRules = mUiccCarrierPrivilegeRules.getAccessRules();
        UiccAccessRule accessRule1 = new UiccAccessRule(
                IccUtils.hexStringToBytes(
                        "B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51465350"),
                "",
                0x00);
        assertTrue(accessRules.contains(accessRule1));
        UiccAccessRule accessRule2 = new UiccAccessRule(
                IccUtils.hexStringToBytes(
                        "4C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859"),
                "",
                0x00);
        assertTrue(accessRules.contains(accessRule2));
    }

    @Test
    @SmallTest
    public void testAID_ARFFallbackToACRF() {
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                String aid = (String) invocation.getArguments()[0];
                Message message = (Message) invocation.getArguments()[2];
                AsyncResult ar = new AsyncResult(null, null, null);
                if (aid.equals(ARAM)) {
                    message.arg2 = 1;
                } else if (aid.equals(ARAD)) {
                    message.arg2 = 0;
                } else {
                    // PKCS15
                    ar = new AsyncResult(null, new int[]{2}, null);
                }
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccOpenLogicalChannel(anyString(), anyInt(), any(Message.class));

        // Select files
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                AsyncResult ar = new AsyncResult(null, new int[]{2}, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xA4), eq(0x00),
                eq(0x04), eq(0x02), anyString(), any(Message.class));

        // Read binary ODF failed
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, new byte[]{});
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
                eq(0x00), eq(0x00), eq("5031"), any(Message.class));

        // Read binary - ACRF
        String acrf = "3010A0080406FFFFFFFFFFFF300404024310";
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(acrf));
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
                eq(0x00), eq(0x00), eq("4300"), any(Message.class));

        // Read binary - ACCF
        String accf =
                "30220420B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB514653503022042"
                        + "04C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859";
        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[7];
                IccIoResult iir = new IccIoResult(0x90, 0x00, IccUtils.hexStringToBytes(accf));
                AsyncResult ar = new AsyncResult(null, iir, null);
                message.obj = ar;
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccTransmitApduLogicalChannel(anyInt(), eq(0x00), eq(0xB0), eq(0x00),
                eq(0x00), eq(0x00), eq("4310"), any(Message.class));


        doAnswer(new Answer<Void>() {
            @Override
            public Void answer(InvocationOnMock invocation) throws Throwable {
                Message message = (Message) invocation.getArguments()[1];
                message.sendToTarget();
                return null;
            }
        }).when(mUiccProfile).iccCloseLogicalChannel(anyInt(), any(Message.class));

        mUiccCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(mUiccProfile, null);
        processAllMessages();

        assertTrue(mUiccCarrierPrivilegeRules.hasCarrierPrivilegeRules());
        assertEquals(2, mUiccCarrierPrivilegeRules.getAccessRules().size());
        List<UiccAccessRule> accessRules = mUiccCarrierPrivilegeRules.getAccessRules();
        UiccAccessRule accessRule1 = new UiccAccessRule(
                IccUtils.hexStringToBytes(
                        "B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51465350"),
                "",
                0x00);
        assertTrue(accessRules.contains(accessRule1));
        UiccAccessRule accessRule2 = new UiccAccessRule(
                IccUtils.hexStringToBytes(
                        "4C36AF4A5BDAD97C1F3D8B283416D244496C2AC5EAFE8226079EF6F676FD1859"),
                "",
                0x00);
        assertTrue(accessRules.contains(accessRule2));
    }

    private static final int P2 = 0x40;
    private static final int P2_EXTENDED_DATA = 0x60;

    @Test
    @SmallTest
    public void testAID_RetransmitLogicalChannel() {