diff options
20 files changed, 1280 insertions, 0 deletions
diff --git a/Android.mk b/Android.mk index 08ef6f59fe7b..4fbe09422a4b 100644 --- a/Android.mk +++ b/Android.mk @@ -278,6 +278,10 @@ LOCAL_SRC_FILES += \ core/java/android/service/carrier/ICarrierService.aidl \ core/java/android/service/carrier/ICarrierMessagingCallback.aidl \ core/java/android/service/carrier/ICarrierMessagingService.aidl \ + core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl \ + core/java/android/service/euicc/IEuiccService.aidl \ + core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl \ + core/java/android/service/euicc/IGetEidCallback.aidl \ core/java/android/service/gatekeeper/IGateKeeperService.aidl \ core/java/android/service/notification/INotificationListener.aidl \ core/java/android/service/notification/IStatusBarNotificationHolder.aidl \ @@ -518,6 +522,7 @@ LOCAL_SRC_FILES += \ telephony/java/com/android/internal/telephony/ITelephony.aidl \ telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \ telephony/java/com/android/internal/telephony/IWapPushManager.aidl \ + telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl \ wifi/java/android/net/wifi/IWifiManager.aidl \ wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl \ wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl \ @@ -614,6 +619,8 @@ aidl_files := \ frameworks/base/telephony/java/android/telephony/IccOpenLogicalChannelResponse.aidl \ frameworks/base/telephony/java/android/telephony/NeighboringCellInfo.aidl \ frameworks/base/telephony/java/android/telephony/ModemActivityInfo.aidl \ + frameworks/base/telephony/java/android/telephony/UiccAccessRule.aidl \ + frameworks/base/telephony/java/android/telephony/euicc/DownloadableSubscription.aidl \ frameworks/base/location/java/android/location/Location.aidl \ frameworks/base/location/java/android/location/Address.aidl \ frameworks/base/location/java/android/location/Criteria.aidl \ @@ -726,6 +733,8 @@ aidl_files := \ frameworks/base/core/java/android/view/textservice/SuggestionsInfo.aidl \ frameworks/base/core/java/android/service/carrier/CarrierIdentifier.aidl \ frameworks/base/core/java/android/service/carrier/MessagePdu.aidl \ + frameworks/base/core/java/android/service/euicc/DownloadResult.aidl \ + frameworks/base/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl \ frameworks/base/core/java/android/service/notification/Adjustment.aidl \ frameworks/base/core/java/android/service/notification/Condition.aidl \ frameworks/base/core/java/android/service/notification/SnoozeCriterion.aidl \ diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java index 9b349dd85614..4c217debb07d 100644 --- a/core/java/android/app/SystemServiceRegistry.java +++ b/core/java/android/app/SystemServiceRegistry.java @@ -118,6 +118,7 @@ import android.os.health.SystemHealthManager; import android.os.storage.StorageManager; import android.print.IPrintManager; import android.print.PrintManager; +import android.telephony.euicc.EuiccManager; import android.view.autofill.AutofillManager; import android.view.autofill.IAutoFillManager; import android.service.persistentdata.IPersistentDataBlockService; @@ -493,6 +494,13 @@ final class SystemServiceRegistry { return new TelecomManager(ctx.getOuterContext()); }}); + registerService(Context.EUICC_SERVICE, EuiccManager.class, + new CachedServiceFetcher<EuiccManager>() { + @Override + public EuiccManager createService(ContextImpl ctx) { + return new EuiccManager(ctx.getOuterContext()); + }}); + registerService(Context.UI_MODE_SERVICE, UiModeManager.class, new CachedServiceFetcher<UiModeManager>() { @Override diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index dbbfe308868c..aa2adc74bc88 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -3455,6 +3455,17 @@ public abstract class Context { /** * Use with {@link #getSystemService} to retrieve a + * {@link android.telephony.euicc.EuiccManager} to manage the device eUICC (embedded SIM). + * + * @see #getSystemService + * @see android.telephony.euicc.EuiccManager + * TODO(b/35851809): Unhide this API. + * @hide + */ + public static final String EUICC_SERVICE = "euicc_service"; + + /** + * Use with {@link #getSystemService} to retrieve a * {@link android.text.ClipboardManager} for accessing and modifying * {@link android.content.ClipboardManager} for accessing and modifying * the contents of the global clipboard. diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 136c13b6f37d..17cb027e045d 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -1958,6 +1958,15 @@ public abstract class PackageManager { "android.hardware.telephony.carrierlock"; /** + * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device + * supports embedded subscriptions on eUICCs. + * TODO(b/35851809): Make this public. + * @hide + */ + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_TELEPHONY_EUICC = "android.hardware.telephony.euicc"; + + /** * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device supports connecting to USB devices * as the USB host. diff --git a/core/java/android/service/euicc/DownloadResult.aidl b/core/java/android/service/euicc/DownloadResult.aidl new file mode 100644 index 000000000000..66ec999b6ce8 --- /dev/null +++ b/core/java/android/service/euicc/DownloadResult.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.euicc; + +parcelable DownloadResult; diff --git a/core/java/android/service/euicc/DownloadResult.java b/core/java/android/service/euicc/DownloadResult.java new file mode 100644 index 000000000000..0aa55fbbc0ff --- /dev/null +++ b/core/java/android/service/euicc/DownloadResult.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.service.euicc; + +import android.annotation.IntDef; +import android.os.Parcel; +import android.os.Parcelable; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Result of a {@link EuiccService#downloadSubscription} operation. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ +public final class DownloadResult implements Parcelable { + + public static final Creator<DownloadResult> CREATOR = new Creator<DownloadResult>() { + @Override + public DownloadResult createFromParcel(Parcel in) { + return new DownloadResult(in); + } + + @Override + public DownloadResult[] newArray(int size) { + return new DownloadResult[size]; + } + }; + + /** @hide */ + @IntDef({ + RESULT_OK, + RESULT_GENERIC_ERROR, + RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ResultCode {} + + public static final int RESULT_OK = 0; + public static final int RESULT_GENERIC_ERROR = 1; + public static final int RESULT_MUST_DEACTIVATE_REMOVABLE_SIM = 2; + + /** Result of the operation - one of the RESULT_* constants. */ + public final @ResultCode int result; + + /** Implementation-defined detailed error code in case of a failure not covered here. */ + public final int detailedCode; + + private DownloadResult(int result, int detailedCode) { + this.result = result; + this.detailedCode = detailedCode; + } + + private DownloadResult(Parcel in) { + this.result = in.readInt(); + this.detailedCode = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(result); + dest.writeInt(detailedCode); + } + + /** Return a result indicating that the download was successful. */ + public static DownloadResult success() { + return new DownloadResult(RESULT_OK, 0); + } + + /** + * Return a result indicating that the removable SIM must be deactivated to perform the + * operation. + */ + public static DownloadResult mustDeactivateRemovableSim() { + return new DownloadResult(RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, 0); + } + + /** + * Return a result indicating that an error occurred for which no other more specific error + * code has been defined. + * + * @param detailedCode an implemenation-defined detailed error code for debugging purposes. + */ + public static DownloadResult genericError(int detailedCode) { + return new DownloadResult(RESULT_GENERIC_ERROR, detailedCode); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java new file mode 100644 index 000000000000..6407507549b1 --- /dev/null +++ b/core/java/android/service/euicc/EuiccService.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.service.euicc; + +import android.annotation.CallSuper; +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.os.RemoteException; +import android.telephony.euicc.DownloadableSubscription; + +/** + * Service interface linking the system with an eUICC local profile assistant (LPA) application. + * + * <p>An LPA consists of two separate components (which may both be implemented in the same APK): + * the LPA backend, and the LPA UI or LUI. + * + * <p>To implement the LPA backend, you must extend this class and declare this service in your + * manifest file. The service must require the + * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission and include an intent filter + * with the {@link #EUICC_SERVICE_INTERFACE} action. The priority of the intent filter must be set + * to a non-zero value in case multiple implementations are present on the device. For example: + * + * <pre>{@code + * <service android:name=".MyEuiccService" + * android:permission="android.permission.BIND_EUICC_SERVICE"> + * <intent-filter android:priority="100"> + * <action android:name="android.service.euicc.EuiccService" /> + * </intent-filter> + * </service> + * }</pre> + * + * <p>To implement the LUI, you must provide an activity for the following actions: + * + * <ul> + * <li>{@link #ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS} + * <li>{@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} + * </ul> + * + * <p>As with the service, each activity must require the + * {@link android.Manifest.permission#BIND_EUICC_SERVICE} permission. Each should have an intent + * filter with the appropriate action, the {@link #CATEGORY_EUICC_UI} category, and a non-zero + * priority. + * + * TODO(b/35851809): Make this a SystemApi. + * @hide + */ +public abstract class EuiccService extends Service { + /** Action which must be included in this service's intent filter. */ + public static final String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService"; + + /** Category which must be defined to all UI actions, for efficient lookup. */ + public static final String CATEGORY_EUICC_UI = "android.service.euicc.category.EUICC_UI"; + + // LUI actions. These are passthroughs of the corresponding EuiccManager actions. + + /** @see android.telephony.euicc.EuiccManager#ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS */ + public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = + "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS"; + /** @see android.telephony.euicc.EuiccManager#ACTION_PROVISION_EMBEDDED_SUBSCRIPTION */ + public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = + "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; + + private final IEuiccService.Stub mStubWrapper; + + public EuiccService() { + mStubWrapper = new IEuiccServiceWrapper(); + } + + /** + * If overriding this method, call through to the super method for any unknown actions. + * {@inheritDoc} + */ + @Override + @CallSuper + public IBinder onBind(Intent intent) { + return mStubWrapper; + } + + /** + * Return the EID of the eUICC. + * + * @param slotId ID of the SIM slot being queried. This is currently not populated but is here + * to future-proof the APIs. + * @return the EID. + * @see android.telephony.euicc.EuiccManager#getEid + */ + // TODO(b/36260308): Update doc when we have multi-SIM support. + public abstract String onGetEid(int slotId); + + /** + * Populate {@link DownloadableSubscription} metadata for the given downloadable subscription. + * + * @param slotId ID of the SIM slot to use when starting the download. This is currently not + * populated but is here to future-proof the APIs. + * @param subscription A subscription whose metadata needs to be populated. + * @return The result of the operation. + * @see android.telephony.euicc.EuiccManager#getDownloadableSubscriptionMetadata + */ + public abstract GetDownloadableSubscriptionMetadataResult getDownloadableSubscriptionMetadata( + int slotId, DownloadableSubscription subscription); + + /** + * Download the given subscription. + * + * @param slotId ID of the SIM slot onto which the subscription should be downloaded. This is + * currently not populated but is here to future-proof the APIs. + * @param subscription The subscription to download. + * @param switchAfterDownload If true, the subscription should be enabled upon successful + * download. + * @return the result of the download operation. + * @see android.telephony.euicc.EuiccManager#downloadSubscription + */ + public abstract DownloadResult downloadSubscription(int slotId, + DownloadableSubscription subscription, boolean switchAfterDownload); + + /** + * Wrapper around IEuiccService that forwards calls to implementations of {@link EuiccService}. + */ + private class IEuiccServiceWrapper extends IEuiccService.Stub { + @Override + public void downloadSubscription(int slotId, DownloadableSubscription subscription, + boolean switchAfterDownload, IDownloadSubscriptionCallback callback) { + DownloadResult result = EuiccService.this.downloadSubscription( + slotId, subscription, switchAfterDownload); + try { + callback.onComplete(result); + } catch (RemoteException e) { + // Can't communicate with the phone process; ignore. + } + } + + @Override + public void getEid(int slotId, IGetEidCallback callback) { + String eid = EuiccService.this.onGetEid(slotId); + try { + callback.onSuccess(eid); + } catch (RemoteException e) { + // Can't communicate with the phone process; ignore. + } + } + + @Override + public void getDownloadableSubscriptionMetadata(int slotId, + DownloadableSubscription subscription, + IGetDownloadableSubscriptionMetadataCallback callback) { + GetDownloadableSubscriptionMetadataResult result = + EuiccService.this.getDownloadableSubscriptionMetadata(slotId, subscription); + try { + callback.onComplete(result); + } catch (RemoteException e) { + // Can't communicate with the phone process; ignore. + } + } + } +} diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl new file mode 100644 index 000000000000..791ad9b469ef --- /dev/null +++ b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.euicc; + +parcelable GetDownloadableSubscriptionMetadataResult; diff --git a/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java new file mode 100644 index 000000000000..b7f46fac2461 --- /dev/null +++ b/core/java/android/service/euicc/GetDownloadableSubscriptionMetadataResult.java @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.service.euicc; + +import android.annotation.IntDef; +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.euicc.DownloadableSubscription; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Result of a {@link EuiccService#getDownloadableSubscriptionMetadata} operation. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ +public final class GetDownloadableSubscriptionMetadataResult implements Parcelable { + + public static final Creator<GetDownloadableSubscriptionMetadataResult> CREATOR = + new Creator<GetDownloadableSubscriptionMetadataResult>() { + @Override + public GetDownloadableSubscriptionMetadataResult createFromParcel(Parcel in) { + return new GetDownloadableSubscriptionMetadataResult(in); + } + + @Override + public GetDownloadableSubscriptionMetadataResult[] newArray(int size) { + return new GetDownloadableSubscriptionMetadataResult[size]; + } + }; + + /** @hide */ + @IntDef({ + RESULT_OK, + RESULT_GENERIC_ERROR, + RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ResultCode {} + + public static final int RESULT_OK = 0; + public static final int RESULT_MUST_DEACTIVATE_REMOVABLE_SIM = 1; + public static final int RESULT_GENERIC_ERROR = 2; + + /** Result of the operation - one of the RESULT_* constants. */ + public final @ResultCode int result; + + /** + * The {@link DownloadableSubscription} with filled-in metadata. + * + * <p>Only non-null if {@link #result} is {@link #RESULT_OK}. + */ + @Nullable + public final DownloadableSubscription subscription; + + /** Implementation-defined detailed error code in case of a failure not covered here. */ + public final int detailedCode; + + private GetDownloadableSubscriptionMetadataResult(int result, + @Nullable DownloadableSubscription subscription, int detailedCode) { + this.result = result; + this.subscription = subscription; + this.detailedCode = detailedCode; + } + + private GetDownloadableSubscriptionMetadataResult(Parcel in) { + this.result = in.readInt(); + this.subscription = DownloadableSubscription.CREATOR.createFromParcel(in); + this.detailedCode = in.readInt(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(result); + this.subscription.writeToParcel(dest, 0); + dest.writeInt(detailedCode); + } + + /** Return a result indicating that the download was successful. */ + public static GetDownloadableSubscriptionMetadataResult success( + DownloadableSubscription subscription) { + return new GetDownloadableSubscriptionMetadataResult(RESULT_OK, subscription, + 0 /* detailedCode */); + } + + /** + * Return a result indicating that the removable SIM must be deactivated to perform the + * operation. + */ + public static GetDownloadableSubscriptionMetadataResult mustDeactivateRemovableSim() { + return new GetDownloadableSubscriptionMetadataResult(RESULT_MUST_DEACTIVATE_REMOVABLE_SIM, + null /* subscription */, 0 /* detailedCode */); + } + + /** + * Return a result indicating that an error occurred for which no other more specific error + * code has been defined. + * + * @param detailedCode an implementation-defined detailed error code for debugging purposes. + */ + public static GetDownloadableSubscriptionMetadataResult genericError(int detailedCode) { + return new GetDownloadableSubscriptionMetadataResult(RESULT_GENERIC_ERROR, + null /* subscription */, detailedCode); + } + + @Override + public int describeContents() { + return 0; + } +}
\ No newline at end of file diff --git a/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl b/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl new file mode 100644 index 000000000000..0677cbe3ca1c --- /dev/null +++ b/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.euicc; + +import android.service.euicc.DownloadResult; + +/** @hide */ +oneway interface IDownloadSubscriptionCallback { + void onComplete(in DownloadResult result); +}
\ No newline at end of file diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl new file mode 100644 index 000000000000..58fe262c8541 --- /dev/null +++ b/core/java/android/service/euicc/IEuiccService.aidl @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.euicc; + +import android.service.euicc.IDownloadSubscriptionCallback; +import android.service.euicc.IGetDownloadableSubscriptionMetadataCallback; +import android.service.euicc.IGetEidCallback; +import android.telephony.euicc.DownloadableSubscription; + +/** @hide */ +oneway interface IEuiccService { + void downloadSubscription(int slotId, in DownloadableSubscription subscription, + boolean switchAfterDownload, in IDownloadSubscriptionCallback callback); + void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription, + in IGetDownloadableSubscriptionMetadataCallback callback); + void getEid(int slotId, in IGetEidCallback callback); +}
\ No newline at end of file diff --git a/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl b/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl new file mode 100644 index 000000000000..3353061ad93e --- /dev/null +++ b/core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.euicc; + +import android.service.euicc.GetDownloadableSubscriptionMetadataResult; + +/** @hide */ +oneway interface IGetDownloadableSubscriptionMetadataCallback { + void onComplete(in GetDownloadableSubscriptionMetadataResult result); +}
\ No newline at end of file diff --git a/core/java/android/service/euicc/IGetEidCallback.aidl b/core/java/android/service/euicc/IGetEidCallback.aidl new file mode 100644 index 000000000000..35ee9c25a48e --- /dev/null +++ b/core/java/android/service/euicc/IGetEidCallback.aidl @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.service.euicc; + +/** @hide */ +oneway interface IGetEidCallback { + void onSuccess(String eid); +}
\ No newline at end of file diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index faaca532dee9..48a460dc1649 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1644,6 +1644,21 @@ <permission android:name="android.permission.BIND_IMS_SERVICE" android:protectionLevel="signature|privileged" /> + <!-- Allows an application to manage embedded subscriptions (those on a eUICC) through + EuiccManager APIs. + <p>Protection level: signature|privileged|development + TODO(b/35851809): Mark this as a SystemApi. + @hide --> + <permission android:name="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" + android:protectionLevel="signature|privileged|development" /> + + <!-- Must be required by an EuiccService to ensure that only the system can bind to it. + <p>Protection level: signature + TODO(b/35851809): Mark this as a SystemApi. + @hide --> + <permission android:name="android.permission.BIND_EUICC_SERVICE" + android:protectionLevel="signature" /> + <!-- ================================== --> <!-- Permissions for sdcard interaction --> diff --git a/telephony/java/android/telephony/UiccAccessRule.aidl b/telephony/java/android/telephony/UiccAccessRule.aidl new file mode 100644 index 000000000000..f923c4562754 --- /dev/null +++ b/telephony/java/android/telephony/UiccAccessRule.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony; + +parcelable UiccAccessRule; diff --git a/telephony/java/android/telephony/UiccAccessRule.java b/telephony/java/android/telephony/UiccAccessRule.java new file mode 100644 index 000000000000..1ac4c5cf7d80 --- /dev/null +++ b/telephony/java/android/telephony/UiccAccessRule.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.telephony; + +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.content.pm.PackageInfo; +import android.content.pm.Signature; +import android.os.Parcel; +import android.os.Parcelable; +import android.text.TextUtils; + +import com.android.internal.telephony.uicc.IccUtils; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +/** + * Describes a single UICC access rule according to the GlobalPlatform Secure Element Access Control + * specification. + * + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ +public final class UiccAccessRule implements Parcelable { + private static final String TAG = "UiccAccessRule"; + + private static final int ENCODING_VERSION = 1; + + public static final Creator<UiccAccessRule> CREATOR = new Creator<UiccAccessRule>() { + @Override + public UiccAccessRule createFromParcel(Parcel in) { + return new UiccAccessRule(in); + } + + @Override + public UiccAccessRule[] newArray(int size) { + return new UiccAccessRule[size]; + } + }; + + /** + * Encode these access rules as a byte array which can be parsed with {@link #decodeRules}. + * @hide + */ + public static byte[] encodeRules(UiccAccessRule[] accessRules) { + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream output = new DataOutputStream(baos); + output.writeInt(ENCODING_VERSION); + output.writeInt(accessRules.length); + for (UiccAccessRule accessRule : accessRules) { + output.writeInt(accessRule.mCertificateHash.length); + output.write(accessRule.mCertificateHash); + output.writeUTF(accessRule.mPackageName); + output.writeLong(accessRule.mAccessType); + } + output.close(); + return baos.toByteArray(); + } catch (IOException e) { + throw new IllegalStateException( + "ByteArrayOutputStream should never lead to an IOException", e); + } + } + + /** + * Decodes a byte array generated with {@link #encodeRules}. + * @hide + */ + public static UiccAccessRule[] decodeRules(byte[] encodedRules) { + ByteArrayInputStream bais = new ByteArrayInputStream(encodedRules); + try (DataInputStream input = new DataInputStream(bais)) { + input.readInt(); // version; currently ignored + int count = input.readInt(); + UiccAccessRule[] accessRules = new UiccAccessRule[count]; + for (int i = 0; i < count; i++) { + int certificateHashLength = input.readInt(); + byte[] certificateHash = new byte[certificateHashLength]; + input.readFully(certificateHash); + String packageName = input.readUTF(); + long accessType = input.readLong(); + accessRules[i] = new UiccAccessRule(certificateHash, packageName, accessType); + } + input.close(); + return accessRules; + } catch (IOException e) { + throw new IllegalStateException( + "ByteArrayInputStream should never lead to an IOException", e); + } + } + + private final byte[] mCertificateHash; + private final @Nullable String mPackageName; + // This bit is not currently used, but reserved for future use. + private final long mAccessType; + + public UiccAccessRule(byte[] certificateHash, @Nullable String packageName, long accessType) { + this.mCertificateHash = certificateHash; + this.mPackageName = packageName; + this.mAccessType = accessType; + } + + UiccAccessRule(Parcel in) { + mCertificateHash = in.createByteArray(); + mPackageName = in.readString(); + mAccessType = in.readLong(); + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeByteArray(mCertificateHash); + dest.writeString(mPackageName); + dest.writeLong(mAccessType); + } + + /** + * Return the package name this rule applies to. + * + * @return the package name, or null if this rule applies to any package signed with the given + * certificate. + */ + public @Nullable String getPackageName() { + return mPackageName; + } + + /** + * Returns the carrier privilege status associated with the given package. + * + * @param packageInfo package info fetched from + * {@link android.content.pm.PackageManager#getPackageInfo}. + * {@link android.content.pm.PackageManager#GET_SIGNATURES} must have been passed in. + * @return either {@link TelephonyManager#CARRIER_PRIVILEGE_STATUS_HAS_ACCESS} or + * {@link TelephonyManager#CARRIER_PRIVILEGE_STATUS_NO_ACCESS}. + */ + public int getCarrierPrivilegeStatus(PackageInfo packageInfo) { + if (packageInfo.signatures == null || packageInfo.signatures.length == 0) { + throw new IllegalArgumentException( + "Must use GET_SIGNATURES when looking up package info"); + } + + for (Signature sig : packageInfo.signatures) { + int accessStatus = getCarrierPrivilegeStatus(sig, packageInfo.packageName); + if (accessStatus != TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS) { + return accessStatus; + } + } + + return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; + } + + /** + * Returns the carrier privilege status for the given certificate and package name. + * + * @param signature The signature of the certificate. + * @param packageName name of the package. + * @return either {@link TelephonyManager#CARRIER_PRIVILEGE_STATUS_HAS_ACCESS} or + * {@link TelephonyManager#CARRIER_PRIVILEGE_STATUS_NO_ACCESS}. + */ + public int getCarrierPrivilegeStatus(Signature signature, String packageName) { + // SHA-1 is for backward compatible support only, strongly discouraged for new use. + byte[] certHash = getCertHash(signature, "SHA-1"); + byte[] certHash256 = getCertHash(signature, "SHA-256"); + if (matches(certHash, packageName) || matches(certHash256, packageName)) { + return TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; + } + + return TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS; + } + + private boolean matches(byte[] certHash, String packageName) { + return certHash != null && Arrays.equals(this.mCertificateHash, certHash) && + (TextUtils.isEmpty(this.mPackageName) || this.mPackageName.equals(packageName)); + } + + @Override + public String toString() { + return "cert: " + IccUtils.bytesToHexString(mCertificateHash) + " pkg: " + + mPackageName + " access: " + mAccessType; + } + + @Override + public int describeContents() { + return 0; + } + + /** + * Converts a Signature into a Certificate hash usable for comparison. + */ + private static byte[] getCertHash(Signature signature, String algo) { + try { + MessageDigest md = MessageDigest.getInstance(algo); + return md.digest(signature.toByteArray()); + } catch (NoSuchAlgorithmException ex) { + Rlog.e(TAG, "NoSuchAlgorithmException: " + ex); + } + return null; + } +} diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.aidl b/telephony/java/android/telephony/euicc/DownloadableSubscription.aidl new file mode 100644 index 000000000000..26679c913050 --- /dev/null +++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.aidl @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.euicc; + +parcelable DownloadableSubscription; diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java new file mode 100644 index 000000000000..e8809781886e --- /dev/null +++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.telephony.euicc; + +import android.annotation.Nullable; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.Preconditions; + +/** + * Information about a subscription which is available for download. + * + * TODO(b/35851809): Make this public. + * @hide + */ +public final class DownloadableSubscription implements Parcelable { + + public static final Creator<DownloadableSubscription> CREATOR = + new Creator<DownloadableSubscription>() { + @Override + public DownloadableSubscription createFromParcel(Parcel in) { + return new DownloadableSubscription(in); + } + + @Override + public DownloadableSubscription[] newArray(int size) { + return new DownloadableSubscription[size]; + } + }; + + /** + * Activation code. May be null for subscriptions which are not based on activation codes, e.g. + * to download a default subscription assigned to this device. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ + @Nullable + public final String encodedActivationCode; + + // see getCarrierName and setCarrierName + @Nullable + private String carrierName; + // see isConsentGranted and setConsentGranted + private boolean consentGranted; + + /** @hide */ + private DownloadableSubscription(String encodedActivationCode) { + this.encodedActivationCode = encodedActivationCode; + } + + private DownloadableSubscription(Parcel in) { + encodedActivationCode = in.readString(); + carrierName = in.readString(); + consentGranted = in.readInt() == 1; + } + + /** + * Create a DownloadableSubscription for the given activation code. + * + * @param encodedActivationCode the activation code to use. Must not be null. + * @return the {@link DownloadableSubscription} which may be passed to + * {@link EuiccManager#downloadSubscription}. + */ + public static DownloadableSubscription forActivationCode(String encodedActivationCode) { + Preconditions.checkNotNull(encodedActivationCode, "Activation code may not be null"); + return new DownloadableSubscription(encodedActivationCode); + } + + /** + * Set the user-visible carrier name. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ + public void setCarrierName(String carrierName) { + this.carrierName = carrierName; + } + + /** + * Returns the user-visible carrier name. + * + * <p>Only present for downloadable subscriptions that were queried from a server (as opposed to + * those created with {@link #forActivationCode}). May be populated with + * {@link EuiccManager#getDownloadableSubscriptionMetadata}. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ + @Nullable + public String getCarrierName() { + return this.carrierName; + } + + + /** + * Mark this download as being consented to by the user. + * @hide + */ + public void setConsentGranted() { + this.consentGranted = true; + } + + /** + * Returns whether the user has granted consent to download this subscription. + * + * <p>The {@link android.service.euicc.EuiccService} implementation should permit a subscription + * download if this is set, even if the calling app doesn't have permission to download it. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ + public boolean isConsentGranted() { + return this.consentGranted; + } + + /** + * Unset any untrusted fields. + * + * <p>Should be called by the platform whenever an instance is received from an untrusted + * source to reset any secure fields that may only be set by the platform. + * @hide + */ + public final void clearUntrustedFields() { + this.consentGranted = false; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + dest.writeString(encodedActivationCode); + dest.writeString(carrierName); + dest.writeInt(consentGranted ? 1 : 0); + } + + @Override + public int describeContents() { + return 0; + } +} diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java new file mode 100644 index 000000000000..73cf162b4676 --- /dev/null +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package android.telephony.euicc; + +import android.annotation.Nullable; +import android.annotation.SdkConstant; +import android.annotation.SystemApi; +import android.app.Activity; +import android.app.PendingIntent; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.os.RemoteException; +import android.os.ServiceManager; + +import com.android.internal.telephony.euicc.IEuiccController; + +/** + * EuiccManager is the application interface to eUICCs, or eSIMs/embedded SIMs. + * + * <p>You do not instantiate this class directly; instead, you retrieve an instance through + * {@link Context#getSystemService(String)} and {@link Context#EUICC_SERVICE}. + * + * <p>See {@link #isEnabled} before attempting to use these APIs. + * + * TODO(b/35851809): Make this public. + * @hide + */ +public class EuiccManager { + + /** + * Intent action to launch the embedded SIM (eUICC) management settings screen. + * + * <p>This screen shows a list of embedded profiles and offers the user the ability to switch + * between them, download new profiles, and delete unused profiles. + * + * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if + * {@link #isEnabled} is false. + */ + @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = + "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS"; + + /** + * Intent action to provision an embedded subscription. + * + * <p>May be called during device provisioning to launch a screen to perform embedded SIM + * provisioning, e.g. if no physical SIM is present and the user elects to configure their + * embedded SIM. + * + * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if + * {@link #isEnabled} is false or if the device is already provisioned. + * + * TODO(b/35851809): Make this a SystemApi. + */ + @SdkConstant(SdkConstant.SdkConstantType.ACTIVITY_INTENT_ACTION) + public static final String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = + "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION"; + + /** + * Result code for an operation indicating that the operation succeeded. + */ + public static final int EMBEDDED_SUBSCRIPTION_RESULT_OK = 0; + + /** + * Result code for an operation indicating that the user must take some action before the + * operation can continue. + * + * @see #startResolutionActivity + */ + public static final int EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR = 1; + + /** + * Result code for an operation indicating that a generic error occurred. + * + * <p>Note that in the future, other result codes may be returned indicating more specific + * errors. Thus, the caller should check for {@link #EMBEDDED_SUBSCRIPTION_RESULT_OK} or + * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} to determine if the operation + * succeeded or failed with a user-resolvable error, and assume the operation failed for any + * other result, rather than checking for this specific value. + */ + public static final int EMBEDDED_SUBSCRIPTION_RESULT_GENERIC_ERROR = 2; + + /** + * Key for an extra set on {@link PendingIntent} result callbacks providing a detailed result + * code. + * + * <p>This code is an implementation detail of the embedded subscription manager and is only + * intended for logging or debugging purposes. + */ + public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE = + "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DETAILED_CODE"; + + /** + * The key for an extra set on {@link #getDownloadableSubscriptionMetadata} PendingIntent result + * callbacks providing the downloadable subscription metadata. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ + public static final String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION = + "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION"; + + private final Context mContext; + private final IEuiccController mController; + + /** @hide */ + public EuiccManager(Context context) { + mContext = context; + mController = IEuiccController.Stub.asInterface(ServiceManager.getService("econtroller")); + } + + /** + * Whether embedded subscriptions are currently enabled. + * + * <p>Even on devices with the {@link PackageManager#FEATURE_TELEPHONY_EUICC} feature, embedded + * subscriptions may be turned off, e.g. because of a carrier restriction from an inserted + * physical SIM. Therefore, this runtime check should be used before accessing embedded + * subscription APIs. + * + * @return true if embedded subscriptions are currently enabled. + */ + public boolean isEnabled() { + // In the future, this may reach out to IEuiccController (if non-null) to check any dynamic + // restrictions. + return mController != null; + } + + /** + * Returns the EID identifying the eUICC hardware. + * + * <p>Requires that the calling app has carrier privileges on the active subscription on the + * eUICC. + * + * @return the EID. May be null if {@link #isEnabled()} is false or the eUICC is not ready. + */ + @Nullable + public String getEid() { + if (!isEnabled()) { + return null; + } + try { + return mController.getEid(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Attempt to download the given {@link DownloadableSubscription}. + * + * <p>Requires the calling app to be authorized to manage both the currently-active subscription + * and the subscription to be downloaded according to the subscription metadata. Without the + * former, a {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR} will be returned in the + * callback intent to prompt the user to accept the download. + * + * @param subscription the subscription to download. + * @param switchAfterDownload if true, the profile will be activated upon successful download. + * @param callbackIntent a PendingIntent to launch when the operation completes. + */ + public void downloadSubscription(DownloadableSubscription subscription, + boolean switchAfterDownload, PendingIntent callbackIntent) { + if (!isEnabled()) { + sendUnavailableError(callbackIntent); + return; + } + try { + mController.downloadSubscription(subscription, switchAfterDownload, callbackIntent); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** + * Start an activity to resolve a user-resolvable error. + * + * <p>If an operation returns {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}, this + * method may be called to prompt the user to resolve the issue. + * + * @param activity the calling activity (which should be in the foreground). + * @param requestCode an application-specific request code which will be provided to + * {@link Activity#onActivityResult} upon completion. Note that the operation may still be + * in progress when the resolution activity completes; it is not fully finished until the + * callback intent is triggered. + * @param resultIntent the Intent provided to the initial callback intent which failed with + * {@link #EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR}. + * @param callbackIntent a PendingIntent to launch when the operation completes. This is + * trigered upon completion of the original operation that required user resolution. + */ + public void startResolutionActivity(Activity activity, int requestCode, Intent resultIntent, + PendingIntent callbackIntent) { + // TODO(b/33075886): Implement this API. + throw new UnsupportedOperationException("Not implemented"); + } + + /** + * Fills in the metadata for a DownloadableSubscription. + * + * <p>May be used in cases that a DownloadableSubscription was constructed to download a + * profile, but the metadata for the profile is unknown (e.g. we only know the activation code). + * The callback will be triggered with an Intent with + * {@link #EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTION} set to the + * downloadable subscription metadata upon success. + * + * <p>Requires that the calling app has the + * {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. This is for + * internal system use only. + * + * @param subscription the subscription which needs metadata filled in + * @param callbackIntent a PendingIntent to launch when the operation completes. + * @hide + * + * TODO(b/35851809): Make this a SystemApi. + */ + @SystemApi + public void getDownloadableSubscriptionMetadata( + DownloadableSubscription subscription, PendingIntent callbackIntent) { + if (!isEnabled()) { + sendUnavailableError(callbackIntent); + return; + } + try { + mController.getDownloadableSubscriptionMetadata(subscription, callbackIntent); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + private static void sendUnavailableError(PendingIntent callbackIntent) { + try { + callbackIntent.send(EMBEDDED_SUBSCRIPTION_RESULT_GENERIC_ERROR); + } catch (PendingIntent.CanceledException e) { + // Caller canceled the callback; do nothing. + } + } +} diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl new file mode 100644 index 000000000000..b2092bb160d1 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.telephony.euicc; + +import android.app.PendingIntent; +import android.telephony.euicc.DownloadableSubscription; + +/** @hide */ +interface IEuiccController { + oneway void getDownloadableSubscriptionMetadata(in DownloadableSubscription subscription, + in PendingIntent callbackIntent); + String getEid(); + oneway void downloadSubscription(in DownloadableSubscription subscription, + boolean switchAfterDownload, in PendingIntent callbackIntent); +}
\ No newline at end of file |