OSDN Git Service

Translate default channel on locale change
[android-x86/frameworks-base.git] / services / tests / notification / src / com / android / server / notification / RankingHelperTest.java
1 /*
2  * Copyright (C) 2014 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 package com.android.server.notification;
17
18 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
19 import static android.app.NotificationManager.IMPORTANCE_HIGH;
20 import static android.app.NotificationManager.IMPORTANCE_LOW;
21 import static android.app.NotificationManager.IMPORTANCE_MAX;
22 import static android.app.NotificationManager.IMPORTANCE_NONE;
23 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
24
25 import static junit.framework.Assert.assertNull;
26 import static junit.framework.Assert.fail;
27
28 import org.json.JSONArray;
29 import org.json.JSONObject;
30 import org.junit.Before;
31 import org.junit.Ignore;
32 import org.junit.Test;
33 import org.junit.runner.RunWith;
34
35 import com.android.internal.util.FastXmlSerializer;
36
37 import org.mockito.Mock;
38 import org.mockito.MockitoAnnotations;
39 import org.xmlpull.v1.XmlPullParser;
40 import org.xmlpull.v1.XmlSerializer;
41
42 import android.app.Notification;
43 import android.app.NotificationChannelGroup;
44 import android.content.Context;
45 import android.app.NotificationChannel;
46 import android.app.NotificationManager;
47 import android.content.pm.ApplicationInfo;
48 import android.content.pm.PackageManager;
49 import android.content.res.Resources;
50 import android.graphics.Color;
51 import android.media.AudioAttributes;
52 import android.net.Uri;
53 import android.os.Build;
54 import android.os.UserHandle;
55 import android.provider.Settings.Secure;
56 import android.service.notification.StatusBarNotification;
57 import android.support.test.InstrumentationRegistry;
58 import android.support.test.runner.AndroidJUnit4;
59 import android.test.suitebuilder.annotation.SmallTest;
60 import android.util.ArrayMap;
61 import android.util.Xml;
62
63 import java.io.BufferedInputStream;
64 import java.io.BufferedOutputStream;
65 import java.io.ByteArrayInputStream;
66 import java.io.ByteArrayOutputStream;
67 import java.util.ArrayList;
68 import java.util.Arrays;
69 import java.util.HashMap;
70 import java.util.List;
71 import java.util.Map;
72 import java.util.Objects;
73 import java.util.concurrent.ThreadLocalRandom;
74
75 import static org.junit.Assert.assertEquals;
76 import static org.junit.Assert.assertFalse;
77 import static org.junit.Assert.assertNotNull;
78 import static org.junit.Assert.assertTrue;
79 import static org.mockito.Matchers.anyInt;
80 import static org.mockito.Matchers.anyString;
81 import static org.mockito.Matchers.eq;
82 import static org.mockito.Mockito.mock;
83 import static org.mockito.Mockito.never;
84 import static org.mockito.Mockito.times;
85 import static org.mockito.Mockito.verify;
86 import static org.mockito.Mockito.when;
87
88 @SmallTest
89 @RunWith(AndroidJUnit4.class)
90 public class RankingHelperTest extends NotificationTestCase {
91     private static final String PKG = "com.android.server.notification";
92     private static final int UID = 0;
93     private static final UserHandle USER = UserHandle.of(0);
94     private static final String UPDATED_PKG = "updatedPkg";
95     private static final int UID2 = 1111;
96     private static final UserHandle USER2 = UserHandle.of(10);
97     private static final String TEST_CHANNEL_ID = "test_channel_id";
98
99     @Mock NotificationUsageStats mUsageStats;
100     @Mock RankingHandler mHandler;
101     @Mock PackageManager mPm;
102     @Mock Context mContext;
103
104     private Notification mNotiGroupGSortA;
105     private Notification mNotiGroupGSortB;
106     private Notification mNotiNoGroup;
107     private Notification mNotiNoGroup2;
108     private Notification mNotiNoGroupSortA;
109     private NotificationRecord mRecordGroupGSortA;
110     private NotificationRecord mRecordGroupGSortB;
111     private NotificationRecord mRecordNoGroup;
112     private NotificationRecord mRecordNoGroup2;
113     private NotificationRecord mRecordNoGroupSortA;
114     private RankingHelper mHelper;
115     private AudioAttributes mAudioAttributes;
116
117     @Before
118     public void setUp() throws Exception {
119         MockitoAnnotations.initMocks(this);
120         UserHandle user = UserHandle.ALL;
121
122         final ApplicationInfo legacy = new ApplicationInfo();
123         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
124         final ApplicationInfo upgrade = new ApplicationInfo();
125         upgrade.targetSdkVersion = Build.VERSION_CODES.O;
126         when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy);
127         when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(upgrade);
128         when(mPm.getPackageUidAsUser(eq(PKG), anyInt())).thenReturn(UID);
129         when(mPm.getPackageUidAsUser(eq(UPDATED_PKG), anyInt())).thenReturn(UID2);
130         when(mContext.getResources()).thenReturn(
131                 InstrumentationRegistry.getContext().getResources());
132         when(mContext.getContentResolver()).thenReturn(
133                 InstrumentationRegistry.getContext().getContentResolver());
134         when(mContext.getPackageManager()).thenReturn(mPm);
135         when(mContext.getApplicationInfo()).thenReturn(legacy);
136         // most tests assume badging is enabled
137         Secure.putIntForUser(getContext().getContentResolver(),
138                 Secure.NOTIFICATION_BADGING, 1, UserHandle.getUserId(UID));
139
140         mHelper = new RankingHelper(getContext(), mPm, mHandler, mUsageStats,
141                 new String[] {ImportanceExtractor.class.getName()});
142
143         mNotiGroupGSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID)
144                 .setContentTitle("A")
145                 .setGroup("G")
146                 .setSortKey("A")
147                 .setWhen(1205)
148                 .build();
149         mRecordGroupGSortA = new NotificationRecord(mContext, new StatusBarNotification(
150                 PKG, PKG, 1, null, 0, 0, mNotiGroupGSortA, user,
151                 null, System.currentTimeMillis()), getDefaultChannel());
152
153         mNotiGroupGSortB = new Notification.Builder(mContext, TEST_CHANNEL_ID)
154                 .setContentTitle("B")
155                 .setGroup("G")
156                 .setSortKey("B")
157                 .setWhen(1200)
158                 .build();
159         mRecordGroupGSortB = new NotificationRecord(mContext, new StatusBarNotification(
160                 PKG, PKG, 1, null, 0, 0, mNotiGroupGSortB, user,
161                 null, System.currentTimeMillis()), getDefaultChannel());
162
163         mNotiNoGroup = new Notification.Builder(mContext, TEST_CHANNEL_ID)
164                 .setContentTitle("C")
165                 .setWhen(1201)
166                 .build();
167         mRecordNoGroup = new NotificationRecord(mContext, new StatusBarNotification(
168                 PKG, PKG, 1, null, 0, 0, mNotiNoGroup, user,
169                 null, System.currentTimeMillis()), getDefaultChannel());
170
171         mNotiNoGroup2 = new Notification.Builder(mContext, TEST_CHANNEL_ID)
172                 .setContentTitle("D")
173                 .setWhen(1202)
174                 .build();
175         mRecordNoGroup2 = new NotificationRecord(mContext, new StatusBarNotification(
176                 PKG, PKG, 1, null, 0, 0, mNotiNoGroup2, user,
177                 null, System.currentTimeMillis()), getDefaultChannel());
178
179         mNotiNoGroupSortA = new Notification.Builder(mContext, TEST_CHANNEL_ID)
180                 .setContentTitle("E")
181                 .setWhen(1201)
182                 .setSortKey("A")
183                 .build();
184         mRecordNoGroupSortA = new NotificationRecord(mContext, new StatusBarNotification(
185                 PKG, PKG, 1, null, 0, 0, mNotiNoGroupSortA, user,
186                 null, System.currentTimeMillis()), getDefaultChannel());
187
188         mAudioAttributes = new AudioAttributes.Builder()
189                 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
190                 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
191                 .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
192                 .build();
193     }
194
195     private NotificationChannel getDefaultChannel() {
196         return new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "name",
197                 IMPORTANCE_LOW);
198     }
199
200     private ByteArrayOutputStream writeXmlAndPurge(String pkg, int uid, boolean forBackup,
201             String... channelIds)
202             throws Exception {
203         XmlSerializer serializer = new FastXmlSerializer();
204         ByteArrayOutputStream baos = new ByteArrayOutputStream();
205         serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
206         serializer.startDocument(null, true);
207         mHelper.writeXml(serializer, forBackup);
208         serializer.endDocument();
209         serializer.flush();
210         for (String channelId : channelIds) {
211             mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId);
212         }
213         return baos;
214     }
215
216     private void loadStreamXml(ByteArrayOutputStream stream, boolean forRestore) throws Exception {
217         XmlPullParser parser = Xml.newPullParser();
218         parser.setInput(new BufferedInputStream(new ByteArrayInputStream(stream.toByteArray())),
219                 null);
220         parser.nextTag();
221         mHelper.readXml(parser, forRestore);
222     }
223
224     private void compareChannels(NotificationChannel expected, NotificationChannel actual) {
225         assertEquals(expected.getId(), actual.getId());
226         assertEquals(expected.getName(), actual.getName());
227         assertEquals(expected.getDescription(), actual.getDescription());
228         assertEquals(expected.shouldVibrate(), actual.shouldVibrate());
229         assertEquals(expected.shouldShowLights(), actual.shouldShowLights());
230         assertEquals(expected.getImportance(), actual.getImportance());
231         assertEquals(expected.getLockscreenVisibility(), actual.getLockscreenVisibility());
232         assertEquals(expected.getSound(), actual.getSound());
233         assertEquals(expected.canBypassDnd(), actual.canBypassDnd());
234         assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern()));
235         assertEquals(expected.getGroup(), actual.getGroup());
236         assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes());
237         assertEquals(expected.getLightColor(), actual.getLightColor());
238     }
239
240     private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) {
241         assertEquals(expected.getId(), actual.getId());
242         assertEquals(expected.getName(), actual.getName());
243     }
244
245     private NotificationChannel getChannel() {
246         return new NotificationChannel("id", "name", IMPORTANCE_LOW);
247     }
248
249     @Test
250     public void testFindAfterRankingWithASplitGroup() throws Exception {
251         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(3);
252         notificationList.add(mRecordGroupGSortA);
253         notificationList.add(mRecordGroupGSortB);
254         notificationList.add(mRecordNoGroup);
255         notificationList.add(mRecordNoGroupSortA);
256         mHelper.sort(notificationList);
257         assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortA) >= 0);
258         assertTrue(mHelper.indexOf(notificationList, mRecordGroupGSortB) >= 0);
259         assertTrue(mHelper.indexOf(notificationList, mRecordNoGroup) >= 0);
260         assertTrue(mHelper.indexOf(notificationList, mRecordNoGroupSortA) >= 0);
261     }
262
263     @Test
264     public void testSortShouldNotThrowWithPlainNotifications() throws Exception {
265         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2);
266         notificationList.add(mRecordNoGroup);
267         notificationList.add(mRecordNoGroup2);
268         mHelper.sort(notificationList);
269     }
270
271     @Test
272     public void testSortShouldNotThrowOneSorted() throws Exception {
273         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(2);
274         notificationList.add(mRecordNoGroup);
275         notificationList.add(mRecordNoGroupSortA);
276         mHelper.sort(notificationList);
277     }
278
279     @Test
280     public void testSortShouldNotThrowOneNotification() throws Exception {
281         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1);
282         notificationList.add(mRecordNoGroup);
283         mHelper.sort(notificationList);
284     }
285
286     @Test
287     public void testSortShouldNotThrowOneSortKey() throws Exception {
288         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>(1);
289         notificationList.add(mRecordGroupGSortB);
290         mHelper.sort(notificationList);
291     }
292
293     @Test
294     public void testSortShouldNotThrowOnEmptyList() throws Exception {
295         ArrayList<NotificationRecord> notificationList = new ArrayList<NotificationRecord>();
296         mHelper.sort(notificationList);
297     }
298
299     @Test
300     public void testChannelXml() throws Exception {
301         NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
302         NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
303         NotificationChannel channel1 =
304                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
305         NotificationChannel channel2 =
306                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
307         channel2.setDescription("descriptions for all");
308         channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
309         channel2.enableLights(true);
310         channel2.setBypassDnd(true);
311         channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
312         channel2.enableVibration(true);
313         channel2.setGroup(ncg.getId());
314         channel2.setVibrationPattern(new long[]{100, 67, 145, 156});
315         channel2.setLightColor(Color.BLUE);
316
317         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
318         mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
319         mHelper.createNotificationChannel(PKG, UID, channel1, true);
320         mHelper.createNotificationChannel(PKG, UID, channel2, false);
321
322         mHelper.setShowBadge(PKG, UID, true);
323
324         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false, channel1.getId(),
325                 channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
326         mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID});
327
328         loadStreamXml(baos, false);
329
330         assertTrue(mHelper.canShowBadge(PKG, UID));
331         assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
332         compareChannels(channel2,
333                 mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
334
335         List<NotificationChannelGroup> actualGroups =
336                 mHelper.getNotificationChannelGroups(PKG, UID, false).getList();
337         boolean foundNcg = false;
338         for (NotificationChannelGroup actual : actualGroups) {
339             if (ncg.getId().equals(actual.getId())) {
340                 foundNcg = true;
341                 compareGroups(ncg, actual);
342             } else if (ncg2.getId().equals(actual.getId())) {
343                 compareGroups(ncg2, actual);
344             }
345         }
346         assertTrue(foundNcg);
347
348         boolean foundChannel2Group = false;
349         for (NotificationChannelGroup actual : actualGroups) {
350             if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
351                 foundChannel2Group = true;
352                 break;
353             }
354         }
355         assertTrue(foundChannel2Group);
356     }
357
358     @Test
359     public void testChannelXmlForBackup() throws Exception {
360         NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
361         NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
362         NotificationChannel channel1 =
363                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
364         NotificationChannel channel2 =
365                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
366         channel2.setDescription("descriptions for all");
367         channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
368         channel2.enableLights(true);
369         channel2.setBypassDnd(true);
370         channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
371         channel2.enableVibration(false);
372         channel2.setGroup(ncg.getId());
373         channel2.setLightColor(Color.BLUE);
374         NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH);
375         channel3.enableVibration(true);
376
377         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
378         mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
379         mHelper.createNotificationChannel(PKG, UID, channel1, true);
380         mHelper.createNotificationChannel(PKG, UID, channel2, false);
381         mHelper.createNotificationChannel(PKG, UID, channel3, false);
382         mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true);
383
384         mHelper.setShowBadge(PKG, UID, true);
385
386         mHelper.setImportance(UPDATED_PKG, UID2, IMPORTANCE_NONE);
387
388         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(),
389                 channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
390         mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG, UPDATED_PKG},
391                 new int[]{UID, UID2});
392
393         mHelper.setShowBadge(UPDATED_PKG, UID2, true);
394
395         loadStreamXml(baos, true);
396
397         assertEquals(IMPORTANCE_NONE, mHelper.getImportance(UPDATED_PKG, UID2));
398         assertTrue(mHelper.canShowBadge(PKG, UID));
399         assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
400         compareChannels(channel2,
401                 mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
402         compareChannels(channel3,
403                 mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false));
404
405         List<NotificationChannelGroup> actualGroups =
406                 mHelper.getNotificationChannelGroups(PKG, UID, false).getList();
407         boolean foundNcg = false;
408         for (NotificationChannelGroup actual : actualGroups) {
409             if (ncg.getId().equals(actual.getId())) {
410                 foundNcg = true;
411                 compareGroups(ncg, actual);
412             } else if (ncg2.getId().equals(actual.getId())) {
413                 compareGroups(ncg2, actual);
414             }
415         }
416         assertTrue(foundNcg);
417
418         boolean foundChannel2Group = false;
419         for (NotificationChannelGroup actual : actualGroups) {
420             if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) {
421                 foundChannel2Group = true;
422                 break;
423             }
424         }
425         assertTrue(foundChannel2Group);
426     }
427
428     @Test
429     public void testChannelXml_backup() throws Exception {
430         NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye");
431         NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello");
432         NotificationChannel channel1 =
433                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
434         NotificationChannel channel2 =
435                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
436         NotificationChannel channel3 =
437                 new NotificationChannel("id3", "name3", IMPORTANCE_LOW);
438         channel3.setGroup(ncg.getId());
439
440         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
441         mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
442         mHelper.createNotificationChannel(PKG, UID, channel1, true);
443         mHelper.createNotificationChannel(PKG, UID, channel2, false);
444         mHelper.createNotificationChannel(PKG, UID, channel3, true);
445
446         mHelper.deleteNotificationChannel(PKG, UID, channel1.getId());
447         mHelper.deleteNotificationChannelGroup(PKG, UID, ncg.getId());
448         assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
449
450         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(),
451                 channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
452         mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG}, new int[]{UID});
453
454         XmlPullParser parser = Xml.newPullParser();
455         parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())),
456                 null);
457         parser.nextTag();
458         mHelper.readXml(parser, true);
459
460         assertNull(mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
461         assertNull(mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false));
462         assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG, UID));
463         //assertEquals(ncg2, mHelper.getNotificationChannelGroup(ncg2.getId(), PKG, UID));
464         assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
465     }
466
467     @Test
468     public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception {
469         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
470                 NotificationChannel.DEFAULT_CHANNEL_ID);
471
472         loadStreamXml(baos, false);
473
474         final NotificationChannel updated = mHelper.getNotificationChannel(PKG, UID,
475                 NotificationChannel.DEFAULT_CHANNEL_ID, false);
476         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance());
477         assertFalse(updated.canBypassDnd());
478         assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility());
479         assertEquals(0, updated.getUserLockedFields());
480     }
481
482     @Test
483     public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception {
484         final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID,
485                 NotificationChannel.DEFAULT_CHANNEL_ID, false);
486         defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW);
487         mHelper.updateNotificationChannel(PKG, UID, defaultChannel);
488
489         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
490                 NotificationChannel.DEFAULT_CHANNEL_ID);
491
492         loadStreamXml(baos, false);
493
494         assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel(
495                 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance());
496     }
497
498     @Test
499     public void testChannelXml_upgradeCreateDefaultChannel() throws Exception {
500         final String preupgradeXml = "<ranking version=\"1\">\n"
501                 + "<package name=\"" + PKG
502                 + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH
503                 + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\""
504                 + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID + "\" />\n"
505                 + "<package name=\"" + UPDATED_PKG + "\" uid=\"" + UID2 + "\" visibility=\""
506                 + Notification.VISIBILITY_PRIVATE + "\" />\n"
507                 + "</ranking>";
508         XmlPullParser parser = Xml.newPullParser();
509         parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())),
510                 null);
511         parser.nextTag();
512         mHelper.readXml(parser, false);
513
514         final NotificationChannel updated1 =
515             mHelper.getNotificationChannel(PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false);
516         assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance());
517         assertTrue(updated1.canBypassDnd());
518         assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility());
519         assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE
520                 | NotificationChannel.USER_LOCKED_PRIORITY
521                 | NotificationChannel.USER_LOCKED_VISIBILITY,
522                 updated1.getUserLockedFields());
523
524         // No Default Channel created for updated packages
525         assertEquals(null, mHelper.getNotificationChannel(UPDATED_PKG, UID2,
526                 NotificationChannel.DEFAULT_CHANNEL_ID, false));
527     }
528
529     @Test
530     public void testChannelXml_upgradeDeletesDefaultChannel() throws Exception {
531         final NotificationChannel defaultChannel = mHelper.getNotificationChannel(
532                 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false);
533         assertTrue(defaultChannel != null);
534         ByteArrayOutputStream baos =
535                 writeXmlAndPurge(PKG, UID, false, NotificationChannel.DEFAULT_CHANNEL_ID);
536         // Load package at higher sdk.
537         final ApplicationInfo upgraded = new ApplicationInfo();
538         upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
539         when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded);
540         loadStreamXml(baos, false);
541
542         // Default Channel should be gone.
543         assertEquals(null, mHelper.getNotificationChannel(PKG, UID,
544                 NotificationChannel.DEFAULT_CHANNEL_ID, false));
545     }
546
547     @Test
548     public void testDeletesDefaultChannelAfterChannelIsCreated() throws Exception {
549         mHelper.createNotificationChannel(PKG, UID,
550                 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true);
551         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
552                 NotificationChannel.DEFAULT_CHANNEL_ID, "bananas");
553
554         // Load package at higher sdk.
555         final ApplicationInfo upgraded = new ApplicationInfo();
556         upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1;
557         when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(upgraded);
558         loadStreamXml(baos, false);
559
560         // Default Channel should be gone.
561         assertEquals(null, mHelper.getNotificationChannel(PKG, UID,
562                 NotificationChannel.DEFAULT_CHANNEL_ID, false));
563     }
564
565     @Test
566     public void testLoadingOldChannelsDoesNotDeleteNewlyCreatedChannels() throws Exception {
567         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, false,
568                 NotificationChannel.DEFAULT_CHANNEL_ID, "bananas");
569         mHelper.createNotificationChannel(PKG, UID,
570                 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true);
571
572         loadStreamXml(baos, false);
573
574         // Should still have the newly created channel that wasn't in the xml.
575         assertTrue(mHelper.getNotificationChannel(PKG, UID, "bananas", false) != null);
576     }
577
578     @Test
579     public void testCreateChannel_blocked() throws Exception {
580         mHelper.setImportance(PKG, UID, IMPORTANCE_NONE);
581
582         mHelper.createNotificationChannel(PKG, UID,
583                 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true);
584     }
585
586     @Test
587     public void testCreateChannel_badImportance() throws Exception {
588         try {
589             mHelper.createNotificationChannel(PKG, UID,
590                     new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1), true);
591             fail("Was allowed to create a channel with invalid importance");
592         } catch (IllegalArgumentException e) {
593             // yay
594         }
595         try {
596             mHelper.createNotificationChannel(PKG, UID,
597                     new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED), true);
598             fail("Was allowed to create a channel with invalid importance");
599         } catch (IllegalArgumentException e) {
600             // yay
601         }
602         try {
603             mHelper.createNotificationChannel(PKG, UID,
604                     new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1), true);
605             fail("Was allowed to create a channel with invalid importance");
606         } catch (IllegalArgumentException e) {
607             // yay
608         }
609         mHelper.createNotificationChannel(PKG, UID,
610                 new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true);
611         mHelper.createNotificationChannel(PKG, UID,
612                 new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true);
613     }
614
615
616     @Test
617     public void testUpdate() throws Exception {
618         // no fields locked by user
619         final NotificationChannel channel =
620                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
621         channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
622         channel.enableLights(true);
623         channel.setBypassDnd(true);
624         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
625
626         mHelper.createNotificationChannel(PKG, UID, channel, false);
627
628         // same id, try to update all fields
629         final NotificationChannel channel2 =
630                 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH);
631         channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes);
632         channel2.enableLights(false);
633         channel2.setBypassDnd(false);
634         channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
635
636         mHelper.updateNotificationChannel(PKG, UID, channel2);
637
638         // all fields should be changed
639         assertEquals(channel2, mHelper.getNotificationChannel(PKG, UID, channel.getId(), false));
640
641         verify(mHandler, times(1)).requestSort();
642     }
643
644     @Test
645     public void testUpdate_preUpgrade_updatesAppFields() throws Exception {
646         mHelper.setImportance(PKG, UID, IMPORTANCE_UNSPECIFIED);
647         assertTrue(mHelper.canShowBadge(PKG, UID));
648         assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID));
649         assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
650                 mHelper.getPackageVisibility(PKG, UID));
651
652         NotificationChannel defaultChannel = mHelper.getNotificationChannel(
653                 PKG, UID, NotificationChannel.DEFAULT_CHANNEL_ID, false);
654
655         defaultChannel.setShowBadge(false);
656         defaultChannel.setImportance(IMPORTANCE_NONE);
657         defaultChannel.setBypassDnd(true);
658         defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
659
660         mHelper.updateNotificationChannel(PKG, UID, defaultChannel);
661
662         // ensure app level fields are changed
663         assertFalse(mHelper.canShowBadge(PKG, UID));
664         assertEquals(Notification.PRIORITY_MAX, mHelper.getPackagePriority(PKG, UID));
665         assertEquals(Notification.VISIBILITY_SECRET, mHelper.getPackageVisibility(PKG, UID));
666         assertEquals(IMPORTANCE_NONE, mHelper.getImportance(PKG, UID));
667     }
668
669     @Test
670     public void testUpdate_postUpgrade_noUpdateAppFields() throws Exception {
671         final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
672
673         mHelper.createNotificationChannel(PKG, UID, channel, false);
674         assertTrue(mHelper.canShowBadge(PKG, UID));
675         assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID));
676         assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
677                 mHelper.getPackageVisibility(PKG, UID));
678
679         channel.setShowBadge(false);
680         channel.setImportance(IMPORTANCE_NONE);
681         channel.setBypassDnd(true);
682         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
683
684         mHelper.updateNotificationChannel(PKG, UID, channel);
685
686         // ensure app level fields are not changed
687         assertTrue(mHelper.canShowBadge(PKG, UID));
688         assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG, UID));
689         assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE,
690                 mHelper.getPackageVisibility(PKG, UID));
691         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID));
692     }
693
694     @Test
695     public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception {
696         assertEquals(null, mHelper.getNotificationChannel(PKG, UID, "garbage", false));
697     }
698
699     @Test
700     public void testCreateChannel_CannotChangeHiddenFields() throws Exception {
701         final NotificationChannel channel =
702                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
703         channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
704         channel.enableLights(true);
705         channel.setBypassDnd(true);
706         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
707         channel.setShowBadge(true);
708         int lockMask = 0;
709         for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
710             lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
711         }
712         channel.lockFields(lockMask);
713
714         mHelper.createNotificationChannel(PKG, UID, channel, true);
715
716         NotificationChannel savedChannel =
717                 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false);
718
719         assertEquals(channel.getName(), savedChannel.getName());
720         assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
721         assertFalse(savedChannel.canBypassDnd());
722         assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
723         assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
724
725         verify(mHandler, never()).requestSort();
726     }
727
728     @Test
729     public void testCreateChannel_CannotChangeHiddenFieldsAssistant() throws Exception {
730         final NotificationChannel channel =
731                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
732         channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
733         channel.enableLights(true);
734         channel.setBypassDnd(true);
735         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
736         channel.setShowBadge(true);
737         int lockMask = 0;
738         for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) {
739             lockMask |= NotificationChannel.LOCKABLE_FIELDS[i];
740         }
741         channel.lockFields(lockMask);
742
743         mHelper.createNotificationChannel(PKG, UID, channel, true);
744
745         NotificationChannel savedChannel =
746                 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false);
747
748         assertEquals(channel.getName(), savedChannel.getName());
749         assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights());
750         assertFalse(savedChannel.canBypassDnd());
751         assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility());
752         assertEquals(channel.canShowBadge(), savedChannel.canShowBadge());
753     }
754
755     @Test
756     public void testClearLockedFields() throws Exception {
757         final NotificationChannel channel = getChannel();
758         mHelper.clearLockedFields(channel);
759         assertEquals(0, channel.getUserLockedFields());
760
761         channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY
762                 | NotificationChannel.USER_LOCKED_IMPORTANCE);
763         mHelper.clearLockedFields(channel);
764         assertEquals(0, channel.getUserLockedFields());
765     }
766
767     @Test
768     public void testLockFields_soundAndVibration() throws Exception {
769         mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
770
771         final NotificationChannel update1 = getChannel();
772         update1.setSound(new Uri.Builder().scheme("test").build(),
773                 new AudioAttributes.Builder().build());
774         update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); // should be ignored
775         mHelper.updateNotificationChannel(PKG, UID, update1);
776         assertEquals(NotificationChannel.USER_LOCKED_SOUND,
777                 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
778                         .getUserLockedFields());
779
780         NotificationChannel update2 = getChannel();
781         update2.enableVibration(true);
782         mHelper.updateNotificationChannel(PKG, UID, update2);
783         assertEquals(NotificationChannel.USER_LOCKED_SOUND
784                         | NotificationChannel.USER_LOCKED_VIBRATION,
785                 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
786                         .getUserLockedFields());
787     }
788
789     @Test
790     public void testLockFields_vibrationAndLights() throws Exception {
791         mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
792
793         final NotificationChannel update1 = getChannel();
794         update1.setVibrationPattern(new long[]{7945, 46 ,246});
795         mHelper.updateNotificationChannel(PKG, UID, update1);
796         assertEquals(NotificationChannel.USER_LOCKED_VIBRATION,
797                 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
798                         .getUserLockedFields());
799
800         final NotificationChannel update2 = getChannel();
801         update2.enableLights(true);
802         mHelper.updateNotificationChannel(PKG, UID, update2);
803         assertEquals(NotificationChannel.USER_LOCKED_VIBRATION
804                         | NotificationChannel.USER_LOCKED_LIGHTS,
805                 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
806                         .getUserLockedFields());
807     }
808
809     @Test
810     public void testLockFields_lightsAndImportance() throws Exception {
811         mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
812
813         final NotificationChannel update1 = getChannel();
814         update1.setLightColor(Color.GREEN);
815         mHelper.updateNotificationChannel(PKG, UID, update1);
816         assertEquals(NotificationChannel.USER_LOCKED_LIGHTS,
817                 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
818                         .getUserLockedFields());
819
820         final NotificationChannel update2 = getChannel();
821         update2.setImportance(IMPORTANCE_DEFAULT);
822         mHelper.updateNotificationChannel(PKG, UID, update2);
823         assertEquals(NotificationChannel.USER_LOCKED_LIGHTS
824                         | NotificationChannel.USER_LOCKED_IMPORTANCE,
825                 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
826                         .getUserLockedFields());
827     }
828
829     @Test
830     public void testLockFields_visibilityAndDndAndBadge() throws Exception {
831         mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
832         assertEquals(0,
833                 mHelper.getNotificationChannel(PKG, UID, getChannel().getId(), false)
834                         .getUserLockedFields());
835
836         final NotificationChannel update1 = getChannel();
837         update1.setBypassDnd(true);
838         mHelper.updateNotificationChannel(PKG, UID, update1);
839         assertEquals(NotificationChannel.USER_LOCKED_PRIORITY,
840                 mHelper.getNotificationChannel(PKG, UID, update1.getId(), false)
841                         .getUserLockedFields());
842
843         final NotificationChannel update2 = getChannel();
844         update2.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
845         mHelper.updateNotificationChannel(PKG, UID, update2);
846         assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
847                         | NotificationChannel.USER_LOCKED_VISIBILITY,
848                 mHelper.getNotificationChannel(PKG, UID, update2.getId(), false)
849                         .getUserLockedFields());
850
851         final NotificationChannel update3 = getChannel();
852         update3.setShowBadge(false);
853         mHelper.updateNotificationChannel(PKG, UID, update3);
854         assertEquals(NotificationChannel.USER_LOCKED_PRIORITY
855                         | NotificationChannel.USER_LOCKED_VISIBILITY
856                         | NotificationChannel.USER_LOCKED_SHOW_BADGE,
857                 mHelper.getNotificationChannel(PKG, UID, update3.getId(), false)
858                         .getUserLockedFields());
859     }
860
861     @Test
862     public void testDeleteNonExistentChannel() throws Exception {
863         mHelper.deleteNotificationChannelGroup(PKG, UID, "does not exist");
864     }
865
866     @Test
867     public void testGetDeletedChannel() throws Exception {
868         NotificationChannel channel = getChannel();
869         channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
870         channel.enableLights(true);
871         channel.setBypassDnd(true);
872         channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
873         channel.enableVibration(true);
874         channel.setVibrationPattern(new long[]{100, 67, 145, 156});
875
876         mHelper.createNotificationChannel(PKG, UID, channel, true);
877         mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
878
879         // Does not return deleted channel
880         NotificationChannel response =
881                 mHelper.getNotificationChannel(PKG, UID, channel.getId(), false);
882         assertNull(response);
883
884         // Returns deleted channel
885         response = mHelper.getNotificationChannel(PKG, UID, channel.getId(), true);
886         compareChannels(channel, response);
887         assertTrue(response.isDeleted());
888     }
889
890     @Test
891     public void testGetDeletedChannels() throws Exception {
892         Map<String, NotificationChannel> channelMap = new HashMap<>();
893         NotificationChannel channel =
894                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
895         channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes);
896         channel.enableLights(true);
897         channel.setBypassDnd(true);
898         channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
899         channel.enableVibration(true);
900         channel.setVibrationPattern(new long[]{100, 67, 145, 156});
901         channelMap.put(channel.getId(), channel);
902         NotificationChannel channel2 =
903                 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
904         channelMap.put(channel2.getId(), channel2);
905         mHelper.createNotificationChannel(PKG, UID, channel, true);
906         mHelper.createNotificationChannel(PKG, UID, channel2, true);
907
908         mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
909
910         // Returns only non-deleted channels
911         List<NotificationChannel> channels =
912                 mHelper.getNotificationChannels(PKG, UID, false).getList();
913         assertEquals(2, channels.size());   // Default channel + non-deleted channel
914         for (NotificationChannel nc : channels) {
915             if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
916                 compareChannels(channel2, nc);
917             }
918         }
919
920         // Returns deleted channels too
921         channels = mHelper.getNotificationChannels(PKG, UID, true).getList();
922         assertEquals(3, channels.size());               // Includes default channel
923         for (NotificationChannel nc : channels) {
924             if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) {
925                 compareChannels(channelMap.get(nc.getId()), nc);
926             }
927         }
928     }
929
930     @Test
931     public void testGetDeletedChannelCount() throws Exception {
932         NotificationChannel channel =
933                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
934         NotificationChannel channel2 =
935                 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
936         NotificationChannel channel3 =
937                 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH);
938         mHelper.createNotificationChannel(PKG, UID, channel, true);
939         mHelper.createNotificationChannel(PKG, UID, channel2, true);
940         mHelper.createNotificationChannel(PKG, UID, channel3, true);
941
942         mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
943         mHelper.deleteNotificationChannel(PKG, UID, channel3.getId());
944
945         assertEquals(2, mHelper.getDeletedChannelCount(PKG, UID));
946         assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID2));
947     }
948
949     @Test
950     public void testCreateDeletedChannel() throws Exception {
951         long[] vibration = new long[]{100, 67, 145, 156};
952         NotificationChannel channel =
953                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
954         channel.setVibrationPattern(vibration);
955
956         mHelper.createNotificationChannel(PKG, UID, channel, true);
957         mHelper.deleteNotificationChannel(PKG, UID, channel.getId());
958
959         NotificationChannel newChannel = new NotificationChannel(
960                 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
961         newChannel.setVibrationPattern(new long[]{100});
962
963         mHelper.createNotificationChannel(PKG, UID, newChannel, true);
964
965         // No long deleted, using old settings
966         compareChannels(channel,
967                 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false));
968     }
969
970     @Test
971     public void testOnlyHasDefaultChannel() throws Exception {
972         assertTrue(mHelper.onlyHasDefaultChannel(PKG, UID));
973         assertFalse(mHelper.onlyHasDefaultChannel(UPDATED_PKG, UID2));
974
975         mHelper.createNotificationChannel(PKG, UID, getChannel(), true);
976         assertFalse(mHelper.onlyHasDefaultChannel(PKG, UID));
977     }
978
979     @Test
980     public void testCreateChannel_defaultChannelId() throws Exception {
981         try {
982             mHelper.createNotificationChannel(PKG, UID, new NotificationChannel(
983                     NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true);
984             fail("Allowed to create default channel");
985         } catch (IllegalArgumentException e) {
986             // pass
987         }
988     }
989
990     @Test
991     public void testCreateChannel_alreadyExists() throws Exception {
992         long[] vibration = new long[]{100, 67, 145, 156};
993         NotificationChannel channel =
994                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
995         channel.setVibrationPattern(vibration);
996
997         mHelper.createNotificationChannel(PKG, UID, channel, true);
998
999         NotificationChannel newChannel = new NotificationChannel(
1000                 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
1001         newChannel.setVibrationPattern(new long[]{100});
1002
1003         mHelper.createNotificationChannel(PKG, UID, newChannel, true);
1004
1005         // Old settings not overridden
1006         compareChannels(channel,
1007                 mHelper.getNotificationChannel(PKG, UID, newChannel.getId(), false));
1008     }
1009
1010     @Test
1011     public void testCreateChannel_noOverrideSound() throws Exception {
1012         Uri sound = new Uri.Builder().scheme("test").build();
1013         final NotificationChannel channel = new NotificationChannel("id2", "name2",
1014                  NotificationManager.IMPORTANCE_DEFAULT);
1015         channel.setSound(sound, mAudioAttributes);
1016         mHelper.createNotificationChannel(PKG, UID, channel, true);
1017         assertEquals(sound, mHelper.getNotificationChannel(
1018                 PKG, UID, channel.getId(), false).getSound());
1019     }
1020
1021     @Test
1022     public void testPermanentlyDeleteChannels() throws Exception {
1023         NotificationChannel channel1 =
1024                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
1025         NotificationChannel channel2 =
1026                 new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
1027
1028         mHelper.createNotificationChannel(PKG, UID, channel1, true);
1029         mHelper.createNotificationChannel(PKG, UID, channel2, false);
1030
1031         mHelper.permanentlyDeleteNotificationChannels(PKG, UID);
1032
1033         // Only default channel remains
1034         assertEquals(1, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
1035     }
1036
1037     @Test
1038     public void testDeleteGroup() throws Exception {
1039         NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted");
1040         NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted");
1041         NotificationChannel nonGroupedNonDeletedChannel =
1042                 new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH);
1043         NotificationChannel groupedButNotDeleted =
1044                 new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT);
1045         groupedButNotDeleted.setGroup("not");
1046         NotificationChannel groupedAndDeleted =
1047                 new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT);
1048         groupedAndDeleted.setGroup("totally");
1049
1050         mHelper.createNotificationChannelGroup(PKG, UID, notDeleted, true);
1051         mHelper.createNotificationChannelGroup(PKG, UID, deleted, true);
1052         mHelper.createNotificationChannel(PKG, UID, nonGroupedNonDeletedChannel, true);
1053         mHelper.createNotificationChannel(PKG, UID, groupedAndDeleted, true);
1054         mHelper.createNotificationChannel(PKG, UID, groupedButNotDeleted, true);
1055
1056         mHelper.deleteNotificationChannelGroup(PKG, UID, deleted.getId());
1057
1058         assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG, UID));
1059         assertNotNull(mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG, UID));
1060
1061         assertNull(mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), false));
1062         compareChannels(groupedAndDeleted,
1063                 mHelper.getNotificationChannel(PKG, UID, groupedAndDeleted.getId(), true));
1064
1065         compareChannels(groupedButNotDeleted,
1066                 mHelper.getNotificationChannel(PKG, UID, groupedButNotDeleted.getId(), false));
1067         compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel(
1068                 PKG, UID, nonGroupedNonDeletedChannel.getId(), false));
1069
1070         // notDeleted
1071         assertEquals(1, mHelper.getNotificationChannelGroups(PKG, UID).size());
1072
1073         verify(mHandler, never()).requestSort();
1074     }
1075
1076     @Test
1077     public void testOnUserRemoved() throws Exception {
1078         int[] user0Uids = {98, 235, 16, 3782};
1079         int[] user1Uids = new int[user0Uids.length];
1080         for (int i = 0; i < user0Uids.length; i++) {
1081             user1Uids[i] = UserHandle.PER_USER_RANGE + user0Uids[i];
1082
1083             final ApplicationInfo legacy = new ApplicationInfo();
1084             legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
1085             when(mPm.getApplicationInfoAsUser(eq(PKG), anyInt(), anyInt())).thenReturn(legacy);
1086
1087             // create records with the default channel for all user 0 and user 1 uids
1088             mHelper.getImportance(PKG, user0Uids[i]);
1089             mHelper.getImportance(PKG, user1Uids[i]);
1090         }
1091
1092         mHelper.onUserRemoved(1);
1093
1094         // user 0 records remain
1095         for (int i = 0; i < user0Uids.length; i++) {
1096             assertEquals(1,
1097                     mHelper.getNotificationChannels(PKG, user0Uids[i], false).getList().size());
1098         }
1099         // user 1 records are gone
1100         for (int i = 0; i < user1Uids.length; i++) {
1101             assertEquals(0,
1102                     mHelper.getNotificationChannels(PKG, user1Uids[i], false).getList().size());
1103         }
1104     }
1105
1106     @Test
1107     public void testOnPackageChanged_packageRemoval() throws Exception {
1108         // Deleted
1109         NotificationChannel channel1 =
1110                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
1111         mHelper.createNotificationChannel(PKG, UID, channel1, true);
1112
1113         mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
1114
1115         assertEquals(0, mHelper.getNotificationChannels(PKG, UID, true).getList().size());
1116
1117         // Not deleted
1118         mHelper.createNotificationChannel(PKG, UID, channel1, true);
1119
1120         mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
1121         assertEquals(2, mHelper.getNotificationChannels(PKG, UID, false).getList().size());
1122     }
1123
1124     @Test
1125     public void testOnPackageChanged_packageRemoval_importance() throws Exception {
1126         mHelper.setImportance(PKG, UID, NotificationManager.IMPORTANCE_HIGH);
1127
1128         mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
1129
1130         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID));
1131     }
1132
1133     @Test
1134     public void testOnPackageChanged_packageRemoval_groups() throws Exception {
1135         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
1136         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
1137         NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
1138         mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
1139
1140         mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG}, new int[]{UID});
1141
1142         assertEquals(0, mHelper.getNotificationChannelGroups(PKG, UID, true).getList().size());
1143     }
1144
1145     @Test
1146     public void testOnPackageChange_downgradeTargetSdk() throws Exception {
1147         // create channel as api 26
1148         mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true);
1149
1150         // install new app version targeting 25
1151         final ApplicationInfo legacy = new ApplicationInfo();
1152         legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1;
1153         when(mPm.getApplicationInfoAsUser(eq(UPDATED_PKG), anyInt(), anyInt())).thenReturn(legacy);
1154         mHelper.onPackagesChanged(
1155                 false, UserHandle.USER_SYSTEM, new String[]{UPDATED_PKG}, new int[]{UID2});
1156
1157         // make sure the default channel was readded
1158         //assertEquals(2, mHelper.getNotificationChannels(UPDATED_PKG, UID2, false).getList().size());
1159         assertNotNull(mHelper.getNotificationChannel(
1160                 UPDATED_PKG, UID2, NotificationChannel.DEFAULT_CHANNEL_ID, false));
1161     }
1162
1163     @Test
1164     public void testRecordDefaults() throws Exception {
1165         assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, mHelper.getImportance(PKG, UID));
1166         assertEquals(true, mHelper.canShowBadge(PKG, UID));
1167         assertEquals(1, mHelper.getNotificationChannels(PKG, UID, false).getList().size());
1168     }
1169
1170     @Test
1171     public void testCreateGroup() throws Exception {
1172         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
1173         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
1174         assertEquals(ncg, mHelper.getNotificationChannelGroups(PKG, UID).iterator().next());
1175         verify(mHandler, never()).requestSort();
1176     }
1177
1178     @Test
1179     public void testCannotCreateChannel_badGroup() throws Exception {
1180         NotificationChannel channel1 =
1181                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
1182         channel1.setGroup("garbage");
1183         try {
1184             mHelper.createNotificationChannel(PKG, UID, channel1, true);
1185             fail("Created a channel with a bad group");
1186         } catch (IllegalArgumentException e) {
1187         }
1188     }
1189
1190     @Test
1191     public void testCannotCreateChannel_goodGroup() throws Exception {
1192         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
1193         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
1194         NotificationChannel channel1 =
1195                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
1196         channel1.setGroup(ncg.getId());
1197         mHelper.createNotificationChannel(PKG, UID, channel1, true);
1198
1199         assertEquals(ncg.getId(),
1200                 mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false).getGroup());
1201     }
1202
1203     @Test
1204     public void testGetChannelGroups() throws Exception {
1205         NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s");
1206         mHelper.createNotificationChannelGroup(PKG, UID, unused, true);
1207         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
1208         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
1209         NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2");
1210         mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
1211
1212         NotificationChannel channel1 =
1213                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
1214         channel1.setGroup(ncg.getId());
1215         mHelper.createNotificationChannel(PKG, UID, channel1, true);
1216         NotificationChannel channel1a =
1217                 new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH);
1218         channel1a.setGroup(ncg.getId());
1219         mHelper.createNotificationChannel(PKG, UID, channel1a, true);
1220
1221         NotificationChannel channel2 =
1222                 new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH);
1223         channel2.setGroup(ncg2.getId());
1224         mHelper.createNotificationChannel(PKG, UID, channel2, true);
1225
1226         NotificationChannel channel3 =
1227                 new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH);
1228         mHelper.createNotificationChannel(PKG, UID, channel3, true);
1229
1230         List<NotificationChannelGroup> actual =
1231                 mHelper.getNotificationChannelGroups(PKG, UID, true).getList();
1232         assertEquals(3, actual.size());
1233         for (NotificationChannelGroup group : actual) {
1234             if (group.getId() == null) {
1235                 assertEquals(2, group.getChannels().size()); // misc channel too
1236                 assertTrue(channel3.getId().equals(group.getChannels().get(0).getId())
1237                         || channel3.getId().equals(group.getChannels().get(1).getId()));
1238             } else if (group.getId().equals(ncg.getId())) {
1239                 assertEquals(2, group.getChannels().size());
1240                 if (group.getChannels().get(0).getId().equals(channel1.getId())) {
1241                     assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId()));
1242                 } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) {
1243                     assertTrue(group.getChannels().get(1).getId().equals(channel1.getId()));
1244                 } else {
1245                     fail("expected channel not found");
1246                 }
1247             } else if (group.getId().equals(ncg2.getId())) {
1248                 assertEquals(1, group.getChannels().size());
1249                 assertEquals(channel2.getId(), group.getChannels().get(0).getId());
1250             }
1251         }
1252     }
1253
1254     @Test
1255     public void testGetChannelGroups_noSideEffects() throws Exception {
1256         NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1");
1257         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
1258
1259         NotificationChannel channel1 =
1260                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
1261         channel1.setGroup(ncg.getId());
1262         mHelper.createNotificationChannel(PKG, UID, channel1, true);
1263         mHelper.getNotificationChannelGroups(PKG, UID, true).getList();
1264
1265         channel1.setImportance(IMPORTANCE_LOW);
1266         mHelper.updateNotificationChannel(PKG, UID, channel1);
1267
1268         List<NotificationChannelGroup> actual =
1269                 mHelper.getNotificationChannelGroups(PKG, UID, true).getList();
1270
1271         assertEquals(2, actual.size());
1272         for (NotificationChannelGroup group : actual) {
1273             if (Objects.equals(group.getId(), ncg.getId())) {
1274                 assertEquals(1, group.getChannels().size());
1275             }
1276         }
1277     }
1278
1279     @Test
1280     public void testCreateChannel_updateName() throws Exception {
1281         NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
1282         mHelper.createNotificationChannel(PKG, UID, nc, true);
1283         NotificationChannel actual = mHelper.getNotificationChannel(PKG, UID, "id", false);
1284         assertEquals("hello", actual.getName());
1285
1286         nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH);
1287         mHelper.createNotificationChannel(PKG, UID, nc, true);
1288
1289         actual = mHelper.getNotificationChannel(PKG, UID, "id", false);
1290         assertEquals("goodbye", actual.getName());
1291         assertEquals(IMPORTANCE_DEFAULT, actual.getImportance());
1292
1293         verify(mHandler, times(1)).requestSort();
1294     }
1295
1296     @Test
1297     public void testDumpChannelsJson() throws Exception {
1298         final ApplicationInfo upgrade = new ApplicationInfo();
1299         upgrade.targetSdkVersion = Build.VERSION_CODES.O;
1300         try {
1301             when(mPm.getApplicationInfoAsUser(
1302                     anyString(), anyInt(), anyInt())).thenReturn(upgrade);
1303         } catch (PackageManager.NameNotFoundException e) {
1304         }
1305         ArrayMap<String, Integer> expectedChannels = new ArrayMap<>();
1306         int numPackages = ThreadLocalRandom.current().nextInt(1, 5);
1307         for (int i = 0; i < numPackages; i++) {
1308             String pkgName = "pkg" + i;
1309             int numChannels = ThreadLocalRandom.current().nextInt(1, 10);
1310             for (int j = 0; j < numChannels; j++) {
1311                 mHelper.createNotificationChannel(pkgName, UID,
1312                         new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true);
1313             }
1314             expectedChannels.put(pkgName, numChannels);
1315         }
1316
1317         // delete the first channel of the first package
1318         String pkg = expectedChannels.keyAt(0);
1319         mHelper.deleteNotificationChannel("pkg" + 0, UID, "0");
1320         // dump should not include deleted channels
1321         int count = expectedChannels.get(pkg);
1322         expectedChannels.put(pkg, count - 1);
1323
1324         JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter());
1325         assertEquals(numPackages, actual.length());
1326         for (int i = 0; i < numPackages; i++) {
1327             JSONObject object = actual.getJSONObject(i);
1328             assertTrue(expectedChannels.containsKey(object.get("packageName")));
1329             assertEquals(expectedChannels.get(object.get("packageName")).intValue(),
1330                     object.getInt("channelCount"));
1331         }
1332     }
1333
1334     @Test
1335     public void testBadgingOverrideTrue() throws Exception {
1336         Secure.putIntForUser(getContext().getContentResolver(),
1337                 Secure.NOTIFICATION_BADGING, 1,
1338                 USER.getIdentifier());
1339         mHelper.updateBadgingEnabled(); // would be called by settings observer
1340         assertTrue(mHelper.badgingEnabled(USER));
1341     }
1342
1343     @Test
1344     public void testBadgingOverrideFalse() throws Exception {
1345         Secure.putIntForUser(getContext().getContentResolver(),
1346                 Secure.NOTIFICATION_BADGING, 0,
1347                 USER.getIdentifier());
1348         mHelper.updateBadgingEnabled(); // would be called by settings observer
1349         assertFalse(mHelper.badgingEnabled(USER));
1350     }
1351
1352     @Test
1353     public void testBadgingForUserAll() throws Exception {
1354         try {
1355             mHelper.badgingEnabled(UserHandle.ALL);
1356         } catch (Exception e) {
1357             fail("just don't throw");
1358         }
1359     }
1360
1361     @Test
1362     public void testBadgingOverrideUserIsolation() throws Exception {
1363         Secure.putIntForUser(getContext().getContentResolver(),
1364                 Secure.NOTIFICATION_BADGING, 0,
1365                 USER.getIdentifier());
1366         Secure.putIntForUser(getContext().getContentResolver(),
1367                 Secure.NOTIFICATION_BADGING, 1,
1368                 USER2.getIdentifier());
1369         mHelper.updateBadgingEnabled(); // would be called by settings observer
1370         assertFalse(mHelper.badgingEnabled(USER));
1371         assertTrue(mHelper.badgingEnabled(USER2));
1372     }
1373
1374     @Test
1375     public void testOnLocaleChanged_updatesDefaultChannels() throws Exception {
1376         String newLabel = "bananas!";
1377         final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG, UID,
1378                 NotificationChannel.DEFAULT_CHANNEL_ID, false);
1379         assertFalse(newLabel.equals(defaultChannel.getName()));
1380
1381         Resources res = mock(Resources.class);
1382         when(mContext.getResources()).thenReturn(res);
1383         when(res.getString(com.android.internal.R.string.default_notification_channel_label))
1384                 .thenReturn(newLabel);
1385
1386         mHelper.onLocaleChanged(mContext, USER.getIdentifier());
1387
1388         assertEquals(newLabel, mHelper.getNotificationChannel(PKG, UID,
1389                 NotificationChannel.DEFAULT_CHANNEL_ID, false).getName());
1390     }
1391 }