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             SubscriptionController.getInstance().clearSubInfoRecord(phoneId);
344             sIccId[phoneId] = null;
345             sSimCardState[phoneId] = TelephonyManager.SIM_STATE_UNKNOWN;
346             sSimApplicationState[phoneId] = TelephonyManager.SIM_STATE_UNKNOWN;
347         }
348     }
349 
getCardIdFromPhoneId(int phoneId)350     protected int getCardIdFromPhoneId(int phoneId) {
351         UiccController uiccController = UiccController.getInstance();
352         UiccCard card = uiccController.getUiccCardForPhone(phoneId);
353         if (card != null) {
354             return uiccController.convertToPublicCardId(card.getCardId());
355         }
356         return TelephonyManager.UNINITIALIZED_CARD_ID;
357     }
358 
requestEmbeddedSubscriptionInfoListRefresh(int cardId, @Nullable Runnable callback)359     void requestEmbeddedSubscriptionInfoListRefresh(int cardId, @Nullable Runnable callback) {
360         sendMessage(obtainMessage(
361                 EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS, cardId, 0 /* arg2 */, callback));
362     }
363 
handleSimLocked(int phoneId, String reason)364     protected void handleSimLocked(int phoneId, String reason) {
365         if (sIccId[phoneId] != null && sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
366             logd("SIM" + (phoneId + 1) + " hot plug in");
367             sIccId[phoneId] = null;
368         }
369 
370         IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
371         if (iccCard == null) {
372             logd("handleSimLocked: IccCard null");
373             return;
374         }
375         IccRecords records = iccCard.getIccRecords();
376         if (records == null) {
377             logd("handleSimLocked: IccRecords null");
378             return;
379         }
380         if (IccUtils.stripTrailingFs(records.getFullIccId()) == null) {
381             logd("handleSimLocked: IccID null");
382             return;
383         }
384         sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId());
385 
386         updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
387 
388         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED, reason);
389         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
390         broadcastSimApplicationStateChanged(phoneId, getSimStateFromLockedReason(reason));
391         updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED);
392         updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED);
393     }
394 
getSimStateFromLockedReason(String lockedReason)395     private static int getSimStateFromLockedReason(String lockedReason) {
396         switch (lockedReason) {
397             case IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN:
398                 return TelephonyManager.SIM_STATE_PIN_REQUIRED;
399             case IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK:
400                 return TelephonyManager.SIM_STATE_PUK_REQUIRED;
401             case IccCardConstants.INTENT_VALUE_LOCKED_NETWORK:
402                 return TelephonyManager.SIM_STATE_NETWORK_LOCKED;
403             case IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED:
404                 return TelephonyManager.SIM_STATE_PERM_DISABLED;
405             default:
406                 Rlog.e(LOG_TAG, "Unexpected SIM locked reason " + lockedReason);
407                 return TelephonyManager.SIM_STATE_UNKNOWN;
408         }
409     }
410 
handleSimReady(int phoneId)411     protected void handleSimReady(int phoneId) {
412         List<Integer> cardIds = new ArrayList<>();
413 
414         cardIds.add(getCardIdFromPhoneId(phoneId));
415         updateEmbeddedSubscriptions(cardIds, (hasChanges) -> {
416         if (hasChanges) {
417             SubscriptionController.getInstance().notifySubscriptionInfoChanged();
418         }
419         });
420         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_READY, null);
421         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
422         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY);
423     }
424 
425 
handleSimNotReady(int phoneId)426     protected void handleSimNotReady(int phoneId) {
427         logd("handleSimNotReady: phoneId: " + phoneId);
428         boolean isFinalState = false;
429 
430         IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
431         boolean uiccAppsDisabled = areUiccAppsDisabledOnCard(phoneId);
432         if (iccCard.isEmptyProfile() || uiccAppsDisabled) {
433             if (uiccAppsDisabled) {
434                 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
435                 sInactiveIccIds[phoneId] = IccUtils.stripTrailingFs(slot.getIccId());
436             }
437             isFinalState = true;
438             // ICC_NOT_READY is a terminal state for
439             // 1) It's an empty profile as there's no uicc applications. Or
440             // 2) Its uicc applications are set to be disabled.
441             // At this phase, the subscription list is accessible. Treating NOT_READY
442             // as equivalent to ABSENT, once the rest of the system can handle it.
443             sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
444             updateSubscriptionInfoByIccId(phoneId, false /* updateEmbeddedSubs */);
445         }
446 
447         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY,
448                 null);
449         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
450         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY);
451         if (isFinalState) {
452             updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY);
453         }
454     }
455 
areUiccAppsDisabledOnCard(int phoneId)456     private boolean areUiccAppsDisabledOnCard(int phoneId) {
457         // When uicc apps are disabled(supported in IRadio 1.5), we will still get IccId from
458         // cardStatus (since IRadio 1.2). Amd upon cardStatus change we'll receive another
459         // handleSimNotReady so this will be evaluated again.
460         UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId);
461         if (slot == null || slot.getIccId() == null) return false;
462         SubscriptionInfo info = SubscriptionController.getInstance()
463                 .getSubInfoForIccId(IccUtils.stripTrailingFs(slot.getIccId()));
464         return info != null && !info.areUiccApplicationsEnabled();
465     }
466 
handleSimLoaded(int phoneId)467     protected void handleSimLoaded(int phoneId) {
468         logd("handleSimLoaded: phoneId: " + phoneId);
469 
470         // The SIM should be loaded at this state, but it is possible in cases such as SIM being
471         // removed or a refresh RESET that the IccRecords could be null. The right behavior is to
472         // not broadcast the SIM loaded.
473         IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard();
474         if (iccCard == null) {  // Possibly a race condition.
475             logd("handleSimLoaded: IccCard null");
476             return;
477         }
478         IccRecords records = iccCard.getIccRecords();
479         if (records == null) {  // Possibly a race condition.
480             logd("handleSimLoaded: IccRecords null");
481             return;
482         }
483         if (IccUtils.stripTrailingFs(records.getFullIccId()) == null) {
484             logd("handleSimLoaded: IccID null");
485             return;
486         }
487         sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId());
488 
489         updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
490         List<SubscriptionInfo> subscriptionInfos = SubscriptionController.getInstance()
491                 .getSubInfoUsingSlotIndexPrivileged(phoneId);
492         if (subscriptionInfos == null || subscriptionInfos.isEmpty()) {
493             loge("empty subinfo for phoneId: " + phoneId + "could not update ContentResolver");
494         } else {
495             for (SubscriptionInfo sub : subscriptionInfos) {
496                 int subId = sub.getSubscriptionId();
497                 TelephonyManager tm = (TelephonyManager)
498                         sContext.getSystemService(Context.TELEPHONY_SERVICE);
499                 String operator = tm.getSimOperatorNumeric(subId);
500 
501                 if (!TextUtils.isEmpty(operator)) {
502                     if (subId == SubscriptionController.getInstance().getDefaultSubId()) {
503                         MccTable.updateMccMncConfiguration(sContext, operator);
504                     }
505                     SubscriptionController.getInstance().setMccMnc(operator, subId);
506                 } else {
507                     logd("EVENT_RECORDS_LOADED Operator name is null");
508                 }
509 
510                 String iso = tm.getSimCountryIsoForPhone(phoneId);
511 
512                 if (!TextUtils.isEmpty(iso)) {
513                     SubscriptionController.getInstance().setCountryIso(iso, subId);
514                 } else {
515                     logd("EVENT_RECORDS_LOADED sim country iso is null");
516                 }
517 
518                 String msisdn = tm.getLine1Number(subId);
519                 if (msisdn != null) {
520                     SubscriptionController.getInstance().setDisplayNumber(msisdn, subId);
521                 }
522 
523                 String imsi = tm.createForSubscriptionId(subId).getSubscriberId();
524                 if (imsi != null) {
525                     SubscriptionController.getInstance().setImsi(imsi, subId);
526                 }
527 
528                 String[] ehplmns = records.getEhplmns();
529                 String[] hplmns = records.getPlmnsFromHplmnActRecord();
530                 if (ehplmns != null || hplmns != null) {
531                     SubscriptionController.getInstance().setAssociatedPlmns(ehplmns, hplmns, subId);
532                 }
533 
534                 /* Update preferred network type and network selection mode on SIM change.
535                  * Storing last subId in SharedPreference for now to detect SIM change.
536                  */
537                 SharedPreferences sp =
538                         PreferenceManager.getDefaultSharedPreferences(sContext);
539                 int storedSubId = sp.getInt(CURR_SUBID + phoneId, -1);
540 
541                 if (storedSubId != subId) {
542                     int networkType = Settings.Global.getInt(
543                             PhoneFactory.getPhone(phoneId).getContext().getContentResolver(),
544                             Settings.Global.PREFERRED_NETWORK_MODE + subId,
545                             -1 /* invalid network mode */);
546 
547                     if (networkType == -1) {
548                         networkType = RILConstants.PREFERRED_NETWORK_MODE;
549                         try {
550                             networkType = TelephonyManager.getIntAtIndex(
551                                     sContext.getContentResolver(),
552                                     Settings.Global.PREFERRED_NETWORK_MODE, phoneId);
553                         } catch (SettingNotFoundException retrySnfe) {
554                             Rlog.e(LOG_TAG, "Settings Exception Reading Value At Index for "
555                                     + "Settings.Global.PREFERRED_NETWORK_MODE");
556                         }
557                         Settings.Global.putInt(
558                                 PhoneFactory.getPhone(phoneId).getContext().getContentResolver(),
559                                 Global.PREFERRED_NETWORK_MODE + subId,
560                                 networkType);
561                     }
562 
563                     // Set the modem network mode
564                     PhoneFactory.getPhone(phoneId).setPreferredNetworkType(networkType, null);
565 
566                     // Only support automatic selection mode on SIM change.
567                     PhoneFactory.getPhone(phoneId).getNetworkSelectionMode(
568                             obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE,
569                                     new Integer(phoneId)));
570 
571                     // Update stored subId
572                     SharedPreferences.Editor editor = sp.edit();
573                     editor.putInt(CURR_SUBID + phoneId, subId);
574                     editor.apply();
575                 }
576             }
577         }
578 
579         // Update set of enabled carrier apps now that the privilege rules may have changed.
580         CarrierAppUtils.disableCarrierAppsUntilPrivileged(sContext.getOpPackageName(),
581                 TelephonyManager.getDefault(), mCurrentlyActiveUserId, sContext);
582 
583         /**
584          * The sim loading sequence will be
585          *  1. ACTION_SUBINFO_CONTENT_CHANGE happens through updateSubscriptionInfoByIccId() above.
586          *  2. ACTION_SIM_STATE_CHANGED/ACTION_SIM_CARD_STATE_CHANGED
587          *  /ACTION_SIM_APPLICATION_STATE_CHANGED
588          *  3. ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED
589          *  4. ACTION_CARRIER_CONFIG_CHANGED
590          */
591         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED, null);
592         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT);
593         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_LOADED);
594         updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED);
595         updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED);
596     }
597 
updateCarrierServices(int phoneId, String simState)598     private void updateCarrierServices(int phoneId, String simState) {
599         CarrierConfigManager configManager =
600                 (CarrierConfigManager) sContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
601         configManager.updateConfigForPhoneId(phoneId, simState);
602         mCarrierServiceBindHelper.updateForPhoneId(phoneId, simState);
603     }
604 
updateSubscriptionCarrierId(int phoneId, String simState)605     private void updateSubscriptionCarrierId(int phoneId, String simState) {
606         if (PhoneFactory.getPhone(phoneId) != null) {
607             PhoneFactory.getPhone(phoneId).resolveSubscriptionCarrierId(simState);
608         }
609     }
610 
611     /**
612      * PhoneId is the corresponding phoneId of the slot if slot was previously active.
613      * It could be INVALID if it was already inactive.
614      */
handleInactiveSlotIccStateChange(int phoneId, String iccId)615     private void handleInactiveSlotIccStateChange(int phoneId, String iccId) {
616         if (SubscriptionManager.isValidPhoneId(phoneId)) {
617             // If phoneId is valid, it means the physical slot was previously active in that
618             // phoneId. In this case, found the subId and set its phoneId to invalid.
619             if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
620                 logd("Slot of SIM" + (phoneId + 1) + " becomes inactive");
621             }
622             cleanSubscriptionInPhone(phoneId);
623         }
624         if (!TextUtils.isEmpty(iccId)) {
625             // If iccId is new, add a subscription record in the db.
626             String strippedIccId = IccUtils.stripTrailingFs(iccId);
627             if (SubscriptionController.getInstance().getSubInfoForIccId(strippedIccId) == null) {
628                 SubscriptionController.getInstance().insertEmptySubInfoRecord(
629                         strippedIccId, "CARD", SubscriptionManager.INVALID_PHONE_INDEX,
630                         SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM);
631             }
632         }
633     }
634 
cleanSubscriptionInPhone(int phoneId)635     private void cleanSubscriptionInPhone(int phoneId) {
636         sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
637         if (sInactiveIccIds[phoneId] != null) {
638             // When a SIM is unplugged, mark uicc applications enabled. This is to make sure when
639             // user unplugs and re-inserts the SIM card, we re-enable it.
640             logd("cleanSubscriptionInPhone " + phoneId + " inactive iccid "
641                     + sInactiveIccIds[phoneId]);
642             ContentValues value = new ContentValues(1);
643             value.put(SubscriptionManager.UICC_APPLICATIONS_ENABLED, true);
644             sContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value,
645                     SubscriptionManager.ICC_ID + "=\'" + sInactiveIccIds[phoneId] + "\'", null);
646             sInactiveIccIds[phoneId] = null;
647         }
648         updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
649     }
650 
handleSimAbsent(int phoneId)651     protected void handleSimAbsent(int phoneId) {
652         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
653             logd("handleSimAbsent on invalid phoneId");
654             return;
655         }
656         if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
657             logd("SIM" + (phoneId + 1) + " hot plug out");
658         }
659         cleanSubscriptionInPhone(phoneId);
660 
661         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT, null);
662         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_ABSENT);
663         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_UNKNOWN);
664         updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
665         updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT);
666     }
667 
handleSimError(int phoneId)668     protected void handleSimError(int phoneId) {
669         if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) {
670             logd("SIM" + (phoneId + 1) + " Error ");
671         }
672         sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM;
673         updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */);
674         broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR,
675                 IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR);
676         broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_CARD_IO_ERROR);
677         broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY);
678         updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR);
679         updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR);
680     }
681 
updateSubscriptionInfoByIccId(int phoneId, boolean updateEmbeddedSubs)682     protected synchronized void updateSubscriptionInfoByIccId(int phoneId,
683             boolean updateEmbeddedSubs) {
684         logd("updateSubscriptionInfoByIccId:+ Start - phoneId: " + phoneId);
685         if (!SubscriptionManager.isValidPhoneId(phoneId)) {
686             loge("[updateSubscriptionInfoByIccId]- invalid phoneId=" + phoneId);
687             return;
688         }
689         logd("updateSubscriptionInfoByIccId: removing subscription info record: phoneId "
690                 + phoneId);
691         // Clear phoneId only when sim absent is not enough. It's possible to switch SIM profile
692         // within the same slot. Need to clear the slot index of the previous sub. Thus always clear
693         // for the changing slot first.
694         SubscriptionController.getInstance().clearSubInfoRecord(phoneId);
695 
696         // If SIM is not absent, insert new record or update existing record.
697         if (!ICCID_STRING_FOR_NO_SIM.equals(sIccId[phoneId])) {
698             logd("updateSubscriptionInfoByIccId: adding subscription info record: iccid: "
699                     + sIccId[phoneId] + ", phoneId:" + phoneId);
700             mSubscriptionManager.addSubscriptionInfoRecord(sIccId[phoneId], phoneId);
701         }
702 
703         List<SubscriptionInfo> subInfos = SubscriptionController.getInstance()
704                 .getSubInfoUsingSlotIndexPrivileged(phoneId);
705         if (subInfos != null) {
706             boolean changed = false;
707             for (int i = 0; i < subInfos.size(); i++) {
708                 SubscriptionInfo temp = subInfos.get(i);
709                 ContentValues value = new ContentValues(1);
710 
711                 String msisdn = TelephonyManager.getDefault().getLine1Number(
712                         temp.getSubscriptionId());
713 
714                 if (!TextUtils.equals(msisdn, temp.getNumber())) {
715                     value.put(SubscriptionManager.NUMBER, msisdn);
716                     sContext.getContentResolver().update(SubscriptionManager
717                             .getUriForSubscriptionId(temp.getSubscriptionId()), value, null, null);
718                     changed = true;
719                 }
720             }
721             if (changed) {
722                 // refresh Cached Active Subscription Info List
723                 SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
724             }
725         }
726 
727         // TODO investigate if we can update for each slot separately.
728         if (isAllIccIdQueryDone()) {
729             // Ensure the modems are mapped correctly
730             if (mSubscriptionManager.isActiveSubId(
731                     mSubscriptionManager.getDefaultDataSubscriptionId())) {
732                 mSubscriptionManager.setDefaultDataSubId(
733                         mSubscriptionManager.getDefaultDataSubscriptionId());
734             } else {
735                 logd("bypass reset default data sub if inactive");
736             }
737             setSubInfoInitialized();
738         }
739 
740         UiccController uiccController = UiccController.getInstance();
741         UiccSlot[] uiccSlots = uiccController.getUiccSlots();
742         if (uiccSlots != null && updateEmbeddedSubs) {
743             List<Integer> cardIds = new ArrayList<>();
744             for (UiccSlot uiccSlot : uiccSlots) {
745                 if (uiccSlot != null && uiccSlot.getUiccCard() != null) {
746                     int cardId = uiccController.convertToPublicCardId(
747                             uiccSlot.getUiccCard().getCardId());
748                     cardIds.add(cardId);
749                 }
750             }
751             updateEmbeddedSubscriptions(cardIds, (hasChanges) -> {
752                 if (hasChanges) {
753                     SubscriptionController.getInstance().notifySubscriptionInfoChanged();
754                 }
755                 if (DBG) logd("updateSubscriptionInfoByIccId: SubscriptionInfo update complete");
756             });
757         }
758 
759         SubscriptionController.getInstance().notifySubscriptionInfoChanged();
760         if (DBG) logd("updateSubscriptionInfoByIccId: SubscriptionInfo update complete");
761     }
762 
setSubInfoInitialized()763     private static void setSubInfoInitialized() {
764         // Should only be triggered once.
765         if (!sIsSubInfoInitialized) {
766             if (DBG) logd("SubInfo Initialized");
767             sIsSubInfoInitialized = true;
768             SubscriptionController.getInstance().notifySubInfoReady();
769             MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded();
770         }
771     }
772 
773     /**
774      * Whether subscriptions of all SIMs are initialized.
775      */
isSubInfoInitialized()776     public static boolean isSubInfoInitialized() {
777         return sIsSubInfoInitialized;
778     }
779 
780     /**
781      * Updates the cached list of embedded subscription for the eUICC with the given list of card
782      * IDs {@code cardIds}. The step of reading the embedded subscription list from eUICC card is
783      * executed in background thread. The callback {@code callback} is executed after the cache is
784      * refreshed. The callback is executed in main thread.
785      */
786     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
updateEmbeddedSubscriptions(List<Integer> cardIds, @Nullable UpdateEmbeddedSubsCallback callback)787     public void updateEmbeddedSubscriptions(List<Integer> cardIds,
788             @Nullable UpdateEmbeddedSubsCallback callback) {
789         // Do nothing if eUICCs are disabled. (Previous entries may remain in the cache, but they
790         // are filtered out of list calls as long as EuiccManager.isEnabled returns false).
791         if (!mEuiccManager.isEnabled()) {
792             callback.run(false /* hasChanges */);
793             return;
794         }
795 
796         mBackgroundHandler.post(() -> {
797             List<Pair<Integer, GetEuiccProfileInfoListResult>> results = new ArrayList<>();
798             for (int cardId : cardIds) {
799                 GetEuiccProfileInfoListResult result =
800                         EuiccController.get().blockingGetEuiccProfileInfoList(cardId);
801                 if (DBG) logd("blockingGetEuiccProfileInfoList cardId " + cardId);
802                 results.add(Pair.create(cardId, result));
803             }
804 
805             // The runnable will be executed in the main thread.
806             this.post(() -> {
807                 boolean hasChanges = false;
808                 for (Pair<Integer, GetEuiccProfileInfoListResult> cardIdAndResult : results) {
809                     if (updateEmbeddedSubscriptionsCache(cardIdAndResult.first,
810                             cardIdAndResult.second)) {
811                         hasChanges = true;
812                     }
813                 }
814                 // The latest state in the main thread may be changed when the callback is
815                 // triggered.
816                 if (callback != null) {
817                     callback.run(hasChanges);
818                 }
819             });
820         });
821     }
822 
823     /**
824      * Update the cached list of embedded subscription based on the passed in
825      * GetEuiccProfileInfoListResult {@code result}.
826      *
827      * @return true if changes may have been made. This is not a guarantee that changes were made,
828      * but notifications about subscription changes may be skipped if this returns false as an
829      * optimization to avoid spurious notifications.
830      */
updateEmbeddedSubscriptionsCache(int cardId, GetEuiccProfileInfoListResult result)831     private boolean updateEmbeddedSubscriptionsCache(int cardId,
832             GetEuiccProfileInfoListResult result) {
833         if (DBG) logd("updateEmbeddedSubscriptionsCache");
834 
835         if (result == null) {
836             // IPC to the eUICC controller failed.
837             return false;
838         }
839 
840         // If the returned result is not RESULT_OK or the profile list is null, don't update cache.
841         // Otherwise, update the cache.
842         final EuiccProfileInfo[] embeddedProfiles;
843         List<EuiccProfileInfo> list = result.getProfiles();
844         if (result.getResult() == EuiccService.RESULT_OK && list != null) {
845             embeddedProfiles = list.toArray(new EuiccProfileInfo[list.size()]);
846             if (DBG) {
847                 logd("blockingGetEuiccProfileInfoList: got " + result.getProfiles().size()
848                         + " profiles");
849             }
850         } else {
851             if (DBG) {
852                 logd("blockingGetEuiccProfileInfoList returns an error. "
853                         + "Result code=" + result.getResult()
854                         + ". Null profile list=" + (result.getProfiles() == null));
855             }
856             return false;
857         }
858 
859         final boolean isRemovable = result.getIsRemovable();
860 
861         final String[] embeddedIccids = new String[embeddedProfiles.length];
862         for (int i = 0; i < embeddedProfiles.length; i++) {
863             embeddedIccids[i] = embeddedProfiles[i].getIccid();
864         }
865 
866         if (DBG) logd("Get eUICC profile list of size " + embeddedProfiles.length);
867 
868         // Note that this only tracks whether we make any writes to the DB. It's possible this will
869         // be set to true for an update even when the row contents remain exactly unchanged from
870         // before, since we don't compare against the previous value. Since this is only intended to
871         // avoid some spurious broadcasts (particularly for users who don't use eSIM at all), this
872         // is fine.
873         boolean hasChanges = false;
874 
875         // Update or insert records for all embedded subscriptions (except non-removable ones if the
876         // current eUICC is non-removable, since we assume these are still accessible though not
877         // returned by the eUICC controller).
878         List<SubscriptionInfo> existingSubscriptions = SubscriptionController.getInstance()
879                 .getSubscriptionInfoListForEmbeddedSubscriptionUpdate(embeddedIccids, isRemovable);
880         ContentResolver contentResolver = sContext.getContentResolver();
881         for (EuiccProfileInfo embeddedProfile : embeddedProfiles) {
882             int index =
883                     findSubscriptionInfoForIccid(existingSubscriptions, embeddedProfile.getIccid());
884             int prevCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
885             int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER_ID;
886             if (index < 0) {
887                 // No existing entry for this ICCID; create an empty one.
888                 SubscriptionController.getInstance().insertEmptySubInfoRecord(
889                         embeddedProfile.getIccid(), SubscriptionManager.SIM_NOT_INSERTED);
890             } else {
891                 nameSource = existingSubscriptions.get(index).getNameSource();
892                 prevCarrierId = existingSubscriptions.get(index).getCarrierId();
893                 existingSubscriptions.remove(index);
894             }
895 
896             if (DBG) {
897                 logd("embeddedProfile " + embeddedProfile + " existing record "
898                         + (index < 0 ? "not found" : "found"));
899             }
900 
901             ContentValues values = new ContentValues();
902             values.put(SubscriptionManager.IS_EMBEDDED, 1);
903             List<UiccAccessRule> ruleList = embeddedProfile.getUiccAccessRules();
904             boolean isRuleListEmpty = false;
905             if (ruleList == null || ruleList.size() == 0) {
906                 isRuleListEmpty = true;
907             }
908             values.put(SubscriptionManager.ACCESS_RULES,
909                     isRuleListEmpty ? null : UiccAccessRule.encodeRules(
910                             ruleList.toArray(new UiccAccessRule[ruleList.size()])));
911             values.put(SubscriptionManager.IS_REMOVABLE, isRemovable);
912             // override DISPLAY_NAME if the priority of existing nameSource is <= carrier
913             if (SubscriptionController.getNameSourcePriority(nameSource)
914                     <= SubscriptionController.getNameSourcePriority(
915                             SubscriptionManager.NAME_SOURCE_CARRIER)) {
916                 values.put(SubscriptionManager.DISPLAY_NAME, embeddedProfile.getNickname());
917                 values.put(SubscriptionManager.NAME_SOURCE,
918                         SubscriptionManager.NAME_SOURCE_CARRIER);
919             }
920             values.put(SubscriptionManager.PROFILE_CLASS, embeddedProfile.getProfileClass());
921             CarrierIdentifier cid = embeddedProfile.getCarrierIdentifier();
922             if (cid != null) {
923                 // Due to the limited subscription information, carrier id identified here might
924                 // not be accurate compared with CarrierResolver. Only update carrier id if there
925                 // is no valid carrier id present.
926                 if (prevCarrierId == TelephonyManager.UNKNOWN_CARRIER_ID) {
927                     values.put(SubscriptionManager.CARRIER_ID,
928                             CarrierResolver.getCarrierIdFromIdentifier(sContext, cid));
929                 }
930                 String mcc = cid.getMcc();
931                 String mnc = cid.getMnc();
932                 values.put(SubscriptionManager.MCC_STRING, mcc);
933                 values.put(SubscriptionManager.MCC, mcc);
934                 values.put(SubscriptionManager.MNC_STRING, mnc);
935                 values.put(SubscriptionManager.MNC, mnc);
936             }
937             // If cardId = unsupported or unitialized, we have no reason to update DB.
938             // Additionally, if the device does not support cardId for default eUICC, the CARD_ID
939             // field should not contain the EID
940             UiccController uiccController = UiccController.getInstance();
941             if (cardId >= 0 && uiccController.getCardIdForDefaultEuicc()
942                     != TelephonyManager.UNSUPPORTED_CARD_ID) {
943                 values.put(SubscriptionManager.CARD_ID, uiccController.convertToCardString(cardId));
944             }
945             hasChanges = true;
946             contentResolver.update(SubscriptionManager.CONTENT_URI, values,
947                     SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.getIccid() + "\"", null);
948 
949             // refresh Cached Active Subscription Info List
950             SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
951         }
952 
953         // Remove all remaining subscriptions which have embedded = true. We set embedded to false
954         // to ensure they are not returned in the list of embedded subscriptions (but keep them
955         // around in case the subscription is added back later, which is equivalent to a removable
956         // SIM being removed and reinserted).
957         if (!existingSubscriptions.isEmpty()) {
958             if (DBG) {
959                 logd("Removing existing embedded subscriptions of size"
960                         + existingSubscriptions.size());
961             }
962             List<String> iccidsToRemove = new ArrayList<>();
963             for (int i = 0; i < existingSubscriptions.size(); i++) {
964                 SubscriptionInfo info = existingSubscriptions.get(i);
965                 if (info.isEmbedded()) {
966                     if (DBG) logd("Removing embedded subscription of IccId " + info.getIccId());
967                     iccidsToRemove.add("\"" + info.getIccId() + "\"");
968                 }
969             }
970             String whereClause = SubscriptionManager.ICC_ID + " IN ("
971                     + TextUtils.join(",", iccidsToRemove) + ")";
972             ContentValues values = new ContentValues();
973             values.put(SubscriptionManager.IS_EMBEDDED, 0);
974             hasChanges = true;
975             contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null);
976 
977             // refresh Cached Active Subscription Info List
978             SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
979         }
980 
981         if (DBG) logd("updateEmbeddedSubscriptions done hasChanges=" + hasChanges);
982         return hasChanges;
983     }
984 
985     /**
986      * Called by CarrierConfigLoader to update the subscription before sending a broadcast.
987      */
updateSubscriptionByCarrierConfigAndNotifyComplete(int phoneId, String configPackageName, PersistableBundle config, Message onComplete)988     public void updateSubscriptionByCarrierConfigAndNotifyComplete(int phoneId,
989             String configPackageName, PersistableBundle config, Message onComplete) {
990         post(() -> {
991             updateSubscriptionByCarrierConfig(phoneId, configPackageName, config);
992             onComplete.sendToTarget();
993         });
994     }
995 
getDefaultCarrierServicePackageName()996     private String getDefaultCarrierServicePackageName() {
997         CarrierConfigManager configManager =
998                 (CarrierConfigManager) sContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
999         return configManager.getDefaultCarrierServicePackageName();
1000     }
1001 
isCarrierServicePackage(int phoneId, String pkgName)1002     private boolean isCarrierServicePackage(int phoneId, String pkgName) {
1003         if (pkgName.equals(getDefaultCarrierServicePackageName())) return false;
1004 
1005         List<String> carrierPackageNames = TelephonyManager.from(sContext)
1006                 .getCarrierPackageNamesForIntentAndPhone(
1007                         new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId);
1008         if (DBG) logd("Carrier Packages For Subscription = " + carrierPackageNames);
1009         return carrierPackageNames != null && carrierPackageNames.contains(pkgName);
1010     }
1011 
1012     /**
1013      * Update the currently active Subscription based on information from CarrierConfig
1014      */
1015     @VisibleForTesting
updateSubscriptionByCarrierConfig( int phoneId, String configPackageName, PersistableBundle config)1016     public void updateSubscriptionByCarrierConfig(
1017             int phoneId, String configPackageName, PersistableBundle config) {
1018         if (!SubscriptionManager.isValidPhoneId(phoneId)
1019                 || TextUtils.isEmpty(configPackageName) || config == null) {
1020             if (DBG) {
1021                 logd("In updateSubscriptionByCarrierConfig(): phoneId=" + phoneId
1022                         + " configPackageName=" + configPackageName + " config="
1023                         + ((config == null) ? "null" : config.hashCode()));
1024             }
1025             return;
1026         }
1027 
1028         SubscriptionController sc = SubscriptionController.getInstance();
1029         if (sc == null) {
1030             loge("SubscriptionController was null");
1031             return;
1032         }
1033 
1034         int currentSubId = sc.getSubIdUsingPhoneId(phoneId);
1035         if (!SubscriptionManager.isValidSubscriptionId(currentSubId)
1036                 || currentSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
1037             if (DBG) logd("No subscription is active for phone being updated");
1038             return;
1039         }
1040 
1041         SubscriptionInfo currentSubInfo = sc.getSubscriptionInfo(currentSubId);
1042         if (currentSubInfo == null) {
1043             loge("Couldn't retrieve subscription info for current subscription");
1044             return;
1045         }
1046 
1047         ContentValues cv = new ContentValues();
1048         ParcelUuid groupUuid = null;
1049 
1050         // carrier certificates are not subscription-specific, so we want to load them even if
1051         // this current package is not a CarrierServicePackage
1052         String[] certs = config.getStringArray(
1053             CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY);
1054         if (certs != null) {
1055             UiccAccessRule[] 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             cv.put(SubscriptionManager.ACCESS_RULES_FROM_CARRIER_CONFIGS,
1061                     UiccAccessRule.encodeRules(carrierConfigAccessRules));
1062         }
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