• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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