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.annotation.IntDef; 19 import android.annotation.Nullable; 20 import android.app.PendingIntent; 21 import android.os.Binder; 22 import android.os.Bundle; 23 import android.os.Parcel; 24 import android.os.Parcelable; 25 import android.service.euicc.EuiccService; 26 import android.telephony.TelephonyManager; 27 import android.telephony.euicc.DownloadableSubscription; 28 import android.telephony.euicc.EuiccManager; 29 import android.text.TextUtils; 30 import android.util.Log; 31 32 import com.android.internal.annotations.VisibleForTesting; 33 34 import java.lang.annotation.Retention; 35 import java.lang.annotation.RetentionPolicy; 36 37 /** 38 * Representation of an {@link EuiccController} operation which failed with a resolvable error. 39 * 40 * <p>This class tracks the operation which failed and the reason for failure. Once the error is 41 * resolved, the operation can be resumed with {@link #continueOperation}. 42 */ 43 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 44 public class EuiccOperation implements Parcelable { 45 private static final String TAG = "EuiccOperation"; 46 47 public static final Creator<EuiccOperation> CREATOR = new Creator<EuiccOperation>() { 48 @Override 49 public EuiccOperation createFromParcel(Parcel in) { 50 return new EuiccOperation(in); 51 } 52 53 @Override 54 public EuiccOperation[] newArray(int size) { 55 return new EuiccOperation[size]; 56 } 57 }; 58 59 @VisibleForTesting 60 @Retention(RetentionPolicy.SOURCE) 61 @IntDef({ 62 ACTION_GET_METADATA_DEACTIVATE_SIM, 63 ACTION_DOWNLOAD_DEACTIVATE_SIM, 64 ACTION_DOWNLOAD_NO_PRIVILEGES, 65 ACTION_GET_DEFAULT_LIST_DEACTIVATE_SIM, 66 ACTION_SWITCH_DEACTIVATE_SIM, 67 ACTION_SWITCH_NO_PRIVILEGES, 68 ACTION_DOWNLOAD_RESOLVABLE_ERRORS, 69 }) 70 @interface Action {} 71 72 @VisibleForTesting 73 static final int ACTION_GET_METADATA_DEACTIVATE_SIM = 1; 74 @VisibleForTesting 75 static final int ACTION_DOWNLOAD_DEACTIVATE_SIM = 2; 76 @VisibleForTesting 77 static final int ACTION_DOWNLOAD_NO_PRIVILEGES = 3; 78 @VisibleForTesting 79 static final int ACTION_GET_DEFAULT_LIST_DEACTIVATE_SIM = 4; 80 @VisibleForTesting 81 static final int ACTION_SWITCH_DEACTIVATE_SIM = 5; 82 @VisibleForTesting 83 static final int ACTION_SWITCH_NO_PRIVILEGES = 6; 84 @VisibleForTesting 85 static final int ACTION_DOWNLOAD_RESOLVABLE_ERRORS = 7; 86 /** 87 * @deprecated Use ACTION_DOWNLOAD_RESOLVABLE_ERRORS and pass the resolvable errors in bit map. 88 */ 89 @VisibleForTesting 90 @Deprecated 91 static final int ACTION_DOWNLOAD_CONFIRMATION_CODE = 8; 92 /** 93 * ACTION_DOWNLOAD_CHECK_METADATA can be used for either NO_PRIVILEGES or DEACTIVATE_SIM. 94 */ 95 @VisibleForTesting 96 static final int ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA = 9; 97 98 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) 99 public final @Action int mAction; 100 101 private final long mCallingToken; 102 103 @Nullable 104 private final DownloadableSubscription mDownloadableSubscription; 105 private final int mSubscriptionId; 106 private final boolean mSwitchAfterDownload; 107 @Nullable 108 private final String mCallingPackage; 109 @Nullable 110 private final int mResolvableErrors; 111 112 /** 113 * {@link EuiccManager#getDownloadableSubscriptionMetadata} failed with 114 * {@link EuiccService#RESULT_MUST_DEACTIVATE_SIM}. 115 */ forGetMetadataDeactivateSim(long callingToken, DownloadableSubscription subscription, String callingPackage)116 static EuiccOperation forGetMetadataDeactivateSim(long callingToken, 117 DownloadableSubscription subscription, String callingPackage) { 118 return new EuiccOperation(ACTION_GET_METADATA_DEACTIVATE_SIM, callingToken, 119 subscription, 0 /* subscriptionId */, false /* switchAfterDownload */, 120 callingPackage); 121 } 122 123 /** 124 * {@link EuiccManager#downloadSubscription} failed with a mustDeactivateSim error. Should only 125 * be used for privileged callers; for unprivileged callers, use 126 * {@link #forDownloadNoPrivileges} to avoid a double prompt. 127 */ forDownloadDeactivateSim(long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage)128 static EuiccOperation forDownloadDeactivateSim(long callingToken, 129 DownloadableSubscription subscription, boolean switchAfterDownload, 130 String callingPackage) { 131 return new EuiccOperation(ACTION_DOWNLOAD_DEACTIVATE_SIM, callingToken, 132 subscription, 0 /* subscriptionId */, switchAfterDownload, callingPackage); 133 } 134 135 /** 136 * {@link EuiccManager#downloadSubscription} failed because the calling app does not have 137 * permission to manage the current active subscription. 138 */ forDownloadNoPrivileges(long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage)139 static EuiccOperation forDownloadNoPrivileges(long callingToken, 140 DownloadableSubscription subscription, boolean switchAfterDownload, 141 String callingPackage) { 142 return new EuiccOperation(ACTION_DOWNLOAD_NO_PRIVILEGES, callingToken, 143 subscription, 0 /* subscriptionId */, switchAfterDownload, callingPackage); 144 } 145 146 /** 147 * {@link EuiccManager#downloadSubscription} failed because the caller can't manage the target 148 * SIM, or we cannot determine the privileges without deactivating the current SIM first. 149 */ forDownloadNoPrivilegesOrDeactivateSimCheckMetadata(long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage)150 static EuiccOperation forDownloadNoPrivilegesOrDeactivateSimCheckMetadata(long callingToken, 151 DownloadableSubscription subscription, boolean switchAfterDownload, 152 String callingPackage) { 153 return new EuiccOperation(ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA, 154 callingToken, subscription, 0 /* subscriptionId */, 155 switchAfterDownload, callingPackage); 156 } 157 158 /** 159 * {@link EuiccManager#downloadSubscription} failed with 160 * {@link EuiccService#RESULT_NEED_CONFIRMATION_CODE} error. 161 * 162 * @deprecated Use 163 * {@link #forDownloadResolvableErrors(long, DownloadableSubscription, boolean, String, int)} 164 * instead. 165 */ 166 @Deprecated forDownloadConfirmationCode(long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage)167 public static EuiccOperation forDownloadConfirmationCode(long callingToken, 168 DownloadableSubscription subscription, boolean switchAfterDownload, 169 String callingPackage) { 170 return new EuiccOperation(ACTION_DOWNLOAD_CONFIRMATION_CODE, callingToken, 171 subscription, 0 /* subscriptionId */, switchAfterDownload, callingPackage); 172 } 173 174 /** 175 * {@link EuiccManager#downloadSubscription} failed with 176 * {@link EuiccService#RESULT_RESOLVABLE_ERRORS} error. 177 */ forDownloadResolvableErrors(long callingToken, DownloadableSubscription subscription, boolean switchAfterDownload, String callingPackage, int resolvableErrors)178 static EuiccOperation forDownloadResolvableErrors(long callingToken, 179 DownloadableSubscription subscription, boolean switchAfterDownload, 180 String callingPackage, int resolvableErrors) { 181 return new EuiccOperation(ACTION_DOWNLOAD_RESOLVABLE_ERRORS, callingToken, 182 subscription, 0 /* subscriptionId */, switchAfterDownload, 183 callingPackage, resolvableErrors); 184 } 185 forGetDefaultListDeactivateSim(long callingToken, String callingPackage)186 static EuiccOperation forGetDefaultListDeactivateSim(long callingToken, String callingPackage) { 187 return new EuiccOperation(ACTION_GET_DEFAULT_LIST_DEACTIVATE_SIM, callingToken, 188 null /* downloadableSubscription */, 0 /* subscriptionId */, 189 false /* switchAfterDownload */, callingPackage); 190 } 191 forSwitchDeactivateSim(long callingToken, int subscriptionId, String callingPackage)192 static EuiccOperation forSwitchDeactivateSim(long callingToken, int subscriptionId, 193 String callingPackage) { 194 return new EuiccOperation(ACTION_SWITCH_DEACTIVATE_SIM, callingToken, 195 null /* downloadableSubscription */, subscriptionId, 196 false /* switchAfterDownload */, callingPackage); 197 } 198 forSwitchNoPrivileges(long callingToken, int subscriptionId, String callingPackage)199 static EuiccOperation forSwitchNoPrivileges(long callingToken, int subscriptionId, 200 String callingPackage) { 201 return new EuiccOperation(ACTION_SWITCH_NO_PRIVILEGES, callingToken, 202 null /* downloadableSubscription */, subscriptionId, 203 false /* switchAfterDownload */, callingPackage); 204 } 205 EuiccOperation(@ction int action, long callingToken, @Nullable DownloadableSubscription downloadableSubscription, int subscriptionId, boolean switchAfterDownload, String callingPackage, int resolvableErrors)206 EuiccOperation(@Action int action, 207 long callingToken, 208 @Nullable DownloadableSubscription downloadableSubscription, 209 int subscriptionId, 210 boolean switchAfterDownload, 211 String callingPackage, 212 int resolvableErrors) { 213 mAction = action; 214 mCallingToken = callingToken; 215 mDownloadableSubscription = downloadableSubscription; 216 mSubscriptionId = subscriptionId; 217 mSwitchAfterDownload = switchAfterDownload; 218 mCallingPackage = callingPackage; 219 mResolvableErrors = resolvableErrors; 220 } 221 EuiccOperation(@ction int action, long callingToken, @Nullable DownloadableSubscription downloadableSubscription, int subscriptionId, boolean switchAfterDownload, String callingPackage)222 EuiccOperation(@Action int action, 223 long callingToken, 224 @Nullable DownloadableSubscription downloadableSubscription, 225 int subscriptionId, 226 boolean switchAfterDownload, 227 String callingPackage) { 228 mAction = action; 229 mCallingToken = callingToken; 230 mDownloadableSubscription = downloadableSubscription; 231 mSubscriptionId = subscriptionId; 232 mSwitchAfterDownload = switchAfterDownload; 233 mCallingPackage = callingPackage; 234 mResolvableErrors = 0; 235 } 236 EuiccOperation(Parcel in)237 EuiccOperation(Parcel in) { 238 mAction = in.readInt(); 239 mCallingToken = in.readLong(); 240 mDownloadableSubscription = in.readTypedObject(DownloadableSubscription.CREATOR); 241 mSubscriptionId = in.readInt(); 242 mSwitchAfterDownload = in.readBoolean(); 243 mCallingPackage = in.readString(); 244 mResolvableErrors = in.readInt(); 245 } 246 247 @Override writeToParcel(Parcel dest, int flags)248 public void writeToParcel(Parcel dest, int flags) { 249 dest.writeInt(mAction); 250 dest.writeLong(mCallingToken); 251 dest.writeTypedObject(mDownloadableSubscription, flags); 252 dest.writeInt(mSubscriptionId); 253 dest.writeBoolean(mSwitchAfterDownload); 254 dest.writeString(mCallingPackage); 255 dest.writeInt(mResolvableErrors); 256 } 257 258 /** 259 * Resume this operation based on the results of the resolution activity. 260 * 261 * @param resolutionExtras The resolution extras as provided to 262 * {@link EuiccManager#continueOperation}. 263 * @param callbackIntent The callback intent to trigger after the operation completes. 264 */ continueOperation(int cardId, Bundle resolutionExtras, PendingIntent callbackIntent)265 public void continueOperation(int cardId, Bundle resolutionExtras, 266 PendingIntent callbackIntent) { 267 // Restore the identity of the caller. We should err on the side of caution and redo any 268 // permission checks before continuing with the operation in case the caller state has 269 // changed. Resolution flows can re-clear the identity if required. 270 Binder.restoreCallingIdentity(mCallingToken); 271 272 switch (mAction) { 273 case ACTION_GET_METADATA_DEACTIVATE_SIM: 274 resolvedGetMetadataDeactivateSim(cardId, 275 resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT), 276 callbackIntent); 277 break; 278 case ACTION_DOWNLOAD_DEACTIVATE_SIM: 279 resolvedDownloadDeactivateSim(cardId, 280 resolutionExtras.getInt(EuiccService.EXTRA_RESOLUTION_PORT_INDEX, 281 TelephonyManager.DEFAULT_PORT_INDEX), 282 resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT), 283 callbackIntent); 284 break; 285 case ACTION_DOWNLOAD_NO_PRIVILEGES: 286 resolvedDownloadNoPrivileges(cardId, 287 resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT), 288 callbackIntent); 289 break; 290 case ACTION_DOWNLOAD_NO_PRIVILEGES_OR_DEACTIVATE_SIM_CHECK_METADATA: 291 resolvedDownloadNoPrivilegesOrDeactivateSimCheckMetadata(cardId, 292 resolutionExtras.getInt(EuiccService.EXTRA_RESOLUTION_PORT_INDEX, 293 TelephonyManager.DEFAULT_PORT_INDEX), 294 resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT), 295 callbackIntent); 296 break; 297 case ACTION_DOWNLOAD_CONFIRMATION_CODE: // Deprecated case 298 resolvedDownloadConfirmationCode(cardId, 299 resolutionExtras.getString(EuiccService.EXTRA_RESOLUTION_CONFIRMATION_CODE), 300 callbackIntent); 301 break; 302 case ACTION_DOWNLOAD_RESOLVABLE_ERRORS: 303 resolvedDownloadResolvableErrors(cardId, resolutionExtras, callbackIntent); 304 break; 305 case ACTION_GET_DEFAULT_LIST_DEACTIVATE_SIM: 306 resolvedGetDefaultListDeactivateSim(cardId, 307 resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT), 308 callbackIntent); 309 break; 310 case ACTION_SWITCH_DEACTIVATE_SIM: { 311 // get portIndex from original operation 312 final int portIndex = resolutionExtras.getInt( 313 EuiccService.EXTRA_RESOLUTION_PORT_INDEX, 314 0); 315 // get whether legacy API was called from original operation 316 final boolean usePortIndex = resolutionExtras.getBoolean( 317 EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, 318 false); 319 resolvedSwitchDeactivateSim(cardId, portIndex, 320 resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT), 321 callbackIntent, usePortIndex); 322 break; 323 } 324 case ACTION_SWITCH_NO_PRIVILEGES: { 325 // get portIndex from original operation 326 final int portIndex = resolutionExtras.getInt( 327 EuiccService.EXTRA_RESOLUTION_PORT_INDEX, 328 0); 329 // get whether port index was passed in from original operation 330 final boolean usePortIndex = resolutionExtras.getBoolean( 331 EuiccService.EXTRA_RESOLUTION_USE_PORT_INDEX, 332 false); 333 resolvedSwitchNoPrivileges(cardId, portIndex, 334 resolutionExtras.getBoolean(EuiccService.EXTRA_RESOLUTION_CONSENT), 335 callbackIntent, usePortIndex); 336 break; 337 } 338 default: 339 Log.wtf(TAG, "Unknown action: " + mAction); 340 break; 341 } 342 } 343 resolvedGetMetadataDeactivateSim(int cardId, boolean consent, PendingIntent callbackIntent)344 private void resolvedGetMetadataDeactivateSim(int cardId, boolean consent, 345 PendingIntent callbackIntent) { 346 if (consent) { 347 // User has consented; perform the lookup, but this time, tell the LPA to deactivate any 348 // required active SIMs. 349 EuiccController.get().getDownloadableSubscriptionMetadata( 350 cardId, 351 mDownloadableSubscription, 352 true /* forceDeactivateSim */, 353 mCallingPackage, 354 callbackIntent); 355 } else { 356 // User has not consented; fail the operation. 357 fail(callbackIntent); 358 } 359 } 360 resolvedDownloadDeactivateSim(int cardId, int portIndex, boolean consent, PendingIntent callbackIntent)361 private void resolvedDownloadDeactivateSim(int cardId, int portIndex, boolean consent, 362 PendingIntent callbackIntent) { 363 if (consent) { 364 // User has consented; perform the download, but this time, tell the LPA to deactivate 365 // any required active SIMs. 366 EuiccController.get().downloadSubscription( 367 cardId, 368 portIndex, 369 mDownloadableSubscription, 370 mSwitchAfterDownload, 371 mCallingPackage, 372 true /* forceDeactivateSim */, 373 null /* resolvedBundle */, 374 callbackIntent); 375 } else { 376 // User has not consented; fail the operation. 377 fail(callbackIntent); 378 } 379 } 380 resolvedDownloadNoPrivileges(int cardId, boolean consent, PendingIntent callbackIntent)381 private void resolvedDownloadNoPrivileges(int cardId, boolean consent, 382 PendingIntent callbackIntent) { 383 if (consent) { 384 // User has consented; perform the download with full privileges. 385 long token = Binder.clearCallingIdentity(); 386 try { 387 // Note: We turn on "forceDeactivateSim" here under the assumption that the 388 // privilege prompt should also cover permission to deactivate an active SIM, as 389 // the privilege prompt makes it clear that we're switching from the current 390 // carrier. 391 // Action {@link #ACTION_DOWNLOAD_NO_PRIVILEGES} is no more used in platform,this 392 // method will never get called, pass {@link TelephonyManager#DEFAULT_PORT_INDEX} 393 // as portIndex. 394 EuiccController.get().downloadSubscriptionPrivileged( 395 cardId, 396 TelephonyManager.DEFAULT_PORT_INDEX, 397 token, 398 mDownloadableSubscription, 399 mSwitchAfterDownload, 400 true /* forceDeactivateSim */, 401 mCallingPackage, 402 null /* resolvedBundle */, 403 callbackIntent); 404 } finally { 405 Binder.restoreCallingIdentity(token); 406 } 407 } else { 408 // User has not consented; fail the operation. 409 fail(callbackIntent); 410 } 411 } 412 resolvedDownloadNoPrivilegesOrDeactivateSimCheckMetadata(int cardId, int portIndex, boolean consent, PendingIntent callbackIntent)413 private void resolvedDownloadNoPrivilegesOrDeactivateSimCheckMetadata(int cardId, 414 int portIndex, boolean consent, PendingIntent callbackIntent) { 415 if (consent) { 416 // User has consented; perform the download with full privileges. 417 long token = Binder.clearCallingIdentity(); 418 try { 419 // Note: We turn on "forceDeactivateSim" here under the assumption that the 420 // privilege prompt should also cover permission to deactivate an active SIM, as 421 // the privilege prompt makes it clear that we're switching from the current 422 // carrier. 423 EuiccController.get().downloadSubscriptionPrivilegedCheckMetadata( 424 cardId, 425 portIndex, 426 token, 427 mDownloadableSubscription, 428 mSwitchAfterDownload, 429 true /* forceDeactivateSim */, 430 mCallingPackage, 431 null /* resolvedBundle */, 432 callbackIntent); 433 } finally { 434 Binder.restoreCallingIdentity(token); 435 } 436 } else { 437 // User has not consented; fail the operation. 438 fail(callbackIntent); 439 } 440 } 441 442 /** 443 * @deprecated The resolvable errors in download step are solved by 444 * {@link #resolvedDownloadResolvableErrors(Bundle, PendingIntent)} from Q. 445 */ 446 @Deprecated resolvedDownloadConfirmationCode(int cardId, String confirmationCode, PendingIntent callbackIntent)447 private void resolvedDownloadConfirmationCode(int cardId, String confirmationCode, 448 PendingIntent callbackIntent) { 449 if (TextUtils.isEmpty(confirmationCode)) { 450 fail(callbackIntent); 451 } else { 452 mDownloadableSubscription.setConfirmationCode(confirmationCode); 453 // Action {@link #ACTION_DOWNLOAD_CONFIRMATION_CODE} is not any more used from LPA with 454 // targetSDK >=Q, pass {@link TelephonyManager#DEFAULT_PORT_INDEX} as portIndex. 455 EuiccController.get().downloadSubscription( 456 cardId, 457 TelephonyManager.DEFAULT_PORT_INDEX, 458 mDownloadableSubscription, 459 mSwitchAfterDownload, 460 mCallingPackage, 461 true /* forceDeactivateSim */, 462 null, 463 callbackIntent); 464 } 465 } 466 resolvedDownloadResolvableErrors(int cardId, Bundle resolvedBundle, PendingIntent callbackIntent)467 private void resolvedDownloadResolvableErrors(int cardId, Bundle resolvedBundle, 468 PendingIntent callbackIntent) { 469 boolean pass = true; 470 String confirmationCode = null; 471 if ((mResolvableErrors & EuiccService.RESOLVABLE_ERROR_POLICY_RULES) != 0) { 472 if (!resolvedBundle.getBoolean(EuiccService.EXTRA_RESOLUTION_ALLOW_POLICY_RULES)) { 473 pass = false; 474 } 475 } 476 if ((mResolvableErrors & EuiccService.RESOLVABLE_ERROR_CONFIRMATION_CODE) != 0) { 477 confirmationCode = resolvedBundle.getString( 478 EuiccService.EXTRA_RESOLUTION_CONFIRMATION_CODE); 479 // The check here just makes sure the entered confirmation code is non-empty. The actual 480 // check to valid the confirmation code is done by LPA on the ensuing download attemp. 481 if (TextUtils.isEmpty(confirmationCode)) { 482 pass = false; 483 } 484 } 485 486 if (!pass) { 487 fail(callbackIntent); 488 } else { 489 mDownloadableSubscription.setConfirmationCode(confirmationCode); 490 EuiccController.get().downloadSubscription( 491 cardId, 492 resolvedBundle.getInt(EuiccService.EXTRA_RESOLUTION_PORT_INDEX, 493 TelephonyManager.DEFAULT_PORT_INDEX), 494 mDownloadableSubscription, 495 mSwitchAfterDownload, 496 mCallingPackage, 497 true /* forceDeactivateSim */, 498 resolvedBundle, 499 callbackIntent); 500 } 501 } 502 resolvedGetDefaultListDeactivateSim(int cardId, boolean consent, PendingIntent callbackIntent)503 private void resolvedGetDefaultListDeactivateSim(int cardId, boolean consent, 504 PendingIntent callbackIntent) { 505 if (consent) { 506 // User has consented; perform the lookup, but this time, tell the LPA to deactivate any 507 // required active SIMs. 508 EuiccController.get().getDefaultDownloadableSubscriptionList( 509 cardId, 510 true /* forceDeactivateSim */, 511 mCallingPackage, 512 callbackIntent); 513 } else { 514 // User has not consented; fail the operation. 515 fail(callbackIntent); 516 } 517 } 518 resolvedSwitchDeactivateSim(int cardId, int portIndex, boolean consent, PendingIntent callbackIntent, boolean usePortIndex)519 private void resolvedSwitchDeactivateSim(int cardId, int portIndex, boolean consent, 520 PendingIntent callbackIntent, boolean usePortIndex) { 521 if (consent) { 522 // User has consented; perform the switch, but this time, tell the LPA to deactivate any 523 // required active SIMs. 524 EuiccController euiccController = EuiccController.get(); 525 euiccController.switchToSubscription( 526 cardId, 527 mSubscriptionId, 528 portIndex, 529 true /* forceDeactivateSim */, 530 mCallingPackage, 531 callbackIntent, 532 usePortIndex); 533 } else { 534 // User has not consented; fail the operation. 535 fail(callbackIntent); 536 } 537 } 538 resolvedSwitchNoPrivileges(int cardId, int portIndex, boolean consent, PendingIntent callbackIntent, boolean usePortIndex)539 private void resolvedSwitchNoPrivileges(int cardId, int portIndex, boolean consent, 540 PendingIntent callbackIntent, boolean usePortIndex) { 541 if (consent) { 542 // User has consented; perform the switch with full privileges. 543 long token = Binder.clearCallingIdentity(); 544 try { 545 // Note: We turn on "forceDeactivateSim" here under the assumption that the 546 // privilege prompt should also cover permission to deactivate an active SIM, as 547 // the privilege prompt makes it clear that we're switching from the current 548 // carrier. Also note that in practice, we'd need to deactivate the active SIM to 549 // even reach this point, because we cannot fetch the metadata needed to check the 550 // privileges without doing so. 551 EuiccController euiccController = EuiccController.get(); 552 euiccController.switchToSubscriptionPrivileged( 553 cardId, 554 portIndex, 555 token, 556 mSubscriptionId, 557 true /* forceDeactivateSim */, 558 mCallingPackage, 559 callbackIntent, 560 usePortIndex); 561 } finally { 562 Binder.restoreCallingIdentity(token); 563 } 564 } else { 565 // User has not consented; fail the operation. 566 fail(callbackIntent); 567 } 568 } 569 fail(PendingIntent callbackIntent)570 private static void fail(PendingIntent callbackIntent) { 571 EuiccController.get().sendResult( 572 callbackIntent, 573 EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR, 574 null /* extrasIntent */); 575 } 576 577 @Override describeContents()578 public int describeContents() { 579 return 0; 580 } 581 } 582