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 static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
20 import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1;
21 import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR;
22 import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
23 import static com.android.systemui.flags.Flags.MIGRATE_LOCK_ICON;
24 
25 import static org.mockito.Mockito.any;
26 import static org.mockito.Mockito.anyInt;
27 import static org.mockito.Mockito.atLeast;
28 import static org.mockito.Mockito.reset;
29 import static org.mockito.Mockito.verify;
30 import static org.mockito.Mockito.when;
31 
32 import android.content.Context;
33 import android.content.res.Resources;
34 import android.graphics.Point;
35 import android.graphics.Rect;
36 import android.graphics.drawable.AnimatedStateListDrawable;
37 import android.util.Pair;
38 import android.view.View;
39 import android.view.WindowManager;
40 import android.view.accessibility.AccessibilityManager;
41 
42 import com.android.systemui.R;
43 import com.android.systemui.SysuiTestCase;
44 import com.android.systemui.biometrics.AuthController;
45 import com.android.systemui.biometrics.AuthRippleController;
46 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
47 import com.android.systemui.doze.util.BurnInHelperKt;
48 import com.android.systemui.dump.DumpManager;
49 import com.android.systemui.flags.FakeFeatureFlags;
50 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository;
51 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
52 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractorFactory;
53 import com.android.systemui.plugins.FalsingManager;
54 import com.android.systemui.plugins.statusbar.StatusBarStateController;
55 import com.android.systemui.statusbar.StatusBarState;
56 import com.android.systemui.statusbar.VibratorHelper;
57 import com.android.systemui.statusbar.policy.ConfigurationController;
58 import com.android.systemui.statusbar.policy.KeyguardStateController;
59 import com.android.systemui.util.concurrency.FakeExecutor;
60 import com.android.systemui.util.time.FakeSystemClock;
61 
62 import org.junit.After;
63 import org.junit.Before;
64 import org.mockito.Answers;
65 import org.mockito.ArgumentCaptor;
66 import org.mockito.Captor;
67 import org.mockito.Mock;
68 import org.mockito.MockitoAnnotations;
69 import org.mockito.MockitoSession;
70 import org.mockito.quality.Strictness;
71 
72 public class LockIconViewControllerBaseTest extends SysuiTestCase {
73     protected static final String UNLOCKED_LABEL = "unlocked";
74     protected static final String LOCKED_LABEL = "locked";
75     protected static final int PADDING = 10;
76 
77     protected MockitoSession mStaticMockSession;
78 
79     protected @Mock LockIconView mLockIconView;
80     protected @Mock AnimatedStateListDrawable mIconDrawable;
81     protected @Mock Context mContext;
82     protected @Mock Resources mResources;
83     protected @Mock(answer = Answers.RETURNS_DEEP_STUBS) WindowManager mWindowManager;
84     protected @Mock StatusBarStateController mStatusBarStateController;
85     protected @Mock KeyguardUpdateMonitor mKeyguardUpdateMonitor;
86     protected @Mock KeyguardViewController mKeyguardViewController;
87     protected @Mock KeyguardStateController mKeyguardStateController;
88     protected @Mock FalsingManager mFalsingManager;
89     protected @Mock AuthController mAuthController;
90     protected @Mock DumpManager mDumpManager;
91     protected @Mock AccessibilityManager mAccessibilityManager;
92     protected @Mock ConfigurationController mConfigurationController;
93     protected @Mock VibratorHelper mVibrator;
94     protected @Mock AuthRippleController mAuthRippleController;
95     protected @Mock KeyguardTransitionRepository mTransitionRepository;
96     protected FakeExecutor mDelayableExecutor = new FakeExecutor(new FakeSystemClock());
97     protected FakeFeatureFlags mFeatureFlags;
98     protected @Mock PrimaryBouncerInteractor mPrimaryBouncerInteractor;
99 
100     protected LockIconViewController mUnderTest;
101 
102     // Capture listeners so that they can be used to send events
103     @Captor protected ArgumentCaptor<View.OnAttachStateChangeListener> mAttachCaptor =
104             ArgumentCaptor.forClass(View.OnAttachStateChangeListener.class);
105 
106     @Captor protected ArgumentCaptor<KeyguardStateController.Callback> mKeyguardStateCaptor =
107             ArgumentCaptor.forClass(KeyguardStateController.Callback.class);
108     protected KeyguardStateController.Callback mKeyguardStateCallback;
109 
110     @Captor protected ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateCaptor =
111             ArgumentCaptor.forClass(StatusBarStateController.StateListener.class);
112     protected StatusBarStateController.StateListener mStatusBarStateListener;
113 
114     @Captor protected ArgumentCaptor<AuthController.Callback> mAuthControllerCallbackCaptor;
115     protected AuthController.Callback mAuthControllerCallback;
116 
117     @Captor protected ArgumentCaptor<KeyguardUpdateMonitorCallback>
118             mKeyguardUpdateMonitorCallbackCaptor =
119             ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback.class);
120     protected KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
121 
122     @Captor protected ArgumentCaptor<Point> mPointCaptor;
123 
124     @Before
setUp()125     public void setUp() throws Exception {
126         mStaticMockSession = mockitoSession()
127                 .mockStatic(BurnInHelperKt.class)
128                 .strictness(Strictness.LENIENT)
129                 .startMocking();
130         MockitoAnnotations.initMocks(this);
131 
132         setupLockIconViewMocks();
133         when(mContext.getResources()).thenReturn(mResources);
134         when(mContext.getSystemService(WindowManager.class)).thenReturn(mWindowManager);
135         Rect windowBounds = new Rect(0, 0, 800, 1200);
136         when(mWindowManager.getCurrentWindowMetrics().getBounds()).thenReturn(windowBounds);
137         when(mResources.getString(R.string.accessibility_unlock_button)).thenReturn(UNLOCKED_LABEL);
138         when(mResources.getString(R.string.accessibility_lock_icon)).thenReturn(LOCKED_LABEL);
139         when(mResources.getDrawable(anyInt(), any())).thenReturn(mIconDrawable);
140         when(mResources.getDimensionPixelSize(R.dimen.lock_icon_padding)).thenReturn(PADDING);
141         when(mAuthController.getScaleFactor()).thenReturn(1f);
142 
143         when(mKeyguardStateController.isShowing()).thenReturn(true);
144         when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
145         when(mStatusBarStateController.isDozing()).thenReturn(false);
146         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
147 
148         mFeatureFlags = new FakeFeatureFlags();
149         mFeatureFlags.set(FACE_AUTH_REFACTOR, false);
150         mFeatureFlags.set(MIGRATE_LOCK_ICON, false);
151         mFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false);
152         mUnderTest = new LockIconViewController(
153                 mLockIconView,
154                 mStatusBarStateController,
155                 mKeyguardUpdateMonitor,
156                 mKeyguardViewController,
157                 mKeyguardStateController,
158                 mFalsingManager,
159                 mAuthController,
160                 mDumpManager,
161                 mAccessibilityManager,
162                 mConfigurationController,
163                 mDelayableExecutor,
164                 mVibrator,
165                 mAuthRippleController,
166                 mResources,
167                 KeyguardTransitionInteractorFactory.create(
168                         TestScopeProvider.getTestScope().getBackgroundScope(),
169                                 mTransitionRepository).getKeyguardTransitionInteractor(),
170                 KeyguardInteractorFactory.create(mFeatureFlags).getKeyguardInteractor(),
171                 mFeatureFlags,
172                 mPrimaryBouncerInteractor
173         );
174     }
175 
176     @After
tearDown()177     public void tearDown() {
178         mStaticMockSession.finishMocking();
179     }
180 
setupUdfps()181     protected Pair<Float, Point> setupUdfps() {
182         when(mKeyguardUpdateMonitor.isUdfpsSupported()).thenReturn(true);
183         final Point udfpsLocation = new Point(50, 75);
184         final float radius = 33f;
185         when(mAuthController.getUdfpsLocation()).thenReturn(udfpsLocation);
186         when(mAuthController.getUdfpsRadius()).thenReturn(radius);
187 
188         return new Pair(radius, udfpsLocation);
189     }
190 
setupShowLockIcon()191     protected void setupShowLockIcon() {
192         when(mKeyguardStateController.isShowing()).thenReturn(true);
193         when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(false);
194         when(mStatusBarStateController.isDozing()).thenReturn(false);
195         when(mStatusBarStateController.getDozeAmount()).thenReturn(0f);
196         when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD);
197         when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
198     }
199 
captureAuthControllerCallback()200     protected void captureAuthControllerCallback() {
201         verify(mAuthController).addCallback(mAuthControllerCallbackCaptor.capture());
202         mAuthControllerCallback = mAuthControllerCallbackCaptor.getValue();
203     }
204 
captureKeyguardStateCallback()205     protected void captureKeyguardStateCallback() {
206         verify(mKeyguardStateController).addCallback(mKeyguardStateCaptor.capture());
207         mKeyguardStateCallback = mKeyguardStateCaptor.getValue();
208     }
209 
captureStatusBarStateListener()210     protected void captureStatusBarStateListener() {
211         verify(mStatusBarStateController).addCallback(mStatusBarStateCaptor.capture());
212         mStatusBarStateListener = mStatusBarStateCaptor.getValue();
213     }
214 
captureKeyguardUpdateMonitorCallback()215     protected void captureKeyguardUpdateMonitorCallback() {
216         verify(mKeyguardUpdateMonitor).registerCallback(
217                 mKeyguardUpdateMonitorCallbackCaptor.capture());
218         mKeyguardUpdateMonitorCallback = mKeyguardUpdateMonitorCallbackCaptor.getValue();
219     }
220 
setupLockIconViewMocks()221     protected void setupLockIconViewMocks() {
222         when(mLockIconView.getResources()).thenReturn(mResources);
223         when(mLockIconView.getContext()).thenReturn(mContext);
224     }
225 
resetLockIconView()226     protected void resetLockIconView() {
227         reset(mLockIconView);
228         setupLockIconViewMocks();
229     }
230 
init(boolean useMigrationFlag)231     protected void init(boolean useMigrationFlag) {
232         mFeatureFlags.set(DOZING_MIGRATION_1, useMigrationFlag);
233         mUnderTest.init();
234 
235         verify(mLockIconView, atLeast(1)).addOnAttachStateChangeListener(mAttachCaptor.capture());
236         mAttachCaptor.getValue().onViewAttachedToWindow(mLockIconView);
237     }
238 }
239