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

Commit c1411a42 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Android Git Automerger
Browse files

am b8bbeff0: am 45ef18b6: Merge "Include reason when wiping data." into lmp-dev

* commit 'b8bbeff0796847bbe98deb2d84989b656356873c':
  Include reason when wiping data.
parents 39b5e7a8 26497569
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -2723,6 +2723,9 @@ public class Intent implements Parcelable, Cloneable {
    public static final String
    public static final String
            ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";
            ACTION_OPEN_DOCUMENT_TREE = "android.intent.action.OPEN_DOCUMENT_TREE";


    /** {@hide} */
    public static final String ACTION_MASTER_CLEAR = "android.intent.action.MASTER_CLEAR";

    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // Standard intent categories (see addCategory()).
    // Standard intent categories (see addCategory()).
@@ -3425,6 +3428,9 @@ public class Intent implements Parcelable, Cloneable {
    public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT =
    public static final String EXTRA_TIME_PREF_24_HOUR_FORMAT =
            "android.intent.extra.TIME_PREF_24_HOUR_FORMAT";
            "android.intent.extra.TIME_PREF_24_HOUR_FORMAT";


    /** {@hide} */
    public static final String EXTRA_REASON = "android.intent.extra.REASON";

    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // ---------------------------------------------------------------------
    // Intent flags (see mFlags variable).
    // Intent flags (see mFlags variable).
+58 −15
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
import android.content.Intent;
import android.content.Intent;
import android.os.UserManager;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
import android.util.Log;


import java.io.ByteArrayInputStream;
import java.io.ByteArrayInputStream;
@@ -333,9 +334,10 @@ public class RecoverySystem {
        throws IOException {
        throws IOException {
        String filename = packageFile.getCanonicalPath();
        String filename = packageFile.getCanonicalPath();
        Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
        Log.w(TAG, "!!! REBOOTING TO INSTALL " + filename + " !!!");
        String arg = "--update_package=" + filename +

            "\n--locale=" + Locale.getDefault().toString();
        final String filenameArg = "--update_package=" + filename;
        bootCommand(context, arg);
        final String localeArg = "--locale=" + Locale.getDefault().toString();
        bootCommand(context, filenameArg, localeArg);
    }
    }


    /**
    /**
@@ -352,7 +354,18 @@ public class RecoverySystem {
     * @throws SecurityException if the current user is not allowed to wipe data.
     * @throws SecurityException if the current user is not allowed to wipe data.
     */
     */
    public static void rebootWipeUserData(Context context) throws IOException {
    public static void rebootWipeUserData(Context context) throws IOException {
        rebootWipeUserData(context, false);
        rebootWipeUserData(context, false, context.getPackageName());
    }

    /** {@hide} */
    public static void rebootWipeUserData(Context context, String reason) throws IOException {
        rebootWipeUserData(context, false, reason);
    }

    /** {@hide} */
    public static void rebootWipeUserData(Context context, boolean shutdown)
            throws IOException {
        rebootWipeUserData(context, shutdown, context.getPackageName());
    }
    }


    /**
    /**
@@ -373,7 +386,7 @@ public class RecoverySystem {
     *
     *
     * @hide
     * @hide
     */
     */
    public static void rebootWipeUserData(Context context, boolean shutdown)
    public static void rebootWipeUserData(Context context, boolean shutdown, String reason)
            throws IOException {
            throws IOException {
        UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
        UserManager um = (UserManager) context.getSystemService(Context.USER_SERVICE);
        if (um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
        if (um.hasUserRestriction(UserManager.DISALLOW_FACTORY_RESET)) {
@@ -395,13 +408,18 @@ public class RecoverySystem {
        // Block until the ordered broadcast has completed.
        // Block until the ordered broadcast has completed.
        condition.block();
        condition.block();


        String shutdownArg = "";
        String shutdownArg = null;
        if (shutdown) {
        if (shutdown) {
            shutdownArg = "--shutdown_after\n";
            shutdownArg = "--shutdown_after";
        }

        String reasonArg = null;
        if (!TextUtils.isEmpty(reason)) {
            reasonArg = "--reason=" + sanitizeArg(reason);
        }
        }


        bootCommand(context, shutdownArg + "--wipe_data\n--locale=" +
        final String localeArg = "--locale=" + Locale.getDefault().toString();
                    Locale.getDefault().toString());
        bootCommand(context, shutdownArg, "--wipe_data", reasonArg, localeArg);
    }
    }


    /**
    /**
@@ -409,23 +427,38 @@ public class RecoverySystem {
     * @throws IOException if something goes wrong.
     * @throws IOException if something goes wrong.
     */
     */
    public static void rebootWipeCache(Context context) throws IOException {
    public static void rebootWipeCache(Context context) throws IOException {
        bootCommand(context, "--wipe_cache\n--locale=" + Locale.getDefault().toString());
        rebootWipeCache(context, context.getPackageName());
    }

    /** {@hide} */
    public static void rebootWipeCache(Context context, String reason) throws IOException {
        String reasonArg = null;
        if (!TextUtils.isEmpty(reason)) {
            reasonArg = "--reason=" + sanitizeArg(reason);
        }

        final String localeArg = "--locale=" + Locale.getDefault().toString();
        bootCommand(context, "--wipe_cache", reasonArg, localeArg);
    }
    }


    /**
    /**
     * Reboot into the recovery system with the supplied argument.
     * Reboot into the recovery system with the supplied argument.
     * @param arg to pass to the recovery utility.
     * @param args to pass to the recovery utility.
     * @throws IOException if something goes wrong.
     * @throws IOException if something goes wrong.
     */
     */
    private static void bootCommand(Context context, String arg) throws IOException {
    private static void bootCommand(Context context, String... args) throws IOException {
        RECOVERY_DIR.mkdirs();  // In case we need it
        RECOVERY_DIR.mkdirs();  // In case we need it
        COMMAND_FILE.delete();  // In case it's not writable
        COMMAND_FILE.delete();  // In case it's not writable
        LOG_FILE.delete();
        LOG_FILE.delete();


        FileWriter command = new FileWriter(COMMAND_FILE);
        FileWriter command = new FileWriter(COMMAND_FILE);
        try {
        try {
            for (String arg : args) {
                if (!TextUtils.isEmpty(arg)) {
                    command.write(arg);
                    command.write(arg);
                    command.write("\n");
                    command.write("\n");
                }
            }
        } finally {
        } finally {
            command.close();
            command.close();
        }
        }
@@ -470,5 +503,15 @@ public class RecoverySystem {
        return log;
        return log;
    }
    }


    /**
     * Internally, recovery treats each line of the command file as a separate
     * argv, so we only need to protect against newlines and nulls.
     */
    private static String sanitizeArg(String arg) {
        arg = arg.replace('\0', '?');
        arg = arg.replace('\n', '?');
        return arg;
    }

    private void RecoverySystem() { }  // Do not instantiate
    private void RecoverySystem() { }  // Do not instantiate
}
}
+14 −3
Original line number Original line Diff line number Diff line
@@ -50,6 +50,7 @@ public class ExternalStorageFormatter extends Service


    private boolean mFactoryReset = false;
    private boolean mFactoryReset = false;
    private boolean mAlwaysReset = false;
    private boolean mAlwaysReset = false;
    private String mReason = null;


    StorageEventListener mStorageListener = new StorageEventListener() {
    StorageEventListener mStorageListener = new StorageEventListener() {
        @Override
        @Override
@@ -84,6 +85,7 @@ public class ExternalStorageFormatter extends Service
            mAlwaysReset = true;
            mAlwaysReset = true;
        }
        }


        mReason = intent.getStringExtra(Intent.EXTRA_REASON);
        mStorageVolume = intent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);
        mStorageVolume = intent.getParcelableExtra(StorageVolume.EXTRA_STORAGE_VOLUME);


        if (mProgressDialog == null) {
        if (mProgressDialog == null) {
@@ -135,7 +137,10 @@ public class ExternalStorageFormatter extends Service
    void fail(int msg) {
    void fail(int msg) {
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
        if (mAlwaysReset) {
        if (mAlwaysReset) {
            sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
            Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
            intent.putExtra(Intent.EXTRA_REASON, mReason);
            sendBroadcast(intent);
        }
        }
        stopSelf();
        stopSelf();
    }
    }
@@ -179,7 +184,10 @@ public class ExternalStorageFormatter extends Service
                        }
                        }
                        if (success) {
                        if (success) {
                            if (mFactoryReset) {
                            if (mFactoryReset) {
                                sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
                                Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
                                intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                                intent.putExtra(Intent.EXTRA_REASON, mReason);
                                sendBroadcast(intent);
                                // Intent handling is asynchronous -- assume it will happen soon.
                                // Intent handling is asynchronous -- assume it will happen soon.
                                stopSelf();
                                stopSelf();
                                return;
                                return;
@@ -188,7 +196,10 @@ public class ExternalStorageFormatter extends Service
                        // If we didn't succeed, or aren't doing a full factory
                        // If we didn't succeed, or aren't doing a full factory
                        // reset, then it is time to remount the storage.
                        // reset, then it is time to remount the storage.
                        if (!success && mAlwaysReset) {
                        if (!success && mAlwaysReset) {
                            sendBroadcast(new Intent("android.intent.action.MASTER_CLEAR"));
                            Intent intent = new Intent(Intent.ACTION_MASTER_CLEAR);
                            intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
                            intent.putExtra(Intent.EXTRA_REASON, mReason);
                            sendBroadcast(intent);
                        } else {
                        } else {
                            try {
                            try {
                                mountService.mountVolume(extStoragePath);
                                mountService.mountVolume(extStoragePath);
+2 −1
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ public class MasterClearReceiver extends BroadcastReceiver {
        }
        }


        final boolean shutdown = intent.getBooleanExtra("shutdown", false);
        final boolean shutdown = intent.getBooleanExtra("shutdown", false);
        final String reason = intent.getStringExtra(Intent.EXTRA_REASON);


        Slog.w(TAG, "!!! FACTORY RESET !!!");
        Slog.w(TAG, "!!! FACTORY RESET !!!");
        // The reboot call is blocking, so we need to do it on another thread.
        // The reboot call is blocking, so we need to do it on another thread.
@@ -45,7 +46,7 @@ public class MasterClearReceiver extends BroadcastReceiver {
            @Override
            @Override
            public void run() {
            public void run() {
                try {
                try {
                    RecoverySystem.rebootWipeUserData(context, shutdown);
                    RecoverySystem.rebootWipeUserData(context, shutdown, reason);
                    Log.wtf(TAG, "Still running after master clear?!");
                    Log.wtf(TAG, "Still running after master clear?!");
                } catch (IOException e) {
                } catch (IOException e) {
                    Slog.e(TAG, "Can't perform master clear/factory reset", e);
                    Slog.e(TAG, "Can't perform master clear/factory reset", e);
+23 −7
Original line number Original line Diff line number Diff line
@@ -2862,7 +2862,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        return false;
        return false;
    }
    }


    void wipeDataLocked(int flags) {
    void wipeDataLocked(int flags, String reason) {
        // If the SD card is encrypted and non-removable, we have to force a wipe.
        // If the SD card is encrypted and non-removable, we have to force a wipe.
        boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
        boolean forceExtWipe = !Environment.isExternalStorageRemovable() && isExtStorageEncrypted();
        boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0;
        boolean wipeExtRequested = (flags&DevicePolicyManager.WIPE_EXTERNAL_STORAGE) != 0;
@@ -2871,12 +2871,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
        if ((forceExtWipe || wipeExtRequested) && !Environment.isExternalStorageEmulated()) {
            Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
            Intent intent = new Intent(ExternalStorageFormatter.FORMAT_AND_FACTORY_RESET);
            intent.putExtra(ExternalStorageFormatter.EXTRA_ALWAYS_RESET, true);
            intent.putExtra(ExternalStorageFormatter.EXTRA_ALWAYS_RESET, true);
            intent.putExtra(Intent.EXTRA_REASON, reason);
            intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
            intent.setComponent(ExternalStorageFormatter.COMPONENT_NAME);
            mWakeLock.acquire(10000);
            mWakeLock.acquire(10000);
            mContext.startService(intent);
            mContext.startService(intent);
        } else {
        } else {
            try {
            try {
                RecoverySystem.rebootWipeUserData(mContext);
                RecoverySystem.rebootWipeUserData(mContext, reason);
            } catch (IOException e) {
            } catch (IOException e) {
                Slog.w(LOG_TAG, "Failed requesting data wipe", e);
                Slog.w(LOG_TAG, "Failed requesting data wipe", e);
            } catch (SecurityException e) {
            } catch (SecurityException e) {
@@ -2885,6 +2886,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        }
    }
    }


    @Override
    public void wipeData(int flags, final int userHandle) {
    public void wipeData(int flags, final int userHandle) {
        if (!mHasFeature) {
        if (!mHasFeature) {
            return;
            return;
@@ -2896,20 +2898,34 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        synchronized (this) {
        synchronized (this) {
            // This API can only be called by an active device admin,
            // This API can only be called by an active device admin,
            // so try to retrieve it to check that the caller is one.
            // so try to retrieve it to check that the caller is one.
            getActiveAdminForCallerLocked(null,
            final ActiveAdmin admin = getActiveAdminForCallerLocked(null,
                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);
                    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();
            long ident = Binder.clearCallingIdentity();
            try {
            try {
                wipeDeviceOrUserLocked(flags, userHandle);
                wipeDeviceOrUserLocked(flags, userHandle,
                        "DevicePolicyManager.wipeData() from " + source);
            } finally {
            } finally {
                Binder.restoreCallingIdentity(ident);
                Binder.restoreCallingIdentity(ident);
            }
            }
        }
        }
    }
    }


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