diff options
5 files changed, 51 insertions, 11 deletions
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java index a3b836adfc8b..d4688f8794a4 100644 --- a/core/java/android/os/RecoverySystem.java +++ b/core/java/android/os/RecoverySystem.java @@ -933,6 +933,12 @@ public class RecoverySystem { rebootWipeUserData(context, shutdown, reason, force, false /* wipeEuicc */); } + /** {@hide} */ + public static void rebootWipeUserData(Context context, boolean shutdown, String reason, + boolean force, boolean wipeEuicc) throws IOException { + rebootWipeUserData(context, shutdown, reason, force, wipeEuicc, false /* keepMemtagMode */); + } + /** * Reboots the device and wipes the user data and cache * partitions. This is sometimes called a "factory reset", which @@ -948,6 +954,7 @@ public class RecoverySystem { * @param force whether the {@link UserManager.DISALLOW_FACTORY_RESET} user restriction * should be ignored * @param wipeEuicc whether wipe the euicc data + * @param keepMemtagMode whether to tell recovery to keep currently configured memtag mode * * @throws IOException if writing the recovery command file * fails, or if the reboot itself fails. @@ -956,7 +963,7 @@ public class RecoverySystem { * @hide */ public static void rebootWipeUserData(Context context, boolean shutdown, String reason, - boolean force, boolean wipeEuicc) throws IOException { + boolean force, boolean wipeEuicc, boolean keepMemtagMode) throws IOException { UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE); if (!force && um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) { throw new SecurityException("Wiping data is not allowed for this user."); @@ -996,8 +1003,13 @@ public class RecoverySystem { reasonArg = "--reason=" + sanitizeArg(reason + "," + timeStamp); } + String memtagArg = null; + if (keepMemtagMode) { + memtagArg = "--keep_memtag_mode"; + } + final String localeArg = "--locale=" + Locale.getDefault().toLanguageTag() ; - bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg); + bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg, memtagArg); } /** diff --git a/services/core/java/com/android/server/MasterClearReceiver.java b/services/core/java/com/android/server/MasterClearReceiver.java index 5a15f17a0922..2b30c013235c 100644 --- a/services/core/java/com/android/server/MasterClearReceiver.java +++ b/services/core/java/com/android/server/MasterClearReceiver.java @@ -88,6 +88,9 @@ public class MasterClearReceiver extends BroadcastReceiver { mWipeEsims = intent.getBooleanExtra(Intent.EXTRA_WIPE_ESIMS, false); final boolean forceWipe = intent.getBooleanExtra(Intent.EXTRA_FORCE_MASTER_CLEAR, false) || intent.getBooleanExtra(Intent.EXTRA_FORCE_FACTORY_RESET, false); + // This is ONLY used by TestHarnessService within System Server, so we don't add a proper + // API constant in Intent for this. + final boolean keepMemtagMode = intent.getBooleanExtra("keep_memtag_mode", false); // TODO(b/189938391): properly handle factory reset on headless system user mode. final int sendingUserId = getSendingUserId(); @@ -110,9 +113,11 @@ public class MasterClearReceiver extends BroadcastReceiver { try { Slog.i(TAG, "Calling RecoverySystem.rebootWipeUserData(context, " + "shutdown=" + shutdown + ", reason=" + reason - + ", forceWipe=" + forceWipe + ", wipeEsims=" + mWipeEsims + ")"); + + ", forceWipe=" + forceWipe + ", wipeEsims=" + mWipeEsims + + ", keepMemtagMode=" + keepMemtagMode + ")"); RecoverySystem - .rebootWipeUserData(context, shutdown, reason, forceWipe, mWipeEsims); + .rebootWipeUserData( + context, shutdown, reason, forceWipe, mWipeEsims, keepMemtagMode); Slog.wtf(TAG, "Still running after master clear?!"); } catch (IOException e) { Slog.e(TAG, "Can't perform master clear/factory reset", e); diff --git a/services/core/java/com/android/server/testharness/TestHarnessModeService.java b/services/core/java/com/android/server/testharness/TestHarnessModeService.java index 9a9b83602832..1f884baf13a1 100644 --- a/services/core/java/com/android/server/testharness/TestHarnessModeService.java +++ b/services/core/java/com/android/server/testharness/TestHarnessModeService.java @@ -71,6 +71,7 @@ import java.util.Set; public class TestHarnessModeService extends SystemService { public static final String TEST_HARNESS_MODE_PROPERTY = "persist.sys.test_harness"; private static final String TAG = TestHarnessModeService.class.getSimpleName(); + private boolean mEnableKeepMemtagMode = false; private PersistentDataBlockManagerInternal mPersistentDataBlockManagerInternal; @@ -298,6 +299,18 @@ public class TestHarnessModeService extends SystemService { switch (cmd) { case "enable": case "restore": + String opt; + while ((opt = getNextOption()) != null) { + switch (opt) { + case "--keep-memtag": + mEnableKeepMemtagMode = true; + break; + default: + getErrPrintWriter().println("Invalid option: " + opt); + return 1; + } + } + checkPermissions(); final long originalId = Binder.clearCallingIdentity(); try { @@ -357,6 +370,7 @@ public class TestHarnessModeService extends SystemService { i.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); i.putExtra(Intent.EXTRA_REASON, TAG); i.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, true); + i.putExtra("keep_memtag_mode", mEnableKeepMemtagMode); getContext().sendBroadcastAsUser(i, UserHandle.SYSTEM); return 0; } diff --git a/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java index cc97b8f792f9..76a1c3cae8dd 100644 --- a/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/MasterClearReceiverTest.java @@ -154,10 +154,11 @@ public final class MasterClearReceiverTest { intent.putExtra(Intent.EXTRA_REASON, "Self destruct"); intent.putExtra(Intent.EXTRA_FORCE_FACTORY_RESET, true); intent.putExtra(Intent.EXTRA_WIPE_ESIMS, true); + intent.putExtra("keep_memtag_mode", true); mReceiver.onReceive(mContext, intent); verifyRebootWipeUserData(/* shutdown= */ true, /* reason= */ "Self destruct", - /* force= */ true, /* wipeEuicc= */ true); + /* force= */ true, /* wipeEuicc= */ true, /* keepMemtagMode= */ true); verifyWipeExternalData(); } @@ -211,7 +212,7 @@ public final class MasterClearReceiverTest { mRebootWipeUserDataLatch.countDown(); return null; }).when(() -> RecoverySystem - .rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(), anyBoolean())); + .rebootWipeUserData(any(), anyBoolean(), any(), anyBoolean(), anyBoolean(), anyBoolean())); } private void expectWipeExternalData() { @@ -244,11 +245,16 @@ public final class MasterClearReceiverTest { private void verifyRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean wipeEuicc) throws Exception { + verifyRebootWipeUserData(shutdown, reason, force, wipeEuicc, /* keepMemtagMode= */ false); + } + + private void verifyRebootWipeUserData(boolean shutdown, String reason, boolean force, + boolean wipeEuicc, boolean keepMemtagMode) throws Exception { boolean called = mRebootWipeUserDataLatch.await(5, TimeUnit.SECONDS); assertWithMessage("rebootWipeUserData not called in 5s").that(called).isTrue(); verify(()-> RecoverySystem.rebootWipeUserData(same(mContext), eq(shutdown), eq(reason), - eq(force), eq(wipeEuicc))); + eq(force), eq(wipeEuicc), eq(keepMemtagMode))); } private void verifyNoRebootWipeUserData() { diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java index 4ffa0fbec758..5f9a17c7ae98 100644 --- a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java @@ -88,7 +88,7 @@ public final class FactoryResetterTest { Log.d(TAG, "Mocking " + inv); return null; }).when(() -> RecoverySystem.rebootWipeUserData(any(), anyBoolean(), any(), - anyBoolean(), anyBoolean())); + anyBoolean(), anyBoolean(), anyBoolean())); } @After @@ -270,17 +270,20 @@ public final class FactoryResetterTest { private void verifyRebootWipeUserDataMinimumArgsCalled() { verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ false, - /* reason= */ null, /* force= */ false, /* wipeEuicc= */ false)); + /* reason= */ null, /* force= */ false, /* wipeEuicc= */ false, + /* keepMemtagMode= */ false)); } private void verifyRebootWipeUserDataMinimumArgsButForceCalled() { verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ false, - /* reason= */ null, /* force= */ true, /* wipeEuicc= */ false)); + /* reason= */ null, /* force= */ true, /* wipeEuicc= */ false, + /* keepMemtagMode= */ false)); } private void verifyRebootWipeUserDataAllArgsCalled() { verify(() -> RecoverySystem.rebootWipeUserData(mContext, /* shutdown= */ true, - /* reason= */ REASON, /* force= */ true, /* wipeEuicc= */ true)); + /* reason= */ REASON, /* force= */ true, /* wipeEuicc= */ true, + /* keepMemtagMode= */ false)); } private void verifyWipeAdoptableStorageNotCalled() { |