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 18ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Liimport static android.telephony.euicc.EuiccManager.EUICC_OTA_STATUS_UNAVAILABLE; 19ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li 20277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.Manifest; 2196d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Liimport android.Manifest.permission; 22277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.annotation.Nullable; 2308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidsonimport android.app.AppOpsManager; 24277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.app.PendingIntent; 25277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.content.Context; 26277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.content.Intent; 270d9f586153114c5df6407d7919117f49593fa149Qingxi Liimport android.content.pm.ComponentInfo; 2808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidsonimport android.content.pm.PackageInfo; 29277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.content.pm.PackageManager; 30277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.os.Binder; 31953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidsonimport android.os.Bundle; 32277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.os.ServiceManager; 334f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidsonimport android.provider.Settings; 34953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidsonimport android.service.euicc.EuiccService; 358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidsonimport android.service.euicc.GetDefaultDownloadableSubscriptionListResult; 36277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.service.euicc.GetDownloadableSubscriptionMetadataResult; 37dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport android.service.euicc.GetEuiccProfileInfoListResult; 38dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport android.telephony.SubscriptionInfo; 39dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport android.telephony.SubscriptionManager; 40277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.telephony.TelephonyManager; 4108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidsonimport android.telephony.UiccAccessRule; 42277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.telephony.euicc.DownloadableSubscription; 438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidsonimport android.telephony.euicc.EuiccInfo; 44277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.telephony.euicc.EuiccManager; 45ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Liimport android.telephony.euicc.EuiccManager.OtaStatus; 46f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sunimport android.text.TextUtils; 47277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport android.util.Log; 48277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 49277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport com.android.internal.annotations.VisibleForTesting; 50dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport com.android.internal.telephony.SubscriptionController; 5196d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Liimport com.android.internal.telephony.euicc.EuiccConnector.OtaStatusChangedCallback; 52277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 53277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport java.io.FileDescriptor; 54277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport java.io.PrintWriter; 55dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidsonimport java.util.List; 56277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport java.util.concurrent.CountDownLatch; 57277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonimport java.util.concurrent.atomic.AtomicReference; 58277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 59277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson/** Backing implementation of {@link android.telephony.euicc.EuiccManager}. */ 60277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidsonpublic class EuiccController extends IEuiccController.Stub { 61277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private static final String TAG = "EuiccController"; 62277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 63953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson /** Extra set on resolution intents containing the {@link EuiccOperation}. */ 64953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @VisibleForTesting 65953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson static final String EXTRA_OPERATION = "operation"; 66953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 6708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // Aliases so line lengths stay short. 6808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private static final int OK = EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_OK; 6908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private static final int RESOLVABLE_ERROR = 7008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR; 7131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson private static final int ERROR = 7231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_ERROR; 738bf20cb416675744e28821f509a20ae2813ad44eHolly Jiuyu Sun private static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = 748bf20cb416675744e28821f509a20ae2813ad44eHolly Jiuyu Sun EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION; 7508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 76277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private static EuiccController sInstance; 77277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 78277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private final Context mContext; 79277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private final EuiccConnector mConnector; 80dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson private final SubscriptionManager mSubscriptionManager; 8108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private final AppOpsManager mAppOpsManager; 8208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private final PackageManager mPackageManager; 83277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 84277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** Initialize the instance. Should only be called once. */ 85277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public static EuiccController init(Context context) { 86277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson synchronized (EuiccController.class) { 87277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (sInstance == null) { 88277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson sInstance = new EuiccController(context); 89277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } else { 90277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Log.wtf(TAG, "init() called multiple times! sInstance = " + sInstance); 91277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 92277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 93277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return sInstance; 94277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 95277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 96277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** Get an instance. Assumes one has already been initialized with {@link #init}. */ 97277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public static EuiccController get() { 98277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (sInstance == null) { 99277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson synchronized (EuiccController.class) { 100277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (sInstance == null) { 101277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson throw new IllegalStateException("get() called before init()"); 102277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 103277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 104277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 105277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return sInstance; 106277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 107277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 108277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private EuiccController(Context context) { 109277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson this(context, new EuiccConnector(context)); 110277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson ServiceManager.addService("econtroller", this); 111277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 112277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 113277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @VisibleForTesting 114277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public EuiccController(Context context, EuiccConnector connector) { 115277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mContext = context; 116277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mConnector = connector; 117dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson mSubscriptionManager = (SubscriptionManager) 118dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 11908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mAppOpsManager = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE); 12008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mPackageManager = context.getPackageManager(); 121277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 122277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 123277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** 124953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * Continue an operation which failed with a user-resolvable error. 125953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * 126953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * <p>The implementation here makes a key assumption that the resolutionIntent has not been 127953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * tampered with. This is guaranteed because: 128953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * <UL> 129953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * <LI>The intent is wrapped in a PendingIntent created by the phone process which is created 130953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * with {@link #EXTRA_OPERATION} already present. This means that the operation cannot be 131953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * overridden on the PendingIntent - a caller can only add new extras. 132953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * <LI>The resolution activity is restricted by a privileged permission; unprivileged apps 133953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * cannot start it directly. So the PendingIntent is the only way to start it. 134953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson * </UL> 135953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson */ 136953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @Override 137953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) { 138953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 139953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson throw new SecurityException( 140953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to continue operation"); 141953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 142953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson long token = Binder.clearCallingIdentity(); 143953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson try { 144953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccOperation op = resolutionIntent.getParcelableExtra(EXTRA_OPERATION); 145953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson if (op == null) { 146953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson throw new IllegalArgumentException("Invalid resolution intent"); 147953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 148953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 149953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent callbackIntent = 150953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson resolutionIntent.getParcelableExtra( 151953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT); 152953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson op.continueOperation(resolutionExtras, callbackIntent); 153953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } finally { 154953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson Binder.restoreCallingIdentity(token); 155953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 156953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 157953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 158953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson /** 159277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * Return the EID. 160277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * 161277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 162277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * that IPC should generally be fast, and the EID shouldn't be needed in the normal course of 163277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * operation. 164277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson */ 165277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 166277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public String getEid() { 167277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (!callerCanReadPhoneStatePrivileged() 168277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson && !callerHasCarrierPrivilegesForActiveSubscription()) { 169277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson throw new SecurityException( 170277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson "Must have carrier privileges on active subscription to read EID"); 171277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 172277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson long token = Binder.clearCallingIdentity(); 173277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 174277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return blockingGetEidFromEuiccService(); 175277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 176277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 177277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 178277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 179277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 180ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li /** 181ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li * Return the current status of OTA update. 182ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li * 183ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 184ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li * that IPC should generally be fast. 185ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li */ 186ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li @Override 187ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li public @OtaStatus int getOtaStatus() { 188ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li if (!callerCanWriteEmbeddedSubscriptions()) { 189ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get OTA status"); 190ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li } 191ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li long token = Binder.clearCallingIdentity(); 192ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li try { 193ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li return blockingGetOtaStatusFromEuiccService(); 194ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li } finally { 195ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li Binder.restoreCallingIdentity(token); 196ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li } 197ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li } 198ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li 19996d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li 20096d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li /** 20196d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li * Start eUICC OTA update if current eUICC OS is not the latest one. When OTA is started or 20296d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li * finished, the broadcast {@link EuiccManager#ACTION_OTA_STATUS_CHANGED} will be sent. 20396d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li * 20496d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li * This function will only be called from phone process and isn't exposed to the other apps. 20596d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li */ 20696d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li public void startOtaUpdatingIfNecessary() { 20796d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li mConnector.startOtaIfNecessary( 20896d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li new OtaStatusChangedCallback() { 20996d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li @Override 21096d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li public void onOtaStatusChanged(int status) { 21196d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li sendOtaStatusChangedBroadcast(); 21296d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li } 21396d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li 21496d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li @Override 21596d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li public void onEuiccServiceUnavailable() {} 21696d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li }); 21796d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li } 21896d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li 219277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 220277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription, 2219af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, PendingIntent callbackIntent) { 222953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson getDownloadableSubscriptionMetadata( 2239af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson subscription, false /* forceDeactivateSim */, callingPackage, callbackIntent); 224953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 225953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 226953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson void getDownloadableSubscriptionMetadata(DownloadableSubscription subscription, 2279af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 228277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 229277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get metadata"); 230277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 2319af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 232277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson long token = Binder.clearCallingIdentity(); 233277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 23408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mConnector.getDownloadableSubscriptionMetadata( 235953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson subscription, forceDeactivateSim, 2369af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson new GetMetadataCommandCallback( 2379af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson token, subscription, callingPackage, callbackIntent)); 238277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 239277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 240277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 241277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 242277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 24308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson class GetMetadataCommandCallback implements EuiccConnector.GetMetadataCommandCallback { 244953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson protected final long mCallingToken; 245953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson protected final DownloadableSubscription mSubscription; 2469af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson protected final String mCallingPackage; 24708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson protected final PendingIntent mCallbackIntent; 24808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 249953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson GetMetadataCommandCallback( 250953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson long callingToken, 251953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson DownloadableSubscription subscription, 2529af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, 253953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent callbackIntent) { 254953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mCallingToken = callingToken; 255953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mSubscription = subscription; 2569af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage = callingPackage; 25708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mCallbackIntent = callbackIntent; 25808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 25908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 26008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 26108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onGetMetadataComplete( 26208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson GetDownloadableSubscriptionMetadataResult result) { 26308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Intent extrasIntent = new Intent(); 26408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson final int resultCode; 265d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun switch (result.getResult()) { 26631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 26708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson resultCode = OK; 26808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson extrasIntent.putExtra( 2698bf20cb416675744e28821f509a20ae2813ad44eHolly Jiuyu Sun EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION, 270d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun result.getDownloadableSubscription()); 27108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 27231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 27308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson resultCode = RESOLVABLE_ERROR; 274953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson addResolutionIntent(extrasIntent, 275953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 2769af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 277f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun false /* confirmationCodeRetried */, 278953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson getOperationForDeactivateSim()); 27908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 28031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 28131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 28208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson extrasIntent.putExtra( 28308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 284d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun result.getResult()); 28508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 28608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 28708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 28808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson sendResult(mCallbackIntent, resultCode, extrasIntent); 28908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 29008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 29108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 29208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onEuiccServiceUnavailable() { 29331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 29408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 295953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 296953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson protected EuiccOperation getOperationForDeactivateSim() { 2979af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson return EuiccOperation.forGetMetadataDeactivateSim( 2989af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingToken, mSubscription, mCallingPackage); 299953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 30008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 30108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 302277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 303277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void downloadSubscription(DownloadableSubscription subscription, 30408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson boolean switchAfterDownload, String callingPackage, PendingIntent callbackIntent) { 305953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson downloadSubscription(subscription, switchAfterDownload, callingPackage, 306953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson false /* forceDeactivateSim */, callbackIntent); 307953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 308953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 309953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson void downloadSubscription(DownloadableSubscription subscription, 310953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson boolean switchAfterDownload, String callingPackage, boolean forceDeactivateSim, 311953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent callbackIntent) { 31208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 31308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 31408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 315277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson long token = Binder.clearCallingIdentity(); 316277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 31708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson if (callerCanWriteEmbeddedSubscriptions) { 31808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // With WRITE_EMBEDDED_SUBSCRIPTIONS, we can skip profile-specific permission checks 31908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // and move straight to the profile download. 320953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson downloadSubscriptionPrivileged(token, subscription, switchAfterDownload, 321953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson forceDeactivateSim, callingPackage, callbackIntent); 32208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 32308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 32408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // Without WRITE_EMBEDDED_SUBSCRIPTIONS, the caller *must* be whitelisted per the 32508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // metadata of the profile to be downloaded, so check the metadata first. 32608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mConnector.getDownloadableSubscriptionMetadata(subscription, 327953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson forceDeactivateSim, 328953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson new DownloadSubscriptionGetMetadataCommandCallback(token, subscription, 329953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson switchAfterDownload, callingPackage, forceDeactivateSim, 330953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson callbackIntent)); 331277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 332277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 333277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 334277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 335277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 33608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson class DownloadSubscriptionGetMetadataCommandCallback extends GetMetadataCommandCallback { 33708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson private final boolean mSwitchAfterDownload; 338953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson private final boolean mForceDeactivateSim; 33908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 340953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson DownloadSubscriptionGetMetadataCommandCallback(long callingToken, 341953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson DownloadableSubscription subscription, boolean switchAfterDownload, 342953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson String callingPackage, boolean forceDeactivateSim, 343953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent callbackIntent) { 3449af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson super(callingToken, subscription, callingPackage, callbackIntent); 34508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mSwitchAfterDownload = switchAfterDownload; 346953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mForceDeactivateSim = forceDeactivateSim; 34708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 34808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 34908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 35008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onGetMetadataComplete( 35108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson GetDownloadableSubscriptionMetadataResult result) { 352d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun if (result.getResult() == EuiccService.RESULT_MUST_DEACTIVATE_SIM) { 3539af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson // If we need to deactivate the current SIM to even check permissions, go ahead and 3549af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson // require that the user resolve the stronger permission dialog. 3559af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson Intent extrasIntent = new Intent(); 3569af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 3579af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 358f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun false /* confirmationCodeRetried */, 3599af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson EuiccOperation.forDownloadNoPrivileges( 3609af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingToken, mSubscription, mSwitchAfterDownload, 3619af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage)); 3629af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson sendResult(mCallbackIntent, RESOLVABLE_ERROR, extrasIntent); 3639af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson return; 3649af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson } 3659af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson 366d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun if (result.getResult() != EuiccService.RESULT_OK) { 36708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson // Just propagate the error as normal. 36808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson super.onGetMetadataComplete(result); 36908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 37008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 37108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 372d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun DownloadableSubscription subscription = result.getDownloadableSubscription(); 373d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun UiccAccessRule[] rules = null; 374d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun List<UiccAccessRule> rulesList = subscription.getAccessRules(); 375d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun if (rulesList != null) { 376d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun rules = rulesList.toArray(new UiccAccessRule[rulesList.size()]); 377d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun } 37808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson if (rules == null) { 37908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Log.e(TAG, "No access rules but caller is unprivileged"); 38031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 38108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 38208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 38308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 38408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson final PackageInfo info; 38508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson try { 38608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson info = mPackageManager.getPackageInfo( 38708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson mCallingPackage, PackageManager.GET_SIGNATURES); 38808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } catch (PackageManager.NameNotFoundException e) { 38908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Log.e(TAG, "Calling package valid but gone"); 39031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 39108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 39208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 39308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 39408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson for (int i = 0; i < rules.length; i++) { 39508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson if (rules[i].getCarrierPrivilegeStatus(info) 39608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 397dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // Caller can download this profile. Now, determine whether the caller can also 398dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // manage the current profile; if so, we can perform the download silently; if 399dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // not, the user must provide consent. 4008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (canManageActiveSubscription(mCallingPackage)) { 4018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson downloadSubscriptionPrivileged( 4028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingToken, subscription, mSwitchAfterDownload, 4038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mForceDeactivateSim, mCallingPackage, mCallbackIntent); 4048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 40508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 406dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson 407dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // Switch might still be permitted, but the user must consent first. 408dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson Intent extrasIntent = new Intent(); 409dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson addResolutionIntent(extrasIntent, EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 4109af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 411f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun false /* confirmationCodeRetried */, 412dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson EuiccOperation.forDownloadNoPrivileges( 4138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingToken, subscription, mSwitchAfterDownload, 4148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingPackage)); 415dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson sendResult(mCallbackIntent, RESOLVABLE_ERROR, extrasIntent); 41608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson return; 41708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 41808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 41908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Log.e(TAG, "Caller is not permitted to download this profile"); 42031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 42108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 422953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 423953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @Override 424953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson protected EuiccOperation getOperationForDeactivateSim() { 425953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson return EuiccOperation.forDownloadDeactivateSim( 426953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mCallingToken, mSubscription, mSwitchAfterDownload, mCallingPackage); 427953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 42808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 42908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 430953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson void downloadSubscriptionPrivileged(final long callingToken, 431953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson DownloadableSubscription subscription, boolean switchAfterDownload, 432953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson boolean forceDeactivateSim, final String callingPackage, 433953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson final PendingIntent callbackIntent) { 434953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mConnector.downloadSubscription( 435953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson subscription, 436953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson switchAfterDownload, 437953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson forceDeactivateSim, 43808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson new EuiccConnector.DownloadCommandCallback() { 43908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 44031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onDownloadComplete(int result) { 44108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson Intent extrasIntent = new Intent(); 44208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson final int resultCode; 44331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 44431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 44508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson resultCode = OK; 4464f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson // Now that a profile has been successfully downloaded, mark the 4474f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson // eUICC as provisioned so it appears in settings UI as appropriate. 4484f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson Settings.Global.putInt( 4494f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson mContext.getContentResolver(), 4504f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson Settings.Global.EUICC_PROVISIONED, 4514f62c3ddcc69bc8217e4794c73d38945e97380eeJeff Davidson 1); 4528bf20cb416675744e28821f509a20ae2813ad44eHolly Jiuyu Sun extrasIntent.putExtra( 4538bf20cb416675744e28821f509a20ae2813ad44eHolly Jiuyu Sun EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION, 4548bf20cb416675744e28821f509a20ae2813ad44eHolly Jiuyu Sun subscription); 455dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson if (!switchAfterDownload) { 456dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // Since we're not switching, nothing will trigger a 457dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson // subscription list refresh on its own, so request one here. 458d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson refreshSubscriptionsAndSendResult( 459d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson callbackIntent, resultCode, extrasIntent); 460d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson return; 461dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 46208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 46331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 46408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson resultCode = RESOLVABLE_ERROR; 465953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson addResolutionIntent(extrasIntent, 466953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 4679af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson callingPackage, 468f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun false /* confirmationCodeRetried */, 469953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccOperation.forDownloadDeactivateSim( 470953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson callingToken, subscription, switchAfterDownload, 471953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson callingPackage)); 47208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 47380fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun case EuiccService.RESULT_NEED_CONFIRMATION_CODE: 47480fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun resultCode = RESOLVABLE_ERROR; 475f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun boolean retried = false; 476f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun if (!TextUtils.isEmpty(subscription.getConfirmationCode())) { 477f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun retried = true; 478f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun } 47980fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun addResolutionIntent(extrasIntent, 48080fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun EuiccService.ACTION_RESOLVE_CONFIRMATION_CODE, 48180fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun callingPackage, 482f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun retried /* confirmationCodeRetried */, 48380fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun EuiccOperation.forDownloadConfirmationCode( 48480fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun callingToken, subscription, switchAfterDownload, 48580fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun callingPackage)); 48680fc6417014d6a884b009557fd7d19861a1087abHolly Jiuyu Sun break; 48731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 48831e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 48908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson extrasIntent.putExtra( 49008d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 49131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 49208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson break; 49308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 49408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 49508d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 49608d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 49708d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 49808d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson @Override 49908d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson public void onEuiccServiceUnavailable() { 50031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 50108d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 50208d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson }); 50308d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson } 50408d3d312d13c3194d8434aeb8c92ea220f4d0e2cJeff Davidson 505dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson /** 506dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * Blocking call to {@link EuiccService#onGetEuiccProfileInfoList}. 507dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * 508dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * <p>Does not perform permission checks as this is not an exposed API and is only used within 509dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson * the phone process. 510dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson */ 511dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public GetEuiccProfileInfoListResult blockingGetEuiccProfileInfoList() { 512dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson final CountDownLatch latch = new CountDownLatch(1); 513dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson final AtomicReference<GetEuiccProfileInfoListResult> resultRef = new AtomicReference<>(); 514dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson mConnector.getEuiccProfileInfoList( 515dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson new EuiccConnector.GetEuiccProfileInfoListCommandCallback() { 516dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson @Override 517dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public void onListComplete(GetEuiccProfileInfoListResult result) { 518dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson resultRef.set(result); 519dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.countDown(); 520dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 521dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson 522dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson @Override 523dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson public void onEuiccServiceUnavailable() { 524dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.countDown(); 525dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 526dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson }); 527dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson try { 528dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson latch.await(); 529dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } catch (InterruptedException e) { 530dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson Thread.currentThread().interrupt(); 531dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 532dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson return resultRef.get(); 533dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson } 534dce529f00c52bedf4377ee5f7ae1b284fe6452beJeff Davidson 5358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5369af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson public void getDefaultDownloadableSubscriptionList( 5379af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson String callingPackage, PendingIntent callbackIntent) { 5389af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson getDefaultDownloadableSubscriptionList( 5399af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson false /* forceDeactivateSim */, callingPackage, callbackIntent); 5408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void getDefaultDownloadableSubscriptionList( 5439af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson boolean forceDeactivateSim, String callingPackage, PendingIntent callbackIntent) { 5448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 5458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 5468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to get default list"); 5478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5489af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 5498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 5508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 5518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.getDefaultDownloadableSubscriptionList( 5529af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson forceDeactivateSim, new GetDefaultListCommandCallback( 5539af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson token, callingPackage, callbackIntent)); 5548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 5558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 5568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson class GetDefaultListCommandCallback implements EuiccConnector.GetDefaultListCommandCallback { 5609af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final long mCallingToken; 5619af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final String mCallingPackage; 5629af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson final PendingIntent mCallbackIntent; 5638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5649af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson GetDefaultListCommandCallback(long callingToken, String callingPackage, 5659af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson PendingIntent callbackIntent) { 5668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallingToken = callingToken; 5679af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage = callingPackage; 5688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mCallbackIntent = callbackIntent; 5698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 5708f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 5718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 5728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onGetDefaultListComplete(GetDefaultDownloadableSubscriptionListResult result) { 5738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 5748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 575d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun switch (result.getResult()) { 57631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 5778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 578d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun List<DownloadableSubscription> list = result.getDownloadableSubscriptions(); 579d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun if (list != null && list.size() > 0) { 580d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun extrasIntent.putExtra( 581d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS, 582d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun list.toArray(new DownloadableSubscription[list.size()])); 583d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun } 5848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 58531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 5868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = RESOLVABLE_ERROR; 5878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 5888f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 5899af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingPackage, 590f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun false /* confirmationCodeRetried */, 5919af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson EuiccOperation.forGetDefaultListDeactivateSim( 5929af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson mCallingToken, mCallingPackage)); 5938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 59431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 59531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 5968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 5978f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 598d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun result.getResult()); 5998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 6008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(mCallbackIntent, resultCode, extrasIntent); 6038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 60731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(mCallbackIntent, ERROR, null /* extrasIntent */); 6088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson /** 6128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * Return the {@link EuiccInfo}. 6138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * 6148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * <p>For API simplicity, this call blocks until completion; while it requires an IPC to load, 6158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * that IPC should generally be fast, and this info shouldn't be needed in the normal course of 6168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson * operation. 6178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson */ 6188f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public EuiccInfo getEuiccInfo() { 6208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // No permissions required as EuiccInfo is not sensitive. 6218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 6228f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 6238f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return blockingGetEuiccInfoFromEuiccService(); 6248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 6258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 6268f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6278f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6288f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6298f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6308f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void deleteSubscription(int subscriptionId, String callingPackage, 6318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 6328f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 6338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 6348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 6368f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 6378f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 6388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 6398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot delete nonexistent subscription: " + subscriptionId); 64031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 6458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson && !sub.canManageSubscription(mContext, callingPackage)) { 6468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "No permissions: " + subscriptionId); 64731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 6498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson deleteSubscriptionPrivileged(sub.getIccId(), callbackIntent); 6528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 6538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 6548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void deleteSubscriptionPrivileged(String iccid, final PendingIntent callbackIntent) { 6588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.deleteSubscription( 6598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid, 6608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.DeleteCommandCallback() { 6618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 66231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onDeleteComplete(int result) { 6638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 6648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 66531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 66631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 6678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 668d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson refreshSubscriptionsAndSendResult( 669d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson callbackIntent, resultCode, extrasIntent); 670d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson return; 67131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 67231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 6738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 6748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 67531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 6768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 6778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6798f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 6808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 68431e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 6858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 6878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6888f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6898f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 6908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void switchToSubscription(int subscriptionId, String callingPackage, 6918f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 6928f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscription( 6938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson subscriptionId, false /* forceDeactivateSim */, callingPackage, callbackIntent); 6948f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 6958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 6968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscription(int subscriptionId, boolean forceDeactivateSim, String callingPackage, 6978f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 6988f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean callerCanWriteEmbeddedSubscriptions = callerCanWriteEmbeddedSubscriptions(); 6998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 7008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 7028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 7032938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson if (callerCanWriteEmbeddedSubscriptions) { 7042938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // Assume that if a privileged caller is calling us, we don't need to prompt the 7052938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // user about changing carriers, because the caller would only be acting in response 7062938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson // to user action. 7072938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson forceDeactivateSim = true; 7082938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson } 7092938f11d0b1e409089828c0247a5b79f3550a35aJeff Davidson 7108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final String iccid; 7118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (subscriptionId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 7128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // Switch to "no" subscription. Only the system can do this. 7138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions) { 7148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Not permitted to switch to empty subscription"); 71531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 7178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7188f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = null; 7198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } else { 7208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 7218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 7228f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot switch to nonexistent subscription: " + subscriptionId); 72331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 7258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7268f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 727d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun && !mSubscriptionManager.canManageSubscription(sub, callingPackage)) { 7288f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Not permitted to switch to subscription: " + subscriptionId); 72931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 7308f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 7318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7328f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = sub.getIccId(); 7338f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions 7368f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson && !canManageActiveSubscription(callingPackage)) { 7378f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // Switch needs consent. 7388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 7398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 7408f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_NO_PRIVILEGES, 7419af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson callingPackage, 742f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun false /* confirmationCodeRetried */, 7438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccOperation.forSwitchNoPrivileges( 7448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson token, subscriptionId, callingPackage)); 7458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, RESOLVABLE_ERROR, extrasIntent); 7468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 7478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscriptionPrivileged(token, subscriptionId, iccid, forceDeactivateSim, 7508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingPackage, callbackIntent); 7518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 7528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 7538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscriptionPrivileged(final long callingToken, int subscriptionId, 7578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson boolean forceDeactivateSim, final String callingPackage, 7588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final PendingIntent callbackIntent) { 7598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson String iccid = null; 7608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 7618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub != null) { 7628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid = sub.getIccId(); 7638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson switchToSubscriptionPrivileged(callingToken, subscriptionId, iccid, forceDeactivateSim, 7658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingPackage, callbackIntent); 7668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7678f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 7688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson void switchToSubscriptionPrivileged(final long callingToken, int subscriptionId, 7698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable String iccid, boolean forceDeactivateSim, final String callingPackage, 7708f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final PendingIntent callbackIntent) { 7718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.switchToSubscription( 7728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson iccid, 7738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson forceDeactivateSim, 7748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.SwitchCommandCallback() { 7758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 77631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onSwitchComplete(int result) { 7778f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 7788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 77931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 78031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 7818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 7828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 78331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_MUST_DEACTIVATE_SIM: 7848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = RESOLVABLE_ERROR; 7858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson addResolutionIntent(extrasIntent, 7868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM, 7879af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson callingPackage, 788f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun false /* confirmationCodeRetried */, 7898f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccOperation.forSwitchDeactivateSim( 7908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson callingToken, subscriptionId, callingPackage)); 7918f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 79231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 79331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 7948f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 7958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 79631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 7978f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 7988f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 7998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 8018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 8048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 80531e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 8068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8078f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 8088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8098f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 8118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void updateSubscriptionNickname(int subscriptionId, String nickname, 8128f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson PendingIntent callbackIntent) { 8138f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 8148f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 8158f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to update nickname"); 8168f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8178f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 8188f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 8198f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = getSubscriptionForSubscriptionId(subscriptionId); 8208f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (sub == null) { 8218f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Log.e(TAG, "Cannot update nickname to nonexistent subscription: " + subscriptionId); 82231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 8238f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return; 8248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.updateSubscriptionNickname( 8268f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sub.getIccId(), nickname, 8278f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson new EuiccConnector.UpdateNicknameCommandCallback() { 8288f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 82931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onUpdateNicknameComplete(int result) { 8308f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 8318f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 83231e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 83331e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 8348f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 8358f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 83631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 83731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 8388f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 8398f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 84031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 8418f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 8428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8438f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8448f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 8458f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 8488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 84931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 8508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 8528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 8538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 8548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 8588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void eraseSubscriptions(PendingIntent callbackIntent) { 8598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (!callerCanWriteEmbeddedSubscriptions()) { 8608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson throw new SecurityException( 8618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson "Must have WRITE_EMBEDDED_SUBSCRIPTIONS to erase subscriptions"); 8628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson long token = Binder.clearCallingIdentity(); 8648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson try { 8658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.eraseSubscriptions(new EuiccConnector.EraseCommandCallback() { 8668f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 86731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson public void onEraseComplete(int result) { 8688f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Intent extrasIntent = new Intent(); 8698f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson final int resultCode; 87031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson switch (result) { 87131e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson case EuiccService.RESULT_OK: 8728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson resultCode = OK; 873d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson refreshSubscriptionsAndSendResult( 874d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson callbackIntent, resultCode, extrasIntent); 875d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson return; 87631e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson default: 87731e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson resultCode = ERROR; 8788f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson extrasIntent.putExtra( 8798f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 88031e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson result); 8818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson break; 8828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8838f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8848f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 8858f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 8878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 8888f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 88931e69b5efbc9b9a39183acce93a4c1b2e73b3006Jeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 8908f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8918f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 8928f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } finally { 8938f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson Binder.restoreCallingIdentity(token); 8948f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8958f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 8968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 897a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 898a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void retainSubscriptionsForFactoryReset(PendingIntent callbackIntent) { 899a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson mContext.enforceCallingPermission(Manifest.permission.MASTER_CLEAR, 900a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson "Must have MASTER_CLEAR to retain subscriptions for factory reset"); 901a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson long token = Binder.clearCallingIdentity(); 902a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson try { 903a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson mConnector.retainSubscriptions( 904a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson new EuiccConnector.RetainSubscriptionsCommandCallback() { 905a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 906a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void onRetainSubscriptionsComplete(int result) { 907a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson Intent extrasIntent = new Intent(); 908a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson final int resultCode; 909a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson switch (result) { 910a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson case EuiccService.RESULT_OK: 911a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson resultCode = OK; 912a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson break; 913a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson default: 914a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson resultCode = ERROR; 915a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson extrasIntent.putExtra( 916a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, 917a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson result); 918a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson break; 919a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 920a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 921a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson sendResult(callbackIntent, resultCode, extrasIntent); 922a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 923a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 924a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson @Override 925a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson public void onEuiccServiceUnavailable() { 926a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson sendResult(callbackIntent, ERROR, null /* extrasIntent */); 927a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 928a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson }); 929a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } finally { 930a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson Binder.restoreCallingIdentity(token); 931a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 932a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson } 933a9c50823e758d35bac39cf2a7e674fcaf957fd4bJeff Davidson 934d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson /** Refresh the embedded subscription list and dispatch the given result upon completion. */ 935d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 936d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson public void refreshSubscriptionsAndSendResult( 937d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 938d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson SubscriptionController.getInstance() 939d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson .requestEmbeddedSubscriptionInfoListRefresh( 940d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson () -> sendResult(callbackIntent, resultCode, extrasIntent)); 941d728841b17b19ab8268a426051f51f64a6913142Jeff Davidson } 9428f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 943fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson /** Dispatch the given callback intent with the given result code and data. */ 944fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 945fc59bf75ccaaa45fcf8b9895f219a01955b75413Jeff Davidson public void sendResult(PendingIntent callbackIntent, int resultCode, Intent extrasIntent) { 946277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 947277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson callbackIntent.send(mContext, resultCode, extrasIntent); 948277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } catch (PendingIntent.CanceledException e) { 949277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson // Caller canceled the callback; do nothing. 950277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 951277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 952277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 953953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson /** Add a resolution intent to the given extras intent. */ 954953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 955953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson public void addResolutionIntent(Intent extrasIntent, String resolutionAction, 956f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun String callingPackage, boolean confirmationCodeRetried, EuiccOperation op) { 957953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson Intent intent = new Intent(EuiccManager.ACTION_RESOLVE_ERROR); 958953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson intent.putExtra(EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_ACTION, 959953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson resolutionAction); 9609af6424827eb9e023e037dd5aefd229235aceddbJeff Davidson intent.putExtra(EuiccService.EXTRA_RESOLUTION_CALLING_PACKAGE, callingPackage); 961f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun intent.putExtra(EuiccService.EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED, 962f2e6e134218a3302a8889ceef73d0f7ccfbddb56Holly Jiuyu Sun confirmationCodeRetried); 963953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson intent.putExtra(EXTRA_OPERATION, op); 964953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson PendingIntent resolutionIntent = PendingIntent.getActivity( 965953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson mContext, 0 /* requestCode */, intent, PendingIntent.FLAG_ONE_SHOT); 966953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson extrasIntent.putExtra( 967953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_INTENT, resolutionIntent); 968953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson } 969953d76b6865b1f76c6fadbbd69898fe064b6c157Jeff Davidson 970277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 971277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 972277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, "Requires DUMP"); 973277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson final long token = Binder.clearCallingIdentity(); 974277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 975277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mConnector.dump(fd, pw, args); 976277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } finally { 977277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Binder.restoreCallingIdentity(token); 978277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 979277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 980277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 98196d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li /** 98296d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li * Send broadcast {@link EuiccManager#ACTION_OTA_STATUS_CHANGED} for OTA status 98396d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li * changed. 98496d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li */ 98596d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) 98696d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li public void sendOtaStatusChangedBroadcast() { 98796d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li Intent intent = new Intent(EuiccManager.ACTION_OTA_STATUS_CHANGED); 9880d9f586153114c5df6407d7919117f49593fa149Qingxi Li ComponentInfo bestComponent = mConnector.findBestComponent(mContext.getPackageManager()); 9890d9f586153114c5df6407d7919117f49593fa149Qingxi Li if (bestComponent != null) { 9900d9f586153114c5df6407d7919117f49593fa149Qingxi Li intent.setPackage(bestComponent.packageName); 9910d9f586153114c5df6407d7919117f49593fa149Qingxi Li } 99296d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li mContext.sendBroadcast(intent, permission.WRITE_EMBEDDED_SUBSCRIPTIONS); 99396d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li } 99496d4dfe105bae38079c1ad834e5840365f2b9cc6Qingxi Li 995277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Nullable 9968f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private SubscriptionInfo getSubscriptionForSubscriptionId(int subscriptionId) { 9978f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson List<SubscriptionInfo> subs = mSubscriptionManager.getAvailableSubscriptionInfoList(); 9988f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson int subCount = subs.size(); 9998f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson for (int i = 0; i < subCount; i++) { 10008f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo sub = subs.get(i); 10018f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson if (subscriptionId == sub.getSubscriptionId()) { 10028f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return sub; 10038f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10048f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10058f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return null; 10068f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10078f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 10088f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable 1009277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private String blockingGetEidFromEuiccService() { 10108f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson CountDownLatch latch = new CountDownLatch(1); 10118f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson AtomicReference<String> eidRef = new AtomicReference<>(); 1012277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson mConnector.getEid(new EuiccConnector.GetEidCommandCallback() { 1013277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 1014277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void onGetEidComplete(String eid) { 1015277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson eidRef.set(eid); 1016277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.countDown(); 1017277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 1018277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 1019277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson @Override 1020277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson public void onEuiccServiceUnavailable() { 1021277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.countDown(); 1022277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 1023277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson }); 10248f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return awaitResult(latch, eidRef); 10258f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10268f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 1027ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li private @OtaStatus int blockingGetOtaStatusFromEuiccService() { 1028ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li CountDownLatch latch = new CountDownLatch(1); 1029ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li AtomicReference<Integer> statusRef = 1030ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li new AtomicReference<>(EUICC_OTA_STATUS_UNAVAILABLE); 1031ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li mConnector.getOtaStatus(new EuiccConnector.GetOtaStatusCommandCallback() { 1032ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li @Override 1033ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li public void onGetOtaStatusComplete(@OtaStatus int status) { 1034ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li statusRef.set(status); 1035ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li latch.countDown(); 1036ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li } 1037ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li 1038ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li @Override 1039ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li public void onEuiccServiceUnavailable() { 1040ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li latch.countDown(); 1041ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li } 1042ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li }); 1043ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li return awaitResult(latch, statusRef); 1044ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li } 1045ebbbe7bdbf2c6226913480bbd83a88cd0460a86aQingxi Li 10468f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Nullable 10478f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private EuiccInfo blockingGetEuiccInfoFromEuiccService() { 10488f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson CountDownLatch latch = new CountDownLatch(1); 10498f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson AtomicReference<EuiccInfo> euiccInfoRef = new AtomicReference<>(); 10508f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson mConnector.getEuiccInfo(new EuiccConnector.GetEuiccInfoCommandCallback() { 10518f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 10528f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onGetEuiccInfoComplete(EuiccInfo euiccInfo) { 10538f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson euiccInfoRef.set(euiccInfo); 10548f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson latch.countDown(); 10558f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10568f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 10578f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson @Override 10588f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson public void onEuiccServiceUnavailable() { 10598f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson latch.countDown(); 10608f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10618f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson }); 10628f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return awaitResult(latch, euiccInfoRef); 10638f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10648f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 10658f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private static <T> T awaitResult(CountDownLatch latch, AtomicReference<T> resultRef) { 1066277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson try { 1067277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson latch.await(); 1068277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } catch (InterruptedException e) { 1069277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson Thread.currentThread().interrupt(); 1070277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 10718f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return resultRef.get(); 10728f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10738f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson 10748f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson private boolean canManageActiveSubscription(String callingPackage) { 10758f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson // TODO(b/36260308): We should plumb a slot ID through here for multi-SIM devices. 10768f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson List<SubscriptionInfo> subInfoList = mSubscriptionManager.getActiveSubscriptionInfoList(); 107727590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson if (subInfoList == null) { 107827590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson return false; 107927590b4156bff85bcd8b68536216526d2dd029c7Jeff Davidson } 10808f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson int size = subInfoList.size(); 10818f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson for (int subIndex = 0; subIndex < size; subIndex++) { 10828f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson SubscriptionInfo subInfo = subInfoList.get(subIndex); 1083d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun 1084d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun if (subInfo.isEmbedded() 1085d828468595f5483da81732d7e321c8204b0fa2b7Jiuyu Sun && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) { 10868f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return true; 10878f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10888f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson } 10898f32416b4c5f5657e7ccf3a1ee031598a0203fd9Jeff Davidson return false; 1090277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 1091277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 1092277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerCanReadPhoneStatePrivileged() { 1093277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return mContext.checkCallingPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 1094277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson == PackageManager.PERMISSION_GRANTED; 1095277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 1096277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 1097277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerCanWriteEmbeddedSubscriptions() { 1098277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return mContext.checkCallingPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) 1099277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson == PackageManager.PERMISSION_GRANTED; 1100277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 1101277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson 1102277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson /** 1103277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson * Returns whether the caller has carrier privileges for the active mSubscription on this eUICC. 1104277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson */ 1105277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson private boolean callerHasCarrierPrivilegesForActiveSubscription() { 1106277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson // TODO(b/36260308): We should plumb a slot ID through here for multi-SIM devices. 1107277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson TelephonyManager tm = 1108277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE); 1109277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson return tm.hasCarrierPrivileges(); 1110277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson } 1111277a5a2aae73ef0233fffc350f3829aee779899fJeff Davidson} 1112