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