diff options
| author | 2024-07-12 17:59:55 +0000 | |
|---|---|---|
| committer | 2024-07-12 17:59:55 +0000 | |
| commit | 499a786e97984c25d73d6603efe0d23a5f6c5b2b (patch) | |
| tree | a12356699948e784319de8097e714258bd68f9c5 | |
| parent | b54b9b5251377e9a5ce31390c59d56cc82556841 (diff) | |
| parent | ba344cc5f967129274fc8faba6a4c847e6749a2b (diff) | |
Merge "Add flag to subscribe trust manager to primary auth events" into main
6 files changed, 86 insertions, 6 deletions
diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index 38afb807dcf2..5e8d720cc943 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -83,3 +83,10 @@ flag { description: "Add a dump capability for attestation_verification service" bug: "335498868" } + +flag { + name: "should_trust_manager_listen_for_primary_auth" + namespace: "biometrics" + description: "Causes TrustManagerService to listen for credential attempts and ignore reports from upstream" + bug: "323086607" +} diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java index f4ad487f48ac..19c6f51ff9a7 100644 --- a/core/java/com/android/internal/widget/LockPatternUtils.java +++ b/core/java/com/android/internal/widget/LockPatternUtils.java @@ -22,6 +22,8 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED; +import static android.security.Flags.reportPrimaryAuthAttempts; +import static android.security.Flags.shouldTrustManagerListenForPrimaryAuth; import android.annotation.IntDef; import android.annotation.NonNull; @@ -414,7 +416,9 @@ public class LockPatternUtils { return; } getDevicePolicyManager().reportFailedPasswordAttempt(userId); - getTrustManager().reportUnlockAttempt(false /* authenticated */, userId); + if (!reportPrimaryAuthAttempts() || !shouldTrustManagerListenForPrimaryAuth()) { + getTrustManager().reportUnlockAttempt(/* authenticated= */ false, userId); + } } @UnsupportedAppUsage @@ -423,7 +427,9 @@ public class LockPatternUtils { return; } getDevicePolicyManager().reportSuccessfulPasswordAttempt(userId); - getTrustManager().reportUnlockAttempt(true /* authenticated */, userId); + if (!reportPrimaryAuthAttempts() || !shouldTrustManagerListenForPrimaryAuth()) { + getTrustManager().reportUnlockAttempt(/* authenticated= */ true, userId); + } } public void reportPasswordLockout(int timeoutMs, int userId) { diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index b3c31a9cfb64..a0ccc9d99d05 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -16,6 +16,7 @@ package com.android.server.trust; +import static android.security.Flags.shouldTrustManagerListenForPrimaryAuth; import static android.service.trust.GrantTrustResult.STATUS_UNLOCKED_BY_GRANT; import static android.service.trust.TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE; @@ -82,6 +83,9 @@ import com.android.internal.content.PackageMonitor; import com.android.internal.infra.AndroidFuture; import com.android.internal.util.DumpUtils; import com.android.internal.widget.LockPatternUtils; +import com.android.internal.widget.LockSettingsInternal; +import com.android.internal.widget.LockSettingsStateListener; +import com.android.server.LocalServices; import com.android.server.SystemService; import org.xmlpull.v1.XmlPullParser; @@ -154,6 +158,7 @@ public class TrustManagerService extends SystemService { /* package */ final TrustArchive mArchive = new TrustArchive(); private final Context mContext; + private final LockSettingsInternal mLockSettings; private final LockPatternUtils mLockPatternUtils; private final KeyStoreAuthorization mKeyStoreAuthorization; private final UserManager mUserManager; @@ -245,6 +250,20 @@ public class TrustManagerService extends SystemService { private final StrongAuthTracker mStrongAuthTracker; + // Used to subscribe to device credential auth attempts. + private final LockSettingsStateListener mLockSettingsStateListener = + new LockSettingsStateListener() { + @Override + public void onAuthenticationSucceeded(int userId) { + mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, 1, userId).sendToTarget(); + } + + @Override + public void onAuthenticationFailed(int userId) { + mHandler.obtainMessage(MSG_DISPATCH_UNLOCK_ATTEMPT, 0, userId).sendToTarget(); + } + }; + private boolean mTrustAgentsCanRun = false; private int mCurrentUser = UserHandle.USER_SYSTEM; @@ -286,6 +305,7 @@ public class TrustManagerService extends SystemService { mHandler = createHandler(injector.getLooper()); mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE); mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); + mLockSettings = LocalServices.getService(LockSettingsInternal.class); mLockPatternUtils = injector.getLockPatternUtils(); mKeyStoreAuthorization = injector.getKeyStoreAuthorization(); mStrongAuthTracker = new StrongAuthTracker(context, injector.getLooper()); @@ -307,6 +327,9 @@ public class TrustManagerService extends SystemService { checkNewAgents(); mPackageMonitor.register(mContext, mHandler.getLooper(), UserHandle.ALL, true); mReceiver.register(mContext); + if (shouldTrustManagerListenForPrimaryAuth()) { + mLockSettings.registerLockSettingsStateListener(mLockSettingsStateListener); + } mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker); mFingerprintManager = mContext.getSystemService(FingerprintManager.class); mFaceManager = mContext.getSystemService(FaceManager.class); diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp index 6d3b8ac45913..7eb3441a487a 100644 --- a/services/tests/mockingservicestests/Android.bp +++ b/services/tests/mockingservicestests/Android.bp @@ -53,6 +53,7 @@ android_test { "mockingservicestests-utils-mockito", "mockito-target-extended-minus-junit4", "platform-compat-test-rules", + "platform-parametric-runner-lib", "platform-test-annotations", "PlatformProperties", "service-blobstore", diff --git a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java index 00daf415375e..1a398c5f1ec3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/trust/TrustManagerServiceTest.java @@ -16,6 +16,8 @@ package com.android.server.trust; +import static android.security.Flags.FLAG_SHOULD_TRUST_MANAGER_LISTEN_FOR_PRIMARY_AUTH; +import static android.security.Flags.shouldTrustManagerListenForPrimaryAuth; import static android.service.trust.TrustAgentService.FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE; import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; @@ -73,6 +75,8 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.UserHandle; import android.os.UserManager; +import android.platform.test.flag.junit.FlagsParameterization; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; import android.security.KeyStoreAuthorization; import android.service.trust.GrantTrustResult; @@ -91,6 +95,7 @@ import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.LockPatternUtils.StrongAuthTracker; import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.StrongAuthFlags; import com.android.internal.widget.LockSettingsInternal; +import com.android.internal.widget.LockSettingsStateListener; import com.android.modules.utils.testing.ExtendedMockitoRule; import com.android.server.LocalServices; import com.android.server.SystemService; @@ -101,6 +106,7 @@ import org.junit.Before; import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.Mock; @@ -112,7 +118,16 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import platform.test.runner.parameterized.ParameterizedAndroidJunit4; +import platform.test.runner.parameterized.Parameters; + +@RunWith(ParameterizedAndroidJunit4.class) public class TrustManagerServiceTest { + @Parameters(name = "{0}") + public static List<FlagsParameterization> getParams() { + return FlagsParameterization.allCombinationsOf( + FLAG_SHOULD_TRUST_MANAGER_LISTEN_FOR_PRIMARY_AUTH); + } @Rule public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this) @@ -122,6 +137,9 @@ public class TrustManagerServiceTest { .build(); @Rule + public final SetFlagsRule mSetFlagsRule; + + @Rule public final MockContext mMockContext = new MockContext( ApplicationProvider.getApplicationContext()); @@ -162,6 +180,10 @@ public class TrustManagerServiceTest { private ITrustManager mTrustManager; private ActivityManagerInternal mPreviousActivityManagerInternal; + public TrustManagerServiceTest(FlagsParameterization flags) { + mSetFlagsRule = new SetFlagsRule(SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT, flags); + } + @Before public void setUp() throws Exception { when(mActivityManager.isUserRunning(TEST_USER_ID)).thenReturn(true); @@ -594,11 +616,27 @@ public class TrustManagerServiceTest { } private void attemptSuccessfulUnlock(int userId) throws RemoteException { - mTrustManager.reportUnlockAttempt(/* successful= */ true, userId); + if (shouldTrustManagerListenForPrimaryAuth()) { + ArgumentCaptor<LockSettingsStateListener> captor = + ArgumentCaptor.forClass(LockSettingsStateListener.class); + verify(mLockSettingsInternal).registerLockSettingsStateListener(captor.capture()); + LockSettingsStateListener listener = captor.getValue(); + listener.onAuthenticationSucceeded(userId); + } else { + mTrustManager.reportUnlockAttempt(/* successful= */ true, userId); + } } private void attemptFailedUnlock(int userId) throws RemoteException { - mTrustManager.reportUnlockAttempt(/* successful= */ false, userId); + if (shouldTrustManagerListenForPrimaryAuth()) { + ArgumentCaptor<LockSettingsStateListener> captor = + ArgumentCaptor.forClass(LockSettingsStateListener.class); + verify(mLockSettingsInternal).registerLockSettingsStateListener(captor.capture()); + LockSettingsStateListener listener = captor.getValue(); + listener.onAuthenticationFailed(userId); + } else { + mTrustManager.reportUnlockAttempt(/* successful= */ false, userId); + } } private void grantRenewableTrust(ITrustAgentServiceCallback callback) throws RemoteException { diff --git a/tests/TrustTests/src/android/trust/test/UnlockAttemptTest.kt b/tests/TrustTests/src/android/trust/test/UnlockAttemptTest.kt index 2c9361df63fd..f9e004bcd29e 100644 --- a/tests/TrustTests/src/android/trust/test/UnlockAttemptTest.kt +++ b/tests/TrustTests/src/android/trust/test/UnlockAttemptTest.kt @@ -17,6 +17,7 @@ package android.trust.test import android.app.trust.TrustManager import android.content.Context +import android.security.Flags.shouldTrustManagerListenForPrimaryAuth import android.trust.BaseTrustAgentService import android.trust.TrustTestActivity import android.trust.test.lib.LockStateTrackingRule @@ -154,13 +155,17 @@ class UnlockAttemptTest { private fun triggerSuccessfulUnlock() { screenLockRule.successfulScreenLockAttempt() - trustAgentRule.reportSuccessfulUnlock() + if (!shouldTrustManagerListenForPrimaryAuth()) { + trustAgentRule.reportSuccessfulUnlock() + } await() } private fun triggerFailedUnlock() { screenLockRule.failedScreenLockAttempt() - trustAgentRule.reportFailedUnlock() + if (!shouldTrustManagerListenForPrimaryAuth()) { + trustAgentRule.reportFailedUnlock() + } await() } |