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
This commit is contained in:
Craig Mautner
2014-09-04 12:56:39 -07:00
parent e8f8bc0ad6
commit 66eb521833

View File

@@ -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 {
long ident = Binder.clearCallingIdentity();
try {
boolean wipeData = false;
int identifier = 0;
synchronized (this) {
DevicePolicyData policy = getUserData(userHandle);
policy.mFailedPasswordAttempts++;
saveSettingsLocked(userHandle);
if (mHasFeature) {
@@ -3013,15 +3015,20 @@ 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);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
if (wipeData) {
// Call without holding lock.
wipeDeviceOrUserLocked(0, identifier);
}
} finally {
Binder.restoreCallingIdentity(ident);
}
}