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

Commit a7e87acb authored by Paul Crowley's avatar Paul Crowley
Browse files

Add flag for wiping factory reset protection data.

Bug: 18366448
Change-Id: If8904888a6bf8611d34647e6d65d2347d824dbb3
parent 5977f7d5
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -5441,6 +5441,7 @@ package android.app.admin {
    field public static final int PASSWORD_QUALITY_UNSPECIFIED = 0; // 0x0
    field public static final int RESET_PASSWORD_REQUIRE_ENTRY = 1; // 0x1
    field public static final int WIPE_EXTERNAL_STORAGE = 1; // 0x1
    field public static final int WIPE_RESET_PROTECTION_DATA = 2; // 0x2
  }
}
+14 −6
Original line number Diff line number Diff line
@@ -1473,22 +1473,30 @@ public class DevicePolicyManager {

    /**
     * Flag for {@link #wipeData(int)}: also erase the device's external
     * storage.
     * storage (such as SD cards).
     */
    public static final int WIPE_EXTERNAL_STORAGE = 0x0001;

    /**
     * Flag for {@link #wipeData(int)}: also erase the factory reset protection
     * data.
     *
     * This flag may only be set by device owner admins; if it is set by other
     * admins a {@link SecurityException} will be thrown.
     */
    public static final int WIPE_RESET_PROTECTION_DATA = 0x0002;

    /**
     * Ask the user data be wiped.  This will cause the device to reboot,
     * erasing all user data while next booting up.  External storage such
     * as SD cards will be also erased if the flag {@link #WIPE_EXTERNAL_STORAGE}
     * is set.
     * erasing all user data while next booting up.
     *
     * <p>The calling device admin must have requested
     * {@link DeviceAdminInfo#USES_POLICY_WIPE_DATA} to be able to call
     * this method; if it has not, a security exception will be thrown.
     *
     * @param flags Bit mask of additional options: currently 0 and
     *              {@link #WIPE_EXTERNAL_STORAGE} are supported.
     * @param flags Bit mask of additional options: currently supported flags
     * are {@link #WIPE_EXTERNAL_STORAGE} and
     * {@link #WIPE_RESET_PROTECTION_DATA}.
     */
    public void wipeData(int flags) {
        if (mService != null) {
+25 −17
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.server.devicepolicy;

import static android.Manifest.permission.MANAGE_CA_CERTIFICATES;
import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;

import android.accessibilityservice.AccessibilityServiceInfo;
@@ -78,6 +80,7 @@ import android.security.IKeyChainService;
import android.security.KeyChain;
import android.security.KeyChain.KeyChainConnection;
import android.text.TextUtils;
import android.service.persistentdata.PersistentDataBlockManager;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
@@ -2925,10 +2928,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        return false;
    }

    void wipeDataLocked(int flags, String reason) {
    private void wipeDataLocked(boolean wipeExtRequested, String reason) {
        // If the SD card is encrypted and non-removable, we have to force a wipe.
        boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
        boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0;

        // Note: we can only do the wipe via ExternalStorageFormatter if the volume is not emulated.
        if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
@@ -2941,9 +2943,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        } else {
            try {
                RecoverySystem.rebootWipeUserData(mContext, reason);
            } catch (IOException e) {
                Slog.w(LOG_TAG, "Failed requesting data wipe", e);
            } catch (SecurityException e) {
            } catch (IOException | SecurityException e) {
                Slog.w(LOG_TAG, "Failed requesting data wipe", e);
            }
        }
@@ -2962,20 +2962,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);

            final String source;
            if (admin != null && admin.info != null) {
            final ComponentName cname = admin.info.getComponent();
            if (cname != null) {
                source = cname.flattenToShortString();
            } else {
                source = admin.info.getPackageName();
            }
            } else {
                source = "?";
            }

            long ident = Binder.clearCallingIdentity();
            try {
                wipeDeviceOrUserLocked(flags, userHandle,
                if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
                    if (userHandle != UserHandle.USER_OWNER
                            || !isDeviceOwner(admin.info.getPackageName())) {
                        throw new SecurityException(
                               "Only device owner admins can set WIPE_RESET_PROTECTION_DATA");
                    }
                    PersistentDataBlockManager manager = (PersistentDataBlockManager)
                            mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
                    manager.wipe();
                }
                boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
                wipeDeviceOrUserLocked(wipeExtRequested, userHandle,
                        "DevicePolicyManager.wipeData() from " + source);
            } finally {
                Binder.restoreCallingIdentity(ident);
@@ -2983,9 +2990,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
    }

    private void wipeDeviceOrUserLocked(int flags, final int userHandle, String reason) {
    private void wipeDeviceOrUserLocked(boolean wipeExtRequested, final int userHandle, String reason) {
        if (userHandle == UserHandle.USER_OWNER) {
            wipeDataLocked(flags, reason);
            wipeDataLocked(wipeExtRequested, reason);
        } else {
            mHandler.post(new Runnable() {
                public void run() {
@@ -3137,7 +3144,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            if (wipeData) {
                // Call without holding lock.
                wipeDeviceOrUserLocked(0, identifier, "reportFailedPasswordAttempt()");
                wipeDeviceOrUserLocked(false, identifier,
                        "reportFailedPasswordAttempt()");
            }
        } finally {
            Binder.restoreCallingIdentity(ident);