diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 673a8ba661b67..57db9d19f42d4 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -61,6 +61,7 @@ import java.util.HashSet; import java.util.Locale; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; @@ -101,6 +102,9 @@ public class RecoverySystem { private static final String ACTION_EUICC_FACTORY_RESET = "com.android.internal.action.EUICC_FACTORY_RESET"; + /** used in {@link #wipeEuiccData} as package name of callback intent */ + private static final String PACKAGE_NAME_WIPING_EUICC_DATA_CALLBACK = "android"; + /** * The recovery image uses this file to identify the location (i.e. blocks) * of an OTA package on the /data partition. The block map file is @@ -751,7 +755,7 @@ public class RecoverySystem { // Block until the ordered broadcast has completed. condition.block(); - wipeEuiccData(context, wipeEuicc); + wipeEuiccData(context, wipeEuicc, PACKAGE_NAME_WIPING_EUICC_DATA_CALLBACK); String shutdownArg = null; if (shutdown) { @@ -767,19 +771,29 @@ public class RecoverySystem { bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg); } - private static void wipeEuiccData(Context context, final boolean isWipeEuicc) { + /** + * Returns whether wipe Euicc data successfully or not. + * + * @param isWipeEuicc whether we want to wipe Euicc data or not + * @param packageName the package name of the caller app. + * + * @hide + */ + public static boolean wipeEuiccData( + Context context, final boolean isWipeEuicc, final String packageName) { ContentResolver cr = context.getContentResolver(); if (Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) == 0) { // If the eUICC isn't provisioned, there's no reason to either wipe or retain profiles, // as there's nothing to wipe nor retain. Log.d(TAG, "Skipping eUICC wipe/retain as it is not provisioned"); - return; + return true; } EuiccManager euiccManager = (EuiccManager) context.getSystemService( Context.EUICC_SERVICE); if (euiccManager != null && euiccManager.isEnabled()) { CountDownLatch euiccFactoryResetLatch = new CountDownLatch(1); + final AtomicBoolean wipingSucceeded = new AtomicBoolean(false); BroadcastReceiver euiccWipeFinishReceiver = new BroadcastReceiver() { @Override @@ -801,6 +815,7 @@ public class RecoverySystem { } else { Log.d(TAG, "Successfully retained euicc data."); } + wipingSucceeded.set(true /* newValue */); } euiccFactoryResetLatch.countDown(); } @@ -808,7 +823,7 @@ public class RecoverySystem { }; Intent intent = new Intent(ACTION_EUICC_FACTORY_RESET); - intent.setPackage("android"); + intent.setPackage(packageName); PendingIntent callbackIntent = PendingIntent.getBroadcastAsUser( context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT, UserHandle.SYSTEM); IntentFilter filterConsent = new IntentFilter(); @@ -839,8 +854,8 @@ public class RecoverySystem { } else { Log.e(TAG, "Timeout retaining eUICC data."); } + return false; } - context.getApplicationContext().unregisterReceiver(euiccWipeFinishReceiver); } catch (InterruptedException e) { Thread.currentThread().interrupt(); if (isWipeEuicc) { @@ -848,8 +863,13 @@ public class RecoverySystem { } else { Log.e(TAG, "Retaining eUICC data interrupted", e); } + return false; + } finally { + context.getApplicationContext().unregisterReceiver(euiccWipeFinishReceiver); } + return wipingSucceeded.get(); } + return false; } /** {@hide} */