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

Commit 66eb5218 authored by Craig Mautner's avatar Craig Mautner
Browse files

Eliminate deadlock by deferring wipe data call

The call to RecoverySystem.rebootWipeUserData() was made while
holding the lock to DevicePolicyManagerService. But it blocks
waiting for system_process' main thread to receive the ordered
broadcast complete callback. It won't receive that callback
because Keyguard is running on the main thread and is concurrently
blocked on DevicePolicyManagerService.

By moving the call to rebootWipeUserData() out of the synchronized
block the deadlock is eliminated.

Fixes bug 16870054.

Change-Id: I3eb587211e5484859cc9dab7e80e5a1f6c85225d
parent e8f8bc0a
Loading
Loading
Loading
Loading
+14 −7
Original line number Diff line number Diff line
@@ -2998,10 +2998,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
        mContext.enforceCallingOrSelfPermission(
                android.Manifest.permission.BIND_DEVICE_ADMIN, null);

        synchronized (this) {
            DevicePolicyData policy = getUserData(userHandle);
        long ident = Binder.clearCallingIdentity();
        try {
            boolean wipeData = false;
            int identifier = 0;
            synchronized (this) {
                DevicePolicyData policy = getUserData(userHandle);
                policy.mFailedPasswordAttempts++;
                saveSettingsLocked(userHandle);
                if (mHasFeature) {
@@ -3013,17 +3015,22 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
                        // Wipe the user/profile associated with the policy that was violated. This
                        // is not necessarily calling user: if the policy that fired was from a
                        // managed profile rather than the main user profile, we wipe former only.
                        wipeDeviceOrUserLocked(0, strictestAdmin.getUserHandle().getIdentifier());
                        wipeData = true;
                        identifier = strictestAdmin.getUserHandle().getIdentifier();
                    }
                    sendAdminCommandToSelfAndProfilesLocked(
                            DeviceAdminReceiver.ACTION_PASSWORD_FAILED,
                            DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, userHandle);
                }
            }
            if (wipeData) {
                // Call without holding lock.
                wipeDeviceOrUserLocked(0, identifier);
            }
        } finally {
            Binder.restoreCallingIdentity(ident);
        }
    }
    }

    public void reportSuccessfulPasswordAttempt(int userHandle) {
        enforceCrossUserPermission(userHandle);