From 7b69a86b02e1e4b469181a8ad286f473df8b6352 Mon Sep 17 00:00:00 2001 From: Jeff Davidson Date: Fri, 16 Jun 2017 15:20:34 -0700 Subject: [PATCH] Add EuiccManager#retainSubscriptionsOnFactoryReset API. By default, all subscriptions are wiped on first boot after a factory reset. This ensures that if data is wiped outside of userspace (e.g. in fastboot/recovery), the profiles are wiped, as there's no way to offer this option to users in those modes - the radio isn't available for us to access the eUICC. This API provides a way to bypass this wipe if the user opts to retain the policies for a wipe done from userspace (e.g. by unchecking the "Wipe eUICC" checkbox in platform settings before wiping). We tell the LPA to note this and skip the wipe on the ensuing factory reset. Change-Id: I2fe472417497e28b043841a5aa2dc9efa45ebbff Test: TreeHugger Fixes: 62681577 --- Android.mk | 1 + .../android/service/euicc/EuiccService.java | 31 +++++++++++++++++++ .../android/service/euicc/IEuiccService.aidl | 3 ++ ...nSubscriptionsForFactoryResetCallback.aidl | 22 +++++++++++++ .../android/telephony/euicc/EuiccManager.java | 30 ++++++++++++++++++ .../telephony/euicc/IEuiccController.aidl | 1 + 6 files changed, 88 insertions(+) create mode 100644 core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl diff --git a/Android.mk b/Android.mk index 933ac6200a3e7..55ea69a7b437f 100644 --- a/Android.mk +++ b/Android.mk @@ -292,6 +292,7 @@ LOCAL_SRC_FILES += \ core/java/android/service/euicc/IGetEidCallback.aidl \ core/java/android/service/euicc/IGetEuiccInfoCallback.aidl \ core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl \ + core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl \ core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl \ core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl \ core/java/android/service/gatekeeper/IGateKeeperService.aidl \ diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java index 26f85288699a0..0c2e4b7ada261 100644 --- a/core/java/android/service/euicc/EuiccService.java +++ b/core/java/android/service/euicc/EuiccService.java @@ -316,6 +316,21 @@ public abstract class EuiccService extends Service { */ public abstract int onEraseSubscriptions(int slotId); + /** + * Ensure that subscriptions will be retained on the next factory reset. + * + *

Called directly before a factory reset. Assumes that a normal factory reset will lead to + * profiles being erased on first boot (to cover fastboot/recovery wipes), so the implementation + * should persist some bit that will remain accessible after the factory reset to bypass this + * flow when this method is called. + * + * @param slotId ID of the SIM slot to use for the operation. This is currently not populated + * but is here to future-proof the APIs. + * @return the result of the operation. May be one of the predefined {@code RESULT_} constants + * or any implementation-specific code starting with {@link #RESULT_FIRST_USER}. + */ + public abstract int onRetainSubscriptionsForFactoryReset(int slotId); + /** * Wrapper around IEuiccService that forwards calls to implementations of {@link EuiccService}. */ @@ -488,5 +503,21 @@ public abstract class EuiccService extends Service { } }); } + + @Override + public void retainSubscriptionsForFactoryReset(int slotId, + IRetainSubscriptionsForFactoryResetCallback callback) { + mExecutor.execute(new Runnable() { + @Override + public void run() { + int result = EuiccService.this.onRetainSubscriptionsForFactoryReset(slotId); + try { + callback.onComplete(result); + } catch (RemoteException e) { + // Can't communicate with the phone process; ignore. + } + } + }); + } } } diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl index 18ea915d5dc7c..e10dd8cdf616e 100644 --- a/core/java/android/service/euicc/IEuiccService.aidl +++ b/core/java/android/service/euicc/IEuiccService.aidl @@ -24,6 +24,7 @@ import android.service.euicc.IGetDownloadableSubscriptionMetadataCallback; import android.service.euicc.IGetEidCallback; import android.service.euicc.IGetEuiccInfoCallback; import android.service.euicc.IGetEuiccProfileInfoListCallback; +import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback; import android.service.euicc.ISwitchToSubscriptionCallback; import android.service.euicc.IUpdateSubscriptionNicknameCallback; import android.telephony.euicc.DownloadableSubscription; @@ -46,4 +47,6 @@ oneway interface IEuiccService { void updateSubscriptionNickname(int slotId, String iccid, String nickname, in IUpdateSubscriptionNicknameCallback callback); void eraseSubscriptions(int slotId, in IEraseSubscriptionsCallback callback); + void retainSubscriptionsForFactoryReset( + int slotId, in IRetainSubscriptionsForFactoryResetCallback callback); } \ No newline at end of file diff --git a/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl b/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl new file mode 100644 index 0000000000000..127683059c021 --- /dev/null +++ b/core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.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 IRetainSubscriptionsForFactoryResetCallback { + void onComplete(int result); +} \ No newline at end of file diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java index f22a6327c80f4..8304d84d8a2b8 100644 --- a/telephony/java/android/telephony/euicc/EuiccManager.java +++ b/telephony/java/android/telephony/euicc/EuiccManager.java @@ -475,6 +475,36 @@ public class EuiccManager { } } + /** + * Ensure that subscriptions will be retained on the next factory reset. + * + *

By default, all subscriptions on the eUICC are erased the first time a device boots (ever + * and after factory resets). This ensures that the data is wiped after a factory reset is + * performed via fastboot or recovery mode, as these modes do not support the necessary radio + * communication needed to wipe the eSIM. + * + *

However, this method may be called right before a factory reset issued via settings when + * the user elects to retain subscriptions. Doing so will mark them for retention so that they + * are not cleared after the ensuing reset. + * + *

Requires that the calling app has the {@link android.Manifest.permission#MASTER_CLEAR} + * permission. This is for internal system use only. + * + * @param callbackIntent a PendingIntent to launch when the operation completes. + * @hide + */ + public void retainSubscriptionsForFactoryReset(PendingIntent callbackIntent) { + if (!isEnabled()) { + sendUnavailableError(callbackIntent); + return; + } + try { + mController.retainSubscriptionsForFactoryReset(callbackIntent); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + private static void sendUnavailableError(PendingIntent callbackIntent) { try { callbackIntent.send(EMBEDDED_SUBSCRIPTION_RESULT_ERROR); diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl index fa43631cee9e2..b3fc90db75d3b 100644 --- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl +++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl @@ -40,4 +40,5 @@ interface IEuiccController { oneway void updateSubscriptionNickname(int subscriptionId, String nickname, in PendingIntent callbackIntent); oneway void eraseSubscriptions(in PendingIntent callbackIntent); + oneway void retainSubscriptionsForFactoryReset(in PendingIntent callbackIntent); } \ No newline at end of file