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