• 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.keyguard
18 
19 import android.testing.TestableLooper
20 import android.view.KeyEvent
21 import android.view.View
22 import android.view.ViewGroup
23 import android.view.inputmethod.InputMethodManager
24 import android.widget.EditText
25 import android.widget.ImageView
26 import androidx.test.ext.junit.runners.AndroidJUnit4
27 import androidx.test.filters.SmallTest
28 import com.android.internal.util.LatencyTracker
29 import com.android.internal.widget.LockPatternUtils
30 import com.android.internal.widget.LockscreenCredential
31 import com.android.keyguard.domain.interactor.KeyguardKeyboardInteractor
32 import com.android.systemui.Flags as AconfigFlags
33 import com.android.systemui.SysuiTestCase
34 import com.android.systemui.classifier.FalsingCollector
35 import com.android.systemui.flags.FakeFeatureFlags
36 import com.android.systemui.flags.Flags
37 import com.android.systemui.haptics.msdl.bouncerHapticPlayer
38 import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
39 import com.android.systemui.res.R
40 import com.android.systemui.statusbar.policy.DevicePostureController
41 import com.android.systemui.testKosmos
42 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
43 import com.android.systemui.util.concurrency.DelayableExecutor
44 import com.android.systemui.util.mockito.mock
45 import com.android.systemui.util.mockito.whenever
46 import junit.framework.Assert.assertFalse
47 import junit.framework.Assert.assertTrue
48 import org.junit.Before
49 import org.junit.Test
50 import org.junit.runner.RunWith
51 import org.mockito.ArgumentCaptor
52 import org.mockito.ArgumentMatchers.anyBoolean
53 import org.mockito.ArgumentMatchers.anyString
54 import org.mockito.Captor
55 import org.mockito.Mock
56 import org.mockito.Mockito
57 import org.mockito.Mockito.mock
58 import org.mockito.Mockito.never
59 import org.mockito.Mockito.verify
60 import org.mockito.Mockito.`when`
61 import org.mockito.MockitoAnnotations
62 
63 @SmallTest
64 @RunWith(AndroidJUnit4::class)
65 // collectFlow in KeyguardPinBasedInputViewController.onViewAttached calls JavaAdapter.CollectFlow,
66 // which calls View.onRepeatWhenAttached, which requires being run on main thread.
67 @TestableLooper.RunWithLooper(setAsMainLooper = true)
68 class KeyguardPasswordViewControllerTest : SysuiTestCase() {
69     @Mock private lateinit var keyguardPasswordView: KeyguardPasswordView
70     @Mock private lateinit var passwordEntry: EditText
71     private var passwordEntryLayoutParams = ViewGroup.LayoutParams(/* width= */ 0, /* height= */ 0)
72     @Mock lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
73     @Mock lateinit var securityMode: KeyguardSecurityModel.SecurityMode
74     @Mock lateinit var lockPatternUtils: LockPatternUtils
75     @Mock lateinit var keyguardSecurityCallback: KeyguardSecurityCallback
76     @Mock lateinit var messageAreaControllerFactory: KeyguardMessageAreaController.Factory
77     @Mock lateinit var latencyTracker: LatencyTracker
78     @Mock lateinit var inputMethodManager: InputMethodManager
79     @Mock lateinit var emergencyButtonController: EmergencyButtonController
80     @Mock lateinit var mainExecutor: DelayableExecutor
81     @Mock lateinit var falsingCollector: FalsingCollector
82     @Mock lateinit var keyguardViewController: KeyguardViewController
83     @Mock lateinit var mSelectedUserInteractor: SelectedUserInteractor
84     @Mock private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea
85     @Mock
86     private lateinit var mKeyguardMessageAreaController:
87         KeyguardMessageAreaController<BouncerKeyguardMessageArea>
88     @Mock private lateinit var postureController: DevicePostureController
89     @Mock private lateinit var mUserActivityNotifier: UserActivityNotifier
90     @Captor private lateinit var keyListenerArgumentCaptor: ArgumentCaptor<View.OnKeyListener>
91     private val kosmos = testKosmos()
92 
93     private lateinit var keyguardPasswordViewController: KeyguardPasswordViewController
94 
95     @Before
setupnull96     fun setup() {
97         MockitoAnnotations.initMocks(this)
98         Mockito.`when`(
99                 keyguardPasswordView.requireViewById<BouncerKeyguardMessageArea>(
100                     R.id.bouncer_message_area
101                 )
102             )
103             .thenReturn(mKeyguardMessageArea)
104         Mockito.`when`(messageAreaControllerFactory.create(mKeyguardMessageArea))
105             .thenReturn(mKeyguardMessageAreaController)
106         Mockito.`when`(keyguardPasswordView.passwordTextViewId).thenReturn(R.id.passwordEntry)
107         Mockito.`when`(keyguardPasswordView.findViewById<EditText>(R.id.passwordEntry))
108             .thenReturn(passwordEntry)
109         whenever(keyguardPasswordView.findViewById<ImageView>(R.id.switch_ime_button))
110             .thenReturn(mock(ImageView::class.java))
111         `when`(keyguardPasswordView.resources).thenReturn(context.resources)
112         // TODO(b/362362385): No need to mock keyguardPasswordView.context once this bug is fixed.
113         `when`(keyguardPasswordView.context).thenReturn(context)
114         whenever(passwordEntry.layoutParams).thenReturn(passwordEntryLayoutParams)
115         val keyguardKeyboardInteractor = KeyguardKeyboardInteractor(FakeKeyboardRepository())
116         val fakeFeatureFlags = FakeFeatureFlags()
117         fakeFeatureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false)
118         mSetFlagsRule.enableFlags(AconfigFlags.FLAG_REVAMPED_BOUNCER_MESSAGES)
119         keyguardPasswordViewController =
120             KeyguardPasswordViewController(
121                 keyguardPasswordView,
122                 keyguardUpdateMonitor,
123                 securityMode,
124                 lockPatternUtils,
125                 keyguardSecurityCallback,
126                 messageAreaControllerFactory,
127                 latencyTracker,
128                 inputMethodManager,
129                 emergencyButtonController,
130                 mainExecutor,
131                 mContext.resources,
132                 falsingCollector,
133                 keyguardViewController,
134                 postureController,
135                 fakeFeatureFlags,
136                 mSelectedUserInteractor,
137                 keyguardKeyboardInteractor,
138                 kosmos.bouncerHapticPlayer,
139                 mUserActivityNotifier,
140             )
141     }
142 
143     @Test
testFocusWhenBouncerIsShownnull144     fun testFocusWhenBouncerIsShown() {
145         Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(true)
146         Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true)
147         keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED)
148         keyguardPasswordView.post {
149             verify(keyguardPasswordView).requestFocus()
150             verify(keyguardPasswordView).showKeyboard()
151         }
152     }
153 
154     @Test
testDoNotFocusWhenBouncerIsHiddennull155     fun testDoNotFocusWhenBouncerIsHidden() {
156         Mockito.`when`(keyguardViewController.isBouncerShowing).thenReturn(false)
157         Mockito.`when`(keyguardPasswordView.isShown).thenReturn(true)
158         keyguardPasswordViewController.onResume(KeyguardSecurityView.VIEW_REVEALED)
159         verify(keyguardPasswordView, never()).requestFocus()
160     }
161 
162     @Test
testHideKeyboardWhenOnPausenull163     fun testHideKeyboardWhenOnPause() {
164         keyguardPasswordViewController.onPause()
165         keyguardPasswordView.post {
166             verify(keyguardPasswordView).clearFocus()
167             verify(keyguardPasswordView).hideKeyboard()
168         }
169     }
170 
171     @Test
testOnViewAttachednull172     fun testOnViewAttached() {
173         keyguardPasswordViewController.onViewAttached()
174         verify(mKeyguardMessageAreaController)
175             .setMessage(context.resources.getString(R.string.keyguard_enter_your_password), false)
176     }
177 
178     @Test
testOnViewAttached_withExistingMessagenull179     fun testOnViewAttached_withExistingMessage() {
180         `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.")
181         keyguardPasswordViewController.onViewAttached()
182         verify(mKeyguardMessageAreaController, never()).setMessage(anyString(), anyBoolean())
183     }
184 
185     @Test
testMessageIsSetWhenResetnull186     fun testMessageIsSetWhenReset() {
187         keyguardPasswordViewController.resetState()
188         verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_password)
189     }
190 
191     @Test
testSpaceKeyDoesNotSubmitPasswordnull192     fun testSpaceKeyDoesNotSubmitPassword() {
193         keyguardPasswordViewController.onViewAttached()
194         verify(passwordEntry).setOnKeyListener(keyListenerArgumentCaptor.capture())
195 
196         val eventHandled =
197             keyListenerArgumentCaptor.value.onKey(
198                 keyguardPasswordView,
199                 KeyEvent.KEYCODE_SPACE,
200                 KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_SPACE),
201             )
202 
203         assertFalse("Unlock attempted.", eventHandled)
204     }
205 
206     @Test
testEnterKeySubmitsPasswordnull207     fun testEnterKeySubmitsPassword() {
208         val password = mock<LockscreenCredential>()
209         `when`(keyguardPasswordView.enteredCredential).thenReturn(password)
210         `when`(password.size()).thenReturn(4)
211         `when`(password.duplicate()).thenReturn(password)
212         keyguardPasswordViewController.onViewAttached()
213         verify(passwordEntry).setOnKeyListener(keyListenerArgumentCaptor.capture())
214 
215         val eventHandled =
216             keyListenerArgumentCaptor.value.onKey(
217                 keyguardPasswordView,
218                 KeyEvent.KEYCODE_ENTER,
219                 KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER),
220             )
221 
222         assertTrue("Unlock not attempted.", eventHandled)
223     }
224 }
225