1 /* 2 * Copyright (C) 2019 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.systemui.statusbar.policy; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.Mockito.mock; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.when; 26 27 import android.hardware.biometrics.BiometricSourceType; 28 import android.testing.TestableLooper; 29 30 import androidx.test.ext.junit.runners.AndroidJUnit4; 31 import androidx.test.filters.SmallTest; 32 33 import com.android.internal.widget.LockPatternUtils; 34 import com.android.keyguard.KeyguardUpdateMonitor; 35 import com.android.keyguard.KeyguardUpdateMonitorCallback; 36 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; 37 import com.android.keyguard.logging.KeyguardUpdateMonitorLogger; 38 import com.android.systemui.SysuiTestCase; 39 import com.android.systemui.dump.DumpManager; 40 import com.android.systemui.flags.FeatureFlags; 41 import com.android.systemui.keyguard.KeyguardUnlockAnimationController; 42 import com.android.systemui.user.domain.interactor.SelectedUserInteractor; 43 44 import dagger.Lazy; 45 46 import org.junit.Before; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.mockito.ArgumentCaptor; 50 import org.mockito.Captor; 51 import org.mockito.Mock; 52 import org.mockito.MockitoAnnotations; 53 54 import java.util.Random; 55 56 @SmallTest 57 @TestableLooper.RunWithLooper 58 @RunWith(AndroidJUnit4.class) 59 public class KeyguardStateControllerTest extends SysuiTestCase { 60 61 @Mock 62 private KeyguardUpdateMonitor mKeyguardUpdateMonitor; 63 @Mock 64 private LockPatternUtils mLockPatternUtils; 65 private KeyguardStateController mKeyguardStateController; 66 @Mock 67 private DumpManager mDumpManager; 68 @Mock 69 private Lazy<KeyguardUnlockAnimationController> mKeyguardUnlockAnimationControllerLazy; 70 @Mock 71 private Lazy<KeyguardInteractor> mKeyguardInteractorLazy; 72 @Mock 73 private SelectedUserInteractor mSelectedUserInteractor; 74 @Mock 75 private KeyguardUpdateMonitorLogger mLogger; 76 @Mock 77 private FeatureFlags mFeatureFlags; 78 79 @Captor 80 private ArgumentCaptor<KeyguardUpdateMonitorCallback> mUpdateCallbackCaptor; 81 82 @Before setup()83 public void setup() { 84 MockitoAnnotations.initMocks(this); 85 mKeyguardStateController = new KeyguardStateControllerImpl( 86 mContext, 87 mKeyguardUpdateMonitor, 88 mLockPatternUtils, 89 mKeyguardUnlockAnimationControllerLazy, 90 mLogger, 91 mDumpManager, 92 mKeyguardInteractorLazy, 93 mFeatureFlags, 94 mSelectedUserInteractor); 95 } 96 97 @Test testAddCallback_registersListener()98 public void testAddCallback_registersListener() { 99 verify(mKeyguardUpdateMonitor).registerCallback(any()); 100 } 101 102 @Test testFaceAuthEnrolleddChanged_calledWhenFaceEnrollmentStateChanges()103 public void testFaceAuthEnrolleddChanged_calledWhenFaceEnrollmentStateChanges() { 104 KeyguardStateController.Callback callback = mock(KeyguardStateController.Callback.class); 105 106 when(mKeyguardUpdateMonitor.isFaceEnabledAndEnrolled()).thenReturn(false); 107 verify(mKeyguardUpdateMonitor).registerCallback(mUpdateCallbackCaptor.capture()); 108 mKeyguardStateController.addCallback(callback); 109 assertThat(mKeyguardStateController.isFaceEnrolledAndEnabled()).isFalse(); 110 111 when(mKeyguardUpdateMonitor.isFaceEnabledAndEnrolled()).thenReturn(true); 112 mUpdateCallbackCaptor.getValue().onBiometricEnrollmentStateChanged( 113 BiometricSourceType.FACE); 114 115 assertThat(mKeyguardStateController.isFaceEnrolledAndEnabled()).isTrue(); 116 verify(callback).onFaceEnrolledChanged(); 117 } 118 119 @Test testIsShowing()120 public void testIsShowing() { 121 assertThat(mKeyguardStateController.isShowing()).isFalse(); 122 mKeyguardStateController.notifyKeyguardState(true /* showing */, false /* occluded */); 123 assertThat(mKeyguardStateController.isShowing()).isTrue(); 124 } 125 126 @Test testIsMethodSecure()127 public void testIsMethodSecure() { 128 assertThat(mKeyguardStateController.isMethodSecure()).isFalse(); 129 130 when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true); 131 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 132 assertThat(mKeyguardStateController.isMethodSecure()).isTrue(); 133 } 134 135 @Test testIsOccluded()136 public void testIsOccluded() { 137 assertThat(mKeyguardStateController.isOccluded()).isFalse(); 138 mKeyguardStateController.notifyKeyguardState(false /* showing */, true /* occluded */); 139 assertThat(mKeyguardStateController.isOccluded()).isTrue(); 140 } 141 142 @Test testCanSkipLockScreen()143 public void testCanSkipLockScreen() { 144 // Can skip because LockPatternUtils#isSecure is false 145 assertThat(mKeyguardStateController.canDismissLockScreen()).isTrue(); 146 147 // Cannot skip after there's a password/pin/pattern 148 when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true); 149 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 150 assertThat(mKeyguardStateController.canDismissLockScreen()).isFalse(); 151 152 // Unless user is authenticated 153 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(anyInt())).thenReturn(true); 154 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 155 assertThat(mKeyguardStateController.canDismissLockScreen()).isTrue(); 156 } 157 158 @Test testCanSkipLockScreen_updateCalledOnFacesCleared()159 public void testCanSkipLockScreen_updateCalledOnFacesCleared() { 160 verify(mKeyguardUpdateMonitor).registerCallback(mUpdateCallbackCaptor.capture()); 161 162 // Cannot skip after there's a password/pin/pattern 163 when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true); 164 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 165 assertThat(mKeyguardStateController.canDismissLockScreen()).isFalse(); 166 167 // Unless user is authenticated 168 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(anyInt())).thenReturn(true); 169 mUpdateCallbackCaptor.getValue().onFacesCleared(); 170 assertThat(mKeyguardStateController.canDismissLockScreen()).isTrue(); 171 } 172 173 @Test testCanSkipLockScreen_updateCalledOnFingerprintssCleared()174 public void testCanSkipLockScreen_updateCalledOnFingerprintssCleared() { 175 verify(mKeyguardUpdateMonitor).registerCallback(mUpdateCallbackCaptor.capture()); 176 177 // Cannot skip after there's a password/pin/pattern 178 when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true); 179 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 180 assertThat(mKeyguardStateController.canDismissLockScreen()).isFalse(); 181 182 // Unless user is authenticated 183 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(anyInt())).thenReturn(true); 184 mUpdateCallbackCaptor.getValue().onFingerprintsCleared(); 185 assertThat(mKeyguardStateController.canDismissLockScreen()).isTrue(); 186 } 187 188 @Test testIsUnlocked()189 public void testIsUnlocked() { 190 // Is unlocked whenever the keyguard is not showing 191 assertThat(mKeyguardStateController.isShowing()).isFalse(); 192 assertThat(mKeyguardStateController.isUnlocked()).isTrue(); 193 194 // Unlocked if showing, but insecure 195 mKeyguardStateController.notifyKeyguardState(true /* showing */, false /* occluded */); 196 assertThat(mKeyguardStateController.isUnlocked()).isTrue(); 197 198 // Locked if showing, and requires password 199 when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true); 200 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 201 assertThat(mKeyguardStateController.isUnlocked()).isFalse(); 202 203 // But unlocked after #getUserCanSkipBouncer allows it 204 when(mKeyguardUpdateMonitor.getUserCanSkipBouncer(anyInt())).thenReturn(true); 205 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 206 assertThat(mKeyguardStateController.isUnlocked()).isTrue(); 207 } 208 209 @Test testIsTrusted()210 public void testIsTrusted() { 211 assertThat(mKeyguardStateController.isTrusted()).isFalse(); 212 213 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 214 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 215 216 assertThat(mKeyguardStateController.isTrusted()).isTrue(); 217 } 218 219 @Test testCallbacksAreInvoked()220 public void testCallbacksAreInvoked() { 221 KeyguardStateController.Callback callback = mock(KeyguardStateController.Callback.class); 222 mKeyguardStateController.addCallback(callback); 223 224 when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); 225 ((KeyguardStateControllerImpl) mKeyguardStateController).update(false /* alwaysUpdate */); 226 227 verify(callback).onUnlockedChanged(); 228 } 229 230 @Test testKeyguardDismissAmountCallbackInvoked()231 public void testKeyguardDismissAmountCallbackInvoked() { 232 KeyguardStateController.Callback callback = mock(KeyguardStateController.Callback.class); 233 mKeyguardStateController.addCallback(callback); 234 235 mKeyguardStateController.notifyKeyguardDismissAmountChanged(100f, false); 236 237 verify(callback).onKeyguardDismissAmountChanged(); 238 } 239 240 @Test testOnEnabledTrustAgentsChangedCallback()241 public void testOnEnabledTrustAgentsChangedCallback() { 242 final Random random = new Random(); 243 244 verify(mKeyguardUpdateMonitor).registerCallback(mUpdateCallbackCaptor.capture()); 245 final KeyguardStateController.Callback stateCallback = 246 mock(KeyguardStateController.Callback.class); 247 mKeyguardStateController.addCallback(stateCallback); 248 249 when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true); 250 mUpdateCallbackCaptor.getValue().onEnabledTrustAgentsChanged(random.nextInt()); 251 verify(stateCallback).onUnlockedChanged(); 252 } 253 } 254