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
17package com.android.systemui.statusbar;
18
19import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
20import static android.app.NotificationManager.IMPORTANCE_LOW;
21import static android.app.NotificationManager.IMPORTANCE_MIN;
22import static android.app.NotificationManager.IMPORTANCE_NONE;
23import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
24import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
25import static android.view.View.GONE;
26import static android.view.View.VISIBLE;
27
28import static junit.framework.Assert.assertEquals;
29import static junit.framework.Assert.assertFalse;
30import static junit.framework.Assert.assertTrue;
31
32import static org.mockito.Mockito.any;
33import static org.mockito.Mockito.anyBoolean;
34import static org.mockito.Mockito.anyInt;
35import static org.mockito.Mockito.anyString;
36import static org.mockito.Mockito.doCallRealMethod;
37import static org.mockito.Mockito.doNothing;
38import static org.mockito.Mockito.eq;
39import static org.mockito.Mockito.mock;
40import static org.mockito.Mockito.never;
41import static org.mockito.Mockito.spy;
42import static org.mockito.Mockito.times;
43import static org.mockito.Mockito.verify;
44import static org.mockito.Mockito.when;
45
46import android.app.INotificationManager;
47import android.app.Notification;
48import android.app.NotificationChannel;
49import android.app.NotificationChannelGroup;
50import android.content.Intent;
51import android.content.pm.ActivityInfo;
52import android.content.pm.ApplicationInfo;
53import android.content.pm.PackageInfo;
54import android.content.pm.PackageManager;
55import android.content.pm.ResolveInfo;
56import android.graphics.drawable.Drawable;
57import android.os.IBinder;
58import android.os.UserHandle;
59import android.service.notification.StatusBarNotification;
60import android.test.suitebuilder.annotation.SmallTest;
61import android.testing.AndroidTestingRunner;
62import android.testing.PollingCheck;
63import android.testing.TestableLooper;
64import android.testing.UiThreadTest;
65import android.view.LayoutInflater;
66import android.view.View;
67import android.widget.ImageView;
68import android.widget.TextView;
69
70import com.android.internal.logging.MetricsLogger;
71import com.android.systemui.Dependency;
72import com.android.systemui.R;
73import com.android.systemui.SysuiTestCase;
74
75import org.junit.Before;
76import org.junit.Rule;
77import org.junit.Test;
78import org.junit.runner.RunWith;
79import org.mockito.ArgumentCaptor;
80import org.mockito.Mock;
81import org.mockito.junit.MockitoJUnit;
82import org.mockito.junit.MockitoRule;
83
84import java.util.ArrayList;
85import java.util.List;
86import java.util.concurrent.CountDownLatch;
87
88@SmallTest
89@RunWith(AndroidTestingRunner.class)
90@TestableLooper.RunWithLooper
91public class NotificationInfoTest extends SysuiTestCase {
92    private static final String TEST_PACKAGE_NAME = "test_package";
93    private static final String TEST_SYSTEM_PACKAGE_NAME = PRINT_SPOOLER_PACKAGE_NAME;
94    private static final int TEST_UID = 1;
95    private static final int MULTIPLE_CHANNEL_COUNT = 2;
96    private static final String TEST_CHANNEL = "test_channel";
97    private static final String TEST_CHANNEL_NAME = "TEST CHANNEL NAME";
98
99    private TestableLooper mTestableLooper;
100    private NotificationInfo mNotificationInfo;
101    private NotificationChannel mNotificationChannel;
102    private NotificationChannel mDefaultNotificationChannel;
103    private StatusBarNotification mSbn;
104
105    @Rule public MockitoRule mockito = MockitoJUnit.rule();
106    @Mock private MetricsLogger mMetricsLogger;
107    @Mock private INotificationManager mMockINotificationManager;
108    @Mock private PackageManager mMockPackageManager;
109    @Mock private NotificationBlockingHelperManager mBlockingHelperManager;
110
111    @Before
112    public void setUp() throws Exception {
113        mDependency.injectTestDependency(
114                NotificationBlockingHelperManager.class,
115                mBlockingHelperManager);
116        mTestableLooper = TestableLooper.get(this);
117        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
118        mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
119        // Inflate the layout
120        final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
121        mNotificationInfo = (NotificationInfo) layoutInflater.inflate(R.layout.notification_info,
122                null);
123        mNotificationInfo.setGutsParent(mock(NotificationGuts.class));
124
125        // PackageManager must return a packageInfo and applicationInfo.
126        final PackageInfo packageInfo = new PackageInfo();
127        packageInfo.packageName = TEST_PACKAGE_NAME;
128        when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt()))
129                .thenReturn(packageInfo);
130        final ApplicationInfo applicationInfo = new ApplicationInfo();
131        applicationInfo.uid = TEST_UID;  // non-zero
132        when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
133                applicationInfo);
134        final PackageInfo systemPackageInfo = new PackageInfo();
135        systemPackageInfo.packageName = TEST_SYSTEM_PACKAGE_NAME;
136        when(mMockPackageManager.getPackageInfo(eq(TEST_SYSTEM_PACKAGE_NAME), anyInt()))
137                .thenReturn(systemPackageInfo);
138        when(mMockPackageManager.getPackageInfo(eq("android"), anyInt()))
139                .thenReturn(packageInfo);
140
141        // Package has one channel by default.
142        when(mMockINotificationManager.getNumNotificationChannelsForPackage(
143                eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(1);
144
145        // Some test channels.
146        mNotificationChannel = new NotificationChannel(
147                TEST_CHANNEL, TEST_CHANNEL_NAME, IMPORTANCE_LOW);
148        mDefaultNotificationChannel = new NotificationChannel(
149                NotificationChannel.DEFAULT_CHANNEL_ID, TEST_CHANNEL_NAME,
150                IMPORTANCE_LOW);
151        mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
152                new Notification(), UserHandle.CURRENT, null, 0);
153    }
154
155    // TODO: if tests are taking too long replace this with something that makes the animation
156    // finish instantly.
157    private void waitForUndoButton() {
158        PollingCheck.waitFor(1000,
159                () -> VISIBLE == mNotificationInfo.findViewById(R.id.confirmation).getVisibility());
160    }
161    private void waitForStopButton() {
162        PollingCheck.waitFor(1000,
163                () -> VISIBLE == mNotificationInfo.findViewById(R.id.prompt).getVisibility());
164    }
165
166    @Test
167    public void testBindNotification_SetsTextApplicationName() throws Exception {
168        when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
169        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
170                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
171        final TextView textView = mNotificationInfo.findViewById(R.id.pkgname);
172        assertTrue(textView.getText().toString().contains("App Name"));
173        assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
174    }
175
176    @Test
177    public void testBindNotification_SetsPackageIcon() throws Exception {
178        final Drawable iconDrawable = mock(Drawable.class);
179        when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
180                .thenReturn(iconDrawable);
181        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
182                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
183        final ImageView iconView = mNotificationInfo.findViewById(R.id.pkgicon);
184        assertEquals(iconDrawable, iconView.getDrawable());
185    }
186
187    @Test
188    public void testBindNotification_GroupNameHiddenIfNoGroup() throws Exception {
189        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
190                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
191        final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
192        assertEquals(GONE, groupNameView.getVisibility());
193        final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
194        assertEquals(GONE, groupDividerView.getVisibility());
195    }
196
197    @Test
198    public void testBindNotification_SetsGroupNameIfNonNull() throws Exception {
199        mNotificationChannel.setGroup("test_group_id");
200        final NotificationChannelGroup notificationChannelGroup =
201                new NotificationChannelGroup("test_group_id", "Test Group Name");
202        when(mMockINotificationManager.getNotificationChannelGroupForPackage(
203                eq("test_group_id"), eq(TEST_PACKAGE_NAME), eq(TEST_UID)))
204                .thenReturn(notificationChannelGroup);
205        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
206                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
207        final TextView groupNameView = mNotificationInfo.findViewById(R.id.group_name);
208        assertEquals(View.VISIBLE, groupNameView.getVisibility());
209        assertEquals("Test Group Name", groupNameView.getText());
210        final TextView groupDividerView = mNotificationInfo.findViewById(R.id.pkg_group_divider);
211        assertEquals(View.VISIBLE, groupDividerView.getVisibility());
212    }
213
214    @Test
215    public void testBindNotification_SetsTextChannelName() throws Exception {
216        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
217                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
218        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
219        assertEquals(TEST_CHANNEL_NAME, textView.getText());
220    }
221
222    @Test
223    public void testBindNotification_DefaultChannelDoesNotUseChannelName() throws Exception {
224        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
225                TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, false);
226        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
227        assertEquals(GONE, textView.getVisibility());
228    }
229
230    @Test
231    public void testBindNotification_DefaultChannelUsesChannelNameIfMoreChannelsExist()
232            throws Exception {
233        // Package has one channel by default.
234        when(mMockINotificationManager.getNumNotificationChannelsForPackage(
235                eq(TEST_PACKAGE_NAME), eq(TEST_UID), anyBoolean())).thenReturn(10);
236        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
237                TEST_PACKAGE_NAME, mDefaultNotificationChannel, 1, mSbn, null, null, null, false);
238        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
239        assertEquals(VISIBLE, textView.getVisibility());
240    }
241
242    @Test
243    public void testBindNotification_UnblockablePackageUsesChannelName() throws Exception {
244        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
245                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
246        final TextView textView = mNotificationInfo.findViewById(R.id.channel_name);
247        assertEquals(VISIBLE, textView.getVisibility());
248    }
249
250    @Test
251    public void testBindNotification_BlockButton() throws Exception {
252       mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
253                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
254        final View block = mNotificationInfo.findViewById(R.id.block);
255        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
256        assertEquals(VISIBLE, block.getVisibility());
257        assertEquals(GONE, minimize.getVisibility());
258    }
259
260    @Test
261    public void testBindNotification_MinButton() throws Exception {
262        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
263        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
264                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
265        final View block = mNotificationInfo.findViewById(R.id.block);
266        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
267        assertEquals(GONE, block.getVisibility());
268        assertEquals(VISIBLE, minimize.getVisibility());
269    }
270
271    @Test
272    public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
273        final CountDownLatch latch = new CountDownLatch(1);
274        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
275                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
276                (View v, NotificationChannel c, int appUid) -> {
277                    assertEquals(mNotificationChannel, c);
278                    latch.countDown();
279                }, null, false);
280
281        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
282        settingsButton.performClick();
283        // Verify that listener was triggered.
284        assertEquals(0, latch.getCount());
285    }
286
287    @Test
288    public void testBindNotification_SettingsButtonInvisibleWhenNoClickListener() throws Exception {
289        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
290                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
291        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
292        assertTrue(settingsButton.getVisibility() != View.VISIBLE);
293    }
294
295    @Test
296    public void testBindNotification_SettingsButtonReappearsAfterSecondBind() throws Exception {
297        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
298                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
299        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
300                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null,
301                (View v, NotificationChannel c, int appUid) -> {
302                }, null, false);
303        final View settingsButton = mNotificationInfo.findViewById(R.id.info);
304        assertEquals(View.VISIBLE, settingsButton.getVisibility());
305    }
306
307    @Test
308    public void testLogBlockingHelperCounter_doesntLogForNormalGutsView() throws Exception {
309        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
310                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
311        mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
312        verify(mMetricsLogger, times(0)).count(anyString(), anyInt());
313    }
314
315    @Test
316    public void testLogBlockingHelperCounter_logsForBlockingHelper() throws Exception {
317        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
318                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, true,
319                true);
320        mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
321        verify(mMetricsLogger, times(1)).count(anyString(), anyInt());
322    }
323
324    @Test
325    public void testOnClickListenerPassesNullChannelForBundle() throws Exception {
326        final CountDownLatch latch = new CountDownLatch(1);
327        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
328                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null,
329                (View v, NotificationChannel c, int appUid) -> {
330                    assertEquals(null, c);
331                    latch.countDown();
332                }, null, true);
333
334        mNotificationInfo.findViewById(R.id.info).performClick();
335        // Verify that listener was triggered.
336        assertEquals(0, latch.getCount());
337    }
338
339    @Test
340    @UiThreadTest
341    public void testBindNotification_ChannelNameInvisibleWhenBundleFromDifferentChannels()
342            throws Exception {
343        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
344                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
345                null, true);
346        final TextView channelNameView =
347                mNotificationInfo.findViewById(R.id.channel_name);
348        assertEquals(GONE, channelNameView.getVisibility());
349    }
350
351    @Test
352    @UiThreadTest
353    public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
354        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
355                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
356                null, true);
357        final TextView blockView = mNotificationInfo.findViewById(R.id.block);
358        assertEquals(GONE, blockView.getVisibility());
359    }
360
361    @Test
362    public void testbindNotification_BlockingHelper() throws Exception {
363        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
364                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false, false,
365                true);
366        final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
367        assertEquals(View.VISIBLE, view.getVisibility());
368        assertEquals(mContext.getString(R.string.inline_blocking_helper), view.getText());
369    }
370
371    @Test
372    public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
373        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
374                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
375        final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
376        assertEquals(View.VISIBLE, view.getVisibility());
377        assertEquals(mContext.getString(R.string.notification_unblockable_desc),
378                view.getText());
379    }
380
381    @Test
382    public void testBindNotification_DoesNotUpdateNotificationChannel() throws Exception {
383        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
384                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
385        mTestableLooper.processAllMessages();
386        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
387                anyString(), eq(TEST_UID), any());
388    }
389
390    @Test
391    public void testDoesNotUpdateNotificationChannelAfterImportanceChanged() throws Exception {
392        mNotificationChannel.setImportance(IMPORTANCE_LOW);
393        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
394                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
395
396        mNotificationInfo.findViewById(R.id.block).performClick();
397        mTestableLooper.processAllMessages();
398        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
399                anyString(), eq(TEST_UID), any());
400    }
401
402    @Test
403    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedMin()
404            throws Exception {
405        mNotificationChannel.setImportance(IMPORTANCE_LOW);
406        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
407                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
408
409        mNotificationInfo.findViewById(R.id.minimize).performClick();
410        mTestableLooper.processAllMessages();
411        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
412                anyString(), eq(TEST_UID), any());
413    }
414
415    @Test
416    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnchanged()
417            throws Exception {
418        int originalImportance = mNotificationChannel.getImportance();
419        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
420                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
421
422        mNotificationInfo.handleCloseControls(true, false);
423        mTestableLooper.processAllMessages();
424        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
425                anyString(), eq(TEST_UID), any());
426        assertEquals(originalImportance, mNotificationChannel.getImportance());
427    }
428
429    @Test
430    public void testHandleCloseControls_DoesNotUpdateNotificationChannelIfUnspecified()
431            throws Exception {
432        mNotificationChannel.setImportance(IMPORTANCE_UNSPECIFIED);
433        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
434                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
435
436        mNotificationInfo.handleCloseControls(true, false);
437
438        mTestableLooper.processAllMessages();
439        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
440                anyString(), eq(TEST_UID), any());
441        assertEquals(IMPORTANCE_UNSPECIFIED, mNotificationChannel.getImportance());
442    }
443
444    @Test
445    public void testHandleCloseControls_setsNotificationsDisabledForMultipleChannelNotifications()
446            throws Exception {
447        mNotificationChannel.setImportance(IMPORTANCE_LOW);
448        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
449                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
450                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
451                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
452                false /* isNonblockable */);
453
454        mNotificationInfo.findViewById(R.id.block).performClick();
455        waitForUndoButton();
456        mNotificationInfo.handleCloseControls(true, false);
457
458        mTestableLooper.processAllMessages();
459        verify(mMockINotificationManager, times(1))
460                .setNotificationsEnabledWithImportanceLockForPackage(
461                        anyString(), eq(TEST_UID), eq(false));
462    }
463
464
465    @Test
466    public void testHandleCloseControls_keepsNotificationsEnabledForMultipleChannelNotifications()
467            throws Exception {
468        mNotificationChannel.setImportance(IMPORTANCE_LOW);
469        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
470                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
471                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
472                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
473                false /* isNonblockable */);
474
475        mNotificationInfo.findViewById(R.id.block).performClick();
476        waitForUndoButton();
477        mNotificationInfo.handleCloseControls(true, false);
478
479        mTestableLooper.processAllMessages();
480        verify(mMockINotificationManager, times(1))
481                .setNotificationsEnabledWithImportanceLockForPackage(
482                        anyString(), eq(TEST_UID), eq(false));
483    }
484
485    @Test
486    public void testCloseControls_blockingHelperSavesImportanceForMultipleChannelNotifications()
487            throws Exception {
488        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
489                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
490                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
491                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
492                false /* isNonblockable */, true /* isForBlockingHelper */,
493                true /* isUserSentimentNegative */);
494
495        NotificationGuts guts = spy(new NotificationGuts(mContext, null));
496        when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
497        doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
498        doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
499        guts.setGutsContent(mNotificationInfo);
500        mNotificationInfo.setGutsParent(guts);
501
502        mNotificationInfo.findViewById(R.id.keep).performClick();
503
504        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
505        mTestableLooper.processAllMessages();
506        verify(mMockINotificationManager, times(1))
507                .setNotificationsEnabledWithImportanceLockForPackage(
508                        anyString(), eq(TEST_UID), eq(true));
509    }
510
511    @Test
512    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing()
513            throws Exception {
514        NotificationInfo.CheckSaveListener listener =
515                mock(NotificationInfo.CheckSaveListener.class);
516        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
517                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
518                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
519                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
520                false /* isNonblockable */, true /* isForBlockingHelper */,
521                true /* isUserSentimentNegative */);
522
523        NotificationGuts guts = spy(new NotificationGuts(mContext, null));
524        when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
525        doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
526        doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
527        guts.setGutsContent(mNotificationInfo);
528        mNotificationInfo.setGutsParent(guts);
529
530        mNotificationInfo.findViewById(R.id.keep).performClick();
531
532        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
533        mTestableLooper.processAllMessages();
534        verify(mMockINotificationManager, times(1))
535                .setNotificationsEnabledWithImportanceLockForPackage(
536                        anyString(), eq(TEST_UID), eq(true));
537    }
538
539    @Test
540    public void testCloseControls_nonNullCheckSaveListenerDoesntDelayDismiss()
541            throws Exception {
542        NotificationInfo.CheckSaveListener listener =
543                mock(NotificationInfo.CheckSaveListener.class);
544        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
545                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
546                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
547                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
548                false /* isNonblockable */, true /* isForBlockingHelper */,
549                true /* isUserSentimentNegative */);
550
551        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
552
553        mTestableLooper.processAllMessages();
554        verify(listener, times(0)).checkSave(any(Runnable.class), eq(mSbn));
555    }
556
557    @Test
558    public void testCloseControls_checkSaveListenerDelaysStopNotifications()
559            throws Exception {
560        NotificationInfo.CheckSaveListener listener =
561                mock(NotificationInfo.CheckSaveListener.class);
562        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
563                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
564                10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
565                null /* onSettingsClick */, null /* onAppSettingsClick */ ,
566                false /* isNonblockable */, true /* isForBlockingHelper */,
567                true /* isUserSentimentNegative */);
568
569        mNotificationInfo.findViewById(R.id.block).performClick();
570        waitForUndoButton();
571        mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
572
573        mTestableLooper.processAllMessages();
574        verify(listener).checkSave(any(Runnable.class), eq(mSbn));
575    }
576
577    @Test
578    public void testCloseControls_blockingHelperDismissedIfShown() throws Exception {
579        mNotificationInfo.bindNotification(
580                mMockPackageManager,
581                mMockINotificationManager,
582                TEST_PACKAGE_NAME,
583                mNotificationChannel,
584                1 /* numChannels */,
585                mSbn,
586                null /* checkSaveListener */,
587                null /* onSettingsClick */,
588                null /* onAppSettingsClick */,
589                false /* isNonblockable */,
590                true /* isForBlockingHelper */,
591                false /* isUserSentimentNegative */);
592        NotificationGuts guts = mock(NotificationGuts.class);
593        doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
594        mNotificationInfo.setGutsParent(guts);
595
596        mNotificationInfo.closeControls(mNotificationInfo);
597
598        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
599    }
600
601    @Test
602    public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
603        mNotificationChannel.setImportance(IMPORTANCE_LOW);
604        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
605                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
606        mNotificationInfo.findViewById(R.id.block).performClick();
607        waitForUndoButton();
608
609        mTestableLooper.processAllMessages();
610        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
611                anyString(), eq(TEST_UID), any());
612    }
613
614    @Test
615    public void testBlockChangedCallsUpdateNotificationChannel() throws Exception {
616        mNotificationChannel.setImportance(IMPORTANCE_LOW);
617        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
618                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
619
620        mNotificationInfo.findViewById(R.id.block).performClick();
621        waitForUndoButton();
622        mNotificationInfo.handleCloseControls(true, false);
623
624        mTestableLooper.processAllMessages();
625        ArgumentCaptor<NotificationChannel> updated =
626                ArgumentCaptor.forClass(NotificationChannel.class);
627        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
628                anyString(), eq(TEST_UID), updated.capture());
629        assertTrue((updated.getValue().getUserLockedFields()
630                & USER_LOCKED_IMPORTANCE) != 0);
631        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
632    }
633
634    @Test
635    public void testBlockChangedCallsUpdateNotificationChannel_blockingHelper() throws Exception {
636        mNotificationChannel.setImportance(IMPORTANCE_LOW);
637        mNotificationInfo.bindNotification(
638                mMockPackageManager,
639                mMockINotificationManager,
640                TEST_PACKAGE_NAME,
641                mNotificationChannel,
642                1 /* numChannels */,
643                mSbn,
644                null /* checkSaveListener */,
645                null /* onSettingsClick */,
646                null /* onAppSettingsClick */,
647                false /* isNonblockable */,
648                true /* isForBlockingHelper */,
649                true /* isUserSentimentNegative */);
650
651        mNotificationInfo.findViewById(R.id.block).performClick();
652        waitForUndoButton();
653        mNotificationInfo.handleCloseControls(true, false);
654
655        mTestableLooper.processAllMessages();
656        ArgumentCaptor<NotificationChannel> updated =
657                ArgumentCaptor.forClass(NotificationChannel.class);
658        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
659                anyString(), eq(TEST_UID), updated.capture());
660        assertTrue((updated.getValue().getUserLockedFields()
661                & USER_LOCKED_IMPORTANCE) != 0);
662        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
663    }
664
665
666    @Test
667    public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
668        mNotificationChannel.setImportance(IMPORTANCE_LOW);
669        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
670                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
671        mNotificationInfo.findViewById(R.id.minimize).performClick();
672        waitForUndoButton();
673
674        mTestableLooper.processAllMessages();
675        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
676                anyString(), eq(TEST_UID), any());
677    }
678
679    @Test
680    public void testMinChangedCallsUpdateNotificationChannel() throws Exception {
681        mNotificationChannel.setImportance(IMPORTANCE_LOW);
682        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
683        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
684                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
685
686        mNotificationInfo.findViewById(R.id.minimize).performClick();
687        waitForUndoButton();
688        mNotificationInfo.handleCloseControls(true, false);
689
690        mTestableLooper.processAllMessages();
691        ArgumentCaptor<NotificationChannel> updated =
692                ArgumentCaptor.forClass(NotificationChannel.class);
693        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
694                anyString(), eq(TEST_UID), updated.capture());
695        assertTrue((updated.getValue().getUserLockedFields()
696                & USER_LOCKED_IMPORTANCE) != 0);
697        assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance());
698    }
699
700    @Test
701    public void testKeepUpdatesNotificationChannel() throws Exception {
702        mNotificationChannel.setImportance(IMPORTANCE_LOW);
703        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
704                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
705
706        mNotificationInfo.handleCloseControls(true, false);
707
708        mTestableLooper.processAllMessages();
709        ArgumentCaptor<NotificationChannel> updated =
710                ArgumentCaptor.forClass(NotificationChannel.class);
711        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
712                anyString(), eq(TEST_UID), updated.capture());
713        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
714        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
715    }
716
717    @Test
718    public void testBlockUndoDoesNotBlockNotificationChannel() throws Exception {
719        mNotificationChannel.setImportance(IMPORTANCE_LOW);
720        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
721                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
722
723        mNotificationInfo.findViewById(R.id.block).performClick();
724        waitForUndoButton();
725        mNotificationInfo.findViewById(R.id.undo).performClick();
726        waitForStopButton();
727        mNotificationInfo.handleCloseControls(true, false);
728
729        mTestableLooper.processAllMessages();
730        ArgumentCaptor<NotificationChannel> updated =
731                ArgumentCaptor.forClass(NotificationChannel.class);
732        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
733                anyString(), eq(TEST_UID), updated.capture());
734        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
735        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
736    }
737
738    @Test
739    public void testMinUndoDoesNotMinNotificationChannel() throws Exception {
740        mNotificationChannel.setImportance(IMPORTANCE_LOW);
741        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
742                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, false);
743
744        mNotificationInfo.findViewById(R.id.minimize).performClick();
745        waitForUndoButton();
746        mNotificationInfo.findViewById(R.id.undo).performClick();
747        waitForStopButton();
748        mNotificationInfo.handleCloseControls(true, false);
749
750        mTestableLooper.processAllMessages();
751        ArgumentCaptor<NotificationChannel> updated =
752                ArgumentCaptor.forClass(NotificationChannel.class);
753        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
754                anyString(), eq(TEST_UID), updated.capture());
755        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
756        assertEquals(IMPORTANCE_LOW, mNotificationChannel.getImportance());
757    }
758
759    @Test
760    public void testCloseControlsDoesNotUpdateiMinIfSaveIsFalse() throws Exception {
761        mNotificationChannel.setImportance(IMPORTANCE_LOW);
762        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
763                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
764
765        mNotificationInfo.findViewById(R.id.minimize).performClick();
766        waitForUndoButton();
767        mNotificationInfo.handleCloseControls(false, false);
768
769        mTestableLooper.processAllMessages();
770        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
771                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
772    }
773
774    @Test
775    public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
776        mNotificationChannel.setImportance(IMPORTANCE_LOW);
777        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
778                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
779
780        mNotificationInfo.findViewById(R.id.block).performClick();
781        waitForUndoButton();
782        mNotificationInfo.handleCloseControls(false, false);
783
784        mTestableLooper.processAllMessages();
785        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
786                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
787    }
788
789    @Test
790    public void testCloseControlsDoesNotUpdateIfCheckSaveListenerIsNoOp() throws Exception {
791        mNotificationChannel.setImportance(IMPORTANCE_LOW);
792        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
793                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
794                (Runnable saveImportance, StatusBarNotification sbn) -> {
795                }, null, null, true);
796
797        mNotificationInfo.findViewById(R.id.block).performClick();
798        waitForUndoButton();
799        mNotificationInfo.handleCloseControls(true, false);
800
801        mTestableLooper.processAllMessages();
802        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
803                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
804    }
805
806    @Test
807    public void testCloseControlsUpdatesWhenCheckSaveListenerUsesCallback() throws Exception {
808        mNotificationChannel.setImportance(IMPORTANCE_LOW);
809        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
810                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
811                (Runnable saveImportance, StatusBarNotification sbn) -> {
812                    saveImportance.run();
813                }, null, null, false);
814
815        mNotificationInfo.findViewById(R.id.block).performClick();
816        waitForUndoButton();
817        mNotificationInfo.handleCloseControls(true, false);
818
819        mTestableLooper.processAllMessages();
820        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
821                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
822    }
823
824    @Test
825    public void testDisplaySettingsLink() throws Exception {
826        final CountDownLatch latch = new CountDownLatch(1);
827        final String settingsText = "work chats";
828        final ResolveInfo ri = new ResolveInfo();
829        ri.activityInfo = new ActivityInfo();
830        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
831        ri.activityInfo.name = "something";
832        List<ResolveInfo> ris = new ArrayList<>();
833        ris.add(ri);
834        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
835        mNotificationChannel.setImportance(IMPORTANCE_LOW);
836        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
837                .setSettingsText(settingsText).build();
838        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
839                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
840
841        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
842                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null,
843                (View v, Intent intent) -> {
844                    latch.countDown();
845                }, false);
846        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
847        assertEquals(View.VISIBLE, settingsLink.getVisibility());
848        settingsLink.performClick();
849        assertEquals(0, latch.getCount());
850    }
851
852    @Test
853    public void testDisplaySettingsLink_multipleChannels() throws Exception {
854        final CountDownLatch latch = new CountDownLatch(1);
855        final String settingsText = "work chats";
856        final ResolveInfo ri = new ResolveInfo();
857        ri.activityInfo = new ActivityInfo();
858        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
859        ri.activityInfo.name = "something";
860        List<ResolveInfo> ris = new ArrayList<>();
861        ris.add(ri);
862        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
863        mNotificationChannel.setImportance(IMPORTANCE_LOW);
864        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
865                .setSettingsText(settingsText).build();
866        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
867                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
868
869        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
870                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
871                (View v, Intent intent) -> {
872                    latch.countDown();
873                }, false);
874        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
875        assertEquals(View.VISIBLE, settingsLink.getVisibility());
876        settingsLink.performClick();
877        assertEquals(0, latch.getCount());
878    }
879
880    @Test
881    public void testNoSettingsLink_noHandlingActivity() throws Exception {
882        final String settingsText = "work chats";
883        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(null);
884        mNotificationChannel.setImportance(IMPORTANCE_LOW);
885        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
886                .setSettingsText(settingsText).build();
887        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
888                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
889
890        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
891                TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, sbn, null, null,
892                null, false);
893        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
894        assertEquals(GONE, settingsLink.getVisibility());
895    }
896
897    @Test
898    public void testNoSettingsLink_noLinkText() throws Exception {
899        final ResolveInfo ri = new ResolveInfo();
900        ri.activityInfo = new ActivityInfo();
901        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
902        ri.activityInfo.name = "something";
903        List<ResolveInfo> ris = new ArrayList<>();
904        ris.add(ri);
905        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
906        mNotificationChannel.setImportance(IMPORTANCE_LOW);
907        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId()).build();
908        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
909                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
910
911        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
912                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false);
913        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
914        assertEquals(GONE, settingsLink.getVisibility());
915    }
916
917    @Test
918    public void testBindHeader_noSettingsLinkWhenIsForBlockingHelper() throws Exception {
919        final String settingsText = "work chats";
920        final ResolveInfo ri = new ResolveInfo();
921        ri.activityInfo = new ActivityInfo();
922        ri.activityInfo.packageName = TEST_PACKAGE_NAME;
923        ri.activityInfo.name = "something";
924        List<ResolveInfo> ris = new ArrayList<>();
925        ris.add(ri);
926        when(mMockPackageManager.queryIntentActivities(any(), anyInt())).thenReturn(ris);
927        mNotificationChannel.setImportance(IMPORTANCE_LOW);
928        Notification n = new Notification.Builder(mContext, mNotificationChannel.getId())
929                .setSettingsText(settingsText).build();
930        StatusBarNotification sbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME,
931                0, null, 0, 0, n, UserHandle.CURRENT, null, 0);
932
933        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
934                TEST_PACKAGE_NAME, mNotificationChannel, 1, sbn, null, null, null, false, true,
935                true);
936        final TextView settingsLink = mNotificationInfo.findViewById(R.id.app_settings);
937        assertEquals(GONE, settingsLink.getVisibility());
938    }
939
940
941    @Test
942    public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
943        assertFalse(mNotificationInfo.willBeRemoved());
944    }
945
946    @Test
947    public void testUndoText_min() throws Exception {
948        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
949        mNotificationChannel.setImportance(IMPORTANCE_LOW);
950        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
951                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
952
953        mNotificationInfo.findViewById(R.id.minimize).performClick();
954        waitForUndoButton();
955        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
956        assertTrue(confirmationText.getText().toString().contains("minimized"));
957    }
958
959    @Test
960    public void testUndoText_block() throws Exception {
961        mNotificationChannel.setImportance(IMPORTANCE_LOW);
962        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
963                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
964
965        mNotificationInfo.findViewById(R.id.block).performClick();
966        waitForUndoButton();
967        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
968        assertTrue(confirmationText.getText().toString().contains("won't see"));
969    }
970
971    @Test
972    public void testNoHeaderOnConfirmation() throws Exception {
973        mNotificationChannel.setImportance(IMPORTANCE_LOW);
974        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
975                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
976
977        mNotificationInfo.findViewById(R.id.block).performClick();
978        waitForUndoButton();
979        assertEquals(GONE, mNotificationInfo.findViewById(R.id.header).getVisibility());
980    }
981
982    @Test
983    public void testHeaderOnUndo() throws Exception {
984        mNotificationChannel.setImportance(IMPORTANCE_LOW);
985        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
986                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true);
987
988        mNotificationInfo.findViewById(R.id.block).performClick();
989        waitForUndoButton();
990        mNotificationInfo.findViewById(R.id.undo).performClick();
991        waitForStopButton();
992        assertEquals(VISIBLE, mNotificationInfo.findViewById(R.id.header).getVisibility());
993    }
994}
995