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