1 /* 2 * Copyright (C) 2021 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.car.notification; 18 19 import static android.app.PendingIntent.FLAG_IMMUTABLE; 20 21 import static com.google.common.truth.Truth.assertThat; 22 23 import static org.mockito.ArgumentMatchers.any; 24 import static org.mockito.ArgumentMatchers.anyInt; 25 import static org.mockito.ArgumentMatchers.anyString; 26 import static org.mockito.ArgumentMatchers.eq; 27 import static org.mockito.ArgumentMatchers.isNull; 28 import static org.mockito.Mockito.never; 29 import static org.mockito.Mockito.times; 30 import static org.mockito.Mockito.verify; 31 import static org.mockito.Mockito.when; 32 33 import android.app.ActivityManager; 34 import android.app.Notification; 35 import android.app.PendingIntent; 36 import android.app.RemoteInput; 37 import android.content.Context; 38 import android.content.Intent; 39 import android.os.Bundle; 40 import android.os.Looper; 41 import android.os.RemoteException; 42 import android.os.UserHandle; 43 import android.service.notification.NotificationStats; 44 import android.service.notification.StatusBarNotification; 45 import android.view.View; 46 47 import androidx.test.core.app.ApplicationProvider; 48 import androidx.test.ext.junit.runners.AndroidJUnit4; 49 50 import com.android.car.assist.client.CarAssistUtils; 51 import com.android.car.notification.template.CarNotificationActionButton; 52 import com.android.car.notification.utils.MockMessageNotificationBuilder; 53 import com.android.internal.statusbar.IStatusBarService; 54 import com.android.internal.statusbar.NotificationVisibility; 55 56 import org.junit.After; 57 import org.junit.Before; 58 import org.junit.Test; 59 import org.junit.runner.RunWith; 60 import org.mockito.Mock; 61 import org.mockito.MockitoAnnotations; 62 63 import java.util.ArrayList; 64 import java.util.List; 65 66 @RunWith(AndroidJUnit4.class) 67 public class NotificationClickHandlerFactoryTest { 68 private static final String PKG_1 = "package_1"; 69 private static final String OP_PKG = "OpPackage"; 70 private static final int ID = 1; 71 private static final String TAG = "Tag"; 72 private static final int UID = 2; 73 private static final int INITIAL_PID = 3; 74 private static final String CHANNEL_ID = "CHANNEL_ID"; 75 private static final String CONTENT_TITLE = "CONTENT_TITLE"; 76 private static final String OVERRIDE_GROUP_KEY = "OVERRIDE_GROUP_KEY"; 77 private static final long POST_TIME = 12345L; 78 private static final UserHandle USER_HANDLE = new UserHandle(/* userId= */ 12); 79 80 private Context mContext; 81 private NotificationClickHandlerFactory mNotificationClickHandlerFactory; 82 private AlertEntry mAlertEntry1; 83 private AlertEntry mAlertEntry2; 84 private AlertEntry mAlertEntryMessageHeadsUp; 85 private AlertEntry mAlertEntryMessageWithMuteAction; 86 private PendingIntent mReplyActionPendingIntent; 87 private PendingIntent mMuteActionPendingIntent; 88 89 @Mock 90 private IStatusBarService mBarService; 91 @Mock 92 private NotificationClickHandlerFactory.OnNotificationClickListener mListener1; 93 @Mock 94 private NotificationClickHandlerFactory.OnNotificationClickListener mListener2; 95 @Mock 96 private View mView; 97 @Mock 98 private StatusBarNotification mStatusBarNotification1; 99 @Mock 100 private StatusBarNotification mStatusBarNotification2; 101 @Mock 102 private UserHandle mUser1; 103 @Mock 104 private UserHandle mUser2; 105 @Mock 106 private PendingIntent mActionIntent; 107 @Mock 108 private RemoteInput mRemoteInput; 109 @Mock 110 private CarAssistUtils mCarAssistUtils; 111 @Mock 112 private NotificationClickHandlerFactory.MuteStatusSetter mMuteStatusSetter; 113 114 @Before setUp()115 public void setUp() { 116 MockitoAnnotations.initMocks(this); 117 mContext = ApplicationProvider.getApplicationContext(); 118 mNotificationClickHandlerFactory = new NotificationClickHandlerFactory(mBarService); 119 Notification notification1 = new Notification(); 120 Notification notification2 = new Notification(); 121 notification1.contentIntent = PendingIntent.getForegroundService( 122 mContext, /* requestCode= */ 0, new Intent(), FLAG_IMMUTABLE); 123 notification2.contentIntent = PendingIntent.getForegroundService( 124 mContext, /* requestCode= */ 0, new Intent(), FLAG_IMMUTABLE); 125 when(mStatusBarNotification1.getNotification()).thenReturn(notification1); 126 when(mStatusBarNotification2.getNotification()).thenReturn(notification2); 127 when(mStatusBarNotification1.getKey()).thenReturn("TEST_KEY_1"); 128 when(mStatusBarNotification2.getKey()).thenReturn("TEST_KEY_2"); 129 when(mStatusBarNotification1.getUser()).thenReturn(mUser1); 130 when(mStatusBarNotification2.getUser()).thenReturn(mUser2); 131 mAlertEntry1 = new AlertEntry(mStatusBarNotification1); 132 mAlertEntry2 = new AlertEntry(mStatusBarNotification2); 133 134 MockMessageNotificationBuilder mockNotificationBuilder_messageHeadsUp = 135 new MockMessageNotificationBuilder(mContext, 136 CHANNEL_ID, android.R.drawable.sym_def_app_icon) 137 .setContentTitle(CONTENT_TITLE) 138 .setCategory(Notification.CATEGORY_MESSAGE) 139 .setHasMessagingStyle(true) 140 .setHasReplyAction(true) 141 .setPendingIntentIsMocked(true) 142 .setHasMarkAsRead(true); 143 MockMessageNotificationBuilder mockNotificationBuilder_messageHeadsUpWithMute = 144 new MockMessageNotificationBuilder(mContext, 145 CHANNEL_ID, android.R.drawable.sym_def_app_icon) 146 .setContentTitle(CONTENT_TITLE) 147 .setCategory(Notification.CATEGORY_MESSAGE) 148 .setHasMessagingStyle(true) 149 .setHasReplyAction(true) 150 .setPendingIntentIsMocked(true) 151 .setHasMarkAsRead(true) 152 .setHasMuteAction(true); 153 mAlertEntryMessageHeadsUp = new AlertEntry( 154 new StatusBarNotification(PKG_1, OP_PKG, ID, TAG, UID, INITIAL_PID, 155 mockNotificationBuilder_messageHeadsUp.build(), USER_HANDLE, 156 OVERRIDE_GROUP_KEY, POST_TIME)); 157 mAlertEntryMessageWithMuteAction = new AlertEntry( 158 new StatusBarNotification(PKG_1, OP_PKG, ID, TAG, UID, INITIAL_PID, 159 mockNotificationBuilder_messageHeadsUpWithMute 160 .build(), USER_HANDLE, 161 OVERRIDE_GROUP_KEY, POST_TIME)); 162 mReplyActionPendingIntent = mockNotificationBuilder_messageHeadsUp.getPendingIntent(); 163 mMuteActionPendingIntent = 164 mockNotificationBuilder_messageHeadsUpWithMute.getPendingIntent(); 165 166 when(mView.getContext()).thenReturn(mContext); 167 mNotificationClickHandlerFactory.setCarAssistUtils(mCarAssistUtils); 168 } 169 170 @After tearDown()171 public void tearDown() { 172 NotificationDataManager.refreshInstance(); 173 } 174 175 @Test onClickClickHandler_noIntent_returnsImmediately()176 public void onClickClickHandler_noIntent_returnsImmediately() { 177 mNotificationClickHandlerFactory.registerClickListener(mListener1); 178 // overriding the non-null value assigned in setup. 179 mAlertEntry1.getNotification().contentIntent = null; 180 mAlertEntry1.getNotification().fullScreenIntent = null; 181 182 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1).onClick(mView); 183 184 verify(mListener1, never()).onNotificationClicked(anyInt(), any(AlertEntry.class)); 185 try { 186 verify(mBarService, never()) 187 .onNotificationClick(anyString(), any(NotificationVisibility.class)); 188 } catch (RemoteException ex) { 189 // ignore 190 } 191 } 192 193 @Test onClickClickHandler_intentExists_callsBarServiceNotificationClicked()194 public void onClickClickHandler_intentExists_callsBarServiceNotificationClicked() { 195 mNotificationClickHandlerFactory.registerClickListener(mListener1); 196 197 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1).onClick(mView); 198 199 try { 200 verify(mBarService) 201 .onNotificationClick(anyString(), any(NotificationVisibility.class)); 202 } catch (RemoteException ex) { 203 // ignore 204 } 205 } 206 207 @Test onClickClickHandler_intentExists_invokesRegisteredClickListeners()208 public void onClickClickHandler_intentExists_invokesRegisteredClickListeners() { 209 mNotificationClickHandlerFactory.registerClickListener(mListener1); 210 211 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1).onClick(mView); 212 213 verify(mListener1).onNotificationClicked(anyInt(), any(AlertEntry.class)); 214 } 215 216 @Test onClickClickHandler_shouldAutoCancel_callsBarServiceOnNotificationClear()217 public void onClickClickHandler_shouldAutoCancel_callsBarServiceOnNotificationClear() { 218 mAlertEntry1.getStatusBarNotification().getNotification().flags = 219 mStatusBarNotification1.getNotification().flags | Notification.FLAG_AUTO_CANCEL; 220 UserHandle user = new UserHandle( /* handle= */ 0); 221 when(mStatusBarNotification1.getUser()).thenReturn(user); 222 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1).onClick(mView); 223 NotificationVisibility notificationVisibility = NotificationVisibility.obtain( 224 mAlertEntry1.getKey(), /* rank= */ -1, /* count= */ -1, /* visible= */ true); 225 226 try { 227 verify(mBarService).onNotificationClear( 228 mAlertEntry1.getStatusBarNotification().getPackageName(), 229 mAlertEntry1.getStatusBarNotification().getUser().getIdentifier(), 230 mAlertEntry1.getKey(), 231 NotificationStats.DISMISSAL_SHADE, 232 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, 233 notificationVisibility); 234 } catch (RemoteException ex) { 235 // ignore 236 } 237 238 } 239 240 @Test onClickActionClickHandler_isReplyAction_sendsPendingIntent()241 public void onClickActionClickHandler_isReplyAction_sendsPendingIntent() { 242 // Have to prepare looper since Toast will be shown in test. 243 Looper.prepare(); 244 245 mNotificationClickHandlerFactory.getActionClickHandler( 246 mAlertEntryMessageHeadsUp, /* index= */ 247 0).onClick(mView); 248 try { 249 verify(mReplyActionPendingIntent).sendAndReturnResult(any(Context.class), eq(0), 250 any(Intent.class), isNull(), isNull(), isNull(), any(Bundle.class)); 251 } catch (PendingIntent.CanceledException e) { 252 // ignore 253 } 254 } 255 256 @Test onClickActionClickHandler_isReplyAction_doesNotInvokeRegisteredClickListeners()257 public void onClickActionClickHandler_isReplyAction_doesNotInvokeRegisteredClickListeners() { 258 // Have to prepare looper since Toast will be shown in test. 259 Looper.prepare(); 260 261 mNotificationClickHandlerFactory.getActionClickHandler( 262 mAlertEntryMessageHeadsUp, /* index= */ 263 0).onClick(mView); 264 265 verify(mListener1, never()).onNotificationClicked(anyInt(), any(AlertEntry.class)); 266 } 267 268 @Test onClickActionClickHandler_notCarCompatibleMessage_sendsPendingIntent()269 public void onClickActionClickHandler_notCarCompatibleMessage_sendsPendingIntent() { 270 PendingIntent pendingIntent = PendingIntent.getForegroundService( 271 mContext, /* requestCode= */0, 272 new Intent(), FLAG_IMMUTABLE); 273 Notification.Action action = new Notification.Action 274 .Builder(/* icon= */ null, "ACTION_TITLE", pendingIntent) 275 .setSemanticAction(Notification.Action.SEMANTIC_ACTION_REPLY) 276 .addRemoteInput(mRemoteInput) 277 .build(); 278 action.actionIntent = mActionIntent; 279 Notification.Action[] actions = {action}; 280 mStatusBarNotification1.getNotification().actions = actions; 281 282 mNotificationClickHandlerFactory.getActionClickHandler(mAlertEntry1, /* index= */ 283 0).onClick(mView); 284 try { 285 verify(mActionIntent).sendAndReturnResult(isNull(), eq(0), isNull(), isNull(), 286 isNull(), isNull(), any(Bundle.class)); 287 } catch (PendingIntent.CanceledException e) { 288 // ignore 289 } 290 } 291 292 @Test onClickActionClickHandler_notCarCompatibleMessage_invokesRegisteredListeners()293 public void onClickActionClickHandler_notCarCompatibleMessage_invokesRegisteredListeners() { 294 mNotificationClickHandlerFactory.registerClickListener(mListener1); 295 PendingIntent pendingIntent = PendingIntent.getForegroundService( 296 mContext, /* requestCode= */0, 297 new Intent(), FLAG_IMMUTABLE); 298 Notification.Action action = new Notification.Action 299 .Builder(/* icon= */ null, "ACTION_TITLE", pendingIntent) 300 .setSemanticAction(Notification.Action.SEMANTIC_ACTION_REPLY) 301 .addRemoteInput(mRemoteInput) 302 .build(); 303 action.actionIntent = mActionIntent; 304 Notification.Action[] actions = {action}; 305 mStatusBarNotification1.getNotification().actions = actions; 306 307 mNotificationClickHandlerFactory.getActionClickHandler(mAlertEntry1, /* index= */ 308 0).onClick(mView); 309 310 verify(mListener1).onNotificationClicked(anyInt(), any(AlertEntry.class)); 311 } 312 313 @Test onClickPlayClickHandler_notCarCompatibleMessage_returnsImmediately()314 public void onClickPlayClickHandler_notCarCompatibleMessage_returnsImmediately() { 315 mNotificationClickHandlerFactory.getPlayClickHandler(mAlertEntry1).onClick(mView); 316 317 verify(mCarAssistUtils, never()).requestAssistantVoiceAction(any(), any(), any()); 318 } 319 320 @Test onClickPlayClickHandler_isCarCompatibleMessage_requestsAssistantVoiceAction()321 public void onClickPlayClickHandler_isCarCompatibleMessage_requestsAssistantVoiceAction() { 322 mNotificationClickHandlerFactory.getPlayClickHandler(mAlertEntryMessageHeadsUp).onClick( 323 mView); 324 325 verify(mCarAssistUtils).requestAssistantVoiceAction(any(), any(), any()); 326 } 327 328 @Test onClickMuteClickHandler_togglesMute()329 public void onClickMuteClickHandler_togglesMute() { 330 NotificationDataManager notificationDataManager = NotificationDataManager.getInstance(); 331 notificationDataManager.addNewMessageNotification(mAlertEntryMessageHeadsUp); 332 CarNotificationActionButton button = new CarNotificationActionButton(mContext); 333 334 // first make sure it is not muted by default 335 assertThat(notificationDataManager.isMessageNotificationMuted( 336 mAlertEntryMessageHeadsUp)).isFalse(); 337 338 mNotificationClickHandlerFactory.getMuteClickHandler(button, 339 mAlertEntryMessageHeadsUp, mMuteStatusSetter).onClick(mView); 340 341 assertThat(notificationDataManager.isMessageNotificationMuted( 342 mAlertEntryMessageHeadsUp)).isTrue(); 343 344 mNotificationClickHandlerFactory.getMuteClickHandler(button, 345 mAlertEntryMessageHeadsUp, mMuteStatusSetter).onClick(mView); 346 347 assertThat(notificationDataManager.isMessageNotificationMuted( 348 mAlertEntryMessageHeadsUp)).isFalse(); 349 } 350 351 @Test onClickMuteClickHandler_mutePendingIntent_notificationDataManagerUnchanged()352 public void onClickMuteClickHandler_mutePendingIntent_notificationDataManagerUnchanged() { 353 NotificationDataManager notificationDataManager = NotificationDataManager.getInstance(); 354 notificationDataManager.addNewMessageNotification(mAlertEntryMessageWithMuteAction); 355 CarNotificationActionButton button = new CarNotificationActionButton(mContext); 356 357 // first make sure it is not muted by default 358 assertThat(notificationDataManager.isMessageNotificationMuted( 359 mAlertEntryMessageWithMuteAction)).isFalse(); 360 361 mNotificationClickHandlerFactory.getMuteClickHandler(button, 362 mAlertEntryMessageWithMuteAction, mMuteStatusSetter).onClick(mView); 363 364 // verify that notification data manager does not handle muting the notification 365 assertThat(notificationDataManager.isMessageNotificationMuted( 366 mAlertEntryMessageWithMuteAction)).isFalse(); 367 } 368 369 @Test onClickMuteClickHandler_mutePendingIntent_dismissesNotification()370 public void onClickMuteClickHandler_mutePendingIntent_dismissesNotification() { 371 NotificationDataManager notificationDataManager = NotificationDataManager.getInstance(); 372 notificationDataManager.addNewMessageNotification(mAlertEntryMessageWithMuteAction); 373 CarNotificationActionButton button = new CarNotificationActionButton(mContext); 374 NotificationVisibility notificationVisibility = NotificationVisibility.obtain( 375 mAlertEntryMessageWithMuteAction.getKey(), 376 /* rank= */ -1, 377 /* count= */ -1, 378 /* visible= */ true); 379 380 mNotificationClickHandlerFactory.getMuteClickHandler(button, 381 mAlertEntryMessageWithMuteAction, mMuteStatusSetter).onClick(mView); 382 383 // verify notification is dismissed 384 try { 385 verify(mBarService).onNotificationClear( 386 mAlertEntryMessageWithMuteAction.getStatusBarNotification().getPackageName(), 387 mAlertEntryMessageWithMuteAction 388 .getStatusBarNotification().getUser().getIdentifier(), 389 mAlertEntryMessageWithMuteAction.getStatusBarNotification().getKey(), 390 NotificationStats.DISMISSAL_SHADE, 391 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, 392 notificationVisibility); 393 } catch (RemoteException e) { 394 // ignore. 395 } 396 } 397 398 @Test onClickMuteClickHandler_mutePendingIntent_firesPendingIntent()399 public void onClickMuteClickHandler_mutePendingIntent_firesPendingIntent() { 400 NotificationDataManager notificationDataManager = NotificationDataManager.getInstance(); 401 notificationDataManager.addNewMessageNotification(mAlertEntryMessageWithMuteAction); 402 CarNotificationActionButton button = new CarNotificationActionButton(mContext); 403 404 // first make sure it is not muted by default 405 assertThat(notificationDataManager.isMessageNotificationMuted( 406 mAlertEntryMessageWithMuteAction)).isFalse(); 407 408 mNotificationClickHandlerFactory.getMuteClickHandler(button, 409 mAlertEntryMessageWithMuteAction, mMuteStatusSetter).onClick(mView); 410 try { 411 verify(mMuteActionPendingIntent).send(); 412 } catch (PendingIntent.CanceledException e) { 413 // ignore 414 } 415 } 416 417 @Test onClickMuteClickHandler_isMuted_muteStatusSetTrue()418 public void onClickMuteClickHandler_isMuted_muteStatusSetTrue() { 419 NotificationDataManager notificationDataManager = NotificationDataManager.getInstance(); 420 notificationDataManager.addNewMessageNotification(mAlertEntryMessageHeadsUp); 421 CarNotificationActionButton button = new CarNotificationActionButton(mContext); 422 // first make sure it is not muted by default 423 assertThat(notificationDataManager.isMessageNotificationMuted( 424 mAlertEntryMessageHeadsUp)).isFalse(); 425 426 mNotificationClickHandlerFactory.getMuteClickHandler(button, 427 mAlertEntryMessageHeadsUp, mMuteStatusSetter).onClick(mView); 428 429 verify(mMuteStatusSetter).setMuteStatus(button, /* isMuted= */ true); 430 } 431 432 @Test onClickMuteClickHandler_isUnmuted_muteStatusSetFalse()433 public void onClickMuteClickHandler_isUnmuted_muteStatusSetFalse() { 434 NotificationDataManager notificationDataManager = NotificationDataManager.getInstance(); 435 notificationDataManager.addNewMessageNotification(mAlertEntryMessageHeadsUp); 436 CarNotificationActionButton button = new CarNotificationActionButton(mContext); 437 // first make sure it is not muted by default 438 assertThat(notificationDataManager.isMessageNotificationMuted( 439 mAlertEntryMessageHeadsUp)).isFalse(); 440 mNotificationClickHandlerFactory.getMuteClickHandler(button, 441 mAlertEntryMessageHeadsUp, mMuteStatusSetter).onClick(mView); 442 verify(mMuteStatusSetter).setMuteStatus(button, /* isMuted= */ true); 443 444 mNotificationClickHandlerFactory.getMuteClickHandler(button, 445 mAlertEntryMessageHeadsUp, mMuteStatusSetter).onClick(mView); 446 447 verify(mMuteStatusSetter).setMuteStatus(button, /* isMuted= */ false); 448 } 449 450 @Test onNotificationClicked_twoListenersRegistered_invokesTwoHandlerCallbacks()451 public void onNotificationClicked_twoListenersRegistered_invokesTwoHandlerCallbacks() { 452 mNotificationClickHandlerFactory.registerClickListener(mListener1); 453 mNotificationClickHandlerFactory.registerClickListener(mListener2); 454 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1).onClick(mView); 455 456 verify(mListener1).onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry1); 457 verify(mListener2).onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry1); 458 } 459 460 @Test onNotificationClicked_oneListenersUnregistered_invokesRegisteredCallback()461 public void onNotificationClicked_oneListenersUnregistered_invokesRegisteredCallback() { 462 mNotificationClickHandlerFactory.registerClickListener(mListener1); 463 mNotificationClickHandlerFactory.registerClickListener(mListener2); 464 mNotificationClickHandlerFactory.unregisterClickListener(mListener2); 465 466 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1).onClick(mView); 467 468 verify(mListener1).onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry1); 469 verify(mListener2, never()).onNotificationClicked(ActivityManager.START_SUCCESS, 470 mAlertEntry1); 471 } 472 473 @Test onNotificationClicked_duplicateListenersRegistered_invokesCallbackOnce()474 public void onNotificationClicked_duplicateListenersRegistered_invokesCallbackOnce() { 475 mNotificationClickHandlerFactory.registerClickListener(mListener1); 476 mNotificationClickHandlerFactory.registerClickListener(mListener1); 477 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1).onClick(mView); 478 479 verify(mListener1).onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry1); 480 } 481 482 @Test onNotificationClicked_twoAlertEntriesSubscribe_passesTheRightAlertEntry()483 public void onNotificationClicked_twoAlertEntriesSubscribe_passesTheRightAlertEntry() { 484 mNotificationClickHandlerFactory.registerClickListener(mListener1); 485 View.OnClickListener clickListener1 = 486 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1); 487 View.OnClickListener clickListener2 = 488 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry2); 489 490 clickListener2.onClick(mView); 491 492 verify(mListener1, never()) 493 .onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry1); 494 verify(mListener1).onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry2); 495 } 496 497 @Test onNotificationClicked_multipleListenersAndAes_passesTheRightAeToAllListeners()498 public void onNotificationClicked_multipleListenersAndAes_passesTheRightAeToAllListeners() { 499 mNotificationClickHandlerFactory.registerClickListener(mListener1); 500 mNotificationClickHandlerFactory.registerClickListener(mListener2); 501 View.OnClickListener clickListener1 = 502 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry1); 503 View.OnClickListener clickListener2 = 504 mNotificationClickHandlerFactory.getClickHandler(mAlertEntry2); 505 506 clickListener2.onClick(mView); 507 508 verify(mListener1, never()) 509 .onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry1); 510 verify(mListener1).onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry2); 511 512 verify(mListener2, never()) 513 .onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry1); 514 verify(mListener2).onNotificationClicked(ActivityManager.START_SUCCESS, mAlertEntry2); 515 } 516 517 @Test onClearNotifications_groupNotificationWithSummary_clearsSummary()518 public void onClearNotifications_groupNotificationWithSummary_clearsSummary() { 519 List<NotificationGroup> notificationsToClear = new ArrayList<>(); 520 NotificationGroup notificationGroup = new NotificationGroup(); 521 notificationGroup.setGroupSummaryNotification(mAlertEntry1); 522 notificationGroup.addNotification(mAlertEntry2); 523 notificationGroup.addNotification(mAlertEntry2); 524 notificationGroup.addNotification(mAlertEntry2); 525 notificationsToClear.add(notificationGroup); 526 NotificationVisibility notificationVisibility = NotificationVisibility.obtain( 527 mAlertEntry1.getKey(), 528 /* rank= */ -1, 529 /* count= */ -1, 530 /* visible= */ true); 531 532 mNotificationClickHandlerFactory.clearNotifications(notificationsToClear); 533 534 try { 535 verify(mBarService).onNotificationClear( 536 mAlertEntry1.getStatusBarNotification().getPackageName(), 537 mAlertEntry1.getStatusBarNotification().getUser().getIdentifier(), 538 mAlertEntry1.getStatusBarNotification().getKey(), 539 NotificationStats.DISMISSAL_SHADE, 540 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, 541 notificationVisibility); 542 } catch (RemoteException e) { 543 // ignore. 544 } 545 } 546 547 @Test onClearNotifications_groupNotificationWithSummary_clearsAllChildren()548 public void onClearNotifications_groupNotificationWithSummary_clearsAllChildren() { 549 List<NotificationGroup> notificationsToClear = new ArrayList<>(); 550 NotificationGroup notificationGroup = new NotificationGroup(); 551 notificationGroup.setGroupSummaryNotification(mAlertEntry1); 552 notificationGroup.addNotification(mAlertEntry2); 553 notificationGroup.addNotification(mAlertEntry2); 554 notificationGroup.addNotification(mAlertEntry2); 555 notificationsToClear.add(notificationGroup); 556 NotificationVisibility notificationVisibility = NotificationVisibility.obtain( 557 mAlertEntry2.getKey(), 558 /* rank= */ -1, 559 /* count= */ -1, 560 /* visible= */ true); 561 562 mNotificationClickHandlerFactory.clearNotifications(notificationsToClear); 563 564 try { 565 verify(mBarService, times(3)).onNotificationClear( 566 mAlertEntry2.getStatusBarNotification().getPackageName(), 567 mAlertEntry2.getStatusBarNotification().getUser().getIdentifier(), 568 mAlertEntry2.getStatusBarNotification().getKey(), 569 NotificationStats.DISMISSAL_SHADE, 570 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, 571 notificationVisibility); 572 } catch (RemoteException e) { 573 // ignore. 574 } 575 } 576 577 @Test onClearNotifications_groupNotificationWithoutSummary_clearsAllChildren()578 public void onClearNotifications_groupNotificationWithoutSummary_clearsAllChildren() { 579 List<NotificationGroup> notificationsToClear = new ArrayList<>(); 580 NotificationGroup notificationGroup = new NotificationGroup(); 581 notificationGroup.addNotification(mAlertEntry2); 582 notificationGroup.addNotification(mAlertEntry2); 583 notificationGroup.addNotification(mAlertEntry2); 584 notificationsToClear.add(notificationGroup); 585 NotificationVisibility notificationVisibility = NotificationVisibility.obtain( 586 mAlertEntry2.getKey(), 587 /* rank= */ -1, 588 /* count= */ -1, 589 /* visible= */ true); 590 591 mNotificationClickHandlerFactory.clearNotifications(notificationsToClear); 592 593 try { 594 verify(mBarService, times(3)).onNotificationClear( 595 mAlertEntry2.getStatusBarNotification().getPackageName(), 596 mAlertEntry2.getStatusBarNotification().getUser().getIdentifier(), 597 mAlertEntry2.getStatusBarNotification().getKey(), 598 NotificationStats.DISMISSAL_SHADE, 599 NotificationStats.DISMISS_SENTIMENT_NEUTRAL, 600 notificationVisibility); 601 } catch (RemoteException e) { 602 // ignore. 603 } 604 } 605 } 606