Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7b69a86b authored by Jeff Davidson's avatar Jeff Davidson
Browse files

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
parent d20db5a0
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -292,6 +292,7 @@ LOCAL_SRC_FILES += \
	core/java/android/service/euicc/IGetEidCallback.aidl \
	core/java/android/service/euicc/IGetEidCallback.aidl \
	core/java/android/service/euicc/IGetEuiccInfoCallback.aidl \
	core/java/android/service/euicc/IGetEuiccInfoCallback.aidl \
	core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.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/ISwitchToSubscriptionCallback.aidl \
	core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl \
	core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl \
	core/java/android/service/gatekeeper/IGateKeeperService.aidl \
	core/java/android/service/gatekeeper/IGateKeeperService.aidl \
+31 −0
Original line number Original line Diff line number Diff line
@@ -316,6 +316,21 @@ public abstract class EuiccService extends Service {
     */
     */
    public abstract int onEraseSubscriptions(int slotId);
    public abstract int onEraseSubscriptions(int slotId);


    /**
     * Ensure that subscriptions will be retained on the next factory reset.
     *
     * <p>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}.
     * 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.
                    }
                }
            });
        }
    }
    }
}
}
+3 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import android.service.euicc.IGetDownloadableSubscriptionMetadataCallback;
import android.service.euicc.IGetEidCallback;
import android.service.euicc.IGetEidCallback;
import android.service.euicc.IGetEuiccInfoCallback;
import android.service.euicc.IGetEuiccInfoCallback;
import android.service.euicc.IGetEuiccProfileInfoListCallback;
import android.service.euicc.IGetEuiccProfileInfoListCallback;
import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.DownloadableSubscription;
@@ -46,4 +47,6 @@ oneway interface IEuiccService {
    void updateSubscriptionNickname(int slotId, String iccid, String nickname,
    void updateSubscriptionNickname(int slotId, String iccid, String nickname,
            in IUpdateSubscriptionNicknameCallback callback);
            in IUpdateSubscriptionNicknameCallback callback);
    void eraseSubscriptions(int slotId, in IEraseSubscriptionsCallback callback);
    void eraseSubscriptions(int slotId, in IEraseSubscriptionsCallback callback);
    void retainSubscriptionsForFactoryReset(
            int slotId, in IRetainSubscriptionsForFactoryResetCallback callback);
}
}
 No newline at end of file
+22 −0
Original line number Original line Diff line number Diff line
/*
 * 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
+30 −0
Original line number Original line Diff line number Diff line
@@ -475,6 +475,36 @@ public class EuiccManager {
        }
        }
    }
    }


    /**
     * Ensure that subscriptions will be retained on the next factory reset.
     *
     * <p>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.
     *
     * <p>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.
     *
     * <p>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) {
    private static void sendUnavailableError(PendingIntent callbackIntent) {
        try {
        try {
            callbackIntent.send(EMBEDDED_SUBSCRIPTION_RESULT_ERROR);
            callbackIntent.send(EMBEDDED_SUBSCRIPTION_RESULT_ERROR);
Loading