OSDN Git Service

Merge "Merge "docs: Described why ProgressDialog is now deprecated." into oc-dev...
[android-x86/frameworks-base.git] / services / tests / notification / src / com / android / server / notification / NotificationManagerServiceTest.java
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.server.notification;
18
19 import static android.app.NotificationManager.IMPORTANCE_LOW;
20 import static android.app.NotificationManager.IMPORTANCE_NONE;
21
22 import static junit.framework.Assert.assertEquals;
23 import static junit.framework.Assert.assertFalse;
24 import static junit.framework.Assert.assertTrue;
25 import static junit.framework.Assert.fail;
26
27 import static org.mockito.Matchers.anyBoolean;
28 import static org.mockito.Matchers.anyLong;
29 import static org.mockito.Matchers.anyString;
30 import static org.mockito.Matchers.eq;
31 import static org.mockito.Mockito.any;
32 import static org.mockito.Mockito.anyInt;
33 import static org.mockito.Mockito.mock;
34 import static org.mockito.Mockito.never;
35 import static org.mockito.Mockito.reset;
36 import static org.mockito.Mockito.times;
37 import static org.mockito.Mockito.verify;
38 import static org.mockito.Mockito.when;
39
40 import android.app.INotificationManager;
41 import android.app.Notification;
42 import android.app.NotificationChannel;
43 import android.app.NotificationChannelGroup;
44 import android.app.NotificationManager;
45 import android.companion.ICompanionDeviceManager;
46 import android.content.ComponentName;
47 import android.content.Context;
48 import android.content.pm.ApplicationInfo;
49 import android.content.pm.IPackageManager;
50 import android.content.pm.PackageManager;
51 import android.content.pm.ParceledListSlice;
52 import android.graphics.Color;
53 import android.os.Binder;
54 import android.os.Process;
55 import android.os.UserHandle;
56 import android.provider.Settings.Secure;
57 import android.service.notification.NotificationListenerService;
58 import android.service.notification.StatusBarNotification;
59 import android.test.suitebuilder.annotation.SmallTest;
60 import android.testing.AndroidTestingRunner;
61 import android.testing.TestableLooper;
62 import android.testing.TestableLooper.RunWithLooper;
63
64 import java.util.ArrayList;
65 import java.util.Arrays;
66 import java.util.List;
67
68 import org.junit.Before;
69 import org.junit.Test;
70 import org.junit.runner.RunWith;
71 import org.mockito.Mock;
72 import org.mockito.MockitoAnnotations;
73
74 import com.android.server.lights.Light;
75 import com.android.server.lights.LightsManager;
76
77 @SmallTest
78 @RunWith(AndroidTestingRunner.class)
79 @RunWithLooper
80 public class NotificationManagerServiceTest extends NotificationTestCase {
81     private static final long WAIT_FOR_IDLE_TIMEOUT = 2;
82     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
83     private final int uid = Binder.getCallingUid();
84     private NotificationManagerService mNotificationManagerService;
85     private INotificationManager mBinderService;
86     private NotificationManagerInternal mInternalService;
87     @Mock
88     private IPackageManager mPackageManager;
89     @Mock
90     private PackageManager mPackageManagerClient;
91     private Context mContext = getContext();
92     private final String PKG = mContext.getPackageName();
93     private TestableLooper mTestableLooper;
94     @Mock
95     private RankingHelper mRankingHelper;
96     @Mock
97     private NotificationUsageStats mUsageStats;
98     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
99             TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
100     @Mock
101     private NotificationManagerService.NotificationListeners mNotificationListeners;
102     private ManagedServices.ManagedServiceInfo mListener;
103     @Mock private ICompanionDeviceManager mCompanionMgr;
104     @Mock SnoozeHelper mSnoozeHelper;
105
106     // Use a Testable subclass so we can simulate calls from the system without failing.
107     private static class TestableNotificationManagerService extends NotificationManagerService {
108         public TestableNotificationManagerService(Context context) { super(context); }
109
110         @Override
111         protected boolean isCallingUidSystem() {
112             return true;
113         }
114
115         @Override
116         protected boolean isCallerSystemOrPhone() {
117             return true;
118         }
119
120         @Override
121         protected ICompanionDeviceManager getCompanionManager() {
122             return null;
123         }
124     }
125
126     @Before
127     public void setUp() throws Exception {
128         MockitoAnnotations.initMocks(this);
129
130         // most tests assume badging is enabled
131         Secure.putIntForUser(getContext().getContentResolver(),
132                 Secure.NOTIFICATION_BADGING, 1,
133                 UserHandle.getUserHandleForUid(uid).getIdentifier());
134
135         mNotificationManagerService = new TestableNotificationManagerService(mContext);
136
137         // MockPackageManager - default returns ApplicationInfo with matching calling UID
138         final ApplicationInfo applicationInfo = new ApplicationInfo();
139         applicationInfo.uid = uid;
140         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
141                 .thenReturn(applicationInfo);
142         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
143                 .thenReturn(applicationInfo);
144         final LightsManager mockLightsManager = mock(LightsManager.class);
145         when(mockLightsManager.getLight(anyInt())).thenReturn(mock(Light.class));
146         // Use this testable looper.
147         mTestableLooper = TestableLooper.get(this);
148
149         mListener = mNotificationListeners.new ManagedServiceInfo(
150                 null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
151         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
152         mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
153                 mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr,
154                 mSnoozeHelper, mUsageStats);
155
156         // Tests call directly into the Binder.
157         mBinderService = mNotificationManagerService.getBinderService();
158         mInternalService = mNotificationManagerService.getInternalService();
159
160         mBinderService.createNotificationChannels(
161                 PKG, new ParceledListSlice(Arrays.asList(mTestNotificationChannel)));
162     }
163
164     public void waitForIdle() throws Exception {
165         mTestableLooper.processAllMessages();
166     }
167
168     private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
169             String groupKey, boolean isSummary) {
170         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
171                 .setContentTitle("foo")
172                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
173                 .setGroup(groupKey)
174                 .setGroupSummary(isSummary);
175
176         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", uid, 0,
177                 nb.build(), new UserHandle(uid), null, 0);
178         return new NotificationRecord(mContext, sbn, channel);
179     }
180     private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
181         return generateNotificationRecord(channel, null);
182     }
183
184     private NotificationRecord generateNotificationRecord(NotificationChannel channel,
185             Notification.TvExtender extender) {
186         if (channel == null) {
187             channel = mTestNotificationChannel;
188         }
189         Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
190                 .setContentTitle("foo")
191                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
192         if (extender != null) {
193             nb.extend(extender);
194         }
195         StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", uid, 0,
196                 nb.build(), new UserHandle(uid), null, 0);
197         return new NotificationRecord(mContext, sbn, channel);
198     }
199
200     @Test
201     public void testCreateNotificationChannels_SingleChannel() throws Exception {
202         final NotificationChannel channel =
203                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
204         mBinderService.createNotificationChannels("test_pkg",
205                 new ParceledListSlice(Arrays.asList(channel)));
206         final NotificationChannel createdChannel =
207                 mBinderService.getNotificationChannel("test_pkg", "id");
208         assertTrue(createdChannel != null);
209     }
210
211     @Test
212     public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
213         try {
214             mBinderService.createNotificationChannels("test_pkg",
215                     new ParceledListSlice(Arrays.asList(null)));
216             fail("Exception should be thrown immediately.");
217         } catch (NullPointerException e) {
218             // pass
219         }
220     }
221
222     @Test
223     public void testCreateNotificationChannels_TwoChannels() throws Exception {
224         final NotificationChannel channel1 =
225                 new NotificationChannel("id1", "name", NotificationManager.IMPORTANCE_DEFAULT);
226         final NotificationChannel channel2 =
227                 new NotificationChannel("id2", "name", NotificationManager.IMPORTANCE_DEFAULT);
228         mBinderService.createNotificationChannels("test_pkg",
229                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
230         assertTrue(mBinderService.getNotificationChannel("test_pkg", "id1") != null);
231         assertTrue(mBinderService.getNotificationChannel("test_pkg", "id2") != null);
232     }
233
234     @Test
235     public void testCreateNotificationChannels_SecondCreateDoesNotChangeImportance()
236             throws Exception {
237         final NotificationChannel channel =
238                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
239         mBinderService.createNotificationChannels("test_pkg",
240                 new ParceledListSlice(Arrays.asList(channel)));
241
242         // Recreating the channel doesn't throw, but ignores importance.
243         final NotificationChannel dupeChannel =
244                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
245         mBinderService.createNotificationChannels("test_pkg",
246                 new ParceledListSlice(Arrays.asList(dupeChannel)));
247         final NotificationChannel createdChannel =
248                 mBinderService.getNotificationChannel("test_pkg", "id");
249         assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance());
250     }
251
252     @Test
253     public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
254             throws Exception {
255         final NotificationChannel channel1 =
256                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
257         final NotificationChannel channel2 =
258                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
259         mBinderService.createNotificationChannels("test_pkg",
260                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
261         final NotificationChannel createdChannel =
262                 mBinderService.getNotificationChannel("test_pkg", "id");
263         assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance());
264     }
265
266     @Test
267     public void testBlockedNotifications_suspended() throws Exception {
268         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
269
270         NotificationChannel channel = new NotificationChannel("id", "name",
271                 NotificationManager.IMPORTANCE_HIGH);
272         NotificationRecord r = generateNotificationRecord(channel);
273         assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
274         verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r));
275     }
276
277     @Test
278     public void testBlockedNotifications_blockedChannel() throws Exception {
279         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
280
281         NotificationChannel channel = new NotificationChannel("id", "name",
282                 NotificationManager.IMPORTANCE_HIGH);
283         channel.setImportance(NotificationManager.IMPORTANCE_NONE);
284         NotificationRecord r = generateNotificationRecord(channel);
285         assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
286         verify(mUsageStats, times(1)).registerBlocked(eq(r));
287     }
288
289     @Test
290     public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
291         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
292
293         mBinderService.setNotificationsEnabledForPackage(PKG, uid, false);
294
295         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
296         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
297                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
298         waitForIdle();
299         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
300     }
301
302     @Test
303     public void testEnqueueNotificationWithTag_PopulatesGetActiveNotifications() throws Exception {
304         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
305                 generateNotificationRecord(null).getNotification(), 0);
306         waitForIdle();
307         StatusBarNotification[] notifs =
308                 mBinderService.getActiveNotifications(PKG);
309         assertEquals(1, notifs.length);
310     }
311
312     @Test
313     public void testCancelNotificationImmediatelyAfterEnqueue() throws Exception {
314         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
315                 generateNotificationRecord(null).getNotification(), 0);
316         mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
317         waitForIdle();
318         StatusBarNotification[] notifs =
319                 mBinderService.getActiveNotifications(PKG);
320         assertEquals(0, notifs.length);
321     }
322
323     @Test
324     public void testCancelNotificationWhilePostedAndEnqueued() throws Exception {
325         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
326                 generateNotificationRecord(null).getNotification(), 0);
327         waitForIdle();
328         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
329                 generateNotificationRecord(null).getNotification(), 0);
330         mBinderService.cancelNotificationWithTag(PKG, "tag", 0, 0);
331         waitForIdle();
332         StatusBarNotification[] notifs =
333                 mBinderService.getActiveNotifications(PKG);
334         assertEquals(0, notifs.length);
335     }
336
337     @Test
338     public void testCancelNotificationsFromListenerImmediatelyAfterEnqueue() throws Exception {
339         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
340         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
341                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
342         mBinderService.cancelNotificationsFromListener(null, null);
343         waitForIdle();
344         StatusBarNotification[] notifs =
345                 mBinderService.getActiveNotifications(sbn.getPackageName());
346         assertEquals(0, notifs.length);
347     }
348
349     @Test
350     public void testCancelAllNotificationsImmediatelyAfterEnqueue() throws Exception {
351         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
352         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
353                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
354         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
355         waitForIdle();
356         StatusBarNotification[] notifs =
357                 mBinderService.getActiveNotifications(sbn.getPackageName());
358         assertEquals(0, notifs.length);
359     }
360
361     @Test
362     public void testCancelAllNotificationsMultipleEnqueuedDoesNotCrash() throws Exception {
363         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
364         for (int i = 0; i < 10; i++) {
365             mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
366                     sbn.getId(), sbn.getNotification(), sbn.getUserId());
367         }
368         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
369         waitForIdle();
370     }
371
372     @Test
373     public void testCancelGroupSummaryMultipleEnqueuedChildrenDoesNotCrash() throws Exception {
374         final NotificationRecord parent = generateNotificationRecord(
375                 mTestNotificationChannel, 1, "group1", true);
376         final NotificationRecord parentAsChild = generateNotificationRecord(
377                 mTestNotificationChannel, 1, "group1", false);
378         final NotificationRecord child = generateNotificationRecord(
379                 mTestNotificationChannel, 2, "group1", false);
380
381         // fully post parent notification
382         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
383                 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
384         waitForIdle();
385
386         // enqueue the child several times
387         for (int i = 0; i < 10; i++) {
388             mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
389                     child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
390         }
391         // make the parent a child, which will cancel the child notification
392         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
393                 parentAsChild.sbn.getId(), parentAsChild.sbn.getNotification(),
394                 parentAsChild.sbn.getUserId());
395         waitForIdle();
396     }
397
398     @Test
399     public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
400         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
401         sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
402         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
403                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
404         mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
405         waitForIdle();
406         StatusBarNotification[] notifs =
407                 mBinderService.getActiveNotifications(sbn.getPackageName());
408         assertEquals(1, notifs.length);
409     }
410
411     @Test
412     public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
413         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
414         sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
415         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
416                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
417         mBinderService.cancelAllNotifications("other_pkg_name", sbn.getUserId());
418         waitForIdle();
419         StatusBarNotification[] notifs =
420                 mBinderService.getActiveNotifications(sbn.getPackageName());
421         assertEquals(1, notifs.length);
422     }
423
424     @Test
425     public void testCancelAllNotifications_NullPkgRemovesAll() throws Exception {
426         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
427         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
428                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
429         mBinderService.cancelAllNotifications(null, sbn.getUserId());
430         waitForIdle();
431         StatusBarNotification[] notifs =
432                 mBinderService.getActiveNotifications(sbn.getPackageName());
433         assertEquals(0, notifs.length);
434     }
435
436     @Test
437     public void testCancelAllNotifications_NullPkgIgnoresUserAllNotifications() throws Exception {
438         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
439         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
440                 sbn.getId(), sbn.getNotification(), UserHandle.USER_ALL);
441         // Null pkg is how we signal a user switch.
442         mBinderService.cancelAllNotifications(null, sbn.getUserId());
443         waitForIdle();
444         StatusBarNotification[] notifs =
445                 mBinderService.getActiveNotifications(sbn.getPackageName());
446         assertEquals(1, notifs.length);
447     }
448
449     @Test
450     public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
451         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
452         sbn.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
453         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
454                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
455         mInternalService.removeForegroundServiceFlagFromNotification(PKG, sbn.getId(),
456                 sbn.getUserId());
457         waitForIdle();
458         StatusBarNotification[] notifs =
459                 mBinderService.getActiveNotifications(sbn.getPackageName());
460         assertEquals(0, notifs[0].getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE);
461     }
462
463     @Test
464     public void testCancelAfterSecondEnqueueDoesNotSpecifyForegroundFlag() throws Exception {
465         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
466         sbn.getNotification().flags =
467                 Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE;
468         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
469                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
470         sbn.getNotification().flags = Notification.FLAG_ONGOING_EVENT;
471         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
472                 sbn.getId(), sbn.getNotification(), sbn.getUserId());
473         mBinderService.cancelNotificationWithTag(PKG, "tag", sbn.getId(), sbn.getUserId());
474         waitForIdle();
475         assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
476     }
477
478     @Test
479     public void testFindGroupNotificationsLocked() throws Exception {
480         // make sure the same notification can be found in both lists and returned
481         final NotificationRecord group1 = generateNotificationRecord(
482                 mTestNotificationChannel, 1, "group1", true);
483         mNotificationManagerService.addEnqueuedNotification(group1);
484         mNotificationManagerService.addNotification(group1);
485
486         // should not be returned
487         final NotificationRecord group2 = generateNotificationRecord(
488                 mTestNotificationChannel, 2, "group2", true);
489         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
490                 group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
491         waitForIdle();
492
493         // should not be returned
494         final NotificationRecord nonGroup = generateNotificationRecord(
495                 mTestNotificationChannel, 3, null, false);
496         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
497                 nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
498         waitForIdle();
499
500         // same group, child, should be returned
501         final NotificationRecord group1Child = generateNotificationRecord(
502                 mTestNotificationChannel, 4, "group1", false);
503         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, group1Child.sbn.getId(),
504                 group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
505         waitForIdle();
506
507         List<NotificationRecord> inGroup1 =
508                 mNotificationManagerService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
509                         group1.sbn.getUserId());
510         assertEquals(3, inGroup1.size());
511         for (NotificationRecord record : inGroup1) {
512             assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
513             assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
514         }
515     }
516
517     @Test
518     public void testTvExtenderChannelOverride_onTv() throws Exception {
519         mNotificationManagerService.setIsTelevision(true);
520         mNotificationManagerService.setRankingHelper(mRankingHelper);
521         when(mRankingHelper.getNotificationChannel(
522                 anyString(), anyInt(), eq("foo"), anyBoolean())).thenReturn(
523                         new NotificationChannel("foo", "foo", NotificationManager.IMPORTANCE_HIGH));
524
525         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
526         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
527                 generateNotificationRecord(null, tv).getNotification(), 0);
528         verify(mRankingHelper, times(1)).getNotificationChannel(
529                 anyString(), anyInt(), eq("foo"), anyBoolean());
530     }
531
532     @Test
533     public void testTvExtenderChannelOverride_notOnTv() throws Exception {
534         mNotificationManagerService.setIsTelevision(false);
535         mNotificationManagerService.setRankingHelper(mRankingHelper);
536         when(mRankingHelper.getNotificationChannel(
537                 anyString(), anyInt(), anyString(), anyBoolean())).thenReturn(
538                 mTestNotificationChannel);
539
540         Notification.TvExtender tv = new Notification.TvExtender().setChannelId("foo");
541         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag", 0,
542                 generateNotificationRecord(null, tv).getNotification(), 0);
543         verify(mRankingHelper, times(1)).getNotificationChannel(
544                 anyString(), anyInt(), eq(mTestNotificationChannel.getId()), anyBoolean());
545     }
546
547     @Test
548     public void testCreateChannelNotifyListener() throws Exception {
549         List<String> associations = new ArrayList<>();
550         associations.add("a");
551         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
552         mNotificationManagerService.setRankingHelper(mRankingHelper);
553         when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
554                 eq(mTestNotificationChannel.getId()), anyBoolean()))
555                 .thenReturn(mTestNotificationChannel);
556         NotificationChannel channel2 = new NotificationChannel("a", "b", IMPORTANCE_LOW);
557         when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
558                 eq(channel2.getId()), anyBoolean()))
559                 .thenReturn(channel2);
560
561         reset(mNotificationListeners);
562         mBinderService.createNotificationChannels(PKG,
563                 new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
564         verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
565                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
566                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
567         verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
568                 eq(Process.myUserHandle()), eq(channel2),
569                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
570     }
571
572     @Test
573     public void testCreateChannelGroupNotifyListener() throws Exception {
574         List<String> associations = new ArrayList<>();
575         associations.add("a");
576         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
577         mNotificationManagerService.setRankingHelper(mRankingHelper);
578         NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
579         NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
580
581         reset(mNotificationListeners);
582         mBinderService.createNotificationChannelGroups(PKG,
583                 new ParceledListSlice(Arrays.asList(group1, group2)));
584         verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
585                 eq(Process.myUserHandle()), eq(group1),
586                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
587         verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
588                 eq(Process.myUserHandle()), eq(group2),
589                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
590     }
591
592     @Test
593     public void testUpdateChannelNotifyListener() throws Exception {
594         List<String> associations = new ArrayList<>();
595         associations.add("a");
596         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
597         mNotificationManagerService.setRankingHelper(mRankingHelper);
598         mTestNotificationChannel.setLightColor(Color.CYAN);
599         when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
600                 eq(mTestNotificationChannel.getId()), anyBoolean()))
601                 .thenReturn(mTestNotificationChannel);
602
603         reset(mNotificationListeners);
604         mBinderService.updateNotificationChannelForPackage(PKG, 0, mTestNotificationChannel);
605         verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
606                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
607                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
608     }
609
610     @Test
611     public void testDeleteChannelNotifyListener() throws Exception {
612         List<String> associations = new ArrayList<>();
613         associations.add("a");
614         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
615         mNotificationManagerService.setRankingHelper(mRankingHelper);
616         when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
617                 eq(mTestNotificationChannel.getId()), anyBoolean()))
618                 .thenReturn(mTestNotificationChannel);
619         reset(mNotificationListeners);
620         mBinderService.deleteNotificationChannel(PKG, mTestNotificationChannel.getId());
621         verify(mNotificationListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
622                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
623                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
624     }
625
626     @Test
627     public void testDeleteChannelGroupNotifyListener() throws Exception {
628         List<String> associations = new ArrayList<>();
629         associations.add("a");
630         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
631         NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
632         mNotificationManagerService.setRankingHelper(mRankingHelper);
633         when(mRankingHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
634                 .thenReturn(ncg);
635         reset(mNotificationListeners);
636         mBinderService.deleteNotificationChannelGroup(PKG, ncg.getId());
637         verify(mNotificationListeners, times(1)).notifyNotificationChannelGroupChanged(eq(PKG),
638                 eq(Process.myUserHandle()), eq(ncg),
639                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_DELETED));
640     }
641
642     @Test
643     public void testUpdateNotificationChannelFromPrivilegedListener_success() throws Exception {
644         mNotificationManagerService.setRankingHelper(mRankingHelper);
645         List<String> associations = new ArrayList<>();
646         associations.add("a");
647         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
648
649         mBinderService.updateNotificationChannelFromPrivilegedListener(
650                 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
651
652         verify(mRankingHelper, times(1)).updateNotificationChannel(anyString(), anyInt(), any());
653
654         verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
655                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
656                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
657     }
658
659     @Test
660     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
661         mNotificationManagerService.setRankingHelper(mRankingHelper);
662         List<String> associations = new ArrayList<>();
663         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
664
665         try {
666             mBinderService.updateNotificationChannelFromPrivilegedListener(
667                     null, PKG, Process.myUserHandle(), mTestNotificationChannel);
668             fail("listeners that don't have a companion device shouldn't be able to call this");
669         } catch (SecurityException e) {
670             // pass
671         }
672
673         verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any());
674
675         verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
676                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
677                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
678     }
679
680     @Test
681     public void testUpdateNotificationChannelFromPrivilegedListener_badUser() throws Exception {
682         mNotificationManagerService.setRankingHelper(mRankingHelper);
683         List<String> associations = new ArrayList<>();
684         associations.add("a");
685         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
686         mListener = mock(ManagedServices.ManagedServiceInfo.class);
687         mListener.component = new ComponentName(PKG, PKG);
688         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
689         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
690
691         try {
692             mBinderService.updateNotificationChannelFromPrivilegedListener(
693                     null, PKG, UserHandle.ALL, mTestNotificationChannel);
694             fail("incorrectly allowed a change to a user listener cannot see");
695         } catch (SecurityException e) {
696             // pass
697         }
698
699         verify(mRankingHelper, never()).updateNotificationChannel(anyString(), anyInt(), any());
700
701         verify(mNotificationListeners, never()).notifyNotificationChannelChanged(eq(PKG),
702                 eq(Process.myUserHandle()), eq(mTestNotificationChannel),
703                 eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
704     }
705
706     @Test
707     public void testGetNotificationChannelFromPrivilegedListener_success() throws Exception {
708         mNotificationManagerService.setRankingHelper(mRankingHelper);
709         List<String> associations = new ArrayList<>();
710         associations.add("a");
711         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
712
713         mBinderService.getNotificationChannelsFromPrivilegedListener(
714                 null, PKG, Process.myUserHandle());
715
716         verify(mRankingHelper, times(1)).getNotificationChannels(
717                 anyString(), anyInt(), anyBoolean());
718     }
719
720     @Test
721     public void testGetNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
722         mNotificationManagerService.setRankingHelper(mRankingHelper);
723         List<String> associations = new ArrayList<>();
724         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
725
726         try {
727             mBinderService.getNotificationChannelsFromPrivilegedListener(
728                     null, PKG, Process.myUserHandle());
729             fail("listeners that don't have a companion device shouldn't be able to call this");
730         } catch (SecurityException e) {
731             // pass
732         }
733
734         verify(mRankingHelper, never()).getNotificationChannels(
735                 anyString(), anyInt(), anyBoolean());
736     }
737
738     @Test
739     public void testGetNotificationChannelFromPrivilegedListener_badUser() throws Exception {
740         mNotificationManagerService.setRankingHelper(mRankingHelper);
741         List<String> associations = new ArrayList<>();
742         associations.add("a");
743         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
744         mListener = mock(ManagedServices.ManagedServiceInfo.class);
745         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
746         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
747
748         try {
749             mBinderService.getNotificationChannelsFromPrivilegedListener(
750                     null, PKG, Process.myUserHandle());
751             fail("listener getting channels from a user they cannot see");
752         } catch (SecurityException e) {
753             // pass
754         }
755
756         verify(mRankingHelper, never()).getNotificationChannels(
757                 anyString(), anyInt(), anyBoolean());
758     }
759
760     @Test
761     public void testGetNotificationChannelGroupsFromPrivilegedListener_success() throws Exception {
762         mNotificationManagerService.setRankingHelper(mRankingHelper);
763         List<String> associations = new ArrayList<>();
764         associations.add("a");
765         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
766
767         mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
768                 null, PKG, Process.myUserHandle());
769
770         verify(mRankingHelper, times(1)).getNotificationChannelGroups(anyString(), anyInt());
771     }
772
773     @Test
774     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
775         mNotificationManagerService.setRankingHelper(mRankingHelper);
776         List<String> associations = new ArrayList<>();
777         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
778
779         try {
780             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
781                     null, PKG, Process.myUserHandle());
782             fail("listeners that don't have a companion device shouldn't be able to call this");
783         } catch (SecurityException e) {
784             // pass
785         }
786
787         verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
788     }
789
790     @Test
791     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
792         mNotificationManagerService.setRankingHelper(mRankingHelper);
793         List<String> associations = new ArrayList<>();
794         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
795         mListener = mock(ManagedServices.ManagedServiceInfo.class);
796         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
797         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
798
799         try {
800             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
801                     null, PKG, Process.myUserHandle());
802             fail("listeners that don't have a companion device shouldn't be able to call this");
803         } catch (SecurityException e) {
804             // pass
805         }
806
807         verify(mRankingHelper, never()).getNotificationChannelGroups(anyString(), anyInt());
808     }
809
810     @Test
811     public void testHasCompanionDevice_failure() throws Exception {
812         when(mCompanionMgr.getAssociations(anyString(), anyInt())).thenThrow(
813                 new IllegalArgumentException());
814         mNotificationManagerService.hasCompanionDevice(mListener);
815     }
816
817     @Test
818     public void testHasCompanionDevice_noService() throws Exception {
819         mNotificationManagerService = new TestableNotificationManagerService(mContext);
820
821         assertFalse(mNotificationManagerService.hasCompanionDevice(mListener));
822     }
823
824     @Test
825     public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
826         final NotificationRecord nonGrouped = generateNotificationRecord(
827                 mTestNotificationChannel, 1, null, false);
828         final NotificationRecord grouped = generateNotificationRecord(
829                 mTestNotificationChannel, 2, "group", false);
830         mNotificationManagerService.addNotification(grouped);
831         mNotificationManagerService.addNotification(nonGrouped);
832
833         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
834                 mNotificationManagerService.new SnoozeNotificationRunnable(
835                         nonGrouped.getKey(), 100, null);
836         snoozeNotificationRunnable.run();
837
838         // only snooze the one notification
839         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
840     }
841
842     @Test
843     public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
844         final NotificationRecord parent = generateNotificationRecord(
845                 mTestNotificationChannel, 1, "group", true);
846         final NotificationRecord child = generateNotificationRecord(
847                 mTestNotificationChannel, 2, "group", false);
848         final NotificationRecord child2 = generateNotificationRecord(
849                 mTestNotificationChannel, 3, "group", false);
850         mNotificationManagerService.addNotification(parent);
851         mNotificationManagerService.addNotification(child);
852         mNotificationManagerService.addNotification(child2);
853
854         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
855                 mNotificationManagerService.new SnoozeNotificationRunnable(
856                         parent.getKey(), 100, null);
857         snoozeNotificationRunnable.run();
858
859         // snooze parent and children
860         verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
861     }
862
863     @Test
864     public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
865         final NotificationRecord parent = generateNotificationRecord(
866                 mTestNotificationChannel, 1, "group", true);
867         final NotificationRecord child = generateNotificationRecord(
868                 mTestNotificationChannel, 2, "group", false);
869         final NotificationRecord child2 = generateNotificationRecord(
870                 mTestNotificationChannel, 3, "group", false);
871         mNotificationManagerService.addNotification(parent);
872         mNotificationManagerService.addNotification(child);
873         mNotificationManagerService.addNotification(child2);
874
875         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
876                 mNotificationManagerService.new SnoozeNotificationRunnable(
877                         child2.getKey(), 100, null);
878         snoozeNotificationRunnable.run();
879
880         // only snooze the one child
881         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
882     }
883
884     @Test
885     public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
886         final NotificationRecord parent = generateNotificationRecord(
887                 mTestNotificationChannel, 1, "group", true);
888         assertTrue(parent.sbn.getNotification().isGroupSummary());
889         final NotificationRecord child = generateNotificationRecord(
890                 mTestNotificationChannel, 2, "group", false);
891         mNotificationManagerService.addNotification(parent);
892         mNotificationManagerService.addNotification(child);
893
894         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
895                 mNotificationManagerService.new SnoozeNotificationRunnable(
896                         child.getKey(), 100, null);
897         snoozeNotificationRunnable.run();
898
899         // snooze child and summary
900         verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
901     }
902
903     @Test
904     public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
905         final NotificationRecord child = generateNotificationRecord(
906                 mTestNotificationChannel, 2, "group", false);
907         mNotificationManagerService.addNotification(child);
908
909         NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
910                 mNotificationManagerService.new SnoozeNotificationRunnable(
911                         child.getKey(), 100, null);
912         snoozeNotificationRunnable.run();
913
914         // snooze child only
915         verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
916     }
917
918     @Test
919     public void testPostGroupChild_unsnoozeParent() throws Exception {
920         final NotificationRecord child = generateNotificationRecord(
921                 mTestNotificationChannel, 2, "group", false);
922
923         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
924                 child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
925         waitForIdle();
926
927         verify(mSnoozeHelper, times(1)).repostGroupSummary(
928                 anyString(), anyInt(), eq(child.getGroupKey()));
929     }
930
931     @Test
932     public void testPostNonGroup_noUnsnoozing() throws Exception {
933         final NotificationRecord record = generateNotificationRecord(
934                 mTestNotificationChannel, 2, null, false);
935
936         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
937                 record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
938         waitForIdle();
939
940         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
941     }
942
943     @Test
944     public void testPostGroupSummary_noUnsnoozing() throws Exception {
945         final NotificationRecord parent = generateNotificationRecord(
946                 mTestNotificationChannel, 2, "group", true);
947
948         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
949                 parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
950         waitForIdle();
951
952         verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
953     }
954 }