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