diff options
5 files changed, 74 insertions, 13 deletions
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 42427fa825eb..247d6f0de831 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -3721,6 +3721,27 @@ public class DevicePolicyManager { } /** + * Returns the password complexity that applies to this user, aggregated from other users if + * necessary (for example, if the DPC has set password complexity requirements on the parent + * profile DPM instance of a managed profile user, they would apply to the primary user on the + * device). + * @hide + */ + @PasswordComplexity + public int getAggregatedPasswordComplexityForUser(int userId) { + if (mService == null) { + return PASSWORD_COMPLEXITY_NONE; + } + + try { + return mService.getAggregatedPasswordComplexityForUser(userId); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + + /** * When called by a profile owner of a managed profile returns true if the profile uses unified * challenge with its parent user. * diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 58368bc3779a..37d34511902d 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -89,6 +89,7 @@ interface IDevicePolicyManager { int getPasswordComplexity(boolean parent); void setRequiredPasswordComplexity(int passwordComplexity, boolean parent); int getRequiredPasswordComplexity(boolean parent); + int getAggregatedPasswordComplexityForUser(int userId); boolean isUsingUnifiedPassword(in ComponentName admin); int getCurrentFailedPasswordAttempts(int userHandle, boolean parent); int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent); diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index b562ef838633..9712b4e794c5 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -311,6 +311,15 @@ public class LockPatternUtils { return getDevicePolicyManager().getPasswordMinimumMetrics(userId); } + /** + * Returns the effective complexity for the user. + * @param userId The user to return the complexity for. + * @return complexity level for the user. + */ + public @DevicePolicyManager.PasswordComplexity int getRequestedPasswordComplexity(int userId) { + return getDevicePolicyManager().getAggregatedPasswordComplexityForUser(userId); + } + public int getRequestedPasswordQuality(int userId) { return getDevicePolicyManager().getPasswordQuality(null, userId); } diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java index 9f16d033aea5..ac20ee14ced2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedLockUtilsInternal.java @@ -408,7 +408,8 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { } /** - * Checks if an admin has enforced minimum password quality requirements on the given user. + * Checks if an admin has enforced minimum password quality or complexity requirements on the + * given user. * * @return EnforcedAdmin Object containing the enforced admin component and admin user details, * or {@code null} if no quality requirements are set. If the requirements are set by @@ -428,6 +429,30 @@ public class RestrictedLockUtilsInternal extends RestrictedLockUtils { } LockPatternUtils lockPatternUtils = new LockPatternUtils(context); + final int aggregatedComplexity = dpm.getAggregatedPasswordComplexityForUser(userId); + if (aggregatedComplexity > DevicePolicyManager.PASSWORD_COMPLEXITY_NONE) { + // First, check if there's a Device Owner. If so, then only it can apply password + // complexity requiremnts (there can be no secondary profiles). + final UserHandle deviceOwnerUser = dpm.getDeviceOwnerUser(); + if (deviceOwnerUser != null) { + return new EnforcedAdmin(dpm.getDeviceOwnerComponentOnAnyUser(), deviceOwnerUser); + } + + // The complexity could be enforced by a Profile Owner - either in the current user + // or the current user is the parent user that is affected by the profile owner. + for (UserInfo userInfo : UserManager.get(context).getProfiles(userId)) { + final ComponentName profileOwnerComponent = dpm.getProfileOwnerAsUser(userInfo.id); + if (profileOwnerComponent != null) { + return new EnforcedAdmin(profileOwnerComponent, getUserHandleOf(userInfo.id)); + } + } + + // Should not get here: A Device Owner or Profile Owner should be found. + throw new IllegalStateException( + String.format("Could not find admin enforcing complexity %d for user %d", + aggregatedComplexity, userId)); + } + if (sProxy.isSeparateProfileChallengeEnabled(lockPatternUtils, userId)) { // userId is managed profile and has a separate challenge, only consider // the admins in that user. diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 81ce8ff3c72f..2f477afecf12 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -4203,11 +4203,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { int maxRequiredComplexity = PASSWORD_COMPLEXITY_NONE; for (ActiveAdmin admin : admins) { adminMetrics.add(admin.mPasswordPolicy.getMinMetrics()); - if (isDeviceOwner(admin) || isProfileOwnerUncheckedLocked(admin.info.getComponent(), - admin.getUserHandle().getIdentifier())) { - maxRequiredComplexity = Math.max(maxRequiredComplexity, - admin.mPasswordComplexity); - } + maxRequiredComplexity = Math.max(maxRequiredComplexity, admin.mPasswordComplexity); } return PasswordMetrics.validatePasswordMetrics(PasswordMetrics.merge(adminMetrics), maxRequiredComplexity, false, metrics).isEmpty(); @@ -4320,13 +4316,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(userHandle); int maxRequiredComplexity = PASSWORD_COMPLEXITY_NONE; for (ActiveAdmin admin : admins) { - final ComponentName adminComponent = admin.info.getComponent(); - final int adminUser = admin.getUserHandle().getIdentifier(); - // Password complexity is only taken into account from DO/PO - if (isDeviceOwner(adminComponent, adminUser) - || isProfileOwnerUncheckedLocked(adminComponent, adminUser)) { - maxRequiredComplexity = Math.max(maxRequiredComplexity, admin.mPasswordComplexity); - } + maxRequiredComplexity = Math.max(maxRequiredComplexity, admin.mPasswordComplexity); } return maxRequiredComplexity; } @@ -4351,6 +4341,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public int getAggregatedPasswordComplexityForUser(int userId) { + if (!mHasFeature) { + return PASSWORD_COMPLEXITY_NONE; + } + + final CallerIdentity caller = getCallerIdentity(); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId)); + + synchronized (getLockObject()) { + return getEffectivePasswordComplexityRequirementLocked(userId); + } + } + + + @Override public int getCurrentFailedPasswordAttempts(int userHandle, boolean parent) { if (!mLockPatternUtils.hasSecureLockScreen()) { return 0; |