1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.keyguard 18 19 import android.hardware.biometrics.BiometricSourceType 20 import android.testing.AndroidTestingRunner 21 import androidx.test.filters.SmallTest 22 import com.android.internal.logging.InstanceId 23 import com.android.internal.logging.UiEventLogger 24 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT 25 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE 26 import com.android.systemui.SysuiTestCase 27 import com.android.systemui.log.SessionTracker 28 import org.junit.Before 29 import org.junit.Test 30 import org.junit.runner.RunWith 31 import org.mockito.ArgumentCaptor 32 import org.mockito.ArgumentMatchers.anyInt 33 import org.mockito.Captor 34 import org.mockito.Mock 35 import org.mockito.Mockito.verify 36 import org.mockito.Mockito.verifyNoMoreInteractions 37 import org.mockito.Mockito.`when` as whenever 38 import org.mockito.MockitoAnnotations 39 40 @RunWith(AndroidTestingRunner::class) 41 @SmallTest 42 class KeyguardBiometricLockoutLoggerTest : SysuiTestCase() { 43 @Mock 44 lateinit var uiEventLogger: UiEventLogger 45 @Mock 46 lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor 47 @Mock 48 lateinit var strongAuthTracker: KeyguardUpdateMonitor.StrongAuthTracker 49 @Mock 50 lateinit var sessionTracker: SessionTracker 51 @Mock 52 lateinit var sessionId: InstanceId 53 54 @Captor 55 lateinit var updateMonitorCallbackCaptor: ArgumentCaptor<KeyguardUpdateMonitorCallback> 56 lateinit var updateMonitorCallback: KeyguardUpdateMonitorCallback 57 58 lateinit var keyguardBiometricLockoutLogger: KeyguardBiometricLockoutLogger 59 60 @Before setUpnull61 fun setUp() { 62 MockitoAnnotations.initMocks(this) 63 whenever(keyguardUpdateMonitor.strongAuthTracker).thenReturn(strongAuthTracker) 64 whenever(sessionTracker.getSessionId(anyInt())).thenReturn(sessionId) 65 keyguardBiometricLockoutLogger = KeyguardBiometricLockoutLogger( 66 uiEventLogger, 67 keyguardUpdateMonitor, 68 sessionTracker) 69 } 70 71 @Test test_logsOnStartnull72 fun test_logsOnStart() { 73 // GIVEN is encrypted / lockdown before start 74 whenever(keyguardUpdateMonitor.isEncryptedOrLockdown(anyInt())) 75 .thenReturn(true) 76 77 // WHEN start 78 keyguardBiometricLockoutLogger.start() 79 80 // THEN encrypted / lockdown state is logged 81 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 82 .PRIMARY_AUTH_REQUIRED_ENCRYPTED_OR_LOCKDOWN, sessionId) 83 } 84 85 @Test test_logTimeoutChangenull86 fun test_logTimeoutChange() { 87 keyguardBiometricLockoutLogger.start() 88 captureUpdateMonitorCallback() 89 90 // GIVEN primary auth required b/c timeout 91 whenever(strongAuthTracker.getStrongAuthForUser(anyInt())) 92 .thenReturn(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) 93 94 // WHEN primary auth requirement changes 95 updateMonitorCallback.onStrongAuthStateChanged(0) 96 97 // THEN primary auth required state is logged 98 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 99 .PRIMARY_AUTH_REQUIRED_TIMEOUT, sessionId) 100 } 101 102 @Test test_logUnattendedUpdatenull103 fun test_logUnattendedUpdate() { 104 keyguardBiometricLockoutLogger.start() 105 captureUpdateMonitorCallback() 106 107 // GIVEN primary auth required b/c unattended update 108 whenever(strongAuthTracker.getStrongAuthForUser(anyInt())) 109 .thenReturn(STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) 110 111 // WHEN primary auth requirement changes 112 updateMonitorCallback.onStrongAuthStateChanged(0) 113 114 // THEN primary auth required state is logged 115 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 116 .PRIMARY_AUTH_REQUIRED_UNATTENDED_UPDATE, sessionId) 117 } 118 119 @Test test_logMultipleChangesnull120 fun test_logMultipleChanges() { 121 keyguardBiometricLockoutLogger.start() 122 captureUpdateMonitorCallback() 123 124 // GIVEN primary auth required b/c timeout 125 whenever(strongAuthTracker.getStrongAuthForUser(anyInt())) 126 .thenReturn(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT 127 or STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) 128 129 // WHEN primary auth requirement changes 130 updateMonitorCallback.onStrongAuthStateChanged(0) 131 132 // THEN primary auth required state is logged with all the reasons 133 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 134 .PRIMARY_AUTH_REQUIRED_TIMEOUT, sessionId) 135 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 136 .PRIMARY_AUTH_REQUIRED_UNATTENDED_UPDATE, sessionId) 137 138 // WHEN onStrongAuthStateChanged is called again 139 updateMonitorCallback.onStrongAuthStateChanged(0) 140 141 // THEN no more events are sent since there haven't been any changes 142 verifyNoMoreInteractions(uiEventLogger) 143 } 144 145 @Test test_logFaceLockoutnull146 fun test_logFaceLockout() { 147 keyguardBiometricLockoutLogger.start() 148 captureUpdateMonitorCallback() 149 150 // GIVEN primary auth required b/c face lock 151 whenever(keyguardUpdateMonitor.isFaceLockedOut).thenReturn(true) 152 153 // WHEN lockout state changes 154 updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FACE) 155 156 // THEN primary auth required state is logged 157 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 158 .PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT, sessionId) 159 160 // WHEN face lockout is reset 161 whenever(keyguardUpdateMonitor.isFaceLockedOut).thenReturn(false) 162 updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FACE) 163 164 // THEN primary auth required state is logged 165 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 166 .PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT_RESET, sessionId) 167 } 168 169 @Test test_logFingerprintLockoutnull170 fun test_logFingerprintLockout() { 171 keyguardBiometricLockoutLogger.start() 172 captureUpdateMonitorCallback() 173 174 // GIVEN primary auth required b/c fingerprint lock 175 whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(true) 176 177 // WHEN lockout state changes 178 updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT) 179 180 // THEN primary auth required state is logged 181 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 182 .PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT, sessionId) 183 184 // WHEN fingerprint lockout is reset 185 whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false) 186 updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT) 187 188 // THEN primary auth required state is logged 189 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 190 .PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT_RESET, sessionId) 191 } 192 captureUpdateMonitorCallbacknull193 fun captureUpdateMonitorCallback() { 194 verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallbackCaptor.capture()) 195 updateMonitorCallback = updateMonitorCallbackCaptor.value 196 } 197 } 198