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