Merge "Fix deadlock in KeyguardDisableHandler" into qt-dev

This commit is contained in:
Rubin Xu
2019-05-27 19:50:06 +00:00
committed by Android (Google) Code Review
4 changed files with 98 additions and 13 deletions

View File

@@ -43,6 +43,12 @@ public abstract class DevicePolicyCache {
*/
public abstract boolean getScreenCaptureDisabled(@UserIdInt int userHandle);
/**
* Caches {@link DevicePolicyManager#getPasswordQuality(android.content.ComponentName)} of the
* given user with {@code null} passed in as argument.
*/
public abstract int getPasswordQuality(@UserIdInt int userHandle);
/**
* Empty implementation.
*/
@@ -53,5 +59,10 @@ public abstract class DevicePolicyCache {
public boolean getScreenCaptureDisabled(int userHandle) {
return false;
}
@Override
public int getPasswordQuality(int userHandle) {
return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
}
}
}

View File

@@ -19,6 +19,7 @@ package com.android.server.wm;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.os.Handler;
@@ -125,9 +126,7 @@ class KeyguardDisableHandler {
return new KeyguardDisableHandler(new Injector() {
@Override
public boolean dpmRequiresPassword(int userId) {
DevicePolicyManager dpm = (DevicePolicyManager) context.getSystemService(
Context.DEVICE_POLICY_SERVICE);
return dpm == null || dpm.getPasswordQuality(null, userId)
return DevicePolicyCache.getInstance().getPasswordQuality(userId)
!= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
}

View File

@@ -15,11 +15,16 @@
*/
package com.android.server.devicepolicy;
import android.annotation.UserIdInt;
import android.app.admin.DevicePolicyCache;
import android.app.admin.DevicePolicyManager;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
/**
* Implementation of {@link DevicePolicyCache}, to which {@link DevicePolicyManagerService} pushes
* policies.
@@ -36,9 +41,13 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
@GuardedBy("mLock")
private final SparseBooleanArray mScreenCaptureDisabled = new SparseBooleanArray();
@GuardedBy("mLock")
private final SparseIntArray mPasswordQuality = new SparseIntArray();
public void onUserRemoved(int userHandle) {
synchronized (mLock) {
mScreenCaptureDisabled.delete(userHandle);
mPasswordQuality.delete(userHandle);
}
}
@@ -54,4 +63,26 @@ public class DevicePolicyCacheImpl extends DevicePolicyCache {
mScreenCaptureDisabled.put(userHandle, disabled);
}
}
@Override
public int getPasswordQuality(@UserIdInt int userHandle) {
synchronized (mLock) {
return mPasswordQuality.get(userHandle,
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
}
}
/** Updat the password quality cache for the given user */
public void setPasswordQuality(int userHandle, int quality) {
synchronized (mLock) {
mPasswordQuality.put(userHandle, quality);
}
}
/** Dump content */
public void dump(String prefix, PrintWriter pw) {
pw.println("Device policy cache");
pw.println(prefix + "Screen capture disabled: " + mScreenCaptureDisabled.toString());
pw.println(prefix + "Password quality: " + mPasswordQuality.toString());
}
}

View File

@@ -2333,8 +2333,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Slog.w(LOG_TAG, "Tried to remove device policy file for user 0! Ignoring.");
return;
}
updatePasswordQualityCacheForUserGroup(userHandle);
mPolicyCache.onUserRemoved(userHandle);
mOwners.removeProfileOwner(userHandle);
mOwners.writeProfileOwner(userHandle);
@@ -3650,6 +3650,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
updateScreenCaptureDisabled(userId,
getScreenCaptureDisabled(null, userId));
pushUserRestrictions(userId);
// When system user is started (device boot), load cache for all users.
// This is to mitigate the potential race between loading the cache and keyguard
// reading the value during user switch, due to onStartUser() being asynchronous.
updatePasswordQualityCacheForUserGroup(
userId == UserHandle.USER_SYSTEM ? UserHandle.USER_ALL : userId);
startOwnerService(userId, "start-user");
}
@@ -4135,13 +4140,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
ActiveAdmin ap = getActiveAdminForCallerLocked(
who, DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD, parent);
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
if (metrics.quality != quality) {
metrics.quality = quality;
updatePasswordValidityCheckpointLocked(userId, parent);
saveSettingsLocked(userId);
final long ident = mInjector.binderClearCallingIdentity();
try {
final PasswordMetrics metrics = ap.minimumPasswordMetrics;
if (metrics.quality != quality) {
metrics.quality = quality;
updatePasswordValidityCheckpointLocked(userId, parent);
updatePasswordQualityCacheForUserGroup(userId);
saveSettingsLocked(userId);
}
maybeLogPasswordComplexitySet(who, userId, parent, metrics);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
maybeLogPasswordComplexitySet(who, userId, parent, metrics);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_PASSWORD_QUALITY)
@@ -4173,6 +4184,32 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
saveSettingsLocked(credentialOwner);
}
/**
* Update password quality values in policy cache for all users in the same user group as
* the given user. The cached password quality for user X is the aggregated quality among all
* admins who have influence of user X's screenlock, i.e. it's equivalent to the return value of
* getPasswordQuality(null, user X, false).
*
* Caches for all users in the same user group often need to be updated alltogether because a
* user's admin policy can affect another's aggregated password quality in some situation.
* For example a managed profile's policy will affect the parent user if the profile has unified
* challenge. A profile can also explicitly set a parent password quality which will affect the
* aggregated password quality of the parent user.
*/
private void updatePasswordQualityCacheForUserGroup(@UserIdInt int userId) {
final List<UserInfo> users;
if (userId == UserHandle.USER_ALL) {
users = mUserManager.getUsers();
} else {
users = mUserManager.getProfiles(userId);
}
for (UserInfo userInfo : users) {
final int currentUserId = userInfo.id;
mPolicyCache.setPasswordQuality(currentUserId,
getPasswordQuality(null, currentUserId, false));
}
}
@Override
public int getPasswordQuality(ComponentName who, int userHandle, boolean parent) {
if (!mHasFeature) {
@@ -8849,6 +8886,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mStatLogger.dump(pw, " ");
pw.println();
pw.println(" Encryption Status: " + getEncryptionStatusName(getEncryptionStatus()));
pw.println();
mPolicyCache.dump(" ", pw);
}
}
@@ -11319,8 +11358,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public void reportSeparateProfileChallengeChanged(@UserIdInt int userId) {
synchronized (getLockObject()) {
updateMaximumTimeToLockLocked(userId);
final long ident = mInjector.binderClearCallingIdentity();
try {
synchronized (getLockObject()) {
updateMaximumTimeToLockLocked(userId);
updatePasswordQualityCacheForUserGroup(userId);
}
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SEPARATE_PROFILE_CHALLENGE_CHANGED)
@@ -11336,7 +11381,6 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public CharSequence getPrintingDisabledReasonForUser(@UserIdInt int userId) {
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(userId);
if (!mUserManager.hasUserRestriction(UserManager.DISALLOW_PRINTING,
UserHandle.of(userId))) {
Log.e(LOG_TAG, "printing is enabled");