1 /* 2 * Copyright (C) 2017 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 package com.android.internal.telephony.euicc; 17 18 import static android.content.pm.PackageManager.FEATURE_TELEPHONY_EUICC; 19 import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING; 20 21 import android.Manifest; 22 import android.Manifest.permission; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.app.ActivityManager; 26 import android.app.AppOpsManager; 27 import android.app.PendingIntent; 28 import android.app.admin.DevicePolicyManager; 29 import android.app.compat.CompatChanges; 30 import android.content.ComponentName; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.pm.ComponentInfo; 34 import android.content.pm.PackageInfo; 35 import android.content.pm.PackageManager; 36 import android.os.Binder; 37 import android.os.Build; 38 import android.os.Bundle; 39 import android.os.SystemProperties; 40 import android.os.UserHandle; 41 import android.os.UserManager; 42 import android.provider.Settings; 43 import android.service.euicc.DownloadSubscriptionResult; 44 import android.service.euicc.EuiccService; 45 import android.service.euicc.GetDefaultDownloadableSubscriptionListResult; 46 import android.service.euicc.GetDownloadableSubscriptionMetadataResult; 47 import android.service.euicc.GetEuiccProfileInfoListResult; 48 import android.telephony.AnomalyReporter; 49 import android.telephony.SubscriptionInfo; 50 import android.telephony.SubscriptionManager; 51 import android.telephony.TelephonyFrameworkInitializer; 52 import android.telephony.TelephonyManager; 53 import android.telephony.UiccAccessRule; 54 import android.telephony.UiccCardInfo; 55 import android.telephony.UiccPortInfo; 56 import android.telephony.UiccSlotInfo; 57 import android.telephony.euicc.DownloadableSubscription; 58 import android.telephony.euicc.EuiccCardManager.ResetOption; 59 import android.telephony.euicc.EuiccInfo; 60 import android.telephony.euicc.EuiccManager; 61 import android.telephony.euicc.EuiccManager.OtaStatus; 62 import android.text.TextUtils; 63 import android.util.ArraySet; 64 import android.util.EventLog; 65 import android.util.Log; 66 import android.util.Pair; 67 68 import com.android.internal.annotations.VisibleForTesting; 69 import com.android.internal.telephony.CarrierPrivilegesTracker; 70 import com.android.internal.telephony.Phone; 71 import com.android.internal.telephony.PhoneFactory; 72 import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback; 73 import com.android.internal.telephony.flags.FeatureFlags; 74 import com.android.internal.telephony.flags.Flags; 75 import com.android.internal.telephony.subscription.SubscriptionManagerService; 76 import com.android.internal.telephony.uicc.IccUtils; 77 import com.android.internal.telephony.uicc.UiccController; 78 import com.android.internal.telephony.uicc.UiccPort; 79 import com.android.internal.telephony.uicc.UiccSlot; 80 81 import java.io.FileDescriptor; 82 import java.io.PrintWriter; 83 import java.util.Arrays; 84 import java.util.Collections; 85 import java.util.List; 86 import java.util.Set; 87 import java.util.Stack; 88 import java.util.UUID; 89 import java.util.concurrent.CountDownLatch; 90 import java.util.concurrent.TimeUnit; 91 import java.util.concurrent.atomic.AtomicReference; 92 import java.util.stream.Collectors; 93 94 /** Backing implementation of {@link android.telephony.euicc.EuiccManager}. */ 95 public class EuiccController extends IEuiccController.Stub { 96 private static final String TAG = "EuiccController"; 97 98 /** Extra set on resolution intents containing the {@link EuiccOperation}. */ 99 @VisibleForTesting 100 static final String EXTRA_OPERATION = "operation"; 101 102 /** 103 * Time out for {@link #dump(FileDescriptor, PrintWriter, String[])} 104 */ 105 private static final int EUICC_DUMP_TIME_OUT_SECONDS = 5; 106 107 // Aliases so line lengths stay short. 108 private static final int OK = EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK; 109 private static final int RESOLVABLE_ERROR = 110 EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR; 111 private static final int ERROR = 112 EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR; 113 private static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = 114 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION; 115 116 /** Restrictions limiting access to the PendingIntent */ 117 private static final String RESOLUTION_ACTIVITY_PACKAGE_NAME = "com.android.phone"; 118 private static final String RESOLUTION_ACTIVITY_CLASS_NAME = 119 "com.android.phone.euicc.EuiccResolutionUiDispatcherActivity"; 120 121 private static EuiccController sInstance; 122 123 private final Context mContext; 124 private final EuiccConnector mConnector; 125 private final SubscriptionManager mSubscriptionManager; 126 private final TelephonyManager mTelephonyManager; 127 private final AppOpsManager mAppOpsManager; 128 private final PackageManager mPackageManager; 129 private final FeatureFlags mFeatureFlags; 130 private final int mVendorApiLevel; 131 132 // These values should be set or updated upon 1) system boot, 2) EuiccService/LPA is bound to 133 // the phone process, 3) values are updated remotely by server flags. 134 private List<String> mSupportedCountries; 135 private List<String> mUnsupportedCountries; 136 private List<Integer> mPsimConversionSupportedCarrierIds; 137 138 /** Initialize the instance. Should only be called once. */ init(Context context, FeatureFlags featureFlags)139 public static EuiccController init(Context context, FeatureFlags featureFlags) { 140 synchronized (EuiccController.class) { 141 if (sInstance == null) { 142 sInstance = new EuiccController(context, featureFlags); 143 } else { 144 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance); 145 } 146 } 147 return sInstance; 148 } 149 150 /** Get an instance. Assumes one has already been initialized with {@link #init}. */ get()151 public static EuiccController get() { 152 if (sInstance == null) { 153 synchronized (EuiccController.class) { 154 if (sInstance == null) { 155 throw new IllegalStateException("get() called before init()"); 156 } 157 } 158 } 159 return sInstance; 160 } 161 EuiccController(Context context, FeatureFlags featureFlags)162 private EuiccController(Context context, FeatureFlags featureFlags) { 163 this(context, new EuiccConnector(context), featureFlags); 164 TelephonyFrameworkInitializer 165 .getTelephonyServiceManager().getEuiccControllerService().register(this); 166 } 167 168 @VisibleForTesting EuiccController(Context context, EuiccConnector connector, FeatureFlags featureFlags)169 public EuiccController(Context context, EuiccConnector connector, FeatureFlags featureFlags) { 170 mContext = context; 171 mConnector = connector; 172 mSubscriptionManager = (SubscriptionManager) 173 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 174 mTelephonyManager = (TelephonyManager) 175 context.getSystemService(Context.TELEPHONY_SERVICE); 176 mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 177 mPackageManager = context.getPackageManager(); 178 mFeatureFlags = featureFlags; 179 mVendorApiLevel = SystemProperties.getInt( 180 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT); 181 } 182 183 /** 184 * Continue an operation which failed with a user-resolvable error. 185 * 186 * <p>The implementation here makes a key assumption that the resolutionIntent has not been 187 * tampered with. This is guaranteed because: 188 * <UL> 189 * <LI>The intent is wrapped in a PendingIntent created by the phone process which is created 190 * with {@link #EXTRA_OPERATION} already present. This means that the operation cannot be 191 * overridden on the PendingIntent - a caller can only add new extras. 192 * <LI>The resolution activity is restricted by a privileged permission; unprivileged apps 193 * cannot start it directly. So the PendingIntent is the only way to start it. 194 * </UL> 195 */ 196 @Override continueOperation(int cardId, Intent resolutionIntent, Bundle resolutionExtras)197 public void continueOperation(int cardId, Intent resolutionIntent, Bundle resolutionExtras) { 198 if (!callerCanWriteEmbeddedSubscriptions()) { 199 throw new SecurityException( 200 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to continue operation"); 201 } 202 long token = Binder.clearCallingIdentity(); 203 try { 204 EuiccOperation op = resolutionIntent.getParcelableExtra(EXTRA_OPERATION); 205 if (op == null) { 206 throw new IllegalArgumentException("Invalid resolution intent"); 207 } 208 209 PendingIntent callbackIntent = 210 resolutionIntent.getParcelableExtra( 211 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT); 212 boolean usePortIndex = resolutionIntent.getBooleanExtra( 213 EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, false); 214 resolutionExtras.putBoolean(EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, usePortIndex); 215 216 if (!EuiccService.ACTION_RESOLVE_NO_PRIVILEGES.equals(resolutionIntent.getAction()) 217 || !resolutionExtras.containsKey(EuiccService.EXTRA_RESOLUTION_PORT_INDEX)) { 218 // Port index resolution is requested only through the ACTION_RESOLVE_NO_PRIVILEGES 219 // action. Therefore, if the action is not ACTION_RESOLVE_NO_PRIVILEGES, use the 220 // port index from the resolution intent. 221 // (OR) If the action is ACTION_RESOLVE_NO_PRIVILEGES and resolutionExtras does not 222 // contain the EXTRA_RESOLUTION_PORT_INDEX key, retrieve the port index from 223 // resolutionIntent. 224 resolutionExtras.putInt(EuiccService.EXTRA_RESOLUTION_PORT_INDEX, 225 resolutionIntent.getIntExtra(EuiccService.EXTRA_RESOLUTION_PORT_INDEX, 226 TelephonyManager.DEFAULT_PORT_INDEX)); 227 } 228 Log.i(TAG, " continueOperation portIndex: " + resolutionExtras.getInt( 229 EuiccService.EXTRA_RESOLUTION_PORT_INDEX) + " usePortIndex: " + usePortIndex); 230 op.continueOperation(cardId, resolutionExtras, callbackIntent); 231 } finally { 232 Binder.restoreCallingIdentity(token); 233 } 234 } 235 236 /** 237 * Return the EID. 238 * 239 * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 240 * that IPC should generally be fast, and the EID shouldn't be needed in the normal course of 241 * operation. 242 */ 243 @Override getEid(int cardId, String callingPackage)244 public String getEid(int cardId, String callingPackage) { 245 boolean callerCanReadPhoneStatePrivileged = callerCanReadPhoneStatePrivileged(); 246 try { 247 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 248 } catch (SecurityException e) { 249 EventLog.writeEvent(0x534e4554, "159062405", -1, "Missing UID checking"); 250 throw e; 251 } 252 long token = Binder.clearCallingIdentity(); 253 try { 254 if (!callerCanReadPhoneStatePrivileged 255 && !canManageSubscriptionOnTargetSim(cardId, callingPackage, false, 256 TelephonyManager.INVALID_PORT_INDEX)) { 257 throw new SecurityException( 258 "Must have carrier privileges on subscription to read EID for cardId=" 259 + cardId); 260 } 261 262 return blockingGetEidFromEuiccService(cardId); 263 } finally { 264 Binder.restoreCallingIdentity(token); 265 } 266 } 267 268 /** 269 * Return the available memory in bytes of the eUICC. 270 * 271 * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 272 * that IPC should generally be fast, and the available memory shouldn't be needed in the normal 273 * course of operation. 274 */ 275 @Override getAvailableMemoryInBytes(int cardId, String callingPackage)276 public long getAvailableMemoryInBytes(int cardId, String callingPackage) { 277 boolean callerCanReadPhoneStatePrivileged = callerCanReadPhoneStatePrivileged(); 278 boolean callerCanReadPhoneState = callerCanReadPhoneState(); 279 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 280 long token = Binder.clearCallingIdentity(); 281 try { 282 if (!callerCanReadPhoneStatePrivileged 283 && !callerCanReadPhoneState 284 && !canManageSubscriptionOnTargetSim( 285 cardId, callingPackage, false, TelephonyManager.INVALID_PORT_INDEX)) { 286 throw new SecurityException( 287 "Must have READ_PHONE_STATE permission or READ_PRIVILEGED_PHONE_STATE" 288 + " permission or carrier privileges to read the available memory for" 289 + "cardId=" 290 + cardId); 291 } 292 return blockingGetAvailableMemoryInBytesFromEuiccService(cardId); 293 } finally { 294 Binder.restoreCallingIdentity(token); 295 } 296 } 297 298 /** 299 * Return the current status of OTA update. 300 * 301 * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 302 * that IPC should generally be fast. 303 */ 304 @Override getOtaStatus(int cardId)305 public @OtaStatus int getOtaStatus(int cardId) { 306 if (!callerCanWriteEmbeddedSubscriptions()) { 307 throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get OTA status"); 308 } 309 long token = Binder.clearCallingIdentity(); 310 try { 311 return blockingGetOtaStatusFromEuiccService(cardId); 312 } finally { 313 Binder.restoreCallingIdentity(token); 314 } 315 } 316 317 /** 318 * Start eUICC OTA update on the default eUICC if current eUICC OS is not the latest one. When 319 * OTA is started or finished, the broadcast {@link EuiccManager#ACTION_OTA_STATUS_CHANGED} will 320 * be sent. 321 * 322 * This function will only be called from phone process and isn't exposed to the other apps. 323 * 324 * (see {@link #startOtaUpdatingIfNecessary(int cardId)}). 325 */ startOtaUpdatingIfNecessary()326 public void startOtaUpdatingIfNecessary() { 327 // TODO(b/120796772) Eventually, we should use startOtaUpdatingIfNecessary(cardId) 328 startOtaUpdatingIfNecessary(mTelephonyManager.getCardIdForDefaultEuicc()); 329 } 330 331 /** 332 * Start eUICC OTA update on the given eUICC if current eUICC OS is not the latest one. 333 */ startOtaUpdatingIfNecessary(int cardId)334 public void startOtaUpdatingIfNecessary(int cardId) { 335 mConnector.startOtaIfNecessary(cardId, 336 new OtaStatusChangedCallback() { 337 @Override 338 public void onOtaStatusChanged(int status) { 339 sendOtaStatusChangedBroadcast(); 340 } 341 342 @Override 343 public void onEuiccServiceUnavailable() {} 344 }); 345 } 346 347 @Override getDownloadableSubscriptionMetadata(int cardId, DownloadableSubscription subscription, String callingPackage, PendingIntent callbackIntent)348 public void getDownloadableSubscriptionMetadata(int cardId, 349 DownloadableSubscription subscription, String callingPackage, 350 PendingIntent callbackIntent) { 351 getDownloadableSubscriptionMetadata(cardId, 352 subscription, false /* forceDeactivateSim */, callingPackage, callbackIntent); 353 } 354 355 /** 356 * Sets the supported or unsupported countries for eUICC. 357 * 358 * <p>If {@code isSupported} is true, the supported country list will be replaced by 359 * {@code countriesList}. Otherwise, unsupported country list will be replaced by 360 * {@code countriesList}. For how we determine whether a country is supported by checking 361 * supported and unsupported country list please check {@link EuiccManager#isSupportedCountry}. 362 * 363 * @param isSupported should be true if caller wants to set supported country list. If 364 * isSupported is false, un-supported country list will be updated. 365 * @param countriesList is a list of strings contains country ISO codes in uppercase. 366 */ 367 @Override setSupportedCountries(boolean isSupported, @NonNull List<String> countriesList)368 public void setSupportedCountries(boolean isSupported, @NonNull List<String> countriesList) { 369 if (!callerCanWriteEmbeddedSubscriptions()) { 370 throw new SecurityException( 371 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to set supported countries"); 372 } 373 if (isSupported) { 374 mSupportedCountries = countriesList; 375 } else { 376 mUnsupportedCountries = countriesList; 377 } 378 } 379 380 /** 381 * Gets the supported or unsupported countries for eUICC. 382 * 383 * <p>If {@code isSupported} is true, the supported country list will be returned. Otherwise, 384 * unsupported country list will be returned. 385 * 386 * @param isSupported should be true if caller wants to get supported country list. If 387 * isSupported is false, unsupported country list will be returned. 388 * @return a list of strings contains country ISO codes in uppercase. 389 */ 390 @Override 391 @NonNull getSupportedCountries(boolean isSupported)392 public List<String> getSupportedCountries(boolean isSupported) { 393 if (!callerCanWriteEmbeddedSubscriptions()) { 394 throw new SecurityException( 395 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get supported countries"); 396 } 397 if (isSupported && mSupportedCountries != null) { 398 return mSupportedCountries; 399 } else if (!isSupported && mUnsupportedCountries != null) { 400 return mUnsupportedCountries; 401 } 402 return Collections.emptyList(); 403 } 404 405 /** 406 * Returns whether the given country supports eUICC. 407 * 408 * <p>Supported country list has a higher prority than unsupported country list. If the 409 * supported country list is not empty, {@code countryIso} will be considered as supported when 410 * it exists in the supported country list. Otherwise {@code countryIso} is not supported. If 411 * the supported country list is empty, {@code countryIso} will be considered as supported if it 412 * does not exist in the unsupported country list. Otherwise {@code countryIso} is not 413 * supported. If both supported and unsupported country lists are empty, then all countries are 414 * consider be supported. For how to set supported and unsupported country list, please check 415 * {@link #setSupportedCountries}. 416 * 417 * @param countryIso should be the ISO-3166 country code is provided in uppercase 2 character 418 * format. 419 * @return whether the given country supports eUICC or not. 420 */ 421 @Override isSupportedCountry(@onNull String countryIso)422 public boolean isSupportedCountry(@NonNull String countryIso) { 423 if (!callerCanWriteEmbeddedSubscriptions()) { 424 throw new SecurityException( 425 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to check if the country is supported"); 426 } 427 if (mSupportedCountries == null || mSupportedCountries.isEmpty()) { 428 Log.i(TAG, "Using deny list unsupportedCountries=" + mUnsupportedCountries); 429 return !isEsimUnsupportedCountry(countryIso); 430 } else { 431 Log.i(TAG, "Using allow list supportedCountries=" + mSupportedCountries); 432 return isEsimSupportedCountry(countryIso); 433 } 434 } 435 isEsimSupportedCountry(String countryIso)436 private boolean isEsimSupportedCountry(String countryIso) { 437 if (mSupportedCountries == null || TextUtils.isEmpty(countryIso)) { 438 return true; 439 } 440 return mSupportedCountries.contains(countryIso); 441 } 442 isEsimUnsupportedCountry(String countryIso)443 private boolean isEsimUnsupportedCountry(String countryIso) { 444 if (mUnsupportedCountries == null || TextUtils.isEmpty(countryIso)) { 445 return false; 446 } 447 return mUnsupportedCountries.contains(countryIso); 448 } 449 getDownloadableSubscriptionMetadata(int cardId, DownloadableSubscription subscription, boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent)450 void getDownloadableSubscriptionMetadata(int cardId, DownloadableSubscription subscription, 451 boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 452 Log.d(TAG, " getDownloadableSubscriptionMetadata callingPackage: " + callingPackage); 453 if (!callerCanWriteEmbeddedSubscriptions()) { 454 throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get metadata"); 455 } 456 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 457 long token = Binder.clearCallingIdentity(); 458 try { 459 mConnector.getDownloadableSubscriptionMetadata(cardId, 460 TelephonyManager.DEFAULT_PORT_INDEX, subscription, 461 false /* switchAfterDownload */, forceDeactivateSim, 462 new GetMetadataCommandCallback( 463 token, subscription, callingPackage, callbackIntent)); 464 } finally { 465 Binder.restoreCallingIdentity(token); 466 } 467 } 468 469 class GetMetadataCommandCallback implements EuiccConnector.GetMetadataCommandCallback { 470 protected final long mCallingToken; 471 protected final DownloadableSubscription mSubscription; 472 protected final String mCallingPackage; 473 protected final PendingIntent mCallbackIntent; 474 GetMetadataCommandCallback( long callingToken, DownloadableSubscription subscription, String callingPackage, PendingIntent callbackIntent)475 GetMetadataCommandCallback( 476 long callingToken, 477 DownloadableSubscription subscription, 478 String callingPackage, 479 PendingIntent callbackIntent) { 480 mCallingToken = callingToken; 481 mSubscription = subscription; 482 mCallingPackage = callingPackage; 483 mCallbackIntent = callbackIntent; 484 } 485 486 @Override onGetMetadataComplete(int cardId, GetDownloadableSubscriptionMetadataResult result)487 public void onGetMetadataComplete(int cardId, 488 GetDownloadableSubscriptionMetadataResult result) { 489 Intent extrasIntent = new Intent(); 490 final int resultCode; 491 switch (result.getResult()) { 492 case EuiccService.RESULT_OK: 493 resultCode = OK; 494 extrasIntent.putExtra( 495 EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION, 496 result.getDownloadableSubscription()); 497 break; 498 case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 499 resultCode = RESOLVABLE_ERROR; 500 addResolutionIntentWithPort(extrasIntent, 501 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 502 mCallingPackage, 503 0 /* resolvableErrors */, 504 false /* confirmationCodeRetried */, 505 getOperationForDeactivateSim(), 506 cardId, 507 TelephonyManager.DEFAULT_PORT_INDEX, false /* usePortIndex */); 508 break; 509 default: 510 resultCode = ERROR; 511 addExtrasToResultIntent(extrasIntent, result.getResult()); 512 break; 513 } 514 515 sendResult(mCallbackIntent, resultCode, extrasIntent); 516 } 517 518 @Override onEuiccServiceUnavailable()519 public void onEuiccServiceUnavailable() { 520 sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 521 } 522 getOperationForDeactivateSim()523 protected EuiccOperation getOperationForDeactivateSim() { 524 return EuiccOperation.forGetMetadataDeactivateSim( 525 mCallingToken, mSubscription, mCallingPackage); 526 } 527 } 528 529 @Override downloadSubscription(int cardId, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage, Bundle resolvedBundle, PendingIntent callbackIntent)530 public void downloadSubscription(int cardId, DownloadableSubscription subscription, 531 boolean switchAfterDownload, String callingPackage, Bundle resolvedBundle, 532 PendingIntent callbackIntent) { 533 // If switchAfterDownload is true, set portIndex as 534 // {@link android.telephony.TelephonyManager#INVALID_PORT_INDEX} to resolve the port index. 535 int portIndex = switchAfterDownload ? TelephonyManager.INVALID_PORT_INDEX 536 : TelephonyManager.DEFAULT_PORT_INDEX; 537 downloadSubscription(cardId, portIndex, subscription, 538 switchAfterDownload, callingPackage, false /* forceDeactivateSim */, 539 resolvedBundle, callbackIntent); 540 } 541 542 /** 543 * Given encoded error code described in 544 * {@link android.telephony.euicc.EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE} decode it 545 * into SubjectCode[5.2.6.1] and ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2) 546 * 547 * @param resultCode from 548 * {@link android.telephony.euicc.EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE} 549 * @return a pair containing SubjectCode[5.2.6.1] and ReasonCode[5.2.6.2] from GSMA (SGP.22 550 * v2.2) 551 */ decodeSmdxSubjectAndReasonCode(int resultCode)552 Pair<String, String> decodeSmdxSubjectAndReasonCode(int resultCode) { 553 final int numOfSections = 6; 554 final int bitsPerSection = 4; 555 final int sectionMask = 0xF; 556 557 final Stack<Integer> sections = new Stack<>(); 558 559 // Extracting each section of digits backwards. 560 for (int i = 0; i < numOfSections; ++i) { 561 int sectionDigit = resultCode & sectionMask; 562 sections.push(sectionDigit); 563 resultCode = resultCode >>> bitsPerSection; 564 } 565 566 String subjectCode = sections.pop() + "." + sections.pop() + "." + sections.pop(); 567 String reasonCode = sections.pop() + "." + sections.pop() + "." + sections.pop(); 568 569 // drop the leading zeros, e.g 0.1 -> 1, 0.0.3 -> 3, 0.5.1 -> 5.1 570 subjectCode = subjectCode.replaceAll("^(0\\.)*", ""); 571 reasonCode = reasonCode.replaceAll("^(0\\.)*", ""); 572 573 return Pair.create(subjectCode, reasonCode); 574 } 575 576 /** 577 * Add more detailed information to the resulting intent. 578 * Fields added includes(key -> value): 579 * 1. {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} -> original error code 580 * 2. {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE} -> 581 * EuiccManager.OperationCode such as {@link EuiccManager#OPERATION_DOWNLOAD} 582 * 3. if @link EuiccManager.OperationCode is not 583 * {@link EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE}: 584 * {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE} -> @link 585 * EuiccManager.ErrorCode such as {@link EuiccManager#OPERATION_SMDX} 586 * 4. if EuiccManager.OperationCode is 587 * {@link EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE}: 588 * a) {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE} -> 589 * SubjectCode[5.2.6.1] from GSMA (SGP.22 v2.2) 590 * b) {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE} -> 591 * ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2 592 */ addExtrasToResultIntent(Intent intent, int resultCode)593 private void addExtrasToResultIntent(Intent intent, int resultCode) { 594 final int firstByteBitOffset = 24; 595 int errorCodeMask = 0xFFFFFF; 596 int operationCode = resultCode >>> firstByteBitOffset; 597 598 intent.putExtra( 599 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, resultCode); 600 601 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE, operationCode); 602 603 // check to see if the operation code is EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE 604 final boolean isSmdxSubjectReasonCode = 605 (operationCode == EuiccManager.OPERATION_SMDX_SUBJECT_REASON_CODE); 606 607 if (isSmdxSubjectReasonCode) { 608 final Pair<String, String> subjectReasonCode = decodeSmdxSubjectAndReasonCode( 609 resultCode); 610 final String subjectCode = subjectReasonCode.first; 611 final String reasonCode = subjectReasonCode.second; 612 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE, 613 subjectCode); 614 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE, reasonCode); 615 } else { 616 final int errorCode = resultCode & errorCodeMask; 617 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE, errorCode); 618 } 619 } 620 downloadSubscription(int cardId, int portIndex, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, Bundle resolvedBundle, PendingIntent callbackIntent)621 void downloadSubscription(int cardId, int portIndex, DownloadableSubscription subscription, 622 boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, 623 Bundle resolvedBundle, PendingIntent callbackIntent) { 624 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 625 626 boolean callerHasAdminPrivileges = 627 callerCanManageDevicePolicyManagedSubscriptions(callingPackage); 628 if (callerHasAdminPrivileges && (switchAfterDownload && !shouldAllowSwitchAfterDownload( 629 callingPackage))) { 630 // Throw error if calling admin does not have privileges to enable 631 // subscription silently after download but switchAfterDownload is passed as true. 632 sendResult(callbackIntent, ERROR, null); 633 return; 634 } 635 if (mContext.getSystemService(UserManager.class).hasUserRestriction( 636 UserManager.DISALLOW_SIM_GLOBALLY) && !callerHasAdminPrivileges) { 637 // Only admin managed subscriptions are allowed, but the caller is not authorised to 638 // download admin managed subscriptions. Abort. 639 sendResult(callbackIntent, ERROR, null); 640 return; 641 } 642 // Don't try to resolve the port index for apps which are not targeting on T for backward 643 // compatibility. instead always use default port 0. 644 boolean shouldResolvePortIndex = isCompatChangeEnabled(callingPackage, 645 EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS); 646 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 647 648 long token = Binder.clearCallingIdentity(); 649 try { 650 boolean isConsentNeededToResolvePortIndex = false; 651 if (switchAfterDownload && portIndex == TelephonyManager.INVALID_PORT_INDEX) { 652 // If switchAfterDownload is true, resolve the portIndex 653 portIndex = shouldResolvePortIndex ? 654 getResolvedPortIndexForSubscriptionSwitch(cardId) 655 : TelephonyManager.DEFAULT_PORT_INDEX; 656 isConsentNeededToResolvePortIndex = (portIndex 657 == TelephonyManager.INVALID_PORT_INDEX); 658 } 659 Log.d(TAG, " downloadSubscription cardId: " + cardId + " switchAfterDownload: " 660 + switchAfterDownload + " portIndex: " + portIndex + " forceDeactivateSim: " 661 + forceDeactivateSim + " callingPackage: " + callingPackage 662 + " isConsentNeededToResolvePortIndex: " + isConsentNeededToResolvePortIndex 663 + " shouldResolvePortIndex:" + shouldResolvePortIndex 664 + " callerHasAdminPrivileges:" + callerHasAdminPrivileges); 665 if (!isConsentNeededToResolvePortIndex && (callerCanWriteEmbeddedSubscriptions 666 || callerHasAdminPrivileges)) { 667 // With WRITE_EMBEDDED_SUBSCRIPTIONS, we can skip profile-specific permission checks 668 // and move straight to the profile download. 669 downloadSubscriptionPrivileged(cardId, portIndex, token, subscription, 670 switchAfterDownload, forceDeactivateSim, callingPackage, resolvedBundle, 671 callbackIntent, callerHasAdminPrivileges, 672 getCurrentEmbeddedSubscriptionIds(cardId)); 673 return; 674 } 675 676 // Without WRITE_EMBEDDED_SUBSCRIPTIONS, we first check whether the caller can manage 677 // subscription on the target SIM (see comments below). If yes, the caller *must* be 678 // allowlisted per the metadata of the profile to be downloaded, so check the metadata; 679 // If no, ask the user's consent before proceed. 680 // On a multi-active SIM device, if the caller can manage the active subscription on the 681 // target SIM, or there is no active subscription on the target SIM and the caller can 682 // manage any active subscription on other SIMs, we perform the download silently. 683 // Otherwise, the user must provide consent. If it's a single-active SIM device, 684 // determine whether the caller can manage the current profile; if so, we can perform 685 // the download silently; if not, the user must provide consent. 686 if (!isConsentNeededToResolvePortIndex 687 && canManageSubscriptionOnTargetSim(cardId, callingPackage, true, 688 portIndex)) { 689 mConnector.getDownloadableSubscriptionMetadata(cardId, portIndex, 690 subscription, switchAfterDownload, forceDeactivateSim, 691 new DownloadSubscriptionGetMetadataCommandCallback(token, subscription, 692 switchAfterDownload, callingPackage, forceDeactivateSim, 693 callbackIntent, false /* withUserConsent */, portIndex)); 694 } else { 695 Log.i(TAG, "Caller can't manage subscription on target SIM or " 696 + " User consent is required for resolving port index. " 697 + "Ask user's consent first"); 698 Intent extrasIntent = new Intent(); 699 addResolutionIntentWithPort(extrasIntent, 700 EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 701 callingPackage, 702 0 /* resolvableErrors */, 703 false /* confirmationCodeRetried */, 704 EuiccOperation.forDownloadNoPrivilegesOrDeactivateSimCheckMetadata(token, 705 subscription, switchAfterDownload, callingPackage), cardId, 706 portIndex, switchAfterDownload /* usePortIndex */); 707 sendResult(callbackIntent, RESOLVABLE_ERROR, extrasIntent); 708 } 709 } finally { 710 Binder.restoreCallingIdentity(token); 711 } 712 } 713 714 class DownloadSubscriptionGetMetadataCommandCallback extends GetMetadataCommandCallback { 715 private final boolean mSwitchAfterDownload; 716 private final boolean mForceDeactivateSim; 717 private final boolean mWithUserConsent; 718 private final int mPortIndex; 719 DownloadSubscriptionGetMetadataCommandCallback(long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, PendingIntent callbackIntent, boolean withUserConsent, int portIndex)720 DownloadSubscriptionGetMetadataCommandCallback(long callingToken, 721 DownloadableSubscription subscription, boolean switchAfterDownload, 722 String callingPackage, boolean forceDeactivateSim, 723 PendingIntent callbackIntent, boolean withUserConsent, int portIndex) { 724 super(callingToken, subscription, callingPackage, callbackIntent); 725 mSwitchAfterDownload = switchAfterDownload; 726 mForceDeactivateSim = forceDeactivateSim; 727 mWithUserConsent = withUserConsent; 728 mPortIndex = portIndex; 729 } 730 731 @Override onGetMetadataComplete(int cardId, GetDownloadableSubscriptionMetadataResult result)732 public void onGetMetadataComplete(int cardId, 733 GetDownloadableSubscriptionMetadataResult result) { 734 DownloadableSubscription subscription = result.getDownloadableSubscription(); 735 if (mWithUserConsent) { 736 // We won't get RESULT_MUST_DEACTIVATE_SIM for the case with user consent. 737 if (result.getResult() != EuiccService.RESULT_OK) { 738 // Just propagate the error as normal. 739 super.onGetMetadataComplete(cardId, result); 740 return; 741 } 742 743 if (checkCarrierPrivilegeInMetadata(subscription, mCallingPackage)) { 744 // Caller can download this profile. Since we already have the user's consent, 745 // proceed to download. 746 downloadSubscriptionPrivileged(cardId, mPortIndex, 747 mCallingToken, subscription, mSwitchAfterDownload, mForceDeactivateSim, 748 mCallingPackage, null /* resolvedBundle */, 749 mCallbackIntent); 750 } else { 751 Log.e(TAG, "Caller does not have carrier privilege in metadata."); 752 sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 753 } 754 } else { // !mWithUserConsent 755 if (result.getResult() == EuiccService.RESULT_MUST_DEACTIVATE_SIM) { 756 // The caller can manage the target SIM. Ask the user's consent to deactivate 757 // the current SIM. 758 Intent extrasIntent = new Intent(); 759 addResolutionIntentWithPort(extrasIntent, 760 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 761 mCallingPackage, 762 0 /* resolvableErrors */, 763 false /* confirmationCodeRetried */, 764 EuiccOperation.forDownloadNoPrivilegesOrDeactivateSimCheckMetadata( 765 mCallingToken, mSubscription, mSwitchAfterDownload, 766 mCallingPackage), 767 cardId, mPortIndex, mSwitchAfterDownload /* usePortIndex */); 768 sendResult(mCallbackIntent, RESOLVABLE_ERROR, extrasIntent); 769 return; 770 } 771 772 if (result.getResult() != EuiccService.RESULT_OK) { 773 // Just propagate the error as normal. 774 super.onGetMetadataComplete(cardId, result); 775 return; 776 } 777 778 if (checkCarrierPrivilegeInMetadata(subscription, mCallingPackage)) { 779 // Caller can download this profile per profile metadata. Also, caller can 780 // manage the subscription on the target SIM, which is already checked. 781 downloadSubscriptionPrivileged(cardId, mPortIndex, 782 mCallingToken, subscription, mSwitchAfterDownload, mForceDeactivateSim, 783 mCallingPackage, null /* resolvedBundle */, 784 mCallbackIntent); 785 } else { 786 Log.e(TAG, "Caller is not permitted to download this profile per metadata"); 787 sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 788 } 789 } 790 } 791 } 792 793 // Already have user consent. Check metadata first before proceed to download. downloadSubscriptionPrivilegedCheckMetadata(int cardId, int portIndex, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent)794 void downloadSubscriptionPrivilegedCheckMetadata(int cardId, int portIndex, 795 final long callingToken, DownloadableSubscription subscription, 796 boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, 797 Bundle resolvedBundle, final PendingIntent callbackIntent) { 798 Log.d(TAG, " downloadSubscriptionPrivilegedCheckMetadata cardId: " + cardId 799 + " switchAfterDownload: " + switchAfterDownload + " portIndex: " + portIndex 800 + " forceDeactivateSim: " + forceDeactivateSim); 801 mConnector.getDownloadableSubscriptionMetadata(cardId, portIndex, 802 subscription, switchAfterDownload, forceDeactivateSim, 803 new DownloadSubscriptionGetMetadataCommandCallback(callingToken, subscription, 804 switchAfterDownload, callingPackage, forceDeactivateSim, callbackIntent, 805 true /* withUserConsent */, portIndex)); 806 } 807 downloadSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent)808 void downloadSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, 809 DownloadableSubscription subscription, boolean switchAfterDownload, 810 boolean forceDeactivateSim, final String callingPackage, 811 Bundle resolvedBundle, final PendingIntent callbackIntent) { 812 downloadSubscriptionPrivileged( 813 cardId, 814 portIndex, 815 callingToken, 816 subscription, 817 switchAfterDownload, 818 forceDeactivateSim, 819 callingPackage, 820 resolvedBundle, 821 callbackIntent, 822 false /* markAsOwnedByAdmin */, 823 new ArraySet<>() /* existingSubscriptions */); 824 } 825 826 // Continue to download subscription without checking anything. downloadSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent, boolean markAsOwnedByAdmin, Set<Integer> existingSubscriptions)827 void downloadSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, 828 DownloadableSubscription subscription, boolean switchAfterDownload, 829 boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, 830 final PendingIntent callbackIntent, boolean markAsOwnedByAdmin, 831 Set<Integer> existingSubscriptions) { 832 mConnector.downloadSubscription( 833 cardId, 834 portIndex, 835 subscription, 836 switchAfterDownload, 837 forceDeactivateSim, 838 addCallingPackageToBundle(resolvedBundle, callingPackage), 839 new EuiccConnector.DownloadCommandCallback() { 840 @Override 841 public void onDownloadComplete(DownloadSubscriptionResult result) { 842 Intent extrasIntent = new Intent(); 843 final int resultCode; 844 switch (result.getResult()) { 845 case EuiccService.RESULT_OK: 846 resultCode = OK; 847 // Now that a profile has been successfully downloaded, mark the 848 // eUICC as provisioned so it appears in settings UI as appropriate. 849 Settings.Global.putInt( 850 mContext.getContentResolver(), 851 Settings.Global.EUICC_PROVISIONED, 852 1); 853 extrasIntent.putExtra( 854 EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION, 855 subscription); 856 if (!switchAfterDownload) { 857 // Since we're not switching, nothing will trigger a 858 // subscription list refresh on its own, so request one here. 859 refreshSubscriptionsAndSendResult( 860 callbackIntent, 861 resultCode, 862 extrasIntent, 863 markAsOwnedByAdmin, 864 callingPackage, 865 cardId, 866 existingSubscriptions); 867 return; 868 } else if (markAsOwnedByAdmin) { 869 refreshSubscriptionsOwnership(true, callingPackage, cardId, 870 existingSubscriptions); 871 } 872 break; 873 case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 874 resultCode = RESOLVABLE_ERROR; 875 addResolutionIntentWithPort(extrasIntent, 876 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 877 callingPackage, 878 0 /* resolvableErrors */, 879 false /* confirmationCodeRetried */, 880 EuiccOperation.forDownloadDeactivateSim( 881 callingToken, subscription, switchAfterDownload, 882 callingPackage), 883 cardId, 884 portIndex, switchAfterDownload /* usePortIndex */); 885 break; 886 case EuiccService.RESULT_RESOLVABLE_ERRORS: 887 // Same value as the deprecated 888 // {@link EuiccService#RESULT_NEED_CONFIRMATION_CODE}. For the 889 // deprecated case, the resolvableErrors is set as 0 in 890 // EuiccService. 891 resultCode = RESOLVABLE_ERROR; 892 boolean retried = false; 893 if (!TextUtils.isEmpty(subscription.getConfirmationCode())) { 894 retried = true; 895 } 896 if (result.getResolvableErrors() != 0) { 897 addResolutionIntentWithPort(extrasIntent, 898 EuiccService.ACTION_RESOLVE_RESOLVABLE_ERRORS, 899 callingPackage, 900 result.getResolvableErrors(), 901 retried, 902 EuiccOperation.forDownloadResolvableErrors( 903 callingToken, subscription, switchAfterDownload, 904 callingPackage, result.getResolvableErrors()), 905 cardId, 906 portIndex, switchAfterDownload /* usePortIndex */); 907 } else { // Deprecated case 908 addResolutionIntentWithPort(extrasIntent, 909 EuiccService.ACTION_RESOLVE_CONFIRMATION_CODE, 910 callingPackage, 911 0 /* resolvableErrors */, 912 retried /* confirmationCodeRetried */, 913 EuiccOperation.forDownloadConfirmationCode( 914 callingToken, subscription, switchAfterDownload, 915 callingPackage), 916 cardId, 917 portIndex, switchAfterDownload /* usePortIndex */); 918 } 919 break; 920 default: 921 resultCode = ERROR; 922 923 addExtrasToResultIntent(extrasIntent, result.getResult()); 924 break; 925 } 926 927 sendResult(callbackIntent, resultCode, extrasIntent); 928 } 929 930 @Override 931 public void onEuiccServiceUnavailable() { 932 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 933 } 934 }); 935 } 936 addCallingPackageToBundle( @ullable Bundle resolvedBundle, String callingPackage)937 private static Bundle addCallingPackageToBundle( 938 @Nullable Bundle resolvedBundle, String callingPackage) { 939 resolvedBundle = resolvedBundle == null ? new Bundle() : resolvedBundle; 940 resolvedBundle.putString(EuiccService.EXTRA_PACKAGE_NAME, callingPackage); 941 return resolvedBundle; 942 } 943 944 /** 945 * Blocking call to {@link EuiccService#onGetEuiccProfileInfoList} of the eUICC with card ID 946 * {@code cardId}. 947 * 948 * <p>Does not perform permission checks as this is not an exposed API and is only used within 949 * the phone process. 950 */ blockingGetEuiccProfileInfoList(int cardId)951 public GetEuiccProfileInfoListResult blockingGetEuiccProfileInfoList(int cardId) { 952 final CountDownLatch latch = new CountDownLatch(1); 953 final AtomicReference<GetEuiccProfileInfoListResult> resultRef = new AtomicReference<>(); 954 mConnector.getEuiccProfileInfoList( 955 cardId, 956 new EuiccConnector.GetEuiccProfileInfoListCommandCallback() { 957 @Override 958 public void onListComplete(GetEuiccProfileInfoListResult result) { 959 resultRef.set(result); 960 latch.countDown(); 961 } 962 963 @Override 964 public void onEuiccServiceUnavailable() { 965 latch.countDown(); 966 } 967 }); 968 try { 969 latch.await(); 970 } catch (InterruptedException e) { 971 Log.e(TAG, "blockingGetEuiccInfoFromEuiccService got InterruptedException e: " + e); 972 Thread.currentThread().interrupt(); 973 } 974 return resultRef.get(); 975 } 976 977 @Override getDefaultDownloadableSubscriptionList(int cardId, String callingPackage, PendingIntent callbackIntent)978 public void getDefaultDownloadableSubscriptionList(int cardId, 979 String callingPackage, PendingIntent callbackIntent) { 980 getDefaultDownloadableSubscriptionList(cardId, 981 false /* forceDeactivateSim */, callingPackage, callbackIntent); 982 } 983 getDefaultDownloadableSubscriptionList(int cardId, boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent)984 void getDefaultDownloadableSubscriptionList(int cardId, 985 boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 986 Log.d(TAG, " getDefaultDownloadableSubscriptionList callingPackage: " + callingPackage); 987 if (!callerCanWriteEmbeddedSubscriptions()) { 988 throw new SecurityException( 989 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get default list"); 990 } 991 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 992 long token = Binder.clearCallingIdentity(); 993 try { 994 mConnector.getDefaultDownloadableSubscriptionList(cardId, 995 forceDeactivateSim, new GetDefaultListCommandCallback( 996 token, callingPackage, callbackIntent)); 997 } finally { 998 Binder.restoreCallingIdentity(token); 999 } 1000 } 1001 1002 class GetDefaultListCommandCallback implements EuiccConnector.GetDefaultListCommandCallback { 1003 final long mCallingToken; 1004 final String mCallingPackage; 1005 final PendingIntent mCallbackIntent; 1006 GetDefaultListCommandCallback(long callingToken, String callingPackage, PendingIntent callbackIntent)1007 GetDefaultListCommandCallback(long callingToken, String callingPackage, 1008 PendingIntent callbackIntent) { 1009 mCallingToken = callingToken; 1010 mCallingPackage = callingPackage; 1011 mCallbackIntent = callbackIntent; 1012 } 1013 1014 @Override onGetDefaultListComplete(int cardId, GetDefaultDownloadableSubscriptionListResult result)1015 public void onGetDefaultListComplete(int cardId, 1016 GetDefaultDownloadableSubscriptionListResult result) { 1017 Intent extrasIntent = new Intent(); 1018 final int resultCode; 1019 switch (result.getResult()) { 1020 case EuiccService.RESULT_OK: 1021 resultCode = OK; 1022 List<DownloadableSubscription> list = result.getDownloadableSubscriptions(); 1023 if (list != null && list.size() > 0) { 1024 extrasIntent.putExtra( 1025 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS, 1026 list.toArray(new DownloadableSubscription[list.size()])); 1027 } 1028 break; 1029 case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 1030 resultCode = RESOLVABLE_ERROR; 1031 addResolutionIntentWithPort(extrasIntent, 1032 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 1033 mCallingPackage, 1034 0 /* resolvableErrors */, 1035 false /* confirmationCodeRetried */, 1036 EuiccOperation.forGetDefaultListDeactivateSim( 1037 mCallingToken, mCallingPackage), 1038 cardId, 1039 TelephonyManager.DEFAULT_PORT_INDEX, false /* usePortIndex */); 1040 break; 1041 default: 1042 resultCode = ERROR; 1043 addExtrasToResultIntent(extrasIntent, result.getResult()); 1044 break; 1045 } 1046 1047 sendResult(mCallbackIntent, resultCode, extrasIntent); 1048 } 1049 1050 @Override onEuiccServiceUnavailable()1051 public void onEuiccServiceUnavailable() { 1052 sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 1053 } 1054 } 1055 1056 /** 1057 * Return the {@link EuiccInfo}. 1058 * 1059 * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 1060 * that IPC should generally be fast, and this info shouldn't be needed in the normal course of 1061 * operation. 1062 */ 1063 @Override getEuiccInfo(int cardId)1064 public EuiccInfo getEuiccInfo(int cardId) { 1065 // No permissions required as EuiccInfo is not sensitive. 1066 long token = Binder.clearCallingIdentity(); 1067 try { 1068 return blockingGetEuiccInfoFromEuiccService(cardId); 1069 } finally { 1070 Binder.restoreCallingIdentity(token); 1071 } 1072 } 1073 1074 @Override deleteSubscription(int cardId, int subscriptionId, String callingPackage, PendingIntent callbackIntent)1075 public void deleteSubscription(int cardId, int subscriptionId, String callingPackage, 1076 PendingIntent callbackIntent) { 1077 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 1078 boolean callerIsAdmin = callerCanManageDevicePolicyManagedSubscriptions(callingPackage); 1079 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 1080 1081 long token = Binder.clearCallingIdentity(); 1082 try { 1083 SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 1084 if (sub == null) { 1085 Log.e(TAG, "Cannot delete nonexistent subscription: " + subscriptionId); 1086 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1087 return; 1088 } 1089 boolean adminOwned = callerIsAdmin && sub.getGroupOwner().equals(callingPackage); 1090 // For both single active SIM device and multi-active SIM device, if the caller is 1091 // system or the caller manage the target subscription, we let it continue. This is 1092 // because deleting subscription won't change status of any other subscriptions. 1093 if (!callerCanWriteEmbeddedSubscriptions 1094 && !canManageSubscription(sub, callingPackage) 1095 && !adminOwned) { 1096 Log.e(TAG, "No permissions: " + subscriptionId + " adminOwned=" + adminOwned); 1097 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1098 return; 1099 } 1100 1101 deleteSubscriptionPrivileged(cardId, sub.getIccId(), callbackIntent); 1102 } finally { 1103 Binder.restoreCallingIdentity(token); 1104 } 1105 } 1106 deleteSubscriptionPrivileged(int cardId, String iccid, final PendingIntent callbackIntent)1107 void deleteSubscriptionPrivileged(int cardId, String iccid, 1108 final PendingIntent callbackIntent) { 1109 mConnector.deleteSubscription( 1110 cardId, 1111 iccid, 1112 new EuiccConnector.DeleteCommandCallback() { 1113 @Override 1114 public void onDeleteComplete(int result) { 1115 Intent extrasIntent = new Intent(); 1116 final int resultCode; 1117 switch (result) { 1118 case EuiccService.RESULT_OK: 1119 resultCode = OK; 1120 refreshSubscriptionsAndSendResult( 1121 callbackIntent, resultCode, extrasIntent); 1122 return; 1123 default: 1124 resultCode = ERROR; 1125 addExtrasToResultIntent(extrasIntent, result); 1126 break; 1127 } 1128 1129 sendResult(callbackIntent, resultCode, extrasIntent); 1130 } 1131 1132 @Override 1133 public void onEuiccServiceUnavailable() { 1134 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1135 } 1136 }); 1137 } 1138 1139 @Override switchToSubscription(int cardId, int subscriptionId, String callingPackage, PendingIntent callbackIntent)1140 public void switchToSubscription(int cardId, int subscriptionId, String callingPackage, 1141 PendingIntent callbackIntent) { 1142 // convert PendingIntent to callback if no callback provided 1143 switchToSubscription(cardId, subscriptionId, 0, false /* forceDeactivateSim */, 1144 callingPackage, callbackIntent, false); 1145 } 1146 1147 @Override switchToSubscriptionWithPort(int cardId, int subscriptionId, int portIndex, String callingPackage, PendingIntent callbackIntent)1148 public void switchToSubscriptionWithPort(int cardId, int subscriptionId, int portIndex, 1149 String callingPackage, PendingIntent callbackIntent) { 1150 switchToSubscription(cardId, subscriptionId, portIndex, false /* forceDeactivateSim */, 1151 callingPackage, callbackIntent, true); 1152 } 1153 switchToSubscription(int cardId, int subscriptionId, int portIndex, boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent, boolean usePortIndex)1154 void switchToSubscription(int cardId, int subscriptionId, int portIndex, 1155 boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent, 1156 boolean usePortIndex) { 1157 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 1158 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 1159 // Resolve the portIndex internally if apps targeting T and beyond are calling 1160 // switchToSubscription API without portIndex. 1161 boolean shouldResolvePortIndex = isCompatChangeEnabled(callingPackage, 1162 EuiccManager.SHOULD_RESOLVE_PORT_INDEX_FOR_APPS); 1163 Log.d(TAG, " subId: " + subscriptionId + " portIndex: " + portIndex 1164 + " forceDeactivateSim: " + forceDeactivateSim + " usePortIndex: " + usePortIndex 1165 + " callingPackage: " + callingPackage + " shouldResolvePortIndex: " 1166 + shouldResolvePortIndex); 1167 long token = Binder.clearCallingIdentity(); 1168 try { 1169 if (callerCanWriteEmbeddedSubscriptions) { 1170 // Assume that if a privileged caller is calling us, we don't need to prompt the 1171 // user about changing carriers, because the caller would only be acting in response 1172 // to user action. 1173 forceDeactivateSim = true; 1174 } 1175 1176 final String iccid; 1177 boolean passConsent = false; 1178 boolean isConsentNeededToResolvePortIndex = false; 1179 if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 1180 if (!usePortIndex) { 1181 // Resolve the portIndex internally if apps are calling switchToSubscription 1182 // API without portIndex and subscription id is invalid. 1183 portIndex = getResolvedPortIndexForDisableSubscription(cardId, callingPackage, 1184 callerCanWriteEmbeddedSubscriptions); 1185 if (portIndex == TelephonyManager.INVALID_PORT_INDEX) { 1186 Log.e(TAG, "Disable is not permitted: no active subscription or cannot" 1187 + " manage subscription"); 1188 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1189 return; 1190 } 1191 usePortIndex = true; 1192 } 1193 if (callerCanWriteEmbeddedSubscriptions 1194 || canManageActiveSubscriptionOnTargetSim(cardId, callingPackage, 1195 usePortIndex, portIndex)) { 1196 passConsent = true; 1197 } else { 1198 Log.e(TAG, "Not permitted to switch to empty subscription"); 1199 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1200 return; 1201 } 1202 iccid = null; 1203 } else { 1204 SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 1205 if (sub == null) { 1206 Log.e(TAG, "Cannot switch to nonexistent sub: " + subscriptionId); 1207 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1208 return; 1209 } 1210 if (callerCanWriteEmbeddedSubscriptions) { 1211 passConsent = true; 1212 } else { 1213 if (!canManageSubscription(sub, callingPackage)) { 1214 Log.e(TAG, "Not permitted to switch to sub: " + subscriptionId); 1215 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1216 return; 1217 } 1218 1219 if (canManageSubscriptionOnTargetSim(cardId, callingPackage, usePortIndex, 1220 portIndex)) { 1221 passConsent = true; 1222 } 1223 } 1224 iccid = sub.getIccId(); 1225 if (usePortIndex) { 1226 boolean hasValidPortIndex = isTargetPortIndexValid(cardId, portIndex); 1227 if (!hasValidPortIndex) { 1228 // Return permanent error. 1229 Log.e(TAG, "Not permitted to switch to invalid portIndex"); 1230 Intent extrasIntent = new Intent(); 1231 extrasIntent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE, 1232 EuiccManager.ERROR_INVALID_PORT); 1233 sendResult(callbackIntent, ERROR, extrasIntent /* extrasIntent */); 1234 return; 1235 } 1236 } else { 1237 // Resolve the portIndex internally if apps targeting T and beyond are calling 1238 // switchToSubscription API without portIndex. 1239 portIndex = shouldResolvePortIndex ? 1240 getResolvedPortIndexForSubscriptionSwitch(cardId) 1241 : TelephonyManager.DEFAULT_PORT_INDEX; 1242 isConsentNeededToResolvePortIndex = (portIndex 1243 == TelephonyManager.INVALID_PORT_INDEX); 1244 usePortIndex = true; 1245 Log.d(TAG, " Resolved portIndex: " + portIndex); 1246 } 1247 } 1248 if (!passConsent || isConsentNeededToResolvePortIndex) { 1249 // Switch needs consent. 1250 Intent extrasIntent = new Intent(); 1251 addResolutionIntent(extrasIntent, 1252 EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 1253 callingPackage, 1254 0 /* resolvableErrors */, 1255 false /* confirmationCodeRetried */, 1256 EuiccOperation.forSwitchNoPrivileges( 1257 token, subscriptionId, callingPackage), 1258 cardId, portIndex, usePortIndex, subscriptionId); 1259 sendResult(callbackIntent, RESOLVABLE_ERROR, extrasIntent); 1260 return; 1261 } 1262 1263 switchToSubscriptionPrivileged(cardId, portIndex, token, subscriptionId, iccid, 1264 forceDeactivateSim, callingPackage, callbackIntent, usePortIndex); 1265 } finally { 1266 Binder.restoreCallingIdentity(token); 1267 } 1268 } 1269 1270 /** 1271 * Returns the resolved portIndex or {@link TelephonyManager#INVALID_PORT_INDEX} if calling 1272 * cannot manage any active subscription. 1273 */ 1274 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getResolvedPortIndexForDisableSubscription(int cardId, String callingPackage, boolean callerCanWriteEmbeddedSubscriptions)1275 public int getResolvedPortIndexForDisableSubscription(int cardId, String callingPackage, 1276 boolean callerCanWriteEmbeddedSubscriptions) { 1277 List<SubscriptionInfo> subInfoList = mSubscriptionManager 1278 .getActiveSubscriptionInfoList(/* userVisibleOnly */false); 1279 if (subInfoList == null || subInfoList.size() == 0) { 1280 // No active subscription on any SIM. 1281 return TelephonyManager.INVALID_PORT_INDEX; 1282 } 1283 // Return the portIndex of the first active subscription managed by the calling app. 1284 for (SubscriptionInfo subInfo : subInfoList) { 1285 // If cardId == TelephonyManager.UNSUPPORTED_CARD_ID, we assume it does not support 1286 // multiple eSIMs. There are older multi-active SIM devices which do not implement HAL 1287 // 1.2 and if they have multiple eSIMs, we let it pass if the app can manage an active 1288 // subscription on any eSIM. That's the best we can do here. 1289 if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId) 1290 && subInfo.isEmbedded() 1291 && (callerCanWriteEmbeddedSubscriptions 1292 || canManageSubscription(subInfo, callingPackage))) { 1293 return subInfo.getPortIndex(); 1294 } 1295 } 1296 return TelephonyManager.INVALID_PORT_INDEX; 1297 } 1298 1299 /** 1300 * Returns the resolved portIndex or {@link TelephonyManager#INVALID_PORT_INDEX} if no port 1301 * is available without user consent. 1302 */ 1303 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) getResolvedPortIndexForSubscriptionSwitch(int cardId)1304 public int getResolvedPortIndexForSubscriptionSwitch(int cardId) { 1305 int slotIndex = getSlotIndexFromCardId(cardId); 1306 // Euicc Slot 1307 UiccSlot slot = UiccController.getInstance().getUiccSlot(slotIndex); 1308 if (slot == null) { 1309 // Check is to make sure crash is avoided in case of slot is null. 1310 Log.d(TAG, "Switch to inactive slot, return default port index. slotIndex: " 1311 + slotIndex); 1312 return TelephonyManager.DEFAULT_PORT_INDEX; 1313 } 1314 if (!slot.isMultipleEnabledProfileSupported()) { 1315 Log.d(TAG, "Multiple enabled profiles is not supported, return default port index"); 1316 return TelephonyManager.DEFAULT_PORT_INDEX; 1317 } 1318 boolean isPsimActive = getRemovableNonEuiccSlot() != null 1319 && getRemovableNonEuiccSlot().isActive(); 1320 if (mTelephonyManager.getActiveModemCount() == 1) { 1321 // SS Mode 1322 if (isPsimActive) { 1323 // In case of SS Mode and pSim is active, return default port index for 1324 // two reasons. 1325 // 1. If psim and esim share the same carrier privilege, then users wouldn't need 1326 // to consent, the switch should be seamless. 1327 // 2. If psim is active and empty or psim and esim doesn't share the same carrier 1328 // privilege, then permission check dialog will be shown anyway. 1329 return TelephonyManager.DEFAULT_PORT_INDEX; 1330 } 1331 // If esim port is active, return the active portIndex irrespective of whether port is 1332 // empty or has active subscription. 1333 for (int portIndex : slot.getPortList()) { 1334 if (slot.isPortActive(portIndex)) { 1335 return portIndex; 1336 } 1337 } 1338 } else { 1339 // DSDS Mode 1340 for (int portIndex : slot.getPortList()) { 1341 if (slot.isPortActive(portIndex)) { 1342 SubscriptionInfo subscriptionInfo = 1343 mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex( 1344 slot.getPhoneIdFromPortIndex(portIndex)); 1345 if (subscriptionInfo == null 1346 || subscriptionInfo.isOpportunistic() 1347 || (mFeatureFlags.esimBootstrapProvisioningFlag() 1348 && subscriptionInfo.getProfileClass() 1349 == SubscriptionManager.PROFILE_CLASS_PROVISIONING)) { 1350 // If the port is active and has empty/opportunistic/provisioning 1351 // profiles then return the portIndex. 1352 return portIndex; 1353 } 1354 } 1355 } 1356 // Check whether the pSim is active and empty 1357 boolean isPsimEmpty = isPsimActive && !isRemovalNonEuiccSlotHasActiveSubscription(); 1358 if (isPsimEmpty) { 1359 // This logic will execute only if below two conditions are true. 1360 // 1. pSim is active and empty 1361 // 2. eSim has active subscription 1362 // Return the next available inactive eSim portIndex. 1363 return getNextAvailableInActivePortIndex(slot); 1364 } 1365 } 1366 return TelephonyManager.INVALID_PORT_INDEX; 1367 } 1368 1369 /** 1370 * Returns true if the target port index is valid. 1371 * 1. Port index is valid if it is non-negative and less than the total port count. 1372 * 2. In SS Mode, port index is invalid if the embedded slot already has an active port 1373 * with different port index than the target port index. 1374 * 3. In DSDS mode, port index is invalid if the pSim slot is active and the embedded slot 1375 * already has an active empty port with different port index than the target port index. 1376 */ isTargetPortIndexValid(int cardId, int targetPortIndex)1377 private boolean isTargetPortIndexValid(int cardId, int targetPortIndex) { 1378 if (targetPortIndex < 0) { 1379 Log.e(TAG, "Invalid portIndex: " + targetPortIndex); 1380 return false; 1381 } 1382 int slotIndex = getSlotIndexFromCardId(cardId); 1383 UiccSlot slot = UiccController.getInstance().getUiccSlot(slotIndex); 1384 if (slot == null || slot.getPortList().length == 0 1385 || targetPortIndex >= slot.getPortList().length) { 1386 Log.e(TAG, "Invalid portIndex"); 1387 return false; 1388 } 1389 1390 if (mTelephonyManager.getActiveModemCount() == 1) { 1391 // SS Mode 1392 for (int portIndex : slot.getPortList()) { 1393 if (slot.isPortActive(portIndex) && portIndex != targetPortIndex) { 1394 // if there is an active esim port, should not try to enable the 1395 // profile on other inactive port. 1396 Log.e(TAG, "In SS Mode, slot already has active port on portIndex " + portIndex 1397 + " , reject the switch request to portIndex " + targetPortIndex); 1398 return false; 1399 } 1400 } 1401 } else if (mTelephonyManager.getActiveModemCount() > 1) { 1402 // DSDS Mode 1403 // If physical slot has active subscription and eSim has active port (without active 1404 // subscription), should not try to enable the profile on other inactive port. 1405 boolean isPsimActive = isRemovalNonEuiccSlotHasActiveSubscription(); 1406 if (isPsimActive) { 1407 for (int portIndex : slot.getPortList()) { 1408 if (slot.isPortActive(portIndex) 1409 && mSubscriptionManager 1410 .getActiveSubscriptionInfoForSimSlotIndex( 1411 slot.getPhoneIdFromPortIndex(portIndex)) == null 1412 && portIndex != targetPortIndex) { 1413 Log.e(TAG, "In DSDS Mode, pSim has active subscription, eSim has empty" 1414 + " active port on portIndex " + portIndex 1415 + " , reject the switch request to portIndex " + targetPortIndex); 1416 return false; 1417 } 1418 } 1419 } 1420 } 1421 return true; 1422 } 1423 getNextAvailableInActivePortIndex(UiccSlot slot)1424 private int getNextAvailableInActivePortIndex(UiccSlot slot) { 1425 if (slot != null) { 1426 for (int portIndex : slot.getPortList()) { 1427 if (!slot.isPortActive(portIndex)) { 1428 return portIndex; 1429 } 1430 } 1431 } 1432 return TelephonyManager.INVALID_PORT_INDEX; 1433 } 1434 1435 /** 1436 * Gets the slot index from the card ID. 1437 */ getSlotIndexFromCardId(int cardId)1438 private int getSlotIndexFromCardId(int cardId) { 1439 UiccSlotInfo[] slotInfos = mTelephonyManager.getUiccSlotsInfo(); 1440 if (slotInfos == null || slotInfos.length == 0) { 1441 Log.e(TAG, "UiccSlotInfo is null or empty"); 1442 return SubscriptionManager.INVALID_SIM_SLOT_INDEX; 1443 } 1444 String cardIdString = UiccController.getInstance().convertToCardString(cardId); 1445 for (int slotIndex = 0; slotIndex < slotInfos.length; slotIndex++) { 1446 if (slotInfos[slotIndex] == null) { 1447 AnomalyReporter.reportAnomaly( 1448 UUID.fromString("e9517acf-e1a1-455f-9231-1b5515a0d0eb"), 1449 "EuiccController: Found UiccSlotInfo Null object."); 1450 } 1451 String retrievedCardId = slotInfos[slotIndex] != null 1452 ? slotInfos[slotIndex].getCardId() : null; 1453 if (IccUtils.compareIgnoreTrailingFs(cardIdString, retrievedCardId)) { 1454 return slotIndex; 1455 } 1456 } 1457 Log.i(TAG, "No UiccSlotInfo found for cardId: " + cardId); 1458 return SubscriptionManager.INVALID_SIM_SLOT_INDEX; 1459 } 1460 isRemovalNonEuiccSlotHasActiveSubscription()1461 private boolean isRemovalNonEuiccSlotHasActiveSubscription() { 1462 UiccSlot uiccSlot = getRemovableNonEuiccSlot(); 1463 if (uiccSlot != null) { 1464 for (int portIndex : uiccSlot.getPortList()) { 1465 if (uiccSlot.isPortActive(portIndex) 1466 && mSubscriptionManager.getActiveSubscriptionInfoForSimSlotIndex( 1467 uiccSlot.getPhoneIdFromPortIndex(portIndex)) != null) { 1468 return true; 1469 } 1470 } 1471 } 1472 return false; 1473 } 1474 getRemovableNonEuiccSlot()1475 private UiccSlot getRemovableNonEuiccSlot() { 1476 UiccSlot[] uiccSlots = UiccController.getInstance().getUiccSlots(); 1477 if (uiccSlots != null) { 1478 for (int i = 0; i < uiccSlots.length; i++) { 1479 if (uiccSlots[i] != null && uiccSlots[i].isRemovable() 1480 && !uiccSlots[i].isEuicc()) { 1481 return uiccSlots[i]; 1482 } 1483 } 1484 } 1485 return null; 1486 } 1487 switchToSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, int subscriptionId, boolean forceDeactivateSim, final String callingPackage, final PendingIntent callbackIntent, boolean usePortIndex)1488 void switchToSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, 1489 int subscriptionId, boolean forceDeactivateSim, final String callingPackage, 1490 final PendingIntent callbackIntent, boolean usePortIndex) { 1491 String iccid = null; 1492 SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 1493 if (sub != null) { 1494 iccid = sub.getIccId(); 1495 } 1496 switchToSubscriptionPrivileged(cardId, portIndex, callingToken, subscriptionId, iccid, 1497 forceDeactivateSim, callingPackage, callbackIntent, usePortIndex); 1498 } 1499 switchToSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, int subscriptionId, @Nullable String iccid, boolean forceDeactivateSim, final String callingPackage, final PendingIntent callbackIntent, boolean usePortIndex)1500 void switchToSubscriptionPrivileged(int cardId, int portIndex, final long callingToken, 1501 int subscriptionId, @Nullable String iccid, boolean forceDeactivateSim, 1502 final String callingPackage, final PendingIntent callbackIntent, boolean usePortIndex) { 1503 mConnector.switchToSubscription( 1504 cardId, 1505 portIndex, 1506 iccid, 1507 forceDeactivateSim, 1508 new EuiccConnector.SwitchCommandCallback() { 1509 @Override 1510 public void onSwitchComplete(int result) { 1511 Intent extrasIntent = new Intent(); 1512 final int resultCode; 1513 switch (result) { 1514 case EuiccService.RESULT_OK: 1515 resultCode = OK; 1516 break; 1517 case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 1518 resultCode = RESOLVABLE_ERROR; 1519 addResolutionIntent(extrasIntent, 1520 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 1521 callingPackage, 1522 0 /* resolvableErrors */, 1523 false /* confirmationCodeRetried */, 1524 EuiccOperation.forSwitchDeactivateSim( 1525 callingToken, subscriptionId, callingPackage), 1526 cardId, portIndex, usePortIndex, subscriptionId); 1527 break; 1528 default: 1529 resultCode = ERROR; 1530 addExtrasToResultIntent(extrasIntent, result); 1531 break; 1532 } 1533 sendResult(callbackIntent, resultCode, extrasIntent); 1534 } 1535 1536 @Override 1537 public void onEuiccServiceUnavailable() { 1538 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1539 } 1540 }, 1541 usePortIndex); 1542 } 1543 1544 @Override updateSubscriptionNickname(int cardId, int subscriptionId, String nickname, String callingPackage, PendingIntent callbackIntent)1545 public void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname, 1546 String callingPackage, PendingIntent callbackIntent) { 1547 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 1548 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 1549 1550 long token = Binder.clearCallingIdentity(); 1551 try { 1552 SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 1553 if (sub == null) { 1554 Log.e(TAG, "Cannot update nickname to nonexistent sub: " + subscriptionId); 1555 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1556 return; 1557 } 1558 1559 // For both single active SIM device and multi-active SIM device, if the caller is 1560 // system or the caller can manage the target subscription, we let it continue. This is 1561 // because updating subscription nickname won't affect any other subscriptions. 1562 if (!callerCanWriteEmbeddedSubscriptions 1563 && !canManageSubscription(sub, callingPackage)) { 1564 Log.e(TAG, "No permissions: " + subscriptionId); 1565 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1566 return; 1567 } 1568 1569 mConnector.updateSubscriptionNickname(cardId, 1570 sub.getIccId(), nickname, 1571 new EuiccConnector.UpdateNicknameCommandCallback() { 1572 @Override 1573 public void onUpdateNicknameComplete(int result) { 1574 Intent extrasIntent = new Intent(); 1575 final int resultCode; 1576 switch (result) { 1577 case EuiccService.RESULT_OK: 1578 resultCode = OK; 1579 refreshSubscriptionsAndSendResult( 1580 callbackIntent, resultCode, extrasIntent); 1581 return; 1582 default: 1583 resultCode = ERROR; 1584 addExtrasToResultIntent(extrasIntent, result); 1585 break; 1586 } 1587 1588 sendResult(callbackIntent, resultCode, extrasIntent); 1589 } 1590 1591 @Override 1592 public void onEuiccServiceUnavailable() { 1593 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1594 } 1595 }); 1596 } finally { 1597 Binder.restoreCallingIdentity(token); 1598 } 1599 } 1600 1601 @Override eraseSubscriptions(int cardId, PendingIntent callbackIntent)1602 public void eraseSubscriptions(int cardId, PendingIntent callbackIntent) { 1603 if (!callerCanWriteEmbeddedSubscriptions()) { 1604 throw new SecurityException( 1605 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to erase subscriptions"); 1606 } 1607 long token = Binder.clearCallingIdentity(); 1608 try { 1609 mConnector.eraseSubscriptions( 1610 cardId, new EuiccConnector.EraseCommandCallback() { 1611 @Override 1612 public void onEraseComplete(int result) { 1613 Intent extrasIntent = new Intent(); 1614 final int resultCode; 1615 switch (result) { 1616 case EuiccService.RESULT_OK: 1617 resultCode = OK; 1618 refreshSubscriptionsAndSendResult( 1619 callbackIntent, resultCode, extrasIntent); 1620 return; 1621 default: 1622 resultCode = ERROR; 1623 addExtrasToResultIntent(extrasIntent, result); 1624 break; 1625 } 1626 1627 sendResult(callbackIntent, resultCode, extrasIntent); 1628 } 1629 1630 @Override 1631 public void onEuiccServiceUnavailable() { 1632 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1633 } 1634 }); 1635 } finally { 1636 Binder.restoreCallingIdentity(token); 1637 } 1638 } 1639 1640 @Override eraseSubscriptionsWithOptions( int cardId, @ResetOption int options, PendingIntent callbackIntent)1641 public void eraseSubscriptionsWithOptions( 1642 int cardId, @ResetOption int options, PendingIntent callbackIntent) { 1643 if (!callerCanWriteEmbeddedSubscriptions()) { 1644 throw new SecurityException( 1645 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to erase subscriptions"); 1646 } 1647 long token = Binder.clearCallingIdentity(); 1648 try { 1649 mConnector.eraseSubscriptionsWithOptions( 1650 cardId, options, new EuiccConnector.EraseCommandCallback() { 1651 @Override 1652 public void onEraseComplete(int result) { 1653 Intent extrasIntent = new Intent(); 1654 final int resultCode; 1655 switch (result) { 1656 case EuiccService.RESULT_OK: 1657 resultCode = OK; 1658 refreshSubscriptionsAndSendResult( 1659 callbackIntent, resultCode, extrasIntent); 1660 return; 1661 default: 1662 resultCode = ERROR; 1663 addExtrasToResultIntent(extrasIntent, result); 1664 break; 1665 } 1666 1667 sendResult(callbackIntent, resultCode, extrasIntent); 1668 } 1669 1670 @Override 1671 public void onEuiccServiceUnavailable() { 1672 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1673 } 1674 }); 1675 } finally { 1676 Binder.restoreCallingIdentity(token); 1677 } 1678 } 1679 1680 @Override retainSubscriptionsForFactoryReset(int cardId, PendingIntent callbackIntent)1681 public void retainSubscriptionsForFactoryReset(int cardId, PendingIntent callbackIntent) { 1682 mContext.enforceCallingPermission(Manifest.permission.MASTER_CLEAR, 1683 "Must have MASTER_CLEAR to retain subscriptions for factory reset"); 1684 long token = Binder.clearCallingIdentity(); 1685 try { 1686 mConnector.retainSubscriptions(cardId, 1687 new EuiccConnector.RetainSubscriptionsCommandCallback() { 1688 @Override 1689 public void onRetainSubscriptionsComplete(int result) { 1690 Intent extrasIntent = new Intent(); 1691 final int resultCode; 1692 switch (result) { 1693 case EuiccService.RESULT_OK: 1694 resultCode = OK; 1695 break; 1696 default: 1697 resultCode = ERROR; 1698 addExtrasToResultIntent(extrasIntent, result); 1699 break; 1700 } 1701 1702 sendResult(callbackIntent, resultCode, extrasIntent); 1703 } 1704 1705 @Override 1706 public void onEuiccServiceUnavailable() { 1707 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1708 } 1709 }); 1710 } finally { 1711 Binder.restoreCallingIdentity(token); 1712 } 1713 } 1714 1715 /** Refresh the embedded subscription list and dispatch the given result upon completion. */ 1716 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) refreshSubscriptionsAndSendResult( PendingIntent callbackIntent, int resultCode, Intent extrasIntent)1717 public void refreshSubscriptionsAndSendResult( 1718 PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 1719 refreshSubscriptionsAndSendResult( 1720 callbackIntent, 1721 resultCode, 1722 extrasIntent, 1723 /* isCallerAdmin= */ false, 1724 /* callingPackage= */ "", 1725 /* cardId */ -1, 1726 /* subscriptionsBefore= */ new ArraySet<>()); 1727 } 1728 1729 /** Refresh the embedded subscription list and dispatch the given result upon completion. */ 1730 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) refreshSubscriptionsAndSendResult( PendingIntent callbackIntent, int resultCode, Intent extrasIntent, boolean isCallerAdmin, String callingPackage, int cardId, Set<Integer> subscriptionsBefore)1731 public void refreshSubscriptionsAndSendResult( 1732 PendingIntent callbackIntent, 1733 int resultCode, 1734 Intent extrasIntent, 1735 boolean isCallerAdmin, 1736 String callingPackage, 1737 int cardId, 1738 Set<Integer> subscriptionsBefore) { 1739 SubscriptionManagerService.getInstance().updateEmbeddedSubscriptions( 1740 List.of(mTelephonyManager.getCardIdForDefaultEuicc()), 1741 () -> { 1742 refreshSubscriptionsOwnership(isCallerAdmin, callingPackage, cardId, 1743 subscriptionsBefore); 1744 sendResult(callbackIntent, resultCode, extrasIntent); 1745 }); 1746 1747 } 1748 refreshSubscriptionsOwnership(boolean isCallerAdmin, String callingPackage, int cardId, Set<Integer> subscriptionsBefore)1749 private void refreshSubscriptionsOwnership(boolean isCallerAdmin, String callingPackage, 1750 int cardId, Set<Integer> subscriptionsBefore) { 1751 if (isCallerAdmin) { 1752 // Mark the newly downloaded subscriptions as being owned by an admin so 1753 // that actions for that subscription can be restricted, 1754 // and the admin is limited to effecting only these subscriptions. 1755 Set<Integer> subscriptionsAfter = getCurrentEmbeddedSubscriptionIds(cardId); 1756 subscriptionsAfter.removeAll(subscriptionsBefore); 1757 for (int subId : subscriptionsAfter) { 1758 SubscriptionManagerService.getInstance().setGroupOwner(subId, callingPackage); 1759 } 1760 } 1761 } 1762 1763 /** Dispatch the given callback intent with the given result code and data. */ 1764 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) sendResult(PendingIntent callbackIntent, int resultCode, Intent extrasIntent)1765 public void sendResult(PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 1766 try { 1767 callbackIntent.send(mContext, resultCode, extrasIntent); 1768 } catch (PendingIntent.CanceledException e) { 1769 // Caller canceled the callback; do nothing. 1770 } 1771 } 1772 1773 /** Add a resolution intent to the given extras intent with invalid subscriptionId */ addResolutionIntentWithPort(Intent extrasIntent, String resolutionAction, String callingPackage, int resolvableErrors, boolean confirmationCodeRetried, EuiccOperation op, int cardId, int portIndex, boolean usePortIndex)1774 public void addResolutionIntentWithPort(Intent extrasIntent, String resolutionAction, 1775 String callingPackage, int resolvableErrors, boolean confirmationCodeRetried, 1776 EuiccOperation op, int cardId, int portIndex, boolean usePortIndex) { 1777 // use invalid subscriptionId in case of download/metadata flow 1778 addResolutionIntent(extrasIntent, resolutionAction, callingPackage, resolvableErrors, 1779 confirmationCodeRetried, op, cardId, portIndex, 1780 usePortIndex /* usePortIndex */, SubscriptionManager.INVALID_SUBSCRIPTION_ID); 1781 } 1782 1783 /** Add a resolution intent to the given extras intent. */ 1784 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) addResolutionIntent(Intent extrasIntent, String resolutionAction, String callingPackage, int resolvableErrors, boolean confirmationCodeRetried, EuiccOperation op, int cardId, int portIndex, boolean usePortIndex, int subscriptionId)1785 public void addResolutionIntent(Intent extrasIntent, String resolutionAction, 1786 String callingPackage, int resolvableErrors, boolean confirmationCodeRetried, 1787 EuiccOperation op, int cardId, int portIndex, boolean usePortIndex, 1788 int subscriptionId) { 1789 Intent intent = new Intent(EuiccManager.ACTION_RESOLVE_ERROR); 1790 intent.setPackage(RESOLUTION_ACTIVITY_PACKAGE_NAME); 1791 intent.setComponent(new ComponentName( 1792 RESOLUTION_ACTIVITY_PACKAGE_NAME, RESOLUTION_ACTIVITY_CLASS_NAME)); 1793 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION, 1794 resolutionAction); 1795 intent.putExtra(EuiccService.EXTRA_RESOLUTION_CALLING_PACKAGE, callingPackage); 1796 intent.putExtra(EuiccService.EXTRA_RESOLVABLE_ERRORS, resolvableErrors); 1797 intent.putExtra(EuiccService.EXTRA_RESOLUTION_CARD_ID, cardId); 1798 intent.putExtra(EuiccService.EXTRA_RESOLUTION_SUBSCRIPTION_ID, subscriptionId); 1799 intent.putExtra(EuiccService.EXTRA_RESOLUTION_PORT_INDEX, portIndex); 1800 intent.putExtra(EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, usePortIndex); 1801 intent.putExtra(EuiccService.EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED, 1802 confirmationCodeRetried); 1803 intent.putExtra(EXTRA_OPERATION, op); 1804 PendingIntent resolutionIntent = PendingIntent.getActivity( 1805 mContext, 1806 0 /* requestCode */, 1807 intent, 1808 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_MUTABLE); 1809 extrasIntent.putExtra( 1810 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT, resolutionIntent); 1811 } 1812 1813 @Override dump(FileDescriptor fd, final PrintWriter pw, String[] args)1814 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1815 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP"); 1816 final long token = Binder.clearCallingIdentity(); 1817 pw.println("===== BEGIN EUICC CLINIC ====="); 1818 try { 1819 pw.println("===== EUICC CONNECTOR ====="); 1820 mConnector.dump(fd, pw, args); 1821 final CountDownLatch countDownLatch = new CountDownLatch(1); 1822 mConnector.dumpEuiccService(new EuiccConnector.DumpEuiccServiceCommandCallback() { 1823 @Override 1824 public void onDumpEuiccServiceComplete(String logs) { 1825 pw.println("===== EUICC SERVICE ====="); 1826 pw.println(logs); 1827 countDownLatch.countDown(); 1828 } 1829 1830 @Override 1831 public void onEuiccServiceUnavailable() { 1832 pw.println("===== EUICC SERVICE UNAVAILABLE ====="); 1833 countDownLatch.countDown(); 1834 } 1835 }); 1836 1837 // Wait up to 5 seconds 1838 if (!countDownLatch.await(EUICC_DUMP_TIME_OUT_SECONDS, TimeUnit.SECONDS)) { 1839 pw.println("===== EUICC SERVICE TIMEOUT ====="); 1840 } 1841 } catch (InterruptedException e) { 1842 pw.println("===== EUICC SERVICE INTERRUPTED ====="); 1843 } finally { 1844 pw.println("===== END EUICC CLINIC ====="); 1845 Binder.restoreCallingIdentity(token); 1846 } 1847 } 1848 1849 /** 1850 * Send broadcast {@link EuiccManager#ACTION_OTA_STATUS_CHANGED} for OTA status 1851 * changed. 1852 */ 1853 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) sendOtaStatusChangedBroadcast()1854 public void sendOtaStatusChangedBroadcast() { 1855 Intent intent = new Intent(EuiccManager.ACTION_OTA_STATUS_CHANGED); 1856 ComponentInfo bestComponent = mConnector.findBestComponent(mContext.getPackageManager()); 1857 if (bestComponent != null) { 1858 intent.setPackage(bestComponent.packageName); 1859 } 1860 if (mFeatureFlags.hsumBroadcast()) { 1861 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 1862 permission.WRITE_EMBEDDED_SUBSCRIPTIONS); 1863 } else { 1864 mContext.sendBroadcast(intent, permission.WRITE_EMBEDDED_SUBSCRIPTIONS); 1865 } 1866 } 1867 1868 @Nullable getSubscriptionForSubscriptionId(int subscriptionId)1869 private SubscriptionInfo getSubscriptionForSubscriptionId(int subscriptionId) { 1870 List<SubscriptionInfo> subs = mSubscriptionManager.getAvailableSubscriptionInfoList(); 1871 int subCount = (subs != null) ? subs.size() : 0; 1872 for (int i = 0; i < subCount; i++) { 1873 SubscriptionInfo sub = subs.get(i); 1874 if (subscriptionId == sub.getSubscriptionId()) { 1875 return sub; 1876 } 1877 } 1878 return null; 1879 } 1880 getCurrentEmbeddedSubscriptionIds(int cardId)1881 private Set<Integer> getCurrentEmbeddedSubscriptionIds(int cardId) { 1882 List<SubscriptionInfo> subscriptionInfos = 1883 mSubscriptionManager.getAvailableSubscriptionInfoList(); 1884 int subCount = (subscriptionInfos != null) ? subscriptionInfos.size() : 0; 1885 Set<Integer> currentEmbeddedSubscriptionIds = new ArraySet<>(); 1886 for (int i = 0; i < subCount; i++) { 1887 SubscriptionInfo subscriptionInfo = subscriptionInfos.get(i); 1888 if (subscriptionInfo.isEmbedded() && subscriptionInfo.getCardId() == cardId) { 1889 currentEmbeddedSubscriptionIds.add(subscriptionInfo.getSubscriptionId()); 1890 } 1891 } 1892 return currentEmbeddedSubscriptionIds; 1893 } 1894 1895 @Nullable blockingGetEidFromEuiccService(int cardId)1896 private String blockingGetEidFromEuiccService(int cardId) { 1897 CountDownLatch latch = new CountDownLatch(1); 1898 AtomicReference<String> eidRef = new AtomicReference<>(); 1899 mConnector.getEid(cardId, new EuiccConnector.GetEidCommandCallback() { 1900 @Override 1901 public void onGetEidComplete(String eid) { 1902 eidRef.set(eid); 1903 latch.countDown(); 1904 } 1905 1906 @Override 1907 public void onEuiccServiceUnavailable() { 1908 latch.countDown(); 1909 } 1910 }); 1911 return awaitResult(latch, eidRef); 1912 } 1913 blockingGetAvailableMemoryInBytesFromEuiccService(int cardId)1914 private long blockingGetAvailableMemoryInBytesFromEuiccService(int cardId) 1915 throws UnsupportedOperationException { 1916 CountDownLatch latch = new CountDownLatch(1); 1917 AtomicReference<Long> memoryRef = 1918 new AtomicReference<>(EuiccManager.EUICC_MEMORY_FIELD_UNAVAILABLE); 1919 AtomicReference<Exception> exceptionRef = new AtomicReference(); 1920 mConnector.getAvailableMemoryInBytes( 1921 cardId, 1922 new EuiccConnector.GetAvailableMemoryInBytesCommandCallback() { 1923 @Override 1924 public void onGetAvailableMemoryInBytesComplete(long availableMemoryInBytes) { 1925 memoryRef.set(availableMemoryInBytes); 1926 latch.countDown(); 1927 } 1928 1929 @Override 1930 public void onUnsupportedOperationExceptionComplete(String message) { 1931 exceptionRef.set(new UnsupportedOperationException(message)); 1932 latch.countDown(); 1933 } 1934 1935 @Override 1936 public void onEuiccServiceUnavailable() { 1937 latch.countDown(); 1938 } 1939 }); 1940 try { 1941 return awaitResultOrException(latch, memoryRef, exceptionRef); 1942 } catch (UnsupportedOperationException uoe) { 1943 throw uoe; 1944 } catch (Exception e) { 1945 // Other type of exceptions are not expected here but re-throw in case that happens. 1946 throw new UnsupportedOperationException(e); 1947 } 1948 } 1949 blockingGetOtaStatusFromEuiccService(int cardId)1950 private @OtaStatus int blockingGetOtaStatusFromEuiccService(int cardId) { 1951 CountDownLatch latch = new CountDownLatch(1); 1952 AtomicReference<Integer> statusRef = 1953 new AtomicReference<>(EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE); 1954 mConnector.getOtaStatus(cardId, new EuiccConnector.GetOtaStatusCommandCallback() { 1955 @Override 1956 public void onGetOtaStatusComplete(@OtaStatus int status) { 1957 statusRef.set(status); 1958 latch.countDown(); 1959 } 1960 1961 @Override 1962 public void onEuiccServiceUnavailable() { 1963 latch.countDown(); 1964 } 1965 }); 1966 return awaitResult(latch, statusRef); 1967 } 1968 1969 @Nullable blockingGetEuiccInfoFromEuiccService(int cardId)1970 private EuiccInfo blockingGetEuiccInfoFromEuiccService(int cardId) { 1971 CountDownLatch latch = new CountDownLatch(1); 1972 AtomicReference<EuiccInfo> euiccInfoRef = new AtomicReference<>(); 1973 mConnector.getEuiccInfo(cardId, new EuiccConnector.GetEuiccInfoCommandCallback() { 1974 @Override 1975 public void onGetEuiccInfoComplete(EuiccInfo euiccInfo) { 1976 euiccInfoRef.set(euiccInfo); 1977 latch.countDown(); 1978 } 1979 1980 @Override 1981 public void onEuiccServiceUnavailable() { 1982 latch.countDown(); 1983 } 1984 }); 1985 return awaitResult(latch, euiccInfoRef); 1986 } 1987 awaitResult(CountDownLatch latch, AtomicReference<T> resultRef)1988 private static <T> T awaitResult(CountDownLatch latch, AtomicReference<T> resultRef) { 1989 try { 1990 latch.await(); 1991 } catch (InterruptedException e) { 1992 Thread.currentThread().interrupt(); 1993 } 1994 return resultRef.get(); 1995 } 1996 awaitResultOrException( CountDownLatch latch, AtomicReference<T> resultRef, AtomicReference<Exception> resultException)1997 private static <T> T awaitResultOrException( 1998 CountDownLatch latch, 1999 AtomicReference<T> resultRef, 2000 AtomicReference<Exception> resultException) 2001 throws Exception { 2002 try { 2003 latch.await(); 2004 } catch (InterruptedException e) { 2005 Thread.currentThread().interrupt(); 2006 } 2007 2008 if (resultException.get() != null) { 2009 throw resultException.get(); 2010 } 2011 2012 return resultRef.get(); 2013 } 2014 2015 // Returns whether the caller has carrier privilege on the given subscription. checkCarrierPrivilegeInMetadata(DownloadableSubscription subscription, String callingPackage)2016 private boolean checkCarrierPrivilegeInMetadata(DownloadableSubscription subscription, 2017 String callingPackage) { 2018 UiccAccessRule[] rules = null; 2019 List<UiccAccessRule> rulesList = subscription.getAccessRules(); 2020 if (rulesList != null) { 2021 rules = rulesList.toArray(new UiccAccessRule[rulesList.size()]); 2022 } 2023 if (rules == null) { 2024 Log.e(TAG, "No access rules but caller is unprivileged"); 2025 return false; 2026 } 2027 2028 final PackageInfo info; 2029 try { 2030 info = mPackageManager.getPackageInfo(callingPackage, 2031 PackageManager.GET_SIGNING_CERTIFICATES); 2032 } catch (PackageManager.NameNotFoundException e) { 2033 Log.e(TAG, "Calling package valid but gone"); 2034 return false; 2035 } 2036 2037 for (int i = 0; i < rules.length; i++) { 2038 if (rules[i].getCarrierPrivilegeStatus(info) 2039 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 2040 Log.i(TAG, "Calling package has carrier privilege to this profile"); 2041 return true; 2042 } 2043 } 2044 Log.e(TAG, "Calling package doesn't have carrier privilege to this profile"); 2045 return false; 2046 } 2047 supportMultiActiveSlots()2048 private boolean supportMultiActiveSlots() { 2049 return mTelephonyManager.getSupportedModemCount() > 1; 2050 } 2051 2052 // Checks whether the caller can manage the active embedded subscription on the SIM with the 2053 // given cardId. 2054 // From Android T, if usePortIndex is true then should check if the calling app has carrier 2055 // privilege over the subscription on the target port index. canManageActiveSubscriptionOnTargetSim(int cardId, String callingPackage, boolean usePortIndex, int targetPortIndex)2056 private boolean canManageActiveSubscriptionOnTargetSim(int cardId, String callingPackage, 2057 boolean usePortIndex, int targetPortIndex) { 2058 List<SubscriptionInfo> subInfoList = mSubscriptionManager 2059 .getActiveSubscriptionInfoList(/* userVisibleOnly */false); 2060 if (subInfoList == null || subInfoList.size() == 0) { 2061 // No active subscription on any SIM. 2062 return false; 2063 } 2064 for (SubscriptionInfo subInfo : subInfoList) { 2065 // If cardId == TelephonyManager.UNSUPPORTED_CARD_ID, we assume it does not support 2066 // multiple eSIMs. There are older multi-active SIM devices which do not implement HAL 2067 // 1.2 and if they have multiple eSIMs, we let it pass if the app can manage an active 2068 // subscription on any eSIM. That's the best we can do here. 2069 if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId) 2070 && subInfo.isEmbedded() 2071 && (!usePortIndex || subInfo.getPortIndex() == targetPortIndex) 2072 && canManageSubscription(subInfo, callingPackage)) { 2073 return true; 2074 } 2075 } 2076 return false; 2077 } 2078 2079 // For a multi-active subscriptions phone, checks whether the caller can manage subscription on 2080 // the target SIM with the given cardId. The caller can only manage subscription on the target 2081 // SIM if it can manage the active subscription on the target SIM or there is no active 2082 // subscription on the target SIM, and the caller can manage any active subscription on any 2083 // other SIM. The target SIM should be an eUICC. 2084 // For a single-active subscription phone, checks whether the caller can manage any active 2085 // embedded subscription. 2086 // From Android T, if usePortIndex is true then verify whether the calling app has carrier 2087 // privilege over the active embedded subscription on the target port index. 2088 // If usePortIndex is false then check whether the calling app can manage any active 2089 // subscription on any of the active ports, if there are no active embedded subscriptions then 2090 // verify whether the calling app can manage any active subscription on any of the other SIM. canManageSubscriptionOnTargetSim(int cardId, String callingPackage, boolean usePortIndex, int targetPortIndex)2091 private boolean canManageSubscriptionOnTargetSim(int cardId, String callingPackage, 2092 boolean usePortIndex, int targetPortIndex) { 2093 List<SubscriptionInfo> subInfoList = mSubscriptionManager 2094 .getActiveSubscriptionInfoList(false /* userVisibleonly */); 2095 // No active subscription on any SIM. 2096 if (subInfoList == null || subInfoList.size() == 0) { 2097 return false; 2098 } 2099 // If it's a multi-active SIM device, we assume it's above HAL 1.2 which supports cardId. 2100 // There are older multi-active SIM devices but don't implement HAL 1.2. In this case, 2101 // platform can't even detect UiccCardInfo#isEuicc as true for eSIM, which won't let the 2102 // below check pass. That's the best we can do here. 2103 if (supportMultiActiveSlots()) { 2104 // The target card should be an eUICC. 2105 List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo(); 2106 if (cardInfos == null || cardInfos.isEmpty()) { 2107 return false; 2108 } 2109 boolean isEuicc = false; 2110 for (UiccCardInfo info : cardInfos) { 2111 if (info != null && info.getCardId() == cardId && info.isEuicc()) { 2112 isEuicc = true; 2113 break; 2114 } 2115 } 2116 if (!isEuicc) { 2117 Log.i(TAG, "The target SIM is not an eUICC."); 2118 return false; 2119 } 2120 2121 // If the caller can't manage the active embedded subscription on the target SIM port, 2122 // return false. If the caller can manage the active embedded subscription on the 2123 // target SIM port, return true directly. 2124 boolean hasActiveEmbeddedSubscription = subInfoList.stream().anyMatch( 2125 subInfo -> subInfo.isEmbedded() && subInfo.getCardId() == cardId 2126 && (!usePortIndex || subInfo.getPortIndex() == targetPortIndex)); 2127 if (hasActiveEmbeddedSubscription) { 2128 // hasActiveEmbeddedSubscription is true if there is an active embedded subscription 2129 // on the target port(in case of usePortIndex is true) or if there is an active 2130 // embedded subscription on any of the active ports. 2131 2132 // 1. If usePortIndex is true, check whether the caller can manage subscription on 2133 // the target port. 2134 // 2. If usePortIndex is false, check whether the caller can manage subscription on 2135 // any of the active ports. 2136 for (SubscriptionInfo subInfo : subInfoList) { 2137 // subInfo.isEmbedded() can only be true for the target SIM. 2138 if (subInfo.isEmbedded() 2139 && subInfo.getCardId() == cardId 2140 && (!usePortIndex || subInfo.getPortIndex() == targetPortIndex) 2141 && canManageSubscription(subInfo, callingPackage)) { 2142 return true; 2143 } 2144 } 2145 Log.i(TAG, "canManageSubscriptionOnTargetSim cannot manage embedded subscription"); 2146 return false; 2147 } 2148 // There is no active subscription on the target SIM, checks whether the caller can 2149 // manage any active subscription on any other SIM. 2150 final long token = Binder.clearCallingIdentity(); 2151 try { 2152 return mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) 2153 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 2154 } finally { 2155 Binder.restoreCallingIdentity(token); 2156 } 2157 } else { 2158 for (SubscriptionInfo subInfo : subInfoList) { 2159 if (subInfo.isEmbedded() 2160 && canManageSubscription(subInfo, callingPackage)) { 2161 return true; 2162 } 2163 } 2164 return false; 2165 } 2166 } 2167 callerCanReadPhoneStatePrivileged()2168 private boolean callerCanReadPhoneStatePrivileged() { 2169 return mContext.checkCallingOrSelfPermission( 2170 Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 2171 == PackageManager.PERMISSION_GRANTED; 2172 } 2173 callerCanReadPhoneState()2174 private boolean callerCanReadPhoneState() { 2175 return mContext.checkCallingOrSelfPermission(Manifest.permission.READ_PHONE_STATE) 2176 == PackageManager.PERMISSION_GRANTED; 2177 } 2178 callerCanWriteEmbeddedSubscriptions()2179 private boolean callerCanWriteEmbeddedSubscriptions() { 2180 return mContext.checkCallingOrSelfPermission( 2181 Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) 2182 == PackageManager.PERMISSION_GRANTED; 2183 } 2184 retrieveDevicePolicyManagerFromUserContext(UserHandle userHandle)2185 private DevicePolicyManager retrieveDevicePolicyManagerFromUserContext(UserHandle userHandle) { 2186 Context userContext; 2187 long ident = Binder.clearCallingIdentity(); 2188 try { 2189 userContext = mContext.createPackageContextAsUser( 2190 mContext.getPackageName(), /* flags= */ 0, userHandle); 2191 } catch (PackageManager.NameNotFoundException e) { 2192 Log.e(TAG, "Unknown package name"); 2193 return null; 2194 } finally { 2195 Binder.restoreCallingIdentity(ident); 2196 } 2197 return userContext.getSystemService(DevicePolicyManager.class); 2198 } 2199 callerCanManageDevicePolicyManagedSubscriptions(String callingPackage)2200 private boolean callerCanManageDevicePolicyManagedSubscriptions(String callingPackage) { 2201 DevicePolicyManager devicePolicyManager = getDevicePolicyManager(); 2202 boolean isAdmin = 2203 devicePolicyManager != null && (devicePolicyManager.isProfileOwnerApp( 2204 callingPackage) 2205 || devicePolicyManager.isDeviceOwnerApp(callingPackage)); 2206 return isAdmin || mContext.checkCallingOrSelfPermission( 2207 Manifest.permission.MANAGE_DEVICE_POLICY_MANAGED_SUBSCRIPTIONS) 2208 == PackageManager.PERMISSION_GRANTED; 2209 } 2210 shouldAllowSwitchAfterDownload(String callingPackage)2211 private boolean shouldAllowSwitchAfterDownload(String callingPackage) { 2212 DevicePolicyManager devicePolicyManager = getDevicePolicyManager(); 2213 return devicePolicyManager != null && (devicePolicyManager.isDeviceOwnerApp(callingPackage) 2214 || (devicePolicyManager.isProfileOwnerApp(callingPackage) 2215 && devicePolicyManager.isOrganizationOwnedDeviceWithManagedProfile())); 2216 } 2217 getDevicePolicyManager()2218 private DevicePolicyManager getDevicePolicyManager() { 2219 // create device policy manager with the correct context associated with the caller. 2220 DevicePolicyManager devicePolicyManager = 2221 retrieveDevicePolicyManagerFromUserContext(Binder.getCallingUserHandle()); 2222 if (devicePolicyManager == null) { 2223 Log.w(TAG, "Unable to get device policy manager"); 2224 } 2225 return devicePolicyManager; 2226 } 2227 2228 @Override isSimPortAvailable(int cardId, int portIndex, String callingPackage)2229 public boolean isSimPortAvailable(int cardId, int portIndex, String callingPackage) { 2230 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 2231 2232 enforceTelephonyFeatureWithException(callingPackage, "isSimPortAvailable"); 2233 2234 // If calling app is targeted for Android U and beyond, check for other conditions 2235 // to decide the port availability. 2236 boolean shouldCheckConditionsForInactivePort = isCompatChangeEnabled(callingPackage, 2237 EuiccManager.INACTIVE_PORT_AVAILABILITY_CHECK); 2238 // In the event that this check is coming from ONS, WRITE_EMBEDDED_SUBSCRIPTIONS will be 2239 // required for the case where a port is inactive but could trivially be enabled without 2240 // requiring user consent. 2241 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 2242 final long token = Binder.clearCallingIdentity(); 2243 try { 2244 List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo(); 2245 for (UiccCardInfo info : cardInfos) { 2246 if (info == null || info.getCardId() != cardId) { 2247 continue; 2248 } 2249 // Return false in case of non esim or passed port index is greater than 2250 // the available ports. 2251 if (!info.isEuicc() || (portIndex == TelephonyManager.INVALID_PORT_INDEX) 2252 || portIndex >= info.getPorts().size()) { 2253 return false; 2254 } 2255 for (UiccPortInfo portInfo : info.getPorts()) { 2256 if (portInfo == null || portInfo.getPortIndex() != portIndex) { 2257 continue; 2258 } 2259 if (!portInfo.isActive()) { 2260 // port is inactive, check whether the caller can activate a new profile 2261 // seamlessly. This is possible in below condition: 2262 // 1. Device in DSDS Mode(P+E). 2263 // 2. pSIM slot is active but no active subscription. 2264 // 3. Caller has carrier privileges on any phone or has 2265 // WRITE_EMBEDDED_SUBSCRIPTIONS. The latter covers calls from ONS 2266 // which does not have carrier privileges. 2267 if (!shouldCheckConditionsForInactivePort) { 2268 return false; 2269 } 2270 boolean hasActiveRemovableNonEuiccSlot = getRemovableNonEuiccSlot() != null 2271 && getRemovableNonEuiccSlot().isActive(); 2272 boolean hasCarrierPrivileges = mTelephonyManager 2273 .checkCarrierPrivilegesForPackageAnyPhone(callingPackage) 2274 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 2275 return mTelephonyManager.isMultiSimEnabled() 2276 && hasActiveRemovableNonEuiccSlot 2277 && !isRemovalNonEuiccSlotHasActiveSubscription() 2278 && (hasCarrierPrivileges || callerCanWriteEmbeddedSubscriptions); 2279 } 2280 // A port is available if it has no profiles enabled on it or calling app has 2281 // Carrier privilege over the profile installed on the selected port. 2282 if (TextUtils.isEmpty(portInfo.getIccId())) { 2283 return true; 2284 } 2285 UiccPort uiccPort = 2286 UiccController.getInstance().getUiccPortForSlot( 2287 info.getPhysicalSlotIndex(), portIndex); 2288 // Some eSim Vendors return boot profile iccid if no profile is installed. 2289 // So in this case if profile is empty, port is available. 2290 if (uiccPort != null 2291 && uiccPort.getUiccProfile() != null 2292 && uiccPort.getUiccProfile().isEmptyProfile()) { 2293 return true; 2294 } 2295 Phone phone = PhoneFactory.getPhone(portInfo.getLogicalSlotIndex()); 2296 if (phone == null) { 2297 Log.e(TAG, "Invalid logical slot: " + portInfo.getLogicalSlotIndex()); 2298 return false; 2299 } 2300 CarrierPrivilegesTracker cpt = phone.getCarrierPrivilegesTracker(); 2301 if (cpt == null) { 2302 Log.e(TAG, "No CarrierPrivilegesTracker"); 2303 return false; 2304 } 2305 return (cpt.getCarrierPrivilegeStatusForPackage(callingPackage) 2306 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS); 2307 } 2308 } 2309 } finally { 2310 Binder.restoreCallingIdentity(token); 2311 } 2312 return false; 2313 } 2314 2315 @Override hasCarrierPrivilegesForPackageOnAnyPhone(String callingPackage)2316 public boolean hasCarrierPrivilegesForPackageOnAnyPhone(String callingPackage) { 2317 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 2318 final long token = Binder.clearCallingIdentity(); 2319 try { 2320 // checkCarrierPrivilegesForPackageAnyPhone API requires READ_PHONE_STATE permission, 2321 // hence cannot call directly from EuiccManager switchToSubscription 2322 return mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) 2323 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 2324 } finally { 2325 Binder.restoreCallingIdentity(token); 2326 } 2327 } 2328 2329 @Override isCompatChangeEnabled(String callingPackage, long changeId)2330 public boolean isCompatChangeEnabled(String callingPackage, long changeId) { 2331 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 2332 // Platform compat framework kills the callingPackage app to ensure that the change 2333 // takes affect immediately. So the corresponding compat checking is moved to controller. 2334 boolean changeEnabled = CompatChanges.isChangeEnabled(changeId, callingPackage, 2335 Binder.getCallingUserHandle()); 2336 Log.i(TAG, "isCompatChangeEnabled changeId: " + changeId 2337 + " changeEnabled: " + changeEnabled); 2338 return changeEnabled; 2339 } 2340 2341 2342 @Override setPsimConversionSupportedCarriers(int[] carrierIds)2343 public void setPsimConversionSupportedCarriers(int[] carrierIds) { 2344 if (!callerCanWriteEmbeddedSubscriptions()) { 2345 throw new SecurityException( 2346 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to " 2347 + "set pSIM conversion supported carriers"); 2348 } 2349 mPsimConversionSupportedCarrierIds = Arrays.stream(carrierIds).boxed() 2350 .collect(Collectors.toList()); 2351 } 2352 2353 2354 2355 @Override isPsimConversionSupported(int carrierId)2356 public boolean isPsimConversionSupported(int carrierId) { 2357 if (!callerCanWriteEmbeddedSubscriptions()) { 2358 throw new SecurityException( 2359 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS " 2360 + "to check if the carrier is supported pSIM conversion"); 2361 } 2362 if (mPsimConversionSupportedCarrierIds == null 2363 || mPsimConversionSupportedCarrierIds.isEmpty()) { 2364 return false; 2365 } 2366 return mPsimConversionSupportedCarrierIds.contains(carrierId); 2367 } 2368 2369 /** 2370 * Make sure the device has required telephony feature 2371 * 2372 * @throws UnsupportedOperationException if the device does not have required telephony feature 2373 */ enforceTelephonyFeatureWithException(@ullable String callingPackage, @NonNull String methodName)2374 private void enforceTelephonyFeatureWithException(@Nullable String callingPackage, 2375 @NonNull String methodName) { 2376 if (callingPackage == null || mPackageManager == null) { 2377 return; 2378 } 2379 2380 if (!CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage, 2381 Binder.getCallingUserHandle()) 2382 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) { 2383 // Skip to check associated telephony feature, 2384 // if compatibility change is not enabled for the current process or 2385 // the SDK version of vendor partition is less than Android V. 2386 return; 2387 } 2388 2389 if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_EUICC)) { 2390 throw new UnsupportedOperationException( 2391 methodName + " is unsupported without " + FEATURE_TELEPHONY_EUICC); 2392 } 2393 } 2394 canManageSubscription(SubscriptionInfo subInfo, String packageName)2395 private boolean canManageSubscription(SubscriptionInfo subInfo, String packageName) { 2396 if (Flags.hsumPackageManager() && UserManager.isHeadlessSystemUserMode()) { 2397 return mSubscriptionManager.canManageSubscriptionAsUser(subInfo, packageName, 2398 UserHandle.of(ActivityManager.getCurrentUser())); 2399 } else { 2400 return mSubscriptionManager.canManageSubscription(subInfo, packageName); 2401 } 2402 } 2403 } 2404