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