EuiccController.java revision 2938f11d0b1e409089828c0247a5b79f3550a35a
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; 41431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 41531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 41608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson extrasIntent.putExtra( 41708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 41831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 41908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 42008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 42108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 42208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 42308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 42408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 42508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 42608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onEuiccServiceUnavailable() { 42731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 42808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 42908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson }); 43008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 43108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 432dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson /** 433dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * Blocking call to {@link EuiccService#onGetEuiccProfileInfoList}. 434dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * 435dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * <p>Does not perform permission checks as this is not an exposed API and is only used within 436dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * the phone process. 437dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson */ 438dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public GetEuiccProfileInfoListResult blockingGetEuiccProfileInfoList() { 439dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson final CountDownLatch latch = new CountDownLatch(1); 440dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson final AtomicReference<GetEuiccProfileInfoListResult> resultRef = new AtomicReference<>(); 441dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson mConnector.getEuiccProfileInfoList( 442dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson new EuiccConnector.GetEuiccProfileInfoListCommandCallback() { 443dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson @Override 444dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public void onListComplete(GetEuiccProfileInfoListResult result) { 445dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson resultRef.set(result); 446dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.countDown(); 447dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 448dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson 449dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson @Override 450dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public void onEuiccServiceUnavailable() { 451dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.countDown(); 452dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 453dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson }); 454dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson try { 455dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.await(); 456dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } catch (InterruptedException e) { 457dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson Thread.currentThread().interrupt(); 458dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 459dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson return resultRef.get(); 460dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 461dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson 4628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 4639af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson public void getDefaultDownloadableSubscriptionList( 4649af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, PendingIntent callbackIntent) { 4659af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson getDefaultDownloadableSubscriptionList( 4669af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson false /* forceDeactivateSim */, callingPackage, callbackIntent); 4678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 4698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void getDefaultDownloadableSubscriptionList( 4709af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 4718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 4728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 4738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get default list"); 4748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4759af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 4768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 4778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 4788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.getDefaultDownloadableSubscriptionList( 4799af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson forceDeactivateSim, new GetDefaultListCommandCallback( 4809af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson token, callingPackage, callbackIntent)); 4818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 4828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 4838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 4868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson class GetDefaultListCommandCallback implements EuiccConnector.GetDefaultListCommandCallback { 4879af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final long mCallingToken; 4889af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final String mCallingPackage; 4899af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final PendingIntent mCallbackIntent; 4908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 4919af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson GetDefaultListCommandCallback(long callingToken, String callingPackage, 4929af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson PendingIntent callbackIntent) { 4938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingToken = callingToken; 4949af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage = callingPackage; 4958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallbackIntent = callbackIntent; 4968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 4978f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 4988f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 4998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onGetDefaultListComplete(GetDefaultDownloadableSubscriptionListResult result) { 5008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 5018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 5028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switch (result.result) { 50331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 5048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 5058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 5068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS, 5078f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson result.subscriptions); 5088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 50931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 5108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = RESOLVABLE_ERROR; 5118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 5128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 5139af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 5149af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson EuiccOperation.forGetDefaultListDeactivateSim( 5159af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingToken, mCallingPackage)); 5168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 51731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 51831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 5198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 5208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 52131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result.result); 5228f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 5238f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(mCallbackIntent, resultCode, extrasIntent); 5268f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5278f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5288f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5298f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 53031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 5318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5328f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson /** 5358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * Return the {@link EuiccInfo}. 5368f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * 5378f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 5388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * that IPC should generally be fast, and this info shouldn't be needed in the normal course of 5398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * operation. 5408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson */ 5418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public EuiccInfo getEuiccInfo() { 5438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // No permissions required as EuiccInfo is not sensitive. 5448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 5458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 5468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return blockingGetEuiccInfoFromEuiccService(); 5478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 5488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 5498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void deleteSubscription(int subscriptionId, String callingPackage, 5548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 5558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 5568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 5578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 5598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 5608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 5618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 5628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot delete nonexistent subscription: " + subscriptionId); 56331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 5648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 5658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 5688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson && !sub.canManageSubscription(mContext, callingPackage)) { 5698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "No permissions: " + subscriptionId); 57031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 5718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 5728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson deleteSubscriptionPrivileged(sub.getIccId(), callbackIntent); 5758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 5768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 5778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5798f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void deleteSubscriptionPrivileged(String iccid, final PendingIntent callbackIntent) { 5818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.deleteSubscription( 5828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid, 5838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.DeleteCommandCallback() { 5848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 58531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onDeleteComplete(int result) { 5868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 5878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 58831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 58931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 5908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 591d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson refreshSubscriptionsAndSendResult( 592d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson callbackIntent, resultCode, extrasIntent); 593d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson return; 59431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 59531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 5968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 5978f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 59831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 5998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 6008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 6038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 60731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 6108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void switchToSubscription(int subscriptionId, String callingPackage, 6148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 6158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscription( 6168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson subscriptionId, false /* forceDeactivateSim */, callingPackage, callbackIntent); 6178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6188f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscription(int subscriptionId, boolean forceDeactivateSim, String callingPackage, 6208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 6218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 6228f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 6238f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 6258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 6262938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson if (callerCanWriteEmbeddedSubscriptions) { 6272938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // Assume that if a privileged caller is calling us, we don't need to prompt the 6282938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // user about changing carriers, because the caller would only be acting in response 6292938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // to user action. 6302938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson forceDeactivateSim = true; 6312938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson } 6322938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson 6338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final String iccid; 6348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 6358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // Switch to "no" subscription. Only the system can do this. 6368f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions) { 6378f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Not permitted to switch to empty subscription"); 63831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = null; 6428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } else { 6438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 6448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 6458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot switch to nonexistent subscription: " + subscriptionId); 64631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 6508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson && !sub.canManageSubscription(mContext, callingPackage)) { 6518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Not permitted to switch to subscription: " + subscriptionId); 65231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = sub.getIccId(); 6568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 6598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson && !canManageActiveSubscription(callingPackage)) { 6608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // Switch needs consent. 6618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 6628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 6638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 6649af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson callingPackage, 6658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccOperation.forSwitchNoPrivileges( 6668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson token, subscriptionId, callingPackage)); 6678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, RESOLVABLE_ERROR, extrasIntent); 6688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6708f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscriptionPrivileged(token, subscriptionId, iccid, forceDeactivateSim, 6728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingPackage, callbackIntent); 6738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 6748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 6758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscriptionPrivileged(final long callingToken, int subscriptionId, 6798f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean forceDeactivateSim, final String callingPackage, 6808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final PendingIntent callbackIntent) { 6818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson String iccid = null; 6828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 6838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub != null) { 6848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = sub.getIccId(); 6858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscriptionPrivileged(callingToken, subscriptionId, iccid, forceDeactivateSim, 6878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingPackage, callbackIntent); 6888f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6898f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscriptionPrivileged(final long callingToken, int subscriptionId, 6918f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable String iccid, boolean forceDeactivateSim, final String callingPackage, 6928f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final PendingIntent callbackIntent) { 6938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.switchToSubscription( 6948f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid, 6958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson forceDeactivateSim, 6968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.SwitchCommandCallback() { 6978f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 69831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onSwitchComplete(int result) { 6998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 7008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 70131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 70231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 7038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 7048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 70531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 7068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = RESOLVABLE_ERROR; 7078f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 7088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 7099af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson callingPackage, 7108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccOperation.forSwitchDeactivateSim( 7118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingToken, subscriptionId, callingPackage)); 7128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 71331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 71431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 7158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 7168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 71731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 7188f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 7198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 7228f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7238f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 7258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 72631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7278f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7288f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 7298f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7308f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 7328f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void updateSubscriptionNickname(int subscriptionId, String nickname, 7338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 7348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 7358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 7368f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to update nickname"); 7378f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 7398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 7408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 7418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 7428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot update nickname to nonexistent subscription: " + subscriptionId); 74331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 7458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.updateSubscriptionNickname( 7478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sub.getIccId(), nickname, 7488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.UpdateNicknameCommandCallback() { 7498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 75031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onUpdateNicknameComplete(int result) { 7518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 7528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 75331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 75431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 7558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 7568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 75731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 75831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 7598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 7608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 76131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 7628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 7638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 7668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 7698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 77031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 7738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 7748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 7758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 7798f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void eraseSubscriptions(PendingIntent callbackIntent) { 7808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 7818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 7828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to erase subscriptions"); 7838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 7858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 7868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.eraseSubscriptions(new EuiccConnector.EraseCommandCallback() { 7878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 78831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onEraseComplete(int result) { 7898f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 7908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 79131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 79231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 7938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 794d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson refreshSubscriptionsAndSendResult( 795d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson callbackIntent, resultCode, extrasIntent); 796d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson return; 79731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 79831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 7998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 8008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 80131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 8028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 8038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 8068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8078f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 8098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 81031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 8118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 8138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 8148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 8158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 818a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 819a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void retainSubscriptionsForFactoryReset(PendingIntent callbackIntent) { 820a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson mContext.enforceCallingPermission(Manifest.permission.MASTER_CLEAR, 821a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson "Must have MASTER_CLEAR to retain subscriptions for factory reset"); 822a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson long token = Binder.clearCallingIdentity(); 823a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson try { 824a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson mConnector.retainSubscriptions( 825a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson new EuiccConnector.RetainSubscriptionsCommandCallback() { 826a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 827a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void onRetainSubscriptionsComplete(int result) { 828a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson Intent extrasIntent = new Intent(); 829a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson final int resultCode; 830a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson switch (result) { 831a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson case EuiccService.RESULT_OK: 832a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson resultCode = OK; 833a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson break; 834a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson default: 835a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson resultCode = ERROR; 836a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson extrasIntent.putExtra( 837a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 838a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson result); 839a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson break; 840a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 841a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 842a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 843a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 844a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 845a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 846a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void onEuiccServiceUnavailable() { 847a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 848a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 849a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson }); 850a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } finally { 851a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson Binder.restoreCallingIdentity(token); 852a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 853a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 854a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 855d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson /** Refresh the embedded subscription list and dispatch the given result upon completion. */ 856d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 857d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson public void refreshSubscriptionsAndSendResult( 858d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 859d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson SubscriptionController.getInstance() 860d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson .requestEmbeddedSubscriptionInfoListRefresh( 861d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson () -> sendResult(callbackIntent, resultCode, extrasIntent)); 862d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson } 8638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 864fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson /** Dispatch the given callback intent with the given result code and data. */ 865fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 866fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson public void sendResult(PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 867277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 868277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson callbackIntent.send(mContext, resultCode, extrasIntent); 869277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } catch (PendingIntent.CanceledException e) { 870277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson // Caller canceled the callback; do nothing. 871277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 872277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 873277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 874953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson /** Add a resolution intent to the given extras intent. */ 875953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 876953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson public void addResolutionIntent(Intent extrasIntent, String resolutionAction, 8779af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, EuiccOperation op) { 878953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson Intent intent = new Intent(EuiccManager.ACTION_RESOLVE_ERROR); 879953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION, 880953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson resolutionAction); 8819af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson intent.putExtra(EuiccService.EXTRA_RESOLUTION_CALLING_PACKAGE, callingPackage); 882953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson intent.putExtra(EXTRA_OPERATION, op); 883953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent resolutionIntent = PendingIntent.getActivity( 884953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_ONE_SHOT); 885953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson extrasIntent.putExtra( 886953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT, resolutionIntent); 887953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 888953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 889277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 890277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 891277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP"); 892277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson final long token = Binder.clearCallingIdentity(); 893277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 894277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mConnector.dump(fd, pw, args); 895277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 896277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 897277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 898277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 899277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 900277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Nullable 9018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private SubscriptionInfo getSubscriptionForSubscriptionId(int subscriptionId) { 9028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson List<SubscriptionInfo> subs = mSubscriptionManager.getAvailableSubscriptionInfoList(); 9038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson int subCount = subs.size(); 9048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson for (int i = 0; i < subCount; i++) { 9058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = subs.get(i); 9068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (subscriptionId == sub.getSubscriptionId()) { 9078f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return sub; 9088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return null; 9118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable 914277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private String blockingGetEidFromEuiccService() { 9158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson CountDownLatch latch = new CountDownLatch(1); 9168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson AtomicReference<String> eidRef = new AtomicReference<>(); 917277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mConnector.getEid(new EuiccConnector.GetEidCommandCallback() { 918277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 919277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void onGetEidComplete(String eid) { 920277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson eidRef.set(eid); 921277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.countDown(); 922277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 923277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 924277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 925277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void onEuiccServiceUnavailable() { 926277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.countDown(); 927277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 928277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson }); 9298f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return awaitResult(latch, eidRef); 9308f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9328f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable 9338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private EuiccInfo blockingGetEuiccInfoFromEuiccService() { 9348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson CountDownLatch latch = new CountDownLatch(1); 9358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson AtomicReference<EuiccInfo> euiccInfoRef = new AtomicReference<>(); 9368f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.getEuiccInfo(new EuiccConnector.GetEuiccInfoCommandCallback() { 9378f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 9388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onGetEuiccInfoComplete(EuiccInfo euiccInfo) { 9398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson euiccInfoRef.set(euiccInfo); 9408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson latch.countDown(); 9418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 9448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 9458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson latch.countDown(); 9468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 9488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return awaitResult(latch, euiccInfoRef); 9498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private static <T> T awaitResult(CountDownLatch latch, AtomicReference<T> resultRef) { 952277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 953277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.await(); 954277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } catch (InterruptedException e) { 955277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Thread.currentThread().interrupt(); 956277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 9578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return resultRef.get(); 9588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 9608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private boolean canManageActiveSubscription(String callingPackage) { 9618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // TODO(b/36260308): We should plumb a slot ID through here for multi-SIM devices. 9628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); 96327590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson if (subInfoList == null) { 96427590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson return false; 96527590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson } 9668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson int size = subInfoList.size(); 9678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson for (int subIndex = 0; subIndex < size; subIndex++) { 9688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo subInfo = subInfoList.get(subIndex); 9698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (subInfo.isEmbedded() && subInfo.canManageSubscription(mContext, callingPackage)) { 9708f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return true; 9718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 9738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return false; 974277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 975277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 976277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerCanReadPhoneStatePrivileged() { 977277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return mContext.checkCallingPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 978277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson == PackageManager.PERMISSION_GRANTED; 979277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 980277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 981277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerCanWriteEmbeddedSubscriptions() { 982277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return mContext.checkCallingPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) 983277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson == PackageManager.PERMISSION_GRANTED; 984277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 985277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 986277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** 987277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * Returns whether the caller has carrier privileges for the active mSubscription on this eUICC. 988277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson */ 989277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerHasCarrierPrivilegesForActiveSubscription() { 990277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson // TODO(b/36260308): We should plumb a slot ID through here for multi-SIM devices. 991277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson TelephonyManager tm = 992277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 993277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return tm.hasCarrierPrivileges(); 994277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 995277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson} 996