diff options
| -rw-r--r-- | packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java | 339 |
1 files changed, 329 insertions, 10 deletions
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 85ecfd3056ff..035404ccbfe1 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -16,6 +16,7 @@ package com.android.keyguard; +import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE; import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID; @@ -31,7 +32,6 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.clearInvocations; -import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -41,6 +41,7 @@ import static org.mockito.Mockito.when; import android.app.Activity; import android.app.ActivityManager; +import android.app.IActivityManager; import android.app.admin.DevicePolicyManager; import android.app.trust.IStrongAuthTracker; import android.app.trust.TrustManager; @@ -52,6 +53,7 @@ import android.content.IntentFilter; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.UserInfo; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.BiometricManager; import android.hardware.biometrics.BiometricSourceType; @@ -68,6 +70,7 @@ import android.os.Bundle; import android.os.CancellationSignal; import android.os.Handler; import android.os.IRemoteCallback; +import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.telephony.ServiceState; @@ -182,6 +185,18 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { private ActiveUnlockConfig mActiveUnlockConfig; @Mock private KeyguardUpdateMonitorLogger mKeyguardUpdateMonitorLogger; + @Mock + private IActivityManager mActivityService; + + private final int mCurrentUserId = 100; + private final UserInfo mCurrentUserInfo = new UserInfo(mCurrentUserId, "Test user", 0); + + @Captor + private ArgumentCaptor<IBiometricEnabledOnKeyguardCallback> + mBiometricEnabledCallbackArgCaptor; + @Captor + private ArgumentCaptor<FaceManager.AuthenticationCallback> mAuthenticationCallbackCaptor; + // Direct executor private Executor mBackgroundExecutor = Runnable::run; private Executor mMainExecutor = Runnable::run; @@ -190,18 +205,16 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { private TestableContext mSpiedContext; private MockitoSession mMockitoSession; private StatusBarStateController.StateListener mStatusBarStateListener; + private IBiometricEnabledOnKeyguardCallback mBiometricEnabledOnKeyguardCallback; @Before - public void setup() { + public void setup() throws RemoteException { MockitoAnnotations.initMocks(this); mSpiedContext = spy(mContext); when(mPackageManager.hasSystemFeature(anyString())).thenReturn(true); when(mSpiedContext.getPackageManager()).thenReturn(mPackageManager); - doAnswer(invocation -> { - IBiometricEnabledOnKeyguardCallback callback = invocation.getArgument(0); - callback.onChanged(true /* enabled */, KeyguardUpdateMonitor.getCurrentUser()); - return null; - }).when(mBiometricManager).registerEnabledOnKeyguardCallback(any()); + when(mActivityService.getCurrentUser()).thenReturn(mCurrentUserInfo); + when(mActivityService.getCurrentUserId()).thenReturn(mCurrentUserId); when(mFaceManager.isHardwareDetected()).thenReturn(true); when(mFaceManager.hasEnrolledTemplates()).thenReturn(true); when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); @@ -262,13 +275,20 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { .startMocking(); ExtendedMockito.doReturn(SubscriptionManager.INVALID_SUBSCRIPTION_ID) .when(SubscriptionManager::getDefaultSubscriptionId); + KeyguardUpdateMonitor.setCurrentUser(mCurrentUserId); ExtendedMockito.doReturn(KeyguardUpdateMonitor.getCurrentUser()) .when(ActivityManager::getCurrentUser); + ExtendedMockito.doReturn(mActivityService).when(ActivityManager::getService); mTestableLooper = TestableLooper.get(this); allowTestableLooperAsMainThread(); mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext); + verify(mBiometricManager) + .registerEnabledOnKeyguardCallback(mBiometricEnabledCallbackArgCaptor.capture()); + mBiometricEnabledOnKeyguardCallback = mBiometricEnabledCallbackArgCaptor.getValue(); + biometricsEnabledForCurrentUser(); + verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue(); mKeyguardUpdateMonitor.registerCallback(mTestCallback); @@ -718,7 +738,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { verify(mLockPatternUtils).requireStrongAuth(anyInt(), anyInt()); } - @Test public void testFaceAndFingerprintLockout() { mKeyguardUpdateMonitor.dispatchStartedWakingUp(); @@ -924,6 +943,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Test public void testSecondaryLockscreenRequirement() { + KeyguardUpdateMonitor.setCurrentUser(UserHandle.myUserId()); int user = KeyguardUpdateMonitor.getCurrentUser(); String packageName = "fake.test.package"; String cls = "FakeService"; @@ -1097,8 +1117,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { @Test public void testShouldNotUpdateBiometricListeningStateOnStatusBarStateChange() { // GIVEN state for face auth should run aside from StatusBarState - when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, - KeyguardUpdateMonitor.getCurrentUser())).thenReturn(0); + biometricsNotDisabledThroughDevicePolicyManager(); mStatusBarStateListener.onStateChanged(StatusBarState.SHADE_LOCKED); setKeyguardBouncerVisibility(false /* isVisible */); mKeyguardUpdateMonitor.dispatchStartedWakingUp(); @@ -1153,6 +1172,306 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { verify(mTestCallback).showTrustGrantedMessage("Unlocked by wearable"); } + @Test + public void testShouldListenForFace_whenFaceManagerNotAvailable_returnsFalse() { + mFaceManager = null; + mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test + public void testShouldListenForFace_whenFpIsLockedOut_returnsFalse() throws RemoteException { + // Face auth should run when the following is true. + keyguardNotGoingAway(); + bouncerFullyVisibleAndNotGoingToSleep(); + currentUserIsPrimary(); + strongAuthNotRequired(); + biometricsEnabledForCurrentUser(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + userNotCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + // Fingerprint is locked out. + fingerprintErrorLockedOut(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test + public void testShouldListenForFace_whenFaceIsAlreadyAuthenticated_returnsFalse() + throws RemoteException { + // Face auth should run when the following is true. + bouncerFullyVisibleAndNotGoingToSleep(); + keyguardNotGoingAway(); + currentUserIsPrimary(); + strongAuthNotRequired(); + biometricsEnabledForCurrentUser(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + userNotCurrentlySwitching(); + + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + + triggerSuccessfulFaceAuth(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test + public void testShouldListenForFace_whenUserIsNotPrimary_returnsFalse() throws RemoteException { + // This disables face auth + when(mUserManager.isPrimaryUser()).thenReturn(false); + mKeyguardUpdateMonitor = + new TestableKeyguardUpdateMonitor(mSpiedContext); + + // Face auth should run when the following is true. + keyguardNotGoingAway(); + bouncerFullyVisibleAndNotGoingToSleep(); + strongAuthNotRequired(); + biometricsEnabledForCurrentUser(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + userNotCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test + public void testShouldListenForFace_whenStrongAuthDoesNotAllowScanning_returnsFalse() + throws RemoteException { + // Face auth should run when the following is true. + keyguardNotGoingAway(); + bouncerFullyVisibleAndNotGoingToSleep(); + currentUserIsPrimary(); + biometricsEnabledForCurrentUser(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + userNotCurrentlySwitching(); + + // This disables face auth + when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser())) + .thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT); + mTestableLooper.processAllMessages(); + + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test + public void testShouldListenForFace_whenBiometricsDisabledForUser_returnsFalse() + throws RemoteException { + // Face auth should run when the following is true. + keyguardNotGoingAway(); + bouncerFullyVisibleAndNotGoingToSleep(); + currentUserIsPrimary(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + biometricsEnabledForCurrentUser(); + userNotCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + + // This disables face auth + biometricsDisabledForCurrentUser(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test + public void testShouldListenForFace_whenUserCurrentlySwitching_returnsFalse() + throws RemoteException { + // Face auth should run when the following is true. + keyguardNotGoingAway(); + bouncerFullyVisibleAndNotGoingToSleep(); + currentUserIsPrimary(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + biometricsEnabledForCurrentUser(); + userNotCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + + userCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test + public void testShouldListenForFace_whenSecureCameraLaunched_returnsFalse() + throws RemoteException { + // Face auth should run when the following is true. + keyguardNotGoingAway(); + bouncerFullyVisibleAndNotGoingToSleep(); + currentUserIsPrimary(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + biometricsEnabledForCurrentUser(); + userNotCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + + secureCameraLaunched(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test + public void testShouldListenForFace_whenOccludingAppRequestsFaceAuth_returnsTrue() + throws RemoteException { + // Face auth should run when the following is true. + keyguardNotGoingAway(); + bouncerFullyVisibleAndNotGoingToSleep(); + currentUserIsPrimary(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + biometricsEnabledForCurrentUser(); + userNotCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + secureCameraLaunched(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + + occludingAppRequestsFaceAuth(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + } + + @Test + public void testShouldListenForFace_whenBouncerShowingAndDeviceIsAwake_returnsTrue() + throws RemoteException { + // Face auth should run when the following is true. + keyguardNotGoingAway(); + currentUserIsPrimary(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + biometricsEnabledForCurrentUser(); + userNotCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + + bouncerFullyVisibleAndNotGoingToSleep(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + } + + @Test + public void testShouldListenForFace_whenAuthInterruptIsActive_returnsTrue() + throws RemoteException { + // Face auth should run when the following is true. + keyguardNotGoingAway(); + currentUserIsPrimary(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + biometricsEnabledForCurrentUser(); + userNotCurrentlySwitching(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + + triggerAuthInterrupt(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + } + + private void triggerAuthInterrupt() { + mKeyguardUpdateMonitor.onAuthInterruptDetected(true); + } + + private void occludingAppRequestsFaceAuth() { + mKeyguardUpdateMonitor.requestFaceAuthOnOccludingApp(true); + } + + private void secureCameraLaunched() { + mKeyguardUpdateMonitor.onCameraLaunched(); + } + + private void userCurrentlySwitching() { + mKeyguardUpdateMonitor.setSwitchingUser(true); + } + + private void fingerprintErrorLockedOut() { + mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback + .onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT, "Fingerprint locked out"); + } + + private void triggerSuccessfulFaceAuth() { + mKeyguardUpdateMonitor.requestFaceAuth(true); + verify(mFaceManager).authenticate(any(), + any(), + mAuthenticationCallbackCaptor.capture(), + any(), + anyInt(), + anyBoolean()); + mAuthenticationCallbackCaptor.getValue() + .onAuthenticationSucceeded( + new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false)); + } + + private void currentUserIsPrimary() { + when(mUserManager.isPrimaryUser()).thenReturn(true); + } + + private void biometricsNotDisabledThroughDevicePolicyManager() { + when(mDevicePolicyManager.getKeyguardDisabledFeatures(null, + KeyguardUpdateMonitor.getCurrentUser())).thenReturn(0); + } + + private void biometricsEnabledForCurrentUser() throws RemoteException { + mBiometricEnabledOnKeyguardCallback.onChanged(true, KeyguardUpdateMonitor.getCurrentUser()); + } + + private void biometricsDisabledForCurrentUser() throws RemoteException { + mBiometricEnabledOnKeyguardCallback.onChanged( + false, + KeyguardUpdateMonitor.getCurrentUser() + ); + } + + private void strongAuthNotRequired() { + when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser())) + .thenReturn(0); + } + + private void currentUserDoesNotHaveTrust() { + mKeyguardUpdateMonitor.onTrustChanged( + false, + KeyguardUpdateMonitor.getCurrentUser(), + -1, + new ArrayList<>() + ); + } + + private void userNotCurrentlySwitching() { + mKeyguardUpdateMonitor.setSwitchingUser(false); + } + + private void keyguardNotGoingAway() { + mKeyguardUpdateMonitor.setKeyguardGoingAway(false); + } + + private void bouncerFullyVisibleAndNotGoingToSleep() { + mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true, true); + mKeyguardUpdateMonitor.dispatchFinishedGoingToSleep(/* value doesn't matter */1); + } + private void setKeyguardBouncerVisibility(boolean isVisible) { mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(isVisible, isVisible); mTestableLooper.processAllMessages(); |