• 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 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.ArgumentMatchers.eq;
24 import static org.mockito.Mockito.mock;
25 import static org.mockito.Mockito.never;
26 import static org.mockito.Mockito.reset;
27 import static org.mockito.Mockito.verify;
28 import static org.mockito.Mockito.verifyNoMoreInteractions;
29 import static org.mockito.Mockito.when;
30 
31 import android.os.SystemClock;
32 import android.platform.test.annotations.DisableFlags;
33 import android.platform.test.annotations.EnableFlags;
34 import android.testing.TestableLooper.RunWithLooper;
35 import android.view.KeyEvent;
36 
37 import androidx.test.ext.junit.runners.AndroidJUnit4;
38 import androidx.test.filters.SmallTest;
39 
40 import com.android.internal.util.LatencyTracker;
41 import com.android.internal.widget.LockPatternUtils;
42 import com.android.keyguard.KeyguardAbsKeyInputView.KeyDownListener;
43 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
44 import com.android.systemui.Flags;
45 import com.android.systemui.SysuiTestCase;
46 import com.android.systemui.bouncer.ui.helper.BouncerHapticPlayer;
47 import com.android.systemui.classifier.FalsingCollector;
48 import com.android.systemui.classifier.FalsingCollectorFake;
49 import com.android.systemui.flags.FakeFeatureFlags;
50 import com.android.systemui.haptics.msdl.FakeMSDLPlayer;
51 import com.android.systemui.kosmos.KosmosJavaAdapter;
52 import com.android.systemui.res.R;
53 import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
54 
55 import com.google.android.msdl.data.model.MSDLToken;
56 
57 import org.junit.Before;
58 import org.junit.Test;
59 import org.junit.runner.RunWith;
60 import org.mockito.ArgumentCaptor;
61 import org.mockito.Mock;
62 import org.mockito.MockitoAnnotations;
63 
64 @SmallTest
65 @RunWith(AndroidJUnit4.class)
66 @RunWithLooper
67 public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase {
68 
69     @Mock
70     private KeyguardAbsKeyInputView mAbsKeyInputView;
71     @Mock
72     private PasswordTextView mPasswordEntry;
73     @Mock
74     private BouncerKeyguardMessageArea mKeyguardMessageArea;
75     @Mock
76     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
77     @Mock
78     private SecurityMode mSecurityMode;
79     @Mock
80     private LockPatternUtils mLockPatternUtils;
81     @Mock
82     private KeyguardSecurityCallback mKeyguardSecurityCallback;
83     @Mock
84     private KeyguardMessageAreaController.Factory mKeyguardMessageAreaControllerFactory;
85     @Mock
86     private KeyguardMessageAreaController mKeyguardMessageAreaController;
87     @Mock
88     private LatencyTracker mLatencyTracker;
89     private final FalsingCollector mFalsingCollector = new FalsingCollectorFake();
90     @Mock
91     private EmergencyButtonController mEmergencyButtonController;
92 
93     private FakeFeatureFlags mFeatureFlags;
94     @Mock
95     private SelectedUserInteractor mSelectedUserInteractor;
96     @Mock
97     private UserActivityNotifier mUserActivityNotifier;
98     private KeyguardAbsKeyInputViewController mKeyguardAbsKeyInputViewController;
99     private KosmosJavaAdapter mKosmosJavaAdapter = new KosmosJavaAdapter(this);
100     private final BouncerHapticPlayer mBouncerHapticPlayer =
101             mKosmosJavaAdapter.getBouncerHapticHelper();
102     private final FakeMSDLPlayer mMSDLPlayer = mKosmosJavaAdapter.getMsdlPlayer();
103 
104     @Before
setup()105     public void setup() {
106         MockitoAnnotations.initMocks(this);
107         when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class)))
108                 .thenReturn(mKeyguardMessageAreaController);
109         when(mAbsKeyInputView.getPasswordTextViewId()).thenReturn(1);
110         when(mAbsKeyInputView.findViewById(1)).thenReturn(mPasswordEntry);
111         when(mAbsKeyInputView.isAttachedToWindow()).thenReturn(true);
112         when(mAbsKeyInputView.requireViewById(R.id.bouncer_message_area))
113                 .thenReturn(mKeyguardMessageArea);
114         when(mAbsKeyInputView.getResources()).thenReturn(getContext().getResources());
115         mFeatureFlags = new FakeFeatureFlags();
116         mKeyguardAbsKeyInputViewController = createTestObject();
117         mKeyguardAbsKeyInputViewController.init();
118         reset(mKeyguardMessageAreaController);  // Clear out implicit call to init.
119     }
120 
createTestObject()121     private KeyguardAbsKeyInputViewController createTestObject() {
122         return new KeyguardAbsKeyInputViewController(mAbsKeyInputView,
123                 mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback,
124                 mKeyguardMessageAreaControllerFactory, mLatencyTracker, mFalsingCollector,
125                 mEmergencyButtonController, mFeatureFlags, mSelectedUserInteractor,
126                 mBouncerHapticPlayer, mUserActivityNotifier) {
127             @Override
128             void resetState() {
129             }
130 
131             @Override
132             public void onResume(int reason) {
133                 super.onResume(reason);
134             }
135 
136             @Override
137             protected int getInitialMessageResId() {
138                 return 0;
139             }
140         };
141     }
142 
143     @Test
144     @EnableFlags(Flags.FLAG_REVAMPED_BOUNCER_MESSAGES)
145     public void withFeatureFlagOn_oldMessage_isHidden() {
146         KeyguardAbsKeyInputViewController underTest = createTestObject();
147 
148         underTest.init();
149 
150         verify(mKeyguardMessageAreaController).disable();
151     }
152 
153     @Test
154     public void onKeyDown_clearsSecurityMessage() {
155         ArgumentCaptor<KeyDownListener> onKeyDownListenerArgumentCaptor =
156                 ArgumentCaptor.forClass(KeyDownListener.class);
157         verify(mAbsKeyInputView).setKeyDownListener(onKeyDownListenerArgumentCaptor.capture());
158         onKeyDownListenerArgumentCaptor.getValue().onKeyDown(
159                 KeyEvent.KEYCODE_0, mock(KeyEvent.class));
160         verify(mKeyguardSecurityCallback).userActivity();
161         verify(mKeyguardMessageAreaController).setMessage(eq(""));
162     }
163 
164     @Test
165     public void onKeyDown_noSecurityMessageInteraction() {
166         ArgumentCaptor<KeyDownListener> onKeyDownListenerArgumentCaptor =
167                 ArgumentCaptor.forClass(KeyDownListener.class);
168         verify(mAbsKeyInputView).setKeyDownListener(onKeyDownListenerArgumentCaptor.capture());
169         onKeyDownListenerArgumentCaptor.getValue().onKeyDown(
170                 KeyEvent.KEYCODE_UNKNOWN, mock(KeyEvent.class));
171         verifyNoMoreInteractions(mKeyguardSecurityCallback);
172         verifyNoMoreInteractions(mKeyguardMessageAreaController);
173     }
174 
175     @Test
176     public void onPromptReasonNone_doesNotSetMessage() {
177         mKeyguardAbsKeyInputViewController.showPromptReason(0);
178         verify(mKeyguardMessageAreaController, never()).setMessage(
179                 getContext().getResources().getString(R.string.kg_prompt_reason_restart_password),
180                 false);
181     }
182 
183     @Test
184     public void onPromptReason_setsMessage() {
185         when(mAbsKeyInputView.getPromptReasonStringRes(1)).thenReturn(
186                 R.string.kg_prompt_reason_restart_password);
187         mKeyguardAbsKeyInputViewController.showPromptReason(1);
188         verify(mKeyguardMessageAreaController).setMessage(
189                 getContext().getResources().getString(R.string.kg_prompt_reason_restart_password),
190                 false);
191     }
192 
193 
194     @Test
195     public void testReset() {
196         mKeyguardAbsKeyInputViewController.reset();
197         verify(mKeyguardMessageAreaController).setMessage("", false);
198     }
199 
200     @Test
201     public void testOnViewAttached() {
202         reset(mLockPatternUtils);
203         mKeyguardAbsKeyInputViewController.onViewAttached();
204         verify(mLockPatternUtils).getLockoutAttemptDeadline(anyInt());
205     }
206 
207     @Test
208     public void testLockedOut_verifyPasswordAndUnlock_doesNotEnableViewInput() {
209         mKeyguardAbsKeyInputViewController.handleAttemptLockout(SystemClock.elapsedRealtime());
210         verify(mAbsKeyInputView).setPasswordEntryInputEnabled(false);
211         verify(mAbsKeyInputView).setPasswordEntryEnabled(false);
212         verify(mAbsKeyInputView, never()).setPasswordEntryInputEnabled(true);
213         verify(mAbsKeyInputView, never()).setPasswordEntryEnabled(true);
214     }
215 
216     @Test
217     @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
218     public void onPasswordChecked_withMSDLFeedback_withMatch_playsUnlockToken() {
219         mKeyguardAbsKeyInputViewController.onPasswordChecked(0, true, 100, true);
220         assertThat(mMSDLPlayer.getLatestTokenPlayed()).isEqualTo(MSDLToken.UNLOCK);
221     }
222 
223     @Test
224     @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
225     public void onPasswordChecked_withoutMSDLFeedback_withMatch_doesNotPlayToken() {
226         mKeyguardAbsKeyInputViewController.onPasswordChecked(0, true, 100, true);
227         assertThat(mMSDLPlayer.getLatestTokenPlayed()).isNull();
228     }
229 
230     @Test
231     @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
232     public void onPasswordChecked_withMSDLFeedback_withoutMatch_playsFailureToken() {
233         mKeyguardAbsKeyInputViewController.onPasswordChecked(0, false, 100, true);
234         assertThat(mMSDLPlayer.getLatestTokenPlayed()).isEqualTo(MSDLToken.FAILURE);
235     }
236 
237     @Test
238     @DisableFlags(Flags.FLAG_MSDL_FEEDBACK)
239     public void onPasswordChecked_withoutMSDLFeedback_withoutMatch_doesNotPlayToken() {
240         mKeyguardAbsKeyInputViewController.onPasswordChecked(0, false, 100, true);
241         assertThat(mMSDLPlayer.getLatestTokenPlayed()).isNull();
242     }
243 }
244