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 android.Manifest; 19 import android.Manifest.permission; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.app.AppOpsManager; 23 import android.app.PendingIntent; 24 import android.content.ComponentName; 25 import android.content.Context; 26 import android.content.Intent; 27 import android.content.pm.ComponentInfo; 28 import android.content.pm.PackageInfo; 29 import android.content.pm.PackageManager; 30 import android.os.Binder; 31 import android.os.Bundle; 32 import android.provider.Settings; 33 import android.service.euicc.DownloadSubscriptionResult; 34 import android.service.euicc.EuiccService; 35 import android.service.euicc.GetDefaultDownloadableSubscriptionListResult; 36 import android.service.euicc.GetDownloadableSubscriptionMetadataResult; 37 import android.service.euicc.GetEuiccProfileInfoListResult; 38 import android.telephony.SubscriptionInfo; 39 import android.telephony.SubscriptionManager; 40 import android.telephony.TelephonyFrameworkInitializer; 41 import android.telephony.TelephonyManager; 42 import android.telephony.UiccAccessRule; 43 import android.telephony.UiccCardInfo; 44 import android.telephony.euicc.DownloadableSubscription; 45 import android.telephony.euicc.EuiccCardManager.ResetOption; 46 import android.telephony.euicc.EuiccInfo; 47 import android.telephony.euicc.EuiccManager; 48 import android.telephony.euicc.EuiccManager.OtaStatus; 49 import android.text.TextUtils; 50 import android.util.Log; 51 import android.util.Pair; 52 53 import com.android.internal.annotations.VisibleForTesting; 54 import com.android.internal.telephony.SubscriptionController; 55 import com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback; 56 57 import java.io.FileDescriptor; 58 import java.io.PrintWriter; 59 import java.util.Collections; 60 import java.util.List; 61 import java.util.Stack; 62 import java.util.concurrent.CountDownLatch; 63 import java.util.concurrent.TimeUnit; 64 import java.util.concurrent.atomic.AtomicReference; 65 66 /** Backing implementation of {@link android.telephony.euicc.EuiccManager}. */ 67 public class EuiccController extends IEuiccController.Stub { 68 private static final String TAG = "EuiccController"; 69 70 /** Extra set on resolution intents containing the {@link EuiccOperation}. */ 71 @VisibleForTesting 72 static final String EXTRA_OPERATION = "operation"; 73 74 /** 75 * Time out for {@link #dump(FileDescriptor, PrintWriter, String[])} 76 */ 77 private static final int EUICC_DUMP_TIME_OUT_SECONDS = 5; 78 79 // Aliases so line lengths stay short. 80 private static final int OK = EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK; 81 private static final int RESOLVABLE_ERROR = 82 EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR; 83 private static final int ERROR = 84 EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR; 85 private static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = 86 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION; 87 88 /** Restrictions limiting access to the PendingIntent */ 89 private static final String RESOLUTION_ACTIVITY_PACKAGE_NAME = "com.android.phone"; 90 private static final String RESOLUTION_ACTIVITY_CLASS_NAME = 91 "com.android.phone.euicc.EuiccResolutionUiDispatcherActivity"; 92 93 private static EuiccController sInstance; 94 95 private final Context mContext; 96 private final EuiccConnector mConnector; 97 private final SubscriptionManager mSubscriptionManager; 98 private final TelephonyManager mTelephonyManager; 99 private final AppOpsManager mAppOpsManager; 100 private final PackageManager mPackageManager; 101 102 // These values should be set or updated upon 1) system boot, 2) EuiccService/LPA is bound to 103 // the phone process, 3) values are updated remotely by server flags. 104 private List<String> mSupportedCountries; 105 private List<String> mUnsupportedCountries; 106 107 /** Initialize the instance. Should only be called once. */ init(Context context)108 public static EuiccController init(Context context) { 109 synchronized (EuiccController.class) { 110 if (sInstance == null) { 111 sInstance = new EuiccController(context); 112 } else { 113 Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance); 114 } 115 } 116 return sInstance; 117 } 118 119 /** Get an instance. Assumes one has already been initialized with {@link #init}. */ get()120 public static EuiccController get() { 121 if (sInstance == null) { 122 synchronized (EuiccController.class) { 123 if (sInstance == null) { 124 throw new IllegalStateException("get() called before init()"); 125 } 126 } 127 } 128 return sInstance; 129 } 130 EuiccController(Context context)131 private EuiccController(Context context) { 132 this(context, new EuiccConnector(context)); 133 TelephonyFrameworkInitializer 134 .getTelephonyServiceManager().getEuiccControllerService().register(this); 135 } 136 137 @VisibleForTesting EuiccController(Context context, EuiccConnector connector)138 public EuiccController(Context context, EuiccConnector connector) { 139 mContext = context; 140 mConnector = connector; 141 mSubscriptionManager = (SubscriptionManager) 142 context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 143 mTelephonyManager = (TelephonyManager) 144 context.getSystemService(Context.TELEPHONY_SERVICE); 145 mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 146 mPackageManager = context.getPackageManager(); 147 } 148 149 /** 150 * Continue an operation which failed with a user-resolvable error. 151 * 152 * <p>The implementation here makes a key assumption that the resolutionIntent has not been 153 * tampered with. This is guaranteed because: 154 * <UL> 155 * <LI>The intent is wrapped in a PendingIntent created by the phone process which is created 156 * with {@link #EXTRA_OPERATION} already present. This means that the operation cannot be 157 * overridden on the PendingIntent - a caller can only add new extras. 158 * <LI>The resolution activity is restricted by a privileged permission; unprivileged apps 159 * cannot start it directly. So the PendingIntent is the only way to start it. 160 * </UL> 161 */ 162 @Override continueOperation(int cardId, Intent resolutionIntent, Bundle resolutionExtras)163 public void continueOperation(int cardId, Intent resolutionIntent, Bundle resolutionExtras) { 164 if (!callerCanWriteEmbeddedSubscriptions()) { 165 throw new SecurityException( 166 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to continue operation"); 167 } 168 long token = Binder.clearCallingIdentity(); 169 try { 170 EuiccOperation op = resolutionIntent.getParcelableExtra(EXTRA_OPERATION); 171 if (op == null) { 172 throw new IllegalArgumentException("Invalid resolution intent"); 173 } 174 175 PendingIntent callbackIntent = 176 resolutionIntent.getParcelableExtra( 177 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT); 178 op.continueOperation(cardId, resolutionExtras, callbackIntent); 179 } finally { 180 Binder.restoreCallingIdentity(token); 181 } 182 } 183 184 /** 185 * Return the EID. 186 * 187 * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 188 * that IPC should generally be fast, and the EID shouldn't be needed in the normal course of 189 * operation. 190 */ 191 @Override getEid(int cardId, String callingPackage)192 public String getEid(int cardId, String callingPackage) { 193 boolean callerCanReadPhoneStatePrivileged = callerCanReadPhoneStatePrivileged(); 194 long token = Binder.clearCallingIdentity(); 195 try { 196 if (!callerCanReadPhoneStatePrivileged 197 && !canManageSubscriptionOnTargetSim(cardId, callingPackage)) { 198 throw new SecurityException( 199 "Must have carrier privileges on subscription to read EID for cardId=" 200 + cardId); 201 } 202 203 return blockingGetEidFromEuiccService(cardId); 204 } finally { 205 Binder.restoreCallingIdentity(token); 206 } 207 } 208 209 /** 210 * Return the current status of OTA update. 211 * 212 * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 213 * that IPC should generally be fast. 214 */ 215 @Override getOtaStatus(int cardId)216 public @OtaStatus int getOtaStatus(int cardId) { 217 if (!callerCanWriteEmbeddedSubscriptions()) { 218 throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get OTA status"); 219 } 220 long token = Binder.clearCallingIdentity(); 221 try { 222 return blockingGetOtaStatusFromEuiccService(cardId); 223 } finally { 224 Binder.restoreCallingIdentity(token); 225 } 226 } 227 228 /** 229 * Start eUICC OTA update on the default eUICC if current eUICC OS is not the latest one. When 230 * OTA is started or finished, the broadcast {@link EuiccManager#ACTION_OTA_STATUS_CHANGED} will 231 * be sent. 232 * 233 * This function will only be called from phone process and isn't exposed to the other apps. 234 * 235 * (see {@link #startOtaUpdatingIfNecessary(int cardId)}). 236 */ startOtaUpdatingIfNecessary()237 public void startOtaUpdatingIfNecessary() { 238 // TODO(b/120796772) Eventually, we should use startOtaUpdatingIfNecessary(cardId) 239 startOtaUpdatingIfNecessary(mTelephonyManager.getCardIdForDefaultEuicc()); 240 } 241 242 /** 243 * Start eUICC OTA update on the given eUICC if current eUICC OS is not the latest one. 244 */ startOtaUpdatingIfNecessary(int cardId)245 public void startOtaUpdatingIfNecessary(int cardId) { 246 mConnector.startOtaIfNecessary(cardId, 247 new OtaStatusChangedCallback() { 248 @Override 249 public void onOtaStatusChanged(int status) { 250 sendOtaStatusChangedBroadcast(); 251 } 252 253 @Override 254 public void onEuiccServiceUnavailable() {} 255 }); 256 } 257 258 @Override getDownloadableSubscriptionMetadata(int cardId, DownloadableSubscription subscription, String callingPackage, PendingIntent callbackIntent)259 public void getDownloadableSubscriptionMetadata(int cardId, 260 DownloadableSubscription subscription, String callingPackage, 261 PendingIntent callbackIntent) { 262 getDownloadableSubscriptionMetadata(cardId, 263 subscription, false /* forceDeactivateSim */, callingPackage, callbackIntent); 264 } 265 266 /** 267 * Sets the supported or unsupported countries for eUICC. 268 * 269 * <p>If {@code isSupported} is true, the supported country list will be replaced by 270 * {@code countriesList}. Otherwise, unsupported country list will be replaced by 271 * {@code countriesList}. For how we determine whether a country is supported by checking 272 * supported and unsupported country list please check {@link EuiccManager#isSupportedCountry}. 273 * 274 * @param isSupported should be true if caller wants to set supported country list. If 275 * isSupported is false, un-supported country list will be updated. 276 * @param countriesList is a list of strings contains country ISO codes in uppercase. 277 */ 278 @Override setSupportedCountries(boolean isSupported, @NonNull List<String> countriesList)279 public void setSupportedCountries(boolean isSupported, @NonNull List<String> countriesList) { 280 if (!callerCanWriteEmbeddedSubscriptions()) { 281 throw new SecurityException( 282 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to set supported countries"); 283 } 284 if (isSupported) { 285 mSupportedCountries = countriesList; 286 } else { 287 mUnsupportedCountries = countriesList; 288 } 289 } 290 291 /** 292 * Gets the supported or unsupported countries for eUICC. 293 * 294 * <p>If {@code isSupported} is true, the supported country list will be returned. Otherwise, 295 * unsupported country list will be returned. 296 * 297 * @param isSupported should be true if caller wants to get supported country list. If 298 * isSupported is false, unsupported country list will be returned. 299 * @return a list of strings contains country ISO codes in uppercase. 300 */ 301 @Override 302 @NonNull getSupportedCountries(boolean isSupported)303 public List<String> getSupportedCountries(boolean isSupported) { 304 if (!callerCanWriteEmbeddedSubscriptions()) { 305 throw new SecurityException( 306 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get supported countries"); 307 } 308 if (isSupported && mSupportedCountries != null) { 309 return mSupportedCountries; 310 } else if (!isSupported && mUnsupportedCountries != null) { 311 return mUnsupportedCountries; 312 } 313 return Collections.emptyList(); 314 } 315 316 /** 317 * Returns whether the given country supports eUICC. 318 * 319 * <p>Supported country list has a higher prority than unsupported country list. If the 320 * supported country list is not empty, {@code countryIso} will be considered as supported when 321 * it exists in the supported country list. Otherwise {@code countryIso} is not supported. If 322 * the supported country list is empty, {@code countryIso} will be considered as supported if it 323 * does not exist in the unsupported country list. Otherwise {@code countryIso} is not 324 * supported. If both supported and unsupported country lists are empty, then all countries are 325 * consider be supported. For how to set supported and unsupported country list, please check 326 * {@link #setSupportedCountries}. 327 * 328 * @param countryIso should be the ISO-3166 country code is provided in uppercase 2 character 329 * format. 330 * @return whether the given country supports eUICC or not. 331 */ 332 @Override isSupportedCountry(@onNull String countryIso)333 public boolean isSupportedCountry(@NonNull String countryIso) { 334 if (!callerCanWriteEmbeddedSubscriptions()) { 335 throw new SecurityException( 336 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to check if the country is supported"); 337 } 338 if (mSupportedCountries == null || mSupportedCountries.isEmpty()) { 339 Log.i(TAG, "Using blacklist unsupportedCountries=" + mUnsupportedCountries); 340 return !isEsimUnsupportedCountry(countryIso); 341 } else { 342 Log.i(TAG, "Using whitelist supportedCountries=" + mSupportedCountries); 343 return isEsimSupportedCountry(countryIso); 344 } 345 } 346 isEsimSupportedCountry(String countryIso)347 private boolean isEsimSupportedCountry(String countryIso) { 348 if (mSupportedCountries == null || TextUtils.isEmpty(countryIso)) { 349 return true; 350 } 351 return mSupportedCountries.contains(countryIso); 352 } 353 isEsimUnsupportedCountry(String countryIso)354 private boolean isEsimUnsupportedCountry(String countryIso) { 355 if (mUnsupportedCountries == null || TextUtils.isEmpty(countryIso)) { 356 return false; 357 } 358 return mUnsupportedCountries.contains(countryIso); 359 } 360 getDownloadableSubscriptionMetadata(int cardId, DownloadableSubscription subscription, boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent)361 void getDownloadableSubscriptionMetadata(int cardId, DownloadableSubscription subscription, 362 boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 363 if (!callerCanWriteEmbeddedSubscriptions()) { 364 throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get metadata"); 365 } 366 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 367 long token = Binder.clearCallingIdentity(); 368 try { 369 mConnector.getDownloadableSubscriptionMetadata(cardId, 370 subscription, forceDeactivateSim, 371 new GetMetadataCommandCallback( 372 token, subscription, callingPackage, callbackIntent)); 373 } finally { 374 Binder.restoreCallingIdentity(token); 375 } 376 } 377 378 class GetMetadataCommandCallback implements EuiccConnector.GetMetadataCommandCallback { 379 protected final long mCallingToken; 380 protected final DownloadableSubscription mSubscription; 381 protected final String mCallingPackage; 382 protected final PendingIntent mCallbackIntent; 383 GetMetadataCommandCallback( long callingToken, DownloadableSubscription subscription, String callingPackage, PendingIntent callbackIntent)384 GetMetadataCommandCallback( 385 long callingToken, 386 DownloadableSubscription subscription, 387 String callingPackage, 388 PendingIntent callbackIntent) { 389 mCallingToken = callingToken; 390 mSubscription = subscription; 391 mCallingPackage = callingPackage; 392 mCallbackIntent = callbackIntent; 393 } 394 395 @Override onGetMetadataComplete(int cardId, GetDownloadableSubscriptionMetadataResult result)396 public void onGetMetadataComplete(int cardId, 397 GetDownloadableSubscriptionMetadataResult result) { 398 Intent extrasIntent = new Intent(); 399 final int resultCode; 400 switch (result.getResult()) { 401 case EuiccService.RESULT_OK: 402 resultCode = OK; 403 extrasIntent.putExtra( 404 EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION, 405 result.getDownloadableSubscription()); 406 break; 407 case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 408 resultCode = RESOLVABLE_ERROR; 409 addResolutionIntent(extrasIntent, 410 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 411 mCallingPackage, 412 0 /* resolvableErrors */, 413 false /* confirmationCodeRetried */, 414 getOperationForDeactivateSim(), 415 cardId); 416 break; 417 default: 418 resultCode = ERROR; 419 addExtrasToResultIntent(extrasIntent, result.getResult()); 420 break; 421 } 422 423 sendResult(mCallbackIntent, resultCode, extrasIntent); 424 } 425 426 @Override onEuiccServiceUnavailable()427 public void onEuiccServiceUnavailable() { 428 sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 429 } 430 getOperationForDeactivateSim()431 protected EuiccOperation getOperationForDeactivateSim() { 432 return EuiccOperation.forGetMetadataDeactivateSim( 433 mCallingToken, mSubscription, mCallingPackage); 434 } 435 } 436 437 @Override downloadSubscription(int cardId, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage, Bundle resolvedBundle, PendingIntent callbackIntent)438 public void downloadSubscription(int cardId, DownloadableSubscription subscription, 439 boolean switchAfterDownload, String callingPackage, Bundle resolvedBundle, 440 PendingIntent callbackIntent) { 441 downloadSubscription(cardId, subscription, switchAfterDownload, callingPackage, 442 false /* forceDeactivateSim */, resolvedBundle, callbackIntent); 443 } 444 445 /** 446 * Given encoded error code described in 447 * {@link android.telephony.euicc.EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE} decode it 448 * into SubjectCode[5.2.6.1] and ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2) 449 * 450 * @param resultCode from 451 * {@link android.telephony.euicc.EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE} 452 * @return a pair containing SubjectCode[5.2.6.1] and ReasonCode[5.2.6.2] from GSMA (SGP.22 453 * v2.2) 454 */ decodeSmdxSubjectAndReasonCode(int resultCode)455 Pair<String, String> decodeSmdxSubjectAndReasonCode(int resultCode) { 456 final int numOfSections = 6; 457 final int bitsPerSection = 4; 458 final int sectionMask = 0xF; 459 460 final Stack<Integer> sections = new Stack<>(); 461 462 // Extracting each section of digits backwards. 463 for (int i = 0; i < numOfSections; ++i) { 464 int sectionDigit = resultCode & sectionMask; 465 sections.push(sectionDigit); 466 resultCode = resultCode >>> bitsPerSection; 467 } 468 469 String subjectCode = sections.pop() + "." + sections.pop() + "." + sections.pop(); 470 String reasonCode = sections.pop() + "." + sections.pop() + "." + sections.pop(); 471 472 // drop the leading zeros, e.g 0.1 -> 1, 0.0.3 -> 3, 0.5.1 -> 5.1 473 subjectCode = subjectCode.replaceAll("^(0\\.)*", ""); 474 reasonCode = reasonCode.replaceAll("^(0\\.)*", ""); 475 476 return Pair.create(subjectCode, reasonCode); 477 } 478 479 /** 480 * Add more detailed information to the resulting intent. 481 * Fields added includes(key -> value): 482 * 1. {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE} -> original error code 483 * 2. {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE} -> 484 * EuiccManager.OperationCode such as {@link EuiccManager#OPERATION_DOWNLOAD} 485 * 3. if @link EuiccManager.OperationCode is not 486 * {@link EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE}: 487 * {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE} -> @link 488 * EuiccManager.ErrorCode such as {@link EuiccManager#OPERATION_SMDX} 489 * 4. if EuiccManager.OperationCode is 490 * {@link EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE}: 491 * a) {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE} -> 492 * SubjectCode[5.2.6.1] from GSMA (SGP.22 v2.2) 493 * b) {@link EuiccManager#EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE} -> 494 * ReasonCode[5.2.6.2] from GSMA (SGP.22 v2.2 495 */ addExtrasToResultIntent(Intent intent, int resultCode)496 private void addExtrasToResultIntent(Intent intent, int resultCode) { 497 final int firstByteBitOffset = 24; 498 int errorCodeMask = 0xFFFFFF; 499 int operationCode = resultCode >>> firstByteBitOffset; 500 501 intent.putExtra( 502 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, resultCode); 503 504 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_OPERATION_CODE, operationCode); 505 506 // check to see if the operation code is EuiccManager#OPERATION_SMDX_SUBJECT_REASON_CODE 507 final boolean isSmdxSubjectReasonCode = 508 (operationCode == EuiccManager.OPERATION_SMDX_SUBJECT_REASON_CODE); 509 510 if (isSmdxSubjectReasonCode) { 511 final Pair<String, String> subjectReasonCode = decodeSmdxSubjectAndReasonCode( 512 resultCode); 513 final String subjectCode = subjectReasonCode.first; 514 final String reasonCode = subjectReasonCode.second; 515 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_SUBJECT_CODE, 516 subjectCode); 517 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_SMDX_REASON_CODE, reasonCode); 518 } else { 519 final int errorCode = resultCode & errorCodeMask; 520 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_ERROR_CODE, errorCode); 521 } 522 } 523 downloadSubscription(int cardId, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, Bundle resolvedBundle, PendingIntent callbackIntent)524 void downloadSubscription(int cardId, DownloadableSubscription subscription, 525 boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, 526 Bundle resolvedBundle, PendingIntent callbackIntent) { 527 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 528 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 529 530 long token = Binder.clearCallingIdentity(); 531 try { 532 if (callerCanWriteEmbeddedSubscriptions) { 533 // With WRITE_EMBEDDED_SUBSCRIPTIONS, we can skip profile-specific permission checks 534 // and move straight to the profile download. 535 downloadSubscriptionPrivileged(cardId, token, subscription, switchAfterDownload, 536 forceDeactivateSim, callingPackage, resolvedBundle, callbackIntent); 537 return; 538 } 539 540 // Without WRITE_EMBEDDED_SUBSCRIPTIONS, we first check whether the caller can manage 541 // subscription on the target SIM (see comments below). If yes, the caller *must* be 542 // whitelisted per the metadata of the profile to be downloaded, so check the metadata; 543 // If no, ask the user's consent before proceed. 544 // On a multi-active SIM device, if the caller can manage the active subscription on the 545 // target SIM, or there is no active subscription on the target SIM and the caller can 546 // manage any active subscription on other SIMs, we perform the download silently. 547 // Otherwise, the user must provide consent. If it's a single-active SIM device, 548 // determine whether the caller can manage the current profile; if so, we can perform 549 // the download silently; if not, the user must provide consent. 550 if (canManageSubscriptionOnTargetSim(cardId, callingPackage)) { 551 mConnector.getDownloadableSubscriptionMetadata(cardId, subscription, 552 forceDeactivateSim, 553 new DownloadSubscriptionGetMetadataCommandCallback(token, subscription, 554 switchAfterDownload, callingPackage, forceDeactivateSim, 555 callbackIntent, false /* withUserConsent */)); 556 } else { 557 Log.i(TAG, "Caller can't manage subscription on target SIM. " 558 + "Ask user's consent first"); 559 Intent extrasIntent = new Intent(); 560 addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 561 callingPackage, 562 0 /* resolvableErrors */, 563 false /* confirmationCodeRetried */, 564 EuiccOperation.forDownloadNoPrivilegesOrDeactivateSimCheckMetadata(token, 565 subscription, switchAfterDownload, callingPackage), cardId); 566 sendResult(callbackIntent, RESOLVABLE_ERROR, extrasIntent); 567 } 568 } finally { 569 Binder.restoreCallingIdentity(token); 570 } 571 } 572 573 class DownloadSubscriptionGetMetadataCommandCallback extends GetMetadataCommandCallback { 574 private final boolean mSwitchAfterDownload; 575 private final boolean mForceDeactivateSim; 576 private final boolean mWithUserConsent; 577 DownloadSubscriptionGetMetadataCommandCallback(long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, PendingIntent callbackIntent, boolean withUserConsent)578 DownloadSubscriptionGetMetadataCommandCallback(long callingToken, 579 DownloadableSubscription subscription, boolean switchAfterDownload, 580 String callingPackage, boolean forceDeactivateSim, 581 PendingIntent callbackIntent, boolean withUserConsent) { 582 super(callingToken, subscription, callingPackage, callbackIntent); 583 mSwitchAfterDownload = switchAfterDownload; 584 mForceDeactivateSim = forceDeactivateSim; 585 mWithUserConsent = withUserConsent; 586 } 587 588 @Override onGetMetadataComplete(int cardId, GetDownloadableSubscriptionMetadataResult result)589 public void onGetMetadataComplete(int cardId, 590 GetDownloadableSubscriptionMetadataResult result) { 591 DownloadableSubscription subscription = result.getDownloadableSubscription(); 592 if (mWithUserConsent) { 593 // We won't get RESULT_MUST_DEACTIVATE_SIM for the case with user consent. 594 if (result.getResult() != EuiccService.RESULT_OK) { 595 // Just propagate the error as normal. 596 super.onGetMetadataComplete(cardId, result); 597 return; 598 } 599 600 if (checkCarrierPrivilegeInMetadata(subscription, mCallingPackage)) { 601 // Caller can download this profile. Since we already have the user's consent, 602 // proceed to download. 603 downloadSubscriptionPrivileged(cardId, 604 mCallingToken, subscription, mSwitchAfterDownload, mForceDeactivateSim, 605 mCallingPackage, null /* resolvedBundle */, 606 mCallbackIntent); 607 } else { 608 Log.e(TAG, "Caller does not have carrier privilege in metadata."); 609 sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 610 } 611 } else { // !mWithUserConsent 612 if (result.getResult() == EuiccService.RESULT_MUST_DEACTIVATE_SIM) { 613 // The caller can manage the target SIM. Ask the user's consent to deactivate 614 // the current SIM. 615 Intent extrasIntent = new Intent(); 616 addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 617 mCallingPackage, 618 0 /* resolvableErrors */, 619 false /* confirmationCodeRetried */, 620 EuiccOperation.forDownloadNoPrivilegesOrDeactivateSimCheckMetadata( 621 mCallingToken, mSubscription, mSwitchAfterDownload, 622 mCallingPackage), 623 cardId); 624 sendResult(mCallbackIntent, RESOLVABLE_ERROR, extrasIntent); 625 return; 626 } 627 628 if (result.getResult() != EuiccService.RESULT_OK) { 629 // Just propagate the error as normal. 630 super.onGetMetadataComplete(cardId, result); 631 return; 632 } 633 634 if (checkCarrierPrivilegeInMetadata(subscription, mCallingPackage)) { 635 // Caller can download this profile per profile metadata. Also, caller can 636 // manage the subscription on the target SIM, which is already checked. 637 downloadSubscriptionPrivileged(cardId, 638 mCallingToken, subscription, mSwitchAfterDownload, mForceDeactivateSim, 639 mCallingPackage, null /* resolvedBundle */, 640 mCallbackIntent); 641 } else { 642 Log.e(TAG, "Caller is not permitted to download this profile per metadata"); 643 sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 644 } 645 } 646 } 647 } 648 649 // Already have user consent. Check metadata first before proceed to download. downloadSubscriptionPrivilegedCheckMetadata(int cardId, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent)650 void downloadSubscriptionPrivilegedCheckMetadata(int cardId, final long callingToken, 651 DownloadableSubscription subscription, boolean switchAfterDownload, 652 boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, 653 final PendingIntent callbackIntent) { 654 mConnector.getDownloadableSubscriptionMetadata(cardId, subscription, forceDeactivateSim, 655 new DownloadSubscriptionGetMetadataCommandCallback(callingToken, subscription, 656 switchAfterDownload, callingPackage, forceDeactivateSim, callbackIntent, 657 true /* withUserConsent */)); 658 } 659 660 // Continue to download subscription without checking anything. downloadSubscriptionPrivileged(int cardId, final long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, final PendingIntent callbackIntent)661 void downloadSubscriptionPrivileged(int cardId, final long callingToken, 662 DownloadableSubscription subscription, boolean switchAfterDownload, 663 boolean forceDeactivateSim, final String callingPackage, Bundle resolvedBundle, 664 final PendingIntent callbackIntent) { 665 mConnector.downloadSubscription( 666 cardId, 667 subscription, 668 switchAfterDownload, 669 forceDeactivateSim, 670 resolvedBundle, 671 new EuiccConnector.DownloadCommandCallback() { 672 @Override 673 public void onDownloadComplete(DownloadSubscriptionResult result) { 674 Intent extrasIntent = new Intent(); 675 final int resultCode; 676 switch (result.getResult()) { 677 case EuiccService.RESULT_OK: 678 resultCode = OK; 679 // Now that a profile has been successfully downloaded, mark the 680 // eUICC as provisioned so it appears in settings UI as appropriate. 681 Settings.Global.putInt( 682 mContext.getContentResolver(), 683 Settings.Global.EUICC_PROVISIONED, 684 1); 685 extrasIntent.putExtra( 686 EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION, 687 subscription); 688 if (!switchAfterDownload) { 689 // Since we're not switching, nothing will trigger a 690 // subscription list refresh on its own, so request one here. 691 refreshSubscriptionsAndSendResult( 692 callbackIntent, resultCode, extrasIntent); 693 return; 694 } 695 break; 696 case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 697 resultCode = RESOLVABLE_ERROR; 698 addResolutionIntent(extrasIntent, 699 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 700 callingPackage, 701 0 /* resolvableErrors */, 702 false /* confirmationCodeRetried */, 703 EuiccOperation.forDownloadDeactivateSim( 704 callingToken, subscription, switchAfterDownload, 705 callingPackage), 706 cardId); 707 break; 708 case EuiccService.RESULT_RESOLVABLE_ERRORS: 709 // Same value as the deprecated 710 // {@link EuiccService#RESULT_NEED_CONFIRMATION_CODE}. For the 711 // deprecated case, the resolvableErrors is set as 0 in 712 // EuiccService. 713 resultCode = RESOLVABLE_ERROR; 714 boolean retried = false; 715 if (!TextUtils.isEmpty(subscription.getConfirmationCode())) { 716 retried = true; 717 } 718 if (result.getResolvableErrors() != 0) { 719 addResolutionIntent(extrasIntent, 720 EuiccService.ACTION_RESOLVE_RESOLVABLE_ERRORS, 721 callingPackage, 722 result.getResolvableErrors(), 723 retried, 724 EuiccOperation.forDownloadResolvableErrors( 725 callingToken, subscription, switchAfterDownload, 726 callingPackage, result.getResolvableErrors()), 727 cardId); 728 } else { // Deprecated case 729 addResolutionIntent(extrasIntent, 730 EuiccService.ACTION_RESOLVE_CONFIRMATION_CODE, 731 callingPackage, 732 0 /* resolvableErrors */, 733 retried /* confirmationCodeRetried */, 734 EuiccOperation.forDownloadConfirmationCode( 735 callingToken, subscription, switchAfterDownload, 736 callingPackage), 737 cardId); 738 } 739 break; 740 default: 741 resultCode = ERROR; 742 743 addExtrasToResultIntent(extrasIntent, result.getResult()); 744 break; 745 } 746 747 sendResult(callbackIntent, resultCode, extrasIntent); 748 } 749 750 @Override 751 public void onEuiccServiceUnavailable() { 752 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 753 } 754 }); 755 } 756 757 /** 758 * Blocking call to {@link EuiccService#onGetEuiccProfileInfoList} of the eUICC with card ID 759 * {@code cardId}. 760 * 761 * <p>Does not perform permission checks as this is not an exposed API and is only used within 762 * the phone process. 763 */ blockingGetEuiccProfileInfoList(int cardId)764 public GetEuiccProfileInfoListResult blockingGetEuiccProfileInfoList(int cardId) { 765 final CountDownLatch latch = new CountDownLatch(1); 766 final AtomicReference<GetEuiccProfileInfoListResult> resultRef = new AtomicReference<>(); 767 mConnector.getEuiccProfileInfoList( 768 cardId, 769 new EuiccConnector.GetEuiccProfileInfoListCommandCallback() { 770 @Override 771 public void onListComplete(GetEuiccProfileInfoListResult result) { 772 resultRef.set(result); 773 latch.countDown(); 774 } 775 776 @Override 777 public void onEuiccServiceUnavailable() { 778 latch.countDown(); 779 } 780 }); 781 try { 782 latch.await(); 783 } catch (InterruptedException e) { 784 Log.e(TAG, "blockingGetEuiccInfoFromEuiccService got InterruptedException e: " + e); 785 Thread.currentThread().interrupt(); 786 } 787 return resultRef.get(); 788 } 789 790 @Override getDefaultDownloadableSubscriptionList(int cardId, String callingPackage, PendingIntent callbackIntent)791 public void getDefaultDownloadableSubscriptionList(int cardId, 792 String callingPackage, PendingIntent callbackIntent) { 793 getDefaultDownloadableSubscriptionList(cardId, 794 false /* forceDeactivateSim */, callingPackage, callbackIntent); 795 } 796 getDefaultDownloadableSubscriptionList(int cardId, boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent)797 void getDefaultDownloadableSubscriptionList(int cardId, 798 boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 799 if (!callerCanWriteEmbeddedSubscriptions()) { 800 throw new SecurityException( 801 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get default list"); 802 } 803 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 804 long token = Binder.clearCallingIdentity(); 805 try { 806 mConnector.getDefaultDownloadableSubscriptionList(cardId, 807 forceDeactivateSim, new GetDefaultListCommandCallback( 808 token, callingPackage, callbackIntent)); 809 } finally { 810 Binder.restoreCallingIdentity(token); 811 } 812 } 813 814 class GetDefaultListCommandCallback implements EuiccConnector.GetDefaultListCommandCallback { 815 final long mCallingToken; 816 final String mCallingPackage; 817 final PendingIntent mCallbackIntent; 818 GetDefaultListCommandCallback(long callingToken, String callingPackage, PendingIntent callbackIntent)819 GetDefaultListCommandCallback(long callingToken, String callingPackage, 820 PendingIntent callbackIntent) { 821 mCallingToken = callingToken; 822 mCallingPackage = callingPackage; 823 mCallbackIntent = callbackIntent; 824 } 825 826 @Override onGetDefaultListComplete(int cardId, GetDefaultDownloadableSubscriptionListResult result)827 public void onGetDefaultListComplete(int cardId, 828 GetDefaultDownloadableSubscriptionListResult result) { 829 Intent extrasIntent = new Intent(); 830 final int resultCode; 831 switch (result.getResult()) { 832 case EuiccService.RESULT_OK: 833 resultCode = OK; 834 List<DownloadableSubscription> list = result.getDownloadableSubscriptions(); 835 if (list != null && list.size() > 0) { 836 extrasIntent.putExtra( 837 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS, 838 list.toArray(new DownloadableSubscription[list.size()])); 839 } 840 break; 841 case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 842 resultCode = RESOLVABLE_ERROR; 843 addResolutionIntent(extrasIntent, 844 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 845 mCallingPackage, 846 0 /* resolvableErrors */, 847 false /* confirmationCodeRetried */, 848 EuiccOperation.forGetDefaultListDeactivateSim( 849 mCallingToken, mCallingPackage), 850 cardId); 851 break; 852 default: 853 resultCode = ERROR; 854 addExtrasToResultIntent(extrasIntent, result.getResult()); 855 break; 856 } 857 858 sendResult(mCallbackIntent, resultCode, extrasIntent); 859 } 860 861 @Override onEuiccServiceUnavailable()862 public void onEuiccServiceUnavailable() { 863 sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 864 } 865 } 866 867 /** 868 * Return the {@link EuiccInfo}. 869 * 870 * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 871 * that IPC should generally be fast, and this info shouldn't be needed in the normal course of 872 * operation. 873 */ 874 @Override getEuiccInfo(int cardId)875 public EuiccInfo getEuiccInfo(int cardId) { 876 // No permissions required as EuiccInfo is not sensitive. 877 long token = Binder.clearCallingIdentity(); 878 try { 879 return blockingGetEuiccInfoFromEuiccService(cardId); 880 } finally { 881 Binder.restoreCallingIdentity(token); 882 } 883 } 884 885 @Override deleteSubscription(int cardId, int subscriptionId, String callingPackage, PendingIntent callbackIntent)886 public void deleteSubscription(int cardId, int subscriptionId, String callingPackage, 887 PendingIntent callbackIntent) { 888 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 889 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 890 891 long token = Binder.clearCallingIdentity(); 892 try { 893 SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 894 if (sub == null) { 895 Log.e(TAG, "Cannot delete nonexistent subscription: " + subscriptionId); 896 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 897 return; 898 } 899 900 // For both single active SIM device and multi-active SIM device, if the caller is 901 // system or the caller manage the target subscription, we let it continue. This is 902 // because deleting subscription won't change status of any other subscriptions. 903 if (!callerCanWriteEmbeddedSubscriptions 904 && !mSubscriptionManager.canManageSubscription(sub, callingPackage)) { 905 Log.e(TAG, "No permissions: " + subscriptionId); 906 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 907 return; 908 } 909 910 deleteSubscriptionPrivileged(cardId, sub.getIccId(), callbackIntent); 911 } finally { 912 Binder.restoreCallingIdentity(token); 913 } 914 } 915 deleteSubscriptionPrivileged(int cardId, String iccid, final PendingIntent callbackIntent)916 void deleteSubscriptionPrivileged(int cardId, String iccid, 917 final PendingIntent callbackIntent) { 918 mConnector.deleteSubscription( 919 cardId, 920 iccid, 921 new EuiccConnector.DeleteCommandCallback() { 922 @Override 923 public void onDeleteComplete(int result) { 924 Intent extrasIntent = new Intent(); 925 final int resultCode; 926 switch (result) { 927 case EuiccService.RESULT_OK: 928 resultCode = OK; 929 refreshSubscriptionsAndSendResult( 930 callbackIntent, resultCode, extrasIntent); 931 return; 932 default: 933 resultCode = ERROR; 934 addExtrasToResultIntent(extrasIntent, result); 935 break; 936 } 937 938 sendResult(callbackIntent, resultCode, extrasIntent); 939 } 940 941 @Override 942 public void onEuiccServiceUnavailable() { 943 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 944 } 945 }); 946 } 947 948 @Override switchToSubscription(int cardId, int subscriptionId, String callingPackage, PendingIntent callbackIntent)949 public void switchToSubscription(int cardId, int subscriptionId, String callingPackage, 950 PendingIntent callbackIntent) { 951 switchToSubscription(cardId, 952 subscriptionId, false /* forceDeactivateSim */, callingPackage, callbackIntent); 953 } 954 switchToSubscription(int cardId, int subscriptionId, boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent)955 void switchToSubscription(int cardId, int subscriptionId, boolean forceDeactivateSim, 956 String callingPackage, PendingIntent callbackIntent) { 957 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 958 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 959 960 long token = Binder.clearCallingIdentity(); 961 try { 962 if (callerCanWriteEmbeddedSubscriptions) { 963 // Assume that if a privileged caller is calling us, we don't need to prompt the 964 // user about changing carriers, because the caller would only be acting in response 965 // to user action. 966 forceDeactivateSim = true; 967 } 968 969 final String iccid; 970 boolean passConsent = false; 971 if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 972 if (callerCanWriteEmbeddedSubscriptions 973 || canManageActiveSubscriptionOnTargetSim(cardId, callingPackage)) { 974 passConsent = true; 975 } else { 976 Log.e(TAG, "Not permitted to switch to empty subscription"); 977 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 978 return; 979 } 980 iccid = null; 981 } else { 982 SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 983 if (sub == null) { 984 Log.e(TAG, "Cannot switch to nonexistent sub: " + subscriptionId); 985 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 986 return; 987 } 988 if (callerCanWriteEmbeddedSubscriptions) { 989 passConsent = true; 990 } else { 991 if (!mSubscriptionManager.canManageSubscription(sub, callingPackage)) { 992 Log.e(TAG, "Not permitted to switch to sub: " + subscriptionId); 993 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 994 return; 995 } 996 997 if (canManageSubscriptionOnTargetSim(cardId, callingPackage)) { 998 passConsent = true; 999 } 1000 } 1001 iccid = sub.getIccId(); 1002 } 1003 1004 if (!passConsent) { 1005 // Switch needs consent. 1006 Intent extrasIntent = new Intent(); 1007 addResolutionIntent(extrasIntent, 1008 EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 1009 callingPackage, 1010 0 /* resolvableErrors */, 1011 false /* confirmationCodeRetried */, 1012 EuiccOperation.forSwitchNoPrivileges( 1013 token, subscriptionId, callingPackage), 1014 cardId); 1015 sendResult(callbackIntent, RESOLVABLE_ERROR, extrasIntent); 1016 return; 1017 } 1018 1019 switchToSubscriptionPrivileged(cardId, token, subscriptionId, iccid, forceDeactivateSim, 1020 callingPackage, callbackIntent); 1021 } finally { 1022 Binder.restoreCallingIdentity(token); 1023 } 1024 } 1025 switchToSubscriptionPrivileged(int cardId, final long callingToken, int subscriptionId, boolean forceDeactivateSim, final String callingPackage, final PendingIntent callbackIntent)1026 void switchToSubscriptionPrivileged(int cardId, final long callingToken, int subscriptionId, 1027 boolean forceDeactivateSim, final String callingPackage, 1028 final PendingIntent callbackIntent) { 1029 String iccid = null; 1030 SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 1031 if (sub != null) { 1032 iccid = sub.getIccId(); 1033 } 1034 switchToSubscriptionPrivileged(cardId, callingToken, subscriptionId, iccid, 1035 forceDeactivateSim, callingPackage, callbackIntent); 1036 } 1037 switchToSubscriptionPrivileged(int cardId, final long callingToken, int subscriptionId, @Nullable String iccid, boolean forceDeactivateSim, final String callingPackage, final PendingIntent callbackIntent)1038 void switchToSubscriptionPrivileged(int cardId, final long callingToken, int subscriptionId, 1039 @Nullable String iccid, boolean forceDeactivateSim, final String callingPackage, 1040 final PendingIntent callbackIntent) { 1041 mConnector.switchToSubscription( 1042 cardId, 1043 iccid, 1044 forceDeactivateSim, 1045 new EuiccConnector.SwitchCommandCallback() { 1046 @Override 1047 public void onSwitchComplete(int result) { 1048 Intent extrasIntent = new Intent(); 1049 final int resultCode; 1050 switch (result) { 1051 case EuiccService.RESULT_OK: 1052 resultCode = OK; 1053 break; 1054 case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 1055 resultCode = RESOLVABLE_ERROR; 1056 addResolutionIntent(extrasIntent, 1057 EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 1058 callingPackage, 1059 0 /* resolvableErrors */, 1060 false /* confirmationCodeRetried */, 1061 EuiccOperation.forSwitchDeactivateSim( 1062 callingToken, subscriptionId, callingPackage), 1063 cardId); 1064 break; 1065 default: 1066 resultCode = ERROR; 1067 addExtrasToResultIntent(extrasIntent, result); 1068 break; 1069 } 1070 1071 sendResult(callbackIntent, resultCode, extrasIntent); 1072 } 1073 1074 @Override 1075 public void onEuiccServiceUnavailable() { 1076 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1077 } 1078 }); 1079 } 1080 1081 @Override updateSubscriptionNickname(int cardId, int subscriptionId, String nickname, String callingPackage, PendingIntent callbackIntent)1082 public void updateSubscriptionNickname(int cardId, int subscriptionId, String nickname, 1083 String callingPackage, PendingIntent callbackIntent) { 1084 boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 1085 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 1086 1087 long token = Binder.clearCallingIdentity(); 1088 try { 1089 SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 1090 if (sub == null) { 1091 Log.e(TAG, "Cannot update nickname to nonexistent sub: " + subscriptionId); 1092 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1093 return; 1094 } 1095 1096 // For both single active SIM device and multi-active SIM device, if the caller is 1097 // system or the caller can manage the target subscription, we let it continue. This is 1098 // because updating subscription nickname won't affect any other subscriptions. 1099 if (!callerCanWriteEmbeddedSubscriptions 1100 && !mSubscriptionManager.canManageSubscription(sub, callingPackage)) { 1101 Log.e(TAG, "No permissions: " + subscriptionId); 1102 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1103 return; 1104 } 1105 1106 mConnector.updateSubscriptionNickname(cardId, 1107 sub.getIccId(), nickname, 1108 new EuiccConnector.UpdateNicknameCommandCallback() { 1109 @Override 1110 public void onUpdateNicknameComplete(int result) { 1111 Intent extrasIntent = new Intent(); 1112 final int resultCode; 1113 switch (result) { 1114 case EuiccService.RESULT_OK: 1115 resultCode = OK; 1116 refreshSubscriptionsAndSendResult( 1117 callbackIntent, resultCode, extrasIntent); 1118 return; 1119 default: 1120 resultCode = ERROR; 1121 addExtrasToResultIntent(extrasIntent, result); 1122 break; 1123 } 1124 1125 sendResult(callbackIntent, resultCode, extrasIntent); 1126 } 1127 1128 @Override 1129 public void onEuiccServiceUnavailable() { 1130 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1131 } 1132 }); 1133 } finally { 1134 Binder.restoreCallingIdentity(token); 1135 } 1136 } 1137 1138 @Override eraseSubscriptions(int cardId, PendingIntent callbackIntent)1139 public void eraseSubscriptions(int cardId, PendingIntent callbackIntent) { 1140 if (!callerCanWriteEmbeddedSubscriptions()) { 1141 throw new SecurityException( 1142 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to erase subscriptions"); 1143 } 1144 long token = Binder.clearCallingIdentity(); 1145 try { 1146 mConnector.eraseSubscriptions( 1147 cardId, new EuiccConnector.EraseCommandCallback() { 1148 @Override 1149 public void onEraseComplete(int result) { 1150 Intent extrasIntent = new Intent(); 1151 final int resultCode; 1152 switch (result) { 1153 case EuiccService.RESULT_OK: 1154 resultCode = OK; 1155 refreshSubscriptionsAndSendResult( 1156 callbackIntent, resultCode, extrasIntent); 1157 return; 1158 default: 1159 resultCode = ERROR; 1160 addExtrasToResultIntent(extrasIntent, result); 1161 break; 1162 } 1163 1164 sendResult(callbackIntent, resultCode, extrasIntent); 1165 } 1166 1167 @Override 1168 public void onEuiccServiceUnavailable() { 1169 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1170 } 1171 }); 1172 } finally { 1173 Binder.restoreCallingIdentity(token); 1174 } 1175 } 1176 1177 @Override eraseSubscriptionsWithOptions( int cardId, @ResetOption int options, PendingIntent callbackIntent)1178 public void eraseSubscriptionsWithOptions( 1179 int cardId, @ResetOption int options, PendingIntent callbackIntent) { 1180 if (!callerCanWriteEmbeddedSubscriptions()) { 1181 throw new SecurityException( 1182 "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to erase subscriptions"); 1183 } 1184 long token = Binder.clearCallingIdentity(); 1185 try { 1186 mConnector.eraseSubscriptionsWithOptions( 1187 cardId, options, new EuiccConnector.EraseCommandCallback() { 1188 @Override 1189 public void onEraseComplete(int result) { 1190 Intent extrasIntent = new Intent(); 1191 final int resultCode; 1192 switch (result) { 1193 case EuiccService.RESULT_OK: 1194 resultCode = OK; 1195 refreshSubscriptionsAndSendResult( 1196 callbackIntent, resultCode, extrasIntent); 1197 return; 1198 default: 1199 resultCode = ERROR; 1200 addExtrasToResultIntent(extrasIntent, result); 1201 break; 1202 } 1203 1204 sendResult(callbackIntent, resultCode, extrasIntent); 1205 } 1206 1207 @Override 1208 public void onEuiccServiceUnavailable() { 1209 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1210 } 1211 }); 1212 } finally { 1213 Binder.restoreCallingIdentity(token); 1214 } 1215 } 1216 1217 @Override retainSubscriptionsForFactoryReset(int cardId, PendingIntent callbackIntent)1218 public void retainSubscriptionsForFactoryReset(int cardId, PendingIntent callbackIntent) { 1219 mContext.enforceCallingPermission(Manifest.permission.MASTER_CLEAR, 1220 "Must have MASTER_CLEAR to retain subscriptions for factory reset"); 1221 long token = Binder.clearCallingIdentity(); 1222 try { 1223 mConnector.retainSubscriptions(cardId, 1224 new EuiccConnector.RetainSubscriptionsCommandCallback() { 1225 @Override 1226 public void onRetainSubscriptionsComplete(int result) { 1227 Intent extrasIntent = new Intent(); 1228 final int resultCode; 1229 switch (result) { 1230 case EuiccService.RESULT_OK: 1231 resultCode = OK; 1232 break; 1233 default: 1234 resultCode = ERROR; 1235 addExtrasToResultIntent(extrasIntent, result); 1236 break; 1237 } 1238 1239 sendResult(callbackIntent, resultCode, extrasIntent); 1240 } 1241 1242 @Override 1243 public void onEuiccServiceUnavailable() { 1244 sendResult(callbackIntent, ERROR, null /* extrasIntent */); 1245 } 1246 }); 1247 } finally { 1248 Binder.restoreCallingIdentity(token); 1249 } 1250 } 1251 1252 /** Refresh the embedded subscription list and dispatch the given result upon completion. */ 1253 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) refreshSubscriptionsAndSendResult( PendingIntent callbackIntent, int resultCode, Intent extrasIntent)1254 public void refreshSubscriptionsAndSendResult( 1255 PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 1256 SubscriptionController.getInstance() 1257 .requestEmbeddedSubscriptionInfoListRefresh( 1258 () -> sendResult(callbackIntent, resultCode, extrasIntent)); 1259 } 1260 1261 /** Dispatch the given callback intent with the given result code and data. */ 1262 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) sendResult(PendingIntent callbackIntent, int resultCode, Intent extrasIntent)1263 public void sendResult(PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 1264 try { 1265 callbackIntent.send(mContext, resultCode, extrasIntent); 1266 } catch (PendingIntent.CanceledException e) { 1267 // Caller canceled the callback; do nothing. 1268 } 1269 } 1270 1271 /** Add a resolution intent to the given extras intent. */ 1272 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) addResolutionIntent(Intent extrasIntent, String resolutionAction, String callingPackage, int resolvableErrors, boolean confirmationCodeRetried, EuiccOperation op, int cardId)1273 public void addResolutionIntent(Intent extrasIntent, String resolutionAction, 1274 String callingPackage, int resolvableErrors, boolean confirmationCodeRetried, 1275 EuiccOperation op, int cardId) { 1276 Intent intent = new Intent(EuiccManager.ACTION_RESOLVE_ERROR); 1277 intent.setPackage(RESOLUTION_ACTIVITY_PACKAGE_NAME); 1278 intent.setComponent(new ComponentName( 1279 RESOLUTION_ACTIVITY_PACKAGE_NAME, RESOLUTION_ACTIVITY_CLASS_NAME)); 1280 intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION, 1281 resolutionAction); 1282 intent.putExtra(EuiccService.EXTRA_RESOLUTION_CALLING_PACKAGE, callingPackage); 1283 intent.putExtra(EuiccService.EXTRA_RESOLVABLE_ERRORS, resolvableErrors); 1284 intent.putExtra(EuiccService.EXTRA_RESOLUTION_CARD_ID, cardId); 1285 intent.putExtra(EuiccService.EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED, 1286 confirmationCodeRetried); 1287 intent.putExtra(EXTRA_OPERATION, op); 1288 PendingIntent resolutionIntent = PendingIntent.getActivity( 1289 mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_ONE_SHOT); 1290 extrasIntent.putExtra( 1291 EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT, resolutionIntent); 1292 } 1293 1294 @Override dump(FileDescriptor fd, final PrintWriter pw, String[] args)1295 public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) { 1296 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP"); 1297 final long token = Binder.clearCallingIdentity(); 1298 pw.println("===== BEGIN EUICC CLINIC ====="); 1299 try { 1300 pw.println("===== EUICC CONNECTOR ====="); 1301 mConnector.dump(fd, pw, args); 1302 final CountDownLatch countDownLatch = new CountDownLatch(1); 1303 mConnector.dumpEuiccService(new EuiccConnector.DumpEuiccServiceCommandCallback() { 1304 @Override 1305 public void onDumpEuiccServiceComplete(String logs) { 1306 pw.println("===== EUICC SERVICE ====="); 1307 pw.println(logs); 1308 countDownLatch.countDown(); 1309 } 1310 1311 @Override 1312 public void onEuiccServiceUnavailable() { 1313 pw.println("===== EUICC SERVICE UNAVAILABLE ====="); 1314 countDownLatch.countDown(); 1315 } 1316 }); 1317 1318 // Wait up to 5 seconds 1319 if (!countDownLatch.await(EUICC_DUMP_TIME_OUT_SECONDS, TimeUnit.SECONDS)) { 1320 pw.println("===== EUICC SERVICE TIMEOUT ====="); 1321 } 1322 } catch (InterruptedException e) { 1323 pw.println("===== EUICC SERVICE INTERRUPTED ====="); 1324 } finally { 1325 pw.println("===== END EUICC CLINIC ====="); 1326 Binder.restoreCallingIdentity(token); 1327 } 1328 } 1329 1330 /** 1331 * Send broadcast {@link EuiccManager#ACTION_OTA_STATUS_CHANGED} for OTA status 1332 * changed. 1333 */ 1334 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) sendOtaStatusChangedBroadcast()1335 public void sendOtaStatusChangedBroadcast() { 1336 Intent intent = new Intent(EuiccManager.ACTION_OTA_STATUS_CHANGED); 1337 ComponentInfo bestComponent = mConnector.findBestComponent(mContext.getPackageManager()); 1338 if (bestComponent != null) { 1339 intent.setPackage(bestComponent.packageName); 1340 } 1341 mContext.sendBroadcast(intent, permission.WRITE_EMBEDDED_SUBSCRIPTIONS); 1342 } 1343 1344 @Nullable getSubscriptionForSubscriptionId(int subscriptionId)1345 private SubscriptionInfo getSubscriptionForSubscriptionId(int subscriptionId) { 1346 List<SubscriptionInfo> subs = mSubscriptionManager.getAvailableSubscriptionInfoList(); 1347 int subCount = (subs != null) ? subs.size() : 0; 1348 for (int i = 0; i < subCount; i++) { 1349 SubscriptionInfo sub = subs.get(i); 1350 if (subscriptionId == sub.getSubscriptionId()) { 1351 return sub; 1352 } 1353 } 1354 return null; 1355 } 1356 1357 @Nullable blockingGetEidFromEuiccService(int cardId)1358 private String blockingGetEidFromEuiccService(int cardId) { 1359 CountDownLatch latch = new CountDownLatch(1); 1360 AtomicReference<String> eidRef = new AtomicReference<>(); 1361 mConnector.getEid(cardId, new EuiccConnector.GetEidCommandCallback() { 1362 @Override 1363 public void onGetEidComplete(String eid) { 1364 eidRef.set(eid); 1365 latch.countDown(); 1366 } 1367 1368 @Override 1369 public void onEuiccServiceUnavailable() { 1370 latch.countDown(); 1371 } 1372 }); 1373 return awaitResult(latch, eidRef); 1374 } 1375 blockingGetOtaStatusFromEuiccService(int cardId)1376 private @OtaStatus int blockingGetOtaStatusFromEuiccService(int cardId) { 1377 CountDownLatch latch = new CountDownLatch(1); 1378 AtomicReference<Integer> statusRef = 1379 new AtomicReference<>(EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE); 1380 mConnector.getOtaStatus(cardId, new EuiccConnector.GetOtaStatusCommandCallback() { 1381 @Override 1382 public void onGetOtaStatusComplete(@OtaStatus int status) { 1383 statusRef.set(status); 1384 latch.countDown(); 1385 } 1386 1387 @Override 1388 public void onEuiccServiceUnavailable() { 1389 latch.countDown(); 1390 } 1391 }); 1392 return awaitResult(latch, statusRef); 1393 } 1394 1395 @Nullable blockingGetEuiccInfoFromEuiccService(int cardId)1396 private EuiccInfo blockingGetEuiccInfoFromEuiccService(int cardId) { 1397 CountDownLatch latch = new CountDownLatch(1); 1398 AtomicReference<EuiccInfo> euiccInfoRef = new AtomicReference<>(); 1399 mConnector.getEuiccInfo(cardId, new EuiccConnector.GetEuiccInfoCommandCallback() { 1400 @Override 1401 public void onGetEuiccInfoComplete(EuiccInfo euiccInfo) { 1402 euiccInfoRef.set(euiccInfo); 1403 latch.countDown(); 1404 } 1405 1406 @Override 1407 public void onEuiccServiceUnavailable() { 1408 latch.countDown(); 1409 } 1410 }); 1411 return awaitResult(latch, euiccInfoRef); 1412 } 1413 awaitResult(CountDownLatch latch, AtomicReference<T> resultRef)1414 private static <T> T awaitResult(CountDownLatch latch, AtomicReference<T> resultRef) { 1415 try { 1416 latch.await(); 1417 } catch (InterruptedException e) { 1418 Thread.currentThread().interrupt(); 1419 } 1420 return resultRef.get(); 1421 } 1422 1423 // Returns whether the caller has carrier privilege on the given subscription. checkCarrierPrivilegeInMetadata(DownloadableSubscription subscription, String callingPackage)1424 private boolean checkCarrierPrivilegeInMetadata(DownloadableSubscription subscription, 1425 String callingPackage) { 1426 UiccAccessRule[] rules = null; 1427 List<UiccAccessRule> rulesList = subscription.getAccessRules(); 1428 if (rulesList != null) { 1429 rules = rulesList.toArray(new UiccAccessRule[rulesList.size()]); 1430 } 1431 if (rules == null) { 1432 Log.e(TAG, "No access rules but caller is unprivileged"); 1433 return false; 1434 } 1435 1436 final PackageInfo info; 1437 try { 1438 info = mPackageManager.getPackageInfo(callingPackage, 1439 PackageManager.GET_SIGNING_CERTIFICATES); 1440 } catch (PackageManager.NameNotFoundException e) { 1441 Log.e(TAG, "Calling package valid but gone"); 1442 return false; 1443 } 1444 1445 for (int i = 0; i < rules.length; i++) { 1446 if (rules[i].getCarrierPrivilegeStatus(info) 1447 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 1448 Log.i(TAG, "Calling package has carrier privilege to this profile"); 1449 return true; 1450 } 1451 } 1452 Log.e(TAG, "Calling package doesn't have carrier privilege to this profile"); 1453 return false; 1454 } 1455 supportMultiActiveSlots()1456 private boolean supportMultiActiveSlots() { 1457 return mTelephonyManager.getSupportedModemCount() > 1; 1458 } 1459 1460 // Checks whether the caller can manage the active embedded subscription on the SIM with the 1461 // given cardId. canManageActiveSubscriptionOnTargetSim(int cardId, String callingPackage)1462 private boolean canManageActiveSubscriptionOnTargetSim(int cardId, String callingPackage) { 1463 List<SubscriptionInfo> subInfoList = mSubscriptionManager 1464 .getActiveSubscriptionInfoList(/* userVisibleOnly */false); 1465 if (subInfoList == null || subInfoList.size() == 0) { 1466 // No active subscription on any SIM. 1467 return false; 1468 } 1469 for (SubscriptionInfo subInfo : subInfoList) { 1470 // If cardId == TelephonyManager.UNSUPPORTED_CARD_ID, we assume it does not support 1471 // multiple eSIMs. There are older multi-active SIM devices which do not implement HAL 1472 // 1.2 and if they have multiple eSIMs, we let it pass if the app can manage an active 1473 // subscription on any eSIM. That's the best we can do here. 1474 if ((cardId == TelephonyManager.UNSUPPORTED_CARD_ID || subInfo.getCardId() == cardId) 1475 && subInfo.isEmbedded() 1476 && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) { 1477 return true; 1478 } 1479 } 1480 return false; 1481 } 1482 1483 // For a multi-active subscriptions phone, checks whether the caller can manage subscription on 1484 // the target SIM with the given cardId. The caller can only manage subscription on the target 1485 // SIM if it can manage the active subscription on the target SIM or there is no active 1486 // subscription on the target SIM, and the caller can manage any active subscription on any 1487 // other SIM. The target SIM should be an eUICC. 1488 // For a single-active subscription phone, checks whether the caller can manage any active 1489 // embedded subscription. canManageSubscriptionOnTargetSim(int cardId, String callingPackage)1490 private boolean canManageSubscriptionOnTargetSim(int cardId, String callingPackage) { 1491 List<SubscriptionInfo> subInfoList = mSubscriptionManager 1492 .getActiveSubscriptionInfoList(false /* userVisibleonly */); 1493 // No active subscription on any SIM. 1494 if (subInfoList == null || subInfoList.size() == 0) { 1495 return false; 1496 } 1497 // If it's a multi-active SIM device, we assume it's above HAL 1.2 which supports cardId. 1498 // There are older multi-active SIM devices but don't implement HAL 1.2. In this case, 1499 // platform can't even detect UiccCardInfo#isEuicc as true for eSIM, which won't let the 1500 // below check pass. That's the best we can do here. 1501 if (supportMultiActiveSlots()) { 1502 // The target card should be an eUICC. 1503 List<UiccCardInfo> cardInfos = mTelephonyManager.getUiccCardsInfo(); 1504 if (cardInfos == null || cardInfos.isEmpty()) { 1505 return false; 1506 } 1507 boolean isEuicc = false; 1508 for (UiccCardInfo info : cardInfos) { 1509 if (info != null && info.getCardId() == cardId && info.isEuicc()) { 1510 isEuicc = true; 1511 break; 1512 } 1513 } 1514 if (!isEuicc) { 1515 Log.i(TAG, "The target SIM is not an eUICC."); 1516 return false; 1517 } 1518 1519 // If the caller can't manage the active embedded subscription on the target SIM, return 1520 // false. If the caller can manage the active embedded subscription on the target SIM, 1521 // return true directly. 1522 for (SubscriptionInfo subInfo : subInfoList) { 1523 // subInfo.isEmbedded() can only be true for the target SIM. 1524 if (subInfo.isEmbedded() && subInfo.getCardId() == cardId) { 1525 return mSubscriptionManager.canManageSubscription(subInfo, callingPackage); 1526 } 1527 } 1528 1529 // There is no active subscription on the target SIM, checks whether the caller can 1530 // manage any active subscription on any other SIM. 1531 return mTelephonyManager.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) 1532 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 1533 } else { 1534 for (SubscriptionInfo subInfo : subInfoList) { 1535 if (subInfo.isEmbedded() 1536 && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) { 1537 return true; 1538 } 1539 } 1540 return false; 1541 } 1542 } 1543 callerCanReadPhoneStatePrivileged()1544 private boolean callerCanReadPhoneStatePrivileged() { 1545 return mContext.checkCallingOrSelfPermission( 1546 Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 1547 == PackageManager.PERMISSION_GRANTED; 1548 } 1549 callerCanWriteEmbeddedSubscriptions()1550 private boolean callerCanWriteEmbeddedSubscriptions() { 1551 return mContext.checkCallingOrSelfPermission( 1552 Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) 1553 == PackageManager.PERMISSION_GRANTED; 1554 } 1555 } 1556