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

Commit a755fb10 authored by Makoto Onuki's avatar Makoto Onuki
Browse files

Do not call RecoverySystem with DPMS lock held

Note DPM.wipeData() on a secondary user is now blocking, just like
it's been always blocking on the primary user.

Test: Manually tested wipeData() with TestDPC, both on 1) the primary user,
2) a secondary user and 3) work profile.
* Modified TestDPC so it supports secondary users

Test: adb shell am instrument -e class com.android.server.devicepolicy.DevicePolicyManagerTest -w com.android.frameworks.servicestests

Bug 30681079

Change-Id: Ib97a92a6af87a5589d2643b9ae0522395735e1a5
parent 220c4155
Loading
Loading
Loading
Loading
+48 −38
Original line number Original line Diff line number Diff line
@@ -4788,7 +4788,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        }
    }
    }


    private void wipeDataLocked(boolean wipeExtRequested, String reason, boolean force) {
    private void wipeDataNoLock(boolean wipeExtRequested, String reason, boolean force) {
        wtfIfInLock();

        if (wipeExtRequested) {
        if (wipeExtRequested) {
            StorageManager sm = (StorageManager) mContext.getSystemService(
            StorageManager sm = (StorageManager) mContext.getSystemService(
                    Context.STORAGE_SERVICE);
                    Context.STORAGE_SERVICE);
@@ -4808,13 +4810,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        }
        final int userHandle = mInjector.userHandleGetCallingUserId();
        final int userHandle = mInjector.userHandleGetCallingUserId();
        enforceFullCrossUsersPermission(userHandle);
        enforceFullCrossUsersPermission(userHandle);

        final String source;
        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.
            final ActiveAdmin admin = getActiveAdminForCallerLocked(null,
            final ActiveAdmin admin = getActiveAdminForCallerLocked(null,
                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);
                    DeviceAdminInfo.USES_POLICY_WIPE_DATA);

            source = admin.info.getComponent().flattenToShortString();
            final String source = admin.info.getComponent().flattenToShortString();


            long ident = mInjector.binderClearCallingIdentity();
            long ident = mInjector.binderClearCallingIdentity();
            try {
            try {
@@ -4844,26 +4847,27 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    }
                    }
                }
                }


                boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
                wipeDeviceOrUserLocked(wipeExtRequested, userHandle,
                        "DevicePolicyManager.wipeData() from " + source, /*force=*/ true);
            } finally {
            } finally {
                mInjector.binderRestoreCallingIdentity(ident);
                mInjector.binderRestoreCallingIdentity(ident);
            }
            }
        }
        }
        final boolean wipeExtRequested = (flags & WIPE_EXTERNAL_STORAGE) != 0;
        wipeDeviceNoLock(wipeExtRequested, userHandle,
                "DevicePolicyManager.wipeData() from " + source, /*force=*/ true);
    }
    }


    private void wipeDeviceOrUserLocked(
    private void wipeDeviceNoLock(
            boolean wipeExtRequested, final int userHandle, String reason, boolean force) {
            boolean wipeExtRequested, final int userHandle, String reason, boolean force) {
        wtfIfInLock();

        long ident = mInjector.binderClearCallingIdentity();
        try {
            // TODO If split user is enabled and the device owner is set in the primary user (rather
            // TODO If split user is enabled and the device owner is set in the primary user (rather
            // than system), we should probably trigger factory reset. Current code just remove
            // than system), we should probably trigger factory reset. Current code just remove
            // that user (but still clears FRP...)
            // that user (but still clears FRP...)
            if (userHandle == UserHandle.USER_SYSTEM) {
            if (userHandle == UserHandle.USER_SYSTEM) {
            wipeDataLocked(wipeExtRequested, reason, force);
                wipeDataNoLock(wipeExtRequested, reason, force);
            } else {
            } else {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                try {
                try {
                    IActivityManager am = mInjector.getIActivityManager();
                    IActivityManager am = mInjector.getIActivityManager();
                    if (am.getCurrentUser().id == userHandle) {
                    if (am.getCurrentUser().id == userHandle) {
@@ -4882,7 +4886,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                    // Shouldn't happen
                    // Shouldn't happen
                }
                }
            }
            }
            });
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
        }
        }
    }
    }


@@ -5047,8 +5052,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
            }
            }
            if (wipeData) {
            if (wipeData) {
                // Call without holding lock.
                // Call without holding lock.
                wipeDeviceOrUserLocked(false, identifier,
                wipeDeviceNoLock(false, identifier, "reportFailedPasswordAttempt()", false);
                        "reportFailedPasswordAttempt()", false);
            }
            }
        } finally {
        } finally {
            mInjector.binderRestoreCallingIdentity(ident);
            mInjector.binderRestoreCallingIdentity(ident);
@@ -6549,6 +6553,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        }
        }
    }
    }


    /**
     * Calls wtfStack() if called with the DPMS lock held.
     */
    private void wtfIfInLock() {
        if (Thread.holdsLock(this)) {
            Slog.wtfStack(LOG_TAG, "Shouldn't be called with DPMS lock held");
        }
    }

    /**
    /**
     * The profile owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
     * The profile owner can only be set by adb or an app with the MANAGE_PROFILE_AND_DEVICE_OWNERS
     * permission.
     * permission.
@@ -9870,10 +9883,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        if (!isAdb()) {
        if (!isAdb()) {
            return true;
            return true;
        }
        }
        if (Thread.holdsLock(this)) {
        wtfIfInLock();
            Slog.wtf(LOG_TAG, "hasIncompatibleAccountsNoLock() called with the DPMS lock held.");
            return true;
        }


        final long token = mInjector.binderClearCallingIdentity();
        final long token = mInjector.binderClearCallingIdentity();
        try {
        try {