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 com.android.systemui.user.domain.interactor.SelectedUserInteractor 29 import org.junit.Before 30 import org.junit.Test 31 import org.junit.runner.RunWith 32 import org.mockito.ArgumentCaptor 33 import org.mockito.ArgumentMatchers.anyInt 34 import org.mockito.Captor 35 import org.mockito.Mock 36 import org.mockito.Mockito.verify 37 import org.mockito.Mockito.verifyNoMoreInteractions 38 import org.mockito.MockitoAnnotations 39 import org.mockito.Mockito.`when` as whenever 40 41 @RunWith(AndroidTestingRunner::class) 42 @SmallTest 43 class KeyguardBiometricLockoutLoggerTest : SysuiTestCase() { 44 @Mock 45 lateinit var uiEventLogger: UiEventLogger 46 @Mock 47 lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor 48 @Mock 49 lateinit var strongAuthTracker: KeyguardUpdateMonitor.StrongAuthTracker 50 @Mock 51 lateinit var sessionTracker: SessionTracker 52 @Mock 53 lateinit var sessionId: InstanceId 54 @Mock 55 lateinit var mSelectedUserInteractor: SelectedUserInteractor 56 57 @Captor 58 lateinit var updateMonitorCallbackCaptor: ArgumentCaptor<KeyguardUpdateMonitorCallback> 59 lateinit var updateMonitorCallback: KeyguardUpdateMonitorCallback 60 61 lateinit var keyguardBiometricLockoutLogger: KeyguardBiometricLockoutLogger 62 63 @Before setUpnull64 fun setUp() { 65 MockitoAnnotations.initMocks(this) 66 whenever(keyguardUpdateMonitor.strongAuthTracker).thenReturn(strongAuthTracker) 67 whenever(sessionTracker.getSessionId(anyInt())).thenReturn(sessionId) 68 keyguardBiometricLockoutLogger = KeyguardBiometricLockoutLogger( 69 uiEventLogger, 70 keyguardUpdateMonitor, 71 sessionTracker, 72 mSelectedUserInteractor) 73 } 74 75 @Test test_logsOnStartnull76 fun test_logsOnStart() { 77 // GIVEN is encrypted / lockdown before start 78 whenever(keyguardUpdateMonitor.isEncryptedOrLockdown(anyInt())) 79 .thenReturn(true) 80 81 // WHEN start 82 keyguardBiometricLockoutLogger.start() 83 84 // THEN encrypted / lockdown state is logged 85 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 86 .PRIMARY_AUTH_REQUIRED_ENCRYPTED_OR_LOCKDOWN, sessionId) 87 } 88 89 @Test test_logTimeoutChangenull90 fun test_logTimeoutChange() { 91 keyguardBiometricLockoutLogger.start() 92 captureUpdateMonitorCallback() 93 94 // GIVEN primary auth required b/c timeout 95 whenever(strongAuthTracker.getStrongAuthForUser(anyInt())) 96 .thenReturn(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT) 97 98 // WHEN primary auth requirement changes 99 updateMonitorCallback.onStrongAuthStateChanged(0) 100 101 // THEN primary auth required state is logged 102 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 103 .PRIMARY_AUTH_REQUIRED_TIMEOUT, sessionId) 104 } 105 106 @Test test_logUnattendedUpdatenull107 fun test_logUnattendedUpdate() { 108 keyguardBiometricLockoutLogger.start() 109 captureUpdateMonitorCallback() 110 111 // GIVEN primary auth required b/c unattended update 112 whenever(strongAuthTracker.getStrongAuthForUser(anyInt())) 113 .thenReturn(STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) 114 115 // WHEN primary auth requirement changes 116 updateMonitorCallback.onStrongAuthStateChanged(0) 117 118 // THEN primary auth required state is logged 119 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 120 .PRIMARY_AUTH_REQUIRED_UNATTENDED_UPDATE, sessionId) 121 } 122 123 @Test test_logMultipleChangesnull124 fun test_logMultipleChanges() { 125 keyguardBiometricLockoutLogger.start() 126 captureUpdateMonitorCallback() 127 128 // GIVEN primary auth required b/c timeout 129 whenever(strongAuthTracker.getStrongAuthForUser(anyInt())) 130 .thenReturn(STRONG_AUTH_REQUIRED_AFTER_TIMEOUT 131 or STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) 132 133 // WHEN primary auth requirement changes 134 updateMonitorCallback.onStrongAuthStateChanged(0) 135 136 // THEN primary auth required state is logged with all the reasons 137 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 138 .PRIMARY_AUTH_REQUIRED_TIMEOUT, sessionId) 139 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 140 .PRIMARY_AUTH_REQUIRED_UNATTENDED_UPDATE, sessionId) 141 142 // WHEN onStrongAuthStateChanged is called again 143 updateMonitorCallback.onStrongAuthStateChanged(0) 144 145 // THEN no more events are sent since there haven't been any changes 146 verifyNoMoreInteractions(uiEventLogger) 147 } 148 149 @Test test_logFaceLockoutnull150 fun test_logFaceLockout() { 151 keyguardBiometricLockoutLogger.start() 152 captureUpdateMonitorCallback() 153 154 // GIVEN primary auth required b/c face lock 155 whenever(keyguardUpdateMonitor.isFaceLockedOut).thenReturn(true) 156 157 // WHEN lockout state changes 158 updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FACE) 159 160 // THEN primary auth required state is logged 161 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 162 .PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT, sessionId) 163 164 // WHEN face lockout is reset 165 whenever(keyguardUpdateMonitor.isFaceLockedOut).thenReturn(false) 166 updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FACE) 167 168 // THEN primary auth required state is logged 169 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 170 .PRIMARY_AUTH_REQUIRED_FACE_LOCKED_OUT_RESET, sessionId) 171 } 172 173 @Test test_logFingerprintLockoutnull174 fun test_logFingerprintLockout() { 175 keyguardBiometricLockoutLogger.start() 176 captureUpdateMonitorCallback() 177 178 // GIVEN primary auth required b/c fingerprint lock 179 whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(true) 180 181 // WHEN lockout state changes 182 updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT) 183 184 // THEN primary auth required state is logged 185 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 186 .PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT, sessionId) 187 188 // WHEN fingerprint lockout is reset 189 whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false) 190 updateMonitorCallback.onLockedOutStateChanged(BiometricSourceType.FINGERPRINT) 191 192 // THEN primary auth required state is logged 193 verify(uiEventLogger).log(KeyguardBiometricLockoutLogger.PrimaryAuthRequiredEvent 194 .PRIMARY_AUTH_REQUIRED_FINGERPRINT_LOCKED_OUT_RESET, sessionId) 195 } 196 captureUpdateMonitorCallbacknull197 fun captureUpdateMonitorCallback() { 198 verify(keyguardUpdateMonitor).registerCallback(updateMonitorCallbackCaptor.capture()) 199 updateMonitorCallback = updateMonitorCallbackCaptor.value 200 } 201 } 202