EuiccController.java revision 80fc6417014d6a884b009557fd7d19861a1087ab
1277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson/* 2277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * Copyright (C) 2017 The Android Open Source Project 3277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * 4277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * Licensed under the Apache License, Version 2.0 (the "License"); 5277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * you may not use this file except in compliance with the License. 6277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * You may obtain a copy of the License at 7277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * 8277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * http://www.apache.org/licenses/LICENSE-2.0 9277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * 10277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * Unless required by applicable law or agreed to in writing, software 11277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * distributed under the License is distributed on an "AS IS" BASIS, 12277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * See the License for the specific language governing permissions and 14277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * limitations under the License. 15277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson */ 16277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonpackage com.android.internal.telephony.euicc; 17277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 18277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.Manifest; 19277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.annotation.Nullable; 2008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidsonimport android.app.AppOpsManager; 21277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.app.PendingIntent; 22277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.content.Context; 23277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.content.Intent; 2408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidsonimport android.content.pm.PackageInfo; 25277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.content.pm.PackageManager; 26277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.os.Binder; 27953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidsonimport android.os.Bundle; 28277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.os.ServiceManager; 294f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidsonimport android.provider.Settings; 30953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidsonimport android.service.euicc.EuiccService; 318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidsonimport android.service.euicc.GetDefaultDownloadableSubscriptionListResult; 32277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.service.euicc.GetDownloadableSubscriptionMetadataResult; 33dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport android.service.euicc.GetEuiccProfileInfoListResult; 34dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport android.telephony.SubscriptionInfo; 35dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport android.telephony.SubscriptionManager; 36277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.telephony.TelephonyManager; 3708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidsonimport android.telephony.UiccAccessRule; 38277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.telephony.euicc.DownloadableSubscription; 398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidsonimport android.telephony.euicc.EuiccInfo; 40277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.telephony.euicc.EuiccManager; 41277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.util.Log; 42277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 43277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport com.android.internal.annotations.VisibleForTesting; 44dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport com.android.internal.telephony.SubscriptionController; 45277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 46277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport java.io.FileDescriptor; 47277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport java.io.PrintWriter; 48dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport java.util.List; 49277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport java.util.concurrent.CountDownLatch; 50277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport java.util.concurrent.atomic.AtomicReference; 51277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 52277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson/** Backing implementation of {@link android.telephony.euicc.EuiccManager}. */ 53277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonpublic class EuiccController extends IEuiccController.Stub { 54277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private static final String TAG = "EuiccController"; 55277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 56953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson /** Extra set on resolution intents containing the {@link EuiccOperation}. */ 57953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @VisibleForTesting 58953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson static final String EXTRA_OPERATION = "operation"; 59953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 6008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // Aliases so line lengths stay short. 6108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private static final int OK = EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK; 6208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private static final int RESOLVABLE_ERROR = 6308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR; 6431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson private static final int ERROR = 6531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR; 6608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 67277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private static EuiccController sInstance; 68277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 69277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private final Context mContext; 70277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private final EuiccConnector mConnector; 71dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson private final SubscriptionManager mSubscriptionManager; 7208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private final AppOpsManager mAppOpsManager; 7308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private final PackageManager mPackageManager; 74277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 75277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** Initialize the instance. Should only be called once. */ 76277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public static EuiccController init(Context context) { 77277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson synchronized (EuiccController.class) { 78277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (sInstance == null) { 79277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson sInstance = new EuiccController(context); 80277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } else { 81277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance); 82277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 83277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 84277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return sInstance; 85277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 86277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 87277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** Get an instance. Assumes one has already been initialized with {@link #init}. */ 88277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public static EuiccController get() { 89277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (sInstance == null) { 90277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson synchronized (EuiccController.class) { 91277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (sInstance == null) { 92277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson throw new IllegalStateException("get() called before init()"); 93277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 94277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 95277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 96277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return sInstance; 97277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 98277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 99277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private EuiccController(Context context) { 100277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson this(context, new EuiccConnector(context)); 101277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson ServiceManager.addService("econtroller", this); 102277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 103277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 104277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @VisibleForTesting 105277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public EuiccController(Context context, EuiccConnector connector) { 106277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mContext = context; 107277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mConnector = connector; 108dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson mSubscriptionManager = (SubscriptionManager) 109dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 11008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 11108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mPackageManager = context.getPackageManager(); 112277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 113277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 114277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** 115953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * Continue an operation which failed with a user-resolvable error. 116953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * 117953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * <p>The implementation here makes a key assumption that the resolutionIntent has not been 118953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * tampered with. This is guaranteed because: 119953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * <UL> 120953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * <LI>The intent is wrapped in a PendingIntent created by the phone process which is created 121953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * with {@link #EXTRA_OPERATION} already present. This means that the operation cannot be 122953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * overridden on the PendingIntent - a caller can only add new extras. 123953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * <LI>The resolution activity is restricted by a privileged permission; unprivileged apps 124953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * cannot start it directly. So the PendingIntent is the only way to start it. 125953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * </UL> 126953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson */ 127953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @Override 128953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) { 129953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 130953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson throw new SecurityException( 131953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to continue operation"); 132953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 133953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson long token = Binder.clearCallingIdentity(); 134953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson try { 135953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccOperation op = resolutionIntent.getParcelableExtra(EXTRA_OPERATION); 136953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson if (op == null) { 137953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson throw new IllegalArgumentException("Invalid resolution intent"); 138953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 139953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 140953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent callbackIntent = 141953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson resolutionIntent.getParcelableExtra( 142953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT); 143953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson op.continueOperation(resolutionExtras, callbackIntent); 144953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } finally { 145953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson Binder.restoreCallingIdentity(token); 146953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 147953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 148953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 149953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson /** 150277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * Return the EID. 151277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * 152277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 153277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * that IPC should generally be fast, and the EID shouldn't be needed in the normal course of 154277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * operation. 155277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson */ 156277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 157277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public String getEid() { 158277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (!callerCanReadPhoneStatePrivileged() 159277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson && !callerHasCarrierPrivilegesForActiveSubscription()) { 160277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson throw new SecurityException( 161277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson "Must have carrier privileges on active subscription to read EID"); 162277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 163277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson long token = Binder.clearCallingIdentity(); 164277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 165277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return blockingGetEidFromEuiccService(); 166277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 167277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 168277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 169277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 170277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 171277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 172277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription, 1739af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, PendingIntent callbackIntent) { 174953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson getDownloadableSubscriptionMetadata( 1759af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson subscription, false /* forceDeactivateSim */, callingPackage, callbackIntent); 176953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 177953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 178953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription, 1799af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 180277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 181277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get metadata"); 182277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 1839af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 184277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson long token = Binder.clearCallingIdentity(); 185277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 18608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mConnector.getDownloadableSubscriptionMetadata( 187953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson subscription, forceDeactivateSim, 1889af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson new GetMetadataCommandCallback( 1899af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson token, subscription, callingPackage, callbackIntent)); 190277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 191277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 192277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 193277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 194277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 19508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson class GetMetadataCommandCallback implements EuiccConnector.GetMetadataCommandCallback { 196953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson protected final long mCallingToken; 197953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson protected final DownloadableSubscription mSubscription; 1989af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson protected final String mCallingPackage; 19908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson protected final PendingIntent mCallbackIntent; 20008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 201953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson GetMetadataCommandCallback( 202953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson long callingToken, 203953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson DownloadableSubscription subscription, 2049af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, 205953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent callbackIntent) { 206953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mCallingToken = callingToken; 207953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mSubscription = subscription; 2089af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage = callingPackage; 20908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mCallbackIntent = callbackIntent; 21008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 21108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 21208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 21308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onGetMetadataComplete( 21408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson GetDownloadableSubscriptionMetadataResult result) { 21508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Intent extrasIntent = new Intent(); 21608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson final int resultCode; 21708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson switch (result.result) { 21831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 21908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson resultCode = OK; 22008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson extrasIntent.putExtra( 22108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION, 22208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson result.subscription); 22308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 22431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 22508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson resultCode = RESOLVABLE_ERROR; 226953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson addResolutionIntent(extrasIntent, 227953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 2289af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 229953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson getOperationForDeactivateSim()); 23008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 23131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 23231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 23308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson extrasIntent.putExtra( 23408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 23531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result.result); 23608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 23708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 23808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 23908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson sendResult(mCallbackIntent, resultCode, extrasIntent); 24008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 24108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 24208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 24308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onEuiccServiceUnavailable() { 24431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 24508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 246953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 247953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson protected EuiccOperation getOperationForDeactivateSim() { 2489af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson return EuiccOperation.forGetMetadataDeactivateSim( 2499af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingToken, mSubscription, mCallingPackage); 250953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 25108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 25208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 253277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 254277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void downloadSubscription(DownloadableSubscription subscription, 25508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson boolean switchAfterDownload, String callingPackage, PendingIntent callbackIntent) { 256953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson downloadSubscription(subscription, switchAfterDownload, callingPackage, 257953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson false /* forceDeactivateSim */, callbackIntent); 258953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 259953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 260953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson void downloadSubscription(DownloadableSubscription subscription, 261953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, 262953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent callbackIntent) { 26308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 26408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 26508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 266277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson long token = Binder.clearCallingIdentity(); 267277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 26808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson if (callerCanWriteEmbeddedSubscriptions) { 26908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // With WRITE_EMBEDDED_SUBSCRIPTIONS, we can skip profile-specific permission checks 27008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // and move straight to the profile download. 271953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson downloadSubscriptionPrivileged(token, subscription, switchAfterDownload, 272953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson forceDeactivateSim, callingPackage, callbackIntent); 27308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 27408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 27508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // Without WRITE_EMBEDDED_SUBSCRIPTIONS, the caller *must* be whitelisted per the 27608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // metadata of the profile to be downloaded, so check the metadata first. 27708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mConnector.getDownloadableSubscriptionMetadata(subscription, 278953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson forceDeactivateSim, 279953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson new DownloadSubscriptionGetMetadataCommandCallback(token, subscription, 280953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson switchAfterDownload, callingPackage, forceDeactivateSim, 281953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson callbackIntent)); 282277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 283277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 284277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 285277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 286277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 28708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson class DownloadSubscriptionGetMetadataCommandCallback extends GetMetadataCommandCallback { 28808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private final boolean mSwitchAfterDownload; 289953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson private final boolean mForceDeactivateSim; 29008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 291953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson DownloadSubscriptionGetMetadataCommandCallback(long callingToken, 292953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson DownloadableSubscription subscription, boolean switchAfterDownload, 293953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson String callingPackage, boolean forceDeactivateSim, 294953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent callbackIntent) { 2959af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson super(callingToken, subscription, callingPackage, callbackIntent); 29608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mSwitchAfterDownload = switchAfterDownload; 297953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mForceDeactivateSim = forceDeactivateSim; 29808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 29908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 30008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 30108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onGetMetadataComplete( 30208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson GetDownloadableSubscriptionMetadataResult result) { 3039af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson if (result.result == EuiccService.RESULT_MUST_DEACTIVATE_SIM) { 3049af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson // If we need to deactivate the current SIM to even check permissions, go ahead and 3059af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson // require that the user resolve the stronger permission dialog. 3069af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson Intent extrasIntent = new Intent(); 3079af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 3089af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 3099af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson EuiccOperation.forDownloadNoPrivileges( 3109af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingToken, mSubscription, mSwitchAfterDownload, 3119af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage)); 3129af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson sendResult(mCallbackIntent, RESOLVABLE_ERROR, extrasIntent); 3139af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson return; 3149af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson } 3159af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson 31631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson if (result.result != EuiccService.RESULT_OK) { 31708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // Just propagate the error as normal. 31808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson super.onGetMetadataComplete(result); 31908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 32008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 32108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 32208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson DownloadableSubscription subscription = result.subscription; 32308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson UiccAccessRule[] rules = subscription.getAccessRules(); 32408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson if (rules == null) { 32508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Log.e(TAG, "No access rules but caller is unprivileged"); 32631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 32708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 32808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 32908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 33008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson final PackageInfo info; 33108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson try { 33208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson info = mPackageManager.getPackageInfo( 33308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mCallingPackage, PackageManager.GET_SIGNATURES); 33408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } catch (PackageManager.NameNotFoundException e) { 33508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Log.e(TAG, "Calling package valid but gone"); 33631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 33708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 33808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 33908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 34008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson for (int i = 0; i < rules.length; i++) { 34108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson if (rules[i].getCarrierPrivilegeStatus(info) 34208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 343dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // Caller can download this profile. Now, determine whether the caller can also 344dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // manage the current profile; if so, we can perform the download silently; if 345dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // not, the user must provide consent. 3468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (canManageActiveSubscription(mCallingPackage)) { 3478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson downloadSubscriptionPrivileged( 3488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingToken, subscription, mSwitchAfterDownload, 3498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mForceDeactivateSim, mCallingPackage, mCallbackIntent); 3508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 35108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 352dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson 353dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // Switch might still be permitted, but the user must consent first. 354dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson Intent extrasIntent = new Intent(); 355dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 3569af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 357dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson EuiccOperation.forDownloadNoPrivileges( 3588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingToken, subscription, mSwitchAfterDownload, 3598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingPackage)); 360dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson sendResult(mCallbackIntent, RESOLVABLE_ERROR, extrasIntent); 36108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 36208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 36308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 36408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Log.e(TAG, "Caller is not permitted to download this profile"); 36531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 36608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 367953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 368953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @Override 369953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson protected EuiccOperation getOperationForDeactivateSim() { 370953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson return EuiccOperation.forDownloadDeactivateSim( 371953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mCallingToken, mSubscription, mSwitchAfterDownload, mCallingPackage); 372953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 37308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 37408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 375953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson void downloadSubscriptionPrivileged(final long callingToken, 376953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson DownloadableSubscription subscription, boolean switchAfterDownload, 377953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson boolean forceDeactivateSim, final String callingPackage, 378953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson final PendingIntent callbackIntent) { 379953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mConnector.downloadSubscription( 380953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson subscription, 381953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson switchAfterDownload, 382953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson forceDeactivateSim, 38308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson new EuiccConnector.DownloadCommandCallback() { 38408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 38531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onDownloadComplete(int result) { 38608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Intent extrasIntent = new Intent(); 38708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson final int resultCode; 38831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 38931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 39008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson resultCode = OK; 3914f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson // Now that a profile has been successfully downloaded, mark the 3924f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson // eUICC as provisioned so it appears in settings UI as appropriate. 3934f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson Settings.Global.putInt( 3944f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson mContext.getContentResolver(), 3954f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson Settings.Global.EUICC_PROVISIONED, 3964f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson 1); 397dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson if (!switchAfterDownload) { 398dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // Since we're not switching, nothing will trigger a 399dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // subscription list refresh on its own, so request one here. 400d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson refreshSubscriptionsAndSendResult( 401d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson callbackIntent, resultCode, extrasIntent); 402d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson return; 403dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 40408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 40531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 40608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson resultCode = RESOLVABLE_ERROR; 407953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson addResolutionIntent(extrasIntent, 408953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 4099af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson callingPackage, 410953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccOperation.forDownloadDeactivateSim( 411953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson callingToken, subscription, switchAfterDownload, 412953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson callingPackage)); 41308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 41480fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun case EuiccService.RESULT_NEED_CONFIRMATION_CODE: 41580fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun resultCode = RESOLVABLE_ERROR; 41680fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun addResolutionIntent(extrasIntent, 41780fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun EuiccService.ACTION_RESOLVE_CONFIRMATION_CODE, 41880fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun callingPackage, 41980fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun EuiccOperation.forDownloadConfirmationCode( 42080fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun callingToken, subscription, switchAfterDownload, 42180fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun callingPackage)); 42280fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun break; 42331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 42431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 42508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson extrasIntent.putExtra( 42608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 42731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 42808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 42908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 43008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 43108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 43208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 43308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 43408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 43508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onEuiccServiceUnavailable() { 43631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 43708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 43808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson }); 43908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 44008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 441dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson /** 442dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * Blocking call to {@link EuiccService#onGetEuiccProfileInfoList}. 443dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * 444dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * <p>Does not perform permission checks as this is not an exposed API and is only used within 445dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * the phone process. 446dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson */ 447dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public GetEuiccProfileInfoListResult blockingGetEuiccProfileInfoList() { 448dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson final CountDownLatch latch = new CountDownLatch(1); 449dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson final AtomicReference<GetEuiccProfileInfoListResult> resultRef = new AtomicReference<>(); 450dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson mConnector.getEuiccProfileInfoList( 451dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson new EuiccConnector.GetEuiccProfileInfoListCommandCallback() { 452dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson @Override 453dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public void onListComplete(GetEuiccProfileInfoListResult result) { 454dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson resultRef.set(result); 455dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.countDown(); 456dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 457dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson 458dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson @Override 459dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public void onEuiccServiceUnavailable() { 460dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.countDown(); 461dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 462dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson }); 463dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson try { 464dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.await(); 465dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } catch (InterruptedException e) { 466dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson Thread.currentThread().interrupt(); 467dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 468dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson return resultRef.get(); 469dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 470dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson 4718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 4729af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson public void getDefaultDownloadableSubscriptionList( 4739af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, PendingIntent callbackIntent) { 4749af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson getDefaultDownloadableSubscriptionList( 4759af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson false /* forceDeactivateSim */, callingPackage, callbackIntent); 4768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 4788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void getDefaultDownloadableSubscriptionList( 4799af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 4808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 4818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 4828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get default list"); 4838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4849af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 4858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 4868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 4878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.getDefaultDownloadableSubscriptionList( 4889af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson forceDeactivateSim, new GetDefaultListCommandCallback( 4899af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson token, callingPackage, callbackIntent)); 4908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 4918f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 4928f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4948f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 4958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson class GetDefaultListCommandCallback implements EuiccConnector.GetDefaultListCommandCallback { 4969af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final long mCallingToken; 4979af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final String mCallingPackage; 4989af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final PendingIntent mCallbackIntent; 4998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5009af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson GetDefaultListCommandCallback(long callingToken, String callingPackage, 5019af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson PendingIntent callbackIntent) { 5028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingToken = callingToken; 5039af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage = callingPackage; 5048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallbackIntent = callbackIntent; 5058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5078f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onGetDefaultListComplete(GetDefaultDownloadableSubscriptionListResult result) { 5098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 5108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 5118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switch (result.result) { 51231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 5138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 5148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 5158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS, 5168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson result.subscriptions); 5178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 51831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 5198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = RESOLVABLE_ERROR; 5208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 5218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 5229af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 5239af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson EuiccOperation.forGetDefaultListDeactivateSim( 5249af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingToken, mCallingPackage)); 5258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 52631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 52731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 5288f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 5298f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 53031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result.result); 5318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 5328f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(mCallbackIntent, resultCode, extrasIntent); 5358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5368f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5378f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 53931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 5408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson /** 5448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * Return the {@link EuiccInfo}. 5458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * 5468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 5478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * that IPC should generally be fast, and this info shouldn't be needed in the normal course of 5488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * operation. 5498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson */ 5508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public EuiccInfo getEuiccInfo() { 5528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // No permissions required as EuiccInfo is not sensitive. 5538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 5548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 5558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return blockingGetEuiccInfoFromEuiccService(); 5568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 5578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 5588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void deleteSubscription(int subscriptionId, String callingPackage, 5638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 5648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 5658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 5668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 5688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 5698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 5708f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 5718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot delete nonexistent subscription: " + subscriptionId); 57231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 5738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 5748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 5778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson && !sub.canManageSubscription(mContext, callingPackage)) { 5788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "No permissions: " + subscriptionId); 57931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 5808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 5818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson deleteSubscriptionPrivileged(sub.getIccId(), callbackIntent); 5848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 5858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 5868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5888f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5898f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void deleteSubscriptionPrivileged(String iccid, final PendingIntent callbackIntent) { 5908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.deleteSubscription( 5918f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid, 5928f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.DeleteCommandCallback() { 5938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 59431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onDeleteComplete(int result) { 5958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 5968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 59731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 59831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 5998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 600d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson refreshSubscriptionsAndSendResult( 601d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson callbackIntent, resultCode, extrasIntent); 602d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson return; 60331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 60431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 6058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 6068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 60731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 6088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 6098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 6128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 61631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6188f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 6198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6228f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void switchToSubscription(int subscriptionId, String callingPackage, 6238f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 6248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscription( 6258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson subscriptionId, false /* forceDeactivateSim */, callingPackage, callbackIntent); 6268f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6278f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6288f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscription(int subscriptionId, boolean forceDeactivateSim, String callingPackage, 6298f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 6308f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 6318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 6328f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 6348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 6352938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson if (callerCanWriteEmbeddedSubscriptions) { 6362938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // Assume that if a privileged caller is calling us, we don't need to prompt the 6372938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // user about changing carriers, because the caller would only be acting in response 6382938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // to user action. 6392938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson forceDeactivateSim = true; 6402938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson } 6412938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson 6428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final String iccid; 6438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 6448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // Switch to "no" subscription. Only the system can do this. 6458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions) { 6468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Not permitted to switch to empty subscription"); 64731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = null; 6518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } else { 6528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 6538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 6548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot switch to nonexistent subscription: " + subscriptionId); 65531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 6598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson && !sub.canManageSubscription(mContext, callingPackage)) { 6608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Not permitted to switch to subscription: " + subscriptionId); 66131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = sub.getIccId(); 6658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 6688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson && !canManageActiveSubscription(callingPackage)) { 6698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // Switch needs consent. 6708f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 6718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 6728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 6739af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson callingPackage, 6748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccOperation.forSwitchNoPrivileges( 6758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson token, subscriptionId, callingPackage)); 6768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, RESOLVABLE_ERROR, extrasIntent); 6778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6798f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscriptionPrivileged(token, subscriptionId, iccid, forceDeactivateSim, 6818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingPackage, callbackIntent); 6828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 6838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 6848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscriptionPrivileged(final long callingToken, int subscriptionId, 6888f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean forceDeactivateSim, final String callingPackage, 6898f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final PendingIntent callbackIntent) { 6908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson String iccid = null; 6918f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 6928f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub != null) { 6938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = sub.getIccId(); 6948f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscriptionPrivileged(callingToken, subscriptionId, iccid, forceDeactivateSim, 6968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingPackage, callbackIntent); 6978f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6988f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscriptionPrivileged(final long callingToken, int subscriptionId, 7008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable String iccid, boolean forceDeactivateSim, final String callingPackage, 7018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final PendingIntent callbackIntent) { 7028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.switchToSubscription( 7038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid, 7048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson forceDeactivateSim, 7058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.SwitchCommandCallback() { 7068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 70731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onSwitchComplete(int result) { 7088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 7098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 71031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 71131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 7128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 7138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 71431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 7158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = RESOLVABLE_ERROR; 7168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 7178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 7189af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson callingPackage, 7198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccOperation.forSwitchDeactivateSim( 7208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingToken, subscriptionId, callingPackage)); 7218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 72231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 72331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 7248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 7258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 72631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 7278f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 7288f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7298f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7308f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 7318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7328f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 7348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 73531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7368f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7378f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 7388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 7418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void updateSubscriptionNickname(int subscriptionId, String nickname, 7428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 7438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 7448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 7458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to update nickname"); 7468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 7488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 7498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 7508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 7518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot update nickname to nonexistent subscription: " + subscriptionId); 75231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 7548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.updateSubscriptionNickname( 7568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sub.getIccId(), nickname, 7578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.UpdateNicknameCommandCallback() { 7588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 75931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onUpdateNicknameComplete(int result) { 7608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 7618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 76231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 76331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 7648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 7658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 76631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 76731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 7688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 7698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 77031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 7718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 7728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 7758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 7788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 77931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 7828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 7838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 7848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 7888f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void eraseSubscriptions(PendingIntent callbackIntent) { 7898f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 7908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 7918f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to erase subscriptions"); 7928f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 7948f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 7958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.eraseSubscriptions(new EuiccConnector.EraseCommandCallback() { 7968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 79731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onEraseComplete(int result) { 7988f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 7998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 80031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 80131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 8028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 803d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson refreshSubscriptionsAndSendResult( 804d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson callbackIntent, resultCode, extrasIntent); 805d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson return; 80631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 80731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 8088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 8098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 81031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 8118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 8128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 8158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 8188f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 81931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 8208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 8228f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 8238f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 8248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8268f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 827a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 828a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void retainSubscriptionsForFactoryReset(PendingIntent callbackIntent) { 829a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson mContext.enforceCallingPermission(Manifest.permission.MASTER_CLEAR, 830a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson "Must have MASTER_CLEAR to retain subscriptions for factory reset"); 831a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson long token = Binder.clearCallingIdentity(); 832a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson try { 833a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson mConnector.retainSubscriptions( 834a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson new EuiccConnector.RetainSubscriptionsCommandCallback() { 835a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 836a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void onRetainSubscriptionsComplete(int result) { 837a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson Intent extrasIntent = new Intent(); 838a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson final int resultCode; 839a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson switch (result) { 840a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson case EuiccService.RESULT_OK: 841a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson resultCode = OK; 842a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson break; 843a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson default: 844a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson resultCode = ERROR; 845a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson extrasIntent.putExtra( 846a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 847a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson result); 848a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson break; 849a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 850a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 851a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 852a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 853a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 854a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 855a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void onEuiccServiceUnavailable() { 856a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 857a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 858a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson }); 859a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } finally { 860a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson Binder.restoreCallingIdentity(token); 861a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 862a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 863a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 864d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson /** Refresh the embedded subscription list and dispatch the given result upon completion. */ 865d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 866d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson public void refreshSubscriptionsAndSendResult( 867d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 868d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson SubscriptionController.getInstance() 869d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson .requestEmbeddedSubscriptionInfoListRefresh( 870d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson () -> sendResult(callbackIntent, resultCode, extrasIntent)); 871d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson } 8728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 873fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson /** Dispatch the given callback intent with the given result code and data. */ 874fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 875fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson public void sendResult(PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 876277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 877277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson callbackIntent.send(mContext, resultCode, extrasIntent); 878277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } catch (PendingIntent.CanceledException e) { 879277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson // Caller canceled the callback; do nothing. 880277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 881277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 882277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 883953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson /** Add a resolution intent to the given extras intent. */ 884953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 885953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson public void addResolutionIntent(Intent extrasIntent, String resolutionAction, 8869af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, EuiccOperation op) { 887953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson Intent intent = new Intent(EuiccManager.ACTION_RESOLVE_ERROR); 888953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION, 889953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson resolutionAction); 8909af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson intent.putExtra(EuiccService.EXTRA_RESOLUTION_CALLING_PACKAGE, callingPackage); 891953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson intent.putExtra(EXTRA_OPERATION, op); 892953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent resolutionIntent = PendingIntent.getActivity( 893953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_ONE_SHOT); 894953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson extrasIntent.putExtra( 895953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT, resolutionIntent); 896953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 897953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 898277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 899277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 900277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP"); 901277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson final long token = Binder.clearCallingIdentity(); 902277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 903277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mConnector.dump(fd, pw, args); 904277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 905277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 906277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 907277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 908277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 909277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Nullable 9108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private SubscriptionInfo getSubscriptionForSubscriptionId(int subscriptionId) { 9118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson List<SubscriptionInfo> subs = mSubscriptionManager.getAvailableSubscriptionInfoList(); 9128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson int subCount = subs.size(); 9138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson for (int i = 0; i < subCount; i++) { 9148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = subs.get(i); 9158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (subscriptionId == sub.getSubscriptionId()) { 9168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return sub; 9178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9188f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return null; 9208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9228f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable 923277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private String blockingGetEidFromEuiccService() { 9248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson CountDownLatch latch = new CountDownLatch(1); 9258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson AtomicReference<String> eidRef = new AtomicReference<>(); 926277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mConnector.getEid(new EuiccConnector.GetEidCommandCallback() { 927277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 928277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void onGetEidComplete(String eid) { 929277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson eidRef.set(eid); 930277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.countDown(); 931277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 932277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 933277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 934277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void onEuiccServiceUnavailable() { 935277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.countDown(); 936277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 937277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson }); 9388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return awaitResult(latch, eidRef); 9398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable 9428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private EuiccInfo blockingGetEuiccInfoFromEuiccService() { 9438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson CountDownLatch latch = new CountDownLatch(1); 9448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson AtomicReference<EuiccInfo> euiccInfoRef = new AtomicReference<>(); 9458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.getEuiccInfo(new EuiccConnector.GetEuiccInfoCommandCallback() { 9468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 9478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onGetEuiccInfoComplete(EuiccInfo euiccInfo) { 9488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson euiccInfoRef.set(euiccInfo); 9498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson latch.countDown(); 9508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 9538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 9548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson latch.countDown(); 9558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 9578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return awaitResult(latch, euiccInfoRef); 9588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private static <T> T awaitResult(CountDownLatch latch, AtomicReference<T> resultRef) { 961277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 962277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.await(); 963277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } catch (InterruptedException e) { 964277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Thread.currentThread().interrupt(); 965277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 9668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return resultRef.get(); 9678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private boolean canManageActiveSubscription(String callingPackage) { 9708f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // TODO(b/36260308): We should plumb a slot ID through here for multi-SIM devices. 9718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); 97227590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson if (subInfoList == null) { 97327590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson return false; 97427590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson } 9758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson int size = subInfoList.size(); 9768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson for (int subIndex = 0; subIndex < size; subIndex++) { 9778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo subInfo = subInfoList.get(subIndex); 9788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (subInfo.isEmbedded() && subInfo.canManageSubscription(mContext, callingPackage)) { 9798f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return true; 9808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return false; 983277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 984277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 985277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerCanReadPhoneStatePrivileged() { 986277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return mContext.checkCallingPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 987277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson == PackageManager.PERMISSION_GRANTED; 988277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 989277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 990277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerCanWriteEmbeddedSubscriptions() { 991277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return mContext.checkCallingPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) 992277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson == PackageManager.PERMISSION_GRANTED; 993277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 994277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 995277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** 996277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * Returns whether the caller has carrier privileges for the active mSubscription on this eUICC. 997277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson */ 998277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerHasCarrierPrivilegesForActiveSubscription() { 999277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson // TODO(b/36260308): We should plumb a slot ID through here for multi-SIM devices. 1000277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson TelephonyManager tm = 1001277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 1002277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return tm.hasCarrierPrivileges(); 1003277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 1004277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson} 1005