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

Commit 3165008c authored by Haining Chen's avatar Haining Chen
Browse files

Add toggle for failed authentication lock

The secure settings disable_adaptive_auth_limit_lock was added to
disable the lock by adaptive auth on debuggable builds via adb. In
prepartion for a user-facing toggle for failed auth lock, this change
does the following:

1. Remove the restriction of debuggable builds
2. Make the behaviors of profiles users consistent with their parent
   users (main users), because the toggle for failed auth lock is for
   main users only. For example, if the lock is enabled for a main user
   (e.g. via the toggle) and is disabled for a profile (e.g. via adb),
   the lock should remain as enabled for the profile. Similarly, if the
   lock is disabled for a main user (e.g. via the toggle) and is enabled
   for a profile (e.g. via adb), the lock should remain as disabled for
   the profile.

Flag: android.security.failed_auth_lock_toggle
Bug: 414605464
Test: atest AuthenticationPolicyServiceTest
Change-Id: I4e2c7e851d296eb4e7600b8e55af693dc661c369
parent 71f68030
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.MANAGE_SECURE_LOCK_DEVICE;
import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
import static android.security.Flags.disableAdaptiveAuthCounterLock;
import static android.security.Flags.failedAuthLockToggle;

import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_ADAPTIVE_AUTH_REQUEST;

@@ -81,6 +82,7 @@ public class AuthenticationPolicyService extends SystemService {

    @VisibleForTesting
    static final int MAX_ALLOWED_FAILED_AUTH_ATTEMPTS = 5;
    private static final boolean DEFAULT_DISABLE_ADAPTIVE_AUTH_LIMIT_LOCK = false;
    private static final int MSG_REPORT_PRIMARY_AUTH_ATTEMPT = 1;
    private static final int MSG_REPORT_BIOMETRIC_AUTH_ATTEMPT = 2;
    private static final int AUTH_SUCCESS = 1;
@@ -264,13 +266,21 @@ public class AuthenticationPolicyService extends SystemService {
            return;
        }

        if (disableAdaptiveAuthCounterLock() && Build.IS_DEBUGGABLE) {
        //TODO(b/421051706): Remove the condition Build.IS_DEBUGGABLE after flags are ramped up
        if (failedAuthLockToggle()
                || (disableAdaptiveAuthCounterLock() && Build.IS_DEBUGGABLE)) {
            // If userId is a profile, use its parent's settings to determine whether failed auth
            // lock is enabled or disabled for the profile, irrespective of the profile's own
            // settings. If userId is a main user (i.e. parentUserId equals to userId), use its own
            // settings
            final int parentUserId = mUserManager.getProfileParentId(userId);
            final boolean disabled = Settings.Secure.getIntForUser(
                    getContext().getContentResolver(),
                    Settings.Secure.DISABLE_ADAPTIVE_AUTH_LIMIT_LOCK,
                    0 /* default */, userId) != 0;
                    DEFAULT_DISABLE_ADAPTIVE_AUTH_LIMIT_LOCK ? 1 : 0, parentUserId) != 0;
            if (disabled) {
                Slog.d(TAG, "not locking (disabled by user)");
                Slog.i(TAG, "userId=" + userId + ", parentUserId=" + parentUserId
                        + ", failed auth lock is disabled by user in settings");
                return;
            }
        }
+37 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.hardware.biometrics.events.AuthenticationFailedInfo;
import android.hardware.biometrics.events.AuthenticationSucceededInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.platform.test.flag.junit.SetFlagsRule;
@@ -159,6 +160,7 @@ public class AuthenticationPolicyServiceTest {
        if (android.security.Flags.secureLockdown()) {
            LocalServices.removeServiceForTest(SecureLockDeviceServiceInternal.class);
        }
        toggleAdaptiveAuthSettingsOverride(PRIMARY_USER_ID, false /* disable */);
    }

    @Test
@@ -334,6 +336,23 @@ public class AuthenticationPolicyServiceTest {
                false /* enabled */);
    }

    @Test
    @DisableFlags({android.security.Flags.FLAG_DISABLE_ADAPTIVE_AUTH_COUNTER_LOCK})
    @EnableFlags({android.security.Flags.FLAG_FAILED_AUTH_LOCK_TOGGLE})
    public void testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_primaryUserAndProfile_deviceLockDisabled()
            throws RemoteException {
        // The failed auth lock toggle for the primary user is set to disable
        toggleAdaptiveAuthSettingsOverride(PRIMARY_USER_ID, true /* disabled */);
        // The failed auth lock toggle for the managed profile is set to enable
        toggleAdaptiveAuthSettingsOverride(MANAGED_PROFILE_USER_ID, false /* disabled */);

        // Device lock should be disabled for both the primary user and its profile
        testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_primaryUser(
                false /* enabled */);
        testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_profileOfPrimaryUser(
                false /* enabled */);
    }

    private void testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_primaryUser(
            boolean enabled) throws RemoteException {
        // Three failed primary auth attempts
@@ -355,8 +374,20 @@ public class AuthenticationPolicyServiceTest {
    }

    @Test
    public void testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_profileOfPrimaryUser()
    @DisableFlags({android.security.Flags.FLAG_DISABLE_ADAPTIVE_AUTH_COUNTER_LOCK})
    @EnableFlags({android.security.Flags.FLAG_FAILED_AUTH_LOCK_TOGGLE})
    public void testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_profile_deviceLockEnabled()
            throws RemoteException {
        // The failed auth lock toggle for the primary user is set to enable in test setup, so the
        // toggle for the managed profile is implicitly set to enable

        // Device lock should be enabled for the managed profile
        testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_profileOfPrimaryUser(
                true /* enabled */);
    }

    private void testReportAuthAttempt_primaryAuthAndBiometricAuthFailed_profileOfPrimaryUser(
            boolean enabled) throws RemoteException {
        // Three failed primary auth attempts
        for (int i = 0; i < 3; i++) {
            mLockSettingsStateListenerCaptor.getValue()
@@ -369,7 +400,11 @@ public class AuthenticationPolicyServiceTest {
        }
        waitForAuthCompletion();

        if (enabled) {
            verifyLockDevice(MANAGED_PROFILE_USER_ID);
        } else {
            verifyNotLockDevice(MAX_ALLOWED_FAILED_AUTH_ATTEMPTS, MANAGED_PROFILE_USER_ID);
        }
    }

    private void verifyNotLockDevice(int expectedCntFailedAttempts, int userId) {