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