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

Commit b4707f9a authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Option to skip profile password requirement during password enrolment"

parents 9e5c68e7 5eab037b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7191,6 +7191,7 @@ package android.app.admin {
    field public static final String EXTRA_ADD_EXPLANATION = "android.app.extra.ADD_EXPLANATION";
    field public static final String EXTRA_DELEGATION_SCOPES = "android.app.extra.DELEGATION_SCOPES";
    field public static final String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
    field public static final String EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY = "android.app.extra.DEVICE_PASSWORD_REQUIREMENT_ONLY";
    field @RequiresPermission(android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY) public static final String EXTRA_PASSWORD_COMPLEXITY = "android.app.extra.PASSWORD_COMPLEXITY";
    field public static final String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
    field public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
+46 −4
Original line number Diff line number Diff line
@@ -1685,6 +1685,20 @@ public class DevicePolicyManager {
     */
    public static final int PASSWORD_COMPLEXITY_HIGH = 0x50000;
    /**
     * A boolean extra for {@link #ACTION_SET_NEW_PARENT_PROFILE_PASSWORD} requesting that only
     * device password requirement is enforced during the parent profile password enrolment flow.
     * <p> Normally when enrolling password for the parent profile, both the device-wide password
     * requirement (requirement set via {@link #getParentProfileInstance(ComponentName)} instance)
     * and the profile password requirement are enforced, if the profile currently does not have a
     * separate work challenge. By setting this to {@code true}, profile password requirement is
     * explicitly disregarded.
     *
     * @see #isActivePasswordSufficientForDeviceRequirement()
     */
    public static final String EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY =
            "android.app.extra.DEVICE_PASSWORD_REQUIREMENT_ONLY";
    /**
     * @hide
     */
@@ -1700,8 +1714,10 @@ public class DevicePolicyManager {
    /**
     * Activity action: have the user enter a new password for the parent profile.
     * If the intent is launched from within a managed profile, this will trigger
     * entering a new password for the parent of the profile. In all other cases
     * the behaviour is identical to {@link #ACTION_SET_NEW_PASSWORD}.
     * entering a new password for the parent of the profile. The caller can optionally
     * set {@link #EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY} to only enforce device-wide
     * password requirement. In all other cases the behaviour is identical to
     * {@link #ACTION_SET_NEW_PASSWORD}.
     */
    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
    public static final String ACTION_SET_NEW_PARENT_PROFILE_PASSWORD
@@ -3844,9 +3860,21 @@ public class DevicePolicyManager {
     * @hide
     */
    public PasswordMetrics getPasswordMinimumMetrics(@UserIdInt int userHandle) {
        return getPasswordMinimumMetrics(userHandle, false);
    }
    /**
     * Returns minimum PasswordMetrics that satisfies all admin policies.
     * If requested, only consider device-wide admin policies and ignore policies set on the
     * managed profile instance (as if the managed profile had separate work challenge).
     *
     * @hide
     */
    public PasswordMetrics getPasswordMinimumMetrics(@UserIdInt int userHandle,
            boolean deviceWideOnly) {
        if (mService != null) {
            try {
                return mService.getPasswordMinimumMetrics(userHandle);
                return mService.getPasswordMinimumMetrics(userHandle, deviceWideOnly);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
@@ -4125,6 +4153,7 @@ public class DevicePolicyManager {
     * @throws SecurityException if the calling application is not a profile owner of a managed
     *   profile, or if this API is not called on the parent DevicePolicyManager instance.
     * @throws IllegalStateException if the user isn't unlocked
     * @see #EXTRA_DEVICE_PASSWORD_REQUIREMENT_ONLY
     */
    public boolean isActivePasswordSufficientForDeviceRequirement() {
        if (!mParentInstance) {
@@ -4250,12 +4279,25 @@ public class DevicePolicyManager {
     */
    @PasswordComplexity
    public int getAggregatedPasswordComplexityForUser(int userId) {
        return getAggregatedPasswordComplexityForUser(userId, false);
    }
    /**
     * 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). If {@code deviceWideOnly} is {@code true}, ignore policies set on the
     * managed profile DPM instance (as if the managed profile had separate work challenge).
     * @hide
     */
    @PasswordComplexity
    public int getAggregatedPasswordComplexityForUser(int userId, boolean deviceWideOnly) {
        if (mService == null) {
            return PASSWORD_COMPLEXITY_NONE;
        }
        try {
            return mService.getAggregatedPasswordComplexityForUser(userId);
            return mService.getAggregatedPasswordComplexityForUser(userId, deviceWideOnly);
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
+2 −2
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@ interface IDevicePolicyManager {
    void setPasswordMinimumNonLetter(in ComponentName who, int length, boolean parent);
    int getPasswordMinimumNonLetter(in ComponentName who, int userHandle, boolean parent);

    PasswordMetrics getPasswordMinimumMetrics(int userHandle);
    PasswordMetrics getPasswordMinimumMetrics(int userHandle, boolean deviceWideOnly);

    void setPasswordHistoryLength(in ComponentName who, int length, boolean parent);
    int getPasswordHistoryLength(in ComponentName who, int userHandle, boolean parent);
@@ -90,7 +90,7 @@ interface IDevicePolicyManager {
    int getPasswordComplexity(boolean parent);
    void setRequiredPasswordComplexity(int passwordComplexity, boolean parent);
    int getRequiredPasswordComplexity(boolean parent);
    int getAggregatedPasswordComplexityForUser(int userId);
    int getAggregatedPasswordComplexityForUser(int userId, boolean deviceWideOnly);
    boolean isUsingUnifiedPassword(in ComponentName admin);
    int getCurrentFailedPasswordAttempts(int userHandle, boolean parent);
    int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent);
+27 −29
Original line number Diff line number Diff line
@@ -307,49 +307,47 @@ public class LockPatternUtils {
        return getDevicePolicyManager().getPasswordMaximumLength(quality);
    }

    /**
     * Returns aggregated (legacy) password quality requirement on the target user from all admins.
     */
    public PasswordMetrics getRequestedPasswordMetrics(int userId) {
        return getDevicePolicyManager().getPasswordMinimumMetrics(userId);
        return getRequestedPasswordMetrics(userId, false);
    }

    /**
     * Returns the effective complexity for the user.
     * @param userId  The user to return the complexity for.
     * @return complexity level for the user.
     * Returns aggregated (legacy) password quality requirement on the target user from all admins,
     * optioanlly disregarding policies set on the managed profile as if the  profile had separate
     * work challenge.
     */
    public @DevicePolicyManager.PasswordComplexity int getRequestedPasswordComplexity(int userId) {
        return getDevicePolicyManager().getAggregatedPasswordComplexityForUser(userId);
    }

    public int getRequestedPasswordQuality(int userId) {
        return getDevicePolicyManager().getPasswordQuality(null, userId);
    public PasswordMetrics getRequestedPasswordMetrics(int userId, boolean deviceWideOnly) {
        return getDevicePolicyManager().getPasswordMinimumMetrics(userId, deviceWideOnly);
    }

    private int getRequestedPasswordHistoryLength(int userId) {
        return getDevicePolicyManager().getPasswordHistoryLength(null, userId);
    }

    public int getRequestedPasswordMinimumLetters(int userId) {
        return getDevicePolicyManager().getPasswordMinimumLetters(null, userId);
    }

    public int getRequestedPasswordMinimumUpperCase(int userId) {
        return getDevicePolicyManager().getPasswordMinimumUpperCase(null, userId);
    }

    public int getRequestedPasswordMinimumLowerCase(int userId) {
        return getDevicePolicyManager().getPasswordMinimumLowerCase(null, userId);
    }

    public int getRequestedPasswordMinimumNumeric(int userId) {
        return getDevicePolicyManager().getPasswordMinimumNumeric(null, 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 getRequestedPasswordComplexity(userId, false);
    }

    public int getRequestedPasswordMinimumSymbols(int userId) {
        return getDevicePolicyManager().getPasswordMinimumSymbols(null, userId);
    }
    /**
     * Returns the effective complexity for the user, optioanlly disregarding complexity set on the
     * managed profile as if the  profile had separate work challenge.

    public int getRequestedPasswordMinimumNonLetter(int userId) {
        return getDevicePolicyManager().getPasswordMinimumNonLetter(null, userId);
     * @param userId  The user to return the complexity for.
     * @param deviceWideOnly  whether to ignore complexity set on the managed profile.
     * @return complexity level for the user.
     */
    public @DevicePolicyManager.PasswordComplexity int getRequestedPasswordComplexity(int userId,
            boolean deviceWideOnly) {
        return getDevicePolicyManager().getAggregatedPasswordComplexityForUser(userId,
                deviceWideOnly);
    }

    @UnsupportedAppUsage
+41 −23
Original line number Diff line number Diff line
@@ -4187,21 +4187,36 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
     * Calculates strictest (maximum) value for a given password property enforced by admin[s].
     */
    @Override
    public PasswordMetrics getPasswordMinimumMetrics(@UserIdInt int userHandle) {
    public PasswordMetrics getPasswordMinimumMetrics(@UserIdInt int userHandle,
            boolean deviceWideOnly) {
        final CallerIdentity caller = getCallerIdentity();
        Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle));
        return getPasswordMinimumMetricsUnchecked(userHandle);
        return getPasswordMinimumMetricsUnchecked(userHandle, deviceWideOnly);
    }
    private PasswordMetrics getPasswordMinimumMetricsUnchecked(@UserIdInt int userId) {
        return getPasswordMinimumMetricsUnchecked(userId, false);
    }
    private PasswordMetrics getPasswordMinimumMetricsUnchecked(@UserIdInt int userId,
            boolean deviceWideOnly) {
        if (!mHasFeature) {
            new PasswordMetrics(CREDENTIAL_TYPE_NONE);
        }
        Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
        if (deviceWideOnly) {
            Preconditions.checkArgument(!isManagedProfile(userId));
        }
        ArrayList<PasswordMetrics> adminMetrics = new ArrayList<>();
        synchronized (getLockObject()) {
            List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(userId);
            final List<ActiveAdmin> admins;
            if (deviceWideOnly) {
                admins = getActiveAdminsForUserAndItsManagedProfilesLocked(userId,
                        /* shouldIncludeProfileAdmins */ (user) -> false);
            } else {
                admins = getActiveAdminsForLockscreenPoliciesLocked(userId);
            }
            for (ActiveAdmin admin : admins) {
                final boolean isAdminOfUser = userId == admin.getUserHandle().getIdentifier();
                // Use the password metrics from the admin in one of three cases:
@@ -4261,22 +4276,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        enforceUserUnlocked(parentUser);
        synchronized (getLockObject()) {
            // Combine password policies across the user and its profiles. Profile admins are
            // excluded since we only want explicit password requirements, while profile admin
            // requirement are applicable only when the profile has unified challenge.
            List<ActiveAdmin> admins = getActiveAdminsForUserAndItsManagedProfilesLocked(parentUser,
                    /* shouldIncludeProfileAdmins */ (user) -> false);
            ArrayList<PasswordMetrics> adminMetrics = new ArrayList<>(admins.size());
            int maxRequiredComplexity = PASSWORD_COMPLEXITY_NONE;
            for (ActiveAdmin admin : admins) {
                adminMetrics.add(admin.mPasswordPolicy.getMinMetrics());
                maxRequiredComplexity = Math.max(maxRequiredComplexity, admin.mPasswordComplexity);
            }
            int complexity = getAggregatedPasswordComplexityLocked(parentUser, true);
            PasswordMetrics minMetrics = getPasswordMinimumMetricsUnchecked(parentUser, true);
            PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(parentUser);
            return PasswordMetrics.validatePasswordMetrics(PasswordMetrics.merge(adminMetrics),
                    maxRequiredComplexity, false, metrics).isEmpty();
            final List<PasswordValidationError> passwordValidationErrors =
                    PasswordMetrics.validatePasswordMetrics(
                            minMetrics, complexity, false, metrics);
            return passwordValidationErrors.isEmpty();
        }
    }
@@ -4380,7 +4387,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
     */
    private boolean isPasswordSufficientForUserWithoutCheckpointLocked(
            @NonNull PasswordMetrics metrics, @UserIdInt int userId) {
        final int complexity = getEffectivePasswordComplexityRequirementLocked(userId);
        final int complexity = getAggregatedPasswordComplexityLocked(userId);
        PasswordMetrics minMetrics = getPasswordMinimumMetricsUnchecked(userId);
        final List<PasswordValidationError> passwordValidationErrors =
                PasswordMetrics.validatePasswordMetrics(
@@ -4482,9 +4489,20 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        }
    }
    private int getEffectivePasswordComplexityRequirementLocked(@UserIdInt int userHandle) {
    private int getAggregatedPasswordComplexityLocked(@UserIdInt int userHandle) {
        return getAggregatedPasswordComplexityLocked(userHandle, false);
    }
    private int getAggregatedPasswordComplexityLocked(@UserIdInt int userHandle,
            boolean deviceWideOnly) {
        ensureLocked();
        List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(userHandle);
        final List<ActiveAdmin> admins;
        if (deviceWideOnly) {
            admins = getActiveAdminsForUserAndItsManagedProfilesLocked(userHandle,
                    /* shouldIncludeProfileAdmins */ (user) -> false);
        } else {
            admins = getActiveAdminsForLockscreenPoliciesLocked(userHandle);
        }
        int maxRequiredComplexity = PASSWORD_COMPLEXITY_NONE;
        for (ActiveAdmin admin : admins) {
            maxRequiredComplexity = Math.max(maxRequiredComplexity, admin.mPasswordComplexity);
@@ -4512,7 +4530,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
    }
    @Override
    public int getAggregatedPasswordComplexityForUser(int userId) {
    public int getAggregatedPasswordComplexityForUser(int userId, boolean deviceWideOnly) {
        if (!mHasFeature) {
            return PASSWORD_COMPLEXITY_NONE;
        }
@@ -4521,7 +4539,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userId));
        synchronized (getLockObject()) {
            return getEffectivePasswordComplexityRequirementLocked(userId);
            return getAggregatedPasswordComplexityLocked(userId, deviceWideOnly);
        }
    }
@@ -4716,7 +4734,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        synchronized (getLockObject()) {
            final PasswordMetrics minMetrics = getPasswordMinimumMetricsUnchecked(userHandle);
            final List<PasswordValidationError> validationErrors;
            final int complexity = getEffectivePasswordComplexityRequirementLocked(userHandle);
            final int complexity = getAggregatedPasswordComplexityLocked(userHandle);
            // TODO: Consider changing validation API to take LockscreenCredential.
            if (password.isEmpty()) {
                validationErrors = PasswordMetrics.validatePasswordMetrics(
Loading