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