1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 5 * except in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the 10 * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 11 * KIND, either express or implied. See the License for the specific language governing 12 * permissions and limitations under the License. 13 */ 14 15 package com.android.systemui.statusbar.phone; 16 17 import static android.view.Display.DEFAULT_DISPLAY; 18 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assert.assertTrue; 21 import static org.mockito.Mockito.mock; 22 import static org.mockito.Mockito.verify; 23 import static org.mockito.Mockito.when; 24 25 import android.app.Notification; 26 import android.app.PendingIntent; 27 import android.app.StatusBarManager; 28 import android.testing.AndroidTestingRunner; 29 import android.testing.TestableLooper; 30 import android.testing.TestableLooper.RunWithLooper; 31 32 import androidx.test.filters.SmallTest; 33 34 import com.android.internal.logging.testing.FakeMetricsLogger; 35 import com.android.systemui.InitController; 36 import com.android.systemui.SysuiTestCase; 37 import com.android.systemui.plugins.ActivityStarter; 38 import com.android.systemui.plugins.statusbar.StatusBarStateController; 39 import com.android.systemui.power.domain.interactor.PowerInteractor; 40 import com.android.systemui.settings.FakeDisplayTracker; 41 import com.android.systemui.shade.NotificationShadeWindowView; 42 import com.android.systemui.shade.QuickSettingsController; 43 import com.android.systemui.shade.ShadeController; 44 import com.android.systemui.shade.ShadeViewController; 45 import com.android.systemui.statusbar.CommandQueue; 46 import com.android.systemui.statusbar.LockscreenShadeTransitionController; 47 import com.android.systemui.statusbar.NotificationLockscreenUserManager; 48 import com.android.systemui.statusbar.NotificationMediaManager; 49 import com.android.systemui.statusbar.NotificationRemoteInputManager; 50 import com.android.systemui.statusbar.NotificationShadeWindowController; 51 import com.android.systemui.statusbar.SysuiStatusBarStateController; 52 import com.android.systemui.statusbar.notification.DynamicPrivacyController; 53 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 54 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder; 55 import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource; 56 import com.android.systemui.statusbar.notification.domain.interactor.NotificationsInteractor; 57 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider; 58 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor; 59 import com.android.systemui.statusbar.notification.row.NotificationGutsManager; 60 import com.android.systemui.statusbar.notification.stack.NotificationListContainer; 61 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout; 62 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController; 63 import com.android.systemui.statusbar.policy.KeyguardStateController; 64 65 import org.junit.Before; 66 import org.junit.Test; 67 import org.junit.runner.RunWith; 68 import org.mockito.ArgumentCaptor; 69 70 @SmallTest 71 @RunWith(AndroidTestingRunner.class) 72 @RunWithLooper() 73 public class StatusBarNotificationPresenterTest extends SysuiTestCase { 74 private StatusBarNotificationPresenter mStatusBarNotificationPresenter; 75 private final NotificationInterruptStateProvider mNotificationInterruptStateProvider = 76 mock(NotificationInterruptStateProvider.class); 77 private NotificationInterruptSuppressor mInterruptSuppressor; 78 private CommandQueue mCommandQueue; 79 private FakeMetricsLogger mMetricsLogger; 80 private final ShadeController mShadeController = mock(ShadeController.class); 81 private final NotificationsInteractor mNotificationsInteractor = 82 mock(NotificationsInteractor.class); 83 private final KeyguardStateController mKeyguardStateController = 84 mock(KeyguardStateController.class); 85 private final InitController mInitController = new InitController(); 86 87 @Before setup()88 public void setup() { 89 mMetricsLogger = new FakeMetricsLogger(); 90 mCommandQueue = new CommandQueue(mContext, new FakeDisplayTracker(mContext)); 91 mDependency.injectTestDependency(StatusBarStateController.class, 92 mock(SysuiStatusBarStateController.class)); 93 mDependency.injectTestDependency(ShadeController.class, mShadeController); 94 mDependency.injectMockDependency(NotificationRemoteInputManager.Callback.class); 95 mDependency.injectMockDependency(NotificationShadeWindowController.class); 96 97 NotificationShadeWindowView notificationShadeWindowView = 98 mock(NotificationShadeWindowView.class); 99 NotificationStackScrollLayoutController stackScrollLayoutController = 100 mock(NotificationStackScrollLayoutController.class); 101 when(stackScrollLayoutController.getView()).thenReturn( 102 mock(NotificationStackScrollLayout.class)); 103 when(notificationShadeWindowView.getResources()).thenReturn(mContext.getResources()); 104 105 ShadeViewController shadeViewController = mock(ShadeViewController.class); 106 mStatusBarNotificationPresenter = new StatusBarNotificationPresenter( 107 mContext, 108 shadeViewController, 109 mock(QuickSettingsController.class), 110 mock(HeadsUpManagerPhone.class), 111 notificationShadeWindowView, 112 mock(ActivityStarter.class), 113 stackScrollLayoutController, 114 mock(DozeScrimController.class), 115 mock(NotificationShadeWindowController.class), 116 mock(DynamicPrivacyController.class), 117 mKeyguardStateController, 118 mNotificationsInteractor, 119 mock(LockscreenShadeTransitionController.class), 120 mock(PowerInteractor.class), 121 mCommandQueue, 122 mock(NotificationLockscreenUserManager.class), 123 mock(SysuiStatusBarStateController.class), 124 mock(NotifShadeEventSource.class), 125 mock(NotificationMediaManager.class), 126 mock(NotificationGutsManager.class), 127 mInitController, 128 mNotificationInterruptStateProvider, 129 mock(NotificationRemoteInputManager.class), 130 mock(NotificationRemoteInputManager.Callback.class), 131 mock(NotificationListContainer.class)); 132 mInitController.executePostInitTasks(); 133 ArgumentCaptor<NotificationInterruptSuppressor> suppressorCaptor = 134 ArgumentCaptor.forClass(NotificationInterruptSuppressor.class); 135 verify(mNotificationInterruptStateProvider).addSuppressor(suppressorCaptor.capture()); 136 mInterruptSuppressor = suppressorCaptor.getValue(); 137 } 138 139 @Test testNoSuppressHeadsUp_default()140 public void testNoSuppressHeadsUp_default() { 141 Notification n = new Notification.Builder(getContext(), "a").build(); 142 NotificationEntry entry = new NotificationEntryBuilder() 143 .setPkg("a") 144 .setOpPkg("a") 145 .setTag("a") 146 .setNotification(n) 147 .build(); 148 149 assertFalse(mInterruptSuppressor.suppressAwakeHeadsUp(entry)); 150 } 151 152 @Test testSuppressHeadsUp_disabledStatusBar()153 public void testSuppressHeadsUp_disabledStatusBar() { 154 Notification n = new Notification.Builder(getContext(), "a").build(); 155 NotificationEntry entry = new NotificationEntryBuilder() 156 .setPkg("a") 157 .setOpPkg("a") 158 .setTag("a") 159 .setNotification(n) 160 .build(); 161 mCommandQueue.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_EXPAND, 0, 162 false /* animate */); 163 TestableLooper.get(this).processAllMessages(); 164 165 assertTrue("The panel should suppress heads up while disabled", 166 mInterruptSuppressor.suppressAwakeHeadsUp(entry)); 167 } 168 169 @Test testSuppressHeadsUp_disabledNotificationShade()170 public void testSuppressHeadsUp_disabledNotificationShade() { 171 Notification n = new Notification.Builder(getContext(), "a").build(); 172 NotificationEntry entry = new NotificationEntryBuilder() 173 .setPkg("a") 174 .setOpPkg("a") 175 .setTag("a") 176 .setNotification(n) 177 .build(); 178 mCommandQueue.disable(DEFAULT_DISPLAY, 0, StatusBarManager.DISABLE2_NOTIFICATION_SHADE, 179 false /* animate */); 180 TestableLooper.get(this).processAllMessages(); 181 182 assertTrue("The panel should suppress interruptions while notification shade " 183 + "disabled", 184 mInterruptSuppressor.suppressAwakeHeadsUp(entry)); 185 } 186 187 @Test testNoSuppressHeadsUp_FSI_nonOccludedKeyguard()188 public void testNoSuppressHeadsUp_FSI_nonOccludedKeyguard() { 189 Notification n = new Notification.Builder(getContext(), "a") 190 .setFullScreenIntent(mock(PendingIntent.class), true) 191 .build(); 192 NotificationEntry entry = new NotificationEntryBuilder() 193 .setPkg("a") 194 .setOpPkg("a") 195 .setTag("a") 196 .setNotification(n) 197 .build(); 198 199 when(mKeyguardStateController.isShowing()).thenReturn(true); 200 when(mKeyguardStateController.isOccluded()).thenReturn(false); 201 assertFalse(mInterruptSuppressor.suppressAwakeHeadsUp(entry)); 202 } 203 204 @Test testSuppressInterruptions_vrMode()205 public void testSuppressInterruptions_vrMode() { 206 Notification n = new Notification.Builder(getContext(), "a").build(); 207 NotificationEntry entry = new NotificationEntryBuilder() 208 .setPkg("a") 209 .setOpPkg("a") 210 .setTag("a") 211 .setNotification(n) 212 .build(); 213 mStatusBarNotificationPresenter.mVrMode = true; 214 215 assertTrue("Vr mode should suppress interruptions", 216 mInterruptSuppressor.suppressAwakeInterruptions(entry)); 217 } 218 219 @Test testSuppressInterruptions_statusBarAlertsDisabled()220 public void testSuppressInterruptions_statusBarAlertsDisabled() { 221 Notification n = new Notification.Builder(getContext(), "a").build(); 222 NotificationEntry entry = new NotificationEntryBuilder() 223 .setPkg("a") 224 .setOpPkg("a") 225 .setTag("a") 226 .setNotification(n) 227 .build(); 228 when(mNotificationsInteractor.areNotificationAlertsEnabled()).thenReturn(false); 229 230 assertTrue("When alerts aren't enabled, interruptions are suppressed", 231 mInterruptSuppressor.suppressInterruptions(entry)); 232 } 233 } 234