1 /* 2 * Copyright (C) 2018 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.row; 18 19 import static android.app.AppOpsManager.OP_CAMERA; 20 import static android.app.AppOpsManager.OP_RECORD_AUDIO; 21 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; 22 import static android.app.NotificationManager.IMPORTANCE_DEFAULT; 23 import static android.app.NotificationManager.IMPORTANCE_HIGH; 24 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; 25 26 import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanking; 27 28 import static junit.framework.Assert.assertNotNull; 29 import static junit.framework.Assert.assertTrue; 30 31 import static kotlinx.coroutines.test.TestCoroutineDispatchersKt.StandardTestDispatcher; 32 33 import static org.junit.Assert.assertEquals; 34 import static org.junit.Assert.fail; 35 import static org.mockito.ArgumentMatchers.any; 36 import static org.mockito.ArgumentMatchers.anyBoolean; 37 import static org.mockito.ArgumentMatchers.anyInt; 38 import static org.mockito.ArgumentMatchers.eq; 39 import static org.mockito.Mockito.doNothing; 40 import static org.mockito.Mockito.mock; 41 import static org.mockito.Mockito.never; 42 import static org.mockito.Mockito.spy; 43 import static org.mockito.Mockito.times; 44 import static org.mockito.Mockito.verify; 45 import static org.mockito.Mockito.when; 46 47 import android.app.INotificationManager; 48 import android.app.Notification; 49 import android.app.NotificationChannel; 50 import android.content.Intent; 51 import android.content.pm.LauncherApps; 52 import android.content.pm.PackageManager; 53 import android.content.pm.ShortcutManager; 54 import android.graphics.Color; 55 import android.os.Binder; 56 import android.os.Handler; 57 import android.os.UserManager; 58 import android.provider.Settings; 59 import android.service.notification.StatusBarNotification; 60 import android.testing.TestableLooper; 61 import android.util.ArraySet; 62 import android.view.View; 63 import android.view.accessibility.AccessibilityManager; 64 65 import androidx.test.ext.junit.runners.AndroidJUnit4; 66 import androidx.test.filters.SmallTest; 67 68 import com.android.internal.logging.MetricsLogger; 69 import com.android.internal.logging.UiEventLogger; 70 import com.android.internal.logging.testing.UiEventLoggerFake; 71 import com.android.internal.statusbar.IStatusBarService; 72 import com.android.systemui.SysuiTestCase; 73 import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository; 74 import com.android.systemui.kosmos.KosmosJavaAdapter; 75 import com.android.systemui.people.widget.PeopleSpaceWidgetManager; 76 import com.android.systemui.plugins.ActivityStarter; 77 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin; 78 import com.android.systemui.plugins.statusbar.StatusBarStateController; 79 import com.android.systemui.power.domain.interactor.PowerInteractorFactory; 80 import com.android.systemui.scene.data.repository.WindowRootViewVisibilityRepository; 81 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor; 82 import com.android.systemui.settings.UserContextProvider; 83 import com.android.systemui.shade.ShadeController; 84 import com.android.systemui.statusbar.NotificationLockscreenUserManager; 85 import com.android.systemui.statusbar.NotificationPresenter; 86 import com.android.systemui.statusbar.notification.AssistantFeedbackController; 87 import com.android.systemui.statusbar.notification.NotificationActivityStarter; 88 import com.android.systemui.statusbar.notification.collection.NotificationEntry; 89 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider; 90 import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository; 91 import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor; 92 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier; 93 import com.android.systemui.statusbar.notification.row.NotificationGutsManager.OnSettingsClickListener; 94 import com.android.systemui.statusbar.notification.stack.NotificationListContainer; 95 import com.android.systemui.statusbar.policy.DeviceProvisionedController; 96 import com.android.systemui.statusbar.policy.HeadsUpManager; 97 import com.android.systemui.util.concurrency.FakeExecutor; 98 import com.android.systemui.util.kotlin.JavaAdapter; 99 import com.android.systemui.wmshell.BubblesManager; 100 101 import kotlinx.coroutines.test.TestScope; 102 103 import org.junit.Before; 104 import org.junit.Rule; 105 import org.junit.Test; 106 import org.junit.runner.RunWith; 107 import org.mockito.ArgumentCaptor; 108 import org.mockito.Mock; 109 import org.mockito.junit.MockitoJUnit; 110 import org.mockito.junit.MockitoRule; 111 112 import java.util.Optional; 113 114 /** 115 * Tests for {@link NotificationGutsManager}. 116 */ 117 @SmallTest 118 @RunWith(AndroidJUnit4.class) 119 @TestableLooper.RunWithLooper 120 public class NotificationGutsManagerTest extends SysuiTestCase { 121 private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId"; 122 123 private NotificationChannel mTestNotificationChannel = new NotificationChannel( 124 TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT); 125 126 private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this); 127 private final TestScope mTestScope = mKosmos.getTestScope(); 128 private final JavaAdapter mJavaAdapter = new JavaAdapter(mTestScope.getBackgroundScope()); 129 private final FakeExecutor mExecutor = mKosmos.getFakeExecutor(); 130 private final Handler mHandler = mKosmos.getFakeExecutorHandler(); 131 private NotificationTestHelper mHelper; 132 private NotificationGutsManager mGutsManager; 133 134 @Rule public MockitoRule mockito = MockitoJUnit.rule(); 135 @Mock private MetricsLogger mMetricsLogger; 136 @Mock private OnUserInteractionCallback mOnUserInteractionCallback; 137 @Mock private NotificationPresenter mPresenter; 138 @Mock private NotificationActivityStarter mNotificationActivityStarter; 139 @Mock private NotificationListContainer mNotificationListContainer; 140 @Mock private OnSettingsClickListener mOnSettingsClickListener; 141 @Mock private DeviceProvisionedController mDeviceProvisionedController; 142 @Mock private AccessibilityManager mAccessibilityManager; 143 @Mock private HighPriorityProvider mHighPriorityProvider; 144 @Mock private INotificationManager mINotificationManager; 145 @Mock private IStatusBarService mBarService; 146 @Mock private LauncherApps mLauncherApps; 147 @Mock private ShortcutManager mShortcutManager; 148 @Mock private ChannelEditorDialogController mChannelEditorDialogController; 149 @Mock private PeopleNotificationIdentifier mPeopleNotificationIdentifier; 150 @Mock private UserContextProvider mContextTracker; 151 @Mock private BubblesManager mBubblesManager; 152 @Mock private ShadeController mShadeController; 153 @Mock private PeopleSpaceWidgetManager mPeopleSpaceWidgetManager; 154 @Mock private AssistantFeedbackController mAssistantFeedbackController; 155 @Mock private NotificationLockscreenUserManager mNotificationLockscreenUserManager; 156 @Mock private StatusBarStateController mStatusBarStateController; 157 @Mock private HeadsUpManager mHeadsUpManager; 158 @Mock private ActivityStarter mActivityStarter; 159 160 @Mock private UserManager mUserManager; 161 162 private final ActiveNotificationListRepository mActiveNotificationListRepository = 163 new ActiveNotificationListRepository(); 164 private final ActiveNotificationsInteractor mActiveNotificationsInteractor = 165 new ActiveNotificationsInteractor(mActiveNotificationListRepository, 166 StandardTestDispatcher(null, null)); 167 168 private WindowRootViewVisibilityInteractor mWindowRootViewVisibilityInteractor; 169 170 @Before setUp()171 public void setUp() { 172 allowTestableLooperAsMainThread(); 173 mHelper = new NotificationTestHelper(mContext, mDependency); 174 when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false); 175 176 mWindowRootViewVisibilityInteractor = new WindowRootViewVisibilityInteractor( 177 mTestScope.getBackgroundScope(), 178 new WindowRootViewVisibilityRepository(mBarService, mExecutor), 179 new FakeKeyguardRepository(), 180 mHeadsUpManager, 181 PowerInteractorFactory.create().getPowerInteractor(), 182 mActiveNotificationsInteractor, 183 () -> mKosmos.getSceneInteractor() 184 ); 185 186 mGutsManager = new NotificationGutsManager( 187 mContext, 188 mHandler, 189 mHandler, 190 mJavaAdapter, 191 mAccessibilityManager, 192 mHighPriorityProvider, 193 mINotificationManager, 194 mUserManager, 195 mPeopleSpaceWidgetManager, 196 mLauncherApps, 197 mShortcutManager, 198 mChannelEditorDialogController, 199 mContextTracker, 200 mAssistantFeedbackController, 201 Optional.of(mBubblesManager), 202 new UiEventLoggerFake(), 203 mOnUserInteractionCallback, 204 mShadeController, 205 mWindowRootViewVisibilityInteractor, 206 mNotificationLockscreenUserManager, 207 mStatusBarStateController, 208 mBarService, 209 mDeviceProvisionedController, 210 mMetricsLogger, 211 mHeadsUpManager, 212 mActivityStarter); 213 mGutsManager.setUpWithPresenter(mPresenter, mNotificationListContainer, 214 mOnSettingsClickListener); 215 mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter); 216 mGutsManager.start(); 217 } 218 219 //////////////////////////////////////////////////////////////////////////////////////////////// 220 // Test methods: 221 222 @Test testOpenAndCloseGuts()223 public void testOpenAndCloseGuts() { 224 NotificationGuts guts = spy(new NotificationGuts(mContext)); 225 when(guts.post(any())).thenAnswer(invocation -> { 226 mHandler.post(((Runnable) invocation.getArguments()[0])); 227 return null; 228 }); 229 230 // Test doesn't support animation since the guts view is not attached. 231 doNothing().when(guts).openControls( 232 anyInt(), 233 anyInt(), 234 anyBoolean(), 235 any(Runnable.class)); 236 237 ExpandableNotificationRow realRow = createTestNotificationRow(); 238 NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow); 239 240 ExpandableNotificationRow row = spy(realRow); 241 when(row.getWindowToken()).thenReturn(new Binder()); 242 when(row.getGuts()).thenReturn(guts); 243 244 assertTrue(mGutsManager.openGutsInternal(row, 0, 0, menuItem)); 245 assertEquals(View.INVISIBLE, guts.getVisibility()); 246 mExecutor.runAllReady(); 247 verify(guts).openControls( 248 anyInt(), 249 anyInt(), 250 anyBoolean(), 251 any(Runnable.class)); 252 verify(mHeadsUpManager).setGutsShown(realRow.getEntry(), true); 253 254 assertEquals(View.VISIBLE, guts.getVisibility()); 255 mGutsManager.closeAndSaveGuts(false, false, true, 0, 0, false); 256 257 verify(guts).closeControls(anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean()); 258 verify(row, times(1)).setGutsView(any()); 259 mExecutor.runAllReady(); 260 verify(mHeadsUpManager).setGutsShown(realRow.getEntry(), false); 261 } 262 263 @Test testLockscreenShadeVisible_visible_gutsNotClosed()264 public void testLockscreenShadeVisible_visible_gutsNotClosed() { 265 // First, start out lockscreen or shade as not visible 266 mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(false); 267 mTestScope.getTestScheduler().runCurrent(); 268 269 NotificationGuts guts = mock(NotificationGuts.class); 270 mGutsManager.setExposedGuts(guts); 271 272 // WHEN the lockscreen or shade becomes visible 273 mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true); 274 mTestScope.getTestScheduler().runCurrent(); 275 276 // THEN the guts are not closed 277 verify(guts, never()).removeCallbacks(any()); 278 verify(guts, never()).closeControls( 279 anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean()); 280 } 281 282 @Test testLockscreenShadeVisible_notVisible_gutsClosed()283 public void testLockscreenShadeVisible_notVisible_gutsClosed() { 284 // First, start out lockscreen or shade as visible 285 mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true); 286 mTestScope.getTestScheduler().runCurrent(); 287 288 NotificationGuts guts = mock(NotificationGuts.class); 289 mGutsManager.setExposedGuts(guts); 290 291 // WHEN the lockscreen or shade is no longer visible 292 mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(false); 293 mTestScope.getTestScheduler().runCurrent(); 294 295 // THEN the guts are closed 296 verify(guts).removeCallbacks(any()); 297 verify(guts).closeControls( 298 /* leavebehinds= */ eq(true), 299 /* controls= */ eq(true), 300 /* x= */ anyInt(), 301 /* y= */ anyInt(), 302 /* force= */ eq(true)); 303 } 304 305 @Test testLockscreenShadeVisible_notVisible_listContainerReset()306 public void testLockscreenShadeVisible_notVisible_listContainerReset() { 307 // First, start out lockscreen or shade as visible 308 mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(true); 309 mTestScope.getTestScheduler().runCurrent(); 310 311 // WHEN the lockscreen or shade is no longer visible 312 mWindowRootViewVisibilityInteractor.setIsLockscreenOrShadeVisible(false); 313 mTestScope.getTestScheduler().runCurrent(); 314 315 // THEN the list container is reset 316 verify(mNotificationListContainer).resetExposedMenuView(anyBoolean(), anyBoolean()); 317 } 318 319 @Test testChangeDensityOrFontScale()320 public void testChangeDensityOrFontScale() { 321 NotificationGuts guts = spy(new NotificationGuts(mContext)); 322 when(guts.post(any())).thenAnswer(invocation -> { 323 mHandler.post(((Runnable) invocation.getArguments()[0])); 324 return null; 325 }); 326 327 // Test doesn't support animation since the guts view is not attached. 328 doNothing().when(guts).openControls( 329 anyInt(), 330 anyInt(), 331 anyBoolean(), 332 any(Runnable.class)); 333 334 ExpandableNotificationRow realRow = createTestNotificationRow(); 335 NotificationMenuRowPlugin.MenuItem menuItem = createTestMenuItem(realRow); 336 337 ExpandableNotificationRow row = spy(realRow); 338 339 when(row.getWindowToken()).thenReturn(new Binder()); 340 when(row.getGuts()).thenReturn(guts); 341 doNothing().when(row).ensureGutsInflated(); 342 343 NotificationEntry realEntry = realRow.getEntry(); 344 NotificationEntry entry = spy(realEntry); 345 346 when(entry.getRow()).thenReturn(row); 347 when(entry.getGuts()).thenReturn(guts); 348 349 assertTrue(mGutsManager.openGutsInternal(row, 0, 0, menuItem)); 350 mExecutor.runAllReady(); 351 verify(guts).openControls( 352 anyInt(), 353 anyInt(), 354 anyBoolean(), 355 any(Runnable.class)); 356 357 // called once by mGutsManager.bindGuts() in mGutsManager.openGuts() 358 verify(row).setGutsView(any()); 359 360 row.onDensityOrFontScaleChanged(); 361 mGutsManager.onDensityOrFontScaleChanged(entry); 362 363 mExecutor.runAllReady(); 364 365 mGutsManager.closeAndSaveGuts(false, false, false, 0, 0, false); 366 367 verify(guts).closeControls(anyBoolean(), anyBoolean(), anyInt(), anyInt(), anyBoolean()); 368 369 // called again by mGutsManager.bindGuts(), in mGutsManager.onDensityOrFontScaleChanged() 370 verify(row, times(2)).setGutsView(any()); 371 } 372 373 @Test testAppOpsSettingsIntent_camera()374 public void testAppOpsSettingsIntent_camera() { 375 ArraySet<Integer> ops = new ArraySet<>(); 376 ops.add(OP_CAMERA); 377 mGutsManager.startAppOpsSettingsActivity("", 0, ops, null); 378 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 379 verify(mNotificationActivityStarter, times(1)) 380 .startNotificationGutsIntent(captor.capture(), anyInt(), any()); 381 assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction()); 382 } 383 384 @Test testAppOpsSettingsIntent_mic()385 public void testAppOpsSettingsIntent_mic() { 386 ArraySet<Integer> ops = new ArraySet<>(); 387 ops.add(OP_RECORD_AUDIO); 388 mGutsManager.startAppOpsSettingsActivity("", 0, ops, null); 389 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 390 verify(mNotificationActivityStarter, times(1)) 391 .startNotificationGutsIntent(captor.capture(), anyInt(), any()); 392 assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction()); 393 } 394 395 @Test testAppOpsSettingsIntent_camera_mic()396 public void testAppOpsSettingsIntent_camera_mic() { 397 ArraySet<Integer> ops = new ArraySet<>(); 398 ops.add(OP_CAMERA); 399 ops.add(OP_RECORD_AUDIO); 400 mGutsManager.startAppOpsSettingsActivity("", 0, ops, null); 401 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 402 verify(mNotificationActivityStarter, times(1)) 403 .startNotificationGutsIntent(captor.capture(), anyInt(), any()); 404 assertEquals(Intent.ACTION_MANAGE_APP_PERMISSIONS, captor.getValue().getAction()); 405 } 406 407 @Test testAppOpsSettingsIntent_overlay()408 public void testAppOpsSettingsIntent_overlay() { 409 ArraySet<Integer> ops = new ArraySet<>(); 410 ops.add(OP_SYSTEM_ALERT_WINDOW); 411 mGutsManager.startAppOpsSettingsActivity("", 0, ops, null); 412 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 413 verify(mNotificationActivityStarter, times(1)) 414 .startNotificationGutsIntent(captor.capture(), anyInt(), any()); 415 assertEquals(Settings.ACTION_MANAGE_APP_OVERLAY_PERMISSION, captor.getValue().getAction()); 416 } 417 418 @Test testAppOpsSettingsIntent_camera_mic_overlay()419 public void testAppOpsSettingsIntent_camera_mic_overlay() { 420 ArraySet<Integer> ops = new ArraySet<>(); 421 ops.add(OP_CAMERA); 422 ops.add(OP_RECORD_AUDIO); 423 ops.add(OP_SYSTEM_ALERT_WINDOW); 424 mGutsManager.startAppOpsSettingsActivity("", 0, ops, null); 425 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 426 verify(mNotificationActivityStarter, times(1)) 427 .startNotificationGutsIntent(captor.capture(), anyInt(), any()); 428 assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction()); 429 } 430 431 @Test testAppOpsSettingsIntent_camera_overlay()432 public void testAppOpsSettingsIntent_camera_overlay() { 433 ArraySet<Integer> ops = new ArraySet<>(); 434 ops.add(OP_CAMERA); 435 ops.add(OP_SYSTEM_ALERT_WINDOW); 436 mGutsManager.startAppOpsSettingsActivity("", 0, ops, null); 437 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 438 verify(mNotificationActivityStarter, times(1)) 439 .startNotificationGutsIntent(captor.capture(), anyInt(), any()); 440 assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction()); 441 } 442 443 @Test testAppOpsSettingsIntent_mic_overlay()444 public void testAppOpsSettingsIntent_mic_overlay() { 445 ArraySet<Integer> ops = new ArraySet<>(); 446 ops.add(OP_RECORD_AUDIO); 447 ops.add(OP_SYSTEM_ALERT_WINDOW); 448 mGutsManager.startAppOpsSettingsActivity("", 0, ops, null); 449 ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class); 450 verify(mNotificationActivityStarter, times(1)) 451 .startNotificationGutsIntent(captor.capture(), anyInt(), any()); 452 assertEquals(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, captor.getValue().getAction()); 453 } 454 455 @Test testInitializeNotificationInfoView_highPriority()456 public void testInitializeNotificationInfoView_highPriority() throws Exception { 457 NotificationInfo notificationInfoView = mock(NotificationInfo.class); 458 ExpandableNotificationRow row = spy(mHelper.createRow()); 459 final NotificationEntry entry = row.getEntry(); 460 modifyRanking(entry) 461 .setUserSentiment(USER_SENTIMENT_NEGATIVE) 462 .setImportance(IMPORTANCE_HIGH) 463 .build(); 464 465 when(row.getIsNonblockable()).thenReturn(false); 466 when(mHighPriorityProvider.isHighPriority(entry)).thenReturn(true); 467 StatusBarNotification statusBarNotification = entry.getSbn(); 468 mGutsManager.initializeNotificationInfo(row, notificationInfoView); 469 470 verify(notificationInfoView).bindNotification( 471 any(PackageManager.class), 472 any(INotificationManager.class), 473 eq(mOnUserInteractionCallback), 474 eq(mChannelEditorDialogController), 475 eq(statusBarNotification.getPackageName()), 476 any(NotificationChannel.class), 477 eq(entry), 478 any(NotificationInfo.OnSettingsClickListener.class), 479 any(NotificationInfo.OnAppSettingsClickListener.class), 480 any(UiEventLogger.class), 481 eq(false), 482 eq(false), 483 eq(true), /* wasShownHighPriority */ 484 eq(mAssistantFeedbackController), 485 any(MetricsLogger.class)); 486 } 487 488 @Test testInitializeNotificationInfoView_PassesAlongProvisionedState()489 public void testInitializeNotificationInfoView_PassesAlongProvisionedState() throws Exception { 490 NotificationInfo notificationInfoView = mock(NotificationInfo.class); 491 ExpandableNotificationRow row = spy(mHelper.createRow()); 492 modifyRanking(row.getEntry()) 493 .setUserSentiment(USER_SENTIMENT_NEGATIVE) 494 .build(); 495 when(row.getIsNonblockable()).thenReturn(false); 496 StatusBarNotification statusBarNotification = row.getEntry().getSbn(); 497 NotificationEntry entry = row.getEntry(); 498 499 when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true); 500 501 mGutsManager.initializeNotificationInfo(row, notificationInfoView); 502 503 verify(notificationInfoView).bindNotification( 504 any(PackageManager.class), 505 any(INotificationManager.class), 506 eq(mOnUserInteractionCallback), 507 eq(mChannelEditorDialogController), 508 eq(statusBarNotification.getPackageName()), 509 any(NotificationChannel.class), 510 eq(entry), 511 any(NotificationInfo.OnSettingsClickListener.class), 512 any(NotificationInfo.OnAppSettingsClickListener.class), 513 any(UiEventLogger.class), 514 eq(true), 515 eq(false), 516 eq(false), /* wasShownHighPriority */ 517 eq(mAssistantFeedbackController), 518 any(MetricsLogger.class)); 519 } 520 521 @Test testInitializeNotificationInfoView_withInitialAction()522 public void testInitializeNotificationInfoView_withInitialAction() throws Exception { 523 NotificationInfo notificationInfoView = mock(NotificationInfo.class); 524 ExpandableNotificationRow row = spy(mHelper.createRow()); 525 modifyRanking(row.getEntry()) 526 .setUserSentiment(USER_SENTIMENT_NEGATIVE) 527 .build(); 528 when(row.getIsNonblockable()).thenReturn(false); 529 StatusBarNotification statusBarNotification = row.getEntry().getSbn(); 530 NotificationEntry entry = row.getEntry(); 531 532 mGutsManager.initializeNotificationInfo(row, notificationInfoView); 533 534 verify(notificationInfoView).bindNotification( 535 any(PackageManager.class), 536 any(INotificationManager.class), 537 eq(mOnUserInteractionCallback), 538 eq(mChannelEditorDialogController), 539 eq(statusBarNotification.getPackageName()), 540 any(NotificationChannel.class), 541 eq(entry), 542 any(NotificationInfo.OnSettingsClickListener.class), 543 any(NotificationInfo.OnAppSettingsClickListener.class), 544 any(UiEventLogger.class), 545 eq(false), 546 eq(false), 547 eq(false), /* wasShownHighPriority */ 548 eq(mAssistantFeedbackController), 549 any(MetricsLogger.class)); 550 } 551 552 //////////////////////////////////////////////////////////////////////////////////////////////// 553 // Utility methods: 554 createTestNotificationRow()555 private ExpandableNotificationRow createTestNotificationRow() { 556 Notification.Builder nb = new Notification.Builder(mContext, 557 mTestNotificationChannel.getId()) 558 .setContentTitle("foo") 559 .setColorized(true).setColor(Color.RED) 560 .setFlag(Notification.FLAG_CAN_COLORIZE, true) 561 .setSmallIcon(android.R.drawable.sym_def_app_icon); 562 563 try { 564 ExpandableNotificationRow row = mHelper.createRow(nb.build()); 565 modifyRanking(row.getEntry()) 566 .setChannel(mTestNotificationChannel) 567 .build(); 568 return row; 569 } catch (Exception e) { 570 fail(); 571 return null; 572 } 573 } 574 createTestMenuItem(ExpandableNotificationRow row)575 private NotificationMenuRowPlugin.MenuItem createTestMenuItem(ExpandableNotificationRow row) { 576 NotificationMenuRowPlugin menuRow = 577 new NotificationMenuRow(mContext, mPeopleNotificationIdentifier); 578 menuRow.createMenu(row, row.getEntry().getSbn()); 579 580 NotificationMenuRowPlugin.MenuItem menuItem = menuRow.getLongpressMenuItem(mContext); 581 assertNotNull(menuItem); 582 return menuItem; 583 } 584 } 585