• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.View
21 import androidx.constraintlayout.widget.ConstraintLayout
22 import androidx.constraintlayout.widget.ConstraintSet
23 import androidx.test.ext.junit.runners.AndroidJUnit4
24 import androidx.test.filters.SmallTest
25 import com.android.internal.util.LatencyTracker
26 import com.android.internal.widget.LockPatternUtils
27 import com.android.systemui.Flags as AConfigFlags
28 import com.android.systemui.SysuiTestCase
29 import com.android.systemui.classifier.FalsingCollector
30 import com.android.systemui.classifier.FalsingCollectorFake
31 import com.android.systemui.flags.FakeFeatureFlags
32 import com.android.systemui.flags.Flags
33 import com.android.systemui.haptics.msdl.bouncerHapticPlayer
34 import com.android.systemui.res.R
35 import com.android.systemui.statusbar.policy.DevicePostureController
36 import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED
37 import com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_OPENED
38 import com.android.systemui.testKosmos
39 import com.android.systemui.user.domain.interactor.SelectedUserInteractor
40 import com.android.systemui.util.mockito.any
41 import com.android.systemui.util.mockito.whenever
42 import com.google.common.truth.Truth.assertThat
43 import org.junit.Before
44 import org.junit.Test
45 import org.junit.runner.RunWith
46 import org.mockito.ArgumentCaptor
47 import org.mockito.ArgumentMatchers.anyBoolean
48 import org.mockito.ArgumentMatchers.anyInt
49 import org.mockito.ArgumentMatchers.anyString
50 import org.mockito.Captor
51 import org.mockito.Mock
52 import org.mockito.Mockito.never
53 import org.mockito.Mockito.reset
54 import org.mockito.Mockito.verify
55 import org.mockito.Mockito.`when`
56 import org.mockito.MockitoAnnotations
57 
58 @SmallTest
59 @RunWith(AndroidJUnit4::class)
60 @TestableLooper.RunWithLooper
61 class KeyguardPatternViewControllerTest : SysuiTestCase() {
62     private lateinit var mKeyguardPatternView: KeyguardPatternView
63 
64     @Mock private lateinit var mKeyguardUpdateMonitor: KeyguardUpdateMonitor
65 
66     @Mock private lateinit var mSecurityMode: KeyguardSecurityModel.SecurityMode
67 
68     @Mock private lateinit var mLockPatternUtils: LockPatternUtils
69 
70     @Mock private lateinit var mKeyguardSecurityCallback: KeyguardSecurityCallback
71 
72     @Mock private lateinit var mLatencyTracker: LatencyTracker
73     private var mFalsingCollector: FalsingCollector = FalsingCollectorFake()
74 
75     @Mock private lateinit var mEmergencyButtonController: EmergencyButtonController
76 
77     @Mock
78     private lateinit var mKeyguardMessageAreaControllerFactory:
79         KeyguardMessageAreaController.Factory
80 
81     @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor
82 
83     @Mock
84     private lateinit var mKeyguardMessageAreaController:
85         KeyguardMessageAreaController<BouncerKeyguardMessageArea>
86 
87     @Mock private lateinit var mPostureController: DevicePostureController
88 
89     private lateinit var mKeyguardPatternViewController: KeyguardPatternViewController
90     private lateinit var fakeFeatureFlags: FakeFeatureFlags
91 
92     @Captor lateinit var postureCallbackCaptor: ArgumentCaptor<DevicePostureController.Callback>
93 
94     private val kosmos = testKosmos()
95     private val bouncerHapticHelper = kosmos.bouncerHapticPlayer
96 
97     @Before
setupnull98     fun setup() {
99         MockitoAnnotations.initMocks(this)
100         whenever(mKeyguardMessageAreaControllerFactory.create(any()))
101             .thenReturn(mKeyguardMessageAreaController)
102         fakeFeatureFlags = FakeFeatureFlags()
103         fakeFeatureFlags.set(Flags.LOCKSCREEN_ENABLE_LANDSCAPE, false)
104         mKeyguardPatternView =
105             View.inflate(mContext, R.layout.keyguard_pattern_view, null) as KeyguardPatternView
106         mKeyguardPatternView.setIsLockScreenLandscapeEnabled(false)
107         mKeyguardPatternViewController =
108             KeyguardPatternViewController(
109                 mKeyguardPatternView,
110                 mKeyguardUpdateMonitor,
111                 mSecurityMode,
112                 mLockPatternUtils,
113                 mKeyguardSecurityCallback,
114                 mLatencyTracker,
115                 mFalsingCollector,
116                 mEmergencyButtonController,
117                 mKeyguardMessageAreaControllerFactory,
118                 mPostureController,
119                 fakeFeatureFlags,
120                 mSelectedUserInteractor,
121                 bouncerHapticHelper,
122             )
123         mKeyguardPatternView.onAttachedToWindow()
124     }
125 
126     @Test
onViewAttached_deviceHalfFolded_propagatedToPatternViewnull127     fun onViewAttached_deviceHalfFolded_propagatedToPatternView() {
128         overrideResource(R.dimen.half_opened_bouncer_height_ratio, 0.5f)
129         whenever(mPostureController.devicePosture).thenReturn(DEVICE_POSTURE_HALF_OPENED)
130 
131         mKeyguardPatternViewController.onViewAttached()
132 
133         assertThat(getPatternTopGuideline()).isEqualTo(getHalfOpenedBouncerHeightRatio())
134     }
135 
136     @Test
onDevicePostureChanged_deviceOpened_propagatedToPatternViewnull137     fun onDevicePostureChanged_deviceOpened_propagatedToPatternView() {
138         overrideResource(R.dimen.half_opened_bouncer_height_ratio, 0.5f)
139         whenever(mPostureController.devicePosture).thenReturn(DEVICE_POSTURE_HALF_OPENED)
140 
141         mKeyguardPatternViewController.onViewAttached()
142 
143         // Verify view begins in posture state DEVICE_POSTURE_HALF_OPENED
144         assertThat(getPatternTopGuideline()).isEqualTo(getHalfOpenedBouncerHeightRatio())
145 
146         // Simulate posture change to state DEVICE_POSTURE_OPENED with callback
147         verify(mPostureController).addCallback(postureCallbackCaptor.capture())
148         val postureCallback: DevicePostureController.Callback = postureCallbackCaptor.value
149         postureCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
150 
151         // Simulate posture change to same state with callback
152         assertThat(getPatternTopGuideline()).isNotEqualTo(getHalfOpenedBouncerHeightRatio())
153 
154         postureCallback.onPostureChanged(DEVICE_POSTURE_OPENED)
155 
156         // Verify view is still in posture state DEVICE_POSTURE_OPENED
157         assertThat(getPatternTopGuideline()).isNotEqualTo(getHalfOpenedBouncerHeightRatio())
158     }
159 
getPatternTopGuidelinenull160     private fun getPatternTopGuideline(): Float {
161         val cs = ConstraintSet()
162         val container =
163             mKeyguardPatternView.requireViewById(R.id.pattern_container) as ConstraintLayout
164         cs.clone(container)
165         return cs.getConstraint(R.id.pattern_top_guideline).layout.guidePercent
166     }
167 
getHalfOpenedBouncerHeightRationull168     private fun getHalfOpenedBouncerHeightRatio(): Float {
169         return mContext.resources.getFloat(R.dimen.half_opened_bouncer_height_ratio)
170     }
171 
172     @Test
withFeatureFlagOn_oldMessage_isHiddennull173     fun withFeatureFlagOn_oldMessage_isHidden() {
174         mSetFlagsRule.enableFlags(AConfigFlags.FLAG_REVAMPED_BOUNCER_MESSAGES)
175 
176         mKeyguardPatternViewController.onViewAttached()
177 
178         verify<KeyguardMessageAreaController<*>>(mKeyguardMessageAreaController).disable()
179     }
180 
181     @Test
onPause_resetsTextnull182     fun onPause_resetsText() {
183         mKeyguardPatternViewController.init()
184         mKeyguardPatternViewController.onPause()
185         verify(mKeyguardMessageAreaController).setMessage(R.string.keyguard_enter_your_pattern)
186     }
187 
188     @Test
testOnViewAttachednull189     fun testOnViewAttached() {
190         reset(mKeyguardMessageAreaController)
191         reset(mLockPatternUtils)
192         mKeyguardPatternViewController.onViewAttached()
193         verify(mKeyguardMessageAreaController)
194             .setMessage(context.resources.getString(R.string.keyguard_enter_your_pattern), false)
195         verify(mLockPatternUtils).getLockoutAttemptDeadline(anyInt())
196     }
197 
198     @Test
testOnViewAttached_withExistingMessagenull199     fun testOnViewAttached_withExistingMessage() {
200         reset(mKeyguardMessageAreaController)
201         `when`(mKeyguardMessageAreaController.message).thenReturn("Unlock to continue.")
202         mKeyguardPatternViewController.onViewAttached()
203         verify(mKeyguardMessageAreaController, never()).setMessage(anyString(), anyBoolean())
204     }
205 }
206