1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.internal.telephony.uicc;
18
19import android.annotation.Nullable;
20import android.content.Intent;
21import android.content.pm.PackageInfo;
22import android.content.pm.PackageManager;
23import android.content.pm.ResolveInfo;
24import android.content.pm.Signature;
25import android.os.AsyncResult;
26import android.os.Binder;
27import android.os.Handler;
28import android.os.Message;
29import android.telephony.Rlog;
30import android.telephony.TelephonyManager;
31import android.telephony.UiccAccessRule;
32import android.text.TextUtils;
33
34import com.android.internal.telephony.CommandException;
35
36import java.io.FileDescriptor;
37import java.io.PrintWriter;
38import java.util.ArrayList;
39import java.util.Collections;
40import java.util.List;
41import java.util.Locale;
42import java.util.concurrent.atomic.AtomicInteger;
43
44/**
45 * Class that reads and stores the carrier privileged rules from the UICC.
46 *
47 * The rules are read when the class is created, hence it should only be created
48 * after the UICC can be read. And it should be deleted when a UICC is changed.
49 *
50 * Document: https://source.android.com/devices/tech/config/uicc.html
51 *
52 * {@hide}
53 */
54public class UiccCarrierPrivilegeRules extends Handler {
55    private static final String LOG_TAG = "UiccCarrierPrivilegeRules";
56    private static final boolean DBG = false;
57
58    private static final String ARAM_AID = "A00000015141434C00";
59    private static final String ARAD_AID = "A00000015144414300";
60    private static final int ARAM = 1;
61    private static final int ARAD = 0;
62    private static final int CLA = 0x80;
63    private static final int COMMAND = 0xCA;
64    private static final int P1 = 0xFF;
65    private static final int P2 = 0x40;
66    private static final int P2_EXTENDED_DATA = 0x60;
67    private static final int P3 = 0x00;
68    private static final String DATA = "";
69
70    /*
71     * Rules format:
72     *   ALL_REF_AR_DO = TAG_ALL_REF_AR_DO + len + [REF_AR_DO]*n
73     *   REF_AR_DO = TAG_REF_AR_DO + len + REF-DO + AR-DO
74     *
75     *   REF_DO = TAG_REF_DO + len + DEVICE_APP_ID_REF_DO + (optional) PKG_REF_DO
76     *   AR_DO = TAG_AR_DO + len + PERM_AR_DO
77     *
78     *   DEVICE_APP_ID_REF_DO = TAG_DEVICE_APP_ID_REF_DO + len + sha256 hexstring of cert
79     *   PKG_REF_DO = TAG_PKG_REF_DO + len + package name
80     *   PERM_AR_DO = TAG_PERM_AR_DO + len + detailed permission (8 bytes)
81     *
82     * Data objects hierarchy by TAG:
83     * FF40
84     *   E2
85     *     E1
86     *       C1
87     *       CA
88     *     E3
89     *       DB
90     */
91    // Values from the data standard.
92    private static final String TAG_ALL_REF_AR_DO = "FF40";
93    private static final String TAG_REF_AR_DO = "E2";
94    private static final String TAG_REF_DO = "E1";
95    private static final String TAG_DEVICE_APP_ID_REF_DO = "C1";
96    private static final String TAG_PKG_REF_DO = "CA";
97    private static final String TAG_AR_DO = "E3";
98    private static final String TAG_PERM_AR_DO = "DB";
99    private static final String TAG_AID_REF_DO = "4F";
100    private static final String CARRIER_PRIVILEGE_AID = "FFFFFFFFFFFF";
101
102    private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 1;
103    private static final int EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE = 2;
104    private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 3;
105    private static final int EVENT_PKCS15_READ_DONE = 4;
106
107    // State of the object.
108    private static final int STATE_LOADING  = 0;
109    private static final int STATE_LOADED   = 1;
110    private static final int STATE_ERROR    = 2;
111
112    // Max number of retries for open logical channel, interval is 10s.
113    private static final int MAX_RETRY = 1;
114    private static final int RETRY_INTERVAL_MS = 10000;
115
116    // Used for parsing the data from the UICC.
117    public static class TLV {
118        private static final int SINGLE_BYTE_MAX_LENGTH = 0x80;
119        private String tag;
120        // Length encoding is in GPC_Specification_2.2.1: 11.1.5 APDU Message and Data Length.
121        // Length field could be either 1 byte if length < 128, or multiple bytes with first byte
122        // specifying how many bytes are used for length, followed by length bytes.
123        // Bytes for the length field, in ASCII HEX string form.
124        private String lengthBytes;
125        // Decoded length as integer.
126        private Integer length;
127        private String value;
128
129        public TLV(String tag) {
130            this.tag = tag;
131        }
132
133        public String getValue() {
134            if (value == null) return "";
135            return value;
136        }
137
138        public String parseLength(String data) {
139            int offset = tag.length();
140            int firstByte = Integer.parseInt(data.substring(offset, offset + 2), 16);
141            if (firstByte < SINGLE_BYTE_MAX_LENGTH) {
142                length = firstByte * 2;
143                lengthBytes = data.substring(offset, offset + 2);
144            } else {
145                int numBytes = firstByte - SINGLE_BYTE_MAX_LENGTH;
146                length = Integer.parseInt(data.substring(offset + 2, offset + 2 + numBytes * 2), 16) * 2;
147                lengthBytes = data.substring(offset, offset + 2 + numBytes * 2);
148            }
149            log("TLV parseLength length=" + length + "lenghtBytes: " + lengthBytes);
150            return lengthBytes;
151        }
152
153        public String parse(String data, boolean shouldConsumeAll) {
154            log("Parse TLV: " + tag);
155            if (!data.startsWith(tag)) {
156                throw new IllegalArgumentException("Tags don't match.");
157            }
158            int index = tag.length();
159            if (index + 2 > data.length()) {
160                throw new IllegalArgumentException("No length.");
161            }
162
163            parseLength(data);
164            index += lengthBytes.length();
165
166            log("index="+index+" length="+length+"data.length="+data.length());
167            int remainingLength = data.length() - (index + length);
168            if (remainingLength < 0) {
169                throw new IllegalArgumentException("Not enough data.");
170            }
171            if (shouldConsumeAll && (remainingLength != 0)) {
172                throw new IllegalArgumentException("Did not consume all.");
173            }
174            value = data.substring(index, index + length);
175
176            log("Got TLV: " + tag + "," + length + "," + value);
177
178            return data.substring(index + length);
179        }
180    }
181
182    private UiccProfile mUiccProfile;  // Parent
183    private UiccPkcs15 mUiccPkcs15; // ARF fallback
184    private AtomicInteger mState;
185    private List<UiccAccessRule> mAccessRules;
186    private String mRules;
187    private Message mLoadedCallback;
188    private String mStatusMessage;  // Only used for debugging.
189    private int mChannelId; // Channel Id for communicating with UICC.
190    private int mRetryCount;  // Number of retries for open logical channel.
191    private boolean mCheckedRules = false;  // Flag that used to mark whether get rules from ARA-D.
192    private int mAIDInUse;  // Message component to identify which AID is currently in-use.
193    private final Runnable mRetryRunnable = new Runnable() {
194        @Override
195        public void run() {
196            openChannel(mAIDInUse);
197        }
198    };
199
200    private void openChannel(int aidId) {
201        // Send open logical channel request.
202        String aid = (aidId == ARAD) ? ARAD_AID : ARAM_AID;
203        int p2 = 0x00;
204        mUiccProfile.iccOpenLogicalChannel(aid, p2, /* supported p2 value */
205                obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, 0, aidId, null));
206    }
207
208    public UiccCarrierPrivilegeRules(UiccProfile uiccProfile, Message loadedCallback) {
209        log("Creating UiccCarrierPrivilegeRules");
210        mUiccProfile = uiccProfile;
211        mState = new AtomicInteger(STATE_LOADING);
212        mStatusMessage = "Not loaded.";
213        mLoadedCallback = loadedCallback;
214        mRules = "";
215        mAccessRules = new ArrayList<>();
216
217        // Open logical channel with ARA_D.
218        mAIDInUse = ARAD;
219        openChannel(mAIDInUse);
220    }
221
222    /**
223     * Returns true if the carrier privilege rules have finished loading.
224     */
225    public boolean areCarrierPriviligeRulesLoaded() {
226        return mState.get() != STATE_LOADING;
227    }
228
229    /**
230     * Returns true if the carrier privilege rules have finished loading and some rules were
231     * specified.
232     */
233    public boolean hasCarrierPrivilegeRules() {
234        return mState.get() != STATE_LOADING && mAccessRules != null && mAccessRules.size() > 0;
235    }
236
237    /**
238     * Returns package names for privilege rules.
239     * Return empty list if no rules defined or package name is empty string.
240     */
241    public List<String> getPackageNames() {
242        List<String> pkgNames = new ArrayList<String>();
243        if (mAccessRules != null) {
244            for (UiccAccessRule ar : mAccessRules) {
245                if (!TextUtils.isEmpty(ar.getPackageName())) {
246                    pkgNames.add(ar.getPackageName());
247                }
248            }
249        }
250        return pkgNames;
251    }
252
253    /**
254     * Returns list of access rules.
255     */
256    public List<UiccAccessRule> getAccessRules() {
257        if (mAccessRules == null) {
258            return Collections.emptyList();
259        }
260        return Collections.unmodifiableList(mAccessRules);
261    }
262
263    /**
264     * Returns the status of the carrier privileges for the input certificate and package name.
265     *
266     * @param signature The signature of the certificate.
267     * @param packageName name of the package.
268     * @return Access status.
269     */
270    public int getCarrierPrivilegeStatus(Signature signature, String packageName) {
271        int state = mState.get();
272        if (state == STATE_LOADING) {
273            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
274        } else if (state == STATE_ERROR) {
275            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES;
276        }
277
278        for (UiccAccessRule ar : mAccessRules) {
279            int accessStatus = ar.getCarrierPrivilegeStatus(signature, packageName);
280            if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
281                return accessStatus;
282            }
283        }
284
285        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
286    }
287
288    /**
289     * Returns the status of the carrier privileges for the input package name.
290     *
291     * @param packageManager PackageManager for getting signatures.
292     * @param packageName name of the package.
293     * @return Access status.
294     */
295    public int getCarrierPrivilegeStatus(PackageManager packageManager, String packageName) {
296        try {
297            // Short-circuit if there are no rules to check against, so we don't need to fetch
298            // the package info with signatures.
299            if (!hasCarrierPrivilegeRules()) {
300                int state = mState.get();
301                if (state == STATE_LOADING) {
302                    return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
303                } else if (state == STATE_ERROR) {
304                    return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES;
305                }
306                return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
307            }
308            // Include DISABLED_UNTIL_USED components. This facilitates cases where a carrier app
309            // is disabled by default, and some other component wants to enable it when it has
310            // gained carrier privileges (as an indication that a matching SIM has been inserted).
311            PackageInfo pInfo = packageManager.getPackageInfo(packageName,
312                    PackageManager.GET_SIGNATURES
313                            | PackageManager.MATCH_DISABLED_UNTIL_USED_COMPONENTS);
314            return getCarrierPrivilegeStatus(pInfo);
315        } catch (PackageManager.NameNotFoundException ex) {
316            log("Package " + packageName + " not found for carrier privilege status check");
317        }
318        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
319    }
320
321    /**
322     * Returns the status of the carrier privileges for the input package info.
323     *
324     * @param packageInfo PackageInfo for the package, containing the package signatures.
325     * @return Access status.
326     */
327    public int getCarrierPrivilegeStatus(PackageInfo packageInfo) {
328        int state = mState.get();
329        if (state == STATE_LOADING) {
330            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_RULES_NOT_LOADED;
331        } else if (state == STATE_ERROR) {
332            return TelephonyManager.CARRIER_PRIVILEGE_STATUS_ERROR_LOADING_RULES;
333        }
334
335        for (UiccAccessRule ar : mAccessRules) {
336            int accessStatus = ar.getCarrierPrivilegeStatus(packageInfo);
337            if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
338                return accessStatus;
339            }
340        }
341        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
342    }
343
344    /**
345     * Returns the status of the carrier privileges for the caller of the current transaction.
346     *
347     * @param packageManager PackageManager for getting signatures and package names.
348     * @return Access status.
349     */
350    public int getCarrierPrivilegeStatusForCurrentTransaction(PackageManager packageManager) {
351        return getCarrierPrivilegeStatusForUid(packageManager, Binder.getCallingUid());
352    }
353
354    /**
355     * Returns the status of the carrier privileges for the caller of the current transaction.
356     *
357     * @param packageManager PackageManager for getting signatures and package names.
358     * @return Access status.
359     */
360    public int getCarrierPrivilegeStatusForUid(
361            PackageManager packageManager, int uid) {
362        String[] packages = packageManager.getPackagesForUid(uid);
363
364        for (String pkg : packages) {
365            int accessStatus = getCarrierPrivilegeStatus(packageManager, pkg);
366            if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
367                return accessStatus;
368            }
369        }
370        return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS;
371    }
372
373    /**
374     * Returns the package name of the carrier app that should handle the input intent.
375     *
376     * @param packageManager PackageManager for getting receivers.
377     * @param intent Intent that will be sent.
378     * @return list of carrier app package names that can handle the intent.
379     *         Returns null if there is an error and an empty list if there
380     *         are no matching packages.
381     */
382    public List<String> getCarrierPackageNamesForIntent(
383            PackageManager packageManager, Intent intent) {
384        List<String> packages = new ArrayList<String>();
385        List<ResolveInfo> receivers = new ArrayList<ResolveInfo>();
386        receivers.addAll(packageManager.queryBroadcastReceivers(intent, 0));
387        receivers.addAll(packageManager.queryIntentContentProviders(intent, 0));
388        receivers.addAll(packageManager.queryIntentActivities(intent, 0));
389        receivers.addAll(packageManager.queryIntentServices(intent, 0));
390
391        for (ResolveInfo resolveInfo : receivers) {
392            String packageName = getPackageName(resolveInfo);
393            if (packageName == null) {
394                continue;
395            }
396
397            int status = getCarrierPrivilegeStatus(packageManager, packageName);
398            if (status == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
399                packages.add(packageName);
400            } else if (status != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) {
401                // Any status apart from HAS_ACCESS and NO_ACCESS is considered an error.
402                return null;
403            }
404        }
405
406        return packages;
407    }
408
409    @Nullable
410    private String getPackageName(ResolveInfo resolveInfo) {
411        if (resolveInfo.activityInfo != null) {
412            return resolveInfo.activityInfo.packageName;
413        } else if (resolveInfo.serviceInfo != null) {
414            return resolveInfo.serviceInfo.packageName;
415        } else if (resolveInfo.providerInfo != null) {
416            return resolveInfo.providerInfo.packageName;
417        }
418        return null;
419    }
420
421    @Override
422    public void handleMessage(Message msg) {
423        AsyncResult ar;
424        mAIDInUse = msg.arg2;  // 0 means ARA-D and 1 means ARA-M.
425
426        switch (msg.what) {
427
428            case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
429                log("EVENT_OPEN_LOGICAL_CHANNEL_DONE");
430                ar = (AsyncResult) msg.obj;
431                if (ar.exception == null && ar.result != null) {
432                    mChannelId = ((int[]) ar.result)[0];
433                    mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND, P1, P2, P3,
434                            DATA, obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE, mChannelId,
435                                    mAIDInUse));
436                } else {
437                    // MISSING_RESOURCE could be due to logical channels temporarily unavailable,
438                    // so we retry up to MAX_RETRY times, with an interval of RETRY_INTERVAL_MS.
439                    if (ar.exception instanceof CommandException && mRetryCount < MAX_RETRY
440                            && ((CommandException) (ar.exception)).getCommandError()
441                            == CommandException.Error.MISSING_RESOURCE) {
442                        mRetryCount++;
443                        removeCallbacks(mRetryRunnable);
444                        postDelayed(mRetryRunnable, RETRY_INTERVAL_MS);
445                    } else {
446                        if (mAIDInUse == ARAD) {
447                            // Open logical channel with ARA_M.
448                            mRules = "";
449                            openChannel(1);
450                        }
451                        if (mAIDInUse == ARAM) {
452                            if (mCheckedRules) {
453                                updateState(STATE_LOADED, "Success!");
454                            } else {
455                                // if rules cannot be read from both ARA_D and ARA_M applet,
456                                // fallback to PKCS15-based ARF.
457                                log("No ARA, try ARF next.");
458                                mUiccPkcs15 = new UiccPkcs15(mUiccProfile,
459                                        obtainMessage(EVENT_PKCS15_READ_DONE));
460                            }
461                        }
462                    }
463                }
464                break;
465
466            case EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE:
467                log("EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE");
468                ar = (AsyncResult) msg.obj;
469                if (ar.exception == null && ar.result != null) {
470                    IccIoResult response = (IccIoResult) ar.result;
471                    if (response.sw1 == 0x90 && response.sw2 == 0x00
472                            && response.payload != null && response.payload.length > 0) {
473                        try {
474                            mRules += IccUtils.bytesToHexString(response.payload)
475                                    .toUpperCase(Locale.US);
476                            if (isDataComplete()) {
477                                mAccessRules.addAll(parseRules(mRules));
478                                if (mAIDInUse == ARAD) {
479                                    mCheckedRules = true;
480                                } else {
481                                    updateState(STATE_LOADED, "Success!");
482                                }
483                            } else {
484                                mUiccProfile.iccTransmitApduLogicalChannel(mChannelId, CLA, COMMAND,
485                                        P1, P2_EXTENDED_DATA, P3, DATA,
486                                        obtainMessage(EVENT_TRANSMIT_LOGICAL_CHANNEL_DONE,
487                                                mChannelId, mAIDInUse));
488                                break;
489                            }
490                        } catch (IllegalArgumentException | IndexOutOfBoundsException ex) {
491                            if (mAIDInUse == ARAM) {
492                                updateState(STATE_ERROR, "Error parsing rules: " + ex);
493                            }
494                        }
495                    } else {
496                        if (mAIDInUse == ARAM) {
497                            String errorMsg = "Invalid response: payload=" + response.payload
498                                    + " sw1=" + response.sw1 + " sw2=" + response.sw2;
499                            updateState(STATE_ERROR, errorMsg);
500                        }
501                    }
502                } else {
503                    if (mAIDInUse == ARAM) {
504                        updateState(STATE_ERROR, "Error reading value from SIM.");
505                    }
506                }
507
508                mUiccProfile.iccCloseLogicalChannel(mChannelId, obtainMessage(
509                        EVENT_CLOSE_LOGICAL_CHANNEL_DONE, 0, mAIDInUse));
510                mChannelId = -1;
511                break;
512
513            case EVENT_CLOSE_LOGICAL_CHANNEL_DONE:
514                log("EVENT_CLOSE_LOGICAL_CHANNEL_DONE");
515                if (mAIDInUse == ARAD) {
516                    // Close logical channel with ARA_D and then open logical channel with ARA_M.
517                    mRules = "";
518                    openChannel(1);
519                }
520                break;
521
522            case EVENT_PKCS15_READ_DONE:
523                log("EVENT_PKCS15_READ_DONE");
524                if (mUiccPkcs15 == null || mUiccPkcs15.getRules() == null) {
525                    updateState(STATE_ERROR, "No ARA or ARF.");
526                } else {
527                    for (String cert : mUiccPkcs15.getRules()) {
528                        UiccAccessRule accessRule = new UiccAccessRule(
529                                IccUtils.hexStringToBytes(cert), "", 0x00);
530                        mAccessRules.add(accessRule);
531                    }
532                    updateState(STATE_LOADED, "Success!");
533                }
534                break;
535
536            default:
537                Rlog.e(LOG_TAG, "Unknown event " + msg.what);
538        }
539    }
540
541    /*
542     * Check if all rule bytes have been read from UICC.
543     * For long payload, we need to fetch it repeatly before start parsing it.
544     */
545    private boolean isDataComplete() {
546        log("isDataComplete mRules:" + mRules);
547        if (mRules.startsWith(TAG_ALL_REF_AR_DO)) {
548            TLV allRules = new TLV(TAG_ALL_REF_AR_DO);
549            String lengthBytes = allRules.parseLength(mRules);
550            log("isDataComplete lengthBytes: " + lengthBytes);
551            if (mRules.length() == TAG_ALL_REF_AR_DO.length() + lengthBytes.length() +
552                    allRules.length) {
553                log("isDataComplete yes");
554                return true;
555            } else {
556                log("isDataComplete no");
557                return false;
558            }
559        } else {
560            throw new IllegalArgumentException("Tags don't match.");
561        }
562    }
563
564    /*
565     * Parses the rules from the input string.
566     */
567    private static List<UiccAccessRule> parseRules(String rules) {
568        log("Got rules: " + rules);
569
570        TLV allRefArDo = new TLV(TAG_ALL_REF_AR_DO); //FF40
571        allRefArDo.parse(rules, true);
572
573        String arDos = allRefArDo.value;
574        List<UiccAccessRule> accessRules = new ArrayList<>();
575        while (!arDos.isEmpty()) {
576            TLV refArDo = new TLV(TAG_REF_AR_DO); //E2
577            arDos = refArDo.parse(arDos, false);
578            UiccAccessRule accessRule = parseRefArdo(refArDo.value);
579            if (accessRule != null) {
580                accessRules.add(accessRule);
581            } else {
582                Rlog.e(LOG_TAG, "Skip unrecognized rule." + refArDo.value);
583            }
584        }
585        return accessRules;
586    }
587
588    /*
589     * Parses a single rule.
590     */
591    private static UiccAccessRule parseRefArdo(String rule) {
592        log("Got rule: " + rule);
593
594        String certificateHash = null;
595        String packageName = null;
596        String tmp = null;
597        long accessType = 0;
598
599        while (!rule.isEmpty()) {
600            if (rule.startsWith(TAG_REF_DO)) {
601                TLV refDo = new TLV(TAG_REF_DO); //E1
602                rule = refDo.parse(rule, false);
603                // Allow 4F tag with a default value "FF FF FF FF FF FF" to be compatible with
604                // devices having GP access control enforcer:
605                //  - If no 4F tag is present, it's a CP rule.
606                //  - If 4F tag has value "FF FF FF FF FF FF", it's a CP rule.
607                //  - If 4F tag has other values, it's not a CP rule and Android should ignore it.
608                TLV deviceDo = new TLV(TAG_DEVICE_APP_ID_REF_DO); //C1
609                if (refDo.value.startsWith(TAG_AID_REF_DO)) {
610                    TLV cpDo = new TLV(TAG_AID_REF_DO); //4F
611                    String remain = cpDo.parse(refDo.value, false);
612                    if (!cpDo.lengthBytes.equals("06") || !cpDo.value.equals(CARRIER_PRIVILEGE_AID)
613                            || remain.isEmpty() || !remain.startsWith(TAG_DEVICE_APP_ID_REF_DO)) {
614                        return null;
615                    }
616                    tmp = deviceDo.parse(remain, false);
617                    certificateHash = deviceDo.value;
618                } else if (refDo.value.startsWith(TAG_DEVICE_APP_ID_REF_DO)) {
619                    tmp = deviceDo.parse(refDo.value, false);
620                    certificateHash = deviceDo.value;
621                } else {
622                    return null;
623                }
624                if (!tmp.isEmpty()) {
625                    if (!tmp.startsWith(TAG_PKG_REF_DO)) {
626                        return null;
627                    }
628                    TLV pkgDo = new TLV(TAG_PKG_REF_DO); //CA
629                    pkgDo.parse(tmp, true);
630                    packageName = new String(IccUtils.hexStringToBytes(pkgDo.value));
631                } else {
632                    packageName = null;
633                }
634            } else if (rule.startsWith(TAG_AR_DO)) {
635                TLV arDo = new TLV(TAG_AR_DO); //E3
636                rule = arDo.parse(rule, false);
637                // Skip all the irrelevant tags (All the optional tags here are two bytes
638                // according to the spec GlobalPlatform Secure Element Access Control).
639                String remain = arDo.value;
640                while (!remain.isEmpty() && !remain.startsWith(TAG_PERM_AR_DO)) {
641                    TLV tmpDo = new TLV(remain.substring(0, 2));
642                    remain = tmpDo.parse(remain, false);
643                }
644                if (remain.isEmpty()) {
645                    return null;
646                }
647                TLV permDo = new TLV(TAG_PERM_AR_DO); //DB
648                permDo.parse(remain, true);
649            } else  {
650                // Spec requires it must be either TAG_REF_DO or TAG_AR_DO.
651                throw new RuntimeException("Invalid Rule type");
652            }
653        }
654
655        UiccAccessRule accessRule = new UiccAccessRule(
656                IccUtils.hexStringToBytes(certificateHash), packageName, accessType);
657        return accessRule;
658    }
659
660    /*
661     * Updates the state and notifies the UiccCard that the rules have finished loading.
662     */
663    private void updateState(int newState, String statusMessage) {
664        mState.set(newState);
665        if (mLoadedCallback != null) {
666            mLoadedCallback.sendToTarget();
667        }
668
669        mStatusMessage = statusMessage;
670    }
671
672    private static void log(String msg) {
673        if (DBG) Rlog.d(LOG_TAG, msg);
674    }
675
676    /**
677     * Dumps info to Dumpsys - useful for debugging.
678     */
679    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
680        pw.println("UiccCarrierPrivilegeRules: " + this);
681        pw.println(" mState=" + getStateString(mState.get()));
682        pw.println(" mStatusMessage='" + mStatusMessage + "'");
683        if (mAccessRules != null) {
684            pw.println(" mAccessRules: ");
685            for (UiccAccessRule ar : mAccessRules) {
686                pw.println("  rule='" + ar + "'");
687            }
688        } else {
689            pw.println(" mAccessRules: null");
690        }
691        if (mUiccPkcs15 != null) {
692            pw.println(" mUiccPkcs15: " + mUiccPkcs15);
693            mUiccPkcs15.dump(fd, pw, args);
694        } else {
695            pw.println(" mUiccPkcs15: null");
696        }
697        pw.flush();
698    }
699
700    /*
701     * Converts state into human readable format.
702     */
703    private String getStateString(int state) {
704        switch (state) {
705            case STATE_LOADING:
706                return "STATE_LOADING";
707            case STATE_LOADED:
708                return "STATE_LOADED";
709            case STATE_ERROR:
710                return "STATE_ERROR";
711            default:
712                return "UNKNOWN";
713        }
714    }
715}
716