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