14baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal/*
24baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Copyright (C) 2014 The Android Open Source Project
34baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
44baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Licensed under the Apache License, Version 2.0 (the "License");
54baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * you may not use this file except in compliance with the License.
64baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * You may obtain a copy of the License at
74baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
84baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *      http://www.apache.org/licenses/LICENSE-2.0
94baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Unless required by applicable law or agreed to in writing, software
114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * distributed under the License is distributed on an "AS IS" BASIS,
124baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * See the License for the specific language governing permissions and
144baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * limitations under the License.
154baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */
164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
174baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalpackage com.android.internal.telephony.uicc;
184baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
19ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastryimport android.annotation.Nullable;
20c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.content.Intent;
21c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.content.pm.PackageInfo;
22c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.content.pm.PackageManager;
23c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.content.pm.ResolveInfo;
244baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.content.pm.Signature;
254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.AsyncResult;
26c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawalimport android.os.Binder;
274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.Handler;
284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.os.Message;
294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.telephony.Rlog;
304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport android.telephony.TelephonyManager;
31277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.telephony.UiccAccessRule;
3288151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liuimport android.text.TextUtils;
334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
34b757d07125d8294062586b5258e4e79d0b8417a3Junda Liuimport com.android.internal.telephony.CommandException;
354baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
3638aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawalimport java.io.FileDescriptor;
3738aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawalimport java.io.PrintWriter;
384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.ArrayList;
399566fe7f15b78503b9e7ce51e27464b523838e28goneilimport java.util.Collections;
404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.List;
414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalimport java.util.Locale;
427f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawalimport java.util.concurrent.atomic.AtomicInteger;
434baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
444baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal/**
454baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * Class that reads and stores the carrier privileged rules from the UICC.
464baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
474baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * The rules are read when the class is created, hence it should only be created
484baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * after the UICC can be read. And it should be deleted when a UICC is changed.
494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
50a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu * Document: https://source.android.com/devices/tech/config/uicc.html
514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal *
524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal * {@hide}
534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal */
544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawalpublic class UiccCarrierPrivilegeRules extends Handler {
554baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String LOG_TAG = "UiccCarrierPrivilegeRules";
56c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu    private static final boolean DBG = false;
574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
58dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie    private static final String ARAM_AID = "A00000015141434C00";
59dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie    private static final String ARAD_AID = "A00000015144414300";
60dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie    private static final int ARAM = 1;
61dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie    private static final int ARAD = 0;
624baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int CLA = 0x80;
637b122b5ef07eca751ca8b6938562737d6e3de2c8Shishir Agrawal    private static final int COMMAND = 0xCA;
647b122b5ef07eca751ca8b6938562737d6e3de2c8Shishir Agrawal    private static final int P1 = 0xFF;
657b122b5ef07eca751ca8b6938562737d6e3de2c8Shishir Agrawal    private static final int P2 = 0x40;
667541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu    private static final int P2_EXTENDED_DATA = 0x60;
674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int P3 = 0x00;
684baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String DATA = "";
694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
70004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    /*
71004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     * Rules format:
72004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   ALL_REF_AR_DO = TAG_ALL_REF_AR_DO + len + [REF_AR_DO]*n
73004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   REF_AR_DO = TAG_REF_AR_DO + len + REF-DO + AR-DO
74004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *
75004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   REF_DO = TAG_REF_DO + len + DEVICE_APP_ID_REF_DO + (optional) PKG_REF_DO
76004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   AR_DO = TAG_AR_DO + len + PERM_AR_DO
77004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *
78c05061bdcff84d8211d51a5080c57f442e4edf74Junda Liu     *   DEVICE_APP_ID_REF_DO = TAG_DEVICE_APP_ID_REF_DO + len + sha256 hexstring of cert
79004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   PKG_REF_DO = TAG_PKG_REF_DO + len + package name
80004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   PERM_AR_DO = TAG_PERM_AR_DO + len + detailed permission (8 bytes)
81004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *
82004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     * Data objects hierarchy by TAG:
83004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     * FF40
84004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *   E2
85004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *     E1
86004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *       C1
87004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *       CA
88004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *     E3
89004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     *       DB
90004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu     */
914baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    // Values from the data standard.
924baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_ALL_REF_AR_DO = "FF40";
934baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_REF_AR_DO = "E2";
944baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_REF_DO = "E1";
954baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_DEVICE_APP_ID_REF_DO = "C1";
964baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final String TAG_PKG_REF_DO = "CA";
97004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    private static final String TAG_AR_DO = "E3";
98004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu    private static final String TAG_PERM_AR_DO = "DB";
99fb41d485d74fba0504e24dd13474d4acdd75a5efCassie    private static final String TAG_AID_REF_DO = "4F";
100fb41d485d74fba0504e24dd13474d4acdd75a5efCassie    private static final String CARRIER_PRIVILEGE_AID = "FFFFFFFFFFFF";
1014baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1024baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 1;
1034baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE = 2;
1044baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 3;
105a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu    private static final int EVENT_PKCS15_READ_DONE = 4;
1064baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1074baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    // State of the object.
1084baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int STATE_LOADING  = 0;
1094baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int STATE_LOADED   = 1;
1104baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private static final int STATE_ERROR    = 2;
1114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
112b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu    // Max number of retries for open logical channel, interval is 10s.
11391e0d7fae8ab78b99ba25aa307ec1a558b5769fcJunda Liu    private static final int MAX_RETRY = 1;
114b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu    private static final int RETRY_INTERVAL_MS = 10000;
115b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu
1164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    // Used for parsing the data from the UICC.
117a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu    public static class TLV {
1187541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        private static final int SINGLE_BYTE_MAX_LENGTH = 0x80;
1194baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        private String tag;
1207541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        // Length encoding is in GPC_Specification_2.2.1: 11.1.5 APDU Message and Data Length.
1217541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        // Length field could be either 1 byte if length < 128, or multiple bytes with first byte
1227541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        // specifying how many bytes are used for length, followed by length bytes.
1237541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        // Bytes for the length field, in ASCII HEX string form.
1247541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        private String lengthBytes;
1257541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        // Decoded length as integer.
1264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        private Integer length;
1274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        private String value;
1284baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1294baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        public TLV(String tag) {
1304baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            this.tag = tag;
1314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
1324baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
133a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu        public String getValue() {
134a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu            if (value == null) return "";
135a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu            return value;
136a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu        }
137a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu
1387541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        public String parseLength(String data) {
1397541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            int offset = tag.length();
1407541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            int firstByte = Integer.parseInt(data.substring(offset, offset + 2), 16);
14164e02b05d7334a9d5704ee2b9f4710a310d9937eIan Pedowitz            if (firstByte < SINGLE_BYTE_MAX_LENGTH) {
1427541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu                length = firstByte * 2;
1437541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu                lengthBytes = data.substring(offset, offset + 2);
1447541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            } else {
1457541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu                int numBytes = firstByte - SINGLE_BYTE_MAX_LENGTH;
1467541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu                length = Integer.parseInt(data.substring(offset + 2, offset + 2 + numBytes * 2), 16) * 2;
1477541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu                lengthBytes = data.substring(offset, offset + 2 + numBytes * 2);
1487541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            }
149c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu            log("TLV parseLength length=" + length + "lenghtBytes: " + lengthBytes);
1507541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            return lengthBytes;
1517541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        }
1527541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu
1534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        public String parse(String data, boolean shouldConsumeAll) {
154c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu            log("Parse TLV: " + tag);
1554baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (!data.startsWith(tag)) {
1564baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new IllegalArgumentException("Tags don't match.");
1574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
1584baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            int index = tag.length();
1594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (index + 2 > data.length()) {
1604baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new IllegalArgumentException("No length.");
1614baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
1624baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1637541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            parseLength(data);
1647541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            index += lengthBytes.length();
1657541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu
166c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu            log("index="+index+" length="+length+"data.length="+data.length());
1674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            int remainingLength = data.length() - (index + length);
1684baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (remainingLength < 0) {
1694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new IllegalArgumentException("Not enough data.");
1704baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
1714baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (shouldConsumeAll && (remainingLength != 0)) {
1724baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new IllegalArgumentException("Did not consume all.");
1734baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
1744baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            value = data.substring(index, index + length);
1754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
176c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu            log("Got TLV: " + tag + "," + length + "," + value);
1774baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1784baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            return data.substring(index + length);
1794baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
1804baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
1814baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
1825b07a62f59800c985a89045fbdb7b91f80b6fb18Amit Mahajan    private UiccProfile mUiccProfile;  // Parent
183a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu    private UiccPkcs15 mUiccPkcs15; // ARF fallback
1844baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    private AtomicInteger mState;
185277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson    private List<UiccAccessRule> mAccessRules;
1867541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu    private String mRules;
187c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal    private Message mLoadedCallback;
18838aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal    private String mStatusMessage;  // Only used for debugging.
1897541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu    private int mChannelId; // Channel Id for communicating with UICC.
190b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu    private int mRetryCount;  // Number of retries for open logical channel.
191dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie    private boolean mCheckedRules = false;  // Flag that used to mark whether get rules from ARA-D.
192dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie    private int mAIDInUse;  // Message component to identify which AID is currently in-use.
193b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu    private final Runnable mRetryRunnable = new Runnable() {
194b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu        @Override
195b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu        public void run() {
196dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie            openChannel(mAIDInUse);
197b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu        }
198b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu    };
199b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu
200dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie    private void openChannel(int aidId) {
201b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu        // Send open logical channel request.
202dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie        String aid = (aidId == ARAD) ? ARAD_AID : ARAM_AID;
20310d75a759b897da1077e3aa21ced4c46698c5552Ajay Nambi        int p2 = 0x00;
2045b07a62f59800c985a89045fbdb7b91f80b6fb18Amit Mahajan        mUiccProfile.iccOpenLogicalChannel(aid, p2, /* supported p2 value */
205dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, 0, aidId, null));
206b757d07125d8294062586b5258e4e79d0b8417a3Junda Liu    }
2074baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
2085b07a62f59800c985a89045fbdb7b91f80b6fb18Amit Mahajan    public UiccCarrierPrivilegeRules(UiccProfile uiccProfile, Message loadedCallback) {
209c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu        log("Creating UiccCarrierPrivilegeRules");
2105b07a62f59800c985a89045fbdb7b91f80b6fb18Amit Mahajan        mUiccProfile = uiccProfile;
2114baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        mState = new AtomicInteger(STATE_LOADING);
21238aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        mStatusMessage = "Not loaded.";
213c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal        mLoadedCallback = loadedCallback;
2147541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        mRules = "";
215277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        mAccessRules = new ArrayList<>();
2164baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
217dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie        // Open logical channel with ARA_D.
218dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie        mAIDInUse = ARAD;
219dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie        openChannel(mAIDInUse);
2204baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
2214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
2224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    /**
223c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal     * Returns true if the carrier privilege rules have finished loading.
224c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal     */
225c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal    public boolean areCarrierPriviligeRulesLoaded() {
226c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal        return mState.get() != STATE_LOADING;
227c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal    }
228c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal
229c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal    /**
230aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani     * Returns true if the carrier privilege rules have finished loading and some rules were
231aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani     * specified.
232aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani     */
233aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani    public boolean hasCarrierPrivilegeRules() {
234aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani        return mState.get() != STATE_LOADING && mAccessRules != null && mAccessRules.size() > 0;
235aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani    }
236aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani
237aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani    /**
23888151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu     * Returns package names for privilege rules.
23988151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu     * Return empty list if no rules defined or package name is empty string.
24088151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu     */
24188151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu    public List<String> getPackageNames() {
24288151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu        List<String> pkgNames = new ArrayList<String>();
24388151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu        if (mAccessRules != null) {
244277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson            for (UiccAccessRule ar : mAccessRules) {
245277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson                if (!TextUtils.isEmpty(ar.getPackageName())) {
246277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson                    pkgNames.add(ar.getPackageName());
24788151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu                }
24888151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu            }
24988151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu        }
25088151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu        return pkgNames;
25188151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu    }
25288151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu
25388151624f06b1a3c7d75d68e2a87cd6c04aab996Junda Liu    /**
2549566fe7f15b78503b9e7ce51e27464b523838e28goneil     * Returns list of access rules.
2559566fe7f15b78503b9e7ce51e27464b523838e28goneil     */
2569566fe7f15b78503b9e7ce51e27464b523838e28goneil    public List<UiccAccessRule> getAccessRules() {
2579566fe7f15b78503b9e7ce51e27464b523838e28goneil        if (mAccessRules == null) {
2589566fe7f15b78503b9e7ce51e27464b523838e28goneil            return Collections.emptyList();
2599566fe7f15b78503b9e7ce51e27464b523838e28goneil        }
2609566fe7f15b78503b9e7ce51e27464b523838e28goneil        return Collections.unmodifiableList(mAccessRules);
2619566fe7f15b78503b9e7ce51e27464b523838e28goneil    }
2629566fe7f15b78503b9e7ce51e27464b523838e28goneil
2639566fe7f15b78503b9e7ce51e27464b523838e28goneil    /**
264c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * Returns the status of the carrier privileges for the input certificate and package name.
2654baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     *
2664baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * @param signature The signature of the certificate.
2674baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * @param packageName name of the package.
2684baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * @return Access status.
2694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     */
270c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    public int getCarrierPrivilegeStatus(Signature signature, String packageName) {
2714baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        int state = mState.get();
2724baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        if (state == STATE_LOADING) {
2734baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
2744baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        } else if (state == STATE_ERROR) {
2754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES;
2764baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
2774baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
278277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        for (UiccAccessRule ar : mAccessRules) {
279277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson            int accessStatus = ar.getCarrierPrivilegeStatus(signature, packageName);
280277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson            if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
281277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson                return accessStatus;
2824baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
2834baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
2844baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
2854baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
2864baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
2874baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
288c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    /**
289c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * Returns the status of the carrier privileges for the input package name.
290c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     *
291c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param packageManager PackageManager for getting signatures.
292c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param packageName name of the package.
293c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @return Access status.
294c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     */
295c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) {
296c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        try {
297aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani            // Short-circuit if there are no rules to check against, so we don't need to fetch
298aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani            // the package info with signatures.
299aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani            if (!hasCarrierPrivilegeRules()) {
300aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani                int state = mState.get();
301aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani                if (state == STATE_LOADING) {
302aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani                    return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
303aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani                } else if (state == STATE_ERROR) {
304aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani                    return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES;
305aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani                }
306aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani                return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
307aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani            }
308cd30338d719dcd77db99766bf21438e494564174Jeff Davidson            // Include DISABLED_UNTIL_USED components. This facilitates cases where a carrier app
309cd30338d719dcd77db99766bf21438e494564174Jeff Davidson            // is disabled by default, and some other component wants to enable it when it has
310cd30338d719dcd77db99766bf21438e494564174Jeff Davidson            // gained carrier privileges (as an indication that a matching SIM has been inserted).
311c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            PackageInfo pInfo = packageManager.getPackageInfo(packageName,
312277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson                    PackageManager.GET_SIGNATURES
313daed5e29637607defb16881eb4bfc17d1d875137Sanry Huang                            | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS);
314aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani            return getCarrierPrivilegeStatus(pInfo);
315c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        } catch (PackageManager.NameNotFoundException ex) {
316b2a8b88ff6ee032bea26eb69cca72e432a7918f9Jeff Davidson            log("Package " + packageName + " not found for carrier privilege status check");
317c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        }
318c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
319c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    }
320c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
321c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    /**
322aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani     * Returns the status of the carrier privileges for the input package info.
323aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani     *
324aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani     * @param packageInfo PackageInfo for the package, containing the package signatures.
325aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani     * @return Access status.
326aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani     */
327aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani    public int getCarrierPrivilegeStatus(PackageInfo packageInfo) {
328277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        int state = mState.get();
329277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        if (state == STATE_LOADING) {
330277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
331277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        } else if (state == STATE_ERROR) {
332277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES;
333277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        }
334277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson
335277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        for (UiccAccessRule ar : mAccessRules) {
336277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson            int accessStatus = ar.getCarrierPrivilegeStatus(packageInfo);
337aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani            if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
338aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani                return accessStatus;
339aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani            }
340aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani        }
341aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
342aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani    }
343aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani
344aeb6df6edf6902d1919bb712fd62bc10f1c623ccAmith Yamasani    /**
345c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * Returns the status of the carrier privileges for the caller of the current transaction.
346c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     *
347c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param packageManager PackageManager for getting signatures and package names.
348c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @return Access status.
349c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     */
350c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) {
351828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson        return getCarrierPrivilegeStatusForUid(packageManager, Binder.getCallingUid());
352828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson    }
353828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson
354828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson    /**
355828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson     * Returns the status of the carrier privileges for the caller of the current transaction.
356828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson     *
357828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson     * @param packageManager PackageManager for getting signatures and package names.
358828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson     * @return Access status.
359828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson     */
360828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson    public int getCarrierPrivilegeStatusForUid(
361828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson            PackageManager packageManager, int uid) {
362828a763161a8e9312052de1864f2f1954dd468c5Jeff Davidson        String[] packages = packageManager.getPackagesForUid(uid);
363c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
364c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        for (String pkg : packages) {
365c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            int accessStatus = getCarrierPrivilegeStatus(packageManager, pkg);
366c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
367c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                return accessStatus;
368c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            }
369c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        }
370c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
371c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    }
372c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
373c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    /**
3747f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal     * Returns the package name of the carrier app that should handle the input intent.
375c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     *
376c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     * @param packageManager PackageManager for getting receivers.
377934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero     * @param intent Intent that will be sent.
3787f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal     * @return list of carrier app package names that can handle the intent.
3797f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal     *         Returns null if there is an error and an empty list if there
3807f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal     *         are no matching packages.
381c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal     */
382934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero    public List<String> getCarrierPackageNamesForIntent(
383c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            PackageManager packageManager, Intent intent) {
3847f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal        List<String> packages = new ArrayList<String>();
385934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero        List<ResolveInfo> receivers = new ArrayList<ResolveInfo>();
386934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero        receivers.addAll(packageManager.queryBroadcastReceivers(intent, 0));
387934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero        receivers.addAll(packageManager.queryIntentContentProviders(intent, 0));
388934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero        receivers.addAll(packageManager.queryIntentActivities(intent, 0));
389934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero        receivers.addAll(packageManager.queryIntentServices(intent, 0));
390934a24a6aa2b7a981e872fa350648904ed80280aDiego Pontoriero
391c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        for (ResolveInfo resolveInfo : receivers) {
392ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry            String packageName = getPackageName(resolveInfo);
393ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry            if (packageName == null) {
394c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal                continue;
395c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            }
396ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry
3977f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal            int status = getCarrierPrivilegeStatus(packageManager, packageName);
3987f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal            if (status == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
3997f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal                packages.add(packageName);
4007f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal            } else if (status != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
4017f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal                // Any status apart from HAS_ACCESS and NO_ACCESS is considered an error.
4027f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal                return null;
403c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal            }
404c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal        }
405c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
4067f1a3f0ab65c144fde56e1246c5747b0c555034aShishir Agrawal        return packages;
407c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal    }
408c9394399180abbc32d04f6a3652ce22d5931e0b8Shishir Agrawal
409ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry    @Nullable
410ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry    private String getPackageName(ResolveInfo resolveInfo) {
411ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry        if (resolveInfo.activityInfo != null) {
412ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry            return resolveInfo.activityInfo.packageName;
413ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry        } else if (resolveInfo.serviceInfo != null) {
414ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry            return resolveInfo.serviceInfo.packageName;
415ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry        } else if (resolveInfo.providerInfo != null) {
416ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry            return resolveInfo.providerInfo.packageName;
417ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry        }
418ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry        return null;
419ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry    }
420ed0cfa93b9e42486bfc7caeca83ceae1a2f7328eAbhijith Shastry
4214baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    @Override
4224baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    public void handleMessage(Message msg) {
4234baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        AsyncResult ar;
424dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie        mAIDInUse = msg.arg2;  // 0 means ARA-D and 1 means ARA-M.
4254baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
4264baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        switch (msg.what) {
4274baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
4287444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson            case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
4297444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                log("EVENT_OPEN_LOGICAL_CHANNEL_DONE");
4307444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                ar = (AsyncResult) msg.obj;
4317444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                if (ar.exception == null && ar.result != null) {
4327444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    mChannelId = ((int[]) ar.result)[0];
4335b07a62f59800c985a89045fbdb7b91f80b6fb18Amit Mahajan                    mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2, P3,
434dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, mChannelId,
435dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                    mAIDInUse));
4367444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                } else {
4377444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    // MISSING_RESOURCE could be due to logical channels temporarily unavailable,
4387444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    // so we retry up to MAX_RETRY times, with an interval of RETRY_INTERVAL_MS.
4397444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    if (ar.exception instanceof CommandException && mRetryCount < MAX_RETRY
4407444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                            && ((CommandException) (ar.exception)).getCommandError()
441dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            == CommandException.Error.MISSING_RESOURCE) {
4427444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                        mRetryCount++;
4437444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                        removeCallbacks(mRetryRunnable);
4447444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                        postDelayed(mRetryRunnable, RETRY_INTERVAL_MS);
4457444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    } else {
446dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                        if (mAIDInUse == ARAD) {
447dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            // Open logical channel with ARA_M.
448dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            mRules = "";
449dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            openChannel(1);
450dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                        }
451dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                        if (mAIDInUse == ARAM) {
452dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            if (mCheckedRules) {
453dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                updateState(STATE_LOADED, "Success!");
454dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            } else {
455dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                // if rules cannot be read from both ARA_D and ARA_M applet,
456dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                // fallback to PKCS15-based ARF.
457dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                log("No ARA, try ARF next.");
4585b07a62f59800c985a89045fbdb7b91f80b6fb18Amit Mahajan                                mUiccPkcs15 = new UiccPkcs15(mUiccProfile,
459dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                        obtainMessage(EVENT_PKCS15_READ_DONE));
460dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            }
461dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                        }
4627444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    }
4637444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                }
4647444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                break;
4657444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson
4667444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson            case EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE:
4677444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                log("EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE");
4687444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                ar = (AsyncResult) msg.obj;
4697444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                if (ar.exception == null && ar.result != null) {
4707444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    IccIoResult response = (IccIoResult) ar.result;
4717444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    if (response.sw1 == 0x90 && response.sw2 == 0x00
4727444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                            && response.payload != null && response.payload.length > 0) {
4737444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                        try {
4747444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                            mRules += IccUtils.bytesToHexString(response.payload)
4757444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                                    .toUpperCase(Locale.US);
4767444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                            if (isDataComplete()) {
477dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                mAccessRules.addAll(parseRules(mRules));
478dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                if (mAIDInUse == ARAD) {
479dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                    mCheckedRules = true;
480dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                } else {
481dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                    updateState(STATE_LOADED, "Success!");
482dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                }
4837444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                            } else {
4845b07a62f59800c985a89045fbdb7b91f80b6fb18Amit Mahajan                                mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND,
4857444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                                        P1, P2_EXTENDED_DATA, P3, DATA,
4867444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                                        obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE,
487dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                                mChannelId, mAIDInUse));
4887444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                                break;
4897444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                            }
4907444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                        } catch (IllegalArgumentException | IndexOutOfBoundsException ex) {
491dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            if (mAIDInUse == ARAM) {
492dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                updateState(STATE_ERROR, "Error parsing rules: " + ex);
493dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            }
4947444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                        }
4957444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    } else {
496dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                        if (mAIDInUse == ARAM) {
497dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            String errorMsg = "Invalid response: payload=" + response.payload
498dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                                    + " sw1=" + response.sw1 + " sw2=" + response.sw2;
499dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                            updateState(STATE_ERROR, errorMsg);
500dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                        }
5017444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    }
5027444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                } else {
503dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                    if (mAIDInUse == ARAM) {
504dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                        updateState(STATE_ERROR, "Error reading value from SIM.");
505dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                    }
5067444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                }
5077444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson
5085b07a62f59800c985a89045fbdb7b91f80b6fb18Amit Mahajan                mUiccProfile.iccCloseLogicalChannel(mChannelId, obtainMessage(
509dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                        EVENT_CLOSE_LOGICAL_CHANNEL_DONE, 0, mAIDInUse));
5107444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                mChannelId = -1;
5117444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                break;
5127444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson
5137444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson            case EVENT_CLOSE_LOGICAL_CHANNEL_DONE:
5147444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                log("EVENT_CLOSE_LOGICAL_CHANNEL_DONE");
515dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                if (mAIDInUse == ARAD) {
516dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                    // Close logical channel with ARA_D and then open logical channel with ARA_M.
517dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                    mRules = "";
518dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                    openChannel(1);
519dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                }
5207444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                break;
5217444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson
5227444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson            case EVENT_PKCS15_READ_DONE:
5237444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                log("EVENT_PKCS15_READ_DONE");
5247444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                if (mUiccPkcs15 == null || mUiccPkcs15.getRules() == null) {
5257444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    updateState(STATE_ERROR, "No ARA or ARF.");
5267444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                } else {
5277444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    for (String cert : mUiccPkcs15.getRules()) {
528277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson                        UiccAccessRule accessRule = new UiccAccessRule(
5297444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                                IccUtils.hexStringToBytes(cert), "", 0x00);
5307444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                        mAccessRules.add(accessRule);
5317444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    }
5327444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                    updateState(STATE_LOADED, "Success!");
5337444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                }
5347444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                break;
5357444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson
5367444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson            default:
5377444a9e9a16749d4653e6038ec81d06f65d0eb85Jeff Davidson                Rlog.e(LOG_TAG, "Unknown event " + msg.what);
5384baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
5394baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
5404baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
5414baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    /*
5427541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu     * Check if all rule bytes have been read from UICC.
5437541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu     * For long payload, we need to fetch it repeatly before start parsing it.
5447541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu     */
5457541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu    private boolean isDataComplete() {
546c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu        log("isDataComplete mRules:" + mRules);
5477541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        if (mRules.startsWith(TAG_ALL_REF_AR_DO)) {
5487541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            TLV allRules = new TLV(TAG_ALL_REF_AR_DO);
5497541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            String lengthBytes = allRules.parseLength(mRules);
550c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu            log("isDataComplete lengthBytes: " + lengthBytes);
5517541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            if (mRules.length() == TAG_ALL_REF_AR_DO.length() + lengthBytes.length() +
552dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                    allRules.length) {
553c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu                log("isDataComplete yes");
5547541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu                return true;
5557541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            } else {
556c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu                log("isDataComplete no");
5577541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu                return false;
5587541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            }
5597541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        } else {
5607541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu            throw new IllegalArgumentException("Tags don't match.");
5617541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu        }
5627541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu    }
5637541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu
5647541d468b7d9464008d6186bc7c1bcef1c925782Junda Liu    /*
5654baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * Parses the rules from the input string.
5664baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     */
567277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson    private static List<UiccAccessRule> parseRules(String rules) {
568c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu        log("Got rules: " + rules);
5694baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
570004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu        TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); //FF40
5714baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        allRefArDo.parse(rules, true);
5724baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
5734baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        String arDos = allRefArDo.value;
574277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        List<UiccAccessRule> accessRules = new ArrayList<>();
5754baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        while (!arDos.isEmpty()) {
576004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu            TLV refArDo = new TLV(TAG_REF_AR_DO); //E2
5774baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            arDos = refArDo.parse(arDos, false);
578277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson            UiccAccessRule accessRule = parseRefArdo(refArDo.value);
57932bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu            if (accessRule != null) {
58032bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                accessRules.add(accessRule);
58132bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu            } else {
582dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                Rlog.e(LOG_TAG, "Skip unrecognized rule." + refArDo.value);
58332bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu            }
5844baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
5854baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        return accessRules;
5864baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
5874baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
5884baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    /*
5894baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     * Parses a single rule.
5904baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal     */
591277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson    private static UiccAccessRule parseRefArdo(String rule) {
592c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu        log("Got rule: " + rule);
5934baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
5944baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        String certificateHash = null;
5954baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        String packageName = null;
596004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu        String tmp = null;
5974baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        long accessType = 0;
5984baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
5994baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        while (!rule.isEmpty()) {
6004baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            if (rule.startsWith(TAG_REF_DO)) {
601004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                TLV refDo = new TLV(TAG_REF_DO); //E1
6024baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                rule = refDo.parse(rule, false);
603fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                // Allow 4F tag with a default value "FF FF FF FF FF FF" to be compatible with
604fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                // devices having GP access control enforcer:
605fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                //  - If no 4F tag is present, it's a CP rule.
606fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                //  - If 4F tag has value "FF FF FF FF FF FF", it's a CP rule.
607fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                //  - If 4F tag has other values, it's not a CP rule and Android should ignore it.
608fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); //C1
609fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                if (refDo.value.startsWith(TAG_AID_REF_DO)) {
610fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    TLV cpDo = new TLV(TAG_AID_REF_DO); //4F
611fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    String remain = cpDo.parse(refDo.value, false);
612fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    if (!cpDo.lengthBytes.equals("06") || !cpDo.value.equals(CARRIER_PRIVILEGE_AID)
613fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                            || remain.isEmpty() || !remain.startsWith(TAG_DEVICE_APP_ID_REF_DO)) {
614fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                        return null;
615fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    }
616fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    tmp = deviceDo.parse(remain, false);
617fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    certificateHash = deviceDo.value;
618fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                } else if (refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) {
619fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    tmp = deviceDo.parse(refDo.value, false);
620fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    certificateHash = deviceDo.value;
621fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                } else {
62232bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                    return null;
62332bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                }
624004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                if (!tmp.isEmpty()) {
625fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    if (!tmp.startsWith(TAG_PKG_REF_DO)) {
626fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                        return null;
627fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    }
628fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    TLV pkgDo = new TLV(TAG_PKG_REF_DO); //CA
629fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    pkgDo.parse(tmp, true);
630fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    packageName = new String(IccUtils.hexStringToBytes(pkgDo.value));
6314baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                } else {
632fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    packageName = null;
6334baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                }
6344baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            } else if (rule.startsWith(TAG_AR_DO)) {
635004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                TLV arDo = new TLV(TAG_AR_DO); //E3
6364baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                rule = arDo.parse(rule, false);
637fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                // Skip all the irrelevant tags (All the optional tags here are two bytes
638fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                // according to the spec GlobalPlatform Secure Element Access Control).
639fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                String remain = arDo.value;
640fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                while (!remain.isEmpty() && !remain.startsWith(TAG_PERM_AR_DO)) {
641fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    TLV tmpDo = new TLV(remain.substring(0, 2));
642fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                    remain = tmpDo.parse(remain, false);
643fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                }
644fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                if (remain.isEmpty()) {
64532bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                    return null;
64632bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                }
647004868eb3f91b06ef7e86b511bbb7b354036834aJunda Liu                TLV permDo = new TLV(TAG_PERM_AR_DO); //DB
648fb41d485d74fba0504e24dd13474d4acdd75a5efCassie                permDo.parse(remain, true);
6494baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            } else  {
65032bbe4213fc554ebf00553cd9935d17fe7530aa1Junda Liu                // Spec requires it must be either TAG_REF_DO or TAG_AR_DO.
6514baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal                throw new RuntimeException("Invalid Rule type");
6524baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal            }
6534baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        }
6544baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
655277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson        UiccAccessRule accessRule = new UiccAccessRule(
656277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson                IccUtils.hexStringToBytes(certificateHash), packageName, accessType);
6574baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal        return accessRule;
6584baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    }
6594baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal
6604baf17fd699249d1b387903b6db7328ad3f7b3e2Shishir Agrawal    /*
661c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal     * Updates the state and notifies the UiccCard that the rules have finished loading.
662c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal     */
66338aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal    private void updateState(int newState, String statusMessage) {
664c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal        mState.set(newState);
665c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal        if (mLoadedCallback != null) {
666c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal            mLoadedCallback.sendToTarget();
667c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal        }
66838aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal
66938aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        mStatusMessage = statusMessage;
670c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu    }
671c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu
672c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu    private static void log(String msg) {
673c3ac6ac3d62e0e1637ff8fddf945953dca60eebaJunda Liu        if (DBG) Rlog.d(LOG_TAG, msg);
67438aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal    }
67538aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal
67638aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal    /**
67738aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal     * Dumps info to Dumpsys - useful for debugging.
67838aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal     */
67938aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
68038aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        pw.println("UiccCarrierPrivilegeRules: " + this);
68138aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        pw.println(" mState=" + getStateString(mState.get()));
68238aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        pw.println(" mStatusMessage='" + mStatusMessage + "'");
68338aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        if (mAccessRules != null) {
68438aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal            pw.println(" mAccessRules: ");
685277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson            for (UiccAccessRule ar : mAccessRules) {
68638aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal                pw.println("  rule='" + ar + "'");
68738aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal            }
68838aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        } else {
68938aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal            pw.println(" mAccessRules: null");
69038aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        }
691a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu        if (mUiccPkcs15 != null) {
692a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu            pw.println(" mUiccPkcs15: " + mUiccPkcs15);
693a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu            mUiccPkcs15.dump(fd, pw, args);
694a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu        } else {
695a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu            pw.println(" mUiccPkcs15: null");
696a4113cd06d2932658ee9e38500a84c1459e27cb8Junda Liu        }
69738aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal        pw.flush();
69838aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal    }
69938aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal
70038aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal    /*
70138aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal     * Converts state into human readable format.
70238aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal     */
70338aa6d75f4edfe03a20826952e41572127bcd6c9Shishir Agrawal    private String getStateString(int state) {
704dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie        switch (state) {
705dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie            case STATE_LOADING:
706dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                return "STATE_LOADING";
707dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie            case STATE_LOADED:
708dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                return "STATE_LOADED";
709dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie            case STATE_ERROR:
710dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                return "STATE_ERROR";
711dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie            default:
712dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie                return "UNKNOWN";
713dff5ca22c114b183d8811f2ea2ec5fb6a0b2121fCassie        }
714c9877fe39ad8f3641d16fd980404916da7f6ce70Shishir Agrawal    }
715b2a8b88ff6ee032bea26eb69cca72e432a7918f9Jeff Davidson}
716