diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 9118f01b498cb..df2c6fcd5c8d5 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -3173,6 +3173,14 @@ public class Intent implements Parcelable, Cloneable { /** {@hide} */ public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR"; + /** + * Boolean intent extra to be used with {@link ACTION_MASTER_CLEAR} in order to force a factory + * reset even if {@link android.os.UserManager.DISALLOW_FACTORY_RESET} is set. + * @hide + */ + public static final String EXTRA_FORCE_MASTER_CLEAR = + "android.intent.extra.FORCE_MASTER_CLEAR"; + /** * Broadcast action: report that a settings element is being restored from backup. The intent * contains three extras: EXTRA_SETTING_NAME is a string naming the restored setting, diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index 4abbf0efc81da..acb24e1ccf9e8 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -570,18 +570,19 @@ public class RecoverySystem { * @throws SecurityException if the current user is not allowed to wipe data. */ public static void rebootWipeUserData(Context context) throws IOException { - rebootWipeUserData(context, false, context.getPackageName()); + rebootWipeUserData(context, false /* shutdown */, context.getPackageName(), + false /* force */); } /** {@hide} */ public static void rebootWipeUserData(Context context, String reason) throws IOException { - rebootWipeUserData(context, false, reason); + rebootWipeUserData(context, false /* shutdown */, reason, false /* force */); } /** {@hide} */ public static void rebootWipeUserData(Context context, boolean shutdown) throws IOException { - rebootWipeUserData(context, shutdown, context.getPackageName()); + rebootWipeUserData(context, shutdown, context.getPackageName(), false /* force */); } /** @@ -595,6 +596,9 @@ public class RecoverySystem { * @param shutdown if true, the device will be powered down after * the wipe completes, rather than being rebooted * back to the regular system. + * @param reason the reason for the wipe that is visible in the logs + * @param force whether the {@link UserManager.DISALLOW_FACTORY_RESET} user restriction + * should be ignored * * @throws IOException if writing the recovery command file * fails, or if the reboot itself fails. @@ -602,10 +606,10 @@ public class RecoverySystem { * * @hide */ - public static void rebootWipeUserData(Context context, boolean shutdown, String reason) - throws IOException { + public static void rebootWipeUserData(Context context, boolean shutdown, String reason, + boolean force) throws IOException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); - if (um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) { + if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) { throw new SecurityException("Wiping data is not allowed for this user."); } final ConditionVariable condition = new ConditionVariable(); diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index 1653db95f15bc..6f8edecb1777f 100644 --- a/services/core/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java @@ -47,6 +47,7 @@ public class MasterClearReceiver extends BroadcastReceiver { final String reason = intent.getStringExtra(Intent.EXTRA_REASON); final boolean wipeExternalStorage = intent.getBooleanExtra( Intent.EXTRA_WIPE_EXTERNAL_STORAGE, false); + final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false); Slog.w(TAG, "!!! FACTORY RESET !!!"); // The reboot call is blocking, so we need to do it on another thread. @@ -54,7 +55,7 @@ public class MasterClearReceiver extends BroadcastReceiver { @Override public void run() { try { - RecoverySystem.rebootWipeUserData(context, shutdown, reason); + RecoverySystem.rebootWipeUserData(context, shutdown, reason, forceWipe); Log.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { Slog.e(TAG, "Can't perform master clear/factory reset", e);