StatusBarTest.java revision 30203159f9b04a7955c4ebdbf8b61f1c754495a2
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
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        IPowerManager powerManagerService = mock(IPowerManager.class);
89        HandlerThread handlerThread = new HandlerThread("TestThread");
90        handlerThread.start();
91        mPowerManager = new PowerManager(mContext, powerManagerService,
92                new Handler(handlerThread.getLooper()));
93        when(powerManagerService.isInteractive()).thenReturn(true);
94
95        mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
96        mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
97                mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
98                mNotificationData, mPowerManager, mSystemServicesProxy);
99
100        doAnswer(invocation -> {
101            OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
102            onDismissAction.onDismiss();
103            return null;
104        }).when(mStatusBarKeyguardViewManager).dismissWithAction(any(), any(), anyBoolean());
105
106        doAnswer(invocation -> {
107            Runnable runnable = (Runnable) invocation.getArguments()[0];
108            runnable.run();
109            return null;
110        }).when(mStatusBarKeyguardViewManager).addAfterKeyguardGoneRunnable(any());
111
112        when(mStackScroller.getActivatedChild()).thenReturn(null);
113    }
114
115    @Test
116    public void executeRunnableDismissingKeyguard_nullRunnable_showingAndOccluded() {
117        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
118        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(true);
119
120        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
121    }
122
123    @Test
124    public void executeRunnableDismissingKeyguard_nullRunnable_showing() {
125        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
126        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
127
128        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
129    }
130
131    @Test
132    public void executeRunnableDismissingKeyguard_nullRunnable_notShowing() {
133        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
134        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
135
136        mStatusBar.executeRunnableDismissingKeyguard(null, null, false, false, false);
137    }
138
139    @Test
140    public void lockscreenStateMetrics_notShowing() {
141        // uninteresting state, except that fingerprint must be non-zero
142        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
143        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
144        // interesting state
145        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
146        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
147        when(mUnlockMethodCache.isMethodSecure()).thenReturn(false);
148        mStatusBar.onKeyguardViewManagerStatesUpdated();
149
150        MetricsAsserts.assertHasLog("missing hidden insecure lockscreen log",
151                mMetricsLogger.getLogs(),
152                new LogMaker(MetricsEvent.LOCKSCREEN)
153                        .setType(MetricsEvent.TYPE_CLOSE)
154                        .setSubtype(0));
155    }
156
157    @Test
158    public void lockscreenStateMetrics_notShowing_secure() {
159        // uninteresting state, except that fingerprint must be non-zero
160        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
161        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
162        // interesting state
163        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(false);
164        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
165        when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
166
167        mStatusBar.onKeyguardViewManagerStatesUpdated();
168
169        MetricsAsserts.assertHasLog("missing hidden secure lockscreen log",
170                mMetricsLogger.getLogs(),
171                new LogMaker(MetricsEvent.LOCKSCREEN)
172                        .setType(MetricsEvent.TYPE_CLOSE)
173                        .setSubtype(1));
174    }
175
176    @Test
177    public void lockscreenStateMetrics_isShowing() {
178        // uninteresting state, except that fingerprint must be non-zero
179        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
180        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
181        // interesting state
182        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
183        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
184        when(mUnlockMethodCache.isMethodSecure()).thenReturn(false);
185
186        mStatusBar.onKeyguardViewManagerStatesUpdated();
187
188        MetricsAsserts.assertHasLog("missing insecure lockscreen showing",
189                mMetricsLogger.getLogs(),
190                new LogMaker(MetricsEvent.LOCKSCREEN)
191                        .setType(MetricsEvent.TYPE_OPEN)
192                        .setSubtype(0));
193    }
194
195    @Test
196    public void lockscreenStateMetrics_isShowing_secure() {
197        // uninteresting state, except that fingerprint must be non-zero
198        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
199        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
200        // interesting state
201        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
202        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false);
203        when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
204
205        mStatusBar.onKeyguardViewManagerStatesUpdated();
206
207        MetricsAsserts.assertHasLog("missing secure lockscreen showing log",
208                mMetricsLogger.getLogs(),
209                new LogMaker(MetricsEvent.LOCKSCREEN)
210                        .setType(MetricsEvent.TYPE_OPEN)
211                        .setSubtype(1));
212    }
213
214    @Test
215    public void lockscreenStateMetrics_isShowingBouncer() {
216        // uninteresting state, except that fingerprint must be non-zero
217        when(mStatusBarKeyguardViewManager.isOccluded()).thenReturn(false);
218        when(mUnlockMethodCache.canSkipBouncer()).thenReturn(true);
219        // interesting state
220        when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
221        when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(true);
222        when(mUnlockMethodCache.isMethodSecure()).thenReturn(true);
223
224        mStatusBar.onKeyguardViewManagerStatesUpdated();
225
226        MetricsAsserts.assertHasLog("missing bouncer log",
227                mMetricsLogger.getLogs(),
228                new LogMaker(MetricsEvent.BOUNCER)
229                        .setType(MetricsEvent.TYPE_OPEN)
230                        .setSubtype(1));
231    }
232
233    @Test
234    public void onActivatedMetrics() {
235        ActivatableNotificationView view =  mock(ActivatableNotificationView.class);
236        mStatusBar.onActivated(view);
237
238        MetricsAsserts.assertHasLog("missing lockscreen note tap log",
239                mMetricsLogger.getLogs(),
240                new LogMaker(MetricsEvent.ACTION_LS_NOTE)
241                        .setType(MetricsEvent.TYPE_ACTION));
242    }
243
244    @Test
245    public void testShouldPeek_nonSuppressedGroupSummary() {
246        when(mPowerManager.isScreenOn()).thenReturn(true);
247        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
248        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
249        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
250        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
251        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
252
253        Notification n = new Notification.Builder(getContext(), "a")
254                .setGroup("a")
255                .setGroupSummary(true)
256                .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
257                .build();
258        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
259                UserHandle.of(0), null, 0);
260        NotificationData.Entry entry = new NotificationData.Entry(sbn);
261
262        assertTrue(mStatusBar.shouldPeek(entry, sbn));
263    }
264
265    @Test
266    public void testShouldPeek_suppressedGroupSummary() {
267        when(mPowerManager.isScreenOn()).thenReturn(true);
268        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
269        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
270        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
271        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
272        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
273
274        Notification n = new Notification.Builder(getContext(), "a")
275                .setGroup("a")
276                .setGroupSummary(true)
277                .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN)
278                .build();
279        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
280                UserHandle.of(0), null, 0);
281        NotificationData.Entry entry = new NotificationData.Entry(sbn);
282
283        assertFalse(mStatusBar.shouldPeek(entry, sbn));
284    }
285
286    static class TestableStatusBar extends StatusBar {
287        public TestableStatusBar(StatusBarKeyguardViewManager man,
288                UnlockMethodCache unlock, KeyguardIndicationController key,
289                NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd,
290                PowerManager pm, SystemServicesProxy ssp) {
291            mStatusBarKeyguardViewManager = man;
292            mUnlockMethodCache = unlock;
293            mKeyguardIndicationController = key;
294            mStackScroller = stack;
295            mHeadsUpManager = hum;
296            mNotificationData = nd;
297            mUseHeadsUp = true;
298            mPowerManager = pm;
299            mSystemServicesProxy = ssp;
300        }
301
302        @Override
303        protected H createHandler() {
304            return null;
305        }
306    }
307}