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

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

Merge "Introduce DPM.isActivePasswordSufficientForDeviceRequirement"

parents fcdeb3ff c942308e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -6989,6 +6989,7 @@ package android.app.admin {
    method public boolean installKeyPair(@Nullable android.content.ComponentName, @NonNull java.security.PrivateKey, @NonNull java.security.cert.Certificate[], @NonNull String, int);
    method public void installSystemUpdate(@NonNull android.content.ComponentName, @NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback);
    method public boolean isActivePasswordSufficient();
    method public boolean isActivePasswordSufficientForDeviceRequirement();
    method public boolean isAdminActive(@NonNull android.content.ComponentName);
    method public boolean isAffiliatedUser();
    method public boolean isAlwaysOnVpnLockdownEnabled(@NonNull android.content.ComponentName);
+45 −0
Original line number Diff line number Diff line
@@ -3885,6 +3885,51 @@ public class DevicePolicyManager {
        return false;
    }
    /**
     * Called by profile owner of a managed profile to determine whether the current device password
     * meets policy requirements set explicitly device-wide.
     * <p> This API is similar to {@link #isActivePasswordSufficient()}, with two notable
     * differences:
     * <ul>
     * <li>this API always targets the device password. As a result it should always be called on
     *   the {@link #getParentProfileInstance(ComponentName)} instance.</li>
     * <li>password policy requirement set on the managed profile is not taken into consideration
     *   by this API, even if the device currently does not have a separate work challenge set.</li>
     * </ul>
     *
     * <p>This API is designed to facilite progressive password enrollment flows when the DPC
     * imposes both device and profile password policies. DPC applies profile password policy by
     * calling {@link #setPasswordQuality(ComponentName, int)} or
     * {@link #setRequiredPasswordComplexity} on the regular {@link DevicePolicyManager} instance,
     * while it applies device-wide policy by calling {@link #setRequiredPasswordComplexity} on the
     * {@link #getParentProfileInstance(ComponentName)} instance. The DPC can utilize this check to
     * guide the user to set a device password first taking into consideration the device-wide
     * policy only, and then prompt the user to either upgrade it to be fully compliant, or enroll a
     * separate work challenge to satisfy the profile password policy only.
     *
     * <p>The device user must be unlocked (@link {@link UserManager#isUserUnlocked(UserHandle)})
     * to perform this check.
     *
     * @return {@code true} if the device password meets explicit requirement set on it,
     *   {@code false} otherwise.
     * @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
     */
    public boolean isActivePasswordSufficientForDeviceRequirement() {
        if (!mParentInstance) {
            throw new SecurityException("only callable on the parent instance");
        }
        if (mService != null) {
            try {
                return mService.isActivePasswordSufficientForDeviceRequirement();
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return false;
    }
    /**
     * Returns how complex the current user's screen lock is.
     *
+1 −0
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ interface IDevicePolicyManager {
    long getPasswordExpiration(in ComponentName who, int userHandle, boolean parent);

    boolean isActivePasswordSufficient(int userHandle, boolean parent);
    boolean isActivePasswordSufficientForDeviceRequirement();
    boolean isProfileActivePasswordSufficientForParent(int userHandle);
    boolean isPasswordSufficientAfterProfileUnification(int userHandle, int profileUser);
    int getPasswordComplexity(boolean parent);
+37 −0
Original line number Diff line number Diff line
@@ -4164,6 +4164,43 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
        }
    }
    @Override
    public boolean isActivePasswordSufficientForDeviceRequirement() {
        if (!mHasFeature) {
            return true;
        }
        final CallerIdentity caller = getCallerIdentity();
        Preconditions.checkCallAuthorization(isProfileOwner(caller));
        final int profileUserId = caller.getUserId();
        Preconditions.checkCallingUser(isManagedProfile(profileUserId));
        // This method is always called on the parent DPM instance to check if its password (i.e.
        // the device password) is sufficient for all explicit password requirement set on it
        // So retrieve the parent user Id to which the device password belongs.
        final int parentUser = getProfileParentId(profileUserId);
        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);
            }
            PasswordMetrics metrics = mLockSettingsInternal.getUserPasswordMetrics(parentUser);
            return PasswordMetrics.validatePasswordMetrics(PasswordMetrics.merge(adminMetrics),
                    maxRequiredComplexity, false, metrics).isEmpty();
        }
    }
    @Override
    public boolean isUsingUnifiedPassword(ComponentName admin) {
        if (!mHasFeature) {