Home | History | Annotate | Download | only in notification
      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 android.app.Notification;
     29 import android.app.NotificationChannel;
     30 import android.app.NotificationChannelGroup;
     31 import android.app.NotificationManager;
     32 import android.content.ContentProvider;
     33 import android.content.Context;
     34 import android.content.IContentProvider;
     35 import android.content.pm.ApplicationInfo;
     36 import android.content.pm.PackageManager;
     37 import android.content.res.Resources;
     38 import android.graphics.Color;
     39 import android.media.AudioAttributes;
     40 import android.net.Uri;
     41 import android.os.Build;
     42 import android.os.UserHandle;
     43 import android.provider.Settings;
     44 import android.provider.Settings.Secure;
     45 import android.service.notification.StatusBarNotification;
     46 import android.support.test.InstrumentationRegistry;
     47 import android.support.test.runner.AndroidJUnit4;
     48 import android.test.suitebuilder.annotation.SmallTest;
     49 import android.testing.TestableContentResolver;
     50 import android.util.ArrayMap;
     51 import android.util.Xml;
     52 
     53 import com.android.internal.util.FastXmlSerializer;
     54 
     55 import org.json.JSONArray;
     56 import org.json.JSONObject;
     57 import org.junit.Before;
     58 import org.junit.Test;
     59 import org.junit.runner.RunWith;
     60 import org.mockito.Mock;
     61 import org.mockito.MockitoAnnotations;
     62 import org.xmlpull.v1.XmlPullParser;
     63 import org.xmlpull.v1.XmlSerializer;
     64 
     65 import java.io.BufferedInputStream;
     66 import java.io.BufferedOutputStream;
     67 import java.io.ByteArrayInputStream;
     68 import java.io.ByteArrayOutputStream;
     69 import java.util.ArrayList;
     70 import java.util.Arrays;
     71 import java.util.HashMap;
     72 import java.util.List;
     73 import java.util.Map;
     74 import java.util.Objects;
     75 import java.util.concurrent.ThreadLocalRandom;
     76 
     77 import static org.junit.Assert.assertEquals;
     78 import static org.junit.Assert.assertFalse;
     79 import static org.junit.Assert.assertNotNull;
     80 import static org.junit.Assert.assertTrue;
     81 import static org.mockito.ArgumentMatchers.any;
     82 import static org.mockito.Matchers.anyInt;
     83 import static org.mockito.Matchers.anyString;
     84 import static org.mockito.Matchers.eq;
     85 import static org.mockito.Mockito.mock;
     86 import static org.mockito.Mockito.never;
     87 import static org.mockito.Mockito.times;
     88 import static org.mockito.Mockito.verify;
     89 import static org.mockito.Mockito.when;
     90 
     91 @SmallTest
     92 @RunWith(AndroidJUnit4.class)
     93 public 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