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