blob: 49dab4a70932a72a61955569dd2ffb6356902f27 [file] [log] [blame]
Adrian Roosef7a4022017-01-19 14:48:35 -08001/*
2 * Copyright (C) 2017 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
17package com.android.systemui.statusbar.phone;
18
Julia Reynolds30203152017-05-26 13:36:31 -040019import static android.app.NotificationManager.IMPORTANCE_HIGH;
20
Julia Reynoldsed1c9af2018-03-21 15:21:09 -040021import static junit.framework.Assert.assertEquals;
Julia Reynolds30203152017-05-26 13:36:31 -040022import static junit.framework.Assert.assertFalse;
Julia Reynoldsed1c9af2018-03-21 15:21:09 -040023import static junit.framework.Assert.assertNotNull;
Julia Reynolds30203152017-05-26 13:36:31 -040024import static junit.framework.Assert.assertTrue;
Chris Wren621933f2017-06-14 15:59:03 -040025import static junit.framework.TestCase.fail;
Julia Reynolds30203152017-05-26 13:36:31 -040026
Chris Wren621933f2017-06-14 15:59:03 -040027import static org.mockito.ArgumentMatchers.any;
28import static org.mockito.ArgumentMatchers.anyBoolean;
29import static org.mockito.ArgumentMatchers.anyInt;
30import static org.mockito.ArgumentMatchers.anyString;
Lucas Dupin311eac82017-12-11 14:40:07 -080031import static org.mockito.ArgumentMatchers.eq;
Adrian Roosef7a4022017-01-19 14:48:35 -080032import static org.mockito.Mockito.doAnswer;
33import static org.mockito.Mockito.mock;
Chris Wren621933f2017-06-14 15:59:03 -040034import static org.mockito.Mockito.never;
Lucas Dupind5107302018-03-19 15:30:29 -070035import static org.mockito.Mockito.reset;
Chris Wren621933f2017-06-14 15:59:03 -040036import static org.mockito.Mockito.times;
Chris Wren621933f2017-06-14 15:59:03 -040037import static org.mockito.Mockito.verify;
Jason Monk9c4faa82017-08-15 09:32:27 -040038import static org.mockito.Mockito.when;
Adrian Roosef7a4022017-01-19 14:48:35 -080039
Julia Reynolds30203152017-05-26 13:36:31 -040040import android.app.Notification;
Charles He2eda2422017-09-24 17:55:21 +010041import android.app.StatusBarManager;
Jason Monk51305372017-06-22 11:41:08 -040042import android.app.trust.TrustManager;
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090043import android.content.Context;
Jason Monk51305372017-06-22 11:41:08 -040044import android.hardware.fingerprint.FingerprintManager;
Chris Wren27a52fa2017-02-01 14:21:43 -050045import android.metrics.LogMaker;
Jason Monk9c4faa82017-08-15 09:32:27 -040046import android.os.Binder;
Julia Reynolds30203152017-05-26 13:36:31 -040047import android.os.Handler;
48import android.os.HandlerThread;
49import android.os.IPowerManager;
Julia Reynolds30203152017-05-26 13:36:31 -040050import android.os.PowerManager;
Chris Wren621933f2017-06-14 15:59:03 -040051import android.os.RemoteException;
Julia Reynolds30203152017-05-26 13:36:31 -040052import android.os.UserHandle;
53import android.service.notification.StatusBarNotification;
Adrian Roosef7a4022017-01-19 14:48:35 -080054import android.support.test.filters.SmallTest;
Chris Wren27a52fa2017-02-01 14:21:43 -050055import android.support.test.metricshelper.MetricsAsserts;
Chris Wren621933f2017-06-14 15:59:03 -040056import android.testing.AndroidTestingRunner;
57import android.testing.TestableLooper;
Chris Wren621933f2017-06-14 15:59:03 -040058import android.testing.TestableLooper.RunWithLooper;
Eliot Courtney09322282017-11-09 15:31:19 +090059import android.util.SparseArray;
Julia Reynoldsed1c9af2018-03-21 15:21:09 -040060import android.view.Gravity;
61import android.view.View;
Jason Monk51305372017-06-22 11:41:08 -040062import android.view.ViewGroup.LayoutParams;
Adrian Roosef7a4022017-01-19 14:48:35 -080063
Chris Wrenef319902017-03-07 17:58:31 -050064import com.android.internal.logging.MetricsLogger;
Chris Wren27a52fa2017-02-01 14:21:43 -050065import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Chris Wrenef319902017-03-07 17:58:31 -050066import com.android.internal.logging.testing.FakeMetricsLogger;
Chris Wren621933f2017-06-14 15:59:03 -040067import com.android.internal.statusbar.IStatusBarService;
Adrian Roosef7a4022017-01-19 14:48:35 -080068import com.android.keyguard.KeyguardHostView.OnDismissAction;
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090069import com.android.systemui.ForegroundServiceController;
Jason Monk9c4faa82017-08-15 09:32:27 -040070import com.android.systemui.R;
Adrian Roosef7a4022017-01-19 14:48:35 -080071import com.android.systemui.SysuiTestCase;
Jason Monk9c4faa82017-08-15 09:32:27 -040072import com.android.systemui.assist.AssistManager;
Adrian Roos6d5ebb72017-08-03 15:10:22 +020073import com.android.systemui.keyguard.WakefulnessLifecycle;
Julia Reynolds30203152017-05-26 13:36:31 -040074import com.android.systemui.recents.misc.SystemServicesProxy;
Chris Wren27a52fa2017-02-01 14:21:43 -050075import com.android.systemui.statusbar.ActivatableNotificationView;
Julia Reynoldsfc640012018-02-21 12:25:27 -050076import com.android.systemui.statusbar.AppOpsListener;
Jason Monk5ecf80c2017-07-06 15:28:17 -040077import com.android.systemui.statusbar.CommandQueue;
Julia Reynoldsed1c9af2018-03-21 15:21:09 -040078import com.android.systemui.statusbar.ExpandableNotificationRow;
79import com.android.systemui.statusbar.FooterView;
80import com.android.systemui.statusbar.FooterViewButton;
Chris Wren27a52fa2017-02-01 14:21:43 -050081import com.android.systemui.statusbar.KeyguardIndicationController;
82import com.android.systemui.statusbar.NotificationData;
Chris Wren621933f2017-06-14 15:59:03 -040083import com.android.systemui.statusbar.NotificationData.Entry;
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090084import com.android.systemui.statusbar.NotificationEntryManager;
85import com.android.systemui.statusbar.NotificationGutsManager;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090086import com.android.systemui.statusbar.NotificationListContainer;
Eliot Courtney3985ad52017-11-17 16:51:52 +090087import com.android.systemui.statusbar.NotificationListener;
Eliot Courtney09322282017-11-09 15:31:19 +090088import com.android.systemui.statusbar.NotificationLockscreenUserManager;
Eliot Courtney3985ad52017-11-17 16:51:52 +090089import com.android.systemui.statusbar.NotificationLogger;
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090090import com.android.systemui.statusbar.NotificationMediaManager;
91import com.android.systemui.statusbar.NotificationPresenter;
92import com.android.systemui.statusbar.NotificationRemoteInputManager;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +090093import com.android.systemui.statusbar.NotificationViewHierarchyManager;
Chris Wren621933f2017-06-14 15:59:03 -040094import com.android.systemui.statusbar.StatusBarState;
Selim Cinek7e222c3c2018-01-25 12:22:41 -080095import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
Eliot Courtneya6d8cf22017-10-20 13:26:58 +090096import com.android.systemui.statusbar.notification.VisualStabilityManager;
Jason Monk9c4faa82017-08-15 09:32:27 -040097import com.android.systemui.statusbar.policy.DeviceProvisionedController;
Jason Monk9c4faa82017-08-15 09:32:27 -040098import com.android.systemui.statusbar.policy.KeyguardMonitor;
99import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
Chris Wren27a52fa2017-02-01 14:21:43 -0500100import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
Adrian Roosef7a4022017-01-19 14:48:35 -0800101
102import org.junit.Before;
103import org.junit.Test;
104import org.junit.runner.RunWith;
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400105import org.mockito.ArgumentCaptor;
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900106import org.mockito.Mock;
107import org.mockito.MockitoAnnotations;
Adrian Roosef7a4022017-01-19 14:48:35 -0800108
Jason Monk51305372017-06-22 11:41:08 -0400109import java.io.ByteArrayOutputStream;
110import java.io.PrintWriter;
Chris Wren621933f2017-06-14 15:59:03 -0400111import java.util.ArrayList;
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400112import java.util.function.Predicate;
Chris Wren621933f2017-06-14 15:59:03 -0400113
Adrian Roos02de4982017-02-11 09:35:54 +0100114@SmallTest
Chris Wren621933f2017-06-14 15:59:03 -0400115@RunWith(AndroidTestingRunner.class)
116@RunWithLooper
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500117public class StatusBarTest extends SysuiTestCase {
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900118 @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
119 @Mock private UnlockMethodCache mUnlockMethodCache;
120 @Mock private KeyguardIndicationController mKeyguardIndicationController;
121 @Mock private NotificationStackScrollLayout mStackScroller;
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900122 @Mock private HeadsUpManagerPhone mHeadsUpManager;
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900123 @Mock private SystemServicesProxy mSystemServicesProxy;
124 @Mock private NotificationPanelView mNotificationPanelView;
125 @Mock private IStatusBarService mBarService;
126 @Mock private ScrimController mScrimController;
127 @Mock private ArrayList<Entry> mNotificationList;
128 @Mock private FingerprintUnlockController mFingerprintUnlockController;
129 @Mock private NotificationData mNotificationData;
Adrian Roosef7a4022017-01-19 14:48:35 -0800130
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900131 // Mock dependencies:
132 @Mock private NotificationViewHierarchyManager mViewHierarchyManager;
133 @Mock private VisualStabilityManager mVisualStabilityManager;
134 @Mock private NotificationListener mNotificationListener;
135
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900136 private TestableStatusBar mStatusBar;
137 private FakeMetricsLogger mMetricsLogger;
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900138 private PowerManager mPowerManager;
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900139 private TestableNotificationEntryManager mEntryManager;
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900140 private NotificationLogger mNotificationLogger;
Chris Wren27a52fa2017-02-01 14:21:43 -0500141
Adrian Roos02de4982017-02-11 09:35:54 +0100142 @Before
Julia Reynolds30203152017-05-26 13:36:31 -0400143 public void setup() throws Exception {
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900144 MockitoAnnotations.initMocks(this);
Jason Monk9c4faa82017-08-15 09:32:27 -0400145 mDependency.injectMockDependency(AssistManager.class);
146 mDependency.injectMockDependency(DeviceProvisionedController.class);
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900147 mDependency.injectMockDependency(NotificationGroupManager.class);
148 mDependency.injectMockDependency(NotificationGutsManager.class);
149 mDependency.injectMockDependency(NotificationRemoteInputManager.class);
150 mDependency.injectMockDependency(NotificationMediaManager.class);
151 mDependency.injectMockDependency(ForegroundServiceController.class);
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900152 mDependency.injectTestDependency(NotificationViewHierarchyManager.class,
153 mViewHierarchyManager);
154 mDependency.injectTestDependency(VisualStabilityManager.class, mVisualStabilityManager);
155 mDependency.injectTestDependency(NotificationListener.class, mNotificationListener);
Jason Monk9c4faa82017-08-15 09:32:27 -0400156 mDependency.injectTestDependency(KeyguardMonitor.class, mock(KeyguardMonitorImpl.class));
Julia Reynoldsfc640012018-02-21 12:25:27 -0500157 mDependency.injectTestDependency(AppOpsListener.class, mock(AppOpsListener.class));
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900158
Jason Monk51305372017-06-22 11:41:08 -0400159 mContext.addMockSystemService(TrustManager.class, mock(TrustManager.class));
160 mContext.addMockSystemService(FingerprintManager.class, mock(FingerprintManager.class));
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900161
Chris Wrenef319902017-03-07 17:58:31 -0500162 mMetricsLogger = new FakeMetricsLogger();
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900163 mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900164 mDependency.injectTestDependency(NotificationLogger.class, mNotificationLogger);
Eugene Susla2de69552018-03-20 13:22:17 -0700165 mNotificationLogger = new NotificationLogger();
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900166
Julia Reynolds30203152017-05-26 13:36:31 -0400167 IPowerManager powerManagerService = mock(IPowerManager.class);
168 HandlerThread handlerThread = new HandlerThread("TestThread");
169 handlerThread.start();
170 mPowerManager = new PowerManager(mContext, powerManagerService,
171 new Handler(handlerThread.getLooper()));
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900172
173 CommandQueue commandQueue = mock(CommandQueue.class);
174 when(commandQueue.asBinder()).thenReturn(new Binder());
175 mContext.putComponent(CommandQueue.class, commandQueue);
176
177 mContext.setTheme(R.style.Theme_SystemUI_Light);
178
179 when(mStackScroller.generateLayoutParams(any())).thenReturn(new LayoutParams(0, 0));
180 when(mNotificationPanelView.getLayoutParams()).thenReturn(new LayoutParams(0, 0));
Julia Reynolds30203152017-05-26 13:36:31 -0400181 when(powerManagerService.isInteractive()).thenReturn(true);
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900182 when(mStackScroller.getActivatedChild()).thenReturn(null);
Julia Reynolds30203152017-05-26 13:36:31 -0400183
Adrian Roosef7a4022017-01-19 14:48:35 -0800184 doAnswer(invocation -> {
185 OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
186 onDismissAction.onDismiss();
187 return null;
188 }).when(mStatusBarKeyguardViewManager).dismissWithAction(any(), any(), anyBoolean());
189
190 doAnswer(invocation -> {
191 Runnable runnable = (Runnable) invocation.getArguments()[0];
192 runnable.run();
193 return null;
194 }).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
Chris Wren27a52fa2017-02-01 14:21:43 -0500195
Eliot Courtney6c313d32017-12-14 19:57:51 +0900196 mEntryManager = new TestableNotificationEntryManager(mSystemServicesProxy, mPowerManager,
197 mContext);
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900198 mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
199 mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
200 mPowerManager, mNotificationPanelView, mBarService, mNotificationListener,
201 mNotificationLogger, mVisualStabilityManager, mViewHierarchyManager,
Selim Cinek7e222c3c2018-01-25 12:22:41 -0800202 mEntryManager, mScrimController, mFingerprintUnlockController,
203 mock(ActivityLaunchAnimator.class));
Eliot Courtney8f56b0e2017-12-14 18:54:28 +0900204 mStatusBar.mContext = mContext;
205 mStatusBar.mComponents = mContext.getComponents();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900206 mEntryManager.setUpForTest(mStatusBar, mStackScroller, mStatusBar, mHeadsUpManager,
207 mNotificationData);
Eliot Courtney4a96b362017-12-14 19:38:52 +0900208 mNotificationLogger.setUpWithEntryManager(mEntryManager, mStackScroller);
Eliot Courtney3985ad52017-11-17 16:51:52 +0900209
Eliot Courtney3985ad52017-11-17 16:51:52 +0900210 TestableLooper.get(this).setMessageHandler(m -> {
211 if (m.getCallback() == mStatusBar.mNotificationLogger.getVisibilityReporter()) {
212 return false;
Chris Wren621933f2017-06-14 15:59:03 -0400213 }
Eliot Courtney3985ad52017-11-17 16:51:52 +0900214 return true;
Chris Wren621933f2017-06-14 15:59:03 -0400215 });
Adrian Roosef7a4022017-01-19 14:48:35 -0800216 }
217
Adrian Roos02de4982017-02-11 09:35:54 +0100218 @Test
Jason Monk5ecf80c2017-07-06 15:28:17 -0400219 public void testSetBouncerShowing_noCrash() {
220 mStatusBar.mCommandQueue = mock(CommandQueue.class);
221 mStatusBar.setBouncerShowing(true);
222 }
223
224 @Test
Adrian Roosef7a4022017-01-19 14:48:35 -0800225 public void executeRunnableDismissingKeyguard_nullRunnable_showingAndOccluded() {
226 when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
227 when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(true);
228
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500229 mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
Adrian Roosef7a4022017-01-19 14:48:35 -0800230 }
231
Adrian Roos02de4982017-02-11 09:35:54 +0100232 @Test
Adrian Roosef7a4022017-01-19 14:48:35 -0800233 public void executeRunnableDismissingKeyguard_nullRunnable_showing() {
234 when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
235 when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
236
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500237 mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
Adrian Roosef7a4022017-01-19 14:48:35 -0800238 }
239
Adrian Roos02de4982017-02-11 09:35:54 +0100240 @Test
Adrian Roosef7a4022017-01-19 14:48:35 -0800241 public void executeRunnableDismissingKeyguard_nullRunnable_notShowing() {
242 when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
243 when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
244
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500245 mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
Adrian Roosef7a4022017-01-19 14:48:35 -0800246 }
247
Adrian Roos02de4982017-02-11 09:35:54 +0100248 @Test
Chris Wren27a52fa2017-02-01 14:21:43 -0500249 public void lockscreenStateMetrics_notShowing() {
250 // uninteresting state, except that fingerprint must be non-zero
251 when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
252 when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
253 // interesting state
254 when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
255 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
256 when(mUnlockMethodCache.isMethodSecure()).thenReturn(false);
Chris Wren27a52fa2017-02-01 14:21:43 -0500257 mStatusBar.onKeyguardViewManagerStatesUpdated();
258
Chris Wrenef319902017-03-07 17:58:31 -0500259 MetricsAsserts.assertHasLog("missing hidden insecure lockscreen log",
260 mMetricsLogger.getLogs(),
Chris Wren27a52fa2017-02-01 14:21:43 -0500261 new LogMaker(MetricsEvent.LOCKSCREEN)
262 .setType(MetricsEvent.TYPE_CLOSE)
263 .setSubtype(0));
264 }
265
Adrian Roos02de4982017-02-11 09:35:54 +0100266 @Test
Chris Wren27a52fa2017-02-01 14:21:43 -0500267 public void lockscreenStateMetrics_notShowing_secure() {
268 // uninteresting state, except that fingerprint must be non-zero
269 when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
270 when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
271 // interesting state
272 when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
273 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
274 when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
275
276 mStatusBar.onKeyguardViewManagerStatesUpdated();
277
Chris Wrenef319902017-03-07 17:58:31 -0500278 MetricsAsserts.assertHasLog("missing hidden secure lockscreen log",
279 mMetricsLogger.getLogs(),
Chris Wren27a52fa2017-02-01 14:21:43 -0500280 new LogMaker(MetricsEvent.LOCKSCREEN)
281 .setType(MetricsEvent.TYPE_CLOSE)
282 .setSubtype(1));
283 }
284
Adrian Roos02de4982017-02-11 09:35:54 +0100285 @Test
Chris Wren27a52fa2017-02-01 14:21:43 -0500286 public void lockscreenStateMetrics_isShowing() {
287 // uninteresting state, except that fingerprint must be non-zero
288 when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
289 when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
290 // interesting state
291 when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
292 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
293 when(mUnlockMethodCache.isMethodSecure()).thenReturn(false);
294
295 mStatusBar.onKeyguardViewManagerStatesUpdated();
296
Chris Wrenef319902017-03-07 17:58:31 -0500297 MetricsAsserts.assertHasLog("missing insecure lockscreen showing",
298 mMetricsLogger.getLogs(),
Chris Wren27a52fa2017-02-01 14:21:43 -0500299 new LogMaker(MetricsEvent.LOCKSCREEN)
300 .setType(MetricsEvent.TYPE_OPEN)
301 .setSubtype(0));
302 }
303
Adrian Roos02de4982017-02-11 09:35:54 +0100304 @Test
Chris Wren27a52fa2017-02-01 14:21:43 -0500305 public void lockscreenStateMetrics_isShowing_secure() {
306 // uninteresting state, except that fingerprint must be non-zero
307 when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
308 when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
309 // interesting state
310 when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
311 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
312 when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
313
314 mStatusBar.onKeyguardViewManagerStatesUpdated();
315
Chris Wrenef319902017-03-07 17:58:31 -0500316 MetricsAsserts.assertHasLog("missing secure lockscreen showing log",
317 mMetricsLogger.getLogs(),
Chris Wren27a52fa2017-02-01 14:21:43 -0500318 new LogMaker(MetricsEvent.LOCKSCREEN)
319 .setType(MetricsEvent.TYPE_OPEN)
320 .setSubtype(1));
321 }
322
Adrian Roos02de4982017-02-11 09:35:54 +0100323 @Test
Chris Wren27a52fa2017-02-01 14:21:43 -0500324 public void lockscreenStateMetrics_isShowingBouncer() {
325 // uninteresting state, except that fingerprint must be non-zero
326 when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
327 when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
328 // interesting state
329 when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
330 when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
331 when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
332
333 mStatusBar.onKeyguardViewManagerStatesUpdated();
334
Chris Wrenef319902017-03-07 17:58:31 -0500335 MetricsAsserts.assertHasLog("missing bouncer log",
336 mMetricsLogger.getLogs(),
Chris Wren27a52fa2017-02-01 14:21:43 -0500337 new LogMaker(MetricsEvent.BOUNCER)
338 .setType(MetricsEvent.TYPE_OPEN)
339 .setSubtype(1));
340 }
341
Adrian Roos02de4982017-02-11 09:35:54 +0100342 @Test
Chris Wren27a52fa2017-02-01 14:21:43 -0500343 public void onActivatedMetrics() {
344 ActivatableNotificationView view = mock(ActivatableNotificationView.class);
345 mStatusBar.onActivated(view);
346
Chris Wrenef319902017-03-07 17:58:31 -0500347 MetricsAsserts.assertHasLog("missing lockscreen note tap log",
348 mMetricsLogger.getLogs(),
Chris Wren27a52fa2017-02-01 14:21:43 -0500349 new LogMaker(MetricsEvent.ACTION_LS_NOTE)
350 .setType(MetricsEvent.TYPE_ACTION));
351 }
352
Julia Reynolds30203152017-05-26 13:36:31 -0400353 @Test
354 public void testShouldPeek_nonSuppressedGroupSummary() {
355 when(mPowerManager.isScreenOn()).thenReturn(true);
356 when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
Julia Reynolds24653c32018-03-02 13:16:37 -0500357 when(mNotificationData.shouldSuppressStatusBar(any())).thenReturn(false);
Julia Reynolds30203152017-05-26 13:36:31 -0400358 when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
359 when(mSystemServicesProxy.isDreaming()).thenReturn(false);
360 when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
361
362 Notification n = new Notification.Builder(getContext(), "a")
363 .setGroup("a")
364 .setGroupSummary(true)
365 .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
366 .build();
367 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
368 UserHandle.of(0), null, 0);
369 NotificationData.Entry entry = new NotificationData.Entry(sbn);
370
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900371 assertTrue(mEntryManager.shouldPeek(entry, sbn));
Julia Reynolds30203152017-05-26 13:36:31 -0400372 }
373
374 @Test
375 public void testShouldPeek_suppressedGroupSummary() {
376 when(mPowerManager.isScreenOn()).thenReturn(true);
377 when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
Julia Reynolds24653c32018-03-02 13:16:37 -0500378 when(mNotificationData.shouldSuppressStatusBar(any())).thenReturn(false);
Julia Reynolds30203152017-05-26 13:36:31 -0400379 when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
380 when(mSystemServicesProxy.isDreaming()).thenReturn(false);
381 when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
382
383 Notification n = new Notification.Builder(getContext(), "a")
384 .setGroup("a")
385 .setGroupSummary(true)
386 .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN)
387 .build();
388 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
389 UserHandle.of(0), null, 0);
390 NotificationData.Entry entry = new NotificationData.Entry(sbn);
391
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900392 assertFalse(mEntryManager.shouldPeek(entry, sbn));
Julia Reynolds30203152017-05-26 13:36:31 -0400393 }
394
Chris Wren621933f2017-06-14 15:59:03 -0400395 @Test
Julia Reynolds24653c32018-03-02 13:16:37 -0500396 public void testShouldPeek_suppressedPeek() {
Beverly38159ce2017-07-13 16:39:24 -0400397 when(mPowerManager.isScreenOn()).thenReturn(true);
398 when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
399 when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
400 when(mSystemServicesProxy.isDreaming()).thenReturn(false);
401 when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
402
Julia Reynolds24653c32018-03-02 13:16:37 -0500403 when(mNotificationData.shouldSuppressPeek(any())).thenReturn(true);
404
405 Notification n = new Notification.Builder(getContext(), "a").build();
406 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
407 UserHandle.of(0), null, 0);
408 NotificationData.Entry entry = new NotificationData.Entry(sbn);
409
410 assertFalse(mEntryManager.shouldPeek(entry, sbn));
411 }
412
413 @Test
414 public void testShouldPeek_noSuppressedPeek() {
415 when(mPowerManager.isScreenOn()).thenReturn(true);
416 when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
417 when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
418 when(mSystemServicesProxy.isDreaming()).thenReturn(false);
419 when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
420
421 when(mNotificationData.shouldSuppressPeek(any())).thenReturn(false);
Beverly38159ce2017-07-13 16:39:24 -0400422
423 Notification n = new Notification.Builder(getContext(), "a").build();
424 StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
425 UserHandle.of(0), null, 0);
426 NotificationData.Entry entry = new NotificationData.Entry(sbn);
427
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900428 assertTrue(mEntryManager.shouldPeek(entry, sbn));
Beverly38159ce2017-07-13 16:39:24 -0400429 }
430
431 @Test
Chris Wren621933f2017-06-14 15:59:03 -0400432 public void testLogHidden() {
433 try {
434 mStatusBar.handleVisibleToUserChanged(false);
Selim Cinek1a891a92017-12-04 17:41:27 +0100435 waitForUiOffloadThread();
Chris Wren621933f2017-06-14 15:59:03 -0400436 verify(mBarService, times(1)).onPanelHidden();
437 verify(mBarService, never()).onPanelRevealed(anyBoolean(), anyInt());
438 } catch (RemoteException e) {
439 fail();
440 }
441 }
442
443 @Test
444 public void testPanelOpenForPeek() {
445 when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(true);
446 when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
447 when(mNotificationList.size()).thenReturn(5);
448 when(mNotificationPanelView.isFullyCollapsed()).thenReturn(true);
449 mStatusBar.setBarStateForTest(StatusBarState.SHADE);
450
451 try {
452 mStatusBar.handleVisibleToUserChanged(true);
Selim Cinek1a891a92017-12-04 17:41:27 +0100453 waitForUiOffloadThread();
Chris Wren621933f2017-06-14 15:59:03 -0400454 verify(mBarService, never()).onPanelHidden();
455 verify(mBarService, times(1)).onPanelRevealed(false, 1);
456 } catch (RemoteException e) {
457 fail();
458 }
459 TestableLooper.get(this).processAllMessages();
460 }
461
462 @Test
463 public void testPanelOpenAndClear() {
464 when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false);
465 when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
466 when(mNotificationList.size()).thenReturn(5);
467 when(mNotificationPanelView.isFullyCollapsed()).thenReturn(false);
468 mStatusBar.setBarStateForTest(StatusBarState.SHADE);
469
470 try {
471 mStatusBar.handleVisibleToUserChanged(true);
Selim Cinek1a891a92017-12-04 17:41:27 +0100472 waitForUiOffloadThread();
Chris Wren621933f2017-06-14 15:59:03 -0400473 verify(mBarService, never()).onPanelHidden();
474 verify(mBarService, times(1)).onPanelRevealed(true, 5);
475 } catch (RemoteException e) {
476 fail();
477 }
478 TestableLooper.get(this).processAllMessages();
479 }
480
481 @Test
482 public void testPanelOpenAndNoClear() {
483 when(mHeadsUpManager.hasPinnedHeadsUp()).thenReturn(false);
484 when(mNotificationData.getActiveNotifications()).thenReturn(mNotificationList);
485 when(mNotificationList.size()).thenReturn(5);
486 when(mNotificationPanelView.isFullyCollapsed()).thenReturn(false);
487 mStatusBar.setBarStateForTest(StatusBarState.KEYGUARD);
488
489 try {
490 mStatusBar.handleVisibleToUserChanged(true);
Selim Cinek1a891a92017-12-04 17:41:27 +0100491 waitForUiOffloadThread();
Chris Wren621933f2017-06-14 15:59:03 -0400492 verify(mBarService, never()).onPanelHidden();
493 verify(mBarService, times(1)).onPanelRevealed(false, 5);
494 } catch (RemoteException e) {
495 fail();
496 }
497 TestableLooper.get(this).processAllMessages();
498 }
499
Jason Monk51305372017-06-22 11:41:08 -0400500 @Test
Charles He2eda2422017-09-24 17:55:21 +0100501 public void testDisableExpandStatusBar() {
502 mStatusBar.setBarStateForTest(StatusBarState.SHADE);
503 mStatusBar.setUserSetupForTest(true);
504 when(mStatusBar.isDeviceProvisioned()).thenReturn(true);
505
506 mStatusBar.disable(StatusBarManager.DISABLE_NONE,
507 StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false);
508 verify(mNotificationPanelView).setQsExpansionEnabled(false);
509 mStatusBar.animateExpandNotificationsPanel();
510 verify(mNotificationPanelView, never()).expand(anyBoolean());
511 mStatusBar.animateExpandSettingsPanel(null);
512 verify(mNotificationPanelView, never()).expand(anyBoolean());
513
514 mStatusBar.disable(StatusBarManager.DISABLE_NONE, StatusBarManager.DISABLE2_NONE, false);
515 verify(mNotificationPanelView).setQsExpansionEnabled(true);
516 mStatusBar.animateExpandNotificationsPanel();
Eugene Susla2de69552018-03-20 13:22:17 -0700517 verify(mNotificationPanelView).expandWithoutQs();
Charles He2eda2422017-09-24 17:55:21 +0100518 mStatusBar.animateExpandSettingsPanel(null);
Eugene Susla2de69552018-03-20 13:22:17 -0700519 verify(mNotificationPanelView).expandWithQs();
Charles He2eda2422017-09-24 17:55:21 +0100520 }
521
522 @Test
Jason Monk51305372017-06-22 11:41:08 -0400523 public void testDump_DoesNotCrash() {
524 mStatusBar.dump(null, new PrintWriter(new ByteArrayOutputStream()), null);
525 }
526
Jason Monk9c4faa82017-08-15 09:32:27 -0400527 @Test
528 @RunWithLooper(setAsMainLooper = true)
529 public void testUpdateKeyguardState_DoesNotCrash() {
530 mStatusBar.mStatusBarWindow = mock(StatusBarWindowView.class);
531 mStatusBar.mState = StatusBarState.KEYGUARD;
532 mStatusBar.mDozeScrimController = mock(DozeScrimController.class);
533 mStatusBar.mNotificationIconAreaController = mock(NotificationIconAreaController.class);
Eliot Courtney09322282017-11-09 15:31:19 +0900534 mStatusBar.mLockscreenUserManager = mock(NotificationLockscreenUserManager.class);
535 when(mStatusBar.mLockscreenUserManager.getCurrentProfiles()).thenReturn(
536 new SparseArray<>());
Jason Monk9c4faa82017-08-15 09:32:27 -0400537 mStatusBar.updateKeyguardState(false, false);
538 }
539
Lucas Dupinc2e75462017-12-06 13:59:25 -0800540 @Test
541 public void testFingerprintNotification_UpdatesScrims() {
542 mStatusBar.mStatusBarWindowManager = mock(StatusBarWindowManager.class);
Lucas Dupinc2e75462017-12-06 13:59:25 -0800543 mStatusBar.mDozeScrimController = mock(DozeScrimController.class);
Julia Reynolds24653c32018-03-02 13:16:37 -0500544 mStatusBar.mNotificationIconAreaController = mock(NotificationIconAreaController.class);
Lucas Dupinc2e75462017-12-06 13:59:25 -0800545 mStatusBar.notifyFpAuthModeChanged();
546 verify(mScrimController).transitionTo(any(), any());
547 }
548
Lucas Dupin311eac82017-12-11 14:40:07 -0800549 @Test
550 public void testFingerprintUnlock_UpdatesScrims() {
551 // Simulate unlocking from AoD with fingerprint.
552 when(mFingerprintUnlockController.getMode())
553 .thenReturn(FingerprintUnlockController.MODE_WAKE_AND_UNLOCK);
554 mStatusBar.updateScrimController();
555 verify(mScrimController).transitionTo(eq(ScrimState.UNLOCKED), any());
556 }
557
Lucas Dupind5107302018-03-19 15:30:29 -0700558 @Test
559 public void testSetOccluded_propagatesToScrimController() {
560 mStatusBar.setOccluded(true);
561 verify(mScrimController).setKeyguardOccluded(eq(true));
562
563 reset(mScrimController);
564 mStatusBar.setOccluded(false);
565 verify(mScrimController).setKeyguardOccluded(eq(false));
566 }
567
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400568 @Test
569 public void testInflateFooterView() {
570 mStatusBar.reevaluateStyles();
571 ArgumentCaptor<FooterView> captor = ArgumentCaptor.forClass(FooterView.class);
572 verify(mStackScroller).setFooterView(captor.capture());
573
574 assertNotNull(captor.getValue().findViewById(R.id.manage_text).hasOnClickListeners());
575 assertNotNull(captor.getValue().findViewById(R.id.dismiss_text).hasOnClickListeners());
576 }
577
578 @Test
579 public void testUpdateFooter_noNotifications() {
580 mStatusBar.setBarStateForTest(StatusBarState.SHADE);
581 assertEquals(0, mEntryManager.getNotificationData().getActiveNotifications().size());
582
583 mStatusBar.updateFooter();
584 verify(mStackScroller).updateFooterView(false, false);
585 }
586
587 @Test
588 public void testUpdateFooter_oneClearableNotification() {
589 mStatusBar.setBarStateForTest(StatusBarState.SHADE);
590 ArrayList<Entry> entries = new ArrayList<>();
591 entries.add(mock(Entry.class));
592 when(mNotificationData.getActiveNotifications()).thenReturn(entries);
593
594 ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
595 when(row.canViewBeDismissed()).thenReturn(true);
596 when(mStackScroller.getChildCount()).thenReturn(1);
597 when(mStackScroller.getChildAt(anyInt())).thenReturn(row);
598
599 mStatusBar.updateFooter();
600 verify(mStackScroller).updateFooterView(true, true);
601 }
602
603 @Test
604 public void testUpdateFooter_oneNonClearableNotification() {
605 mStatusBar.setBarStateForTest(StatusBarState.SHADE);
606 ArrayList<Entry> entries = new ArrayList<>();
607 entries.add(mock(Entry.class));
608 when(mNotificationData.getActiveNotifications()).thenReturn(entries);
609
610 mStatusBar.updateFooter();
611 verify(mStackScroller).updateFooterView(true, false);
612 }
613
614 @Test
615 public void testUpdateFooter_atEnd() {
616 // add footer
617 mStatusBar.reevaluateStyles();
618
619 // add notification
620 ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
621 when(row.isClearable()).thenReturn(true);
622 mStackScroller.addContainerView(row);
623
624 mStatusBar.onUpdateRowStates();
625
626 // move footer to end
627 verify(mStackScroller).changeViewPosition(any(FooterView.class), eq(-1 /* end */));
628 }
629
Jason Monk2a6ea9c2017-01-26 11:14:51 -0500630 static class TestableStatusBar extends StatusBar {
Chris Wren27a52fa2017-02-01 14:21:43 -0500631 public TestableStatusBar(StatusBarKeyguardViewManager man,
632 UnlockMethodCache unlock, KeyguardIndicationController key,
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900633 NotificationStackScrollLayout stack, HeadsUpManagerPhone hum,
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900634 PowerManager pm, NotificationPanelView panelView,
Eliot Courtney3985ad52017-11-17 16:51:52 +0900635 IStatusBarService barService, NotificationListener notificationListener,
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900636 NotificationLogger notificationLogger,
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900637 VisualStabilityManager visualStabilityManager,
638 NotificationViewHierarchyManager viewHierarchyManager,
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900639 TestableNotificationEntryManager entryManager, ScrimController scrimController,
Selim Cinek7e222c3c2018-01-25 12:22:41 -0800640 FingerprintUnlockController fingerprintUnlockController,
641 ActivityLaunchAnimator launchAnimator) {
Adrian Roosef7a4022017-01-19 14:48:35 -0800642 mStatusBarKeyguardViewManager = man;
Chris Wren27a52fa2017-02-01 14:21:43 -0500643 mUnlockMethodCache = unlock;
644 mKeyguardIndicationController = key;
645 mStackScroller = stack;
Julia Reynolds30203152017-05-26 13:36:31 -0400646 mHeadsUpManager = hum;
Julia Reynolds30203152017-05-26 13:36:31 -0400647 mPowerManager = pm;
Jorim Jaggifd3b1a12017-06-06 17:04:19 -0700648 mNotificationPanel = panelView;
Chris Wren621933f2017-06-14 15:59:03 -0400649 mBarService = barService;
Eliot Courtney3985ad52017-11-17 16:51:52 +0900650 mNotificationListener = notificationListener;
651 mNotificationLogger = notificationLogger;
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200652 mWakefulnessLifecycle = createAwakeWakefulnessLifecycle();
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900653 mVisualStabilityManager = visualStabilityManager;
654 mViewHierarchyManager = viewHierarchyManager;
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900655 mEntryManager = entryManager;
Lucas Dupinc2e75462017-12-06 13:59:25 -0800656 mScrimController = scrimController;
Lucas Dupin311eac82017-12-11 14:40:07 -0800657 mFingerprintUnlockController = fingerprintUnlockController;
Selim Cinek7e222c3c2018-01-25 12:22:41 -0800658 mActivityLaunchAnimator = launchAnimator;
Julia Reynoldsed1c9af2018-03-21 15:21:09 -0400659 mClearAllEnabled = true;
Adrian Roos6d5ebb72017-08-03 15:10:22 +0200660 }
661
662 private WakefulnessLifecycle createAwakeWakefulnessLifecycle() {
663 WakefulnessLifecycle wakefulnessLifecycle = new WakefulnessLifecycle();
664 wakefulnessLifecycle.dispatchStartedWakingUp();
665 wakefulnessLifecycle.dispatchFinishedWakingUp();
666 return wakefulnessLifecycle;
Adrian Roosef7a4022017-01-19 14:48:35 -0800667 }
668
Jason Monk9c4faa82017-08-15 09:32:27 -0400669 @Override
670 protected void updateTheme() {
671 // Do nothing for now, until we have more mocking and StatusBar is smaller.
672 }
673
Chris Wren621933f2017-06-14 15:59:03 -0400674 public void setBarStateForTest(int state) {
675 mState = state;
Adrian Roosef7a4022017-01-19 14:48:35 -0800676 }
Charles He2eda2422017-09-24 17:55:21 +0100677
678 public void setUserSetupForTest(boolean userSetup) {
679 mUserSetup = userSetup;
680 }
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900681
682 }
683
684 private class TestableNotificationEntryManager extends NotificationEntryManager {
685
Eliot Courtney6c313d32017-12-14 19:57:51 +0900686 public TestableNotificationEntryManager(SystemServicesProxy systemServicesProxy,
687 PowerManager powerManager, Context context) {
688 super(context);
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900689 mSystemServicesProxy = systemServicesProxy;
690 mPowerManager = powerManager;
691 }
692
693 public void setUpForTest(NotificationPresenter presenter,
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900694 NotificationListContainer listContainer,
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900695 Callback callback,
yoshiki iguchi4e30e762018-02-06 12:09:23 +0900696 HeadsUpManagerPhone headsUpManager,
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900697 NotificationData notificationData) {
Eliot Courtney2b4c3a02017-11-27 13:27:46 +0900698 super.setUpWithPresenter(presenter, listContainer, callback, headsUpManager);
Eliot Courtneya6d8cf22017-10-20 13:26:58 +0900699 mNotificationData = notificationData;
700 mUseHeadsUp = true;
701 }
Adrian Roosef7a4022017-01-19 14:48:35 -0800702 }
Eliot Courtney09322282017-11-09 15:31:19 +0900703}