• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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 
17 package com.android.internal.telephony.uicc;
18 
19 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT;
20 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_FAILURE;
21 import static com.android.internal.telephony.TelephonyStatsLog.PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SUCCESS;
22 
23 import android.annotation.Nullable;
24 import android.app.ActivityManager;
25 import android.app.usage.UsageStatsManager;
26 import android.content.BroadcastReceiver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.IntentFilter;
30 import android.content.SharedPreferences;
31 import android.content.pm.PackageManager;
32 import android.database.ContentObserver;
33 import android.net.Uri;
34 import android.os.AsyncResult;
35 import android.os.Binder;
36 import android.os.Handler;
37 import android.os.Message;
38 import android.os.ParcelUuid;
39 import android.os.PersistableBundle;
40 import android.os.Registrant;
41 import android.os.RegistrantList;
42 import android.os.UserManager;
43 import android.preference.PreferenceManager;
44 import android.provider.Settings;
45 import android.telephony.CarrierConfigManager;
46 import android.telephony.ServiceState;
47 import android.telephony.SubscriptionInfo;
48 import android.telephony.SubscriptionManager;
49 import android.telephony.TelephonyManager;
50 import android.telephony.UiccAccessRule;
51 import android.text.TextUtils;
52 import android.util.ArrayMap;
53 import android.util.ArraySet;
54 import android.util.IndentingPrintWriter;
55 
56 import com.android.internal.annotations.VisibleForTesting;
57 import com.android.internal.telephony.CarrierAppUtils;
58 import com.android.internal.telephony.CarrierPrivilegesTracker;
59 import com.android.internal.telephony.CommandsInterface;
60 import com.android.internal.telephony.IccCard;
61 import com.android.internal.telephony.IccCardConstants;
62 import com.android.internal.telephony.MccTable;
63 import com.android.internal.telephony.Phone;
64 import com.android.internal.telephony.PhoneConstants;
65 import com.android.internal.telephony.PhoneFactory;
66 import com.android.internal.telephony.TelephonyStatsLog;
67 import com.android.internal.telephony.cat.CatService;
68 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
69 import com.android.internal.telephony.subscription.SubscriptionManagerService;
70 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
71 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState;
72 import com.android.internal.telephony.uicc.IccCardStatus.CardState;
73 import com.android.internal.telephony.uicc.IccCardStatus.PinState;
74 import com.android.internal.telephony.uicc.euicc.EuiccCard;
75 import com.android.telephony.Rlog;
76 
77 import java.io.FileDescriptor;
78 import java.io.PrintWriter;
79 import java.util.ArrayList;
80 import java.util.Arrays;
81 import java.util.Collections;
82 import java.util.List;
83 import java.util.Locale;
84 import java.util.Map;
85 import java.util.Set;
86 
87 /**
88  * This class represents the carrier profiles in the {@link UiccCard}. Each profile contains
89  * multiple {@link UiccCardApplication}, one {@link UiccCarrierPrivilegeRules} and one
90  * {@link CatService}.
91  *
92  * Profile is related to {@link android.telephony.SubscriptionInfo} but those two concepts are
93  * different. {@link android.telephony.SubscriptionInfo} contains all the subscription information
94  * while Profile contains all the {@link UiccCardApplication} which will be used to fetch those
95  * subscription information from the {@link UiccCard}.
96  *
97  * {@hide}
98  */
99 public class UiccProfile extends IccCard {
100     protected static final String LOG_TAG = "UiccProfile";
101     protected static final boolean DBG = true;
102     private static final boolean VDBG = false; //STOPSHIP if true
103 
104     private static final String OPERATOR_BRAND_OVERRIDE_PREFIX = "operator_branding_";
105 
106     // The lock object is created by UiccSlot that owns the UiccCard that owns this UiccProfile.
107     // This is to share the lock between UiccSlot, UiccCard and UiccProfile for now.
108     private final Object mLock;
109     private PinState mUniversalPinState;
110     private int mGsmUmtsSubscriptionAppIndex;
111     private int mCdmaSubscriptionAppIndex;
112     private int mImsSubscriptionAppIndex;
113     private UiccCardApplication[] mUiccApplications =
114             new UiccCardApplication[IccCardStatus.CARD_MAX_APPS];
115     private Context mContext;
116     private CommandsInterface mCi;
117     private final UiccCard mUiccCard;
118     private CatService mCatService;
119     private UiccCarrierPrivilegeRules mCarrierPrivilegeRules;
120     private UiccCarrierPrivilegeRules mTestOverrideCarrierPrivilegeRules;
121     private boolean mDisposed = false;
122 
123     private RegistrantList mOperatorBrandOverrideRegistrants = new RegistrantList();
124 
125     private final int mPhoneId;
126     private final PinStorage mPinStorage;
127 
128     private final CarrierConfigManager mCarrierConfigManager;
129 
130     private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 1;
131     private static final int EVENT_ICC_LOCKED = 2;
132     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
133     public static final int EVENT_APP_READY = 3;
134     private static final int EVENT_RECORDS_LOADED = 4;
135     private static final int EVENT_NETWORK_LOCKED = 5;
136     private static final int EVENT_EID_READY = 6;
137     private static final int EVENT_ICC_RECORD_EVENTS = 7;
138     private static final int EVENT_OPEN_LOGICAL_CHANNEL_DONE = 8;
139     private static final int EVENT_CLOSE_LOGICAL_CHANNEL_DONE = 9;
140     private static final int EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE = 10;
141     private static final int EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE = 11;
142     private static final int EVENT_SIM_IO_DONE = 12;
143     private static final int EVENT_CARRIER_PRIVILEGES_LOADED = 13;
144     private static final int EVENT_CARRIER_CONFIG_CHANGED = 14;
145     private static final int EVENT_CARRIER_PRIVILEGES_TEST_OVERRIDE_SET = 15;
146     private static final int EVENT_SUPPLY_ICC_PIN_DONE = 16;
147     // NOTE: any new EVENT_* values must be added to eventToString.
148 
149     private TelephonyManager mTelephonyManager;
150 
151     private RegistrantList mNetworkLockedRegistrants = new RegistrantList();
152 
153     @VisibleForTesting
154     public int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp?
155     private int mRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
156     private UiccCardApplication mUiccApplication = null;
157     private IccRecords mIccRecords = null;
158     private IccCardConstants.State mExternalState = IccCardConstants.State.UNKNOWN;
159 
160     // The number of UiccApplications modem reported. It's different from mUiccApplications.length
161     // which is always CARD_MAX_APPS, and only updated when modem sends an update, and NOT updated
162     // during SIM refresh. It's currently only used to help identify empty profile.
163     private int mLastReportedNumOfUiccApplications;
164 
165     private final ContentObserver mProvisionCompleteContentObserver =
166             new ContentObserver(new Handler()) {
167                 @Override
168                 public void onChange(boolean selfChange) {
169                     synchronized (mLock) {
170                         mContext.getContentResolver().unregisterContentObserver(this);
171                         mProvisionCompleteContentObserverRegistered = false;
172                         showCarrierAppNotificationsIfPossible();
173                     }
174                 }
175             };
176     private boolean mProvisionCompleteContentObserverRegistered;
177 
178     private final BroadcastReceiver mUserUnlockReceiver = new BroadcastReceiver() {
179         @Override
180         public void onReceive(Context context, Intent intent) {
181             synchronized (mLock) {
182                 mContext.unregisterReceiver(this);
183                 mUserUnlockReceiverRegistered = false;
184                 showCarrierAppNotificationsIfPossible();
185             }
186         }
187     };
188     private boolean mUserUnlockReceiverRegistered;
189 
190     private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
191             new CarrierConfigManager.CarrierConfigChangeListener() {
192                 @Override
193                 public void onCarrierConfigChanged(int logicalSlotIndex, int subscriptionId,
194                         int carrierId, int specificCarrierId) {
195                     if (logicalSlotIndex == mPhoneId) {
196                         log("onCarrierConfigChanged: slotIndex=" + logicalSlotIndex
197                                 + ", subId=" + subscriptionId + ", carrierId=" + carrierId);
198                         handleCarrierNameOverride();
199                         handleSimCountryIsoOverride();
200                     }
201                 }
202             };
203 
204     @VisibleForTesting
205     public final Handler mHandler = new Handler() {
206         @Override
207         public void handleMessage(Message msg) {
208             String eventName = eventToString(msg.what);
209             // We still need to handle the following response messages even the UiccProfile has been
210             // disposed because whoever sent the request may be still waiting for the response.
211             if (mDisposed && msg.what != EVENT_OPEN_LOGICAL_CHANNEL_DONE
212                     && msg.what != EVENT_CLOSE_LOGICAL_CHANNEL_DONE
213                     && msg.what != EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE
214                     && msg.what != EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE
215                     && msg.what != EVENT_SIM_IO_DONE) {
216                 loge("handleMessage: Received " + eventName
217                         + " after dispose(); ignoring the message");
218                 return;
219             }
220             logWithLocalLog("handleMessage: Received " + eventName + " for phoneId " + mPhoneId);
221             switch (msg.what) {
222                 case EVENT_NETWORK_LOCKED:
223                     if (mUiccApplication != null) {
224                         mNetworkLockedRegistrants.notifyRegistrants(new AsyncResult(
225                                 null, mUiccApplication.getPersoSubState().ordinal(), null));
226                     } else {
227                         log("EVENT_NETWORK_LOCKED: mUiccApplication is NULL, "
228                                 + "mNetworkLockedRegistrants not notified.");
229                     }
230                     // intentional fall through
231                 case EVENT_RADIO_OFF_OR_UNAVAILABLE:
232                 case EVENT_ICC_LOCKED:
233                 case EVENT_APP_READY:
234                 case EVENT_RECORDS_LOADED:
235                 case EVENT_EID_READY:
236                     if (VDBG) log("handleMessage: Received " + eventName);
237                     updateExternalState();
238                     break;
239 
240                 case EVENT_ICC_RECORD_EVENTS:
241                     if ((mCurrentAppType == UiccController.APP_FAM_3GPP) && (mIccRecords != null)) {
242                         AsyncResult ar = (AsyncResult) msg.obj;
243                         int eventCode = (Integer) ar.result;
244                         if (eventCode == SIMRecords.EVENT_SPN) {
245                             mTelephonyManager.setSimOperatorNameForPhone(
246                                     mPhoneId, mIccRecords.getServiceProviderName());
247                         }
248                     }
249                     break;
250 
251                 case EVENT_CARRIER_PRIVILEGES_LOADED:
252                     if (VDBG) log("handleMessage: EVENT_CARRIER_PRIVILEGES_LOADED");
253                     Phone phone = PhoneFactory.getPhone(mPhoneId);
254                     if (phone != null) {
255                         CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker();
256                         if (cpt != null) {
257                             cpt.onUiccAccessRulesLoaded();
258                         }
259                     }
260                     onCarrierPrivilegesLoadedMessage();
261                     updateExternalState();
262                     break;
263 
264                 case EVENT_CARRIER_CONFIG_CHANGED:
265                     handleCarrierNameOverride();
266                     handleSimCountryIsoOverride();
267                     break;
268 
269                 case EVENT_OPEN_LOGICAL_CHANNEL_DONE:
270                 case EVENT_CLOSE_LOGICAL_CHANNEL_DONE:
271                 case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
272                 case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE:
273                 case EVENT_SIM_IO_DONE: {
274                     AsyncResult ar = (AsyncResult) msg.obj;
275                     if (ar.exception != null) {
276                         logWithLocalLog("handleMessage: Error in SIM access with exception "
277                                 + ar.exception);
278                     }
279                     if (ar.userObj != null) {
280                         AsyncResult.forMessage((Message) ar.userObj, ar.result, ar.exception);
281                         ((Message) ar.userObj).sendToTarget();
282                     } else {
283                         loge("handleMessage: ar.userObj is null in event:" + eventName
284                                 + ", failed to post status back to caller");
285                     }
286                     break;
287                 }
288 
289                 case EVENT_CARRIER_PRIVILEGES_TEST_OVERRIDE_SET:
290                     if (msg.obj == null) {
291                         mTestOverrideCarrierPrivilegeRules = null;
292                     } else {
293                         mTestOverrideCarrierPrivilegeRules =
294                                 new UiccCarrierPrivilegeRules((List<UiccAccessRule>) msg.obj);
295                     }
296                     refresh();
297                     break;
298 
299                 case EVENT_SUPPLY_ICC_PIN_DONE: {
300                     AsyncResult ar = (AsyncResult) msg.obj;
301                     if (ar.exception != null) {
302                         // An error occurred during automatic PIN verification. At this point,
303                         // clear the cache and propagate the state.
304                         loge("An error occurred during internal PIN verification");
305                         mPinStorage.clearPin(mPhoneId);
306                         updateExternalState();
307                     } else {
308                         log("Internal PIN verification was successful!");
309                         // Nothing to do.
310                     }
311                     // Update metrics:
312                     TelephonyStatsLog.write(
313                             PIN_STORAGE_EVENT,
314                             ar.exception != null
315                                     ? PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_FAILURE
316                                     : PIN_STORAGE_EVENT__EVENT__PIN_VERIFICATION_SUCCESS,
317                             /* number_of_pins= */ 1);
318                     break;
319                 }
320 
321                 default:
322                     loge("handleMessage: Unhandled message with number: " + msg.what);
323                     break;
324             }
325         }
326     };
327 
UiccProfile(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId, UiccCard uiccCard, Object lock)328     public UiccProfile(Context c, CommandsInterface ci, IccCardStatus ics, int phoneId,
329             UiccCard uiccCard, Object lock) {
330         if (DBG) log("Creating profile");
331         mLock = lock;
332         mUiccCard = uiccCard;
333         mPhoneId = phoneId;
334         // set current app type based on phone type - do this before calling update() as that
335         // calls updateIccAvailability() which uses mCurrentAppType
336         Phone phone = PhoneFactory.getPhone(phoneId);
337         if (phone != null) {
338             setCurrentAppType(phone.getPhoneType() == PhoneConstants.PHONE_TYPE_GSM);
339         }
340 
341         if (mUiccCard instanceof EuiccCard) {
342             // for RadioConfig<1.2 eid is not known when the EuiccCard is constructed
343             ((EuiccCard) mUiccCard).registerForEidReady(mHandler, EVENT_EID_READY, null);
344         }
345         mPinStorage = UiccController.getInstance().getPinStorage();
346 
347         update(c, ci, ics);
348         ci.registerForOffOrNotAvailable(mHandler, EVENT_RADIO_OFF_OR_UNAVAILABLE, null);
349         resetProperties();
350 
351         mCarrierConfigManager = c.getSystemService(CarrierConfigManager.class);
352         // Listener callback directly handles config change and thus runs on handler thread
353         mCarrierConfigManager.registerCarrierConfigChangeListener(mHandler::post,
354                 mCarrierConfigChangeListener);
355     }
356 
357     /**
358      * Dispose the UiccProfile.
359      */
dispose()360     public void dispose() {
361         if (DBG) log("Disposing profile");
362 
363         // mUiccCard is outside of mLock in order to prevent deadlocking. This is safe because
364         // EuiccCard#unregisterForEidReady handles its own lock
365         if (mUiccCard instanceof EuiccCard) {
366             ((EuiccCard) mUiccCard).unregisterForEidReady(mHandler);
367         }
368         synchronized (mLock) {
369             unregisterAllAppEvents();
370             unregisterCurrAppEvents();
371 
372             if (mProvisionCompleteContentObserverRegistered) {
373                 mContext.getContentResolver()
374                         .unregisterContentObserver(mProvisionCompleteContentObserver);
375                 mProvisionCompleteContentObserverRegistered = false;
376             }
377 
378             if (mUserUnlockReceiverRegistered) {
379                 mContext.unregisterReceiver(mUserUnlockReceiver);
380                 mUserUnlockReceiverRegistered = false;
381             }
382 
383             InstallCarrierAppUtils.hideAllNotifications(mContext);
384             InstallCarrierAppUtils.unregisterPackageInstallReceiver(mContext);
385 
386             mCi.unregisterForOffOrNotAvailable(mHandler);
387 
388             if (mCarrierConfigManager != null && mCarrierConfigChangeListener != null) {
389                 mCarrierConfigManager.unregisterCarrierConfigChangeListener(
390                         mCarrierConfigChangeListener);
391             }
392 
393             if (mCatService != null) mCatService.dispose();
394             for (UiccCardApplication app : mUiccApplications) {
395                 if (app != null) {
396                     app.dispose();
397                 }
398             }
399             mCatService = null;
400             mUiccApplications = null;
401             mRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
402             mCarrierPrivilegeRules = null;
403             mContext.getContentResolver().unregisterContentObserver(
404                     mProvisionCompleteContentObserver);
405             mDisposed = true;
406         }
407     }
408 
409     /**
410      * The card application that the external world sees will be based on the
411      * voice radio technology only!
412      */
setVoiceRadioTech(int radioTech)413     public void setVoiceRadioTech(int radioTech) {
414         synchronized (mLock) {
415             if (DBG) {
416                 log("Setting radio tech " + ServiceState.rilRadioTechnologyToString(radioTech));
417             }
418             mRadioTech = radioTech;
419             setCurrentAppType(ServiceState.isGsm(radioTech));
420             updateIccAvailability(false);
421         }
422     }
423 
setCurrentAppType(boolean isGsm)424     private void setCurrentAppType(boolean isGsm) {
425         if (VDBG) log("setCurrentAppType");
426         int primaryAppType;
427         int secondaryAppType;
428         if (isGsm) {
429             primaryAppType = UiccController.APP_FAM_3GPP;
430             secondaryAppType = UiccController.APP_FAM_3GPP2;
431         } else {
432             primaryAppType = UiccController.APP_FAM_3GPP2;
433             secondaryAppType = UiccController.APP_FAM_3GPP;
434         }
435         synchronized (mLock) {
436             UiccCardApplication newApp = getApplication(primaryAppType);
437             if (newApp != null || getApplication(secondaryAppType) == null) {
438                 mCurrentAppType = primaryAppType;
439             } else {
440                 mCurrentAppType = secondaryAppType;
441             }
442         }
443     }
444 
445     /**
446      * Override the carrier name with either carrier config or SPN
447      * if an override is provided.
448      */
handleCarrierNameOverride()449     private void handleCarrierNameOverride() {
450         final int subId = SubscriptionManager.getSubscriptionId(mPhoneId);
451         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
452             loge("subId not valid for Phone " + mPhoneId);
453             return;
454         }
455 
456         CarrierConfigManager configLoader = (CarrierConfigManager)
457                 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
458         if (configLoader == null) {
459             loge("Failed to load a Carrier Config");
460             return;
461         }
462 
463         PersistableBundle config =
464                 CarrierConfigManager.getCarrierConfigSubset(
465                         mContext,
466                         subId,
467                         CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL,
468                         CarrierConfigManager.KEY_CARRIER_NAME_STRING);
469         if (config.isEmpty()) {
470             loge("handleCarrierNameOverride: fail to get carrier configs.");
471             return;
472         }
473         boolean preferCcName = config.getBoolean(
474                 CarrierConfigManager.KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
475         String ccName = config.getString(CarrierConfigManager.KEY_CARRIER_NAME_STRING);
476 
477         String newCarrierName = null;
478         String currSpn = getServiceProviderName();  // Get the name from EF_SPN.
479         int nameSource = SubscriptionManager.NAME_SOURCE_SIM_SPN;
480         // If carrier config is priority, use it regardless - the preference
481         // and the name were both set by the carrier, so this is safe;
482         // otherwise, if the SPN is priority but we don't have one *and* we have
483         // a name in carrier config, use the carrier config name as a backup.
484         if (preferCcName || (TextUtils.isEmpty(currSpn) && !TextUtils.isEmpty(ccName))) {
485             newCarrierName = ccName;
486             nameSource = SubscriptionManager.NAME_SOURCE_CARRIER;
487         } else if (TextUtils.isEmpty(currSpn)) {
488             // currSpn is empty and could not get name from carrier config; get name from PNN or
489             // carrier id
490             Phone phone = PhoneFactory.getPhone(mPhoneId);
491             if (phone != null) {
492                 String currPnn = phone.getPlmn();   // Get the name from EF_PNN.
493                 if (!TextUtils.isEmpty(currPnn)) {
494                     newCarrierName = currPnn;
495                     nameSource = SubscriptionManager.NAME_SOURCE_SIM_PNN;
496                 } else {
497                     newCarrierName = phone.getCarrierName();    // Get the name from carrier id.
498                     nameSource = SubscriptionManager.NAME_SOURCE_CARRIER_ID;
499                 }
500             }
501         }
502 
503         if (!TextUtils.isEmpty(newCarrierName)) {
504             mTelephonyManager.setSimOperatorNameForPhone(mPhoneId, newCarrierName);
505             mOperatorBrandOverrideRegistrants.notifyRegistrants();
506         }
507 
508         updateCarrierNameForSubscription(subId, nameSource);
509     }
510 
511     /**
512      * Override sim country iso based on carrier config.
513      * Telephony country iso is based on MCC table which is coarse and doesn't work with dual IMSI
514      * SIM. e.g, a US carrier might have a roaming agreement with carriers from Europe. Devices
515      * will switch to different IMSI (differnt mccmnc) when enter roaming state. As a result, sim
516      * country iso (locale) will change to non-US.
517      *
518      * Each sim carrier should have a single country code. We should improve the accuracy of
519      * SIM country code look-up by using carrierid-to-countrycode table as an override on top of
520      * MCC table
521      */
handleSimCountryIsoOverride()522     private void handleSimCountryIsoOverride() {
523         final int subId = SubscriptionManager.getSubscriptionId(mPhoneId);
524         if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
525             loge("subId not valid for Phone " + mPhoneId);
526             return;
527         }
528 
529         CarrierConfigManager configLoader = (CarrierConfigManager)
530                 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
531         if (configLoader == null) {
532             loge("Failed to load a Carrier Config");
533             return;
534         }
535 
536         PersistableBundle config =
537                 CarrierConfigManager.getCarrierConfigSubset(
538                         mContext, subId, CarrierConfigManager.KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING);
539         if (config.isEmpty()) {
540             loge("handleSimCountryIsoOverride: fail to get carrier configs.");
541             return;
542         }
543         String iso = config.getString(CarrierConfigManager.KEY_SIM_COUNTRY_ISO_OVERRIDE_STRING);
544         if (!TextUtils.isEmpty(iso)
545                 && !iso.equals(TelephonyManager.getSimCountryIsoForPhone(mPhoneId))) {
546             mTelephonyManager.setSimCountryIsoForPhone(mPhoneId, iso);
547             SubscriptionManagerService.getInstance().setCountryIso(subId, iso);
548         }
549     }
550 
updateCarrierNameForSubscription(int subId, int nameSource)551     private void updateCarrierNameForSubscription(int subId, int nameSource) {
552         /* update display name with carrier override */
553         SubscriptionInfo subInfo = SubscriptionManagerService.getInstance()
554                 .getActiveSubscriptionInfo(subId, mContext.getOpPackageName(),
555                         mContext.getAttributionTag());
556 
557         if (subInfo == null) {
558             return;
559         }
560 
561         CharSequence oldSubName = subInfo.getDisplayName();
562         String newCarrierName = mTelephonyManager.getSimOperatorName(subId);
563 
564         if (!TextUtils.isEmpty(newCarrierName) && !newCarrierName.equals(oldSubName)) {
565             log("sim name[" + mPhoneId + "] = " + newCarrierName);
566             SubscriptionManagerService.getInstance().setDisplayNameUsingSrc(
567                     newCarrierName, subId, nameSource);
568         }
569     }
570 
571     /**
572      * ICC availability/state changed. Update corresponding fields and external state if needed.
573      */
updateIccAvailability(boolean allAppsChanged)574     private void updateIccAvailability(boolean allAppsChanged) {
575         synchronized (mLock) {
576             UiccCardApplication newApp;
577             IccRecords newRecords = null;
578             newApp = getApplication(mCurrentAppType);
579             if (newApp != null) {
580                 newRecords = newApp.getIccRecords();
581             }
582 
583             if (allAppsChanged) {
584                 unregisterAllAppEvents();
585                 registerAllAppEvents();
586             }
587 
588             if (mIccRecords != newRecords || mUiccApplication != newApp) {
589                 if (DBG) log("Icc changed. Reregistering.");
590                 unregisterCurrAppEvents();
591                 mUiccApplication = newApp;
592                 mIccRecords = newRecords;
593                 registerCurrAppEvents();
594             }
595             updateExternalState();
596         }
597     }
598 
resetProperties()599     void resetProperties() {
600         if (mCurrentAppType == UiccController.APP_FAM_3GPP) {
601             log("update icc_operator_numeric=" + "");
602             mTelephonyManager.setSimOperatorNumericForPhone(mPhoneId, "");
603             mTelephonyManager.setSimCountryIsoForPhone(mPhoneId, "");
604             mTelephonyManager.setSimOperatorNameForPhone(mPhoneId, "");
605         }
606     }
607 
608     /**
609      * Update the external SIM state
610      */
611     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
updateExternalState()612     public void updateExternalState() {
613         // First check if card state is IO_ERROR or RESTRICTED
614         if (mUiccCard.getCardState() == IccCardStatus.CardState.CARDSTATE_ERROR) {
615             setExternalState(IccCardConstants.State.CARD_IO_ERROR);
616             return;
617         }
618 
619         if (mUiccCard.getCardState() == IccCardStatus.CardState.CARDSTATE_RESTRICTED) {
620             setExternalState(IccCardConstants.State.CARD_RESTRICTED);
621             return;
622         }
623 
624         if (mUiccCard instanceof EuiccCard && ((EuiccCard) mUiccCard).getEid() == null) {
625             // for RadioConfig<1.2 the EID is not known when the EuiccCard is constructed
626             if (DBG) log("EID is not ready yet.");
627             return;
628         }
629 
630         // By process of elimination, the UICC Card State = PRESENT and state needs to be decided
631         // based on apps
632         if (mUiccApplication == null) {
633             loge("updateExternalState: setting state to NOT_READY because mUiccApplication is "
634                     + "null");
635             setExternalState(IccCardConstants.State.NOT_READY);
636             return;
637         }
638 
639         // Check if SIM is locked
640         boolean cardLocked = false;
641         IccCardConstants.State lockedState = null;
642         IccCardApplicationStatus.AppState appState = mUiccApplication.getState();
643 
644         PinState pin1State = mUiccApplication.getPin1State();
645         if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) {
646             if (VDBG) log("updateExternalState: PERM_DISABLED");
647             cardLocked = true;
648             lockedState = IccCardConstants.State.PERM_DISABLED;
649         } else {
650             if (appState == IccCardApplicationStatus.AppState.APPSTATE_PIN) {
651                 if (VDBG) log("updateExternalState: PIN_REQUIRED");
652                 cardLocked = true;
653                 lockedState = IccCardConstants.State.PIN_REQUIRED;
654             } else if (appState == IccCardApplicationStatus.AppState.APPSTATE_PUK) {
655                 if (VDBG) log("updateExternalState: PUK_REQUIRED");
656                 cardLocked = true;
657                 lockedState = IccCardConstants.State.PUK_REQUIRED;
658             } else if (appState == IccCardApplicationStatus.AppState.APPSTATE_SUBSCRIPTION_PERSO) {
659                 if (PersoSubState.isPersoLocked(mUiccApplication.getPersoSubState())) {
660                     if (VDBG) log("updateExternalState: PERSOSUBSTATE_SIM_NETWORK");
661                     cardLocked = true;
662                     lockedState = IccCardConstants.State.NETWORK_LOCKED;
663                 }
664             }
665         }
666 
667         // If SIM is locked, broadcast state as NOT_READY/LOCKED depending on if records are loaded
668         if (cardLocked) {
669             if (mIccRecords != null && (mIccRecords.getLockedRecordsLoaded()
670                     || mIccRecords.getNetworkLockedRecordsLoaded())) { // locked records loaded
671                 if (VDBG) {
672                     log("updateExternalState: card locked and records loaded; "
673                             + "setting state to locked");
674                 }
675                 // If the PIN code is required and an available cached PIN is available, intercept
676                 // the update of external state and perform an internal PIN verification.
677                 if (lockedState == IccCardConstants.State.PIN_REQUIRED) {
678                     String pin = mPinStorage.getPin(mPhoneId, mIccRecords.getFullIccId());
679                     if (!pin.isEmpty()) {
680                         log("PIN_REQUIRED[" + mPhoneId + "] - Cache present");
681                         mCi.supplyIccPin(pin, mHandler.obtainMessage(EVENT_SUPPLY_ICC_PIN_DONE));
682                         return;
683                     }
684                 }
685 
686                 setExternalState(lockedState);
687             } else {
688                 if (VDBG) {
689                     log("updateExternalState: card locked but records not loaded; "
690                             + "setting state to NOT_READY");
691                 }
692                 setExternalState(IccCardConstants.State.NOT_READY);
693             }
694             return;
695         }
696 
697         // Check for remaining app states
698         switch (appState) {
699             case APPSTATE_UNKNOWN:
700                 /*
701                  * APPSTATE_UNKNOWN is a catch-all state reported whenever the app
702                  * is not explicitly in one of the other states. To differentiate the
703                  * case where we know that there is a card present, but the APP is not
704                  * ready, we choose NOT_READY here instead of unknown. This is possible
705                  * in at least two cases:
706                  * 1) A transient during the process of the SIM bringup
707                  * 2) There is no valid App on the SIM to load, which can be the case with an
708                  *    eSIM/soft SIM.
709                  */
710                 if (VDBG) {
711                     log("updateExternalState: app state is unknown; setting state to NOT_READY");
712                 }
713                 setExternalState(IccCardConstants.State.NOT_READY);
714                 break;
715             case APPSTATE_DETECTED:
716                 if (VDBG) {
717                     log("updateExternalState: app state is detected; setting state to NOT_READY");
718                 }
719                 setExternalState(IccCardConstants.State.NOT_READY);
720                 break;
721             case APPSTATE_READY:
722                 checkAndUpdateIfAnyAppToBeIgnored();
723                 if (areAllApplicationsReady()) {
724                     if (areAllRecordsLoaded() && areCarrierPrivilegeRulesLoaded()) {
725                         if (VDBG) log("updateExternalState: setting state to LOADED");
726                         setExternalState(IccCardConstants.State.LOADED);
727                     } else {
728                         if (VDBG) {
729                             log("updateExternalState: setting state to READY; records loaded "
730                                     + areAllRecordsLoaded() + ", carrier privilige rules loaded "
731                                     + areCarrierPrivilegeRulesLoaded());
732                         }
733                         setExternalState(IccCardConstants.State.READY);
734                     }
735                 } else {
736                     if (VDBG) {
737                         log("updateExternalState: app state is READY but not for all apps; "
738                                 + "setting state to NOT_READY");
739                     }
740                     setExternalState(IccCardConstants.State.NOT_READY);
741                 }
742                 break;
743         }
744     }
745 
registerAllAppEvents()746     private void registerAllAppEvents() {
747         // todo: all of these should be notified to UiccProfile directly without needing to register
748         for (UiccCardApplication app : mUiccApplications) {
749             if (app != null) {
750                 if (VDBG) log("registerUiccCardEvents: registering for EVENT_APP_READY");
751                 app.registerForReady(mHandler, EVENT_APP_READY, null);
752                 IccRecords ir = app.getIccRecords();
753                 if (ir != null) {
754                     if (VDBG) log("registerUiccCardEvents: registering for EVENT_RECORDS_LOADED");
755                     ir.registerForRecordsLoaded(mHandler, EVENT_RECORDS_LOADED, null);
756                     ir.registerForRecordsEvents(mHandler, EVENT_ICC_RECORD_EVENTS, null);
757                 }
758             }
759         }
760     }
761 
unregisterAllAppEvents()762     private void unregisterAllAppEvents() {
763         for (UiccCardApplication app : mUiccApplications) {
764             if (app != null) {
765                 app.unregisterForReady(mHandler);
766                 IccRecords ir = app.getIccRecords();
767                 if (ir != null) {
768                     ir.unregisterForRecordsLoaded(mHandler);
769                     ir.unregisterForRecordsEvents(mHandler);
770                 }
771             }
772         }
773     }
774 
registerCurrAppEvents()775     private void registerCurrAppEvents() {
776         // In case of locked, only listen to the current application.
777         if (mIccRecords != null) {
778             mIccRecords.registerForLockedRecordsLoaded(mHandler, EVENT_ICC_LOCKED, null);
779             mIccRecords.registerForNetworkLockedRecordsLoaded(mHandler, EVENT_NETWORK_LOCKED, null);
780         }
781     }
782 
unregisterCurrAppEvents()783     private void unregisterCurrAppEvents() {
784         if (mIccRecords != null) {
785             mIccRecords.unregisterForLockedRecordsLoaded(mHandler);
786             mIccRecords.unregisterForNetworkLockedRecordsLoaded(mHandler);
787         }
788     }
789 
setExternalState(IccCardConstants.State newState, boolean override)790     private void setExternalState(IccCardConstants.State newState, boolean override) {
791         synchronized (mLock) {
792             if (!SubscriptionManager.isValidSlotIndex(mPhoneId)) {
793                 loge("setExternalState: mPhoneId=" + mPhoneId + " is invalid; Return!!");
794                 return;
795             }
796 
797             if (!override && newState == mExternalState) {
798                 log("setExternalState: !override and newstate unchanged from " + newState);
799                 return;
800             }
801             mExternalState = newState;
802             if (mExternalState == IccCardConstants.State.LOADED) {
803                 // Update the MCC/MNC.
804                 if (mIccRecords != null) {
805                     String operator = mIccRecords.getOperatorNumeric();
806                     log("setExternalState: operator=" + operator + " mPhoneId=" + mPhoneId);
807 
808                     if (!TextUtils.isEmpty(operator)) {
809                         mTelephonyManager.setSimOperatorNumericForPhone(mPhoneId, operator);
810                         String countryCode = operator.substring(0, 3);
811                         if (countryCode != null) {
812                             mTelephonyManager.setSimCountryIsoForPhone(mPhoneId,
813                                     MccTable.countryCodeForMcc(countryCode));
814                         } else {
815                             loge("setExternalState: state LOADED; Country code is null");
816                         }
817                     } else {
818                         loge("setExternalState: state LOADED; Operator name is null");
819                     }
820                 }
821             }
822             log("setExternalState: set mPhoneId=" + mPhoneId + " mExternalState=" + mExternalState);
823 
824             UiccController.getInstance().updateSimState(mPhoneId, mExternalState,
825                     getIccStateReason(mExternalState));
826         }
827     }
828 
setExternalState(IccCardConstants.State newState)829     private void setExternalState(IccCardConstants.State newState) {
830         setExternalState(newState, false);
831     }
832 
833     /**
834      * Function to check if all ICC records have been loaded
835      * @return true if all ICC records have been loaded, false otherwise.
836      */
getIccRecordsLoaded()837     public boolean getIccRecordsLoaded() {
838         synchronized (mLock) {
839             if (mIccRecords != null) {
840                 return mIccRecords.getRecordsLoaded();
841             }
842             return false;
843         }
844     }
845 
846     /**
847      * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED, CARD_IO_ERROR)
848      * @return reason
849      */
getIccStateReason(IccCardConstants.State state)850     private String getIccStateReason(IccCardConstants.State state) {
851         switch (state) {
852             case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN;
853             case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK;
854             case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK;
855             case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED;
856             case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR;
857             case CARD_RESTRICTED: return IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED;
858             default: return null;
859         }
860     }
861 
862     /* IccCard interface implementation */
863     @Override
getState()864     public IccCardConstants.State getState() {
865         synchronized (mLock) {
866             return mExternalState;
867         }
868     }
869 
870     @Override
getIccRecords()871     public IccRecords getIccRecords() {
872         synchronized (mLock) {
873             return mIccRecords;
874         }
875     }
876 
877     /**
878      * Notifies handler of any transition into State.NETWORK_LOCKED
879      */
880     @Override
registerForNetworkLocked(Handler h, int what, Object obj)881     public void registerForNetworkLocked(Handler h, int what, Object obj) {
882         synchronized (mLock) {
883             Registrant r = new Registrant(h, what, obj);
884 
885             mNetworkLockedRegistrants.add(r);
886 
887             if (getState() == IccCardConstants.State.NETWORK_LOCKED) {
888                 if (mUiccApplication != null) {
889                     r.notifyRegistrant(
890                             new AsyncResult(null, mUiccApplication.getPersoSubState().ordinal(),
891                                     null));
892 
893                 } else {
894                     log("registerForNetworkLocked: not notifying registrants, "
895                             + "mUiccApplication == null");
896                 }
897             }
898         }
899     }
900 
901     @Override
unregisterForNetworkLocked(Handler h)902     public void unregisterForNetworkLocked(Handler h) {
903         synchronized (mLock) {
904             mNetworkLockedRegistrants.remove(h);
905         }
906     }
907 
908     @Override
supplyPin(String pin, Message onComplete)909     public void supplyPin(String pin, Message onComplete) {
910         synchronized (mLock) {
911             if (mUiccApplication != null) {
912                 mUiccApplication.supplyPin(pin, onComplete);
913             } else if (onComplete != null) {
914                 Exception e = new RuntimeException("ICC card is absent.");
915                 AsyncResult.forMessage(onComplete).exception = e;
916                 onComplete.sendToTarget();
917                 return;
918             }
919         }
920     }
921 
922     @Override
supplyPuk(String puk, String newPin, Message onComplete)923     public void supplyPuk(String puk, String newPin, Message onComplete) {
924         synchronized (mLock) {
925             if (mUiccApplication != null) {
926                 mUiccApplication.supplyPuk(puk, newPin, onComplete);
927             } else if (onComplete != null) {
928                 Exception e = new RuntimeException("ICC card is absent.");
929                 AsyncResult.forMessage(onComplete).exception = e;
930                 onComplete.sendToTarget();
931                 return;
932             }
933         }
934     }
935 
936     @Override
supplyPin2(String pin2, Message onComplete)937     public void supplyPin2(String pin2, Message onComplete) {
938         synchronized (mLock) {
939             if (mUiccApplication != null) {
940                 mUiccApplication.supplyPin2(pin2, onComplete);
941             } else if (onComplete != null) {
942                 Exception e = new RuntimeException("ICC card is absent.");
943                 AsyncResult.forMessage(onComplete).exception = e;
944                 onComplete.sendToTarget();
945                 return;
946             }
947         }
948     }
949 
950     @Override
supplyPuk2(String puk2, String newPin2, Message onComplete)951     public void supplyPuk2(String puk2, String newPin2, Message onComplete) {
952         synchronized (mLock) {
953             if (mUiccApplication != null) {
954                 mUiccApplication.supplyPuk2(puk2, newPin2, onComplete);
955             } else if (onComplete != null) {
956                 Exception e = new RuntimeException("ICC card is absent.");
957                 AsyncResult.forMessage(onComplete).exception = e;
958                 onComplete.sendToTarget();
959                 return;
960             }
961         }
962     }
963 
964     @Override
supplyNetworkDepersonalization(String pin, Message onComplete)965     public void supplyNetworkDepersonalization(String pin, Message onComplete) {
966         synchronized (mLock) {
967             if (mUiccApplication != null) {
968                 mUiccApplication.supplyNetworkDepersonalization(pin, onComplete);
969             } else if (onComplete != null) {
970                 Exception e = new RuntimeException("CommandsInterface is not set.");
971                 AsyncResult.forMessage(onComplete).exception = e;
972                 onComplete.sendToTarget();
973                 return;
974             }
975         }
976     }
977 
978     @Override
supplySimDepersonalization(PersoSubState persoType, String pin, Message onComplete)979     public void supplySimDepersonalization(PersoSubState persoType, String pin, Message onComplete) {
980         synchronized (mLock) {
981             if (mUiccApplication != null) {
982                 mUiccApplication.supplySimDepersonalization(persoType, pin, onComplete);
983             } else if (onComplete != null) {
984                 Exception e = new RuntimeException("CommandsInterface is not set.");
985                 AsyncResult.forMessage(onComplete).exception = e;
986                 onComplete.sendToTarget();
987                 return;
988             }
989         }
990     }
991 
992     @Override
getIccLockEnabled()993     public boolean getIccLockEnabled() {
994         synchronized (mLock) {
995             /* defaults to false, if ICC is absent/deactivated */
996             return mUiccApplication != null && mUiccApplication.getIccLockEnabled();
997         }
998     }
999 
1000     @Override
getIccFdnEnabled()1001     public boolean getIccFdnEnabled() {
1002         synchronized (mLock) {
1003             return mUiccApplication != null && mUiccApplication.getIccFdnEnabled();
1004         }
1005     }
1006 
1007     @Override
getIccFdnAvailable()1008     public boolean getIccFdnAvailable() {
1009         synchronized (mLock) {
1010             return mUiccApplication != null && mUiccApplication.getIccFdnAvailable();
1011         }
1012     }
1013 
1014     @Override
getIccPin2Blocked()1015     public boolean getIccPin2Blocked() {
1016         /* defaults to disabled */
1017         return mUiccApplication != null && mUiccApplication.getIccPin2Blocked();
1018     }
1019 
1020     @Override
getIccPuk2Blocked()1021     public boolean getIccPuk2Blocked() {
1022         /* defaults to disabled */
1023         return mUiccApplication != null && mUiccApplication.getIccPuk2Blocked();
1024     }
1025 
1026     @Override
isEmptyProfile()1027     public boolean isEmptyProfile() {
1028         // If there's no UiccCardApplication, it's an empty profile.
1029         // Empty profile is a valid case of eSIM (default boot profile).
1030         // But we clear all apps of mUiccCardApplication to be null during refresh (see
1031         // resetAppWithAid) but not mLastReportedNumOfUiccApplications.
1032         // So if mLastReportedNumOfUiccApplications == 0, it means modem confirmed that we landed
1033         // on empty profile.
1034         return mLastReportedNumOfUiccApplications == 0;
1035     }
1036 
1037     @Override
setIccLockEnabled(boolean enabled, String password, Message onComplete)1038     public void setIccLockEnabled(boolean enabled, String password, Message onComplete) {
1039         synchronized (mLock) {
1040             if (mUiccApplication != null) {
1041                 mUiccApplication.setIccLockEnabled(enabled, password, onComplete);
1042             } else if (onComplete != null) {
1043                 Exception e = new RuntimeException("ICC card is absent.");
1044                 AsyncResult.forMessage(onComplete).exception = e;
1045                 onComplete.sendToTarget();
1046                 return;
1047             }
1048         }
1049     }
1050 
1051     @Override
setIccFdnEnabled(boolean enabled, String password, Message onComplete)1052     public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) {
1053         synchronized (mLock) {
1054             if (mUiccApplication != null) {
1055                 mUiccApplication.setIccFdnEnabled(enabled, password, onComplete);
1056             } else if (onComplete != null) {
1057                 Exception e = new RuntimeException("ICC card is absent.");
1058                 AsyncResult.forMessage(onComplete).exception = e;
1059                 onComplete.sendToTarget();
1060                 return;
1061             }
1062         }
1063     }
1064 
1065     @Override
changeIccLockPassword(String oldPassword, String newPassword, Message onComplete)1066     public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) {
1067         synchronized (mLock) {
1068             if (mUiccApplication != null) {
1069                 mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete);
1070             } else if (onComplete != null) {
1071                 Exception e = new RuntimeException("ICC card is absent.");
1072                 AsyncResult.forMessage(onComplete).exception = e;
1073                 onComplete.sendToTarget();
1074                 return;
1075             }
1076         }
1077     }
1078 
1079     @Override
changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete)1080     public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) {
1081         synchronized (mLock) {
1082             if (mUiccApplication != null) {
1083                 mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete);
1084             } else if (onComplete != null) {
1085                 Exception e = new RuntimeException("ICC card is absent.");
1086                 AsyncResult.forMessage(onComplete).exception = e;
1087                 onComplete.sendToTarget();
1088                 return;
1089             }
1090         }
1091     }
1092 
1093     @Override
getServiceProviderName()1094     public String getServiceProviderName() {
1095         synchronized (mLock) {
1096             if (mIccRecords != null) {
1097                 return mIccRecords.getServiceProviderName();
1098             }
1099             return null;
1100         }
1101     }
1102 
1103     @Override
hasIccCard()1104     public boolean hasIccCard() {
1105         // mUiccCard is initialized in constructor, so won't be null
1106         if (mUiccCard.getCardState()
1107                 != IccCardStatus.CardState.CARDSTATE_ABSENT) {
1108             return true;
1109         }
1110         loge("hasIccCard: UiccProfile is not null but UiccCard is null or card state is "
1111                 + "ABSENT");
1112         return false;
1113     }
1114 
1115     /**
1116      * Update the UiccProfile.
1117      */
update(Context c, CommandsInterface ci, IccCardStatus ics)1118     public void update(Context c, CommandsInterface ci, IccCardStatus ics) {
1119         synchronized (mLock) {
1120             mUniversalPinState = ics.mUniversalPinState;
1121             mGsmUmtsSubscriptionAppIndex = ics.mGsmUmtsSubscriptionAppIndex;
1122             mCdmaSubscriptionAppIndex = ics.mCdmaSubscriptionAppIndex;
1123             mImsSubscriptionAppIndex = ics.mImsSubscriptionAppIndex;
1124             mContext = c;
1125             mCi = ci;
1126             mTelephonyManager = (TelephonyManager) mContext.getSystemService(
1127                     Context.TELEPHONY_SERVICE);
1128 
1129             //update applications
1130             if (DBG) log(ics.mApplications.length + " applications");
1131             mLastReportedNumOfUiccApplications = ics.mApplications.length;
1132 
1133             for (int i = 0; i < mUiccApplications.length; i++) {
1134                 if (mUiccApplications[i] == null) {
1135                     //Create newly added Applications
1136                     if (i < ics.mApplications.length) {
1137                         mUiccApplications[i] = new UiccCardApplication(this,
1138                                 ics.mApplications[i], mContext, mCi);
1139                     }
1140                 } else if (i >= ics.mApplications.length) {
1141                     //Delete removed applications
1142                     mUiccApplications[i].dispose();
1143                     mUiccApplications[i] = null;
1144                 } else {
1145                     //Update the rest
1146                     mUiccApplications[i].update(ics.mApplications[i], mContext, mCi);
1147                 }
1148             }
1149 
1150             createAndUpdateCatServiceLocked();
1151 
1152             // Reload the carrier privilege rules if necessary.
1153             log("Before privilege rules: " + mCarrierPrivilegeRules + " : " + ics.mCardState);
1154             if (mCarrierPrivilegeRules == null && ics.mCardState == CardState.CARDSTATE_PRESENT) {
1155                 mCarrierPrivilegeRules = new UiccCarrierPrivilegeRules(this,
1156                         mHandler.obtainMessage(EVENT_CARRIER_PRIVILEGES_LOADED));
1157             } else if (mCarrierPrivilegeRules != null
1158                     && ics.mCardState != CardState.CARDSTATE_PRESENT) {
1159                 mCarrierPrivilegeRules = null;
1160                 mContext.getContentResolver().unregisterContentObserver(
1161                         mProvisionCompleteContentObserver);
1162             }
1163 
1164             sanitizeApplicationIndexesLocked();
1165             if (mRadioTech != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
1166                 setCurrentAppType(ServiceState.isGsm(mRadioTech));
1167             }
1168             updateIccAvailability(true);
1169         }
1170     }
1171 
createAndUpdateCatServiceLocked()1172     private void createAndUpdateCatServiceLocked() {
1173         if (mUiccApplications.length > 0 && mUiccApplications[0] != null) {
1174             // Initialize or Reinitialize CatService
1175             if (mCatService == null) {
1176                 mCatService = CatService.getInstance(mCi, mContext, this, mPhoneId);
1177             } else {
1178                 mCatService.update(mCi, mContext, this);
1179             }
1180         } else {
1181             if (mCatService != null) {
1182                 mCatService.dispose();
1183             }
1184             mCatService = null;
1185         }
1186     }
1187 
1188     @Override
finalize()1189     protected void finalize() {
1190         if (DBG) log("UiccProfile finalized");
1191     }
1192 
1193     /**
1194      * This function makes sure that application indexes are valid
1195      * and resets invalid indexes. (This should never happen, but in case
1196      * RIL misbehaves we need to manage situation gracefully)
1197      */
sanitizeApplicationIndexesLocked()1198     private void sanitizeApplicationIndexesLocked() {
1199         mGsmUmtsSubscriptionAppIndex =
1200                 checkIndexLocked(
1201                         mGsmUmtsSubscriptionAppIndex, AppType.APPTYPE_SIM, AppType.APPTYPE_USIM);
1202         mCdmaSubscriptionAppIndex =
1203                 checkIndexLocked(
1204                         mCdmaSubscriptionAppIndex, AppType.APPTYPE_RUIM, AppType.APPTYPE_CSIM);
1205         mImsSubscriptionAppIndex =
1206                 checkIndexLocked(mImsSubscriptionAppIndex, AppType.APPTYPE_ISIM, null);
1207     }
1208 
1209     /**
1210      * Checks if the app is supported for the purposes of checking if all apps are ready/loaded, so
1211      * this only checks for SIM/USIM and CSIM/RUIM apps. ISIM is considered not supported for this
1212      * purpose as there are cards that have ISIM app that is never read (there are SIMs for which
1213      * the state of ISIM goes to DETECTED but never to READY).
1214      * CSIM/RUIM apps are considered not supported if CDMA is not supported.
1215      */
isSupportedApplication(UiccCardApplication app)1216     private boolean isSupportedApplication(UiccCardApplication app) {
1217         // TODO: 2/15/18 Add check to see if ISIM app will go to READY state, and if yes, check for
1218         // ISIM also (currently ISIM is considered as not supported in this function)
1219         if (app.getType() == AppType.APPTYPE_USIM || app.getType() == AppType.APPTYPE_SIM
1220                 || (UiccController.isCdmaSupported(mContext)
1221                 && (app.getType() == AppType.APPTYPE_CSIM
1222                 || app.getType() == AppType.APPTYPE_RUIM))) {
1223             return true;
1224         }
1225         return false;
1226     }
1227 
checkAndUpdateIfAnyAppToBeIgnored()1228     private void checkAndUpdateIfAnyAppToBeIgnored() {
1229         boolean[] appReadyStateTracker = new boolean[AppType.APPTYPE_ISIM.ordinal() + 1];
1230         for (UiccCardApplication app : mUiccApplications) {
1231             if (app != null && isSupportedApplication(app) && app.isReady()) {
1232                 appReadyStateTracker[app.getType().ordinal()] = true;
1233             }
1234         }
1235 
1236         for (UiccCardApplication app : mUiccApplications) {
1237             if (app != null && isSupportedApplication(app) && !app.isReady()) {
1238                 /* Checks if the  appReadyStateTracker has already an entry in ready state
1239                    with same type as app */
1240                 if (appReadyStateTracker[app.getType().ordinal()]) {
1241                     app.setAppIgnoreState(true);
1242                 }
1243             }
1244         }
1245     }
1246 
areAllApplicationsReady()1247     private boolean areAllApplicationsReady() {
1248         for (UiccCardApplication app : mUiccApplications) {
1249             if (app != null && isSupportedApplication(app) && !app.isReady()
1250                     && !app.isAppIgnored()) {
1251                 if (VDBG) log("areAllApplicationsReady: return false");
1252                 return false;
1253             }
1254         }
1255 
1256         if (VDBG) {
1257             log("areAllApplicationsReady: outside loop, return " + (mUiccApplication != null));
1258         }
1259         return mUiccApplication != null;
1260     }
1261 
areAllRecordsLoaded()1262     private boolean areAllRecordsLoaded() {
1263         for (UiccCardApplication app : mUiccApplications) {
1264             if (app != null && isSupportedApplication(app) && !app.isAppIgnored()) {
1265                 IccRecords ir = app.getIccRecords();
1266                 if (ir == null || !ir.isLoaded()) {
1267                     if (VDBG) log("areAllRecordsLoaded: return false");
1268                     return false;
1269                 }
1270             }
1271         }
1272         if (VDBG) {
1273             log("areAllRecordsLoaded: outside loop, return " + (mUiccApplication != null));
1274         }
1275         return mUiccApplication != null;
1276     }
1277 
checkIndexLocked(int index, AppType expectedAppType, AppType altExpectedAppType)1278     private int checkIndexLocked(int index, AppType expectedAppType, AppType altExpectedAppType) {
1279         if (mUiccApplications == null || index >= mUiccApplications.length) {
1280             loge("App index " + index + " is invalid since there are no applications");
1281             return -1;
1282         }
1283 
1284         if (index < 0) {
1285             // This is normal. (i.e. no application of this type)
1286             return -1;
1287         }
1288 
1289         if (mUiccApplications[index].getType() != expectedAppType
1290                 && mUiccApplications[index].getType() != altExpectedAppType) {
1291             loge("App index " + index + " is invalid since it's not "
1292                     + expectedAppType + " and not " + altExpectedAppType);
1293             return -1;
1294         }
1295 
1296         // Seems to be valid
1297         return index;
1298     }
1299 
1300     /**
1301      * Registers the handler when operator brand name is overridden.
1302      *
1303      * @param h Handler for notification message.
1304      * @param what User-defined message code.
1305      * @param obj User object.
1306      */
registerForOpertorBrandOverride(Handler h, int what, Object obj)1307     public void registerForOpertorBrandOverride(Handler h, int what, Object obj) {
1308         synchronized (mLock) {
1309             Registrant r = new Registrant(h, what, obj);
1310             mOperatorBrandOverrideRegistrants.add(r);
1311         }
1312     }
1313 
1314     /**
1315      * Unregister for notifications when operator brand name is overriden.
1316      *
1317      * @param h Handler to be removed from the registrant list.
1318      */
unregisterForOperatorBrandOverride(Handler h)1319     public void unregisterForOperatorBrandOverride(Handler h) {
1320         synchronized (mLock) {
1321             mOperatorBrandOverrideRegistrants.remove(h);
1322         }
1323     }
1324 
isPackageBundled(Context context, String pkgName)1325     static boolean isPackageBundled(Context context, String pkgName) {
1326         PackageManager pm = context.getPackageManager();
1327         try {
1328             // We also match hidden-until-installed apps. The assumption here is that some other
1329             // mechanism (like CarrierAppUtils) would automatically enable such an app, so we
1330             // shouldn't prompt the user about it.
1331             pm.getApplicationInfo(pkgName, PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS);
1332             if (DBG) log(pkgName + " is installed.");
1333             return true;
1334         } catch (PackageManager.NameNotFoundException e) {
1335             if (DBG) log(pkgName + " is not installed.");
1336             return false;
1337         }
1338     }
1339 
promptInstallCarrierApp(String pkgName)1340     private void promptInstallCarrierApp(String pkgName) {
1341         Intent showDialogIntent = InstallCarrierAppTrampolineActivity.get(mContext, pkgName);
1342         showDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
1343         mContext.startActivity(showDialogIntent);
1344     }
1345 
onCarrierPrivilegesLoadedMessage()1346     private void onCarrierPrivilegesLoadedMessage() {
1347         // TODO(b/211796398): clean up logic below once all carrier privilege check migration done
1348         // Update set of enabled carrier apps now that the privilege rules may have changed.
1349         ActivityManager am = mContext.getSystemService(ActivityManager.class);
1350         CarrierAppUtils.disableCarrierAppsUntilPrivileged(mContext.getOpPackageName(),
1351                 mTelephonyManager, am.getCurrentUser(), mContext);
1352 
1353         UsageStatsManager usm = (UsageStatsManager) mContext.getSystemService(
1354                 Context.USAGE_STATS_SERVICE);
1355         if (usm != null) {
1356             usm.onCarrierPrivilegedAppsChanged();
1357         }
1358 
1359         InstallCarrierAppUtils.hideAllNotifications(mContext);
1360         InstallCarrierAppUtils.unregisterPackageInstallReceiver(mContext);
1361 
1362         synchronized (mLock) {
1363             boolean isProvisioned = isProvisioned();
1364             boolean isUnlocked = isUserUnlocked();
1365             // Only show dialog if the phone is through with Setup Wizard and is unlocked.
1366             // Otherwise, wait for completion and unlock and show a notification instead.
1367             if (isProvisioned && isUnlocked) {
1368                 for (String pkgName : getUninstalledCarrierPackages()) {
1369                     promptInstallCarrierApp(pkgName);
1370                 }
1371             } else {
1372                 if (!isProvisioned) {
1373                     final Uri uri = Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED);
1374                     mContext.getContentResolver().registerContentObserver(
1375                             uri,
1376                             false,
1377                             mProvisionCompleteContentObserver);
1378                     mProvisionCompleteContentObserverRegistered = true;
1379                 }
1380                 if (!isUnlocked) {
1381                     mContext.registerReceiver(
1382                             mUserUnlockReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));
1383                     mUserUnlockReceiverRegistered = true;
1384                 }
1385             }
1386         }
1387     }
1388 
isProvisioned()1389     private boolean isProvisioned() {
1390         return Settings.Global.getInt(
1391                 mContext.getContentResolver(),
1392                 Settings.Global.DEVICE_PROVISIONED, 1) == 1;
1393     }
1394 
isUserUnlocked()1395     private boolean isUserUnlocked() {
1396         return mContext.getSystemService(UserManager.class).isUserUnlocked();
1397     }
1398 
showCarrierAppNotificationsIfPossible()1399     private void showCarrierAppNotificationsIfPossible() {
1400         if (isProvisioned() && isUserUnlocked()) {
1401             for (String pkgName : getUninstalledCarrierPackages()) {
1402                 InstallCarrierAppUtils.showNotification(mContext, pkgName);
1403                 InstallCarrierAppUtils.registerPackageInstallReceiver(mContext);
1404             }
1405         }
1406     }
1407 
getUninstalledCarrierPackages()1408     private Set<String> getUninstalledCarrierPackages() {
1409         String allowListSetting = Settings.Global.getString(
1410                 mContext.getContentResolver(),
1411                 Settings.Global.CARRIER_APP_WHITELIST);
1412         if (TextUtils.isEmpty(allowListSetting)) {
1413             return Collections.emptySet();
1414         }
1415         Map<String, String> certPackageMap = parseToCertificateToPackageMap(allowListSetting);
1416         if (certPackageMap.isEmpty()) {
1417             return Collections.emptySet();
1418         }
1419         UiccCarrierPrivilegeRules rules = getCarrierPrivilegeRules();
1420         if (rules == null) {
1421             return Collections.emptySet();
1422         }
1423         Set<String> uninstalledCarrierPackages = new ArraySet<>();
1424         List<UiccAccessRule> accessRules = rules.getAccessRules();
1425         for (UiccAccessRule accessRule : accessRules) {
1426             String certHexString = accessRule.getCertificateHexString().toUpperCase(Locale.ROOT);
1427             String pkgName = certPackageMap.get(certHexString);
1428             if (!TextUtils.isEmpty(pkgName) && !isPackageBundled(mContext, pkgName)) {
1429                 uninstalledCarrierPackages.add(pkgName);
1430             }
1431         }
1432         return uninstalledCarrierPackages;
1433     }
1434 
1435     /**
1436      * Converts a string in the format: key1:value1;key2:value2... into a map where the keys are
1437      * hex representations of app certificates - all upper case - and the values are package names
1438      * @hide
1439      */
1440     @VisibleForTesting
parseToCertificateToPackageMap(String allowListSetting)1441     public static Map<String, String> parseToCertificateToPackageMap(String allowListSetting) {
1442         final String pairDelim = "\\s*;\\s*";
1443         final String keyValueDelim = "\\s*:\\s*";
1444 
1445         List<String> keyValuePairList = Arrays.asList(allowListSetting.split(pairDelim));
1446 
1447         if (keyValuePairList.isEmpty()) {
1448             return Collections.emptyMap();
1449         }
1450 
1451         Map<String, String> map = new ArrayMap<>(keyValuePairList.size());
1452         for (String keyValueString: keyValuePairList) {
1453             String[] keyValue = keyValueString.split(keyValueDelim);
1454 
1455             if (keyValue.length == 2) {
1456                 map.put(keyValue[0].toUpperCase(Locale.ROOT), keyValue[1]);
1457             } else {
1458                 loge("Incorrect length of key-value pair in carrier app allow list map.  "
1459                         + "Length should be exactly 2");
1460             }
1461         }
1462 
1463         return map;
1464     }
1465 
1466     /**
1467      * Check whether the specified type of application exists in the profile.
1468      *
1469      * @param type UICC application type.
1470      */
isApplicationOnIcc(IccCardApplicationStatus.AppType type)1471     public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) {
1472         synchronized (mLock) {
1473             for (int i = 0; i < mUiccApplications.length; i++) {
1474                 if (mUiccApplications[i] != null && mUiccApplications[i].getType() == type) {
1475                     return true;
1476                 }
1477             }
1478             return false;
1479         }
1480     }
1481 
1482     /**
1483      * Return the universal pin state of the profile.
1484      */
getUniversalPinState()1485     public PinState getUniversalPinState() {
1486         synchronized (mLock) {
1487             return mUniversalPinState;
1488         }
1489     }
1490 
1491     /**
1492      * Return the application of the specified family.
1493      *
1494      * @param family UICC application family.
1495      * @return application corresponding to family or a null if no match found
1496      */
getApplication(int family)1497     public UiccCardApplication getApplication(int family) {
1498         synchronized (mLock) {
1499             int index = IccCardStatus.CARD_MAX_APPS;
1500             switch (family) {
1501                 case UiccController.APP_FAM_3GPP:
1502                     index = mGsmUmtsSubscriptionAppIndex;
1503                     break;
1504                 case UiccController.APP_FAM_3GPP2:
1505                     index = mCdmaSubscriptionAppIndex;
1506                     break;
1507                 case UiccController.APP_FAM_IMS:
1508                     index = mImsSubscriptionAppIndex;
1509                     break;
1510             }
1511             if (index >= 0 && index < mUiccApplications.length) {
1512                 return mUiccApplications[index];
1513             }
1514             return null;
1515         }
1516     }
1517 
1518     /**
1519      * Return the application with the index of the array.
1520      *
1521      * @param index Index of the application array.
1522      * @return application corresponding to index or a null if no match found
1523      */
getApplicationIndex(int index)1524     public UiccCardApplication getApplicationIndex(int index) {
1525         synchronized (mLock) {
1526             if (index >= 0 && index < mUiccApplications.length) {
1527                 return mUiccApplications[index];
1528             }
1529             return null;
1530         }
1531     }
1532 
1533     /**
1534      * Returns the SIM application of the specified type.
1535      *
1536      * @param type ICC application type
1537      * (@see com.android.internal.telephony.PhoneConstants#APPTYPE_xxx)
1538      * @return application corresponding to type or a null if no match found
1539      */
getApplicationByType(int type)1540     public UiccCardApplication getApplicationByType(int type) {
1541         synchronized (mLock) {
1542             for (int i = 0; i < mUiccApplications.length; i++) {
1543                 if (mUiccApplications[i] != null
1544                         && mUiccApplications[i].getType().ordinal() == type) {
1545                     return mUiccApplications[i];
1546                 }
1547             }
1548             return null;
1549         }
1550     }
1551 
1552     /**
1553      * Resets the application with the input AID.
1554      *
1555      * A null aid implies a card level reset - all applications must be reset.
1556      *
1557      * @param aid aid of the application which should be reset; null imples all applications
1558      * @param reset true if reset is required. false for initialization.
1559      * @return boolean indicating if there was any change made as part of the reset which
1560      * requires carrier config to be reset too (for e.g. if only ISIM app is refreshed carrier
1561      * config should not be reset)
1562      */
1563     @VisibleForTesting
resetAppWithAid(String aid, boolean reset)1564     public boolean resetAppWithAid(String aid, boolean reset) {
1565         synchronized (mLock) {
1566             boolean changed = false;
1567             boolean isIsimRefresh = false;
1568             for (int i = 0; i < mUiccApplications.length; i++) {
1569                 if (mUiccApplications[i] != null
1570                         && (TextUtils.isEmpty(aid) || aid.equals(mUiccApplications[i].getAid()))) {
1571                     // Resetting only ISIM does not need to be treated as a change from caller
1572                     // perspective, as it does not affect SIM state now or even later when ISIM
1573                     // is re-loaded, hence return false.
1574                     if (!TextUtils.isEmpty(aid)
1575                             && mUiccApplications[i].getType() == AppType.APPTYPE_ISIM) {
1576                         isIsimRefresh = true;
1577                     }
1578 
1579                     // Delete removed applications
1580                     mUiccApplications[i].dispose();
1581                     mUiccApplications[i] = null;
1582                     changed = true;
1583                 }
1584             }
1585             if (reset && TextUtils.isEmpty(aid)) {
1586                 if (mCarrierPrivilegeRules != null) {
1587                     mCarrierPrivilegeRules = null;
1588                     mContext.getContentResolver().unregisterContentObserver(
1589                             mProvisionCompleteContentObserver);
1590                     changed = true;
1591                 }
1592                 // CatService shall be disposed only when a card level reset happens.
1593                 if (mCatService != null) {
1594                     mCatService.dispose();
1595                     mCatService = null;
1596                     changed = true;
1597                 }
1598             }
1599             return changed && !isIsimRefresh;
1600         }
1601     }
1602 
1603     /**
1604      * Exposes {@link CommandsInterface#iccOpenLogicalChannel}
1605      */
iccOpenLogicalChannel(String aid, int p2, Message response)1606     public void iccOpenLogicalChannel(String aid, int p2, Message response) {
1607         logWithLocalLog("iccOpenLogicalChannel: " + aid + " , " + p2 + " by pid:"
1608                 + Binder.getCallingPid() + " uid:" + Binder.getCallingUid());
1609         mCi.iccOpenLogicalChannel(aid, p2,
1610                 mHandler.obtainMessage(EVENT_OPEN_LOGICAL_CHANNEL_DONE, response));
1611     }
1612 
1613     /**
1614      * Exposes {@link CommandsInterface#iccCloseLogicalChannel}
1615      */
iccCloseLogicalChannel(int channel, boolean isEs10, Message response)1616     public void iccCloseLogicalChannel(int channel, boolean isEs10, Message response) {
1617         logWithLocalLog("iccCloseLogicalChannel: " + channel);
1618         mCi.iccCloseLogicalChannel(channel, isEs10,
1619                 mHandler.obtainMessage(EVENT_CLOSE_LOGICAL_CHANNEL_DONE, response));
1620     }
1621 
1622     /**
1623      * Exposes {@link CommandsInterface#iccTransmitApduLogicalChannel}
1624      */
iccTransmitApduLogicalChannel(int channel, int cla, int command, int p1, int p2, int p3, String data, boolean isEs10Command, Message response)1625     public void iccTransmitApduLogicalChannel(int channel, int cla, int command,
1626             int p1, int p2, int p3, String data, boolean isEs10Command, Message response) {
1627         mCi.iccTransmitApduLogicalChannel(channel, cla, command, p1, p2, p3, data, isEs10Command,
1628                 mHandler.obtainMessage(EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE, response));
1629     }
1630 
1631     /**
1632      * Exposes {@link CommandsInterface#iccTransmitApduBasicChannel}
1633      */
iccTransmitApduBasicChannel(int cla, int command, int p1, int p2, int p3, String data, Message response)1634     public void iccTransmitApduBasicChannel(int cla, int command,
1635             int p1, int p2, int p3, String data, Message response) {
1636         mCi.iccTransmitApduBasicChannel(cla, command, p1, p2, p3,
1637                 data, mHandler.obtainMessage(EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE, response));
1638     }
1639 
1640     /**
1641      * Exposes {@link CommandsInterface#iccIO}
1642      */
iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3, String pathID, Message response)1643     public void iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
1644             String pathID, Message response) {
1645         mCi.iccIO(command, fileID, pathID, p1, p2, p3, null, null,
1646                 mHandler.obtainMessage(EVENT_SIM_IO_DONE, response));
1647     }
1648 
1649     /**
1650      * Exposes {@link CommandsInterface#sendEnvelopeWithStatus}
1651      */
sendEnvelopeWithStatus(String contents, Message response)1652     public void sendEnvelopeWithStatus(String contents, Message response) {
1653         mCi.sendEnvelopeWithStatus(contents, response);
1654     }
1655 
1656     /**
1657      * Returns number of applications on this card
1658      */
getNumApplications()1659     public int getNumApplications() {
1660         return mLastReportedNumOfUiccApplications;
1661     }
1662 
1663     /**
1664      * Returns the id of the phone which is associated with this profile.
1665      */
getPhoneId()1666     public int getPhoneId() {
1667         return mPhoneId;
1668     }
1669 
1670     /**
1671      * Returns true iff carrier privileges rules are null (dont need to be loaded) or loaded.
1672      */
1673     @VisibleForTesting
areCarrierPrivilegeRulesLoaded()1674     public boolean areCarrierPrivilegeRulesLoaded() {
1675         UiccCarrierPrivilegeRules carrierPrivilegeRules = getCarrierPrivilegeRules();
1676         return carrierPrivilegeRules == null
1677                 || carrierPrivilegeRules.areCarrierPriviligeRulesLoaded();
1678     }
1679 
1680     /**
1681      * Return a list of certs in hex string from loaded carrier privileges access rules.
1682      *
1683      * @return a list of certificate in hex string. return {@code null} if there is no certs
1684      * or privilege rules are not loaded yet.
1685      */
getCertsFromCarrierPrivilegeAccessRules()1686     public List<String> getCertsFromCarrierPrivilegeAccessRules() {
1687         final List<String> certs = new ArrayList<>();
1688         final UiccCarrierPrivilegeRules carrierPrivilegeRules = getCarrierPrivilegeRules();
1689         if (carrierPrivilegeRules != null) {
1690             List<UiccAccessRule> accessRules = carrierPrivilegeRules.getAccessRules();
1691             for (UiccAccessRule accessRule : accessRules) {
1692                 certs.add(accessRule.getCertificateHexString());
1693             }
1694         }
1695         return certs.isEmpty() ? null : certs;
1696     }
1697 
1698     /** @return a list of {@link UiccAccessRule}s, or an empty list if none have been loaded yet. */
getCarrierPrivilegeAccessRules()1699     public List<UiccAccessRule> getCarrierPrivilegeAccessRules() {
1700         UiccCarrierPrivilegeRules carrierPrivilegeRules = getCarrierPrivilegeRules();
1701         if (carrierPrivilegeRules == null) {
1702             return Collections.EMPTY_LIST;
1703         }
1704         return new ArrayList<>(carrierPrivilegeRules.getAccessRules());
1705     }
1706 
1707     /** Returns a reference to the current {@link UiccCarrierPrivilegeRules}. */
getCarrierPrivilegeRules()1708     private UiccCarrierPrivilegeRules getCarrierPrivilegeRules() {
1709         synchronized (mLock) {
1710             if (mTestOverrideCarrierPrivilegeRules != null) {
1711                 return mTestOverrideCarrierPrivilegeRules;
1712             }
1713             return mCarrierPrivilegeRules;
1714         }
1715     }
1716 
1717     /**
1718      * Sets the overridden operator brand.
1719      */
setOperatorBrandOverride(String brand)1720     public boolean setOperatorBrandOverride(String brand) {
1721         log("setOperatorBrandOverride: " + brand);
1722         log("current iccId: " + SubscriptionInfo.getPrintableId(getIccId()));
1723 
1724         String iccId = getIccId();
1725         if (TextUtils.isEmpty(iccId)) {
1726             return false;
1727         }
1728 
1729         int subId = SubscriptionManager.getSubscriptionId(getPhoneId());
1730         SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance()
1731                 .getSubscriptionInfoInternal(subId);
1732         if (subInfo == null) {
1733             loge("setOperatorBrandOverride: Cannot find subscription info for sub " + subId);
1734             return false;
1735         }
1736 
1737         List<SubscriptionInfo> subInfos = new ArrayList<>();
1738         subInfos.add(subInfo.toSubscriptionInfo());
1739         String groupUuid = subInfo.getGroupUuid();
1740         if (!TextUtils.isEmpty(groupUuid)) {
1741             subInfos.addAll(SubscriptionManagerService.getInstance()
1742                     .getSubscriptionsInGroup(ParcelUuid.fromString(groupUuid),
1743                             mContext.getOpPackageName(), mContext.getFeatureId()));
1744         }
1745 
1746         if (subInfos.stream().noneMatch(info -> TextUtils.equals(IccUtils.stripTrailingFs(
1747                 info.getIccId()), IccUtils.stripTrailingFs(iccId)))) {
1748             loge("iccId doesn't match current active subId.");
1749             return false;
1750         }
1751 
1752         SharedPreferences.Editor spEditor =
1753                 PreferenceManager.getDefaultSharedPreferences(mContext).edit();
1754         String key = OPERATOR_BRAND_OVERRIDE_PREFIX + iccId;
1755         if (brand == null) {
1756             spEditor.remove(key).commit();
1757         } else {
1758             spEditor.putString(key, brand).commit();
1759         }
1760         mOperatorBrandOverrideRegistrants.notifyRegistrants();
1761         return true;
1762     }
1763 
1764     /**
1765      * Returns the overridden operator brand.
1766      */
getOperatorBrandOverride()1767     public String getOperatorBrandOverride() {
1768         String iccId = getIccId();
1769         if (TextUtils.isEmpty(iccId)) {
1770             return null;
1771         }
1772         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
1773         return sp.getString(OPERATOR_BRAND_OVERRIDE_PREFIX + iccId, null);
1774     }
1775 
1776     /**
1777      * Returns the iccid of the profile.
1778      */
getIccId()1779     public String getIccId() {
1780         // ICCID should be same across all the apps.
1781         for (UiccCardApplication app : mUiccApplications) {
1782             if (app != null) {
1783                 IccRecords ir = app.getIccRecords();
1784                 if (ir != null && ir.getIccId() != null) {
1785                     return ir.getIccId();
1786                 }
1787             }
1788         }
1789         return null;
1790     }
1791 
eventToString(int event)1792     private static String eventToString(int event) {
1793         switch (event) {
1794             case EVENT_RADIO_OFF_OR_UNAVAILABLE: return "RADIO_OFF_OR_UNAVAILABLE";
1795             case EVENT_ICC_LOCKED: return "ICC_LOCKED";
1796             case EVENT_APP_READY: return "APP_READY";
1797             case EVENT_RECORDS_LOADED: return "RECORDS_LOADED";
1798             case EVENT_NETWORK_LOCKED: return "NETWORK_LOCKED";
1799             case EVENT_EID_READY: return "EID_READY";
1800             case EVENT_ICC_RECORD_EVENTS: return "ICC_RECORD_EVENTS";
1801             case EVENT_OPEN_LOGICAL_CHANNEL_DONE: return "OPEN_LOGICAL_CHANNEL_DONE";
1802             case EVENT_CLOSE_LOGICAL_CHANNEL_DONE: return "CLOSE_LOGICAL_CHANNEL_DONE";
1803             case EVENT_TRANSMIT_APDU_LOGICAL_CHANNEL_DONE:
1804                 return "TRANSMIT_APDU_LOGICAL_CHANNEL_DONE";
1805             case EVENT_TRANSMIT_APDU_BASIC_CHANNEL_DONE: return "TRANSMIT_APDU_BASIC_CHANNEL_DONE";
1806             case EVENT_SIM_IO_DONE: return "SIM_IO_DONE";
1807             case EVENT_CARRIER_PRIVILEGES_LOADED: return "CARRIER_PRIVILEGES_LOADED";
1808             case EVENT_CARRIER_CONFIG_CHANGED: return "CARRIER_CONFIG_CHANGED";
1809             case EVENT_CARRIER_PRIVILEGES_TEST_OVERRIDE_SET:
1810                 return "CARRIER_PRIVILEGES_TEST_OVERRIDE_SET";
1811             case EVENT_SUPPLY_ICC_PIN_DONE: return "SUPPLY_ICC_PIN_DONE";
1812             default: return "UNKNOWN(" + event + ")";
1813         }
1814     }
1815 
log(String msg)1816     private static void log(String msg) {
1817         Rlog.d(LOG_TAG, msg);
1818     }
1819 
loge(String msg)1820     private static void loge(String msg) {
1821         Rlog.e(LOG_TAG, msg);
1822     }
1823 
logWithLocalLog(String msg)1824     private void logWithLocalLog(String msg) {
1825         Rlog.d(LOG_TAG, msg);
1826         if (DBG) UiccController.addLocalLog("UiccProfile[" + mPhoneId + "]: " + msg);
1827     }
1828 
1829     /**
1830      * Reloads carrier privileges as if a change were just detected.  Useful to force a profile
1831      * refresh without having to physically insert or remove a SIM card.
1832      */
1833     @VisibleForTesting
refresh()1834     public void refresh() {
1835         mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARRIER_PRIVILEGES_LOADED));
1836     }
1837 
1838     /**
1839      * Set a test set of carrier privilege rules which will override the actual rules on the SIM.
1840      *
1841      * <p>May be null, in which case the rules on the SIM will be used and any previous overrides
1842      * will be cleared.
1843      *
1844      * @see TelephonyManager#setCarrierTestOverride
1845      */
setTestOverrideCarrierPrivilegeRules(@ullable List<UiccAccessRule> rules)1846     public void setTestOverrideCarrierPrivilegeRules(@Nullable List<UiccAccessRule> rules) {
1847         mHandler.sendMessage(
1848                 mHandler.obtainMessage(EVENT_CARRIER_PRIVILEGES_TEST_OVERRIDE_SET, rules));
1849     }
1850 
1851     /**
1852      * Dump
1853      */
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1854     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
1855         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
1856         pw.increaseIndent();
1857         pw.println("mCatService=" + mCatService);
1858         for (int i = 0; i < mOperatorBrandOverrideRegistrants.size(); i++) {
1859             pw.println("mOperatorBrandOverrideRegistrants[" + i + "]="
1860                     + ((Registrant) mOperatorBrandOverrideRegistrants.get(i)).getHandler());
1861         }
1862         pw.println("mUniversalPinState=" + mUniversalPinState);
1863         pw.println("mGsmUmtsSubscriptionAppIndex=" + mGsmUmtsSubscriptionAppIndex);
1864         pw.println("mCdmaSubscriptionAppIndex=" + mCdmaSubscriptionAppIndex);
1865         pw.println("mImsSubscriptionAppIndex=" + mImsSubscriptionAppIndex);
1866         pw.println("mUiccApplications: length=" + mUiccApplications.length);
1867         pw.increaseIndent();
1868         for (int i = 0; i < mUiccApplications.length; i++) {
1869             if (mUiccApplications[i] == null) {
1870                 pw.println("mUiccApplications[" + i + "]=" + null);
1871             } else {
1872                 pw.println("mUiccApplications[" + i + "]="
1873                         + mUiccApplications[i].getType() + " " + mUiccApplications[i]);
1874             }
1875         }
1876         pw.decreaseIndent();
1877         pw.println();
1878         // Print details of all applications
1879         for (UiccCardApplication app : mUiccApplications) {
1880             if (app != null) {
1881                 app.dump(fd, pw, args);
1882                 pw.println();
1883             }
1884         }
1885         // Print details of all IccRecords
1886         for (UiccCardApplication app : mUiccApplications) {
1887             if (app != null) {
1888                 IccRecords ir = app.getIccRecords();
1889                 if (ir != null) {
1890                     ir.dump(fd, pw, args);
1891                     pw.println();
1892                 }
1893             }
1894         }
1895         // Print UiccCarrierPrivilegeRules and registrants.
1896         if (mCarrierPrivilegeRules == null) {
1897             pw.println("mCarrierPrivilegeRules: null");
1898         } else {
1899             pw.println("mCarrierPrivilegeRules: ");
1900             pw.increaseIndent();
1901             mCarrierPrivilegeRules.dump(fd, pw, args);
1902             pw.decreaseIndent();
1903         }
1904         if (mTestOverrideCarrierPrivilegeRules != null) {
1905             pw.println("mTestOverrideCarrierPrivilegeRules: "
1906                     + mTestOverrideCarrierPrivilegeRules);
1907             mTestOverrideCarrierPrivilegeRules.dump(fd, pw, args);
1908         }
1909         pw.flush();
1910 
1911         pw.println("mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size());
1912         for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) {
1913             pw.println("  mNetworkLockedRegistrants[" + i + "]="
1914                     + ((Registrant) mNetworkLockedRegistrants.get(i)).getHandler());
1915         }
1916         pw.println("mCurrentAppType=" + mCurrentAppType);
1917         pw.println("mUiccCard=" + mUiccCard);
1918         pw.println("mUiccApplication=" + mUiccApplication);
1919         pw.println("mIccRecords=" + mIccRecords);
1920         pw.println("mExternalState=" + mExternalState);
1921         pw.decreaseIndent();
1922         pw.flush();
1923     }
1924 }
1925