• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 package com.android.internal.telephony;
18 
19 import android.Manifest;
20 import android.annotation.Nullable;
21 import android.app.ActivityManager;
22 import android.compat.annotation.UnsupportedAppUsage;
23 import android.content.BroadcastReceiver;
24 import android.content.ContentResolver;
25 import android.content.ContentValues;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.content.SharedPreferences;
30 import android.os.AsyncResult;
31 import android.os.Handler;
32 import android.os.Looper;
33 import android.os.Message;
34 import android.os.ParcelUuid;
35 import android.os.PersistableBundle;
36 import android.os.UserHandle;
37 import android.preference.PreferenceManager;
38 import android.provider.Settings;
39 import android.provider.Settings.Global;
40 import android.provider.Settings.SettingNotFoundException;
41 import android.service.carrier.CarrierIdentifier;
42 import android.service.carrier.CarrierService;
43 import android.service.euicc.EuiccProfileInfo;
44 import android.service.euicc.EuiccService;
45 import android.service.euicc.GetEuiccProfileInfoListResult;
46 import android.telephony.CarrierConfigManager;
47 import android.telephony.SubscriptionInfo;
48 import android.telephony.SubscriptionManager;
49 import android.telephony.TelephonyManager;
50 import android.telephony.TelephonyManager.SimState;
51 import android.telephony.UiccAccessRule;
52 import android.telephony.euicc.EuiccManager;
53 import android.text.TextUtils;
54 import android.util.Pair;
55 
56 import com.android.internal.annotations.VisibleForTesting;
57 import com.android.internal.telephony.euicc.EuiccController;
58 import com.android.internal.telephony.metrics.TelephonyMetrics;
59 import com.android.internal.telephony.uicc.IccRecords;
60 import com.android.internal.telephony.uicc.IccUtils;
61 import com.android.internal.telephony.uicc.UiccCard;
62 import com.android.internal.telephony.uicc.UiccController;
63 import com.android.internal.telephony.uicc.UiccSlot;
64 import com.android.telephony.Rlog;
65 
66 import java.io.FileDescriptor;
67 import java.io.PrintWriter;
68 import java.util.ArrayList;
69 import java.util.List;
70 
71 /**
72  *@hide
73  */
74 public class SubscriptionInfoUpdater extends Handler {
75     private static final String LOG_TAG = "SubscriptionInfoUpdater";
76     @UnsupportedAppUsage
77     private static final int SUPPORTED_MODEM_COUNT = TelephonyManager.getDefault()
78             .getSupportedModemCount();
79 
80     private static final boolean DBG = true;
81 
82     private static final int EVENT_INVALID = -1;
83     private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 2;
84     private static final int EVENT_SIM_LOADED = 3;
85     private static final int EVENT_SIM_ABSENT = 4;
86     private static final int EVENT_SIM_LOCKED = 5;
87     private static final int EVENT_SIM_IO_ERROR = 6;
88     private static final int EVENT_SIM_UNKNOWN = 7;
89     private static final int EVENT_SIM_RESTRICTED = 8;
90     private static final int EVENT_SIM_NOT_READY = 9;
91     private static final int EVENT_SIM_READY = 10;
92     private static final int EVENT_SIM_IMSI = 11;
93     private static final int EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS = 12;
94     private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 13;
95     private static final int EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED = 14;
96 
97     private static final String ICCID_STRING_FOR_NO_SIM = "";
98 
99     private static final ParcelUuid REMOVE_GROUP_UUID =
100             ParcelUuid.fromString(CarrierConfigManager.REMOVE_GROUP_UUID_STRING);
101 
102     // Key used to read/write the current IMSI. Updated on SIM_STATE_CHANGED - LOADED.
103     public static final String CURR_SUBID = "curr_subid";
104 
105     @UnsupportedAppUsage
106     private static Context sContext = null;
107     @UnsupportedAppUsage
108 
109     protected static String[] sIccId = new String[SUPPORTED_MODEM_COUNT];
110     private static String[] sInactiveIccIds = new String[SUPPORTED_MODEM_COUNT];
111     private static int[] sSimCardState = new int[SUPPORTED_MODEM_COUNT];
112     private static int[] sSimApplicationState = new int[SUPPORTED_MODEM_COUNT];
113     private static boolean sIsSubInfoInitialized = false;
114     private SubscriptionManager mSubscriptionManager = null;
115     private EuiccManager mEuiccManager;
116     private Handler mBackgroundHandler;
117 
118     // The current foreground user ID.
119     @UnsupportedAppUsage
120     private int mCurrentlyActiveUserId;
121     private CarrierServiceBindHelper mCarrierServiceBindHelper;
122 
123     /**
124      * Runnable with a boolean parameter. This is used in
125      * updateEmbeddedSubscriptions(List<Integer> cardIds, @Nullable UpdateEmbeddedSubsCallback).
126      */
127     protected interface UpdateEmbeddedSubsCallback {
128         /**
129          * Callback of the Runnable.
130          * @param hasChanges Whether there is any subscription info change. If yes, we need to
131          * notify the listeners.
132          */
run(boolean hasChanges)133         void run(boolean hasChanges);
134     }
135 
136     // TODO: The SubscriptionController instance should be passed in here from PhoneFactory
137     // rather than invoking the static getter all over the place.
SubscriptionInfoUpdater(Looper looper, Context context, CommandsInterface[] ci)138     @VisibleForTesting public SubscriptionInfoUpdater(Looper looper, Context context,
139             CommandsInterface[] ci) {
140         logd("Constructor invoked");
141         mBackgroundHandler = new Handler(looper);
142 
143         sContext = context;
144         mSubscriptionManager = SubscriptionManager.from(sContext);
145         mEuiccManager = (EuiccManager) sContext.getSystemService(Context.EUICC_SERVICE);
146 
147         mCarrierServiceBindHelper = new CarrierServiceBindHelper(sContext);
148         initializeCarrierApps();
149 
150         PhoneConfigurationManager.registerForMultiSimConfigChange(
151                 this, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
152     }
153 
initializeCarrierApps()154     private void initializeCarrierApps() {
155         // Initialize carrier apps:
156         // -Now (on system startup)
157         // -Whenever new carrier privilege rules might change (new SIM is loaded)
158         // -Whenever we switch to a new user
159         mCurrentlyActiveUserId = 0;
160         sContext.registerReceiverForAllUsers(new BroadcastReceiver() {
161             @Override
162             public void onReceive(Context context, Intent intent) {
163                 // Remove this line after testing
164                 if (Intent.ACTION_USER_FOREGROUND.equals(intent.getAction())) {
165                     UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
166                     // If couldn't get current user ID, guess it's 0.
167                     mCurrentlyActiveUserId = userHandle != null ? userHandle.getIdentifier() : 0;
168                     CarrierAppUtils.disableCarrierAppsUntilPrivileged(sContext.getOpPackageName(),
169                             TelephonyManager.getDefault(), mCurrentlyActiveUserId, sContext);
170                 }
171             }
172         }, new IntentFilter(Intent.ACTION_USER_FOREGROUND), null, null);
173         ActivityManager am = (ActivityManager) sContext.getSystemService(Context.ACTIVITY_SERVICE);
174         mCurrentlyActiveUserId = am.getCurrentUser();
175         CarrierAppUtils.disableCarrierAppsUntilPrivileged(sContext.getOpPackageName(),
176                 TelephonyManager.getDefault(), mCurrentlyActiveUserId, sContext);
177     }
178 
179     /**
180      * Update subscriptions when given a new ICC state.
181      */
updateInternalIccState(String simStatus, String reason, int phoneId)182     public void updateInternalIccState(String simStatus, String reason, int phoneId) {
183         logd("updateInternalIccState to simStatus " + simStatus + " reason " + reason
184                 + " phoneId " + phoneId);
185         int message = internalIccStateToMessage(simStatus);
186         if (message != EVENT_INVALID) {
187             sendMessage(obtainMessage(message, phoneId, 0, reason));
188         }
189     }
190 
191     /**
192      * Update subscriptions if needed when there's a change in inactive slot.
193      * @param prevActivePhoneId is the corresponding phoneId of the slot if slot was previously
194      *                          active. It could be INVALID if it was already inactive.
195      * @param iccId iccId in that slot, if any.
196      */
updateInternalIccStateForInactiveSlot(int prevActivePhoneId, String iccId)197     public void updateInternalIccStateForInactiveSlot(int prevActivePhoneId, String iccId) {
198         sendMessage(obtainMessage(EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED, prevActivePhoneId,
199                 0, iccId));
200     }
201 
internalIccStateToMessage(String simStatus)202     private int internalIccStateToMessage(String simStatus) {
203         switch(simStatus) {
204             case IccCardConstants.INTENT_VALUE_ICC_ABSENT: return EVENT_SIM_ABSENT;
205             case IccCardConstants.INTENT_VALUE_ICC_UNKNOWN: return EVENT_SIM_UNKNOWN;
206             case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR: return EVENT_SIM_IO_ERROR;
207             case IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED: return EVENT_SIM_RESTRICTED;
208             case IccCardConstants.INTENT_VALUE_ICC_NOT_READY: return EVENT_SIM_NOT_READY;
209             case IccCardConstants.INTENT_VALUE_ICC_LOCKED: return EVENT_SIM_LOCKED;
210             case IccCardConstants.INTENT_VALUE_ICC_LOADED: return EVENT_SIM_LOADED;
211             case IccCardConstants.INTENT_VALUE_ICC_READY: return EVENT_SIM_READY;
212             case IccCardConstants.INTENT_VALUE_ICC_IMSI: return EVENT_SIM_IMSI;
213             default:
214                 logd("Ignoring simStatus: " + simStatus);
215                 return EVENT_INVALID;
216         }
217     }
218 
219     @UnsupportedAppUsage
isAllIccIdQueryDone()220     protected boolean isAllIccIdQueryDone() {
221         for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) {
222             UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(i);
223             int slotId = UiccController.getInstance().getSlotIdFromPhoneId(i);
224             if  (sIccId[i] == null || slot == null || !slot.isActive()) {
225                 if (sIccId[i] == null) {
226                     logd("Wait for SIM " + i + " Iccid");
227                 } else {
228                     logd(String.format("Wait for slot corresponding to phone %d to be active, "
229                             + "slotId is %d", i, slotId));
230                 }
231                 return false;
232             }
233         }
234         logd("All IccIds query complete");
235 
236         return true;
237     }
238 
239     @Override
handleMessage(Message msg)240     public void handleMessage(Message msg) {
241         List<Integer> cardIds = new ArrayList<>();
242         switch (msg.what) {
243             case EVENT_GET_NETWORK_SELECTION_MODE_DONE: {
244                 AsyncResult ar = (AsyncResult)msg.obj;
245                 Integer slotId = (Integer)ar.userObj;
246                 if (ar.exception == null && ar.result != null) {
247                     int[] modes = (int[])ar.result;
248                     if (modes[0] == 1) {  // Manual mode.
249                         PhoneFactory.getPhone(slotId).setNetworkSelectionModeAutomatic(null);
250                     }
251                 } else {
252                     logd("EVENT_GET_NETWORK_SELECTION_MODE_DONE: error getting network mode.");
253                 }
254                 break;
255             }
256 
257             case EVENT_SIM_LOADED:
258                 handleSimLoaded(msg.arg1);
259                 break;
260 
261             case EVENT_SIM_ABSENT:
262                 handleSimAbsent(msg.arg1);
263                 break;
264 
265             case EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED:
266                 handleInactiveSlotIccStateChange(msg.arg1, (String) msg.obj);
267                 break;
268 
269             case EVENT_SIM_LOCKED:
270                 handleSimLocked(msg.arg1, (String) msg.obj);
271                 break;
272 
273             case EVENT_SIM_UNKNOWN:
274                 broadcastSimStateChanged(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN, null);
275                 broadcastSimCardStateChanged(msg.arg1, TelephonyManager.SIM_STATE_UNKNOWN);
276                 broadcastSimApplicationStateChanged(msg.arg1, TelephonyManager.SIM_STATE_UNKNOWN);
277                 updateSubscriptionCarrierId(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN);
278                 updateCarrierServices(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN);
279                 break;
280 
281             case EVENT_SIM_IO_ERROR:
282                 handleSimError(msg.arg1);
283                 break;
284 
285             case EVENT_SIM_RESTRICTED:
286                 broadcastSimStateChanged(msg.arg1,
287                         IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED,
288                         IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED);
289                 broadcastSimCardStateChanged(msg.arg1, TelephonyManager.SIM_STATE_CARD_RESTRICTED);
290                 broadcastSimApplicationStateChanged(msg.arg1, TelephonyManager.SIM_STATE_NOT_READY);
291                 updateSubscriptionCarrierId(msg.arg1,
292                         IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED);
293                 updateCarrierServices(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED);
294                 break;
295 
296             case EVENT_SIM_READY:
297                 handleSimReady(msg.arg1);
298                 break;
299 
300             case EVENT_SIM_IMSI:
301                 broadcastSimStateChanged(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_IMSI, null);
302                 break;
303 
304             case EVENT_SIM_NOT_READY:
305                 // an eUICC with no active subscriptions never becomes ready, so we need to trigger
306                 // the embedded subscriptions update here
307                 cardIds.add(getCardIdFromPhoneId(msg.arg1));
308                 updateEmbeddedSubscriptions(cardIds, (hasChanges) -> {
309                     if (hasChanges) {
310                         SubscriptionController.getInstance().notifySubscriptionInfoChanged();
311                     }
312                 });
313                 handleSimNotReady(msg.arg1);
314                 break;
315 
316             case EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS:
317                 cardIds.add(msg.arg1);
318                 Runnable r = (Runnable) msg.obj;
319                 updateEmbeddedSubscriptions(cardIds, (hasChanges) -> {
320                     if (hasChanges) {
321                         SubscriptionController.getInstance().notifySubscriptionInfoChanged();
322                     }
323                     if (r != null) {
324                         r.run();
325                     }
326                 });
327                 break;
328 
329             case EVENT_MULTI_SIM_CONFIG_CHANGED:
330                 onMultiSimConfigChanged();
331                 break;
332 
333             default:
334                 logd("Unknown msg:" + msg.what);
335         }
336     }
337 
onMultiSimConfigChanged()338     private void onMultiSimConfigChanged() {
339         int activeModemCount = ((TelephonyManager) sContext.getSystemService(
340                 Context.TELEPHONY_SERVICE)).getActiveModemCount();
341         // For inactive modems, reset its states.
342         for (int phoneId = activeModemCount; phoneId < SUPPORTED_MODEM_COUNT; phoneId++) {
343             sIccId[phoneId] = null;
344             sSimCardState[phoneId] = TelephonyManager.SIM_STATE_UNKNOWN;
345             sSimApplicationState[phoneId] = TelephonyManager.SIM_STATE_UNKNOWN;
346         }
347     }
348 
getCardIdFromPhoneId(int phoneId)349     protected int getCardIdFromPhoneId(int phoneId) {
350         UiccController uiccController = UiccController.getInstance();
351         UiccCard card = uiccController.getUiccCardForPhone(phoneId);
352         if (card != null) {
353             return uiccController.convertToPublicCardId(card.getCardId());
354         }
355         return TelephonyManager.UNINITIALIZED_CARD_ID;
356     }
357 
requestEmbeddedSubscriptionInfoListRefresh(int cardId, @Nullable Runnable callback)358     void requestEmbeddedSubscriptionInfoListRefresh(int cardId, @Nullable Runnable callback) {
359         sendMessage(obtainMessage(
360                 EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS, cardId, 0 /* arg2 */, callback));
361     }
362 
handleSimLocked(int phoneId, String reason)363     protected void handleSimLocked(int phoneId, String reason) {
364         if (sIccId[phoneId] != null && sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
365             logd("SIM" + (phoneId + 1) + " hot plug in");
366             sIccId[phoneId] = null;
367         }
368 
369         IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
370         if (iccCard == null) {
371             logd("handleSimLocked: IccCard null");
372             return;
373         }
374         IccRecords records = iccCard.getIccRecords();
375         if (records == null) {
376             logd("handleSimLocked: IccRecords null");
377             return;
378         }
379         if (IccUtils.stripTrailingFs(records.getFullIccId()) == null) {
380             logd("handleSimLocked: IccID null");
381             return;
382         }
383         sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId());
384 
385         updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
386 
387         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED, reason);
388         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
389         broadcastSimApplicationStateChanged(phoneId, getSimStateFromLockedReason(reason));
390         updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED);
391         updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED);
392     }
393 
getSimStateFromLockedReason(String lockedReason)394     private static int getSimStateFromLockedReason(String lockedReason) {
395         switch (lockedReason) {
396             case IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN:
397                 return TelephonyManager.SIM_STATE_PIN_REQUIRED;
398             case IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK:
399                 return TelephonyManager.SIM_STATE_PUK_REQUIRED;
400             case IccCardConstants.INTENT_VALUE_LOCKED_NETWORK:
401                 return TelephonyManager.SIM_STATE_NETWORK_LOCKED;
402             case IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED:
403                 return TelephonyManager.SIM_STATE_PERM_DISABLED;
404             default:
405                 Rlog.e(LOG_TAG, "Unexpected SIM locked reason " + lockedReason);
406                 return TelephonyManager.SIM_STATE_UNKNOWN;
407         }
408     }
409 
handleSimReady(int phoneId)410     protected void handleSimReady(int phoneId) {
411         List<Integer> cardIds = new ArrayList<>();
412 
413         cardIds.add(getCardIdFromPhoneId(phoneId));
414         updateEmbeddedSubscriptions(cardIds, (hasChanges) -> {
415         if (hasChanges) {
416             SubscriptionController.getInstance().notifySubscriptionInfoChanged();
417         }
418         });
419         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_READY, null);
420         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
421         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY);
422     }
423 
424 
handleSimNotReady(int phoneId)425     protected void handleSimNotReady(int phoneId) {
426         logd("handleSimNotReady: phoneId: " + phoneId);
427         boolean isFinalState = false;
428 
429         IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
430         boolean uiccAppsDisabled = areUiccAppsDisabledOnCard(phoneId);
431         if (iccCard.isEmptyProfile() || uiccAppsDisabled) {
432             if (uiccAppsDisabled) {
433                 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
434                 sInactiveIccIds[phoneId] = IccUtils.stripTrailingFs(slot.getIccId());
435             }
436             isFinalState = true;
437             // ICC_NOT_READY is a terminal state for
438             // 1) It's an empty profile as there's no uicc applications. Or
439             // 2) Its uicc applications are set to be disabled.
440             // At this phase, the subscription list is accessible. Treating NOT_READY
441             // as equivalent to ABSENT, once the rest of the system can handle it.
442             sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
443             updateSubscriptionInfoByIccId(phoneId, false /* updateEmbeddedSubs */);
444         }
445 
446         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY,
447                 null);
448         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
449         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY);
450         if (isFinalState) {
451             updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY);
452         }
453     }
454 
areUiccAppsDisabledOnCard(int phoneId)455     private boolean areUiccAppsDisabledOnCard(int phoneId) {
456         // When uicc apps are disabled(supported in IRadio 1.5), we will still get IccId from
457         // cardStatus (since IRadio 1.2). Amd upon cardStatus change we'll receive another
458         // handleSimNotReady so this will be evaluated again.
459         UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
460         if (slot == null || slot.getIccId() == null) return false;
461         SubscriptionInfo info = SubscriptionController.getInstance()
462                 .getSubInfoForIccId(IccUtils.stripTrailingFs(slot.getIccId()));
463         return info != null && !info.areUiccApplicationsEnabled();
464     }
465 
handleSimLoaded(int phoneId)466     protected void handleSimLoaded(int phoneId) {
467         logd("handleSimLoaded: phoneId: " + phoneId);
468 
469         // The SIM should be loaded at this state, but it is possible in cases such as SIM being
470         // removed or a refresh RESET that the IccRecords could be null. The right behavior is to
471         // not broadcast the SIM loaded.
472         IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
473         if (iccCard == null) {  // Possibly a race condition.
474             logd("handleSimLoaded: IccCard null");
475             return;
476         }
477         IccRecords records = iccCard.getIccRecords();
478         if (records == null) {  // Possibly a race condition.
479             logd("handleSimLoaded: IccRecords null");
480             return;
481         }
482         if (IccUtils.stripTrailingFs(records.getFullIccId()) == null) {
483             logd("handleSimLoaded: IccID null");
484             return;
485         }
486         sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId());
487 
488         updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
489         List<SubscriptionInfo> subscriptionInfos = SubscriptionController.getInstance()
490                 .getSubInfoUsingSlotIndexPrivileged(phoneId);
491         if (subscriptionInfos == null || subscriptionInfos.isEmpty()) {
492             loge("empty subinfo for phoneId: " + phoneId + "could not update ContentResolver");
493         } else {
494             for (SubscriptionInfo sub : subscriptionInfos) {
495                 int subId = sub.getSubscriptionId();
496                 TelephonyManager tm = (TelephonyManager)
497                         sContext.getSystemService(Context.TELEPHONY_SERVICE);
498                 String operator = tm.getSimOperatorNumeric(subId);
499 
500                 if (!TextUtils.isEmpty(operator)) {
501                     if (subId == SubscriptionController.getInstance().getDefaultSubId()) {
502                         MccTable.updateMccMncConfiguration(sContext, operator);
503                     }
504                     SubscriptionController.getInstance().setMccMnc(operator, subId);
505                 } else {
506                     logd("EVENT_RECORDS_LOADED Operator name is null");
507                 }
508 
509                 String iso = tm.getSimCountryIsoForPhone(phoneId);
510 
511                 if (!TextUtils.isEmpty(iso)) {
512                     SubscriptionController.getInstance().setCountryIso(iso, subId);
513                 } else {
514                     logd("EVENT_RECORDS_LOADED sim country iso is null");
515                 }
516 
517                 String msisdn = tm.getLine1Number(subId);
518                 if (msisdn != null) {
519                     SubscriptionController.getInstance().setDisplayNumber(msisdn, subId);
520                 }
521 
522                 String imsi = tm.createForSubscriptionId(subId).getSubscriberId();
523                 if (imsi != null) {
524                     SubscriptionController.getInstance().setImsi(imsi, subId);
525                 }
526 
527                 String[] ehplmns = records.getEhplmns();
528                 String[] hplmns = records.getPlmnsFromHplmnActRecord();
529                 if (ehplmns != null || hplmns != null) {
530                     SubscriptionController.getInstance().setAssociatedPlmns(ehplmns, hplmns, subId);
531                 }
532 
533                 /* Update preferred network type and network selection mode on SIM change.
534                  * Storing last subId in SharedPreference for now to detect SIM change.
535                  */
536                 SharedPreferences sp =
537                         PreferenceManager.getDefaultSharedPreferences(sContext);
538                 int storedSubId = sp.getInt(CURR_SUBID + phoneId, -1);
539 
540                 if (storedSubId != subId) {
541                     int networkType = Settings.Global.getInt(
542                             PhoneFactory.getPhone(phoneId).getContext().getContentResolver(),
543                             Settings.Global.PREFERRED_NETWORK_MODE + subId,
544                             -1 /* invalid network mode */);
545 
546                     if (networkType == -1) {
547                         networkType = RILConstants.PREFERRED_NETWORK_MODE;
548                         try {
549                             networkType = TelephonyManager.getIntAtIndex(
550                                     sContext.getContentResolver(),
551                                     Settings.Global.PREFERRED_NETWORK_MODE, phoneId);
552                         } catch (SettingNotFoundException retrySnfe) {
553                             Rlog.e(LOG_TAG, "Settings Exception Reading Value At Index for "
554                                     + "Settings.Global.PREFERRED_NETWORK_MODE");
555                         }
556                         Settings.Global.putInt(
557                                 PhoneFactory.getPhone(phoneId).getContext().getContentResolver(),
558                                 Global.PREFERRED_NETWORK_MODE + subId,
559                                 networkType);
560                     }
561 
562                     // Set the modem network mode
563                     PhoneFactory.getPhone(phoneId).setPreferredNetworkType(networkType, null);
564 
565                     // Only support automatic selection mode on SIM change.
566                     PhoneFactory.getPhone(phoneId).getNetworkSelectionMode(
567                             obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE,
568                                     new Integer(phoneId)));
569 
570                     // Update stored subId
571                     SharedPreferences.Editor editor = sp.edit();
572                     editor.putInt(CURR_SUBID + phoneId, subId);
573                     editor.apply();
574                 }
575             }
576         }
577 
578         // Update set of enabled carrier apps now that the privilege rules may have changed.
579         CarrierAppUtils.disableCarrierAppsUntilPrivileged(sContext.getOpPackageName(),
580                 TelephonyManager.getDefault(), mCurrentlyActiveUserId, sContext);
581 
582         /**
583          * The sim loading sequence will be
584          *  1. ACTION_SUBINFO_CONTENT_CHANGE happens through updateSubscriptionInfoByIccId() above.
585          *  2. ACTION_SIM_STATE_CHANGED/ACTION_SIM_CARD_STATE_CHANGED
586          *  /ACTION_SIM_APPLICATION_STATE_CHANGED
587          *  3. ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED
588          *  4. ACTION_CARRIER_CONFIG_CHANGED
589          */
590         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
591         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
592         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_LOADED);
593         updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED);
594         updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED);
595     }
596 
updateCarrierServices(int phoneId, String simState)597     private void updateCarrierServices(int phoneId, String simState) {
598         CarrierConfigManager configManager =
599                 (CarrierConfigManager) sContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
600         configManager.updateConfigForPhoneId(phoneId, simState);
601         mCarrierServiceBindHelper.updateForPhoneId(phoneId, simState);
602     }
603 
updateSubscriptionCarrierId(int phoneId, String simState)604     private void updateSubscriptionCarrierId(int phoneId, String simState) {
605         if (PhoneFactory.getPhone(phoneId) != null) {
606             PhoneFactory.getPhone(phoneId).resolveSubscriptionCarrierId(simState);
607         }
608     }
609 
610     /**
611      * PhoneId is the corresponding phoneId of the slot if slot was previously active.
612      * It could be INVALID if it was already inactive.
613      */
handleInactiveSlotIccStateChange(int phoneId, String iccId)614     private void handleInactiveSlotIccStateChange(int phoneId, String iccId) {
615         if (SubscriptionManager.isValidPhoneId(phoneId)) {
616             // If phoneId is valid, it means the physical slot was previously active in that
617             // phoneId. In this case, found the subId and set its phoneId to invalid.
618             if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
619                 logd("Slot of SIM" + (phoneId + 1) + " becomes inactive");
620             }
621             cleanSubscriptionInPhone(phoneId);
622         }
623         if (!TextUtils.isEmpty(iccId)) {
624             // If iccId is new, add a subscription record in the db.
625             String strippedIccId = IccUtils.stripTrailingFs(iccId);
626             if (SubscriptionController.getInstance().getSubInfoForIccId(strippedIccId) == null) {
627                 SubscriptionController.getInstance().insertEmptySubInfoRecord(
628                         strippedIccId, "CARD", SubscriptionManager.INVALID_PHONE_INDEX,
629                         SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
630             }
631         }
632     }
633 
cleanSubscriptionInPhone(int phoneId)634     private void cleanSubscriptionInPhone(int phoneId) {
635         sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
636         if (sInactiveIccIds[phoneId] != null) {
637             // When a SIM is unplugged, mark uicc applications enabled. This is to make sure when
638             // user unplugs and re-inserts the SIM card, we re-enable it.
639             logd("cleanSubscriptionInPhone " + phoneId + " inactive iccid "
640                     + sInactiveIccIds[phoneId]);
641             ContentValues value = new ContentValues(1);
642             value.put(SubscriptionManager.UICC_APPLICATIONS_ENABLED, true);
643             sContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value,
644                     SubscriptionManager.ICC_ID + "=\'" + sInactiveIccIds[phoneId] + "\'", null);
645             sInactiveIccIds[phoneId] = null;
646         }
647         updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
648     }
649 
handleSimAbsent(int phoneId)650     protected void handleSimAbsent(int phoneId) {
651         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
652             logd("handleSimAbsent on invalid phoneId");
653             return;
654         }
655         if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
656             logd("SIM" + (phoneId + 1) + " hot plug out");
657         }
658         cleanSubscriptionInPhone(phoneId);
659 
660         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT, null);
661         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_ABSENT);
662         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_UNKNOWN);
663         updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
664         updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
665     }
666 
handleSimError(int phoneId)667     protected void handleSimError(int phoneId) {
668         if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
669             logd("SIM" + (phoneId + 1) + " Error ");
670         }
671         sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
672         updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
673         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR,
674                 IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR);
675         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_CARD_IO_ERROR);
676         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY);
677         updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR);
678         updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR);
679     }
680 
updateSubscriptionInfoByIccId(int phoneId, boolean updateEmbeddedSubs)681     protected synchronized void updateSubscriptionInfoByIccId(int phoneId,
682             boolean updateEmbeddedSubs) {
683         logd("updateSubscriptionInfoByIccId:+ Start - phoneId: " + phoneId);
684         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
685             loge("[updateSubscriptionInfoByIccId]- invalid phoneId=" + phoneId);
686             return;
687         }
688         logd("updateSubscriptionInfoByIccId: removing subscription info record: phoneId "
689                 + phoneId);
690         // Clear phoneId only when sim absent is not enough. It's possible to switch SIM profile
691         // within the same slot. Need to clear the slot index of the previous sub. Thus always clear
692         // for the changing slot first.
693         SubscriptionController.getInstance().clearSubInfoRecord(phoneId);
694 
695         // If SIM is not absent, insert new record or update existing record.
696         if (!ICCID_STRING_FOR_NO_SIM.equals(sIccId[phoneId])) {
697             logd("updateSubscriptionInfoByIccId: adding subscription info record: iccid: "
698                     + sIccId[phoneId] + ", phoneId:" + phoneId);
699             mSubscriptionManager.addSubscriptionInfoRecord(sIccId[phoneId], phoneId);
700         }
701 
702         List<SubscriptionInfo> subInfos = SubscriptionController.getInstance()
703                 .getSubInfoUsingSlotIndexPrivileged(phoneId);
704         if (subInfos != null) {
705             boolean changed = false;
706             for (int i = 0; i < subInfos.size(); i++) {
707                 SubscriptionInfo temp = subInfos.get(i);
708                 ContentValues value = new ContentValues(1);
709 
710                 String msisdn = TelephonyManager.getDefault().getLine1Number(
711                         temp.getSubscriptionId());
712 
713                 if (!TextUtils.equals(msisdn, temp.getNumber())) {
714                     value.put(SubscriptionManager.NUMBER, msisdn);
715                     sContext.getContentResolver().update(SubscriptionManager
716                             .getUriForSubscriptionId(temp.getSubscriptionId()), value, null, null);
717                     changed = true;
718                 }
719             }
720             if (changed) {
721                 // refresh Cached Active Subscription Info List
722                 SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
723             }
724         }
725 
726         // TODO investigate if we can update for each slot separately.
727         if (isAllIccIdQueryDone()) {
728             // Ensure the modems are mapped correctly
729             if (mSubscriptionManager.isActiveSubId(
730                     mSubscriptionManager.getDefaultDataSubscriptionId())) {
731                 mSubscriptionManager.setDefaultDataSubId(
732                         mSubscriptionManager.getDefaultDataSubscriptionId());
733             } else {
734                 logd("bypass reset default data sub if inactive");
735             }
736             setSubInfoInitialized();
737         }
738 
739         UiccController uiccController = UiccController.getInstance();
740         UiccSlot[] uiccSlots = uiccController.getUiccSlots();
741         if (uiccSlots != null && updateEmbeddedSubs) {
742             List<Integer> cardIds = new ArrayList<>();
743             for (UiccSlot uiccSlot : uiccSlots) {
744                 if (uiccSlot != null && uiccSlot.getUiccCard() != null) {
745                     int cardId = uiccController.convertToPublicCardId(
746                             uiccSlot.getUiccCard().getCardId());
747                     cardIds.add(cardId);
748                 }
749             }
750             updateEmbeddedSubscriptions(cardIds, (hasChanges) -> {
751                 if (hasChanges) {
752                     SubscriptionController.getInstance().notifySubscriptionInfoChanged();
753                 }
754                 if (DBG) logd("updateSubscriptionInfoByIccId: SubscriptionInfo update complete");
755             });
756         }
757 
758         SubscriptionController.getInstance().notifySubscriptionInfoChanged();
759         if (DBG) logd("updateSubscriptionInfoByIccId: SubscriptionInfo update complete");
760     }
761 
setSubInfoInitialized()762     private static void setSubInfoInitialized() {
763         // Should only be triggered once.
764         if (!sIsSubInfoInitialized) {
765             if (DBG) logd("SubInfo Initialized");
766             sIsSubInfoInitialized = true;
767             SubscriptionController.getInstance().notifySubInfoReady();
768             MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded();
769         }
770     }
771 
772     /**
773      * Whether subscriptions of all SIMs are initialized.
774      */
isSubInfoInitialized()775     public static boolean isSubInfoInitialized() {
776         return sIsSubInfoInitialized;
777     }
778 
779     /**
780      * Updates the cached list of embedded subscription for the eUICC with the given list of card
781      * IDs {@code cardIds}. The step of reading the embedded subscription list from eUICC card is
782      * executed in background thread. The callback {@code callback} is executed after the cache is
783      * refreshed. The callback is executed in main thread.
784      */
785     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
updateEmbeddedSubscriptions(List<Integer> cardIds, @Nullable UpdateEmbeddedSubsCallback callback)786     public void updateEmbeddedSubscriptions(List<Integer> cardIds,
787             @Nullable UpdateEmbeddedSubsCallback callback) {
788         // Do nothing if eUICCs are disabled. (Previous entries may remain in the cache, but they
789         // are filtered out of list calls as long as EuiccManager.isEnabled returns false).
790         if (!mEuiccManager.isEnabled()) {
791             callback.run(false /* hasChanges */);
792             return;
793         }
794 
795         mBackgroundHandler.post(() -> {
796             List<Pair<Integer, GetEuiccProfileInfoListResult>> results = new ArrayList<>();
797             for (int cardId : cardIds) {
798                 GetEuiccProfileInfoListResult result =
799                         EuiccController.get().blockingGetEuiccProfileInfoList(cardId);
800                 if (DBG) logd("blockingGetEuiccProfileInfoList cardId " + cardId);
801                 results.add(Pair.create(cardId, result));
802             }
803 
804             // The runnable will be executed in the main thread.
805             this.post(() -> {
806                 boolean hasChanges = false;
807                 for (Pair<Integer, GetEuiccProfileInfoListResult> cardIdAndResult : results) {
808                     if (updateEmbeddedSubscriptionsCache(cardIdAndResult.first,
809                             cardIdAndResult.second)) {
810                         hasChanges = true;
811                     }
812                 }
813                 // The latest state in the main thread may be changed when the callback is
814                 // triggered.
815                 if (callback != null) {
816                     callback.run(hasChanges);
817                 }
818             });
819         });
820     }
821 
822     /**
823      * Update the cached list of embedded subscription based on the passed in
824      * GetEuiccProfileInfoListResult {@code result}.
825      *
826      * @return true if changes may have been made. This is not a guarantee that changes were made,
827      * but notifications about subscription changes may be skipped if this returns false as an
828      * optimization to avoid spurious notifications.
829      */
updateEmbeddedSubscriptionsCache(int cardId, GetEuiccProfileInfoListResult result)830     private boolean updateEmbeddedSubscriptionsCache(int cardId,
831             GetEuiccProfileInfoListResult result) {
832         if (DBG) logd("updateEmbeddedSubscriptionsCache");
833 
834         if (result == null) {
835             // IPC to the eUICC controller failed.
836             return false;
837         }
838 
839         // If the returned result is not RESULT_OK or the profile list is null, don't update cache.
840         // Otherwise, update the cache.
841         final EuiccProfileInfo[] embeddedProfiles;
842         List<EuiccProfileInfo> list = result.getProfiles();
843         if (result.getResult() == EuiccService.RESULT_OK && list != null) {
844             embeddedProfiles = list.toArray(new EuiccProfileInfo[list.size()]);
845             if (DBG) {
846                 logd("blockingGetEuiccProfileInfoList: got " + result.getProfiles().size()
847                         + " profiles");
848             }
849         } else {
850             if (DBG) {
851                 logd("blockingGetEuiccProfileInfoList returns an error. "
852                         + "Result code=" + result.getResult()
853                         + ". Null profile list=" + (result.getProfiles() == null));
854             }
855             return false;
856         }
857 
858         final boolean isRemovable = result.getIsRemovable();
859 
860         final String[] embeddedIccids = new String[embeddedProfiles.length];
861         for (int i = 0; i < embeddedProfiles.length; i++) {
862             embeddedIccids[i] = embeddedProfiles[i].getIccid();
863         }
864 
865         if (DBG) logd("Get eUICC profile list of size " + embeddedProfiles.length);
866 
867         // Note that this only tracks whether we make any writes to the DB. It's possible this will
868         // be set to true for an update even when the row contents remain exactly unchanged from
869         // before, since we don't compare against the previous value. Since this is only intended to
870         // avoid some spurious broadcasts (particularly for users who don't use eSIM at all), this
871         // is fine.
872         boolean hasChanges = false;
873 
874         // Update or insert records for all embedded subscriptions (except non-removable ones if the
875         // current eUICC is non-removable, since we assume these are still accessible though not
876         // returned by the eUICC controller).
877         List<SubscriptionInfo> existingSubscriptions = SubscriptionController.getInstance()
878                 .getSubscriptionInfoListForEmbeddedSubscriptionUpdate(embeddedIccids, isRemovable);
879         ContentResolver contentResolver = sContext.getContentResolver();
880         for (EuiccProfileInfo embeddedProfile : embeddedProfiles) {
881             int index =
882                     findSubscriptionInfoForIccid(existingSubscriptions, embeddedProfile.getIccid());
883             int prevCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
884             int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER_ID;
885             if (index < 0) {
886                 // No existing entry for this ICCID; create an empty one.
887                 SubscriptionController.getInstance().insertEmptySubInfoRecord(
888                         embeddedProfile.getIccid(), SubscriptionManager.SIM_NOT_INSERTED);
889             } else {
890                 nameSource = existingSubscriptions.get(index).getNameSource();
891                 prevCarrierId = existingSubscriptions.get(index).getCarrierId();
892                 existingSubscriptions.remove(index);
893             }
894 
895             if (DBG) {
896                 logd("embeddedProfile " + embeddedProfile + " existing record "
897                         + (index < 0 ? "not found" : "found"));
898             }
899 
900             ContentValues values = new ContentValues();
901             values.put(SubscriptionManager.IS_EMBEDDED, 1);
902             List<UiccAccessRule> ruleList = embeddedProfile.getUiccAccessRules();
903             boolean isRuleListEmpty = false;
904             if (ruleList == null || ruleList.size() == 0) {
905                 isRuleListEmpty = true;
906             }
907             values.put(SubscriptionManager.ACCESS_RULES,
908                     isRuleListEmpty ? null : UiccAccessRule.encodeRules(
909                             ruleList.toArray(new UiccAccessRule[ruleList.size()])));
910             values.put(SubscriptionManager.IS_REMOVABLE, isRemovable);
911             // override DISPLAY_NAME if the priority of existing nameSource is <= carrier
912             if (SubscriptionController.getNameSourcePriority(nameSource)
913                     <= SubscriptionController.getNameSourcePriority(
914                             SubscriptionManager.NAME_SOURCE_CARRIER)) {
915                 values.put(SubscriptionManager.DISPLAY_NAME, embeddedProfile.getNickname());
916                 values.put(SubscriptionManager.NAME_SOURCE,
917                         SubscriptionManager.NAME_SOURCE_CARRIER);
918             }
919             values.put(SubscriptionManager.PROFILE_CLASS, embeddedProfile.getProfileClass());
920             CarrierIdentifier cid = embeddedProfile.getCarrierIdentifier();
921             if (cid != null) {
922                 // Due to the limited subscription information, carrier id identified here might
923                 // not be accurate compared with CarrierResolver. Only update carrier id if there
924                 // is no valid carrier id present.
925                 if (prevCarrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
926                     values.put(SubscriptionManager.CARRIER_ID,
927                             CarrierResolver.getCarrierIdFromIdentifier(sContext, cid));
928                 }
929                 String mcc = cid.getMcc();
930                 String mnc = cid.getMnc();
931                 values.put(SubscriptionManager.MCC_STRING, mcc);
932                 values.put(SubscriptionManager.MCC, mcc);
933                 values.put(SubscriptionManager.MNC_STRING, mnc);
934                 values.put(SubscriptionManager.MNC, mnc);
935             }
936             // If cardId = unsupported or unitialized, we have no reason to update DB.
937             // Additionally, if the device does not support cardId for default eUICC, the CARD_ID
938             // field should not contain the EID
939             UiccController uiccController = UiccController.getInstance();
940             if (cardId >= 0 && uiccController.getCardIdForDefaultEuicc()
941                     != TelephonyManager.UNSUPPORTED_CARD_ID) {
942                 values.put(SubscriptionManager.CARD_ID, uiccController.convertToCardString(cardId));
943             }
944             hasChanges = true;
945             contentResolver.update(SubscriptionManager.CONTENT_URI, values,
946                     SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.getIccid() + "\"", null);
947 
948             // refresh Cached Active Subscription Info List
949             SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
950         }
951 
952         // Remove all remaining subscriptions which have embedded = true. We set embedded to false
953         // to ensure they are not returned in the list of embedded subscriptions (but keep them
954         // around in case the subscription is added back later, which is equivalent to a removable
955         // SIM being removed and reinserted).
956         if (!existingSubscriptions.isEmpty()) {
957             if (DBG) {
958                 logd("Removing existing embedded subscriptions of size"
959                         + existingSubscriptions.size());
960             }
961             List<String> iccidsToRemove = new ArrayList<>();
962             for (int i = 0; i < existingSubscriptions.size(); i++) {
963                 SubscriptionInfo info = existingSubscriptions.get(i);
964                 if (info.isEmbedded()) {
965                     if (DBG) logd("Removing embedded subscription of IccId " + info.getIccId());
966                     iccidsToRemove.add("\"" + info.getIccId() + "\"");
967                 }
968             }
969             String whereClause = SubscriptionManager.ICC_ID + " IN ("
970                     + TextUtils.join(",", iccidsToRemove) + ")";
971             ContentValues values = new ContentValues();
972             values.put(SubscriptionManager.IS_EMBEDDED, 0);
973             hasChanges = true;
974             contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null);
975 
976             // refresh Cached Active Subscription Info List
977             SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
978         }
979 
980         if (DBG) logd("updateEmbeddedSubscriptions done hasChanges=" + hasChanges);
981         return hasChanges;
982     }
983 
984     /**
985      * Called by CarrierConfigLoader to update the subscription before sending a broadcast.
986      */
updateSubscriptionByCarrierConfigAndNotifyComplete(int phoneId, String configPackageName, PersistableBundle config, Message onComplete)987     public void updateSubscriptionByCarrierConfigAndNotifyComplete(int phoneId,
988             String configPackageName, PersistableBundle config, Message onComplete) {
989         post(() -> {
990             updateSubscriptionByCarrierConfig(phoneId, configPackageName, config);
991             onComplete.sendToTarget();
992         });
993     }
994 
getDefaultCarrierServicePackageName()995     private String getDefaultCarrierServicePackageName() {
996         CarrierConfigManager configManager =
997                 (CarrierConfigManager) sContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
998         return configManager.getDefaultCarrierServicePackageName();
999     }
1000 
isCarrierServicePackage(int phoneId, String pkgName)1001     private boolean isCarrierServicePackage(int phoneId, String pkgName) {
1002         if (pkgName.equals(getDefaultCarrierServicePackageName())) return false;
1003 
1004         List<String> carrierPackageNames = TelephonyManager.from(sContext)
1005                 .getCarrierPackageNamesForIntentAndPhone(
1006                         new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId);
1007         if (DBG) logd("Carrier Packages For Subscription = " + carrierPackageNames);
1008         return carrierPackageNames != null && carrierPackageNames.contains(pkgName);
1009     }
1010 
1011     /**
1012      * Update the currently active Subscription based on information from CarrierConfig
1013      */
1014     @VisibleForTesting
updateSubscriptionByCarrierConfig( int phoneId, String configPackageName, PersistableBundle config)1015     public void updateSubscriptionByCarrierConfig(
1016             int phoneId, String configPackageName, PersistableBundle config) {
1017         if (!SubscriptionManager.isValidPhoneId(phoneId)
1018                 || TextUtils.isEmpty(configPackageName) || config == null) {
1019             if (DBG) {
1020                 logd("In updateSubscriptionByCarrierConfig(): phoneId=" + phoneId
1021                         + " configPackageName=" + configPackageName + " config="
1022                         + ((config == null) ? "null" : config.hashCode()));
1023             }
1024             return;
1025         }
1026 
1027         SubscriptionController sc = SubscriptionController.getInstance();
1028         if (sc == null) {
1029             loge("SubscriptionController was null");
1030             return;
1031         }
1032 
1033         int currentSubId = sc.getSubIdUsingPhoneId(phoneId);
1034         if (!SubscriptionManager.isValidSubscriptionId(currentSubId)
1035                 || currentSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
1036             if (DBG) logd("No subscription is active for phone being updated");
1037             return;
1038         }
1039 
1040         SubscriptionInfo currentSubInfo = sc.getSubscriptionInfo(currentSubId);
1041         if (currentSubInfo == null) {
1042             loge("Couldn't retrieve subscription info for current subscription");
1043             return;
1044         }
1045 
1046         ContentValues cv = new ContentValues();
1047         ParcelUuid groupUuid = null;
1048 
1049         // carrier certificates are not subscription-specific, so we want to load them even if
1050         // this current package is not a CarrierServicePackage
1051         String[] certs = config.getStringArray(
1052             CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY);
1053         UiccAccessRule[] carrierConfigAccessRules = null;
1054         if (certs != null) {
1055             carrierConfigAccessRules = new UiccAccessRule[certs.length];
1056             for (int i = 0; i < certs.length; i++) {
1057                 carrierConfigAccessRules[i] = new UiccAccessRule(IccUtils.hexStringToBytes(
1058                     certs[i]), null, 0);
1059             }
1060         }
1061         cv.put(SubscriptionManager.ACCESS_RULES_FROM_CARRIER_CONFIGS,
1062                 UiccAccessRule.encodeRules(carrierConfigAccessRules));
1063 
1064         if (!isCarrierServicePackage(phoneId, configPackageName)) {
1065             loge("Cannot manage subId=" + currentSubId + ", carrierPackage=" + configPackageName);
1066         } else {
1067             boolean isOpportunistic = config.getBoolean(
1068                     CarrierConfigManager.KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL, false);
1069             if (currentSubInfo.isOpportunistic() != isOpportunistic) {
1070                 if (DBG) logd("Set SubId=" + currentSubId + " isOpportunistic=" + isOpportunistic);
1071                 cv.put(SubscriptionManager.IS_OPPORTUNISTIC, isOpportunistic ? "1" : "0");
1072             }
1073 
1074             String groupUuidString =
1075                 config.getString(CarrierConfigManager.KEY_SUBSCRIPTION_GROUP_UUID_STRING, "");
1076             if (!TextUtils.isEmpty(groupUuidString)) {
1077                 try {
1078                     // Update via a UUID Structure to ensure consistent formatting
1079                     groupUuid = ParcelUuid.fromString(groupUuidString);
1080                     if (groupUuid.equals(REMOVE_GROUP_UUID)
1081                             && currentSubInfo.getGroupUuid() != null) {
1082                         cv.put(SubscriptionManager.GROUP_UUID, (String) null);
1083                         if (DBG) logd("Group Removed for" + currentSubId);
1084                     } else if (SubscriptionController.getInstance().canPackageManageGroup(groupUuid,
1085                         configPackageName)) {
1086                         cv.put(SubscriptionManager.GROUP_UUID, groupUuid.toString());
1087                         cv.put(SubscriptionManager.GROUP_OWNER, configPackageName);
1088                         if (DBG) logd("Group Added for" + currentSubId);
1089                     } else {
1090                         loge("configPackageName " + configPackageName + " doesn't own grouUuid "
1091                             + groupUuid);
1092                     }
1093                 } catch (IllegalArgumentException e) {
1094                     loge("Invalid Group UUID=" + groupUuidString);
1095                 }
1096             }
1097         }
1098         if (cv.size() > 0 && sContext.getContentResolver().update(SubscriptionManager
1099                     .getUriForSubscriptionId(currentSubId), cv, null, null) > 0) {
1100             sc.refreshCachedActiveSubscriptionInfoList();
1101             sc.notifySubscriptionInfoChanged();
1102             MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupUuid);
1103         }
1104     }
1105 
findSubscriptionInfoForIccid(List<SubscriptionInfo> list, String iccid)1106     private static int findSubscriptionInfoForIccid(List<SubscriptionInfo> list, String iccid) {
1107         for (int i = 0; i < list.size(); i++) {
1108             if (TextUtils.equals(iccid, list.get(i).getIccId())) {
1109                 return i;
1110             }
1111         }
1112         return -1;
1113     }
1114 
isNewSim(String iccId, String decIccId, String[] oldIccId)1115     private boolean isNewSim(String iccId, String decIccId, String[] oldIccId) {
1116         boolean newSim = true;
1117         for (int i = 0; i < TelephonyManager.getDefault().getPhoneCount(); i++) {
1118             if(iccId.equals(oldIccId[i])) {
1119                 newSim = false;
1120                 break;
1121             } else if (decIccId != null && decIccId.equals(oldIccId[i])) {
1122                 newSim = false;
1123                 break;
1124             }
1125         }
1126         logd("newSim = " + newSim);
1127 
1128         return newSim;
1129     }
1130 
1131     @UnsupportedAppUsage
broadcastSimStateChanged(int phoneId, String state, String reason)1132     protected void broadcastSimStateChanged(int phoneId, String state, String reason) {
1133         Intent i = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
1134         // TODO - we'd like this intent to have a single snapshot of all sim state,
1135         // but until then this should not use REPLACE_PENDING or we may lose
1136         // information
1137         // i.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
1138         //         | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1139         i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1140         i.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone");
1141         i.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, state);
1142         i.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason);
1143         SubscriptionManager.putPhoneIdAndSubIdExtra(i, phoneId);
1144         logd("Broadcasting intent ACTION_SIM_STATE_CHANGED " + state + " reason " + reason +
1145                 " for phone: " + phoneId);
1146         IntentBroadcaster.getInstance().broadcastStickyIntent(sContext, i, phoneId);
1147     }
1148 
broadcastSimCardStateChanged(int phoneId, int state)1149     protected void broadcastSimCardStateChanged(int phoneId, int state) {
1150         if (state != sSimCardState[phoneId]) {
1151             sSimCardState[phoneId] = state;
1152             Intent i = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED);
1153             i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1154             i.putExtra(TelephonyManager.EXTRA_SIM_STATE, state);
1155             SubscriptionManager.putPhoneIdAndSubIdExtra(i, phoneId);
1156             // TODO(b/130664115) we manually populate this intent with the slotId. In the future we
1157             // should do a review of whether to make this public
1158             int slotId = UiccController.getInstance().getSlotIdFromPhoneId(phoneId);
1159             i.putExtra(PhoneConstants.SLOT_KEY, slotId);
1160             logd("Broadcasting intent ACTION_SIM_CARD_STATE_CHANGED " + simStateString(state)
1161                     + " for phone: " + phoneId + " slot: " + slotId);
1162             sContext.sendBroadcast(i, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
1163             TelephonyMetrics.getInstance().updateSimState(phoneId, state);
1164         }
1165     }
1166 
broadcastSimApplicationStateChanged(int phoneId, int state)1167     protected void broadcastSimApplicationStateChanged(int phoneId, int state) {
1168         // Broadcast if the state has changed, except if old state was UNKNOWN and new is NOT_READY,
1169         // because that's the initial state and a broadcast should be sent only on a transition
1170         // after SIM is PRESENT. The only exception is eSIM boot profile, where NOT_READY is the
1171         // terminal state.
1172         boolean isUnknownToNotReady =
1173                 (sSimApplicationState[phoneId] == TelephonyManager.SIM_STATE_UNKNOWN
1174                         && state == TelephonyManager.SIM_STATE_NOT_READY);
1175         IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
1176         boolean emptyProfile = iccCard != null && iccCard.isEmptyProfile();
1177         if (state != sSimApplicationState[phoneId] && (!isUnknownToNotReady || emptyProfile)) {
1178             sSimApplicationState[phoneId] = state;
1179             Intent i = new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED);
1180             i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
1181             i.putExtra(TelephonyManager.EXTRA_SIM_STATE, state);
1182             SubscriptionManager.putPhoneIdAndSubIdExtra(i, phoneId);
1183             // TODO(b/130664115) we populate this intent with the actual slotId. In the future we
1184             // should do a review of whether to make this public
1185             int slotId = UiccController.getInstance().getSlotIdFromPhoneId(phoneId);
1186             i.putExtra(PhoneConstants.SLOT_KEY, slotId);
1187             logd("Broadcasting intent ACTION_SIM_APPLICATION_STATE_CHANGED " + simStateString(state)
1188                     + " for phone: " + phoneId + " slot: " + slotId);
1189             sContext.sendBroadcast(i, Manifest.permission.READ_PRIVILEGED_PHONE_STATE);
1190             TelephonyMetrics.getInstance().updateSimState(phoneId, state);
1191         }
1192     }
1193 
1194     /**
1195      * Convert SIM state into string
1196      *
1197      * @param state SIM state
1198      * @return SIM state in string format
1199      */
simStateString(@imState int state)1200     public static String simStateString(@SimState int state) {
1201         switch (state) {
1202             case TelephonyManager.SIM_STATE_UNKNOWN:
1203                 return "UNKNOWN";
1204             case TelephonyManager.SIM_STATE_ABSENT:
1205                 return "ABSENT";
1206             case TelephonyManager.SIM_STATE_PIN_REQUIRED:
1207                 return "PIN_REQUIRED";
1208             case TelephonyManager.SIM_STATE_PUK_REQUIRED:
1209                 return "PUK_REQUIRED";
1210             case TelephonyManager.SIM_STATE_NETWORK_LOCKED:
1211                 return "NETWORK_LOCKED";
1212             case TelephonyManager.SIM_STATE_READY:
1213                 return "READY";
1214             case TelephonyManager.SIM_STATE_NOT_READY:
1215                 return "NOT_READY";
1216             case TelephonyManager.SIM_STATE_PERM_DISABLED:
1217                 return "PERM_DISABLED";
1218             case TelephonyManager.SIM_STATE_CARD_IO_ERROR:
1219                 return "CARD_IO_ERROR";
1220             case TelephonyManager.SIM_STATE_CARD_RESTRICTED:
1221                 return "CARD_RESTRICTED";
1222             case TelephonyManager.SIM_STATE_LOADED:
1223                 return "LOADED";
1224             case TelephonyManager.SIM_STATE_PRESENT:
1225                 return "PRESENT";
1226             default:
1227                 return "INVALID";
1228         }
1229     }
1230 
1231     @UnsupportedAppUsage
logd(String message)1232     private static void logd(String message) {
1233         Rlog.d(LOG_TAG, message);
1234     }
1235 
loge(String message)1236     private static void loge(String message) {
1237         Rlog.e(LOG_TAG, message);
1238     }
1239 
dump(FileDescriptor fd, PrintWriter pw, String[] args)1240     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1241         pw.println("SubscriptionInfoUpdater:");
1242         mCarrierServiceBindHelper.dump(fd, pw, args);
1243     }
1244 }
1245