Loading services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java +61 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.devicepolicy; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManager; Loading @@ -24,6 +25,7 @@ import android.os.FileUtils; import android.os.PersistableBundle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.TypedXmlPullParser; Loading Loading @@ -85,6 +87,15 @@ class DevicePolicyData { static final String NEW_USER_DISCLAIMER_NOT_NEEDED = "not_needed"; static final String NEW_USER_DISCLAIMER_NEEDED = "needed"; private static final String ATTR_FACTORY_RESET_FLAGS = "factory-reset-flags"; private static final String ATTR_FACTORY_RESET_REASON = "factory-reset-reason"; // NOTE: must be public because of DebugUtils.flagsToString() public static final int FACTORY_RESET_FLAG_ON_BOOT = 1; public static final int FACTORY_RESET_FLAG_WIPE_EXTERNAL_STORAGE = 2; public static final int FACTORY_RESET_FLAG_WIPE_EUICC = 4; public static final int FACTORY_RESET_FLAG_WIPE_FACTORY_RESET_PROTECTION = 8; private static final String TAG = DevicePolicyManagerService.LOG_TAG; private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE Loading @@ -99,6 +110,9 @@ class DevicePolicyData { int mUserProvisioningState; int mPermissionPolicy; int mFactoryResetFlags; String mFactoryResetReason; boolean mDeviceProvisioningConfigApplied = false; final ArrayMap<ComponentName, ActiveAdmin> mAdminMap = new ArrayMap<>(); Loading Loading @@ -200,6 +214,17 @@ class DevicePolicyData { out.attribute(null, ATTR_NEW_USER_DISCLAIMER, policyData.mNewUserDisclaimer); } if (policyData.mFactoryResetFlags != 0) { if (VERBOSE_LOG) { Slog.v(TAG, "Storing factory reset flags for user " + policyData.mUserId + ": " + factoryResetFlagsToString(policyData.mFactoryResetFlags)); } out.attributeInt(null, ATTR_FACTORY_RESET_FLAGS, policyData.mFactoryResetFlags); } if (policyData.mFactoryResetReason != null) { out.attribute(null, ATTR_FACTORY_RESET_REASON, policyData.mFactoryResetReason); } // Serialize delegations. for (int i = 0; i < policyData.mDelegationMap.size(); ++i) { final String delegatePackage = policyData.mDelegationMap.keyAt(i); Loading Loading @@ -427,6 +452,13 @@ class DevicePolicyData { } policy.mNewUserDisclaimer = parser.getAttributeValue(null, ATTR_NEW_USER_DISCLAIMER); policy.mFactoryResetFlags = parser.getAttributeInt(null, ATTR_FACTORY_RESET_FLAGS, 0); if (VERBOSE_LOG) { Slog.v(TAG, "Restored factory reset flags for user " + policy.mUserId + ": " + factoryResetFlagsToString(policy.mFactoryResetFlags)); } policy.mFactoryResetReason = parser.getAttributeValue(null, ATTR_FACTORY_RESET_REASON); int outerDepth = parser.getDepth(); policy.mLockTaskPackages.clear(); policy.mAdminList.clear(); Loading Loading @@ -572,6 +604,22 @@ class DevicePolicyData { } } void setDelayedFactoryReset(@NonNull String reason, boolean wipeExtRequested, boolean wipeEuicc, boolean wipeResetProtectionData) { mFactoryResetReason = reason; mFactoryResetFlags = FACTORY_RESET_FLAG_ON_BOOT; if (wipeExtRequested) { mFactoryResetFlags |= FACTORY_RESET_FLAG_WIPE_EXTERNAL_STORAGE; } if (wipeEuicc) { mFactoryResetFlags |= FACTORY_RESET_FLAG_WIPE_EUICC; } if (wipeResetProtectionData) { mFactoryResetFlags |= FACTORY_RESET_FLAG_WIPE_FACTORY_RESET_PROTECTION; } } void dump(IndentingPrintWriter pw) { pw.println(); pw.println("Enabled Device Admins (User " + mUserId + ", provisioningState: " Loading Loading @@ -603,6 +651,19 @@ class DevicePolicyData { pw.print("mUserSetupComplete="); pw.println(mUserSetupComplete); pw.print("mAffiliationIds="); pw.println(mAffiliationIds); pw.print("mNewUserDisclaimer="); pw.println(mNewUserDisclaimer); if (mFactoryResetFlags != 0) { pw.print("mFactoryResetFlags="); pw.print(mFactoryResetFlags); pw.print(" ("); pw.print(factoryResetFlagsToString(mFactoryResetFlags)); pw.println(')'); } if (mFactoryResetReason != null) { pw.print("mFactoryResetReason="); pw.println(mFactoryResetReason); } pw.decreaseIndent(); } static String factoryResetFlagsToString(int flags) { return DebugUtils.flagsToString(DevicePolicyData.class, "FACTORY_RESET_FLAG_", flags); } } services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +56 −5 Original line number Diff line number Diff line Loading @@ -1320,12 +1320,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mContext.getSystemService(PowerManager.class).reboot(reason); } void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData) throws IOException { FactoryResetter.newBuilder(mContext).setSafetyChecker(mSafetyChecker) .setReason(reason).setShutdown(shutdown) .setForce(force).setWipeEuicc(wipeEuicc) return FactoryResetter.newBuilder(mContext).setSafetyChecker(mSafetyChecker) .setReason(reason).setShutdown(shutdown).setForce(force).setWipeEuicc(wipeEuicc) .setWipeAdoptableStorage(wipeExtRequested) .setWipeFactoryResetProtection(wipeResetProtectionData) .build().factoryReset(); Loading Loading @@ -2787,6 +2786,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { maybeStartSecurityLogMonitorOnActivityManagerReady(); break; case SystemService.PHASE_BOOT_COMPLETED: // Ideally it should be done earlier, but currently it relies on RecoverySystem, // which would hang on earlier phases factoryResetIfDelayedEarlier(); ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this. break; } Loading Loading @@ -6261,10 +6264,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { boolean wipeResetProtectionData) { wtfIfInLock(); boolean success = false; try { mInjector.recoverySystemRebootWipeUserData( boolean delayed = !mInjector.recoverySystemRebootWipeUserData( /* shutdown= */ false, reason, /* force= */ true, /* wipeEuicc= */ wipeEuicc, wipeExtRequested, wipeResetProtectionData); if (delayed) { // Persist the request so the device is automatically factory-reset on next start if // the system crashes or reboots before the {@code DevicePolicySafetyChecker} calls // its callback. Slog.i(LOG_TAG, String.format("Persisting factory reset request as it could be " + "delayed by %s", mSafetyChecker)); synchronized (getLockObject()) { DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM); policy.setDelayedFactoryReset(reason, wipeExtRequested, wipeEuicc, wipeResetProtectionData); saveSettingsLocked(UserHandle.USER_SYSTEM); } } success = true; } catch (IOException | SecurityException e) { Slog.w(LOG_TAG, "Failed requesting data wipe", e); Loading @@ -6273,6 +6290,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private void factoryResetIfDelayedEarlier() { synchronized (getLockObject()) { DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM); if (policy.mFactoryResetFlags == 0) return; if (policy.mFactoryResetReason == null) { // Shouldn't happen. Slog.e(LOG_TAG, "no persisted reason for factory resetting"); policy.mFactoryResetReason = "requested before boot"; } FactoryResetter factoryResetter = FactoryResetter.newBuilder(mContext) .setReason(policy.mFactoryResetReason).setForce(true) .setWipeEuicc((policy.mFactoryResetFlags & DevicePolicyData .FACTORY_RESET_FLAG_WIPE_EUICC) != 0) .setWipeAdoptableStorage((policy.mFactoryResetFlags & DevicePolicyData .FACTORY_RESET_FLAG_WIPE_EXTERNAL_STORAGE) != 0) .setWipeFactoryResetProtection((policy.mFactoryResetFlags & DevicePolicyData .FACTORY_RESET_FLAG_WIPE_FACTORY_RESET_PROTECTION) != 0) .build(); Slog.i(LOG_TAG, "Factory resetting on boot using " + factoryResetter); try { if (!factoryResetter.factoryReset()) { // Shouldn't happen because FactoryResetter was created without a // DevicePolicySafetyChecker. Slog.wtf(LOG_TAG, "Factory reset using " + factoryResetter + " failed."); } } catch (IOException e) { // Shouldn't happen. Slog.wtf(LOG_TAG, "Could not factory reset using " + factoryResetter, e); } } } private void forceWipeUser(int userId, String wipeReasonForUser, boolean wipeSilently) { boolean success = false; try { Loading services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java +35 −2 Original line number Diff line number Diff line Loading @@ -52,14 +52,17 @@ public final class FactoryResetter { /** * Factory reset the device according to the builder's arguments. * * @return {@code true} if device was factory reset, or {@code false} if it was delayed by the * {@link DevicePolicySafetyChecker}. */ public void factoryReset() throws IOException { public boolean factoryReset() throws IOException { Preconditions.checkCallAuthorization(mContext.checkCallingOrSelfPermission( android.Manifest.permission.MASTER_CLEAR) == PackageManager.PERMISSION_GRANTED); if (mSafetyChecker == null) { factoryResetInternalUnchecked(); return; return true; } IResultReceiver receiver = new IResultReceiver.Stub() { Loading @@ -77,6 +80,36 @@ public final class FactoryResetter { }; Slog.i(TAG, String.format("Delaying factory reset until %s confirms", mSafetyChecker)); mSafetyChecker.onFactoryReset(receiver); return false; } @Override public String toString() { StringBuilder builder = new StringBuilder("FactoryResetter["); if (mReason == null) { builder.append("no_reason"); } else { builder.append("reason='").append(mReason).append("'"); } if (mSafetyChecker != null) { builder.append(",hasSafetyChecker"); } if (mShutdown) { builder.append(",shutdown"); } if (mForce) { builder.append(",force"); } if (mWipeEuicc) { builder.append(",wipeEuicc"); } if (mWipeAdoptableStorage) { builder.append(",wipeAdoptableStorage"); } if (mWipeFactoryResetProtection) { builder.append(",ipeFactoryResetProtection"); } return builder.append(']').toString(); } private void factoryResetInternalUnchecked() throws IOException { Loading services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java +13 −6 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.never; Loading Loading @@ -158,10 +160,11 @@ public final class FactoryResetterTest { public void testFactoryReset_storageOnly() throws Exception { allowFactoryReset(); FactoryResetter.newBuilder(mContext) boolean success = FactoryResetter.newBuilder(mContext) .setWipeAdoptableStorage(true).build() .factoryReset(); assertThat(success).isTrue(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionNotCalled(); verifyRebootWipeUserDataMinimumArgsCalled(); Loading @@ -171,10 +174,11 @@ public final class FactoryResetterTest { public void testFactoryReset_frpOnly() throws Exception { allowFactoryReset(); FactoryResetter.newBuilder(mContext) boolean success = FactoryResetter.newBuilder(mContext) .setWipeFactoryResetProtection(true) .build().factoryReset(); assertThat(success).isTrue(); verifyWipeAdoptableStorageNotCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataMinimumArgsCalled(); Loading @@ -184,7 +188,7 @@ public final class FactoryResetterTest { public void testFactoryReset_allArgs() throws Exception { allowFactoryReset(); FactoryResetter.newBuilder(mContext) boolean success = FactoryResetter.newBuilder(mContext) .setReason(REASON) .setForce(true) .setShutdown(true) Loading @@ -193,6 +197,7 @@ public final class FactoryResetterTest { .setWipeFactoryResetProtection(true) .build().factoryReset(); assertThat(success).isTrue(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataAllArgsCalled(); Loading @@ -202,9 +207,10 @@ public final class FactoryResetterTest { public void testFactoryReset_minimumArgs_safetyChecker_neverReplied() throws Exception { allowFactoryReset(); FactoryResetter.newBuilder(mContext).setSafetyChecker(mSafetyChecker).build() .factoryReset(); boolean success = FactoryResetter.newBuilder(mContext) .setSafetyChecker(mSafetyChecker).build().factoryReset(); assertThat(success).isFalse(); verifyWipeAdoptableStorageNotCalled(); verifyWipeFactoryResetProtectionNotCalled(); verifyRebootWipeUserDataNotCalled(); Loading @@ -221,7 +227,7 @@ public final class FactoryResetterTest { return null; }).when(mSafetyChecker).onFactoryReset(any()); FactoryResetter.newBuilder(mContext) boolean success = FactoryResetter.newBuilder(mContext) .setSafetyChecker(mSafetyChecker) .setReason(REASON) .setForce(true) Loading @@ -231,6 +237,7 @@ public final class FactoryResetterTest { .setWipeFactoryResetProtection(true) .build().factoryReset(); assertThat(success).isFalse(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataAllArgsCalled(); Loading services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +2 −2 Original line number Diff line number Diff line Loading @@ -319,10 +319,10 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi } @Override void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData) throws IOException { services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc, return services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc, wipeExtRequested, wipeResetProtectionData); } Loading Loading
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java +61 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.devicepolicy; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.admin.DeviceAdminInfo; import android.app.admin.DevicePolicyManager; Loading @@ -24,6 +25,7 @@ import android.os.FileUtils; import android.os.PersistableBundle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; import android.util.IndentingPrintWriter; import android.util.Slog; import android.util.TypedXmlPullParser; Loading Loading @@ -85,6 +87,15 @@ class DevicePolicyData { static final String NEW_USER_DISCLAIMER_NOT_NEEDED = "not_needed"; static final String NEW_USER_DISCLAIMER_NEEDED = "needed"; private static final String ATTR_FACTORY_RESET_FLAGS = "factory-reset-flags"; private static final String ATTR_FACTORY_RESET_REASON = "factory-reset-reason"; // NOTE: must be public because of DebugUtils.flagsToString() public static final int FACTORY_RESET_FLAG_ON_BOOT = 1; public static final int FACTORY_RESET_FLAG_WIPE_EXTERNAL_STORAGE = 2; public static final int FACTORY_RESET_FLAG_WIPE_EUICC = 4; public static final int FACTORY_RESET_FLAG_WIPE_FACTORY_RESET_PROTECTION = 8; private static final String TAG = DevicePolicyManagerService.LOG_TAG; private static final boolean VERBOSE_LOG = false; // DO NOT SUBMIT WITH TRUE Loading @@ -99,6 +110,9 @@ class DevicePolicyData { int mUserProvisioningState; int mPermissionPolicy; int mFactoryResetFlags; String mFactoryResetReason; boolean mDeviceProvisioningConfigApplied = false; final ArrayMap<ComponentName, ActiveAdmin> mAdminMap = new ArrayMap<>(); Loading Loading @@ -200,6 +214,17 @@ class DevicePolicyData { out.attribute(null, ATTR_NEW_USER_DISCLAIMER, policyData.mNewUserDisclaimer); } if (policyData.mFactoryResetFlags != 0) { if (VERBOSE_LOG) { Slog.v(TAG, "Storing factory reset flags for user " + policyData.mUserId + ": " + factoryResetFlagsToString(policyData.mFactoryResetFlags)); } out.attributeInt(null, ATTR_FACTORY_RESET_FLAGS, policyData.mFactoryResetFlags); } if (policyData.mFactoryResetReason != null) { out.attribute(null, ATTR_FACTORY_RESET_REASON, policyData.mFactoryResetReason); } // Serialize delegations. for (int i = 0; i < policyData.mDelegationMap.size(); ++i) { final String delegatePackage = policyData.mDelegationMap.keyAt(i); Loading Loading @@ -427,6 +452,13 @@ class DevicePolicyData { } policy.mNewUserDisclaimer = parser.getAttributeValue(null, ATTR_NEW_USER_DISCLAIMER); policy.mFactoryResetFlags = parser.getAttributeInt(null, ATTR_FACTORY_RESET_FLAGS, 0); if (VERBOSE_LOG) { Slog.v(TAG, "Restored factory reset flags for user " + policy.mUserId + ": " + factoryResetFlagsToString(policy.mFactoryResetFlags)); } policy.mFactoryResetReason = parser.getAttributeValue(null, ATTR_FACTORY_RESET_REASON); int outerDepth = parser.getDepth(); policy.mLockTaskPackages.clear(); policy.mAdminList.clear(); Loading Loading @@ -572,6 +604,22 @@ class DevicePolicyData { } } void setDelayedFactoryReset(@NonNull String reason, boolean wipeExtRequested, boolean wipeEuicc, boolean wipeResetProtectionData) { mFactoryResetReason = reason; mFactoryResetFlags = FACTORY_RESET_FLAG_ON_BOOT; if (wipeExtRequested) { mFactoryResetFlags |= FACTORY_RESET_FLAG_WIPE_EXTERNAL_STORAGE; } if (wipeEuicc) { mFactoryResetFlags |= FACTORY_RESET_FLAG_WIPE_EUICC; } if (wipeResetProtectionData) { mFactoryResetFlags |= FACTORY_RESET_FLAG_WIPE_FACTORY_RESET_PROTECTION; } } void dump(IndentingPrintWriter pw) { pw.println(); pw.println("Enabled Device Admins (User " + mUserId + ", provisioningState: " Loading Loading @@ -603,6 +651,19 @@ class DevicePolicyData { pw.print("mUserSetupComplete="); pw.println(mUserSetupComplete); pw.print("mAffiliationIds="); pw.println(mAffiliationIds); pw.print("mNewUserDisclaimer="); pw.println(mNewUserDisclaimer); if (mFactoryResetFlags != 0) { pw.print("mFactoryResetFlags="); pw.print(mFactoryResetFlags); pw.print(" ("); pw.print(factoryResetFlagsToString(mFactoryResetFlags)); pw.println(')'); } if (mFactoryResetReason != null) { pw.print("mFactoryResetReason="); pw.println(mFactoryResetReason); } pw.decreaseIndent(); } static String factoryResetFlagsToString(int flags) { return DebugUtils.flagsToString(DevicePolicyData.class, "FACTORY_RESET_FLAG_", flags); } }
services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +56 −5 Original line number Diff line number Diff line Loading @@ -1320,12 +1320,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { mContext.getSystemService(PowerManager.class).reboot(reason); } void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData) throws IOException { FactoryResetter.newBuilder(mContext).setSafetyChecker(mSafetyChecker) .setReason(reason).setShutdown(shutdown) .setForce(force).setWipeEuicc(wipeEuicc) return FactoryResetter.newBuilder(mContext).setSafetyChecker(mSafetyChecker) .setReason(reason).setShutdown(shutdown).setForce(force).setWipeEuicc(wipeEuicc) .setWipeAdoptableStorage(wipeExtRequested) .setWipeFactoryResetProtection(wipeResetProtectionData) .build().factoryReset(); Loading Loading @@ -2787,6 +2786,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { maybeStartSecurityLogMonitorOnActivityManagerReady(); break; case SystemService.PHASE_BOOT_COMPLETED: // Ideally it should be done earlier, but currently it relies on RecoverySystem, // which would hang on earlier phases factoryResetIfDelayedEarlier(); ensureDeviceOwnerUserStarted(); // TODO Consider better place to do this. break; } Loading Loading @@ -6261,10 +6264,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { boolean wipeResetProtectionData) { wtfIfInLock(); boolean success = false; try { mInjector.recoverySystemRebootWipeUserData( boolean delayed = !mInjector.recoverySystemRebootWipeUserData( /* shutdown= */ false, reason, /* force= */ true, /* wipeEuicc= */ wipeEuicc, wipeExtRequested, wipeResetProtectionData); if (delayed) { // Persist the request so the device is automatically factory-reset on next start if // the system crashes or reboots before the {@code DevicePolicySafetyChecker} calls // its callback. Slog.i(LOG_TAG, String.format("Persisting factory reset request as it could be " + "delayed by %s", mSafetyChecker)); synchronized (getLockObject()) { DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM); policy.setDelayedFactoryReset(reason, wipeExtRequested, wipeEuicc, wipeResetProtectionData); saveSettingsLocked(UserHandle.USER_SYSTEM); } } success = true; } catch (IOException | SecurityException e) { Slog.w(LOG_TAG, "Failed requesting data wipe", e); Loading @@ -6273,6 +6290,40 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } } private void factoryResetIfDelayedEarlier() { synchronized (getLockObject()) { DevicePolicyData policy = getUserData(UserHandle.USER_SYSTEM); if (policy.mFactoryResetFlags == 0) return; if (policy.mFactoryResetReason == null) { // Shouldn't happen. Slog.e(LOG_TAG, "no persisted reason for factory resetting"); policy.mFactoryResetReason = "requested before boot"; } FactoryResetter factoryResetter = FactoryResetter.newBuilder(mContext) .setReason(policy.mFactoryResetReason).setForce(true) .setWipeEuicc((policy.mFactoryResetFlags & DevicePolicyData .FACTORY_RESET_FLAG_WIPE_EUICC) != 0) .setWipeAdoptableStorage((policy.mFactoryResetFlags & DevicePolicyData .FACTORY_RESET_FLAG_WIPE_EXTERNAL_STORAGE) != 0) .setWipeFactoryResetProtection((policy.mFactoryResetFlags & DevicePolicyData .FACTORY_RESET_FLAG_WIPE_FACTORY_RESET_PROTECTION) != 0) .build(); Slog.i(LOG_TAG, "Factory resetting on boot using " + factoryResetter); try { if (!factoryResetter.factoryReset()) { // Shouldn't happen because FactoryResetter was created without a // DevicePolicySafetyChecker. Slog.wtf(LOG_TAG, "Factory reset using " + factoryResetter + " failed."); } } catch (IOException e) { // Shouldn't happen. Slog.wtf(LOG_TAG, "Could not factory reset using " + factoryResetter, e); } } } private void forceWipeUser(int userId, String wipeReasonForUser, boolean wipeSilently) { boolean success = false; try { Loading
services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java +35 −2 Original line number Diff line number Diff line Loading @@ -52,14 +52,17 @@ public final class FactoryResetter { /** * Factory reset the device according to the builder's arguments. * * @return {@code true} if device was factory reset, or {@code false} if it was delayed by the * {@link DevicePolicySafetyChecker}. */ public void factoryReset() throws IOException { public boolean factoryReset() throws IOException { Preconditions.checkCallAuthorization(mContext.checkCallingOrSelfPermission( android.Manifest.permission.MASTER_CLEAR) == PackageManager.PERMISSION_GRANTED); if (mSafetyChecker == null) { factoryResetInternalUnchecked(); return; return true; } IResultReceiver receiver = new IResultReceiver.Stub() { Loading @@ -77,6 +80,36 @@ public final class FactoryResetter { }; Slog.i(TAG, String.format("Delaying factory reset until %s confirms", mSafetyChecker)); mSafetyChecker.onFactoryReset(receiver); return false; } @Override public String toString() { StringBuilder builder = new StringBuilder("FactoryResetter["); if (mReason == null) { builder.append("no_reason"); } else { builder.append("reason='").append(mReason).append("'"); } if (mSafetyChecker != null) { builder.append(",hasSafetyChecker"); } if (mShutdown) { builder.append(",shutdown"); } if (mForce) { builder.append(",force"); } if (mWipeEuicc) { builder.append(",wipeEuicc"); } if (mWipeAdoptableStorage) { builder.append(",wipeAdoptableStorage"); } if (mWipeFactoryResetProtection) { builder.append(",ipeFactoryResetProtection"); } return builder.append(']').toString(); } private void factoryResetInternalUnchecked() throws IOException { Loading
services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java +13 −6 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.Mockito.never; Loading Loading @@ -158,10 +160,11 @@ public final class FactoryResetterTest { public void testFactoryReset_storageOnly() throws Exception { allowFactoryReset(); FactoryResetter.newBuilder(mContext) boolean success = FactoryResetter.newBuilder(mContext) .setWipeAdoptableStorage(true).build() .factoryReset(); assertThat(success).isTrue(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionNotCalled(); verifyRebootWipeUserDataMinimumArgsCalled(); Loading @@ -171,10 +174,11 @@ public final class FactoryResetterTest { public void testFactoryReset_frpOnly() throws Exception { allowFactoryReset(); FactoryResetter.newBuilder(mContext) boolean success = FactoryResetter.newBuilder(mContext) .setWipeFactoryResetProtection(true) .build().factoryReset(); assertThat(success).isTrue(); verifyWipeAdoptableStorageNotCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataMinimumArgsCalled(); Loading @@ -184,7 +188,7 @@ public final class FactoryResetterTest { public void testFactoryReset_allArgs() throws Exception { allowFactoryReset(); FactoryResetter.newBuilder(mContext) boolean success = FactoryResetter.newBuilder(mContext) .setReason(REASON) .setForce(true) .setShutdown(true) Loading @@ -193,6 +197,7 @@ public final class FactoryResetterTest { .setWipeFactoryResetProtection(true) .build().factoryReset(); assertThat(success).isTrue(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataAllArgsCalled(); Loading @@ -202,9 +207,10 @@ public final class FactoryResetterTest { public void testFactoryReset_minimumArgs_safetyChecker_neverReplied() throws Exception { allowFactoryReset(); FactoryResetter.newBuilder(mContext).setSafetyChecker(mSafetyChecker).build() .factoryReset(); boolean success = FactoryResetter.newBuilder(mContext) .setSafetyChecker(mSafetyChecker).build().factoryReset(); assertThat(success).isFalse(); verifyWipeAdoptableStorageNotCalled(); verifyWipeFactoryResetProtectionNotCalled(); verifyRebootWipeUserDataNotCalled(); Loading @@ -221,7 +227,7 @@ public final class FactoryResetterTest { return null; }).when(mSafetyChecker).onFactoryReset(any()); FactoryResetter.newBuilder(mContext) boolean success = FactoryResetter.newBuilder(mContext) .setSafetyChecker(mSafetyChecker) .setReason(REASON) .setForce(true) Loading @@ -231,6 +237,7 @@ public final class FactoryResetterTest { .setWipeFactoryResetProtection(true) .build().factoryReset(); assertThat(success).isFalse(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataAllArgsCalled(); Loading
services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java +2 −2 Original line number Diff line number Diff line Loading @@ -319,10 +319,10 @@ public class DevicePolicyManagerServiceTestable extends DevicePolicyManagerServi } @Override void recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean recoverySystemRebootWipeUserData(boolean shutdown, String reason, boolean force, boolean wipeEuicc, boolean wipeExtRequested, boolean wipeResetProtectionData) throws IOException { services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc, return services.recoverySystem.rebootWipeUserData(shutdown, reason, force, wipeEuicc, wipeExtRequested, wipeResetProtectionData); } Loading