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