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

Commit de633f32 authored by Rubin Xu's avatar Rubin Xu
Browse files

Improve work profile unification flow

Expose internal API to check if the user's password
will be sufficient after profile unification. Also
expose some other helper methods and refactor
DevicePolicyManagerService to unify a few similar
methods that gather admins from user and its profiles.

Bug: 148630506
Fix: 149682344
Test: atest com.android.server.locksettings
Test: atest FrameworksServicesTests:DevicePolicyManagerTest
Change-Id: Ic647c14d5bab7e7337185bc40b1368e42c65f738
parent c6eea102
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -3663,6 +3663,28 @@ public class DevicePolicyManager {
        return false;
    }
    /**
     * Returns whether the given user's credential will be sufficient for all password policy
     * requirement, once the user's profile has switched to unified challenge.
     *
     * <p>This is different from {@link #isActivePasswordSufficient()} since once the profile
     * switches to unified challenge, policies set explicitly on the profile will start to affect
     * the parent user.
     * @param userHandle the user whose password requirement will be checked
     * @param profileUser the profile user whose lockscreen challenge will be unified.
     * @hide
     */
    public boolean isPasswordSufficientAfterProfileUnification(int userHandle, int profileUser) {
        if (mService != null) {
            try {
                return mService.isPasswordSufficientAfterProfileUnification(userHandle,
                        profileUser);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        }
        return false;
    }
    /**
     * Retrieve the number of times the user has failed at entering a password since that last
     * successful password entry.
+1 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ interface IDevicePolicyManager {

    boolean isActivePasswordSufficient(int userHandle, boolean parent);
    boolean isProfileActivePasswordSufficientForParent(int userHandle);
    boolean isPasswordSufficientAfterProfileUnification(int userHandle, int profileUser);
    int getPasswordComplexity(boolean parent);
    boolean isUsingUnifiedPassword(in ComponentName admin);
    int getCurrentFailedPasswordAttempts(int userHandle, boolean parent);
+1 −1
Original line number Diff line number Diff line
@@ -350,7 +350,7 @@ public final class PasswordMetrics implements Parcelable {
     *
     * TODO: move to PasswordPolicy
     */
    private void maxWith(PasswordMetrics other) {
    public void maxWith(PasswordMetrics other) {
        credType = Math.max(credType, other.credType);
        if (credType != CREDENTIAL_TYPE_PASSWORD) {
            return;
+22 −0
Original line number Diff line number Diff line
@@ -147,6 +147,28 @@ public class RestrictedLockUtils {
        public EnforcedAdmin() {
        }

        /**
         * Combines two {@link EnforcedAdmin} into one: if one of them is null, then just return
         * the other. If both of them are the same, then return that. Otherwise return the symbolic
         * {@link #MULTIPLE_ENFORCED_ADMIN}
         */
        public static EnforcedAdmin combine(EnforcedAdmin admin1, EnforcedAdmin admin2) {
            if (admin1 == null) {
                return admin2;
            }
            if (admin2 == null) {
                return admin1;
            }
            if (admin1.equals(admin2)) {
                return admin1;
            }
            if (!admin1.enforcedRestriction.equals(admin2.enforcedRestriction)) {
                throw new IllegalArgumentException(
                        "Admins with different restriction cannot be combined");
            }
            return MULTIPLE_ENFORCED_ADMIN;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
+25 −4
Original line number Diff line number Diff line
@@ -366,10 +366,15 @@ public class LockSettingsService extends ILockSettings.Stub {
        if (mStorage.hasChildProfileLock(managedUserId)) {
            return;
        }
        // Do not tie it to parent when parent does not have a screen lock
        // If parent does not have a screen lock, simply clear credential from the managed profile,
        // to maintain the invariant that unified profile should always have the same secure state
        // as its parent.
        final int parentId = mUserManager.getProfileParent(managedUserId).id;
        if (!isUserSecure(parentId)) {
            if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock");
        if (!isUserSecure(parentId) && !managedUserPassword.isNone()) {
            if (DEBUG) Slog.v(TAG, "Parent does not have a screen lock but profile has one");

            setLockCredentialInternal(LockscreenCredential.createNone(), managedUserPassword,
                    managedUserId, /* isLockTiedToParent= */ true);
            return;
        }
        // Do not tie when the parent has no SID (but does have a screen lock).
@@ -3161,6 +3166,21 @@ public class LockSettingsService extends ILockSettings.Stub {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timestamp));
    }

    private static String credentialTypeToString(int credentialType) {
        switch (credentialType) {
            case CREDENTIAL_TYPE_NONE:
                return "None";
            case CREDENTIAL_TYPE_PATTERN:
                return "Pattern";
            case CREDENTIAL_TYPE_PIN:
                return "Pin";
            case CREDENTIAL_TYPE_PASSWORD:
                return "Password";
            default:
                return "Unknown " + credentialType;
        }
    }

    @Override
    protected void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
        if (!DumpUtils.checkDumpPermission(mContext, TAG, printWriter)) return;
@@ -3192,7 +3212,8 @@ public class LockSettingsService extends ILockSettings.Stub {
            // It's OK to dump the password type since anyone with physical access can just
            // observe it from the keyguard directly.
            pw.println("Quality: " + getKeyguardStoredQuality(userId));
            pw.println("CredentialType: " + getCredentialTypeInternal(userId));
            pw.println("CredentialType: " + credentialTypeToString(
                    getCredentialTypeInternal(userId)));
            pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabledInternal(userId));
            pw.println(String.format("Metrics: %s",
                    getUserPasswordMetrics(userId) != null ? "known" : "unknown"));
Loading