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.systemui.bouncer.domain.interactor
18 
19 import androidx.test.ext.junit.runners.AndroidJUnit4
20 import androidx.test.filters.SmallTest
21 import com.android.keyguard.KeyguardUpdateMonitor
22 import com.android.systemui.RoboPilotTest
23 import com.android.systemui.SysuiTestCase
24 import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
25 import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepositoryImpl
26 import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
27 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
28 import com.android.systemui.log.table.TableLogBuffer
29 import com.android.systemui.plugins.statusbar.StatusBarStateController
30 import com.android.systemui.statusbar.policy.KeyguardStateController
31 import com.android.systemui.util.mockito.whenever
32 import com.android.systemui.util.time.FakeSystemClock
33 import com.android.systemui.util.time.SystemClock
34 import kotlinx.coroutines.ExperimentalCoroutinesApi
35 import kotlinx.coroutines.test.TestCoroutineScope
36 import org.junit.Assert.assertFalse
37 import org.junit.Assert.assertTrue
38 import org.junit.Before
39 import org.junit.Test
40 import org.junit.runner.RunWith
41 import org.mockito.Mock
42 import org.mockito.MockitoAnnotations
43 
44 @OptIn(ExperimentalCoroutinesApi::class)
45 @SmallTest
46 @RoboPilotTest
47 @RunWith(AndroidJUnit4::class)
48 class AlternateBouncerInteractorTest : SysuiTestCase() {
49     private lateinit var underTest: AlternateBouncerInteractor
50     private lateinit var bouncerRepository: KeyguardBouncerRepository
51     private lateinit var biometricSettingsRepository: FakeBiometricSettingsRepository
52     private lateinit var deviceEntryFingerprintAuthRepository:
53         FakeDeviceEntryFingerprintAuthRepository
54     @Mock private lateinit var statusBarStateController: StatusBarStateController
55     @Mock private lateinit var keyguardStateController: KeyguardStateController
56     @Mock private lateinit var systemClock: SystemClock
57     @Mock private lateinit var bouncerLogger: TableLogBuffer
58     @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
59 
60     @Before
61     fun setup() {
62         MockitoAnnotations.initMocks(this)
63         bouncerRepository =
64             KeyguardBouncerRepositoryImpl(
65                 FakeSystemClock(),
66                 TestCoroutineScope(),
67                 bouncerLogger,
68             )
69         biometricSettingsRepository = FakeBiometricSettingsRepository()
70         deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
71         underTest =
72             AlternateBouncerInteractor(
73                 statusBarStateController,
74                 keyguardStateController,
75                 bouncerRepository,
76                 biometricSettingsRepository,
77                 systemClock,
78                 keyguardUpdateMonitor,
79             )
80     }
81 
82     @Test
83     fun canShowAlternateBouncerForFingerprint_givenCanShow() {
84         givenCanShowAlternateBouncer()
85         assertTrue(underTest.canShowAlternateBouncerForFingerprint())
86     }
87 
88     @Test
89     fun canShowAlternateBouncerForFingerprint_alternateBouncerUIUnavailable() {
90         givenCanShowAlternateBouncer()
91         bouncerRepository.setAlternateBouncerUIAvailable(false)
92 
93         assertFalse(underTest.canShowAlternateBouncerForFingerprint())
94     }
95 
96     @Test
97     fun canShowAlternateBouncerForFingerprint_ifFingerprintIsNotUsuallyAllowed() {
98         givenCanShowAlternateBouncer()
99         biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
100 
101         assertFalse(underTest.canShowAlternateBouncerForFingerprint())
102     }
103 
104     @Test
105     fun canShowAlternateBouncerForFingerprint_strongBiometricNotAllowed() {
106         givenCanShowAlternateBouncer()
107         biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(false)
108 
109         assertFalse(underTest.canShowAlternateBouncerForFingerprint())
110     }
111 
112     @Test
113     fun canShowAlternateBouncerForFingerprint_fingerprintLockedOut() {
114         givenCanShowAlternateBouncer()
115         whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(true)
116 
117         assertFalse(underTest.canShowAlternateBouncerForFingerprint())
118     }
119 
120     @Test
121     fun show_whenCanShow() {
122         givenCanShowAlternateBouncer()
123 
124         assertTrue(underTest.show())
125         assertTrue(bouncerRepository.alternateBouncerVisible.value)
126     }
127 
128     @Test
129     fun canShowAlternateBouncerForFingerprint_butCanDismissLockScreen() {
130         givenCanShowAlternateBouncer()
131         whenever(keyguardStateController.isUnlocked).thenReturn(true)
132 
133         assertFalse(underTest.canShowAlternateBouncerForFingerprint())
134     }
135 
136     @Test
137     fun show_whenCannotShow() {
138         givenCannotShowAlternateBouncer()
139 
140         assertFalse(underTest.show())
141         assertFalse(bouncerRepository.alternateBouncerVisible.value)
142     }
143 
144     @Test
145     fun hide_wasPreviouslyShowing() {
146         bouncerRepository.setAlternateVisible(true)
147 
148         assertTrue(underTest.hide())
149         assertFalse(bouncerRepository.alternateBouncerVisible.value)
150     }
151 
152     @Test
153     fun hide_wasNotPreviouslyShowing() {
154         bouncerRepository.setAlternateVisible(false)
155 
156         assertFalse(underTest.hide())
157         assertFalse(bouncerRepository.alternateBouncerVisible.value)
158     }
159 
160     @Test
161     fun alternateBouncerUiAvailable_fromMultipleSources() {
162         assertFalse(bouncerRepository.alternateBouncerUIAvailable.value)
163 
164         // GIVEN there are two different sources indicating the alternate bouncer is available
165         underTest.setAlternateBouncerUIAvailable(true, "source1")
166         underTest.setAlternateBouncerUIAvailable(true, "source2")
167         assertTrue(bouncerRepository.alternateBouncerUIAvailable.value)
168 
169         // WHEN one of the sources no longer says the UI is available
170         underTest.setAlternateBouncerUIAvailable(false, "source1")
171 
172         // THEN alternate bouncer UI is still available (from the other source)
173         assertTrue(bouncerRepository.alternateBouncerUIAvailable.value)
174 
175         // WHEN all sources say the UI is not available
176         underTest.setAlternateBouncerUIAvailable(false, "source2")
177 
178         // THEN alternate boucer UI is not available
179         assertFalse(bouncerRepository.alternateBouncerUIAvailable.value)
180     }
181 
182     private fun givenCanShowAlternateBouncer() {
183         bouncerRepository.setAlternateBouncerUIAvailable(true)
184         biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(true)
185         biometricSettingsRepository.setIsFingerprintAuthCurrentlyAllowed(true)
186         whenever(keyguardUpdateMonitor.isFingerprintLockedOut).thenReturn(false)
187         whenever(keyguardStateController.isUnlocked).thenReturn(false)
188     }
189 
190     private fun givenCannotShowAlternateBouncer() {
191         biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
192     }
193 }
194