1 /* 2 * Copyright (C) 2019 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.notification.collection.coordinator; 18 19 import static android.app.Notification.VISIBILITY_PUBLIC; 20 import static android.app.Notification.VISIBILITY_SECRET; 21 import static android.app.NotificationManager.IMPORTANCE_HIGH; 22 import static android.app.NotificationManager.IMPORTANCE_MIN; 23 24 import static com.android.systemui.statusbar.notification.collection.EntryUtilKt.modifyEntry; 25 26 import static org.junit.Assert.assertFalse; 27 import static org.junit.Assert.assertTrue; 28 import static org.mockito.Mockito.times; 29 import static org.mockito.Mockito.verify; 30 import static org.mockito.Mockito.when; 31 32 import android.os.Handler; 33 import android.os.UserHandle; 34 import android.testing.AndroidTestingRunner; 35 36 import androidx.test.filters.SmallTest; 37 38 import com.android.keyguard.KeyguardUpdateMonitor; 39 import com.android.systemui.SysuiTestCase; 40 import com.android.systemui.broadcast.BroadcastDispatcher; 41 import com.android.systemui.plugins.statusbar.StatusBarStateController; 42 import com.android.systemui.statusbar.NotificationLockscreenUserManager; 43 import com.android.systemui.statusbar.RankingBuilder; 44 import com.android.systemui.statusbar.notification.collection.GroupEntry; 45 import com.android.systemui.statusbar.notification.collection.GroupEntryBuilder; 46 import com.android.systemui.statusbar.notification.collection.NotifPipeline; 47 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 48 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; 49 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter; 50 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; 51 import com.android.systemui.statusbar.policy.KeyguardStateController; 52 53 import org.junit.Before; 54 import org.junit.Test; 55 import org.junit.runner.RunWith; 56 import org.mockito.ArgumentCaptor; 57 import org.mockito.Mock; 58 import org.mockito.MockitoAnnotations; 59 60 @SmallTest 61 @RunWith(AndroidTestingRunner.class) 62 public class KeyguardCoordinatorTest extends SysuiTestCase { 63 private static final int NOTIF_USER_ID = 0; 64 private static final int CURR_USER_ID = 1; 65 66 @Mock private Handler mMainHandler; 67 @Mock private KeyguardStateController mKeyguardStateController; 68 @Mock private NotificationLockscreenUserManager mLockscreenUserManager; 69 @Mock private BroadcastDispatcher mBroadcastDispatcher; 70 @Mock private StatusBarStateController mStatusBarStateController; 71 @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; 72 @Mock private HighPriorityProvider mHighPriorityProvider; 73 @Mock private NotifPipeline mNotifPipeline; 74 75 private NotificationEntry mEntry; 76 private NotifFilter mKeyguardFilter; 77 78 @Before setup()79 public void setup() { 80 MockitoAnnotations.initMocks(this); 81 KeyguardCoordinator keyguardCoordinator = new KeyguardCoordinator( 82 mContext, mMainHandler, mKeyguardStateController, mLockscreenUserManager, 83 mBroadcastDispatcher, mStatusBarStateController, 84 mKeyguardUpdateMonitor, mHighPriorityProvider); 85 86 mEntry = new NotificationEntryBuilder() 87 .setUser(new UserHandle(NOTIF_USER_ID)) 88 .build(); 89 90 ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class); 91 keyguardCoordinator.attach(mNotifPipeline); 92 verify(mNotifPipeline, times(1)).addFinalizeFilter(filterCaptor.capture()); 93 mKeyguardFilter = filterCaptor.getValue(); 94 } 95 96 @Test unfilteredState()97 public void unfilteredState() { 98 // GIVEN an 'unfiltered-keyguard-showing' state 99 setupUnfilteredState(mEntry); 100 101 // THEN don't filter out the entry 102 assertFalse(mKeyguardFilter.shouldFilterOut(mEntry, 0)); 103 } 104 105 @Test keyguardNotShowing()106 public void keyguardNotShowing() { 107 // GIVEN the lockscreen isn't showing 108 setupUnfilteredState(mEntry); 109 when(mKeyguardStateController.isShowing()).thenReturn(false); 110 111 // THEN don't filter out the entry 112 assertFalse(mKeyguardFilter.shouldFilterOut(mEntry, 0)); 113 } 114 115 @Test doNotShowLockscreenNotifications()116 public void doNotShowLockscreenNotifications() { 117 // GIVEN an 'unfiltered-keyguard-showing' state 118 setupUnfilteredState(mEntry); 119 120 // WHEN we shouldn't show any lockscreen notifications 121 when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false); 122 123 // THEN filter out the entry 124 assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); 125 } 126 127 @Test lockdown()128 public void lockdown() { 129 // GIVEN an 'unfiltered-keyguard-showing' state 130 setupUnfilteredState(mEntry); 131 132 // WHEN the notification's user is in lockdown: 133 when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(true); 134 135 // THEN filter out the entry 136 assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); 137 } 138 139 @Test publicMode_settingsDisallow()140 public void publicMode_settingsDisallow() { 141 // GIVEN an 'unfiltered-keyguard-showing' state 142 setupUnfilteredState(mEntry); 143 144 // WHEN the notification's user is in public mode and settings are configured to disallow 145 // notifications in public mode 146 when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(true); 147 when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID)) 148 .thenReturn(false); 149 150 // THEN filter out the entry 151 assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); 152 } 153 154 @Test publicMode_notifDisallowed()155 public void publicMode_notifDisallowed() { 156 // GIVEN an 'unfiltered-keyguard-showing' state 157 setupUnfilteredState(mEntry); 158 159 // WHEN the notification's user is in public mode and settings are configured to disallow 160 // notifications in public mode 161 when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(true); 162 mEntry.setRanking(new RankingBuilder() 163 .setKey(mEntry.getKey()) 164 .setVisibilityOverride(VISIBILITY_SECRET).build()); 165 166 // THEN filter out the entry 167 assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); 168 } 169 170 @Test doesNotExceedThresholdToShow()171 public void doesNotExceedThresholdToShow() { 172 // GIVEN an 'unfiltered-keyguard-showing' state 173 setupUnfilteredState(mEntry); 174 175 // WHEN the notification doesn't exceed the threshold to show on the lockscreen 176 mEntry.setRanking(new RankingBuilder() 177 .setKey(mEntry.getKey()) 178 .setImportance(IMPORTANCE_MIN) 179 .build()); 180 when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(false); 181 182 // THEN filter out the entry 183 assertTrue(mKeyguardFilter.shouldFilterOut(mEntry, 0)); 184 } 185 186 @Test summaryExceedsThresholdToShow()187 public void summaryExceedsThresholdToShow() { 188 // GIVEN the notification doesn't exceed the threshold to show on the lockscreen 189 // but it's part of a group (has a parent) 190 final NotificationEntry entryWithParent = new NotificationEntryBuilder() 191 .setUser(new UserHandle(NOTIF_USER_ID)) 192 .build(); 193 194 final GroupEntry parent = new GroupEntryBuilder() 195 .setKey("test_group_key") 196 .setSummary(new NotificationEntryBuilder() 197 .setImportance(IMPORTANCE_HIGH) 198 .build()) 199 .addChild(entryWithParent) 200 .build(); 201 202 setupUnfilteredState(entryWithParent); 203 entryWithParent.setRanking(new RankingBuilder() 204 .setKey(entryWithParent.getKey()) 205 .setImportance(IMPORTANCE_MIN) 206 .build()); 207 208 // WHEN its parent does exceed threshold tot show on the lockscreen 209 when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(true); 210 211 // THEN don't filter out the entry 212 assertFalse(mKeyguardFilter.shouldFilterOut(entryWithParent, 0)); 213 214 // WHEN its parent doesn't exceed threshold to show on lockscreen 215 when(mHighPriorityProvider.isHighPriority(parent)).thenReturn(false); 216 modifyEntry(parent.getSummary(), builder -> builder 217 .setImportance(IMPORTANCE_MIN) 218 .done()); 219 220 // THEN filter out the entry 221 assertTrue(mKeyguardFilter.shouldFilterOut(entryWithParent, 0)); 222 } 223 224 /** 225 * setup a state where the notification will not be filtered by the 226 * KeyguardNotificationCoordinator when the keyguard is showing. 227 */ setupUnfilteredState(NotificationEntry entry)228 private void setupUnfilteredState(NotificationEntry entry) { 229 // keyguard is showing 230 when(mKeyguardStateController.isShowing()).thenReturn(true); 231 232 // show notifications on the lockscreen 233 when(mLockscreenUserManager.shouldShowLockscreenNotifications()).thenReturn(true); 234 235 // neither the current user nor the notification's user is in lockdown 236 when(mLockscreenUserManager.getCurrentUserId()).thenReturn(CURR_USER_ID); 237 when(mKeyguardUpdateMonitor.isUserInLockdown(NOTIF_USER_ID)).thenReturn(false); 238 when(mKeyguardUpdateMonitor.isUserInLockdown(CURR_USER_ID)).thenReturn(false); 239 240 // not in public mode 241 when(mLockscreenUserManager.isLockscreenPublicMode(CURR_USER_ID)).thenReturn(false); 242 when(mLockscreenUserManager.isLockscreenPublicMode(NOTIF_USER_ID)).thenReturn(false); 243 244 // entry's ranking - should show on all lockscreens 245 // + priority of the notification exceeds the threshold to be shown on the lockscreen 246 entry.setRanking(new RankingBuilder() 247 .setKey(mEntry.getKey()) 248 .setVisibilityOverride(VISIBILITY_PUBLIC) 249 .setImportance(IMPORTANCE_HIGH) 250 .build()); 251 252 // settings allows notifications in public mode 253 when(mLockscreenUserManager.userAllowsNotificationsInPublic(CURR_USER_ID)).thenReturn(true); 254 when(mLockscreenUserManager.userAllowsNotificationsInPublic(NOTIF_USER_ID)) 255 .thenReturn(true); 256 257 // notification doesn't have a summary 258 259 // notification is high priority, so it shouldn't be filtered 260 when(mHighPriorityProvider.isHighPriority(mEntry)).thenReturn(true); 261 } 262 } 263