• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.statusbar;
18 
19 import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
20 
21 import static com.android.systemui.flags.Flags.KEYGUARD_TALKBACK_FIX;
22 import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED;
23 import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_TRANSIENT;
24 import static com.android.systemui.keyguard.ScreenLifecycle.SCREEN_ON;
25 
26 import static com.google.common.truth.Truth.assertThat;
27 
28 import static org.mockito.ArgumentMatchers.any;
29 import static org.mockito.ArgumentMatchers.anyBoolean;
30 import static org.mockito.ArgumentMatchers.anyInt;
31 import static org.mockito.ArgumentMatchers.anyString;
32 import static org.mockito.ArgumentMatchers.eq;
33 import static org.mockito.Mockito.clearInvocations;
34 import static org.mockito.Mockito.mock;
35 import static org.mockito.Mockito.never;
36 import static org.mockito.Mockito.reset;
37 import static org.mockito.Mockito.verify;
38 import static org.mockito.Mockito.when;
39 
40 import static java.util.Collections.emptySet;
41 
42 import android.app.AlarmManager;
43 import android.app.Instrumentation;
44 import android.app.admin.DevicePolicyManager;
45 import android.app.admin.DevicePolicyResourcesManager;
46 import android.app.trust.TrustManager;
47 import android.content.BroadcastReceiver;
48 import android.content.ComponentName;
49 import android.content.Context;
50 import android.hardware.fingerprint.FingerprintManager;
51 import android.os.Looper;
52 import android.os.UserManager;
53 import android.provider.DeviceConfig;
54 import android.testing.TestableLooper;
55 import android.view.ViewGroup;
56 import android.view.accessibility.AccessibilityManager;
57 
58 import androidx.test.InstrumentationRegistry;
59 
60 import com.android.internal.app.IBatteryStats;
61 import com.android.internal.widget.LockPatternUtils;
62 import com.android.keyguard.KeyguardUpdateMonitor;
63 import com.android.keyguard.KeyguardUpdateMonitorCallback;
64 import com.android.keyguard.logging.KeyguardLogger;
65 import com.android.systemui.SysuiTestCase;
66 import com.android.systemui.biometrics.AuthController;
67 import com.android.systemui.biometrics.FaceHelpMessageDeferral;
68 import com.android.systemui.biometrics.FaceHelpMessageDeferralFactory;
69 import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor;
70 import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
71 import com.android.systemui.broadcast.BroadcastDispatcher;
72 import com.android.systemui.deviceentry.domain.interactor.BiometricMessageInteractor;
73 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor;
74 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor;
75 import com.android.systemui.dock.DockManager;
76 import com.android.systemui.flags.FakeFeatureFlags;
77 import com.android.systemui.keyguard.KeyguardIndication;
78 import com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController;
79 import com.android.systemui.keyguard.ScreenLifecycle;
80 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractorFactory;
81 import com.android.systemui.keyguard.util.IndicationHelper;
82 import com.android.systemui.plugins.FalsingManager;
83 import com.android.systemui.plugins.statusbar.StatusBarStateController;
84 import com.android.systemui.res.R;
85 import com.android.systemui.settings.UserTracker;
86 import com.android.systemui.statusbar.phone.KeyguardBypassController;
87 import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
88 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
89 import com.android.systemui.statusbar.policy.KeyguardStateController;
90 import com.android.systemui.util.concurrency.FakeExecutor;
91 import com.android.systemui.util.time.FakeSystemClock;
92 import com.android.systemui.util.wakelock.WakeLockFake;
93 
94 import kotlinx.coroutines.flow.StateFlow;
95 
96 import org.junit.After;
97 import org.junit.Before;
98 import org.mockito.ArgumentCaptor;
99 import org.mockito.Captor;
100 import org.mockito.Mock;
101 import org.mockito.MockitoAnnotations;
102 
103 public class KeyguardIndicationControllerBaseTest extends SysuiTestCase {
104 
105     protected static final String ORGANIZATION_NAME = "organization";
106 
107     protected static final ComponentName DEVICE_OWNER_COMPONENT = new ComponentName(
108             "com.android.foo",
109             "bar");
110 
111     protected static final int TEST_STRING_RES = R.string.keyguard_indication_trust_unlocked;
112 
113     protected String mDisclosureWithOrganization;
114     protected String mDisclosureGeneric;
115     protected String mFinancedDisclosureWithOrganization;
116 
117     @Mock
118     protected DevicePolicyManager mDevicePolicyManager;
119     @Mock
120     protected DevicePolicyResourcesManager mDevicePolicyResourcesManager;
121     @Mock
122     protected ViewGroup mIndicationArea;
123     @Mock
124     protected KeyguardStateController mKeyguardStateController;
125     @Mock
126     protected KeyguardIndicationTextView mIndicationAreaBottom;
127     @Mock
128     protected BroadcastDispatcher mBroadcastDispatcher;
129     @Mock
130     protected StatusBarStateController mStatusBarStateController;
131     @Mock
132     protected KeyguardUpdateMonitor mKeyguardUpdateMonitor;
133     @Mock
134     protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
135     @Mock
136     protected UserManager mUserManager;
137     @Mock
138     protected IBatteryStats mIBatteryStats;
139     @Mock
140     protected DockManager mDockManager;
141     @Mock
142     protected KeyguardIndicationRotateTextViewController mRotateTextViewController;
143     @Mock
144     protected FalsingManager mFalsingManager;
145     @Mock
146     protected LockPatternUtils mLockPatternUtils;
147     @Mock
148     protected KeyguardBypassController mKeyguardBypassController;
149     @Mock
150     protected AccessibilityManager mAccessibilityManager;
151     @Mock
152     protected FaceHelpMessageDeferralFactory mFaceHelpMessageDeferralFactory;
153     @Mock
154     protected FaceHelpMessageDeferral mFaceHelpMessageDeferral;
155     @Mock
156     protected AlternateBouncerInteractor mAlternateBouncerInteractor;
157     @Mock
158     protected BiometricMessageInteractor mBiometricMessageInteractor;
159     @Mock
160     protected DeviceEntryFaceAuthInteractor mDeviceEntryFaceAuthInteractor;
161     @Mock
162     protected DeviceEntryFingerprintAuthInteractor mDeviceEntryFingerprintAuthInteractor;
163     @Mock
164     protected ScreenLifecycle mScreenLifecycle;
165     @Mock
166     protected AuthController mAuthController;
167     @Mock
168     protected AlarmManager mAlarmManager;
169     @Mock
170     protected UserTracker mUserTracker;
171     @Captor
172     protected ArgumentCaptor<DockManager.AlignmentStateListener> mAlignmentListener;
173     @Captor
174     protected ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
175     @Captor
176     protected ArgumentCaptor<BroadcastReceiver> mBroadcastReceiverCaptor;
177     @Captor
178     protected ArgumentCaptor<KeyguardIndication> mKeyguardIndicationCaptor;
179     @Captor
180     protected ArgumentCaptor<KeyguardUpdateMonitorCallback> mKeyguardUpdateMonitorCallbackCaptor;
181     @Captor
182     protected ArgumentCaptor<KeyguardStateController.Callback>
183             mKeyguardStateControllerCallbackCaptor;
184     @Captor
185     protected ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor;
186     protected KeyguardStateController.Callback mKeyguardStateControllerCallback;
187     protected KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback;
188     protected StatusBarStateController.StateListener mStatusBarStateListener;
189     protected ScreenLifecycle.Observer mScreenObserver;
190     protected BroadcastReceiver mBroadcastReceiver;
191     protected IndicationHelper mIndicationHelper;
192     protected FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
193     protected TestableLooper mTestableLooper;
194     protected final int mCurrentUserId = 1;
195 
196     protected KeyguardIndicationTextView mTextView; // AOD text
197 
198     protected KeyguardIndicationController mController;
199     protected WakeLockFake.Builder mWakeLockBuilder;
200     protected WakeLockFake mWakeLock;
201     protected Instrumentation mInstrumentation;
202     protected FakeFeatureFlags mFlags;
203 
204     @Before
setUp()205     public void setUp() throws Exception {
206         MockitoAnnotations.initMocks(this);
207         mInstrumentation = InstrumentationRegistry.getInstrumentation();
208         mTestableLooper = TestableLooper.get(this);
209         mTextView = new KeyguardIndicationTextView(mContext);
210         mTextView.setAnimationsEnabled(false);
211 
212         // TODO(b/259908270): remove
213         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
214                 DevicePolicyManager.ADD_ISFINANCED_DEVICE_FLAG, "true",
215                 /* makeDefault= */ false);
216         mContext.addMockSystemService(Context.DEVICE_POLICY_SERVICE, mDevicePolicyManager);
217         mContext.addMockSystemService(UserManager.class, mUserManager);
218         mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class));
219         mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager.class));
220         mDisclosureWithOrganization = mContext.getString(R.string.do_disclosure_with_name,
221                 ORGANIZATION_NAME);
222         mDisclosureGeneric = mContext.getString(R.string.do_disclosure_generic);
223         mFinancedDisclosureWithOrganization = mContext.getString(
224                 R.string.do_financed_disclosure_with_name, ORGANIZATION_NAME);
225 
226         when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
227         when(mScreenLifecycle.getScreenState()).thenReturn(SCREEN_ON);
228         when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
229 
230         when(mIndicationArea.findViewById(R.id.keyguard_indication_text_bottom))
231                 .thenReturn(mIndicationAreaBottom);
232         when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView);
233 
234         when(mDevicePolicyManager.getResources()).thenReturn(mDevicePolicyResourcesManager);
235         when(mDevicePolicyManager.getDeviceOwnerComponentOnAnyUser())
236                 .thenReturn(DEVICE_OWNER_COMPONENT);
237         when(mDevicePolicyManager.isFinancedDevice()).thenReturn(false);
238         // TODO(b/259908270): remove
239         when(mDevicePolicyManager.getDeviceOwnerType(DEVICE_OWNER_COMPONENT))
240                 .thenReturn(DEVICE_OWNER_TYPE_DEFAULT);
241 
242         when(mDevicePolicyResourcesManager.getString(anyString(), any()))
243                 .thenReturn(mDisclosureGeneric);
244         when(mDevicePolicyResourcesManager.getString(anyString(), any(), anyString()))
245                 .thenReturn(mDisclosureWithOrganization);
246         when(mUserTracker.getUserId()).thenReturn(mCurrentUserId);
247         when(mBiometricMessageInteractor.getCoExFaceAcquisitionMsgIdsToShow())
248                 .thenReturn(mock(StateFlow.class));
249 
250         when(mFaceHelpMessageDeferralFactory.create()).thenReturn(mFaceHelpMessageDeferral);
251         when(mDeviceEntryFingerprintAuthInteractor.isEngaged()).thenReturn(mock(StateFlow.class));
252 
253         mIndicationHelper = new IndicationHelper(mKeyguardUpdateMonitor);
254 
255         mWakeLock = new WakeLockFake();
256         mWakeLockBuilder = new WakeLockFake.Builder(mContext);
257         mWakeLockBuilder.setWakeLock(mWakeLock);
258     }
259 
260     @After
tearDown()261     public void tearDown() throws Exception {
262         mTextView.setAnimationsEnabled(true);
263         if (mController != null) {
264             mController.destroy();
265             mController = null;
266         }
267     }
268 
createController()269     protected void createController() {
270         if (Looper.myLooper() == null) {
271             Looper.prepare();
272         }
273 
274         mFlags = new FakeFeatureFlags();
275         mFlags.set(KEYGUARD_TALKBACK_FIX, true);
276         mFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false);
277         mController = new KeyguardIndicationController(
278                 mContext,
279                 mTestableLooper.getLooper(),
280                 mWakeLockBuilder,
281                 mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor,
282                 mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats,
283                 mUserManager, mExecutor, mExecutor, mFalsingManager,
284                 mAuthController, mLockPatternUtils, mScreenLifecycle,
285                 mKeyguardBypassController, mAccessibilityManager,
286                 mFaceHelpMessageDeferralFactory, mock(KeyguardLogger.class),
287                 mAlternateBouncerInteractor,
288                 mAlarmManager,
289                 mUserTracker,
290                 mock(BouncerMessageInteractor.class),
291                 mFlags,
292                 mIndicationHelper,
293                 KeyguardInteractorFactory.create(mFlags).getKeyguardInteractor(),
294                 mBiometricMessageInteractor,
295                 mDeviceEntryFingerprintAuthInteractor,
296                 mDeviceEntryFaceAuthInteractor
297         );
298         mController.init();
299         mController.setIndicationArea(mIndicationArea);
300         mController.mCoExAcquisitionMsgIdsToShowCallback.accept(emptySet());
301         verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
302         mStatusBarStateListener = mStatusBarStateListenerCaptor.getValue();
303         verify(mBroadcastDispatcher).registerReceiver(mBroadcastReceiverCaptor.capture(), any());
304         mBroadcastReceiver = mBroadcastReceiverCaptor.getValue();
305         mController.mRotateTextViewController = mRotateTextViewController;
306         mController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
307         clearInvocations(mIBatteryStats);
308 
309         verify(mKeyguardStateController).addCallback(
310                 mKeyguardStateControllerCallbackCaptor.capture());
311         mKeyguardStateControllerCallback = mKeyguardStateControllerCallbackCaptor.getValue();
312 
313         verify(mKeyguardUpdateMonitor).registerCallback(
314                 mKeyguardUpdateMonitorCallbackCaptor.capture());
315         mKeyguardUpdateMonitorCallback = mKeyguardUpdateMonitorCallbackCaptor.getValue();
316 
317         verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
318         mScreenObserver = mScreenObserverCaptor.getValue();
319 
320         mExecutor.runAllReady();
321         reset(mRotateTextViewController);
322     }
323 
verifyNoMessage(int type)324     void verifyNoMessage(int type) {
325         if (type == INDICATION_TYPE_TRANSIENT) {
326             verify(mRotateTextViewController, never()).showTransient(anyString());
327         } else {
328             verify(mRotateTextViewController, never()).updateIndication(eq(type),
329                     any(KeyguardIndication.class), anyBoolean());
330         }
331     }
332 
verifyIndicationShown(int indicationType, String message)333     void verifyIndicationShown(int indicationType, String message) {
334         verify(mRotateTextViewController)
335                 .updateIndication(eq(indicationType),
336                         mKeyguardIndicationCaptor.capture(),
337                         eq(true));
338         assertThat(mKeyguardIndicationCaptor.getValue().getMessage().toString())
339                 .isEqualTo(message);
340     }
341 }
342