• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.biometrics
18 
19 import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
20 import android.hardware.biometrics.BiometricManager
21 import android.hardware.biometrics.PromptInfo
22 import android.hardware.face.FaceSensorPropertiesInternal
23 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
24 import android.os.Handler
25 import android.os.IBinder
26 import android.os.UserManager
27 import android.testing.AndroidTestingRunner
28 import android.testing.TestableLooper
29 import android.testing.ViewUtils
30 import androidx.test.filters.SmallTest
31 import com.android.internal.jank.InteractionJankMonitor
32 import com.android.internal.widget.LockPatternUtils
33 import com.android.internal.widget.LockPatternView
34 import com.android.internal.widget.VerifyCredentialResponse
35 import com.android.systemui.SysuiTestCase
36 import com.android.systemui.biometrics.AuthContainerView.BiometricCallback
37 import com.android.systemui.biometrics.AuthCredentialView.ErrorTimer
38 import com.android.systemui.keyguard.WakefulnessLifecycle
39 import com.android.systemui.util.concurrency.FakeExecutor
40 import com.android.systemui.util.time.FakeSystemClock
41 import com.google.common.truth.Truth.assertThat
42 import org.junit.After
43 import org.junit.Rule
44 import org.junit.Test
45 import org.junit.runner.RunWith
46 import org.mockito.Mock
47 import org.mockito.Mockito.anyInt
48 import org.mockito.Mockito.spy
49 import org.mockito.Mockito.verify
50 import org.mockito.Mockito.`when`
51 import org.mockito.junit.MockitoJUnit
52 
53 @RunWith(AndroidTestingRunner::class)
54 @TestableLooper.RunWithLooper(setAsMainLooper = true)
55 @SmallTest
56 class AuthCredentialViewTest : SysuiTestCase() {
57     @JvmField @Rule var mockitoRule = MockitoJUnit.rule()
58 
59     @Mock lateinit var callback: AuthDialogCallback
60     @Mock lateinit var lockPatternUtils: LockPatternUtils
61     @Mock lateinit var userManager: UserManager
62     @Mock lateinit var wakefulnessLifecycle: WakefulnessLifecycle
63     @Mock lateinit var windowToken: IBinder
64     @Mock lateinit var interactionJankMonitor: InteractionJankMonitor
65 
66     private var authContainer: TestAuthContainerView? = null
67     private var authCredentialView: AuthCredentialPatternView? = null
68     private var lockPatternView: LockPatternView? = null
69     private var biometricCallback: BiometricCallback? = null
70     private var errorTimer: ErrorTimer? = null
71 
72     @After
tearDownnull73     fun tearDown() {
74         if (authContainer?.isAttachedToWindow == true) {
75             ViewUtils.detachView(authContainer)
76         }
77     }
78 
79     @Test
testAuthCredentialPatternView_onErrorTimeoutFinish_setPatternEnablednull80     fun testAuthCredentialPatternView_onErrorTimeoutFinish_setPatternEnabled() {
81         `when`(lockPatternUtils.getCredentialTypeForUser(anyInt()))
82             .thenReturn(LockPatternUtils.CREDENTIAL_TYPE_PATTERN)
83         `when`(lockPatternUtils.getKeyguardStoredPasswordQuality(anyInt()))
84             .thenReturn(PASSWORD_QUALITY_SOMETHING)
85         val errorResponse: VerifyCredentialResponse = VerifyCredentialResponse.fromError()
86 
87         assertThat(initializeFingerprintContainer()).isNotNull()
88         authContainer?.animateToCredentialUI()
89         waitForIdleSync()
90 
91         authCredentialView = spy(authContainer?.mCredentialView as AuthCredentialPatternView)
92         authCredentialView?.onCredentialVerified(errorResponse, 5000)
93         errorTimer = authCredentialView?.mErrorTimer
94         errorTimer?.onFinish()
95         waitForIdleSync()
96 
97         verify(authCredentialView)?.onErrorTimeoutFinish()
98 
99         lockPatternView = authCredentialView?.mLockPatternView
100         assertThat(lockPatternView?.isEnabled).isTrue()
101     }
102 
initializeFingerprintContainernull103     private fun initializeFingerprintContainer(
104         authenticators: Int = BiometricManager.Authenticators.BIOMETRIC_WEAK,
105         addToView: Boolean = true
106     ) =
107         initializeContainer(
108             TestAuthContainerView(
109                 authenticators = authenticators,
110                 fingerprintProps = fingerprintSensorPropertiesInternal()
111             ),
112             addToView
113         )
114 
115     private fun initializeContainer(
116         view: TestAuthContainerView,
117         addToView: Boolean
118     ): TestAuthContainerView {
119         authContainer = view
120         if (addToView) {
121             authContainer!!.addToView()
122             biometricCallback = authContainer?.mBiometricCallback
123         }
124         return authContainer!!
125     }
126 
127     private inner class TestAuthContainerView(
128         authenticators: Int = BiometricManager.Authenticators.BIOMETRIC_WEAK,
129         fingerprintProps: List<FingerprintSensorPropertiesInternal> = listOf(),
130         faceProps: List<FaceSensorPropertiesInternal> = listOf()
131     ) :
132         AuthContainerView(
<lambda>null133             Config().apply {
134                 mContext = context
135                 mCallback = callback
136                 mSensorIds =
137                     (fingerprintProps.map { it.sensorId } + faceProps.map { it.sensorId })
138                         .toIntArray()
139                 mSkipAnimation = true
140                 mPromptInfo = PromptInfo().apply { this.authenticators = authenticators }
141             },
142             fingerprintProps,
143             faceProps,
144             wakefulnessLifecycle,
145             userManager,
146             lockPatternUtils,
147             interactionJankMonitor,
148             Handler(TestableLooper.get(this).looper),
149             FakeExecutor(FakeSystemClock())
150         ) {
postOnAnimationnull151         override fun postOnAnimation(runnable: Runnable) {
152             runnable.run()
153         }
154     }
155 
waitForIdleSyncnull156     override fun waitForIdleSync() = TestableLooper.get(this).processAllMessages()
157 
158     private fun AuthContainerView.addToView() {
159         ViewUtils.attachView(this)
160         waitForIdleSync()
161         assertThat(isAttachedToWindow).isTrue()
162     }
163 }
164