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