StatusBarTest.java revision fd3b1a1b76c69d08ab9e9a969a7996b132825943
1/*
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
19import static android.app.NotificationManager.IMPORTANCE_HIGH;
20
21import static junit.framework.Assert.assertFalse;
22import static junit.framework.Assert.assertTrue;
23
24import static org.mockito.Matchers.any;
25import static org.mockito.Matchers.anyBoolean;
26import static org.mockito.Matchers.anyString;
27import static org.mockito.Mockito.doAnswer;
28import static org.mockito.Mockito.mock;
29import static org.mockito.Mockito.when;
30
31import android.app.Notification;
32import android.metrics.LogMaker;
33import android.os.Handler;
34import android.os.HandlerThread;
35import android.os.IPowerManager;
36import android.os.Looper;
37import android.os.PowerManager;
38import android.os.UserHandle;
39import android.service.notification.StatusBarNotification;
40import android.support.test.filters.SmallTest;
41import android.support.test.metricshelper.MetricsAsserts;
42import android.support.test.runner.AndroidJUnit4;
43import android.util.DisplayMetrics;
44
45import com.android.internal.logging.MetricsLogger;
46import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
47import com.android.internal.logging.testing.FakeMetricsLogger;
48import com.android.keyguard.KeyguardHostView.OnDismissAction;
49import com.android.systemui.SysuiTestCase;
50import com.android.systemui.recents.misc.SystemServicesProxy;
51import com.android.systemui.statusbar.ActivatableNotificationView;
52import com.android.systemui.statusbar.KeyguardIndicationController;
53import com.android.systemui.statusbar.NotificationData;
54import com.android.systemui.statusbar.policy.HeadsUpManager;
55import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
56
57import org.junit.Before;
58import org.junit.Test;
59import org.junit.runner.RunWith;
60
61@SmallTest
62@RunWith(AndroidJUnit4.class)
63public class StatusBarTest extends SysuiTestCase {
64
65    StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
66    UnlockMethodCache mUnlockMethodCache;
67    KeyguardIndicationController mKeyguardIndicationController;
68    NotificationStackScrollLayout mStackScroller;
69    StatusBar mStatusBar;
70    FakeMetricsLogger mMetricsLogger;
71    HeadsUpManager mHeadsUpManager;
72    NotificationData mNotificationData;
73    PowerManager mPowerManager;
74    SystemServicesProxy mSystemServicesProxy;
75    NotificationPanelView mNotificationPanelView;
76    private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
77
78    @Before
79    public void setup() throws Exception {
80        mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class);
81        mUnlockMethodCache = mock(UnlockMethodCache.class);
82        mKeyguardIndicationController = mock(KeyguardIndicationController.class);
83        mStackScroller = mock(NotificationStackScrollLayout.class);
84        mMetricsLogger = new FakeMetricsLogger();
85        mHeadsUpManager = mock(HeadsUpManager.class);
86        mNotificationData = mock(NotificationData.class);
87        mSystemServicesProxy = mock(SystemServicesProxy.class);
88        mNotificationPanelView = mock(NotificationPanelView.class);
89        IPowerManager powerManagerService = mock(IPowerManager.class);
90        HandlerThread handlerThread = new HandlerThread("TestThread");
91        handlerThread.start();
92        mPowerManager = new PowerManager(mContext, powerManagerService,
93                new Handler(handlerThread.getLooper()));
94        when(powerManagerService.isInteractive()).thenReturn(true);
95
96        mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
97        mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
98                mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
99                mNotificationData, mPowerManager, mSystemServicesProxy, mNotificationPanelView);
100
101        doAnswer(invocation -> {
102            OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
103            onDismissAction.onDismiss();
104            return null;
105        }).when(mStatusBarKeyguardViewManager).dismissWithAction(any(), any(), anyBoolean());
106
107        doAnswer(invocation -> {
108            Runnable runnable = (Runnable) invocation.getArguments()[0];
109            runnable.run();
110            return null;
111        }).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
112
113        when(mStackScroller.getActivatedChild()).thenReturn(null);
114    }
115
116    @Test
117    public void executeRunnableDismissingKeyguard_nullRunnable_showingAndOccluded() {
118        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
119        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(true);
120
121        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
122    }
123
124    @Test
125    public void executeRunnableDismissingKeyguard_nullRunnable_showing() {
126        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
127        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
128
129        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
130    }
131
132    @Test
133    public void executeRunnableDismissingKeyguard_nullRunnable_notShowing() {
134        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
135        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
136
137        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
138    }
139
140    @Test
141    public void lockscreenStateMetrics_notShowing() {
142        // uninteresting state, except that fingerprint must be non-zero
143        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
144        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
145        // interesting state
146        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
147        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
148        when(mUnlockMethodCache.isMethodSecure()).thenReturn(false);
149        mStatusBar.onKeyguardViewManagerStatesUpdated();
150
151        MetricsAsserts.assertHasLog("missing hidden insecure lockscreen log",
152                mMetricsLogger.getLogs(),
153                new LogMaker(MetricsEvent.LOCKSCREEN)
154                        .setType(MetricsEvent.TYPE_CLOSE)
155                        .setSubtype(0));
156    }
157
158    @Test
159    public void lockscreenStateMetrics_notShowing_secure() {
160        // uninteresting state, except that fingerprint must be non-zero
161        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
162        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
163        // interesting state
164        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
165        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
166        when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
167
168        mStatusBar.onKeyguardViewManagerStatesUpdated();
169
170        MetricsAsserts.assertHasLog("missing hidden secure lockscreen log",
171                mMetricsLogger.getLogs(),
172                new LogMaker(MetricsEvent.LOCKSCREEN)
173                        .setType(MetricsEvent.TYPE_CLOSE)
174                        .setSubtype(1));
175    }
176
177    @Test
178    public void lockscreenStateMetrics_isShowing() {
179        // uninteresting state, except that fingerprint must be non-zero
180        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
181        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
182        // interesting state
183        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
184        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
185        when(mUnlockMethodCache.isMethodSecure()).thenReturn(false);
186
187        mStatusBar.onKeyguardViewManagerStatesUpdated();
188
189        MetricsAsserts.assertHasLog("missing insecure lockscreen showing",
190                mMetricsLogger.getLogs(),
191                new LogMaker(MetricsEvent.LOCKSCREEN)
192                        .setType(MetricsEvent.TYPE_OPEN)
193                        .setSubtype(0));
194    }
195
196    @Test
197    public void lockscreenStateMetrics_isShowing_secure() {
198        // uninteresting state, except that fingerprint must be non-zero
199        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
200        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
201        // interesting state
202        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
203        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
204        when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
205
206        mStatusBar.onKeyguardViewManagerStatesUpdated();
207
208        MetricsAsserts.assertHasLog("missing secure lockscreen showing log",
209                mMetricsLogger.getLogs(),
210                new LogMaker(MetricsEvent.LOCKSCREEN)
211                        .setType(MetricsEvent.TYPE_OPEN)
212                        .setSubtype(1));
213    }
214
215    @Test
216    public void lockscreenStateMetrics_isShowingBouncer() {
217        // uninteresting state, except that fingerprint must be non-zero
218        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
219        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
220        // interesting state
221        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
222        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
223        when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
224
225        mStatusBar.onKeyguardViewManagerStatesUpdated();
226
227        MetricsAsserts.assertHasLog("missing bouncer log",
228                mMetricsLogger.getLogs(),
229                new LogMaker(MetricsEvent.BOUNCER)
230                        .setType(MetricsEvent.TYPE_OPEN)
231                        .setSubtype(1));
232    }
233
234    @Test
235    public void onActivatedMetrics() {
236        ActivatableNotificationView view =  mock(ActivatableNotificationView.class);
237        mStatusBar.onActivated(view);
238
239        MetricsAsserts.assertHasLog("missing lockscreen note tap log",
240                mMetricsLogger.getLogs(),
241                new LogMaker(MetricsEvent.ACTION_LS_NOTE)
242                        .setType(MetricsEvent.TYPE_ACTION));
243    }
244
245    @Test
246    public void testShouldPeek_nonSuppressedGroupSummary() {
247        when(mPowerManager.isScreenOn()).thenReturn(true);
248        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
249        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
250        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
251        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
252        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
253
254        Notification n = new Notification.Builder(getContext(), "a")
255                .setGroup("a")
256                .setGroupSummary(true)
257                .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
258                .build();
259        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
260                UserHandle.of(0), null, 0);
261        NotificationData.Entry entry = new NotificationData.Entry(sbn);
262
263        assertTrue(mStatusBar.shouldPeek(entry, sbn));
264    }
265
266    @Test
267    public void testShouldPeek_suppressedGroupSummary() {
268        when(mPowerManager.isScreenOn()).thenReturn(true);
269        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
270        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
271        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
272        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
273        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
274
275        Notification n = new Notification.Builder(getContext(), "a")
276                .setGroup("a")
277                .setGroupSummary(true)
278                .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN)
279                .build();
280        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
281                UserHandle.of(0), null, 0);
282        NotificationData.Entry entry = new NotificationData.Entry(sbn);
283
284        assertFalse(mStatusBar.shouldPeek(entry, sbn));
285    }
286
287    static class TestableStatusBar extends StatusBar {
288        public TestableStatusBar(StatusBarKeyguardViewManager man,
289                UnlockMethodCache unlock, KeyguardIndicationController key,
290                NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd,
291                PowerManager pm, SystemServicesProxy ssp, NotificationPanelView panelView) {
292            mStatusBarKeyguardViewManager = man;
293            mUnlockMethodCache = unlock;
294            mKeyguardIndicationController = key;
295            mStackScroller = stack;
296            mHeadsUpManager = hum;
297            mNotificationData = nd;
298            mUseHeadsUp = true;
299            mPowerManager = pm;
300            mSystemServicesProxy = ssp;
301            mNotificationPanel = panelView;
302        }
303
304        @Override
305        protected H createHandler() {
306            return null;
307        }
308    }
309}