1 /* 2 * Copyright (C) 2016 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.NotificationChannel.USER_LOCKED_IMPORTANCE; 20 import static android.app.NotificationManager.IMPORTANCE_DEFAULT; 21 import static android.app.NotificationManager.IMPORTANCE_LOW; 22 import static android.app.NotificationManager.IMPORTANCE_MIN; 23 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; 24 import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME; 25 import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL; 26 import static android.view.View.GONE; 27 import static android.view.View.VISIBLE; 28 29 import static junit.framework.Assert.assertEquals; 30 import static junit.framework.Assert.assertFalse; 31 import static junit.framework.Assert.assertTrue; 32 33 import static org.mockito.ArgumentMatchers.argThat; 34 import static org.mockito.Mockito.any; 35 import static org.mockito.Mockito.anyBoolean; 36 import static org.mockito.Mockito.anyInt; 37 import static org.mockito.Mockito.anyString; 38 import static org.mockito.Mockito.doCallRealMethod; 39 import static org.mockito.Mockito.doNothing; 40 import static org.mockito.Mockito.eq; 41 import static org.mockito.Mockito.mock; 42 import static org.mockito.Mockito.never; 43 import static org.mockito.Mockito.spy; 44 import static org.mockito.Mockito.times; 45 import static org.mockito.Mockito.verify; 46 import static org.mockito.Mockito.when; 47 48 import android.app.INotificationManager; 49 import android.app.Notification; 50 import android.app.NotificationChannel; 51 import android.app.NotificationChannelGroup; 52 import android.content.pm.ApplicationInfo; 53 import android.content.pm.PackageInfo; 54 import android.content.pm.PackageManager; 55 import android.graphics.drawable.Drawable; 56 import android.os.IBinder; 57 import android.os.UserHandle; 58 import android.provider.Settings; 59 import android.service.notification.StatusBarNotification; 60 import android.test.suitebuilder.annotation.SmallTest; 61 import android.testing.AndroidTestingRunner; 62 import android.testing.PollingCheck; 63 import android.testing.TestableLooper; 64 import android.testing.UiThreadTest; 65 import android.view.LayoutInflater; 66 import android.view.View; 67 import android.widget.ImageView; 68 import android.widget.TextView; 69 70 import com.android.internal.logging.MetricsLogger; 71 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 72 import com.android.systemui.Dependency; 73 import com.android.systemui.R; 74 import com.android.systemui.SysuiTestCase; 75 import com.android.systemui.statusbar.notification.VisualStabilityManager; 76 77 import org.junit.After; 78 import org.junit.Before; 79 import org.junit.Rule; 80 import org.junit.Test; 81 import org.junit.runner.RunWith; 82 import org.mockito.ArgumentCaptor; 83 import org.mockito.Mock; 84 import org.mockito.junit.MockitoJUnit; 85 import org.mockito.junit.MockitoRule; 86 87 import java.util.HashSet; 88 import java.util.Set; 89 import java.util.concurrent.CountDownLatch; 90 91 @SmallTest 92 @RunWith(AndroidTestingRunner.class) 93 @TestableLooper.RunWithLooper 94 public class NotificationInfoTest extends SysuiTestCase { 95 private static final String TEST_PACKAGE_NAME = "test_package"; 96 private static final String TEST_SYSTEM_PACKAGE_NAME = PRINT_SPOOLER_PACKAGE_NAME; 97 private static final int TEST_UID = 1; 98 private static final int MULTIPLE_CHANNEL_COUNT = 2; 99 private static final String TEST_CHANNEL = "test_channel"; 100 private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME"; 101 102 private TestableLooper mTestableLooper; 103 private NotificationInfo mNotificationInfo; 104 private NotificationChannel mNotificationChannel; 105 private NotificationChannel mDefaultNotificationChannel; 106 private Set<NotificationChannel> mNotificationChannelSet = new HashSet<>(); 107 private Set<NotificationChannel> mDefaultNotificationChannelSet = new HashSet<>(); 108 private StatusBarNotification mSbn; 109 110 @Rule 111 public MockitoRule mockito = MockitoJUnit.rule(); 112 @Mock 113 private MetricsLogger mMetricsLogger; 114 @Mock 115 private INotificationManager mMockINotificationManager; 116 @Mock 117 private PackageManager mMockPackageManager; 118 @Mock 119 private NotificationBlockingHelperManager mBlockingHelperManager; 120 @Mock 121 private VisualStabilityManager mVisualStabilityManager; 122 123 @Before setUp()124 public void setUp() throws Exception { 125 mDependency.injectTestDependency( 126 NotificationBlockingHelperManager.class, 127 mBlockingHelperManager); 128 mTestableLooper = TestableLooper.get(this); 129 mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper()); 130 mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); 131 // Inflate the layout 132 final LayoutInflater layoutInflater = LayoutInflater.from(mContext); 133 mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info, 134 null); 135 mNotificationInfo.setGutsParent(mock(NotificationGuts.class)); 136 137 // PackageManager must return a packageInfo and applicationInfo. 138 final PackageInfo packageInfo = new PackageInfo(); 139 packageInfo.packageName = TEST_PACKAGE_NAME; 140 when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt())) 141 .thenReturn(packageInfo); 142 final ApplicationInfo applicationInfo = new ApplicationInfo(); 143 applicationInfo.uid = TEST_UID; // non-zero 144 when(mMockPackageManager.getApplicationInfo(eq(TEST_PACKAGE_NAME), anyInt())).thenReturn( 145 applicationInfo); 146 final PackageInfo systemPackageInfo = new PackageInfo(); 147 systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME; 148 when(mMockPackageManager.getPackageInfo(eq(TEST_SYSTEM_PACKAGE_NAME), anyInt())) 149 .thenReturn(systemPackageInfo); 150 when(mMockPackageManager.getPackageInfo(eq("android"), anyInt())) 151 .thenReturn(packageInfo); 152 153 // Package has one channel by default. 154 when(mMockINotificationManager.getNumNotificationChannelsForPackage( 155 eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(1); 156 157 // Some test channels. 158 mNotificationChannel = new NotificationChannel( 159 TEST_CHANNEL, TEST_CHANNEL_NAME, IMPORTANCE_LOW); 160 mNotificationChannelSet.add(mNotificationChannel); 161 mDefaultNotificationChannel = new NotificationChannel( 162 NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME, 163 IMPORTANCE_LOW); 164 mDefaultNotificationChannelSet.add(mDefaultNotificationChannel); 165 mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0, 166 new Notification(), UserHandle.CURRENT, null, 0); 167 168 Settings.Secure.putInt(mContext.getContentResolver(), 169 NOTIFICATION_NEW_INTERRUPTION_MODEL, 1); 170 } 171 172 @After tearDown()173 public void tearDown() { 174 Settings.Secure.putInt(mContext.getContentResolver(), 175 NOTIFICATION_NEW_INTERRUPTION_MODEL, 0); 176 } 177 178 // TODO: if tests are taking too long replace this with something that makes the animation 179 // finish instantly. waitForUndoButton()180 private void waitForUndoButton() { 181 PollingCheck.waitFor(1000, 182 () -> VISIBLE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility()); 183 } 184 ensureNoUndoButton()185 private void ensureNoUndoButton() { 186 PollingCheck.waitFor(1000, 187 () -> GONE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility() 188 && !mNotificationInfo.isAnimating()); 189 } 190 waitForStopButton()191 private void waitForStopButton() { 192 PollingCheck.waitFor(1000, 193 () -> VISIBLE == mNotificationInfo.findViewById(R.id.prompt).getVisibility()); 194 } 195 196 @Test testBindNotification_SetsTextApplicationName()197 public void testBindNotification_SetsTextApplicationName() throws Exception { 198 when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name"); 199 mNotificationInfo.bindNotification( 200 mMockPackageManager, 201 mMockINotificationManager, 202 mVisualStabilityManager, 203 TEST_PACKAGE_NAME, 204 mNotificationChannel, 205 mNotificationChannelSet, 206 mSbn, 207 null, 208 null, 209 null, 210 true, 211 false, 212 IMPORTANCE_DEFAULT, 213 true); 214 final TextView textView = mNotificationInfo.findViewById(R.id.pkgname); 215 assertTrue(textView.getText().toString().contains("App Name")); 216 assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility()); 217 } 218 219 @Test testBindNotification_SetsPackageIcon()220 public void testBindNotification_SetsPackageIcon() throws Exception { 221 final Drawable iconDrawable = mock(Drawable.class); 222 when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class))) 223 .thenReturn(iconDrawable); 224 mNotificationInfo.bindNotification( 225 mMockPackageManager, 226 mMockINotificationManager, 227 mVisualStabilityManager, 228 TEST_PACKAGE_NAME, 229 mNotificationChannel, 230 mNotificationChannelSet, 231 mSbn, 232 null, 233 null, 234 null, 235 true, 236 false, 237 IMPORTANCE_DEFAULT, 238 true); 239 final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon); 240 assertEquals(iconDrawable, iconView.getDrawable()); 241 } 242 243 @Test testBindNotification_noDelegate()244 public void testBindNotification_noDelegate() throws Exception { 245 mNotificationInfo.bindNotification( 246 mMockPackageManager, 247 mMockINotificationManager, 248 mVisualStabilityManager, 249 TEST_PACKAGE_NAME, 250 mNotificationChannel, 251 mNotificationChannelSet, 252 mSbn, 253 null, 254 null, 255 null, 256 true, 257 false, 258 IMPORTANCE_DEFAULT, 259 true); 260 final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name); 261 assertEquals(GONE, nameView.getVisibility()); 262 final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider); 263 assertEquals(GONE, dividerView.getVisibility()); 264 } 265 266 @Test testBindNotification_delegate()267 public void testBindNotification_delegate() throws Exception { 268 mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, "other", 0, null, TEST_UID, 0, 269 new Notification(), UserHandle.CURRENT, null, 0); 270 final ApplicationInfo applicationInfo = new ApplicationInfo(); 271 applicationInfo.uid = 7; // non-zero 272 when(mMockPackageManager.getApplicationInfo(eq("other"), anyInt())).thenReturn( 273 applicationInfo); 274 when(mMockPackageManager.getApplicationLabel(any())).thenReturn("Other"); 275 276 mNotificationInfo.bindNotification( 277 mMockPackageManager, 278 mMockINotificationManager, 279 mVisualStabilityManager, 280 TEST_PACKAGE_NAME, 281 mNotificationChannel, 282 mNotificationChannelSet, 283 mSbn, 284 null, 285 null, 286 null, 287 true, 288 false, 289 IMPORTANCE_DEFAULT, 290 true); 291 final TextView nameView = mNotificationInfo.findViewById(R.id.delegate_name); 292 assertEquals(VISIBLE, nameView.getVisibility()); 293 assertTrue(nameView.getText().toString().contains("Proxied")); 294 final TextView dividerView = mNotificationInfo.findViewById(R.id.pkg_divider); 295 assertEquals(VISIBLE, dividerView.getVisibility()); 296 } 297 298 @Test testBindNotification_GroupNameHiddenIfNoGroup()299 public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception { 300 mNotificationInfo.bindNotification( 301 mMockPackageManager, 302 mMockINotificationManager, 303 mVisualStabilityManager, 304 TEST_PACKAGE_NAME, 305 mNotificationChannel, 306 mNotificationChannelSet, 307 mSbn, 308 null, 309 null, 310 null, 311 true, 312 false, 313 IMPORTANCE_DEFAULT, 314 true); 315 final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name); 316 assertEquals(GONE, groupNameView.getVisibility()); 317 } 318 319 @Test testBindNotification_SetsGroupNameIfNonNull()320 public void testBindNotification_SetsGroupNameIfNonNull() throws Exception { 321 mNotificationChannel.setGroup("test_group_id"); 322 final NotificationChannelGroup notificationChannelGroup = 323 new NotificationChannelGroup("test_group_id", "Test Group Name"); 324 when(mMockINotificationManager.getNotificationChannelGroupForPackage( 325 eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID))) 326 .thenReturn(notificationChannelGroup); 327 mNotificationInfo.bindNotification( 328 mMockPackageManager, 329 mMockINotificationManager, 330 mVisualStabilityManager, 331 TEST_PACKAGE_NAME, 332 mNotificationChannel, 333 mNotificationChannelSet, 334 mSbn, 335 null, 336 null, 337 null, 338 true, 339 false, 340 IMPORTANCE_DEFAULT, 341 true); 342 final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name); 343 assertEquals(View.VISIBLE, groupNameView.getVisibility()); 344 assertEquals("Test Group Name", groupNameView.getText()); 345 } 346 347 @Test testBindNotification_SetsTextChannelName()348 public void testBindNotification_SetsTextChannelName() throws Exception { 349 mNotificationInfo.bindNotification( 350 mMockPackageManager, 351 mMockINotificationManager, 352 mVisualStabilityManager, 353 TEST_PACKAGE_NAME, 354 mNotificationChannel, 355 mNotificationChannelSet, 356 mSbn, 357 null, 358 null, 359 null, 360 true, 361 false, 362 IMPORTANCE_DEFAULT, 363 true); 364 final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); 365 assertEquals(TEST_CHANNEL_NAME, textView.getText()); 366 } 367 368 @Test testBindNotification_DefaultChannelDoesNotUseChannelName()369 public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception { 370 mNotificationInfo.bindNotification( 371 mMockPackageManager, 372 mMockINotificationManager, 373 mVisualStabilityManager, 374 TEST_PACKAGE_NAME, 375 mDefaultNotificationChannel, 376 mDefaultNotificationChannelSet, 377 mSbn, 378 null, 379 null, 380 null, 381 true, 382 false, 383 IMPORTANCE_DEFAULT, 384 true); 385 final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); 386 assertEquals(GONE, textView.getVisibility()); 387 } 388 389 @Test testBindNotification_DefaultChannelUsesChannelNameIfMoreChannelsExist()390 public void testBindNotification_DefaultChannelUsesChannelNameIfMoreChannelsExist() 391 throws Exception { 392 // Package has one channel by default. 393 when(mMockINotificationManager.getNumNotificationChannelsForPackage( 394 eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10); 395 mNotificationInfo.bindNotification( 396 mMockPackageManager, 397 mMockINotificationManager, 398 mVisualStabilityManager, 399 TEST_PACKAGE_NAME, 400 mDefaultNotificationChannel, 401 mDefaultNotificationChannelSet, 402 mSbn, 403 null, 404 null, 405 null, 406 true, 407 false, 408 IMPORTANCE_DEFAULT, 409 true); 410 final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); 411 assertEquals(VISIBLE, textView.getVisibility()); 412 } 413 414 @Test testBindNotification_UnblockablePackageUsesChannelName()415 public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception { 416 mNotificationInfo.bindNotification( 417 mMockPackageManager, 418 mMockINotificationManager, 419 mVisualStabilityManager, 420 TEST_PACKAGE_NAME, 421 mNotificationChannel, 422 mNotificationChannelSet, 423 mSbn, 424 null, 425 null, 426 null, 427 true, 428 true, 429 IMPORTANCE_DEFAULT, 430 true); 431 final TextView textView = mNotificationInfo.findViewById(R.id.channel_name); 432 assertEquals(VISIBLE, textView.getVisibility()); 433 } 434 435 @Test testBindNotification_BlockLink_BlockingHelper()436 public void testBindNotification_BlockLink_BlockingHelper() throws Exception { 437 mNotificationInfo.bindNotification( 438 mMockPackageManager, 439 mMockINotificationManager, 440 mVisualStabilityManager, 441 TEST_PACKAGE_NAME, 442 mNotificationChannel, 443 mNotificationChannelSet, 444 mSbn, 445 null, 446 mock(NotificationInfo.OnSettingsClickListener.class), 447 null, 448 true, 449 false, 450 true /* isBlockingHelper */, 451 IMPORTANCE_DEFAULT, 452 true); 453 final View block = 454 mNotificationInfo.findViewById(R.id.blocking_helper_turn_off_notifications); 455 final View interruptivenessSettings = mNotificationInfo.findViewById( 456 R.id.inline_controls); 457 assertEquals(VISIBLE, block.getVisibility()); 458 assertEquals(GONE, interruptivenessSettings.getVisibility()); 459 } 460 461 @Test testBindNotification_SetsOnClickListenerForSettings()462 public void testBindNotification_SetsOnClickListenerForSettings() throws Exception { 463 final CountDownLatch latch = new CountDownLatch(1); 464 mNotificationInfo.bindNotification( 465 mMockPackageManager, 466 mMockINotificationManager, 467 mVisualStabilityManager, 468 TEST_PACKAGE_NAME, 469 mNotificationChannel, 470 mNotificationChannelSet, 471 mSbn, 472 null, 473 (View v, NotificationChannel c, int appUid) -> { 474 assertEquals(mNotificationChannel, c); 475 latch.countDown(); 476 }, 477 null, 478 true, 479 false, 480 IMPORTANCE_DEFAULT, 481 true); 482 483 final View settingsButton = mNotificationInfo.findViewById(R.id.info); 484 settingsButton.performClick(); 485 // Verify that listener was triggered. 486 assertEquals(0, latch.getCount()); 487 } 488 489 @Test testBindNotification_SettingsButtonInvisibleWhenNoClickListener()490 public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception { 491 mNotificationInfo.bindNotification( 492 mMockPackageManager, 493 mMockINotificationManager, 494 mVisualStabilityManager, 495 TEST_PACKAGE_NAME, 496 mNotificationChannel, 497 mNotificationChannelSet, 498 mSbn, 499 null, 500 null, 501 null, 502 true, 503 false, 504 IMPORTANCE_DEFAULT, 505 true); 506 final View settingsButton = mNotificationInfo.findViewById(R.id.info); 507 assertTrue(settingsButton.getVisibility() != View.VISIBLE); 508 } 509 510 @Test testBindNotification_SettingsButtonInvisibleWhenDeviceUnprovisioned()511 public void testBindNotification_SettingsButtonInvisibleWhenDeviceUnprovisioned() 512 throws Exception { 513 mNotificationInfo.bindNotification( 514 mMockPackageManager, 515 mMockINotificationManager, 516 mVisualStabilityManager, 517 TEST_PACKAGE_NAME, 518 mNotificationChannel, 519 mNotificationChannelSet, 520 mSbn, 521 null, 522 (View v, NotificationChannel c, int appUid) -> { 523 assertEquals(mNotificationChannel, c); 524 }, 525 null, 526 false, 527 false, 528 IMPORTANCE_DEFAULT, 529 true); 530 final View settingsButton = mNotificationInfo.findViewById(R.id.info); 531 assertTrue(settingsButton.getVisibility() != View.VISIBLE); 532 } 533 534 @Test testBindNotification_SettingsButtonReappearsAfterSecondBind()535 public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception { 536 mNotificationInfo.bindNotification( 537 mMockPackageManager, 538 mMockINotificationManager, 539 mVisualStabilityManager, 540 TEST_PACKAGE_NAME, 541 mNotificationChannel, 542 mNotificationChannelSet, 543 mSbn, 544 null, 545 null, 546 null, 547 true, 548 false, 549 IMPORTANCE_DEFAULT, 550 true); 551 mNotificationInfo.bindNotification( 552 mMockPackageManager, 553 mMockINotificationManager, 554 mVisualStabilityManager, 555 TEST_PACKAGE_NAME, 556 mNotificationChannel, 557 mNotificationChannelSet, 558 mSbn, 559 null, 560 (View v, NotificationChannel c, int appUid) -> { }, 561 null, 562 true, 563 false, 564 IMPORTANCE_DEFAULT, 565 true); 566 final View settingsButton = mNotificationInfo.findViewById(R.id.info); 567 assertEquals(View.VISIBLE, settingsButton.getVisibility()); 568 } 569 570 @Test testBindNotificationLogging_notBlockingHelper()571 public void testBindNotificationLogging_notBlockingHelper() throws Exception { 572 mNotificationInfo.bindNotification( 573 mMockPackageManager, 574 mMockINotificationManager, 575 mVisualStabilityManager, 576 TEST_PACKAGE_NAME, 577 mNotificationChannel, 578 mNotificationChannelSet, 579 mSbn, 580 null, 581 null, 582 null, 583 true, 584 false, 585 IMPORTANCE_DEFAULT, 586 true); 587 verify(mMetricsLogger).write(argThat(logMaker -> 588 logMaker.getCategory() == MetricsEvent.ACTION_NOTE_CONTROLS 589 && logMaker.getType() == MetricsEvent.TYPE_OPEN 590 && logMaker.getSubtype() == MetricsEvent.BLOCKING_HELPER_UNKNOWN 591 )); 592 } 593 594 @Test testBindNotificationLogging_BlockingHelper()595 public void testBindNotificationLogging_BlockingHelper() throws Exception { 596 mNotificationInfo.bindNotification( 597 mMockPackageManager, 598 mMockINotificationManager, 599 mVisualStabilityManager, 600 TEST_PACKAGE_NAME, 601 mNotificationChannel, 602 mNotificationChannelSet, 603 mSbn, 604 null, 605 null, 606 null, 607 false, 608 true, 609 true, 610 IMPORTANCE_DEFAULT, 611 true); 612 verify(mMetricsLogger).write(argThat(logMaker -> 613 logMaker.getCategory() == MetricsEvent.ACTION_NOTE_CONTROLS 614 && logMaker.getType() == MetricsEvent.TYPE_OPEN 615 && logMaker.getSubtype() == MetricsEvent.BLOCKING_HELPER_DISPLAY 616 )); 617 } 618 619 @Test testLogBlockingHelperCounter_logsForBlockingHelper()620 public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception { 621 mNotificationInfo.bindNotification( 622 mMockPackageManager, 623 mMockINotificationManager, 624 mVisualStabilityManager, 625 TEST_PACKAGE_NAME, 626 mNotificationChannel, 627 mNotificationChannelSet, 628 mSbn, 629 null, 630 null, 631 null, 632 false, 633 true, 634 true, 635 IMPORTANCE_DEFAULT, 636 true); 637 mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent"); 638 verify(mMetricsLogger).count(eq("HowCanNotifsBeRealIfAppsArent"), eq(1)); 639 } 640 641 @Test testOnClickListenerPassesNullChannelForBundle()642 public void testOnClickListenerPassesNullChannelForBundle() throws Exception { 643 final CountDownLatch latch = new CountDownLatch(1); 644 mNotificationInfo.bindNotification( 645 mMockPackageManager, 646 mMockINotificationManager, 647 mVisualStabilityManager, 648 TEST_PACKAGE_NAME, mNotificationChannel, 649 createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT), 650 mSbn, 651 null, 652 (View v, NotificationChannel c, int appUid) -> { 653 assertEquals(null, c); 654 latch.countDown(); 655 }, 656 null, 657 true, 658 true, 659 IMPORTANCE_DEFAULT, 660 true); 661 662 mNotificationInfo.findViewById(R.id.info).performClick(); 663 // Verify that listener was triggered. 664 assertEquals(0, latch.getCount()); 665 } 666 667 @Test 668 @UiThreadTest testBindNotification_ChannelNameInvisibleWhenBundleFromDifferentChannels()669 public void testBindNotification_ChannelNameInvisibleWhenBundleFromDifferentChannels() 670 throws Exception { 671 mNotificationInfo.bindNotification( 672 mMockPackageManager, 673 mMockINotificationManager, 674 mVisualStabilityManager, 675 TEST_PACKAGE_NAME, 676 mNotificationChannel, 677 createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT), 678 mSbn, 679 null, 680 null, 681 null, 682 true, 683 false, 684 IMPORTANCE_DEFAULT, 685 true); 686 final TextView channelNameView = 687 mNotificationInfo.findViewById(R.id.channel_name); 688 assertEquals(GONE, channelNameView.getVisibility()); 689 } 690 691 @Test 692 @UiThreadTest testStopInvisibleIfBundleFromDifferentChannels()693 public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception { 694 mNotificationInfo.bindNotification( 695 mMockPackageManager, 696 mMockINotificationManager, 697 mVisualStabilityManager, 698 TEST_PACKAGE_NAME, 699 mNotificationChannel, 700 createMultipleChannelSet(MULTIPLE_CHANNEL_COUNT), 701 mSbn, 702 null, 703 null, 704 null, 705 true, 706 false, 707 IMPORTANCE_DEFAULT, 708 true); 709 assertEquals(GONE, mNotificationInfo.findViewById( 710 R.id.interruptiveness_settings).getVisibility()); 711 assertEquals(VISIBLE, mNotificationInfo.findViewById( 712 R.id.non_configurable_multichannel_text).getVisibility()); 713 } 714 715 @Test testBindNotification_whenAppUnblockable()716 public void testBindNotification_whenAppUnblockable() throws Exception { 717 mNotificationInfo.bindNotification( 718 mMockPackageManager, 719 mMockINotificationManager, 720 mVisualStabilityManager, 721 TEST_PACKAGE_NAME, 722 mNotificationChannel, 723 mNotificationChannelSet, 724 mSbn, 725 null, 726 null, 727 null, 728 true, 729 true, 730 IMPORTANCE_DEFAULT, 731 true); 732 final TextView view = mNotificationInfo.findViewById(R.id.non_configurable_text); 733 assertEquals(View.VISIBLE, view.getVisibility()); 734 assertEquals(mContext.getString(R.string.notification_unblockable_desc), 735 view.getText()); 736 assertEquals(GONE, 737 mNotificationInfo.findViewById(R.id.interruptiveness_settings).getVisibility()); 738 } 739 740 @Test testBindNotification_DoesNotUpdateNotificationChannel()741 public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception { 742 mNotificationInfo.bindNotification( 743 mMockPackageManager, 744 mMockINotificationManager, 745 mVisualStabilityManager, 746 TEST_PACKAGE_NAME, 747 mNotificationChannel, 748 mNotificationChannelSet, 749 mSbn, 750 null, 751 null, 752 null, 753 true, 754 false, 755 IMPORTANCE_DEFAULT, 756 true); 757 mTestableLooper.processAllMessages(); 758 verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( 759 anyString(), eq(TEST_UID), any()); 760 } 761 762 @Test testDoesNotUpdateNotificationChannelAfterImportanceChanged()763 public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception { 764 mNotificationChannel.setImportance(IMPORTANCE_LOW); 765 mNotificationInfo.bindNotification( 766 mMockPackageManager, 767 mMockINotificationManager, 768 mVisualStabilityManager, 769 TEST_PACKAGE_NAME, 770 mNotificationChannel, 771 mNotificationChannelSet, 772 mSbn, 773 null, 774 null, 775 null, 776 true, 777 false, 778 IMPORTANCE_LOW, 779 false); 780 781 mNotificationInfo.findViewById(R.id.alert).performClick(); 782 mTestableLooper.processAllMessages(); 783 verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( 784 anyString(), eq(TEST_UID), any()); 785 } 786 787 @Test testDoesNotUpdateNotificationChannelAfterImportanceChangedSilenced()788 public void testDoesNotUpdateNotificationChannelAfterImportanceChangedSilenced() 789 throws Exception { 790 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 791 mNotificationInfo.bindNotification( 792 mMockPackageManager, 793 mMockINotificationManager, 794 mVisualStabilityManager, 795 TEST_PACKAGE_NAME, 796 mNotificationChannel, 797 mNotificationChannelSet, 798 mSbn, 799 null, 800 null, 801 null, 802 true, 803 false, 804 IMPORTANCE_DEFAULT, 805 true); 806 807 mNotificationInfo.findViewById(R.id.silence).performClick(); 808 mTestableLooper.processAllMessages(); 809 verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( 810 anyString(), eq(TEST_UID), any()); 811 } 812 813 @Test testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()814 public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged() 815 throws Exception { 816 int originalImportance = mNotificationChannel.getImportance(); 817 mNotificationInfo.bindNotification( 818 mMockPackageManager, 819 mMockINotificationManager, 820 mVisualStabilityManager, 821 TEST_PACKAGE_NAME, 822 mNotificationChannel, 823 mNotificationChannelSet, 824 mSbn, 825 null, 826 null, 827 null, 828 true, 829 false, 830 IMPORTANCE_DEFAULT, 831 true); 832 833 mNotificationInfo.handleCloseControls(true, false); 834 mTestableLooper.processAllMessages(); 835 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 836 anyString(), eq(TEST_UID), any()); 837 assertEquals(originalImportance, mNotificationChannel.getImportance()); 838 } 839 840 @Test testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()841 public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified() 842 throws Exception { 843 mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED); 844 mNotificationInfo.bindNotification( 845 mMockPackageManager, 846 mMockINotificationManager, 847 mVisualStabilityManager, 848 TEST_PACKAGE_NAME, 849 mNotificationChannel, 850 mNotificationChannelSet, 851 mSbn, 852 null, 853 null, 854 null, 855 true, 856 false, 857 IMPORTANCE_UNSPECIFIED, 858 true); 859 860 mNotificationInfo.handleCloseControls(true, false); 861 862 mTestableLooper.processAllMessages(); 863 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 864 anyString(), eq(TEST_UID), any()); 865 assertEquals(IMPORTANCE_UNSPECIFIED, mNotificationChannel.getImportance()); 866 } 867 868 @Test testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing_BlockingHelper()869 public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing_BlockingHelper() 870 throws Exception { 871 NotificationInfo.CheckSaveListener listener = 872 mock(NotificationInfo.CheckSaveListener.class); 873 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 874 mNotificationInfo.bindNotification( 875 mMockPackageManager, 876 mMockINotificationManager, 877 mVisualStabilityManager, 878 TEST_PACKAGE_NAME, 879 mNotificationChannel /* notificationChannel */, 880 createMultipleChannelSet(10) /* numUniqueChannelsInRow */, 881 mSbn, 882 listener /* checkSaveListener */, 883 null /* onSettingsClick */, 884 null /* onAppSettingsClick */, 885 true /* provisioned */, 886 false /* isNonblockable */, 887 true /* isForBlockingHelper */, 888 IMPORTANCE_DEFAULT, 889 true); 890 891 NotificationGuts guts = spy(new NotificationGuts(mContext, null)); 892 when(guts.getWindowToken()).thenReturn(mock(IBinder.class)); 893 doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean()); 894 doNothing().when(guts).setExposed(anyBoolean(), anyBoolean()); 895 guts.setGutsContent(mNotificationInfo); 896 mNotificationInfo.setGutsParent(guts); 897 898 mNotificationInfo.findViewById(R.id.keep_showing).performClick(); 899 900 verify(mBlockingHelperManager).dismissCurrentBlockingHelper(); 901 mTestableLooper.processAllMessages(); 902 verify(mMockINotificationManager, times(1)) 903 .setNotificationsEnabledWithImportanceLockForPackage( 904 anyString(), eq(TEST_UID), eq(true)); 905 } 906 907 @Test testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss_BlockingHelper()908 public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss_BlockingHelper() 909 throws Exception { 910 NotificationInfo.CheckSaveListener listener = 911 mock(NotificationInfo.CheckSaveListener.class); 912 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 913 mNotificationInfo.bindNotification( 914 mMockPackageManager, 915 mMockINotificationManager, 916 mVisualStabilityManager, 917 TEST_PACKAGE_NAME, 918 mNotificationChannel /* notificationChannel */, 919 createMultipleChannelSet(10) /* numUniqueChannelsInRow */, 920 mSbn, 921 listener /* checkSaveListener */, 922 null /* onSettingsClick */, 923 null /* onAppSettingsClick */, 924 false /* isNonblockable */, 925 true /* isForBlockingHelper */, 926 true, IMPORTANCE_DEFAULT, 927 true); 928 929 mNotificationInfo.handleCloseControls(true /* save */, false /* force */); 930 931 mTestableLooper.processAllMessages(); 932 verify(listener, times(0)).checkSave(any(Runnable.class), eq(mSbn)); 933 } 934 935 @Test testCloseControls_checkSaveListenerDelaysStopNotifications_BlockingHelper()936 public void testCloseControls_checkSaveListenerDelaysStopNotifications_BlockingHelper() 937 throws Exception { 938 NotificationInfo.CheckSaveListener listener = 939 mock(NotificationInfo.CheckSaveListener.class); 940 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 941 mNotificationInfo.bindNotification( 942 mMockPackageManager, 943 mMockINotificationManager, 944 mVisualStabilityManager, 945 TEST_PACKAGE_NAME, 946 mNotificationChannel /* notificationChannel */, 947 createMultipleChannelSet(10) /* numUniqueChannelsInRow */, 948 mSbn, 949 listener /* checkSaveListener */, 950 null /* onSettingsClick */, 951 null /* onAppSettingsClick */, 952 true /* provisioned */, 953 false /* isNonblockable */, 954 true /* isForBlockingHelper */, 955 IMPORTANCE_DEFAULT, 956 true); 957 958 mNotificationInfo.findViewById(R.id.deliver_silently).performClick(); 959 mTestableLooper.processAllMessages(); 960 verify(listener).checkSave(any(Runnable.class), eq(mSbn)); 961 } 962 963 @Test testCloseControls_blockingHelperDismissedIfShown()964 public void testCloseControls_blockingHelperDismissedIfShown() throws Exception { 965 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 966 mNotificationInfo.bindNotification( 967 mMockPackageManager, 968 mMockINotificationManager, 969 mVisualStabilityManager, 970 TEST_PACKAGE_NAME, 971 mNotificationChannel, 972 mNotificationChannelSet /* numChannels */, 973 mSbn, 974 null /* checkSaveListener */, 975 null /* onSettingsClick */, 976 null /* onAppSettingsClick */, 977 false /* isNonblockable */, 978 true /* isForBlockingHelper */, 979 true, 980 IMPORTANCE_DEFAULT, 981 true); 982 NotificationGuts guts = mock(NotificationGuts.class); 983 doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean()); 984 mNotificationInfo.setGutsParent(guts); 985 986 mNotificationInfo.closeControls(mNotificationInfo, true); 987 988 verify(mBlockingHelperManager).dismissCurrentBlockingHelper(); 989 } 990 991 @Test testSilentlyChangedCallsUpdateNotificationChannel_blockingHelper()992 public void testSilentlyChangedCallsUpdateNotificationChannel_blockingHelper() 993 throws Exception { 994 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 995 mNotificationInfo.bindNotification( 996 mMockPackageManager, 997 mMockINotificationManager, 998 mVisualStabilityManager, 999 TEST_PACKAGE_NAME, 1000 mNotificationChannel, 1001 mNotificationChannelSet /* numChannels */, 1002 mSbn, 1003 null /* checkSaveListener */, 1004 null /* onSettingsClick */, 1005 null /* onAppSettingsClick */, 1006 true /*provisioned */, 1007 false /* isNonblockable */, 1008 true /* isForBlockingHelper */, 1009 IMPORTANCE_DEFAULT, 1010 true); 1011 1012 mNotificationInfo.findViewById(R.id.deliver_silently).performClick(); 1013 waitForUndoButton(); 1014 mNotificationInfo.handleCloseControls(true, false); 1015 1016 mTestableLooper.processAllMessages(); 1017 ArgumentCaptor<NotificationChannel> updated = 1018 ArgumentCaptor.forClass(NotificationChannel.class); 1019 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1020 anyString(), eq(TEST_UID), updated.capture()); 1021 assertTrue((updated.getValue().getUserLockedFields() 1022 & USER_LOCKED_IMPORTANCE) != 0); 1023 assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance()); 1024 } 1025 1026 @Test testKeepUpdatesNotificationChannel_blockingHelper()1027 public void testKeepUpdatesNotificationChannel_blockingHelper() throws Exception { 1028 mNotificationChannel.setImportance(IMPORTANCE_LOW); 1029 mNotificationInfo.bindNotification( 1030 mMockPackageManager, 1031 mMockINotificationManager, 1032 mVisualStabilityManager, 1033 TEST_PACKAGE_NAME, 1034 mNotificationChannel, 1035 mNotificationChannelSet, 1036 mSbn, 1037 null, 1038 null, 1039 null, 1040 true, 1041 true, 1042 IMPORTANCE_LOW, 1043 false); 1044 1045 mNotificationInfo.findViewById(R.id.keep_showing).performClick(); 1046 mNotificationInfo.handleCloseControls(true, false); 1047 1048 mTestableLooper.processAllMessages(); 1049 ArgumentCaptor<NotificationChannel> updated = 1050 ArgumentCaptor.forClass(NotificationChannel.class); 1051 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1052 anyString(), eq(TEST_UID), updated.capture()); 1053 assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE)); 1054 assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance()); 1055 } 1056 1057 @Test testNoActionsUpdatesNotificationChannel_blockingHelper()1058 public void testNoActionsUpdatesNotificationChannel_blockingHelper() throws Exception { 1059 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 1060 mNotificationInfo.bindNotification( 1061 mMockPackageManager, 1062 mMockINotificationManager, 1063 mVisualStabilityManager, 1064 TEST_PACKAGE_NAME, 1065 mNotificationChannel, 1066 mNotificationChannelSet, 1067 mSbn, 1068 null, 1069 null, 1070 null, 1071 true, 1072 true, 1073 IMPORTANCE_DEFAULT, 1074 true); 1075 1076 mNotificationInfo.handleCloseControls(true, false); 1077 1078 mTestableLooper.processAllMessages(); 1079 ArgumentCaptor<NotificationChannel> updated = 1080 ArgumentCaptor.forClass(NotificationChannel.class); 1081 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1082 anyString(), eq(TEST_UID), updated.capture()); 1083 assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE)); 1084 assertEquals(IMPORTANCE_DEFAULT, mNotificationChannel.getImportance()); 1085 } 1086 1087 @Test testSilenceCallsUpdateNotificationChannel()1088 public void testSilenceCallsUpdateNotificationChannel() throws Exception { 1089 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 1090 mNotificationInfo.bindNotification( 1091 mMockPackageManager, 1092 mMockINotificationManager, 1093 mVisualStabilityManager, 1094 TEST_PACKAGE_NAME, 1095 mNotificationChannel, 1096 mNotificationChannelSet, 1097 mSbn, 1098 null, 1099 null, 1100 null, 1101 true, 1102 false, 1103 IMPORTANCE_DEFAULT, 1104 true); 1105 1106 mNotificationInfo.findViewById(R.id.silence).performClick(); 1107 mNotificationInfo.findViewById(R.id.done).performClick(); 1108 mNotificationInfo.handleCloseControls(true, false); 1109 1110 mTestableLooper.processAllMessages(); 1111 ArgumentCaptor<NotificationChannel> updated = 1112 ArgumentCaptor.forClass(NotificationChannel.class); 1113 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1114 anyString(), eq(TEST_UID), updated.capture()); 1115 assertTrue((updated.getValue().getUserLockedFields() 1116 & USER_LOCKED_IMPORTANCE) != 0); 1117 assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance()); 1118 } 1119 1120 @Test testUnSilenceCallsUpdateNotificationChannel()1121 public void testUnSilenceCallsUpdateNotificationChannel() throws Exception { 1122 mNotificationChannel.setImportance(IMPORTANCE_LOW); 1123 mNotificationInfo.bindNotification( 1124 mMockPackageManager, 1125 mMockINotificationManager, 1126 mVisualStabilityManager, 1127 TEST_PACKAGE_NAME, 1128 mNotificationChannel, 1129 mNotificationChannelSet, 1130 mSbn, 1131 null, 1132 null, 1133 null, 1134 true, 1135 false, 1136 IMPORTANCE_LOW, 1137 false); 1138 1139 mNotificationInfo.findViewById(R.id.alert).performClick(); 1140 mNotificationInfo.findViewById(R.id.done).performClick(); 1141 mNotificationInfo.handleCloseControls(true, false); 1142 1143 mTestableLooper.processAllMessages(); 1144 ArgumentCaptor<NotificationChannel> updated = 1145 ArgumentCaptor.forClass(NotificationChannel.class); 1146 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1147 anyString(), eq(TEST_UID), updated.capture()); 1148 assertTrue((updated.getValue().getUserLockedFields() 1149 & USER_LOCKED_IMPORTANCE) != 0); 1150 assertEquals(IMPORTANCE_DEFAULT, updated.getValue().getImportance()); 1151 } 1152 1153 @Test testSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()1154 public void testSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified() 1155 throws Exception { 1156 mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED); 1157 mNotificationInfo.bindNotification( 1158 mMockPackageManager, 1159 mMockINotificationManager, 1160 mVisualStabilityManager, 1161 TEST_PACKAGE_NAME, 1162 mNotificationChannel, 1163 mNotificationChannelSet, 1164 mSbn, 1165 null, 1166 null, 1167 null, 1168 true, 1169 false, 1170 IMPORTANCE_UNSPECIFIED, 1171 true); 1172 1173 mNotificationInfo.findViewById(R.id.silence).performClick(); 1174 mNotificationInfo.findViewById(R.id.done).performClick(); 1175 mNotificationInfo.handleCloseControls(true, false); 1176 1177 mTestableLooper.processAllMessages(); 1178 ArgumentCaptor<NotificationChannel> updated = 1179 ArgumentCaptor.forClass(NotificationChannel.class); 1180 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1181 anyString(), eq(TEST_UID), updated.capture()); 1182 assertTrue((updated.getValue().getUserLockedFields() 1183 & USER_LOCKED_IMPORTANCE) != 0); 1184 assertEquals(IMPORTANCE_LOW, updated.getValue().getImportance()); 1185 } 1186 1187 @Test testSilenceCallsUpdateNotificationChannel_channelImportanceMin()1188 public void testSilenceCallsUpdateNotificationChannel_channelImportanceMin() 1189 throws Exception { 1190 mNotificationChannel.setImportance(IMPORTANCE_MIN); 1191 mNotificationInfo.bindNotification( 1192 mMockPackageManager, 1193 mMockINotificationManager, 1194 mVisualStabilityManager, 1195 TEST_PACKAGE_NAME, 1196 mNotificationChannel, 1197 mNotificationChannelSet, 1198 mSbn, 1199 null, 1200 null, 1201 null, 1202 true, 1203 false, 1204 IMPORTANCE_MIN, 1205 false); 1206 1207 assertEquals(mContext.getString(R.string.inline_done_button), 1208 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); 1209 mNotificationInfo.findViewById(R.id.silence).performClick(); 1210 assertEquals(mContext.getString(R.string.inline_done_button), 1211 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); 1212 mNotificationInfo.findViewById(R.id.done).performClick(); 1213 mNotificationInfo.handleCloseControls(true, false); 1214 1215 mTestableLooper.processAllMessages(); 1216 ArgumentCaptor<NotificationChannel> updated = 1217 ArgumentCaptor.forClass(NotificationChannel.class); 1218 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1219 anyString(), eq(TEST_UID), updated.capture()); 1220 assertTrue((updated.getValue().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); 1221 assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance()); 1222 } 1223 1224 @Test testAlertCallsUpdateNotificationChannel_channelImportanceMin()1225 public void testAlertCallsUpdateNotificationChannel_channelImportanceMin() 1226 throws Exception { 1227 mNotificationChannel.setImportance(IMPORTANCE_MIN); 1228 mNotificationInfo.bindNotification( 1229 mMockPackageManager, 1230 mMockINotificationManager, 1231 mVisualStabilityManager, 1232 TEST_PACKAGE_NAME, 1233 mNotificationChannel, 1234 mNotificationChannelSet, 1235 mSbn, 1236 null, 1237 null, 1238 null, 1239 true, 1240 false, 1241 IMPORTANCE_MIN, 1242 false); 1243 1244 assertEquals(mContext.getString(R.string.inline_done_button), 1245 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); 1246 mNotificationInfo.findViewById(R.id.alert).performClick(); 1247 assertEquals(mContext.getString(R.string.inline_ok_button), 1248 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); 1249 mNotificationInfo.findViewById(R.id.done).performClick(); 1250 mNotificationInfo.handleCloseControls(true, false); 1251 1252 mTestableLooper.processAllMessages(); 1253 ArgumentCaptor<NotificationChannel> updated = 1254 ArgumentCaptor.forClass(NotificationChannel.class); 1255 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1256 anyString(), eq(TEST_UID), updated.capture()); 1257 assertTrue((updated.getValue().getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); 1258 assertEquals(IMPORTANCE_DEFAULT, updated.getValue().getImportance()); 1259 } 1260 1261 @Test testAdjustImportanceTemporarilyAllowsReordering()1262 public void testAdjustImportanceTemporarilyAllowsReordering() throws Exception { 1263 mNotificationChannel.setImportance(IMPORTANCE_DEFAULT); 1264 mNotificationInfo.bindNotification( 1265 mMockPackageManager, 1266 mMockINotificationManager, 1267 mVisualStabilityManager, 1268 TEST_PACKAGE_NAME, 1269 mNotificationChannel, 1270 mNotificationChannelSet, 1271 mSbn, 1272 null, 1273 null, 1274 null, 1275 true, 1276 false, 1277 IMPORTANCE_DEFAULT, 1278 true); 1279 1280 mNotificationInfo.findViewById(R.id.silence).performClick(); 1281 mNotificationInfo.findViewById(R.id.done).performClick(); 1282 mNotificationInfo.handleCloseControls(true, false); 1283 1284 verify(mVisualStabilityManager).temporarilyAllowReordering(); 1285 } 1286 1287 @Test testDoneText()1288 public void testDoneText() 1289 throws Exception { 1290 mNotificationChannel.setImportance(IMPORTANCE_LOW); 1291 mNotificationInfo.bindNotification( 1292 mMockPackageManager, 1293 mMockINotificationManager, 1294 mVisualStabilityManager, 1295 TEST_PACKAGE_NAME, 1296 mNotificationChannel, 1297 mNotificationChannelSet, 1298 mSbn, 1299 null, 1300 null, 1301 null, 1302 true, 1303 false, 1304 IMPORTANCE_LOW, 1305 false); 1306 1307 assertEquals(mContext.getString(R.string.inline_done_button), 1308 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); 1309 mNotificationInfo.findViewById(R.id.alert).performClick(); 1310 assertEquals(mContext.getString(R.string.inline_ok_button), 1311 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); 1312 mNotificationInfo.findViewById(R.id.silence).performClick(); 1313 assertEquals(mContext.getString(R.string.inline_done_button), 1314 ((TextView) mNotificationInfo.findViewById(R.id.done)).getText()); 1315 } 1316 1317 @Test testUnSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified()1318 public void testUnSilenceCallsUpdateNotificationChannel_channelImportanceUnspecified() 1319 throws Exception { 1320 mNotificationChannel.setImportance(IMPORTANCE_LOW); 1321 mNotificationInfo.bindNotification( 1322 mMockPackageManager, 1323 mMockINotificationManager, 1324 mVisualStabilityManager, 1325 TEST_PACKAGE_NAME, 1326 mNotificationChannel, 1327 mNotificationChannelSet, 1328 mSbn, 1329 null, 1330 null, 1331 null, 1332 true, 1333 false, 1334 IMPORTANCE_LOW, 1335 false); 1336 1337 mNotificationInfo.findViewById(R.id.alert).performClick(); 1338 mNotificationInfo.findViewById(R.id.done).performClick(); 1339 mNotificationInfo.handleCloseControls(true, false); 1340 1341 mTestableLooper.processAllMessages(); 1342 ArgumentCaptor<NotificationChannel> updated = 1343 ArgumentCaptor.forClass(NotificationChannel.class); 1344 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1345 anyString(), eq(TEST_UID), updated.capture()); 1346 assertTrue((updated.getValue().getUserLockedFields() 1347 & USER_LOCKED_IMPORTANCE) != 0); 1348 assertEquals(IMPORTANCE_DEFAULT, updated.getValue().getImportance()); 1349 } 1350 1351 @Test testCloseControlsDoesNotUpdateIfSaveIsFalse()1352 public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception { 1353 mNotificationChannel.setImportance(IMPORTANCE_LOW); 1354 mNotificationInfo.bindNotification( 1355 mMockPackageManager, 1356 mMockINotificationManager, 1357 mVisualStabilityManager, 1358 TEST_PACKAGE_NAME, 1359 mNotificationChannel, 1360 mNotificationChannelSet, 1361 mSbn, 1362 null, 1363 null, 1364 null, 1365 true, 1366 false, 1367 IMPORTANCE_LOW, 1368 false); 1369 1370 mNotificationInfo.findViewById(R.id.alert).performClick(); 1371 mNotificationInfo.findViewById(R.id.done).performClick(); 1372 mNotificationInfo.handleCloseControls(false, false); 1373 1374 mTestableLooper.processAllMessages(); 1375 verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( 1376 eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel)); 1377 } 1378 1379 @Test testCloseControlsUpdatesWhenCheckSaveListenerUsesCallback()1380 public void testCloseControlsUpdatesWhenCheckSaveListenerUsesCallback() throws Exception { 1381 mNotificationChannel.setImportance(IMPORTANCE_LOW); 1382 mNotificationInfo.bindNotification( 1383 mMockPackageManager, 1384 mMockINotificationManager, 1385 mVisualStabilityManager, 1386 TEST_PACKAGE_NAME, 1387 mNotificationChannel, 1388 mNotificationChannelSet, 1389 mSbn, 1390 (Runnable saveImportance, StatusBarNotification sbn) -> { 1391 saveImportance.run(); 1392 }, 1393 null, 1394 null, 1395 true, 1396 false, 1397 IMPORTANCE_LOW, 1398 false 1399 ); 1400 1401 mNotificationInfo.findViewById(R.id.alert).performClick(); 1402 mNotificationInfo.findViewById(R.id.done).performClick(); 1403 mTestableLooper.processAllMessages(); 1404 verify(mMockINotificationManager, never()).updateNotificationChannelForPackage( 1405 eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel)); 1406 1407 mNotificationInfo.handleCloseControls(true, false); 1408 1409 mTestableLooper.processAllMessages(); 1410 verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage( 1411 eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel)); 1412 } 1413 1414 @Test testCloseControls_withoutHittingApply()1415 public void testCloseControls_withoutHittingApply() throws Exception { 1416 mNotificationChannel.setImportance(IMPORTANCE_LOW); 1417 mNotificationInfo.bindNotification( 1418 mMockPackageManager, 1419 mMockINotificationManager, 1420 mVisualStabilityManager, 1421 TEST_PACKAGE_NAME, 1422 mNotificationChannel, 1423 mNotificationChannelSet, 1424 mSbn, 1425 (Runnable saveImportance, StatusBarNotification sbn) -> { 1426 saveImportance.run(); 1427 }, 1428 null, 1429 null, 1430 true, 1431 false, 1432 IMPORTANCE_LOW, 1433 false 1434 ); 1435 1436 mNotificationInfo.findViewById(R.id.alert).performClick(); 1437 1438 assertFalse(mNotificationInfo.shouldBeSaved()); 1439 } 1440 1441 @Test testWillBeRemovedReturnsFalse()1442 public void testWillBeRemovedReturnsFalse() throws Exception { 1443 assertFalse(mNotificationInfo.willBeRemoved()); 1444 1445 mNotificationInfo.bindNotification( 1446 mMockPackageManager, 1447 mMockINotificationManager, 1448 mVisualStabilityManager, 1449 TEST_PACKAGE_NAME, 1450 mNotificationChannel, 1451 mNotificationChannelSet, 1452 mSbn, 1453 (Runnable saveImportance, StatusBarNotification sbn) -> { 1454 saveImportance.run(); 1455 }, 1456 null, 1457 null, 1458 true, 1459 false, 1460 IMPORTANCE_LOW, 1461 false 1462 ); 1463 1464 assertFalse(mNotificationInfo.willBeRemoved()); 1465 } 1466 createMultipleChannelSet(int howMany)1467 private Set<NotificationChannel> createMultipleChannelSet(int howMany) { 1468 Set<NotificationChannel> multiChannelSet = new HashSet<>(); 1469 for (int i = 0; i < howMany; i++) { 1470 if (i == 0) { 1471 multiChannelSet.add(mNotificationChannel); 1472 continue; 1473 } 1474 1475 NotificationChannel channel = new NotificationChannel( 1476 TEST_CHANNEL, TEST_CHANNEL_NAME + i, IMPORTANCE_LOW); 1477 1478 multiChannelSet.add(channel); 1479 } 1480 1481 return multiChannelSet; 1482 } 1483 } 1484