1 /* 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 */ 16 package com.android.server.notification; 17 18 import static android.app.AppOpsManager.MODE_ALLOWED; 19 import static android.app.AppOpsManager.MODE_DEFAULT; 20 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW; 21 import static android.app.NotificationChannel.CONVERSATION_CHANNEL_ID_FORMAT; 22 import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE; 23 import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL; 24 import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE; 25 import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED; 26 import static android.app.NotificationManager.IMPORTANCE_DEFAULT; 27 import static android.app.NotificationManager.IMPORTANCE_HIGH; 28 import static android.app.NotificationManager.IMPORTANCE_LOW; 29 import static android.app.NotificationManager.IMPORTANCE_MAX; 30 import static android.app.NotificationManager.IMPORTANCE_NONE; 31 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED; 32 import static android.media.AudioAttributes.CONTENT_TYPE_SONIFICATION; 33 import static android.media.AudioAttributes.USAGE_NOTIFICATION; 34 import static android.os.UserHandle.USER_SYSTEM; 35 import static android.util.StatsLog.ANNOTATION_ID_IS_UID; 36 37 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES; 38 import static com.android.internal.util.FrameworkStatsLog.PACKAGE_NOTIFICATION_PREFERENCES; 39 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_ID_FIELD_NUMBER; 40 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.CHANNEL_NAME_FIELD_NUMBER; 41 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IMPORTANCE_FIELD_NUMBER; 42 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_CONVERSATION_FIELD_NUMBER; 43 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_DELETED_FIELD_NUMBER; 44 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_DEMOTED_CONVERSATION_FIELD_NUMBER; 45 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.IS_IMPORTANT_CONVERSATION_FIELD_NUMBER; 46 import static com.android.os.AtomsProto.PackageNotificationChannelPreferences.UID_FIELD_NUMBER; 47 import static com.android.server.notification.PreferencesHelper.DEFAULT_BUBBLE_PREFERENCE; 48 import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_COUNT_LIMIT; 49 import static com.android.server.notification.PreferencesHelper.NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT; 50 import static com.android.server.notification.PreferencesHelper.UNKNOWN_UID; 51 52 import static com.google.common.truth.Truth.assertThat; 53 54 import static junit.framework.Assert.assertNull; 55 import static junit.framework.Assert.fail; 56 57 import static org.junit.Assert.assertEquals; 58 import static org.junit.Assert.assertFalse; 59 import static org.junit.Assert.assertNotNull; 60 import static org.junit.Assert.assertTrue; 61 import static org.mockito.ArgumentMatchers.any; 62 import static org.mockito.ArgumentMatchers.anyInt; 63 import static org.mockito.ArgumentMatchers.anyString; 64 import static org.mockito.ArgumentMatchers.eq; 65 import static org.mockito.Mockito.doAnswer; 66 import static org.mockito.Mockito.doReturn; 67 import static org.mockito.Mockito.mock; 68 import static org.mockito.Mockito.never; 69 import static org.mockito.Mockito.reset; 70 import static org.mockito.Mockito.times; 71 import static org.mockito.Mockito.verify; 72 import static org.mockito.Mockito.when; 73 74 import android.app.AppOpsManager; 75 import android.app.Notification; 76 import android.app.NotificationChannel; 77 import android.app.NotificationChannelGroup; 78 import android.app.NotificationManager; 79 import android.content.AttributionSource; 80 import android.content.ContentProvider; 81 import android.content.ContentResolver; 82 import android.content.Context; 83 import android.content.IContentProvider; 84 import android.content.pm.ApplicationInfo; 85 import android.content.pm.PackageInfo; 86 import android.content.pm.PackageManager; 87 import android.content.pm.Signature; 88 import android.content.pm.UserInfo; 89 import android.content.res.Resources; 90 import android.graphics.Color; 91 import android.media.AudioAttributes; 92 import android.net.Uri; 93 import android.os.AsyncTask; 94 import android.os.Build; 95 import android.os.Bundle; 96 import android.os.RemoteCallback; 97 import android.os.RemoteException; 98 import android.os.UserHandle; 99 import android.os.UserManager; 100 import android.provider.Settings; 101 import android.provider.Settings.Global; 102 import android.provider.Settings.Secure; 103 import android.service.notification.ConversationChannelWrapper; 104 import android.service.notification.nano.RankingHelperProto; 105 import android.test.suitebuilder.annotation.SmallTest; 106 import android.testing.TestableContentResolver; 107 import android.text.format.DateUtils; 108 import android.util.ArrayMap; 109 import android.util.ArraySet; 110 import android.util.IntArray; 111 import android.util.Pair; 112 import android.util.StatsEvent; 113 import android.util.TypedXmlPullParser; 114 import android.util.TypedXmlSerializer; 115 import android.util.Xml; 116 import android.util.proto.ProtoOutputStream; 117 118 import androidx.test.InstrumentationRegistry; 119 import androidx.test.runner.AndroidJUnit4; 120 121 import com.android.os.AtomsProto.PackageNotificationPreferences; 122 import com.android.server.UiServiceTestCase; 123 import com.android.server.notification.PermissionHelper.PackagePermission; 124 125 import com.google.common.collect.ImmutableList; 126 127 import org.json.JSONArray; 128 import org.json.JSONObject; 129 import org.junit.Before; 130 import org.junit.Test; 131 import org.junit.runner.RunWith; 132 import org.mockito.Mock; 133 import org.mockito.MockitoAnnotations; 134 135 import java.io.BufferedInputStream; 136 import java.io.BufferedOutputStream; 137 import java.io.ByteArrayInputStream; 138 import java.io.ByteArrayOutputStream; 139 import java.io.PrintWriter; 140 import java.io.StringWriter; 141 import java.util.ArrayList; 142 import java.util.Arrays; 143 import java.util.HashMap; 144 import java.util.LinkedList; 145 import java.util.List; 146 import java.util.Map; 147 import java.util.Objects; 148 import java.util.Set; 149 import java.util.concurrent.ThreadLocalRandom; 150 151 @SmallTest 152 @RunWith(AndroidJUnit4.class) 153 public class PreferencesHelperTest extends UiServiceTestCase { 154 private static final int UID_N_MR1 = 0; 155 private static final int UID_HEADLESS = 1000000; 156 private static final UserHandle USER = UserHandle.of(0); 157 private static final int UID_O = 1111; 158 private static final int UID_P = 2222; 159 private static final String SYSTEM_PKG = "android"; 160 private static final int SYSTEM_UID = 1000; 161 private static final UserHandle USER2 = UserHandle.of(10); 162 private static final String TEST_CHANNEL_ID = "test_channel_id"; 163 private static final String TEST_AUTHORITY = "test"; 164 private static final Uri SOUND_URI = 165 Uri.parse("content://" + TEST_AUTHORITY + "/internal/audio/media/10"); 166 private static final Uri CANONICAL_SOUND_URI = 167 Uri.parse("content://" + TEST_AUTHORITY 168 + "/internal/audio/media/10?title=Test&canonical=1"); 169 170 @Mock PermissionHelper mPermissionHelper; 171 @Mock RankingHandler mHandler; 172 @Mock PackageManager mPm; 173 IContentProvider mTestIContentProvider; 174 @Mock Context mContext; 175 @Mock ZenModeHelper mMockZenModeHelper; 176 @Mock AppOpsManager mAppOpsManager; 177 178 private NotificationManager.Policy mTestNotificationPolicy; 179 180 private PreferencesHelper mHelper; 181 private AudioAttributes mAudioAttributes; 182 private NotificationChannelLoggerFake mLogger = new NotificationChannelLoggerFake(); 183 private WrappedSysUiStatsEvent.WrappedBuilderFactory mStatsEventBuilderFactory; 184 185 @Before setUp()186 public void setUp() throws Exception { 187 MockitoAnnotations.initMocks(this); 188 189 final ApplicationInfo legacy = new ApplicationInfo(); 190 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 191 final ApplicationInfo upgrade = new ApplicationInfo(); 192 upgrade.targetSdkVersion = Build.VERSION_CODES.O; 193 when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy); 194 when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(upgrade); 195 when(mPm.getApplicationInfoAsUser(eq(PKG_P), anyInt(), anyInt())).thenReturn(upgrade); 196 when(mPm.getApplicationInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(upgrade); 197 when(mPm.getPackageUidAsUser(eq(PKG_N_MR1), anyInt())).thenReturn(UID_N_MR1); 198 when(mPm.getPackageUidAsUser(eq(PKG_O), anyInt())).thenReturn(UID_O); 199 when(mPm.getPackageUidAsUser(eq(PKG_P), anyInt())).thenReturn(UID_P); 200 when(mPm.getPackageUidAsUser(eq(SYSTEM_PKG), anyInt())).thenReturn(SYSTEM_UID); 201 PackageInfo info = mock(PackageInfo.class); 202 info.signatures = new Signature[] {mock(Signature.class)}; 203 when(mPm.getPackageInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(info); 204 when(mPm.getPackageInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())) 205 .thenReturn(mock(PackageInfo.class)); 206 when(mContext.getResources()).thenReturn( 207 InstrumentationRegistry.getContext().getResources()); 208 when(mContext.getContentResolver()).thenReturn( 209 InstrumentationRegistry.getContext().getContentResolver()); 210 when(mContext.getPackageManager()).thenReturn(mPm); 211 when(mContext.getApplicationInfo()).thenReturn(legacy); 212 // most tests assume badging is enabled 213 TestableContentResolver contentResolver = getContext().getContentResolver(); 214 contentResolver.setFallbackToExisting(false); 215 Secure.putIntForUser(contentResolver, 216 Secure.NOTIFICATION_BADGING, 1, UserHandle.getUserId(UID_N_MR1)); 217 Secure.putIntForUser(contentResolver, Secure.NOTIFICATION_BUBBLES, 1, 218 UserHandle.getUserId(UID_N_MR1)); 219 220 ContentProvider testContentProvider = mock(ContentProvider.class); 221 mTestIContentProvider = mock(IContentProvider.class, invocation -> { 222 throw new UnsupportedOperationException("unimplemented mock method"); 223 }); 224 doAnswer(invocation -> { 225 AttributionSource attributionSource = invocation.getArgument(0); 226 Uri uri = invocation.getArgument(1); 227 RemoteCallback cb = invocation.getArgument(2); 228 IContentProvider mock = (IContentProvider) (invocation.getMock()); 229 AsyncTask.SERIAL_EXECUTOR.execute(() -> { 230 final Bundle bundle = new Bundle(); 231 try { 232 bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, 233 mock.canonicalize(attributionSource, uri)); 234 } catch (RemoteException e) { /* consume */ } 235 cb.sendResult(bundle); 236 }); 237 return null; 238 }).when(mTestIContentProvider).canonicalizeAsync(any(), any(), any()); 239 doAnswer(invocation -> { 240 AttributionSource attributionSource = invocation.getArgument(0); 241 Uri uri = invocation.getArgument(1); 242 RemoteCallback cb = invocation.getArgument(2); 243 IContentProvider mock = (IContentProvider) (invocation.getMock()); 244 AsyncTask.SERIAL_EXECUTOR.execute(() -> { 245 final Bundle bundle = new Bundle(); 246 try { 247 bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, 248 mock.uncanonicalize(attributionSource, uri)); 249 } catch (RemoteException e) { /* consume */ } 250 cb.sendResult(bundle); 251 }); 252 return null; 253 }).when(mTestIContentProvider).uncanonicalizeAsync(any(), any(), any()); 254 doAnswer(invocation -> { 255 Uri uri = invocation.getArgument(0); 256 RemoteCallback cb = invocation.getArgument(1); 257 IContentProvider mock = (IContentProvider) (invocation.getMock()); 258 AsyncTask.SERIAL_EXECUTOR.execute(() -> { 259 final Bundle bundle = new Bundle(); 260 try { 261 bundle.putString(ContentResolver.REMOTE_CALLBACK_RESULT, mock.getType(uri)); 262 } catch (RemoteException e) { /* consume */ } 263 cb.sendResult(bundle); 264 }); 265 return null; 266 }).when(mTestIContentProvider).getTypeAsync(any(), any()); 267 268 when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider); 269 contentResolver.addProvider(TEST_AUTHORITY, testContentProvider); 270 271 doReturn(CANONICAL_SOUND_URI) 272 .when(mTestIContentProvider).canonicalize(any(), eq(SOUND_URI)); 273 doReturn(CANONICAL_SOUND_URI) 274 .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI)); 275 doReturn(SOUND_URI) 276 .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI)); 277 278 mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 279 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0); 280 when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); 281 when(mAppOpsManager.noteOpNoThrow(anyInt(), anyInt(), 282 anyString(), eq(null), anyString())).thenReturn(MODE_DEFAULT); 283 284 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 285 appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false)); 286 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(true, false)); 287 appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false)); 288 289 when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM)) 290 .thenReturn(appPermissions); 291 292 mStatsEventBuilderFactory = new WrappedSysUiStatsEvent.WrappedBuilderFactory(); 293 294 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 295 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 296 resetZenModeHelper(); 297 298 mAudioAttributes = new AudioAttributes.Builder() 299 .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN) 300 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE) 301 .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED) 302 .build(); 303 304 // make sure that the settings for review notification permissions are unset to begin with 305 Settings.Global.putInt(mContext.getContentResolver(), 306 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 307 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN); 308 } 309 writeXmlAndPurge( String pkg, int uid, boolean forBackup, int userId, String... channelIds)310 private ByteArrayOutputStream writeXmlAndPurge( 311 String pkg, int uid, boolean forBackup, int userId, String... channelIds) 312 throws Exception { 313 TypedXmlSerializer serializer = Xml.newFastSerializer(); 314 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 315 serializer.setOutput(new BufferedOutputStream(baos), "utf-8"); 316 serializer.startDocument(null, true); 317 mHelper.writeXml(serializer, forBackup, userId); 318 serializer.endDocument(); 319 serializer.flush(); 320 for (String channelId : channelIds) { 321 mHelper.permanentlyDeleteNotificationChannel(pkg, uid, channelId); 322 } 323 return baos; 324 } 325 loadStreamXml(ByteArrayOutputStream stream, boolean forRestore, int userId)326 private void loadStreamXml(ByteArrayOutputStream stream, boolean forRestore, int userId) 327 throws Exception { 328 loadByteArrayXml(stream.toByteArray(), forRestore, userId); 329 } 330 loadByteArrayXml(byte[] byteArray, boolean forRestore, int userId)331 private void loadByteArrayXml(byte[] byteArray, boolean forRestore, int userId) 332 throws Exception { 333 TypedXmlPullParser parser = Xml.newFastPullParser(); 334 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(byteArray)), null); 335 parser.nextTag(); 336 mHelper.readXml(parser, forRestore, userId); 337 } 338 compareChannels(NotificationChannel expected, NotificationChannel actual)339 private void compareChannels(NotificationChannel expected, NotificationChannel actual) { 340 assertEquals(expected.getId(), actual.getId()); 341 assertEquals(expected.getName(), actual.getName()); 342 assertEquals(expected.getDescription(), actual.getDescription()); 343 assertEquals(expected.shouldVibrate(), actual.shouldVibrate()); 344 assertEquals(expected.shouldShowLights(), actual.shouldShowLights()); 345 assertEquals(expected.getImportance(), actual.getImportance()); 346 assertEquals(expected.getLockscreenVisibility(), actual.getLockscreenVisibility()); 347 assertEquals(expected.getSound(), actual.getSound()); 348 assertEquals(expected.canBypassDnd(), actual.canBypassDnd()); 349 assertTrue(Arrays.equals(expected.getVibrationPattern(), actual.getVibrationPattern())); 350 assertEquals(expected.getGroup(), actual.getGroup()); 351 assertEquals(expected.getAudioAttributes(), actual.getAudioAttributes()); 352 assertEquals(expected.getLightColor(), actual.getLightColor()); 353 assertEquals(expected.getParentChannelId(), actual.getParentChannelId()); 354 assertEquals(expected.getConversationId(), actual.getConversationId()); 355 assertEquals(expected.isDemoted(), actual.isDemoted()); 356 } 357 compareChannelsParentChild(NotificationChannel parent, NotificationChannel actual, String conversationId)358 private void compareChannelsParentChild(NotificationChannel parent, 359 NotificationChannel actual, String conversationId) { 360 assertEquals(parent.getName(), actual.getName()); 361 assertEquals(parent.getDescription(), actual.getDescription()); 362 assertEquals(parent.shouldVibrate(), actual.shouldVibrate()); 363 assertEquals(parent.shouldShowLights(), actual.shouldShowLights()); 364 assertEquals(parent.getImportance(), actual.getImportance()); 365 assertEquals(parent.getLockscreenVisibility(), actual.getLockscreenVisibility()); 366 assertEquals(parent.getSound(), actual.getSound()); 367 assertEquals(parent.canBypassDnd(), actual.canBypassDnd()); 368 assertTrue(Arrays.equals(parent.getVibrationPattern(), actual.getVibrationPattern())); 369 assertEquals(parent.getGroup(), actual.getGroup()); 370 assertEquals(parent.getAudioAttributes(), actual.getAudioAttributes()); 371 assertEquals(parent.getLightColor(), actual.getLightColor()); 372 assertEquals(parent.getId(), actual.getParentChannelId()); 373 assertEquals(conversationId, actual.getConversationId()); 374 } 375 compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual)376 private void compareGroups(NotificationChannelGroup expected, NotificationChannelGroup actual) { 377 assertEquals(expected.getId(), actual.getId()); 378 assertEquals(expected.getName(), actual.getName()); 379 assertEquals(expected.getDescription(), actual.getDescription()); 380 assertEquals(expected.isBlocked(), actual.isBlocked()); 381 } 382 getChannel()383 private NotificationChannel getChannel() { 384 return new NotificationChannel("id", "name", IMPORTANCE_LOW); 385 } 386 findChannel(List<NotificationChannel> channels, String id)387 private NotificationChannel findChannel(List<NotificationChannel> channels, String id) { 388 for (NotificationChannel channel : channels) { 389 if (channel.getId().equals(id)) { 390 return channel; 391 } 392 } 393 return null; 394 } 395 resetZenModeHelper()396 private void resetZenModeHelper() { 397 reset(mMockZenModeHelper); 398 when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); 399 } 400 setUpPackageWithUid(String packageName, int uid)401 private void setUpPackageWithUid(String packageName, int uid) throws Exception { 402 when(mPm.getApplicationInfoAsUser(eq(packageName), anyInt(), anyInt())) 403 .thenReturn(new ApplicationInfo()); 404 when(mPm.getPackageUidAsUser(eq(packageName), anyInt())).thenReturn(uid); 405 } 406 407 @Test testWriteXml_onlyBackupsTargetUser()408 public void testWriteXml_onlyBackupsTargetUser() throws Exception { 409 // Setup package notifications. 410 String package0 = "test.package.user0"; 411 int uid0 = 1001; 412 setUpPackageWithUid(package0, uid0); 413 NotificationChannel channel0 = new NotificationChannel("id0", "name0", IMPORTANCE_HIGH); 414 assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false)); 415 416 String package10 = "test.package.user10"; 417 int uid10 = 1001001; 418 setUpPackageWithUid(package10, uid10); 419 NotificationChannel channel10 = new NotificationChannel("id10", "name10", IMPORTANCE_HIGH); 420 assertTrue(mHelper.createNotificationChannel(package10, uid10, channel10, true, false)); 421 422 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 423 appPermissions.put(new Pair(uid0, package0), new Pair(false, false)); 424 appPermissions.put(new Pair(uid10, package10), new Pair(true, false)); 425 426 when(mPermissionHelper.getNotificationPermissionValues(10)) 427 .thenReturn(appPermissions); 428 429 ByteArrayOutputStream baos = writeXmlAndPurge(package10, uid10, true, 10); 430 431 // Reset state. 432 mHelper.onPackagesChanged(true, 0, new String[] {package0}, new int[] {uid0}); 433 mHelper.onPackagesChanged(true, 10, new String[] {package10}, new int[] {uid10}); 434 435 // Parse backup data. 436 loadStreamXml(baos, true, 0); 437 loadStreamXml(baos, true, 10); 438 439 assertEquals( 440 channel10, 441 mHelper.getNotificationChannel(package10, uid10, channel10.getId(), false)); 442 assertNull(mHelper.getNotificationChannel(package0, uid0, channel0.getId(), false)); 443 } 444 445 @Test testReadXml_onlyRestoresTargetUser()446 public void testReadXml_onlyRestoresTargetUser() throws Exception { 447 // Setup package in user 0. 448 String package0 = "test.package.user0"; 449 int uid0 = 1001; 450 setUpPackageWithUid(package0, uid0); 451 NotificationChannel channel0 = new NotificationChannel("id0", "name0", IMPORTANCE_HIGH); 452 assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false)); 453 454 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 455 appPermissions.put(new Pair(uid0, package0), new Pair(true, false)); 456 457 when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM)) 458 .thenReturn(appPermissions); 459 460 ByteArrayOutputStream baos = writeXmlAndPurge(package0, uid0, true, 0); 461 462 // Reset state. 463 mHelper.onPackagesChanged(true, 0, new String[] {package0}, new int[] {uid0}); 464 465 // Restore should convert the uid according to the target user. 466 int expectedUid = 1001001; 467 setUpPackageWithUid(package0, expectedUid); 468 // Parse backup data. 469 loadStreamXml(baos, true, 10); 470 471 assertEquals( 472 channel0, 473 mHelper.getNotificationChannel(package0, expectedUid, channel0.getId(), false)); 474 assertNull(mHelper.getNotificationChannel(package0, uid0, channel0.getId(), false)); 475 } 476 477 @Test testChannelXml()478 public void testChannelXml() throws Exception { 479 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 480 ncg.setBlocked(true); 481 ncg.setDescription("group desc"); 482 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 483 NotificationChannel channel1 = 484 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 485 NotificationChannel channel2 = 486 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 487 channel2.setDescription("descriptions for all"); 488 channel2.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 489 channel2.enableLights(true); 490 channel2.setBypassDnd(true); 491 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 492 channel2.enableVibration(true); 493 channel2.setGroup(ncg.getId()); 494 channel2.setVibrationPattern(new long[]{100, 67, 145, 156}); 495 channel2.setLightColor(Color.BLUE); 496 channel2.setConversationId("id1", "conversation"); 497 channel2.setDemoted(true); 498 499 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 500 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); 501 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false)); 502 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false)); 503 504 mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true); 505 506 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, 507 UserHandle.USER_ALL, channel1.getId(), channel2.getId(), 508 NotificationChannel.DEFAULT_CHANNEL_ID); 509 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1}, new int[]{ 510 UID_N_MR1}); 511 512 loadStreamXml(baos, false, UserHandle.USER_ALL); 513 514 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 515 assertEquals(channel1, 516 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false)); 517 compareChannels(channel2, 518 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false)); 519 520 List<NotificationChannelGroup> actualGroups = mHelper.getNotificationChannelGroups( 521 PKG_N_MR1, UID_N_MR1, false, true, false).getList(); 522 boolean foundNcg = false; 523 for (NotificationChannelGroup actual : actualGroups) { 524 if (ncg.getId().equals(actual.getId())) { 525 foundNcg = true; 526 compareGroups(ncg, actual); 527 } else if (ncg2.getId().equals(actual.getId())) { 528 compareGroups(ncg2, actual); 529 } 530 } 531 assertTrue(foundNcg); 532 533 boolean foundChannel2Group = false; 534 for (NotificationChannelGroup actual : actualGroups) { 535 if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) { 536 foundChannel2Group = true; 537 break; 538 } 539 } 540 assertTrue(foundChannel2Group); 541 } 542 543 @Test testChannelXmlForBackup()544 public void testChannelXmlForBackup() throws Exception { 545 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 546 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 547 NotificationChannel channel1 = 548 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 549 NotificationChannel channel2 = 550 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 551 channel2.setDescription("descriptions for all"); 552 channel2.setSound(SOUND_URI, mAudioAttributes); 553 channel2.enableLights(true); 554 channel2.setBypassDnd(true); 555 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 556 channel2.enableVibration(false); 557 channel2.setGroup(ncg.getId()); 558 channel2.setLightColor(Color.BLUE); 559 NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH); 560 channel3.enableVibration(true); 561 562 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 563 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); 564 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 565 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); 566 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false); 567 mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); 568 569 mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true); 570 mHelper.setInvalidMessageSent(PKG_P, UID_P); 571 mHelper.setValidMessageSent(PKG_P, UID_P); 572 mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true); 573 mHelper.setValidBubbleSent(PKG_P, UID_P); 574 575 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, 576 USER_SYSTEM, channel1.getId(), channel2.getId(), channel3.getId(), 577 NotificationChannel.DEFAULT_CHANNEL_ID); 578 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1, PKG_O}, 579 new int[]{UID_N_MR1, UID_O}); 580 581 mHelper.setShowBadge(PKG_O, UID_O, true); 582 583 loadStreamXml(baos, true, USER_SYSTEM); 584 585 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 586 assertTrue(mHelper.hasSentInvalidMsg(PKG_P, UID_P)); 587 assertFalse(mHelper.hasSentInvalidMsg(PKG_N_MR1, UID_N_MR1)); 588 assertTrue(mHelper.hasSentValidMsg(PKG_P, UID_P)); 589 assertTrue(mHelper.didUserEverDemoteInvalidMsgApp(PKG_P, UID_P)); 590 assertTrue(mHelper.hasSentValidBubble(PKG_P, UID_P)); 591 assertEquals(channel1, 592 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false)); 593 compareChannels(channel2, 594 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false)); 595 compareChannels(channel3, 596 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId(), false)); 597 598 List<NotificationChannelGroup> actualGroups = mHelper.getNotificationChannelGroups( 599 PKG_N_MR1, UID_N_MR1, false, true, false).getList(); 600 boolean foundNcg = false; 601 for (NotificationChannelGroup actual : actualGroups) { 602 if (ncg.getId().equals(actual.getId())) { 603 foundNcg = true; 604 compareGroups(ncg, actual); 605 } else if (ncg2.getId().equals(actual.getId())) { 606 compareGroups(ncg2, actual); 607 } 608 } 609 assertTrue(foundNcg); 610 611 boolean foundChannel2Group = false; 612 for (NotificationChannelGroup actual : actualGroups) { 613 if (channel2.getGroup().equals(actual.getChannels().get(0).getGroup())) { 614 foundChannel2Group = true; 615 break; 616 } 617 } 618 assertTrue(foundChannel2Group); 619 } 620 621 @Test testReadXml_oldXml_migrates()622 public void testReadXml_oldXml_migrates() throws Exception { 623 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 624 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true); 625 626 String xml = "<ranking version=\"2\">\n" 627 + "<package name=\"" + PKG_N_MR1 + "\" uid=\"" + UID_N_MR1 628 + "\" show_badge=\"true\">\n" 629 + "<channel id=\"idn\" name=\"name\" importance=\"2\" />\n" 630 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" />\n" 631 + "</package>\n" 632 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" importance=\"0\">\n" 633 + "<channel id=\"ido\" name=\"name2\" importance=\"2\" show_badge=\"true\"/>\n" 634 + "</package>\n" 635 + "<package name=\"" + PKG_P + "\" uid=\"" + UID_P + "\" importance=\"2\">\n" 636 + "<channel id=\"idp\" name=\"name3\" importance=\"4\" locked=\"2\" />\n" 637 + "</package>\n" 638 + "</ranking>\n"; 639 640 loadByteArrayXml(xml.getBytes(), false, USER_SYSTEM); 641 642 // expected values 643 NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW); 644 idn.setSound(null, new AudioAttributes.Builder() 645 .setUsage(USAGE_NOTIFICATION) 646 .setContentType(CONTENT_TYPE_SONIFICATION) 647 .setFlags(0) 648 .build()); 649 idn.setShowBadge(false); 650 NotificationChannel ido = new NotificationChannel("ido", "name2", IMPORTANCE_LOW); 651 ido.setShowBadge(true); 652 ido.setSound(null, new AudioAttributes.Builder() 653 .setUsage(USAGE_NOTIFICATION) 654 .setContentType(CONTENT_TYPE_SONIFICATION) 655 .setFlags(0) 656 .build()); 657 NotificationChannel idp = new NotificationChannel("idp", "name3", IMPORTANCE_HIGH); 658 idp.lockFields(2); 659 idp.setSound(null, new AudioAttributes.Builder() 660 .setUsage(USAGE_NOTIFICATION) 661 .setContentType(CONTENT_TYPE_SONIFICATION) 662 .setFlags(0) 663 .build()); 664 665 // Notifications enabled, not user set 666 PackagePermission nMr1Expected = new PackagePermission(PKG_N_MR1, 0, true, false); 667 // Notifications not enabled, so user set 668 PackagePermission oExpected = new PackagePermission(PKG_O, 0, false, true); 669 // Notifications enabled, user set b/c channel modified 670 PackagePermission pExpected = new PackagePermission(PKG_P, 0, true, true); 671 672 // verify data 673 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 674 675 assertEquals(idn, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, idn.getId(), false)); 676 compareChannels(ido, mHelper.getNotificationChannel(PKG_O, UID_O, ido.getId(), false)); 677 compareChannels(idp, mHelper.getNotificationChannel(PKG_P, UID_P, idp.getId(), false)); 678 679 verify(mPermissionHelper).setNotificationPermission(nMr1Expected); 680 verify(mPermissionHelper).setNotificationPermission(oExpected); 681 verify(mPermissionHelper).setNotificationPermission(pExpected); 682 683 // verify that we also write a state for review_permissions_notification to eventually 684 // show a notification 685 assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW, 686 Settings.Global.getInt(mContext.getContentResolver(), 687 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 688 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN)); 689 } 690 691 @Test testReadXml_oldXml_backup_migratesWhenPkgInstalled()692 public void testReadXml_oldXml_backup_migratesWhenPkgInstalled() throws Exception { 693 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 694 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 695 696 when(mPm.getPackageUidAsUser("pkg1", USER_SYSTEM)).thenReturn(UNKNOWN_UID); 697 when(mPm.getPackageUidAsUser("pkg2", USER_SYSTEM)).thenReturn(UNKNOWN_UID); 698 when(mPm.getPackageUidAsUser("pkg3", USER_SYSTEM)).thenReturn(UNKNOWN_UID); 699 when(mPm.getApplicationInfoAsUser(eq("pkg1"), anyInt(), anyInt())).thenThrow( 700 new PackageManager.NameNotFoundException()); 701 when(mPm.getApplicationInfoAsUser(eq("pkg2"), anyInt(), anyInt())).thenThrow( 702 new PackageManager.NameNotFoundException()); 703 when(mPm.getApplicationInfoAsUser(eq("pkg3"), anyInt(), anyInt())).thenThrow( 704 new PackageManager.NameNotFoundException()); 705 706 String xml = "<ranking version=\"2\">\n" 707 + "<package name=\"pkg1\" show_badge=\"true\">\n" 708 + "<channel id=\"idn\" name=\"name\" importance=\"2\" />\n" 709 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" />\n" 710 + "</package>\n" 711 + "<package name=\"pkg2\" importance=\"0\">\n" 712 + "<channel id=\"ido\" name=\"name2\" importance=\"2\" show_badge=\"true\"/>\n" 713 + "</package>\n" 714 + "<package name=\"pkg3\" importance=\"2\">\n" 715 + "<channel id=\"idp\" name=\"name3\" importance=\"4\" locked=\"2\" />\n" 716 + "</package>\n" 717 + "</ranking>\n"; 718 NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW); 719 idn.setSound(null, new AudioAttributes.Builder() 720 .setUsage(USAGE_NOTIFICATION) 721 .setContentType(CONTENT_TYPE_SONIFICATION) 722 .setFlags(0) 723 .build()); 724 idn.setShowBadge(false); 725 NotificationChannel ido = new NotificationChannel("ido", "name2", IMPORTANCE_LOW); 726 ido.setShowBadge(true); 727 ido.setSound(null, new AudioAttributes.Builder() 728 .setUsage(USAGE_NOTIFICATION) 729 .setContentType(CONTENT_TYPE_SONIFICATION) 730 .setFlags(0) 731 .build()); 732 NotificationChannel idp = new NotificationChannel("idp", "name3", IMPORTANCE_HIGH); 733 idp.lockFields(2); 734 idp.setSound(null, new AudioAttributes.Builder() 735 .setUsage(USAGE_NOTIFICATION) 736 .setContentType(CONTENT_TYPE_SONIFICATION) 737 .setFlags(0) 738 .build()); 739 740 // Notifications enabled, not user set 741 PackagePermission pkg1Expected = new PackagePermission("pkg1", 0, true, false); 742 // Notifications not enabled, so user set 743 PackagePermission pkg2Expected = new PackagePermission("pkg2", 0, false, true); 744 // Notifications enabled, user set b/c channel modified 745 PackagePermission pkg3Expected = new PackagePermission("pkg3", 0, true, true); 746 747 loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM); 748 749 verify(mPermissionHelper, never()).setNotificationPermission(any()); 750 751 when(mPm.getPackageUidAsUser("pkg1", USER_SYSTEM)).thenReturn(11); 752 when(mPm.getPackageUidAsUser("pkg2", USER_SYSTEM)).thenReturn(12); 753 when(mPm.getPackageUidAsUser("pkg3", USER_SYSTEM)).thenReturn(13); 754 755 mHelper.onPackagesChanged( 756 false, 0, new String[]{"pkg1", "pkg2", "pkg3"}, new int[] {11, 12, 13}); 757 758 assertTrue(mHelper.canShowBadge("pkg1", 11)); 759 760 assertEquals(idn, mHelper.getNotificationChannel("pkg1", 11, idn.getId(), false)); 761 compareChannels(ido, mHelper.getNotificationChannel("pkg2", 12, ido.getId(), false)); 762 compareChannels(idp, mHelper.getNotificationChannel("pkg3", 13, idp.getId(), false)); 763 764 verify(mPermissionHelper).setNotificationPermission(pkg1Expected); 765 verify(mPermissionHelper).setNotificationPermission(pkg2Expected); 766 verify(mPermissionHelper).setNotificationPermission(pkg3Expected); 767 } 768 769 @Test testReadXml_newXml_noMigration_showPermissionNotification()770 public void testReadXml_newXml_noMigration_showPermissionNotification() throws Exception { 771 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 772 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true); 773 774 String xml = "<ranking version=\"3\">\n" 775 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" 776 + "<channel id=\"idn\" name=\"name\" importance=\"2\"/>\n" 777 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" />\n" 778 + "</package>\n" 779 + "<package name=\"" + PKG_O + "\" >\n" 780 + "<channel id=\"ido\" name=\"name2\" importance=\"2\" show_badge=\"true\"/>\n" 781 + "</package>\n" 782 + "<package name=\"" + PKG_P + "\" >\n" 783 + "<channel id=\"idp\" name=\"name3\" importance=\"4\" locked=\"2\" />\n" 784 + "</package>\n" 785 + "</ranking>\n"; 786 NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW); 787 idn.setSound(null, new AudioAttributes.Builder() 788 .setUsage(USAGE_NOTIFICATION) 789 .setContentType(CONTENT_TYPE_SONIFICATION) 790 .setFlags(0) 791 .build()); 792 idn.setShowBadge(false); 793 NotificationChannel ido = new NotificationChannel("ido", "name2", IMPORTANCE_LOW); 794 ido.setShowBadge(true); 795 ido.setSound(null, new AudioAttributes.Builder() 796 .setUsage(USAGE_NOTIFICATION) 797 .setContentType(CONTENT_TYPE_SONIFICATION) 798 .setFlags(0) 799 .build()); 800 NotificationChannel idp = new NotificationChannel("idp", "name3", IMPORTANCE_HIGH); 801 idp.lockFields(2); 802 idp.setSound(null, new AudioAttributes.Builder() 803 .setUsage(USAGE_NOTIFICATION) 804 .setContentType(CONTENT_TYPE_SONIFICATION) 805 .setFlags(0) 806 .build()); 807 808 loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM); 809 810 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 811 812 assertEquals(idn, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, idn.getId(), false)); 813 compareChannels(ido, mHelper.getNotificationChannel(PKG_O, UID_O, ido.getId(), false)); 814 compareChannels(idp, mHelper.getNotificationChannel(PKG_P, UID_P, idp.getId(), false)); 815 816 verify(mPermissionHelper, never()).setNotificationPermission(any()); 817 818 // verify that we do, however, write a state for review_permissions_notification to 819 // eventually show a notification, since this XML version is older than the notification 820 assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_SHOULD_SHOW, 821 Settings.Global.getInt(mContext.getContentResolver(), 822 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 823 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN)); 824 } 825 826 @Test testReadXml_newXml_permissionNotificationOff()827 public void testReadXml_newXml_permissionNotificationOff() throws Exception { 828 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 829 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 830 831 String xml = "<ranking version=\"3\">\n" 832 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" 833 + "<channel id=\"idn\" name=\"name\" importance=\"2\"/>\n" 834 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" />\n" 835 + "</package>\n" 836 + "<package name=\"" + PKG_O + "\" >\n" 837 + "<channel id=\"ido\" name=\"name2\" importance=\"2\" show_badge=\"true\"/>\n" 838 + "</package>\n" 839 + "<package name=\"" + PKG_P + "\" >\n" 840 + "<channel id=\"idp\" name=\"name3\" importance=\"4\" locked=\"2\" />\n" 841 + "</package>\n" 842 + "</ranking>\n"; 843 NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW); 844 idn.setSound(null, new AudioAttributes.Builder() 845 .setUsage(USAGE_NOTIFICATION) 846 .setContentType(CONTENT_TYPE_SONIFICATION) 847 .setFlags(0) 848 .build()); 849 idn.setShowBadge(false); 850 NotificationChannel ido = new NotificationChannel("ido", "name2", IMPORTANCE_LOW); 851 ido.setShowBadge(true); 852 ido.setSound(null, new AudioAttributes.Builder() 853 .setUsage(USAGE_NOTIFICATION) 854 .setContentType(CONTENT_TYPE_SONIFICATION) 855 .setFlags(0) 856 .build()); 857 NotificationChannel idp = new NotificationChannel("idp", "name3", IMPORTANCE_HIGH); 858 idp.lockFields(2); 859 idp.setSound(null, new AudioAttributes.Builder() 860 .setUsage(USAGE_NOTIFICATION) 861 .setContentType(CONTENT_TYPE_SONIFICATION) 862 .setFlags(0) 863 .build()); 864 865 loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM); 866 867 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 868 869 assertEquals(idn, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, idn.getId(), false)); 870 compareChannels(ido, mHelper.getNotificationChannel(PKG_O, UID_O, ido.getId(), false)); 871 compareChannels(idp, mHelper.getNotificationChannel(PKG_P, UID_P, idp.getId(), false)); 872 873 verify(mPermissionHelper, never()).setNotificationPermission(any()); 874 875 // while this is the same case as above, if the permission helper is set to not show the 876 // review permissions notification it should not write anything to the settings int 877 assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN, 878 Settings.Global.getInt(mContext.getContentResolver(), 879 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 880 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN)); 881 } 882 883 @Test testReadXml_newXml_noMigration_noPermissionNotification()884 public void testReadXml_newXml_noMigration_noPermissionNotification() throws Exception { 885 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 886 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true); 887 888 String xml = "<ranking version=\"4\">\n" 889 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" 890 + "<channel id=\"idn\" name=\"name\" importance=\"2\"/>\n" 891 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" />\n" 892 + "</package>\n" 893 + "<package name=\"" + PKG_O + "\" >\n" 894 + "<channel id=\"ido\" name=\"name2\" importance=\"2\" show_badge=\"true\"/>\n" 895 + "</package>\n" 896 + "<package name=\"" + PKG_P + "\" >\n" 897 + "<channel id=\"idp\" name=\"name3\" importance=\"4\" locked=\"2\" />\n" 898 + "</package>\n" 899 + "</ranking>\n"; 900 NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW); 901 idn.setSound(null, new AudioAttributes.Builder() 902 .setUsage(USAGE_NOTIFICATION) 903 .setContentType(CONTENT_TYPE_SONIFICATION) 904 .setFlags(0) 905 .build()); 906 idn.setShowBadge(false); 907 NotificationChannel ido = new NotificationChannel("ido", "name2", IMPORTANCE_LOW); 908 ido.setShowBadge(true); 909 ido.setSound(null, new AudioAttributes.Builder() 910 .setUsage(USAGE_NOTIFICATION) 911 .setContentType(CONTENT_TYPE_SONIFICATION) 912 .setFlags(0) 913 .build()); 914 NotificationChannel idp = new NotificationChannel("idp", "name3", IMPORTANCE_HIGH); 915 idp.lockFields(2); 916 idp.setSound(null, new AudioAttributes.Builder() 917 .setUsage(USAGE_NOTIFICATION) 918 .setContentType(CONTENT_TYPE_SONIFICATION) 919 .setFlags(0) 920 .build()); 921 922 loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM); 923 924 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 925 926 assertEquals(idn, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, idn.getId(), false)); 927 compareChannels(ido, mHelper.getNotificationChannel(PKG_O, UID_O, ido.getId(), false)); 928 compareChannels(idp, mHelper.getNotificationChannel(PKG_P, UID_P, idp.getId(), false)); 929 930 verify(mPermissionHelper, never()).setNotificationPermission(any()); 931 932 // this XML is new enough, we should not be attempting to show a notification or anything 933 assertEquals(NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN, 934 Settings.Global.getInt(mContext.getContentResolver(), 935 Settings.Global.REVIEW_PERMISSIONS_NOTIFICATION_STATE, 936 NotificationManagerService.REVIEW_NOTIF_STATE_UNKNOWN)); 937 } 938 939 @Test testReadXml_oldXml_migration_NoUid()940 public void testReadXml_oldXml_migration_NoUid() throws Exception { 941 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 942 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 943 944 when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(UNKNOWN_UID); 945 String xml = "<ranking version=\"2\">\n" 946 + "<package name=\"something\" show_badge=\"true\">\n" 947 + "<channel id=\"idn\" name=\"name\" importance=\"2\"/>\n" 948 + "</package>\n" 949 + "</ranking>\n"; 950 NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW); 951 idn.setSound(null, new AudioAttributes.Builder() 952 .setUsage(USAGE_NOTIFICATION) 953 .setContentType(CONTENT_TYPE_SONIFICATION) 954 .setFlags(0) 955 .build()); 956 idn.setShowBadge(false); 957 958 loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM); 959 verify(mPermissionHelper, never()).setNotificationPermission(any()); 960 961 when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(1234); 962 final ApplicationInfo app = new ApplicationInfo(); 963 app.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 964 when(mPm.getApplicationInfoAsUser(eq("something"), anyInt(), anyInt())).thenReturn(app); 965 966 mHelper.onPackagesChanged(false, 0, new String[] {"something"}, new int[] {1234}); 967 968 969 verify(mPermissionHelper, times(1)).setNotificationPermission(any()); 970 } 971 972 @Test testReadXml_newXml_noMigration_NoUid()973 public void testReadXml_newXml_noMigration_NoUid() throws Exception { 974 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 975 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 976 977 when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(UNKNOWN_UID); 978 String xml = "<ranking version=\"3\">\n" 979 + "<package name=\"something\" show_badge=\"true\">\n" 980 + "<channel id=\"idn\" name=\"name\" importance=\"2\"/>\n" 981 + "</package>\n" 982 + "</ranking>\n"; 983 NotificationChannel idn = new NotificationChannel("idn", "name", IMPORTANCE_LOW); 984 idn.setSound(null, new AudioAttributes.Builder() 985 .setUsage(USAGE_NOTIFICATION) 986 .setContentType(CONTENT_TYPE_SONIFICATION) 987 .setFlags(0) 988 .build()); 989 idn.setShowBadge(false); 990 991 loadByteArrayXml(xml.getBytes(), true, USER_SYSTEM); 992 993 when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(1234); 994 final ApplicationInfo app = new ApplicationInfo(); 995 app.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 996 when(mPm.getApplicationInfoAsUser(eq("something"), anyInt(), anyInt())).thenReturn(app); 997 998 mHelper.onPackagesChanged(false, 0, new String[] {"something"}, new int[] {1234}); 999 1000 1001 verify(mPermissionHelper, never()).setNotificationPermission(any()); 1002 } 1003 1004 @Test testChannelXmlForNonBackup_postMigration()1005 public void testChannelXmlForNonBackup_postMigration() throws Exception { 1006 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 1007 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 1008 1009 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 1010 appPermissions.put(new Pair(1, "first"), new Pair(true, false)); 1011 appPermissions.put(new Pair(3, "third"), new Pair(false, false)); 1012 appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false)); 1013 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); 1014 appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false)); 1015 1016 when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM)) 1017 .thenReturn(appPermissions); 1018 1019 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 1020 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 1021 NotificationChannel channel1 = 1022 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1023 channel1.setSound(null, null); 1024 NotificationChannel channel2 = 1025 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1026 channel2.setDescription("descriptions for all"); 1027 channel2.setSound(null, null); 1028 channel2.enableLights(true); 1029 channel2.setBypassDnd(true); 1030 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1031 channel2.enableVibration(false); 1032 channel2.setGroup(ncg.getId()); 1033 channel2.setLightColor(Color.BLUE); 1034 NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH); 1035 channel3.enableVibration(true); 1036 1037 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 1038 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); 1039 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 1040 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); 1041 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false); 1042 mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); 1043 1044 mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true); 1045 mHelper.setInvalidMessageSent(PKG_P, UID_P); 1046 mHelper.setValidMessageSent(PKG_P, UID_P); 1047 mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true); 1048 1049 ByteArrayOutputStream baos = writeXmlAndPurge( 1050 PKG_N_MR1, UID_N_MR1, false, USER_SYSTEM); 1051 String expected = "<ranking version=\"4\">\n" 1052 + "<package name=\"com.example.o\" show_badge=\"true\" " 1053 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" " 1054 + "sent_valid_msg=\"false\" user_demote_msg_app=\"false\" uid=\"1111\">\n" 1055 + "<channel id=\"id\" name=\"name\" importance=\"2\" " 1056 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1057 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n" 1058 + "</package>\n" 1059 + "<package name=\"com.example.p\" show_badge=\"true\" " 1060 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\"" 1061 + " user_demote_msg_app=\"true\" uid=\"2222\" />\n" 1062 + "<package name=\"com.example.n_mr1\" show_badge=\"true\" " 1063 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" " 1064 + "sent_valid_msg=\"false\" user_demote_msg_app=\"false\" uid=\"0\">\n" 1065 + "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n" 1066 + "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n" 1067 + "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" " 1068 + "orig_imp=\"4\" />\n" 1069 + "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" " 1070 + "importance=\"2\" priority=\"2\" visibility=\"-1\" lights=\"true\" " 1071 + "light_color=\"-16776961\" show_badge=\"true\" group=\"1\" orig_imp=\"2\" />\n" 1072 + "<channel id=\"id3\" name=\"NAM3\" importance=\"4\" " 1073 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1074 + "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" " 1075 + "orig_imp=\"4\" />\n" 1076 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" " 1077 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1078 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" 1079 + "</package>\n" 1080 + "</ranking>"; 1081 assertThat(baos.toString()).contains(expected); 1082 } 1083 1084 @Test testChannelXmlForBackup_postMigration()1085 public void testChannelXmlForBackup_postMigration() throws Exception { 1086 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 1087 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 1088 1089 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 1090 appPermissions.put(new Pair(1, "first"), new Pair(true, false)); 1091 appPermissions.put(new Pair(3, "third"), new Pair(false, false)); 1092 appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false)); 1093 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); 1094 appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false)); 1095 1096 when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM)) 1097 .thenReturn(appPermissions); 1098 1099 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 1100 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 1101 NotificationChannel channel1 = 1102 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1103 channel1.setSound(null, null); 1104 NotificationChannel channel2 = 1105 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1106 channel2.setDescription("descriptions for all"); 1107 channel2.setSound(null, null); 1108 channel2.enableLights(true); 1109 channel2.setBypassDnd(true); 1110 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1111 channel2.enableVibration(false); 1112 channel2.setGroup(ncg.getId()); 1113 channel2.setLightColor(Color.BLUE); 1114 NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH); 1115 channel3.enableVibration(true); 1116 1117 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 1118 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); 1119 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 1120 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); 1121 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false); 1122 mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); 1123 1124 mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true); 1125 mHelper.setInvalidMessageSent(PKG_P, UID_P); 1126 mHelper.setValidMessageSent(PKG_P, UID_P); 1127 mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true); 1128 1129 ByteArrayOutputStream baos = writeXmlAndPurge( 1130 PKG_N_MR1, UID_N_MR1, true, USER_SYSTEM); 1131 String expected = "<ranking version=\"4\">\n" 1132 // Importance 0 because off in permissionhelper 1133 + "<package name=\"com.example.o\" importance=\"0\" show_badge=\"true\" " 1134 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" " 1135 + "sent_valid_msg=\"false\" user_demote_msg_app=\"false\">\n" 1136 + "<channel id=\"id\" name=\"name\" importance=\"2\" " 1137 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1138 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n" 1139 + "</package>\n" 1140 // Importance default because on in permission helper 1141 + "<package name=\"com.example.p\" importance=\"3\" show_badge=\"true\" " 1142 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\"" 1143 + " user_demote_msg_app=\"true\" />\n" 1144 // Importance default because on in permission helper 1145 + "<package name=\"com.example.n_mr1\" importance=\"3\" show_badge=\"true\" " 1146 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" " 1147 + "sent_valid_msg=\"false\" user_demote_msg_app=\"false\">\n" 1148 + "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n" 1149 + "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n" 1150 + "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" " 1151 + "orig_imp=\"4\" />\n" 1152 + "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" " 1153 + "importance=\"2\" priority=\"2\" visibility=\"-1\" lights=\"true\" " 1154 + "light_color=\"-16776961\" show_badge=\"true\" group=\"1\" orig_imp=\"2\" />\n" 1155 + "<channel id=\"id3\" name=\"NAM3\" importance=\"4\" " 1156 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1157 + "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" " 1158 + "orig_imp=\"4\" />\n" 1159 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" " 1160 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1161 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" 1162 + "</package>\n" 1163 // Packages that exist solely in permissionhelper 1164 + "<package name=\"first\" importance=\"3\" />\n" 1165 + "<package name=\"third\" importance=\"0\" />\n" 1166 + "</ranking>"; 1167 assertThat(baos.toString()).contains(expected); 1168 } 1169 1170 @Test testChannelXmlForBackup_postMigration_noExternal()1171 public void testChannelXmlForBackup_postMigration_noExternal() throws Exception { 1172 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 1173 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 1174 1175 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 1176 appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false)); 1177 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); 1178 when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM)) 1179 .thenReturn(appPermissions); 1180 1181 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 1182 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 1183 NotificationChannel channel1 = 1184 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1185 channel1.setSound(null, null); 1186 NotificationChannel channel2 = 1187 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1188 channel2.setDescription("descriptions for all"); 1189 channel2.setSound(null, null); 1190 channel2.enableLights(true); 1191 channel2.setBypassDnd(true); 1192 channel2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1193 channel2.enableVibration(false); 1194 channel2.setGroup(ncg.getId()); 1195 channel2.setLightColor(Color.BLUE); 1196 NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH); 1197 channel3.enableVibration(true); 1198 1199 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 1200 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); 1201 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 1202 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); 1203 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false); 1204 mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); 1205 1206 mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true); 1207 mHelper.setInvalidMessageSent(PKG_P, UID_P); 1208 mHelper.setValidMessageSent(PKG_P, UID_P); 1209 mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true); 1210 1211 ByteArrayOutputStream baos = writeXmlAndPurge( 1212 PKG_N_MR1, UID_N_MR1, true, USER_SYSTEM); 1213 String expected = "<ranking version=\"4\">\n" 1214 // Importance 0 because off in permissionhelper 1215 + "<package name=\"com.example.o\" importance=\"0\" show_badge=\"true\" " 1216 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" " 1217 + "sent_valid_msg=\"false\" user_demote_msg_app=\"false\">\n" 1218 + "<channel id=\"id\" name=\"name\" importance=\"2\" " 1219 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1220 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" orig_imp=\"2\" />\n" 1221 + "</package>\n" 1222 // Importance default because on in permission helper 1223 + "<package name=\"com.example.p\" importance=\"3\" show_badge=\"true\" " 1224 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"true\" sent_valid_msg=\"true\"" 1225 + " user_demote_msg_app=\"true\" />\n" 1226 // Importance missing because missing from permission helper 1227 + "<package name=\"com.example.n_mr1\" show_badge=\"true\" " 1228 + "app_user_locked_fields=\"0\" sent_invalid_msg=\"false\" " 1229 + "sent_valid_msg=\"false\" user_demote_msg_app=\"false\">\n" 1230 + "<channelGroup id=\"1\" name=\"bye\" blocked=\"false\" locked=\"0\" />\n" 1231 + "<channelGroup id=\"2\" name=\"hello\" blocked=\"false\" locked=\"0\" />\n" 1232 + "<channel id=\"id1\" name=\"name1\" importance=\"4\" show_badge=\"true\" " 1233 + "orig_imp=\"4\" />\n" 1234 + "<channel id=\"id2\" name=\"name2\" desc=\"descriptions for all\" " 1235 + "importance=\"2\" priority=\"2\" visibility=\"-1\" lights=\"true\" " 1236 + "light_color=\"-16776961\" show_badge=\"true\" group=\"1\" orig_imp=\"2\" />\n" 1237 + "<channel id=\"id3\" name=\"NAM3\" importance=\"4\" " 1238 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1239 + "content_type=\"4\" flags=\"0\" vibration_enabled=\"true\" show_badge=\"true\" " 1240 + "orig_imp=\"4\" />\n" 1241 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" " 1242 + "sound=\"content://settings/system/notification_sound\" usage=\"5\" " 1243 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" 1244 + "</package>\n" 1245 + "</ranking>"; 1246 assertThat(baos.toString()).contains(expected); 1247 } 1248 1249 @Test testChannelXmlForBackup_postMigration_noLocalSettings()1250 public void testChannelXmlForBackup_postMigration_noLocalSettings() throws Exception { 1251 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 1252 mPermissionHelper, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false); 1253 1254 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 1255 appPermissions.put(new Pair(1, "first"), new Pair(true, false)); 1256 appPermissions.put(new Pair(3, "third"), new Pair(false, false)); 1257 appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false)); 1258 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); 1259 appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false)); 1260 1261 when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM)) 1262 .thenReturn(appPermissions); 1263 1264 ByteArrayOutputStream baos = writeXmlAndPurge( 1265 PKG_N_MR1, UID_N_MR1, true, USER_SYSTEM); 1266 String expected = "<ranking version=\"4\">\n" 1267 // Packages that exist solely in permissionhelper 1268 + "<package name=\"" + PKG_P + "\" importance=\"3\" />\n" 1269 + "<package name=\"" + PKG_O + "\" importance=\"0\" />\n" 1270 + "<package name=\"" + PKG_N_MR1 + "\" importance=\"3\" />\n" 1271 + "<package name=\"first\" importance=\"3\" />\n" 1272 + "<package name=\"third\" importance=\"0\" />\n" 1273 + "</ranking>"; 1274 assertThat(baos.toString()).contains(expected); 1275 } 1276 1277 @Test testBackupXml_backupCanonicalizedSoundUri()1278 public void testBackupXml_backupCanonicalizedSoundUri() throws Exception { 1279 NotificationChannel channel = 1280 new NotificationChannel("id", "name", IMPORTANCE_LOW); 1281 channel.setSound(SOUND_URI, mAudioAttributes); 1282 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1283 1284 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, 1285 USER_SYSTEM, channel.getId()); 1286 1287 // Testing that in restore we are given the canonical version 1288 loadStreamXml(baos, true, USER_SYSTEM); 1289 verify(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI)); 1290 } 1291 1292 @Test testRestoreXml_withExistentCanonicalizedSoundUri()1293 public void testRestoreXml_withExistentCanonicalizedSoundUri() throws Exception { 1294 Uri localUri = Uri.parse("content://" + TEST_AUTHORITY + "/local/url"); 1295 Uri canonicalBasedOnLocal = localUri.buildUpon() 1296 .appendQueryParameter("title", "Test") 1297 .appendQueryParameter("canonical", "1") 1298 .build(); 1299 doReturn(canonicalBasedOnLocal) 1300 .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI)); 1301 doReturn(localUri) 1302 .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI)); 1303 doReturn(localUri) 1304 .when(mTestIContentProvider).uncanonicalize(any(), eq(canonicalBasedOnLocal)); 1305 1306 NotificationChannel channel = 1307 new NotificationChannel("id", "name", IMPORTANCE_LOW); 1308 channel.setSound(SOUND_URI, mAudioAttributes); 1309 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1310 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, 1311 USER_SYSTEM, channel.getId()); 1312 1313 loadStreamXml(baos, true, USER_SYSTEM); 1314 1315 NotificationChannel actualChannel = mHelper.getNotificationChannel( 1316 PKG_N_MR1, UID_N_MR1, channel.getId(), false); 1317 assertEquals(localUri, actualChannel.getSound()); 1318 } 1319 1320 @Test testRestoreXml_withNonExistentCanonicalizedSoundUri()1321 public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception { 1322 Thread.sleep(3000); 1323 doReturn(null) 1324 .when(mTestIContentProvider).canonicalize(any(), eq(CANONICAL_SOUND_URI)); 1325 doReturn(null) 1326 .when(mTestIContentProvider).uncanonicalize(any(), eq(CANONICAL_SOUND_URI)); 1327 1328 NotificationChannel channel = 1329 new NotificationChannel("id", "name", IMPORTANCE_LOW); 1330 channel.setSound(SOUND_URI, mAudioAttributes); 1331 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1332 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, 1333 USER_SYSTEM, channel.getId()); 1334 1335 loadStreamXml(baos, true, USER_SYSTEM); 1336 1337 NotificationChannel actualChannel = mHelper.getNotificationChannel( 1338 PKG_N_MR1, UID_N_MR1, channel.getId(), false); 1339 assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound()); 1340 } 1341 1342 1343 /** 1344 * Although we don't make backups with uncanonicalized uris anymore, we used to, so we have to 1345 * handle its restore properly. 1346 */ 1347 @Test testRestoreXml_withUncanonicalizedNonLocalSoundUri()1348 public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception { 1349 // Not a local uncanonicalized uri, simulating that it fails to exist locally 1350 doReturn(null) 1351 .when(mTestIContentProvider).canonicalize(any(), eq(SOUND_URI)); 1352 String id = "id"; 1353 String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n" 1354 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" 1355 + "<channel id=\"" + id + "\" name=\"name\" importance=\"2\" " 1356 + "sound=\"" + SOUND_URI + "\" " 1357 + "usage=\"6\" content_type=\"0\" flags=\"1\" show_badge=\"true\" />\n" 1358 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" usage=\"5\" " 1359 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" 1360 + "</package>\n" 1361 + "</ranking>\n"; 1362 1363 loadByteArrayXml( 1364 backupWithUncanonicalizedSoundUri.getBytes(), true, USER_SYSTEM); 1365 1366 NotificationChannel actualChannel = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, id, false); 1367 assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, actualChannel.getSound()); 1368 } 1369 1370 @Test testBackupRestoreXml_withNullSoundUri()1371 public void testBackupRestoreXml_withNullSoundUri() throws Exception { 1372 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 1373 appPermissions.put(new Pair(UID_N_MR1, PKG_N_MR1), new Pair(true, false)); 1374 1375 when(mPermissionHelper.getNotificationPermissionValues(USER_SYSTEM)) 1376 .thenReturn(appPermissions); 1377 1378 NotificationChannel channel = 1379 new NotificationChannel("id", "name", IMPORTANCE_LOW); 1380 channel.setSound(null, mAudioAttributes); 1381 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1382 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, 1383 USER_SYSTEM, channel.getId()); 1384 1385 loadStreamXml(baos, true, USER_SYSTEM); 1386 1387 NotificationChannel actualChannel = mHelper.getNotificationChannel( 1388 PKG_N_MR1, UID_N_MR1, channel.getId(), false); 1389 assertEquals(null, actualChannel.getSound()); 1390 } 1391 1392 @Test testChannelXml_backup()1393 public void testChannelXml_backup() throws Exception { 1394 NotificationChannelGroup ncg = new NotificationChannelGroup("1", "bye"); 1395 NotificationChannelGroup ncg2 = new NotificationChannelGroup("2", "hello"); 1396 NotificationChannel channel1 = 1397 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 1398 NotificationChannel channel2 = 1399 new NotificationChannel("id2", "name2", IMPORTANCE_HIGH); 1400 NotificationChannel channel3 = 1401 new NotificationChannel("id3", "name3", IMPORTANCE_LOW); 1402 channel3.setGroup(ncg.getId()); 1403 1404 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 1405 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); 1406 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 1407 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); 1408 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false); 1409 1410 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId()); 1411 mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg.getId()); 1412 assertEquals(channel2, 1413 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false)); 1414 1415 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, true, 1416 USER_SYSTEM, channel1.getId(), channel2.getId(), channel3.getId(), 1417 NotificationChannel.DEFAULT_CHANNEL_ID); 1418 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_N_MR1}, new int[]{ 1419 UID_N_MR1}); 1420 1421 TypedXmlPullParser parser = Xml.newFastPullParser(); 1422 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), 1423 null); 1424 parser.nextTag(); 1425 mHelper.readXml(parser, true, USER_SYSTEM); 1426 1427 assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1.getId(), false)); 1428 assertNull(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId(), false)); 1429 assertNull(mHelper.getNotificationChannelGroup(ncg.getId(), PKG_N_MR1, UID_N_MR1)); 1430 assertEquals(channel2, 1431 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2.getId(), false)); 1432 } 1433 1434 @Test testChannelXml_defaultChannelLegacyApp_noUserSettings()1435 public void testChannelXml_defaultChannelLegacyApp_noUserSettings() throws Exception { 1436 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, 1437 UserHandle.USER_ALL, NotificationChannel.DEFAULT_CHANNEL_ID); 1438 1439 loadStreamXml(baos, false, UserHandle.USER_ALL); 1440 1441 final NotificationChannel updated = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, 1442 NotificationChannel.DEFAULT_CHANNEL_ID, false); 1443 assertEquals(NotificationManager.IMPORTANCE_UNSPECIFIED, updated.getImportance()); 1444 assertFalse(updated.canBypassDnd()); 1445 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, updated.getLockscreenVisibility()); 1446 assertEquals(0, updated.getUserLockedFields()); 1447 } 1448 1449 @Test testChannelXml_defaultChannelUpdatedApp_userSettings()1450 public void testChannelXml_defaultChannelUpdatedApp_userSettings() throws Exception { 1451 final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG_N_MR1, 1452 UID_N_MR1, 1453 NotificationChannel.DEFAULT_CHANNEL_ID, false); 1454 defaultChannel.setImportance(NotificationManager.IMPORTANCE_LOW); 1455 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true); 1456 1457 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, 1458 UserHandle.USER_ALL, NotificationChannel.DEFAULT_CHANNEL_ID); 1459 1460 loadStreamXml(baos, false, UserHandle.USER_ALL); 1461 1462 assertEquals(NotificationManager.IMPORTANCE_LOW, mHelper.getNotificationChannel( 1463 PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false).getImportance()); 1464 } 1465 1466 @Test testChannelXml_upgradeCreateDefaultChannel()1467 public void testChannelXml_upgradeCreateDefaultChannel() throws Exception { 1468 final String preupgradeXml = "<ranking version=\"1\">\n" 1469 + "<package name=\"" + PKG_N_MR1 1470 + "\" importance=\"" + NotificationManager.IMPORTANCE_HIGH 1471 + "\" priority=\"" + Notification.PRIORITY_MAX + "\" visibility=\"" 1472 + Notification.VISIBILITY_SECRET + "\"" +" uid=\"" + UID_N_MR1 + "\" />\n" 1473 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" visibility=\"" 1474 + Notification.VISIBILITY_PRIVATE + "\" />\n" 1475 + "</ranking>"; 1476 TypedXmlPullParser parser = Xml.newFastPullParser(); 1477 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(preupgradeXml.getBytes())), 1478 null); 1479 parser.nextTag(); 1480 mHelper.readXml(parser, false, UserHandle.USER_ALL); 1481 1482 final NotificationChannel updated1 = 1483 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); 1484 assertEquals(NotificationManager.IMPORTANCE_HIGH, updated1.getImportance()); 1485 assertTrue(updated1.canBypassDnd()); 1486 assertEquals(Notification.VISIBILITY_SECRET, updated1.getLockscreenVisibility()); 1487 assertEquals(NotificationChannel.USER_LOCKED_IMPORTANCE 1488 | NotificationChannel.USER_LOCKED_PRIORITY 1489 | NotificationChannel.USER_LOCKED_VISIBILITY, 1490 updated1.getUserLockedFields()); 1491 1492 // No Default Channel created for updated packages 1493 assertEquals(null, mHelper.getNotificationChannel(PKG_O, UID_O, 1494 NotificationChannel.DEFAULT_CHANNEL_ID, false)); 1495 } 1496 1497 @Test testChannelXml_upgradeDeletesDefaultChannel()1498 public void testChannelXml_upgradeDeletesDefaultChannel() throws Exception { 1499 final NotificationChannel defaultChannel = mHelper.getNotificationChannel( 1500 PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); 1501 assertTrue(defaultChannel != null); 1502 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, 1503 UserHandle.USER_ALL, NotificationChannel.DEFAULT_CHANNEL_ID); 1504 // Load package at higher sdk. 1505 final ApplicationInfo upgraded = new ApplicationInfo(); 1506 upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 1507 when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(upgraded); 1508 loadStreamXml(baos, false, UserHandle.USER_ALL); 1509 1510 // Default Channel should be gone. 1511 assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, 1512 NotificationChannel.DEFAULT_CHANNEL_ID, false)); 1513 } 1514 1515 @Test testDeletesDefaultChannelAfterChannelIsCreated()1516 public void testDeletesDefaultChannelAfterChannelIsCreated() throws Exception { 1517 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, 1518 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false); 1519 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, 1520 UserHandle.USER_ALL, NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); 1521 1522 // Load package at higher sdk. 1523 final ApplicationInfo upgraded = new ApplicationInfo(); 1524 upgraded.targetSdkVersion = Build.VERSION_CODES.N_MR1 + 1; 1525 when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(upgraded); 1526 loadStreamXml(baos, false, UserHandle.USER_ALL); 1527 1528 // Default Channel should be gone. 1529 assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, 1530 NotificationChannel.DEFAULT_CHANNEL_ID, false)); 1531 } 1532 1533 @Test testLoadingOldChannelsDoesNotDeleteNewlyCreatedChannels()1534 public void testLoadingOldChannelsDoesNotDeleteNewlyCreatedChannels() throws Exception { 1535 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_N_MR1, UID_N_MR1, false, 1536 UserHandle.USER_ALL, NotificationChannel.DEFAULT_CHANNEL_ID, "bananas"); 1537 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, 1538 new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false); 1539 1540 loadStreamXml(baos, false, UserHandle.USER_ALL); 1541 1542 // Should still have the newly created channel that wasn't in the xml. 1543 assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "bananas", false) != null); 1544 } 1545 1546 @Test testCreateChannel_badImportance()1547 public void testCreateChannel_badImportance() throws Exception { 1548 try { 1549 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, 1550 new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1), 1551 true, false); 1552 fail("Was allowed to create a channel with invalid importance"); 1553 } catch (IllegalArgumentException e) { 1554 // yay 1555 } 1556 try { 1557 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, 1558 new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED), 1559 true, false); 1560 fail("Was allowed to create a channel with invalid importance"); 1561 } catch (IllegalArgumentException e) { 1562 // yay 1563 } 1564 try { 1565 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, 1566 new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1), 1567 true, false); 1568 fail("Was allowed to create a channel with invalid importance"); 1569 } catch (IllegalArgumentException e) { 1570 // yay 1571 } 1572 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, 1573 new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true, false)); 1574 assertFalse(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, 1575 new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false)); 1576 } 1577 1578 1579 @Test testUpdate()1580 public void testUpdate() throws Exception { 1581 // no fields locked by user 1582 final NotificationChannel channel = 1583 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1584 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 1585 channel.enableLights(true); 1586 channel.setBypassDnd(true); 1587 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1588 1589 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false)); 1590 1591 // same id, try to update all fields 1592 final NotificationChannel channel2 = 1593 new NotificationChannel("id2", "name2", NotificationManager.IMPORTANCE_HIGH); 1594 channel2.setSound(new Uri.Builder().scheme("test2").build(), mAudioAttributes); 1595 channel2.enableLights(false); 1596 channel2.setBypassDnd(false); 1597 channel2.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); 1598 1599 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true); 1600 1601 // all fields should be changed 1602 assertEquals(channel2, 1603 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false)); 1604 1605 verify(mHandler, times(1)).requestSort(); 1606 } 1607 1608 @Test testUpdate_preUpgrade_updatesAppFields()1609 public void testUpdate_preUpgrade_updatesAppFields() throws Exception { 1610 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 1611 assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1)); 1612 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, 1613 mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1)); 1614 1615 NotificationChannel defaultChannel = mHelper.getNotificationChannel( 1616 PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); 1617 1618 defaultChannel.setShowBadge(false); 1619 defaultChannel.setImportance(IMPORTANCE_NONE); 1620 defaultChannel.setBypassDnd(true); 1621 defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1622 1623 mHelper.setAppImportanceLocked(PKG_N_MR1, UID_N_MR1); 1624 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true); 1625 1626 // ensure app level fields are changed 1627 assertFalse(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 1628 assertEquals(Notification.PRIORITY_MAX, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1)); 1629 assertEquals(Notification.VISIBILITY_SECRET, mHelper.getPackageVisibility(PKG_N_MR1, 1630 UID_N_MR1)); 1631 } 1632 1633 @Test testUpdate_postUpgrade_noUpdateAppFields()1634 public void testUpdate_postUpgrade_noUpdateAppFields() throws Exception { 1635 final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1636 1637 mHelper.createNotificationChannel(PKG_O, UID_O, channel, false, false); 1638 assertTrue(mHelper.canShowBadge(PKG_O, UID_O)); 1639 assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_O, UID_O)); 1640 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, 1641 mHelper.getPackageVisibility(PKG_O, UID_O)); 1642 1643 channel.setShowBadge(false); 1644 channel.setImportance(IMPORTANCE_NONE); 1645 channel.setBypassDnd(true); 1646 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1647 1648 mHelper.updateNotificationChannel(PKG_O, UID_O, channel, true); 1649 1650 // ensure app level fields are not changed 1651 assertTrue(mHelper.canShowBadge(PKG_O, UID_O)); 1652 assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_O, UID_O)); 1653 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, 1654 mHelper.getPackageVisibility(PKG_O, UID_O)); 1655 } 1656 1657 @Test testUpdate_preUpgrade_noUpdateAppFieldsWithMultipleChannels()1658 public void testUpdate_preUpgrade_noUpdateAppFieldsWithMultipleChannels() throws Exception { 1659 final NotificationChannel channel = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1660 1661 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false); 1662 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 1663 assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1)); 1664 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, 1665 mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1)); 1666 1667 channel.setShowBadge(false); 1668 channel.setImportance(IMPORTANCE_NONE); 1669 channel.setBypassDnd(true); 1670 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1671 1672 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true); 1673 1674 NotificationChannel defaultChannel = mHelper.getNotificationChannel( 1675 PKG_N_MR1, UID_N_MR1, NotificationChannel.DEFAULT_CHANNEL_ID, false); 1676 1677 defaultChannel.setShowBadge(false); 1678 defaultChannel.setImportance(IMPORTANCE_NONE); 1679 defaultChannel.setBypassDnd(true); 1680 defaultChannel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1681 1682 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, defaultChannel, true); 1683 1684 // ensure app level fields are not changed 1685 assertTrue(mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 1686 assertEquals(Notification.PRIORITY_DEFAULT, mHelper.getPackagePriority(PKG_N_MR1, UID_N_MR1)); 1687 assertEquals(NotificationManager.VISIBILITY_NO_OVERRIDE, 1688 mHelper.getPackageVisibility(PKG_N_MR1, UID_N_MR1)); 1689 } 1690 1691 @Test testGetNotificationChannel_ReturnsNullForUnknownChannel()1692 public void testGetNotificationChannel_ReturnsNullForUnknownChannel() throws Exception { 1693 assertEquals(null, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "garbage", false)); 1694 } 1695 1696 @Test testCreateChannel_CannotChangeHiddenFields()1697 public void testCreateChannel_CannotChangeHiddenFields() { 1698 final NotificationChannel channel = 1699 new NotificationChannel("id2", "name2", IMPORTANCE_HIGH); 1700 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 1701 channel.enableLights(true); 1702 channel.setBypassDnd(true); 1703 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1704 channel.setShowBadge(true); 1705 channel.setAllowBubbles(false); 1706 channel.setImportantConversation(true); 1707 int lockMask = 0; 1708 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 1709 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 1710 } 1711 channel.lockFields(lockMask); 1712 1713 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false)); 1714 1715 NotificationChannel savedChannel = 1716 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false); 1717 1718 assertEquals(channel.getName(), savedChannel.getName()); 1719 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 1720 assertFalse(savedChannel.canBypassDnd()); 1721 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 1722 assertFalse(channel.isImportantConversation()); 1723 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 1724 assertEquals(channel.canBubble(), savedChannel.canBubble()); 1725 1726 verify(mHandler, never()).requestSort(); 1727 } 1728 1729 @Test testCreateChannel_CannotChangeHiddenFieldsAssistant()1730 public void testCreateChannel_CannotChangeHiddenFieldsAssistant() { 1731 final NotificationChannel channel = 1732 new NotificationChannel("id2", "name2", IMPORTANCE_HIGH); 1733 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 1734 channel.enableLights(true); 1735 channel.setBypassDnd(true); 1736 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1737 channel.setShowBadge(true); 1738 channel.setAllowBubbles(false); 1739 int lockMask = 0; 1740 for (int i = 0; i < NotificationChannel.LOCKABLE_FIELDS.length; i++) { 1741 lockMask |= NotificationChannel.LOCKABLE_FIELDS[i]; 1742 } 1743 channel.lockFields(lockMask); 1744 1745 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1746 1747 NotificationChannel savedChannel = 1748 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false); 1749 1750 assertEquals(channel.getName(), savedChannel.getName()); 1751 assertEquals(channel.shouldShowLights(), savedChannel.shouldShowLights()); 1752 assertFalse(savedChannel.canBypassDnd()); 1753 assertFalse(Notification.VISIBILITY_SECRET == savedChannel.getLockscreenVisibility()); 1754 assertEquals(channel.canShowBadge(), savedChannel.canShowBadge()); 1755 assertEquals(channel.canBubble(), savedChannel.canBubble()); 1756 } 1757 1758 @Test testClearLockedFields()1759 public void testClearLockedFields() { 1760 final NotificationChannel channel = getChannel(); 1761 mHelper.clearLockedFieldsLocked(channel); 1762 assertEquals(0, channel.getUserLockedFields()); 1763 1764 channel.lockFields(NotificationChannel.USER_LOCKED_PRIORITY 1765 | NotificationChannel.USER_LOCKED_IMPORTANCE); 1766 mHelper.clearLockedFieldsLocked(channel); 1767 assertEquals(0, channel.getUserLockedFields()); 1768 } 1769 1770 @Test testLockFields_soundAndVibration()1771 public void testLockFields_soundAndVibration() { 1772 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); 1773 1774 final NotificationChannel update1 = getChannel(); 1775 update1.setSound(new Uri.Builder().scheme("test").build(), 1776 new AudioAttributes.Builder().build()); 1777 update1.lockFields(NotificationChannel.USER_LOCKED_PRIORITY); 1778 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true); 1779 assertEquals(NotificationChannel.USER_LOCKED_PRIORITY 1780 | NotificationChannel.USER_LOCKED_SOUND, 1781 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false) 1782 .getUserLockedFields()); 1783 1784 NotificationChannel update2 = getChannel(); 1785 update2.enableVibration(true); 1786 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true); 1787 assertEquals(NotificationChannel.USER_LOCKED_PRIORITY 1788 | NotificationChannel.USER_LOCKED_SOUND 1789 | NotificationChannel.USER_LOCKED_VIBRATION, 1790 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false) 1791 .getUserLockedFields()); 1792 } 1793 1794 @Test testLockFields_vibrationAndLights()1795 public void testLockFields_vibrationAndLights() { 1796 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); 1797 1798 final NotificationChannel update1 = getChannel(); 1799 update1.setVibrationPattern(new long[]{7945, 46 ,246}); 1800 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true); 1801 assertEquals(NotificationChannel.USER_LOCKED_VIBRATION, 1802 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false) 1803 .getUserLockedFields()); 1804 1805 final NotificationChannel update2 = getChannel(); 1806 update2.enableLights(true); 1807 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true); 1808 assertEquals(NotificationChannel.USER_LOCKED_VIBRATION 1809 | NotificationChannel.USER_LOCKED_LIGHTS, 1810 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false) 1811 .getUserLockedFields()); 1812 } 1813 1814 @Test testLockFields_lightsAndImportance()1815 public void testLockFields_lightsAndImportance() { 1816 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); 1817 1818 final NotificationChannel update1 = getChannel(); 1819 update1.setLightColor(Color.GREEN); 1820 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true); 1821 assertEquals(NotificationChannel.USER_LOCKED_LIGHTS, 1822 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false) 1823 .getUserLockedFields()); 1824 1825 final NotificationChannel update2 = getChannel(); 1826 update2.setImportance(IMPORTANCE_DEFAULT); 1827 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true); 1828 assertEquals(NotificationChannel.USER_LOCKED_LIGHTS 1829 | NotificationChannel.USER_LOCKED_IMPORTANCE, 1830 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false) 1831 .getUserLockedFields()); 1832 } 1833 1834 @Test testLockFields_visibilityAndDndAndBadge()1835 public void testLockFields_visibilityAndDndAndBadge() { 1836 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); 1837 assertEquals(0, 1838 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel().getId(), false) 1839 .getUserLockedFields()); 1840 1841 final NotificationChannel update1 = getChannel(); 1842 update1.setBypassDnd(true); 1843 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update1, true); 1844 assertEquals(NotificationChannel.USER_LOCKED_PRIORITY, 1845 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update1.getId(), false) 1846 .getUserLockedFields()); 1847 1848 final NotificationChannel update2 = getChannel(); 1849 update2.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1850 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update2, true); 1851 assertEquals(NotificationChannel.USER_LOCKED_PRIORITY 1852 | NotificationChannel.USER_LOCKED_VISIBILITY, 1853 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update2.getId(), false) 1854 .getUserLockedFields()); 1855 1856 final NotificationChannel update3 = getChannel(); 1857 update3.setShowBadge(false); 1858 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update3, true); 1859 assertEquals(NotificationChannel.USER_LOCKED_PRIORITY 1860 | NotificationChannel.USER_LOCKED_VISIBILITY 1861 | NotificationChannel.USER_LOCKED_SHOW_BADGE, 1862 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update3.getId(), false) 1863 .getUserLockedFields()); 1864 } 1865 1866 @Test testLockFields_allowBubble()1867 public void testLockFields_allowBubble() { 1868 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); 1869 assertEquals(0, 1870 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel().getId(), false) 1871 .getUserLockedFields()); 1872 1873 final NotificationChannel update = getChannel(); 1874 update.setAllowBubbles(true); 1875 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true); 1876 assertEquals(NotificationChannel.USER_LOCKED_ALLOW_BUBBLE, 1877 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, update.getId(), false) 1878 .getUserLockedFields()); 1879 } 1880 1881 @Test testDeleteNonExistentChannel()1882 public void testDeleteNonExistentChannel() throws Exception { 1883 mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, "does not exist"); 1884 } 1885 1886 @Test testDoubleDeleteChannel()1887 public void testDoubleDeleteChannel() throws Exception { 1888 NotificationChannel channel = getChannel(); 1889 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1890 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); 1891 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); 1892 assertEquals(2, mLogger.getCalls().size()); 1893 assertEquals( 1894 NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED, 1895 mLogger.get(0).event); 1896 assertEquals( 1897 NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_DELETED, 1898 mLogger.get(1).event); 1899 // No log for the second delete of the same channel. 1900 } 1901 1902 @Test testGetDeletedChannel()1903 public void testGetDeletedChannel() throws Exception { 1904 NotificationChannel channel = getChannel(); 1905 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 1906 channel.enableLights(true); 1907 channel.setBypassDnd(true); 1908 channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET); 1909 channel.enableVibration(true); 1910 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 1911 1912 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1913 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); 1914 1915 // Does not return deleted channel 1916 NotificationChannel response = 1917 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false); 1918 assertNull(response); 1919 1920 // Returns deleted channel 1921 response = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true); 1922 compareChannels(channel, response); 1923 assertTrue(response.isDeleted()); 1924 } 1925 1926 @Test testGetDeletedChannels()1927 public void testGetDeletedChannels() throws Exception { 1928 Map<String, NotificationChannel> channelMap = new HashMap<>(); 1929 NotificationChannel channel = 1930 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1931 channel.setSound(new Uri.Builder().scheme("test").build(), mAudioAttributes); 1932 channel.enableLights(true); 1933 channel.setBypassDnd(true); 1934 channel.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE); 1935 channel.enableVibration(true); 1936 channel.setVibrationPattern(new long[]{100, 67, 145, 156}); 1937 channelMap.put(channel.getId(), channel); 1938 NotificationChannel channel2 = 1939 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 1940 channelMap.put(channel2.getId(), channel2); 1941 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1942 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false); 1943 1944 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); 1945 1946 // Returns only non-deleted channels 1947 List<NotificationChannel> channels = 1948 mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList(); 1949 assertEquals(2, channels.size()); // Default channel + non-deleted channel 1950 for (NotificationChannel nc : channels) { 1951 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 1952 compareChannels(channel2, nc); 1953 } 1954 } 1955 1956 // Returns deleted channels too 1957 channels = mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList(); 1958 assertEquals(3, channels.size()); // Includes default channel 1959 for (NotificationChannel nc : channels) { 1960 if (!NotificationChannel.DEFAULT_CHANNEL_ID.equals(nc.getId())) { 1961 compareChannels(channelMap.get(nc.getId()), nc); 1962 } 1963 } 1964 } 1965 1966 @Test testGetDeletedChannelCount()1967 public void testGetDeletedChannelCount() throws Exception { 1968 NotificationChannel channel = 1969 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1970 NotificationChannel channel2 = 1971 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_HIGH); 1972 NotificationChannel channel3 = 1973 new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_HIGH); 1974 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1975 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false); 1976 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false); 1977 1978 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); 1979 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId()); 1980 1981 assertEquals(2, mHelper.getDeletedChannelCount(PKG_N_MR1, UID_N_MR1)); 1982 assertEquals(0, mHelper.getDeletedChannelCount("pkg2", UID_O)); 1983 } 1984 1985 @Test testGetBlockedChannelCount()1986 public void testGetBlockedChannelCount() throws Exception { 1987 NotificationChannel channel = 1988 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 1989 NotificationChannel channel2 = 1990 new NotificationChannel("id4", "a", NotificationManager.IMPORTANCE_NONE); 1991 NotificationChannel channel3 = 1992 new NotificationChannel("id5", "a", NotificationManager.IMPORTANCE_NONE); 1993 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 1994 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false); 1995 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false); 1996 1997 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3.getId()); 1998 1999 assertEquals(1, mHelper.getBlockedChannelCount(PKG_N_MR1, UID_N_MR1)); 2000 assertEquals(0, mHelper.getBlockedChannelCount("pkg2", UID_O)); 2001 } 2002 2003 @Test testGetChannelsBypassingDndCount_noChannelsBypassing()2004 public void testGetChannelsBypassingDndCount_noChannelsBypassing() throws Exception { 2005 assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1, 2006 UID_N_MR1).getList().size()); 2007 } 2008 2009 @Test testGetChannelsBypassingDnd_noChannelsForUidBypassing()2010 public void testGetChannelsBypassingDnd_noChannelsForUidBypassing() 2011 throws Exception { 2012 int uid = 222; 2013 NotificationChannel channel = new NotificationChannel("id", "name", 2014 NotificationManager.IMPORTANCE_MAX); 2015 channel.setBypassDnd(true); 2016 mHelper.createNotificationChannel(PKG_N_MR1, 111, channel, true, true); 2017 2018 assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1, 2019 uid).getList().size()); 2020 } 2021 2022 @Test testGetChannelsBypassingDndCount_oneChannelBypassing_groupBlocked()2023 public void testGetChannelsBypassingDndCount_oneChannelBypassing_groupBlocked() { 2024 int uid = UID_N_MR1; 2025 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 2026 NotificationChannel channel1 = new NotificationChannel("id1", "name1", 2027 NotificationManager.IMPORTANCE_MAX); 2028 channel1.setBypassDnd(true); 2029 channel1.setGroup(ncg.getId()); 2030 mHelper.createNotificationChannelGroup(PKG_N_MR1, uid, ncg, /* fromTargetApp */ true); 2031 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel1, true, /*has DND access*/ true); 2032 2033 assertEquals(1, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1, 2034 uid).getList().size()); 2035 2036 // disable group 2037 ncg.setBlocked(true); 2038 mHelper.createNotificationChannelGroup(PKG_N_MR1, uid, ncg, /* fromTargetApp */ false); 2039 assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1, 2040 uid).getList().size()); 2041 } 2042 2043 @Test testGetChannelsBypassingDndCount_multipleChannelsBypassing()2044 public void testGetChannelsBypassingDndCount_multipleChannelsBypassing() { 2045 int uid = UID_N_MR1; 2046 NotificationChannel channel1 = new NotificationChannel("id1", "name1", 2047 NotificationManager.IMPORTANCE_MAX); 2048 NotificationChannel channel2 = new NotificationChannel("id2", "name2", 2049 NotificationManager.IMPORTANCE_MAX); 2050 NotificationChannel channel3 = new NotificationChannel("id3", "name3", 2051 NotificationManager.IMPORTANCE_MAX); 2052 channel1.setBypassDnd(true); 2053 channel2.setBypassDnd(true); 2054 channel3.setBypassDnd(true); 2055 // has DND access, so can set bypassDnd attribute 2056 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel1, true, /*has DND access*/ true); 2057 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true); 2058 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel3, true, true); 2059 assertEquals(3, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1, 2060 uid).getList().size()); 2061 2062 // setBypassDnd false for some channels 2063 channel1.setBypassDnd(false); 2064 channel2.setBypassDnd(false); 2065 assertEquals(1, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1, 2066 uid).getList().size()); 2067 2068 // setBypassDnd false for rest of the channels 2069 channel3.setBypassDnd(false); 2070 assertEquals(0, mHelper.getNotificationChannelsBypassingDnd(PKG_N_MR1, 2071 uid).getList().size()); 2072 } 2073 2074 @Test testCreateAndDeleteCanChannelsBypassDnd_localSettings()2075 public void testCreateAndDeleteCanChannelsBypassDnd_localSettings() { 2076 int uid = UserManager.isHeadlessSystemUserMode() ? UID_HEADLESS : UID_N_MR1; 2077 when(mPermissionHelper.hasPermission(uid)).thenReturn(true); 2078 2079 // create notification channel that can't bypass dnd 2080 // expected result: areChannelsBypassingDnd = false 2081 // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false 2082 NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW); 2083 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false); 2084 assertFalse(mHelper.areChannelsBypassingDnd()); 2085 verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); 2086 resetZenModeHelper(); 2087 2088 // create notification channel that can bypass dnd 2089 // expected result: areChannelsBypassingDnd = true 2090 NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2091 channel2.setBypassDnd(true); 2092 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true); 2093 assertTrue(mHelper.areChannelsBypassingDnd()); 2094 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2095 resetZenModeHelper(); 2096 2097 // delete channels 2098 mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel.getId()); 2099 assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND 2100 verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); 2101 resetZenModeHelper(); 2102 2103 mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel2.getId()); 2104 assertFalse(mHelper.areChannelsBypassingDnd()); 2105 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2106 resetZenModeHelper(); 2107 } 2108 2109 @Test testCreateAndUpdateChannelsBypassingDnd_permissionHelper()2110 public void testCreateAndUpdateChannelsBypassingDnd_permissionHelper() { 2111 int uid = UserManager.isHeadlessSystemUserMode() ? UID_HEADLESS : UID_N_MR1; 2112 when(mPermissionHelper.hasPermission(uid)).thenReturn(true); 2113 2114 // create notification channel that can't bypass dnd 2115 // expected result: areChannelsBypassingDnd = false 2116 // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false 2117 NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW); 2118 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false); 2119 assertFalse(mHelper.areChannelsBypassingDnd()); 2120 verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); 2121 resetZenModeHelper(); 2122 2123 // Recreate a channel & now the app has dnd access granted and can set the bypass dnd field 2124 NotificationChannel update = new NotificationChannel("id1", "name1", IMPORTANCE_LOW); 2125 update.setBypassDnd(true); 2126 mHelper.createNotificationChannel(PKG_N_MR1, uid, update, true, true); 2127 2128 assertTrue(mHelper.areChannelsBypassingDnd()); 2129 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2130 resetZenModeHelper(); 2131 } 2132 2133 @Test testCreateAndDeleteCanChannelsBypassDnd_permissionHelper()2134 public void testCreateAndDeleteCanChannelsBypassDnd_permissionHelper() { 2135 int uid = UserManager.isHeadlessSystemUserMode() ? UID_HEADLESS : UID_N_MR1; 2136 when(mPermissionHelper.hasPermission(uid)).thenReturn(true); 2137 2138 // create notification channel that can't bypass dnd 2139 // expected result: areChannelsBypassingDnd = false 2140 // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false 2141 NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW); 2142 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false); 2143 assertFalse(mHelper.areChannelsBypassingDnd()); 2144 verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); 2145 resetZenModeHelper(); 2146 2147 // create notification channel that can bypass dnd, using local app level settings 2148 // expected result: areChannelsBypassingDnd = true 2149 NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2150 channel2.setBypassDnd(true); 2151 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true); 2152 assertTrue(mHelper.areChannelsBypassingDnd()); 2153 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2154 resetZenModeHelper(); 2155 2156 // delete channels 2157 mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel.getId()); 2158 assertTrue(mHelper.areChannelsBypassingDnd()); // channel2 can still bypass DND 2159 verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); 2160 resetZenModeHelper(); 2161 2162 mHelper.deleteNotificationChannel(PKG_N_MR1, uid, channel2.getId()); 2163 assertFalse(mHelper.areChannelsBypassingDnd()); 2164 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2165 resetZenModeHelper(); 2166 } 2167 2168 @Test testBlockedGroupDoesNotBypassDnd()2169 public void testBlockedGroupDoesNotBypassDnd() { 2170 int uid = UserManager.isHeadlessSystemUserMode() ? UID_HEADLESS : UID_N_MR1; 2171 when(mPermissionHelper.hasPermission(uid)).thenReturn(true); 2172 2173 // start in a 'allowed to bypass dnd state' 2174 mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 2175 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0); 2176 when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); 2177 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 2178 mPermissionHelper, mLogger, 2179 mAppOpsManager, mStatsEventBuilderFactory, false); 2180 2181 2182 // create notification channel that can bypass dnd, but app is blocked 2183 // expected result: areChannelsBypassingDnd = false 2184 NotificationChannelGroup group = new NotificationChannelGroup("group", "group"); 2185 group.setBlocked(true); 2186 mHelper.createNotificationChannelGroup(PKG_N_MR1, uid, group, false); 2187 NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2188 channel2.setGroup("group"); 2189 channel2.setBypassDnd(true); 2190 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true); 2191 assertFalse(mHelper.areChannelsBypassingDnd()); 2192 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2193 resetZenModeHelper(); 2194 } 2195 2196 @Test testBlockedAppsDoNotBypassDnd_localSettings()2197 public void testBlockedAppsDoNotBypassDnd_localSettings() { 2198 int uid = UserManager.isHeadlessSystemUserMode() ? UID_HEADLESS : UID_N_MR1; 2199 when(mPermissionHelper.hasPermission(uid)).thenReturn(false); 2200 2201 // start in a 'allowed to bypass dnd state' 2202 mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 2203 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0); 2204 when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); 2205 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 2206 mPermissionHelper, mLogger, 2207 mAppOpsManager, mStatsEventBuilderFactory, false); 2208 2209 // create notification channel that can bypass dnd, but app is blocked 2210 // expected result: areChannelsBypassingDnd = false 2211 NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2212 channel2.setBypassDnd(true); 2213 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true); 2214 assertFalse(mHelper.areChannelsBypassingDnd()); 2215 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2216 resetZenModeHelper(); 2217 } 2218 2219 @Test testBlockedAppsDoNotBypassDnd_permissionHelper()2220 public void testBlockedAppsDoNotBypassDnd_permissionHelper() { 2221 int uid = UserManager.isHeadlessSystemUserMode() ? UID_HEADLESS : UID_N_MR1; 2222 when(mPermissionHelper.hasPermission(uid)).thenReturn(false); 2223 2224 // start in a 'allowed to bypass dnd state' 2225 mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 2226 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0); 2227 when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); 2228 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 2229 mPermissionHelper, mLogger, 2230 mAppOpsManager, mStatsEventBuilderFactory, false); 2231 2232 // create notification channel that can bypass dnd, but app is blocked 2233 // expected result: areChannelsBypassingDnd = false 2234 NotificationChannel channel2 = new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2235 channel2.setBypassDnd(true); 2236 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel2, true, true); 2237 assertFalse(mHelper.areChannelsBypassingDnd()); 2238 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2239 resetZenModeHelper(); 2240 } 2241 2242 @Test testUpdateCanChannelsBypassDnd()2243 public void testUpdateCanChannelsBypassDnd() { 2244 int uid = UserManager.isHeadlessSystemUserMode() ? UID_HEADLESS : UID_N_MR1; 2245 when(mPermissionHelper.hasPermission(uid)).thenReturn(true); 2246 2247 // create notification channel that can't bypass dnd 2248 // expected result: areChannelsBypassingDnd = false 2249 // setNotificationPolicy isn't called since areChannelsBypassingDnd was already false 2250 NotificationChannel channel = new NotificationChannel("id1", "name1", IMPORTANCE_LOW); 2251 mHelper.createNotificationChannel(PKG_N_MR1, uid, channel, true, false); 2252 assertFalse(mHelper.areChannelsBypassingDnd()); 2253 verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); 2254 resetZenModeHelper(); 2255 2256 // update channel so it CAN bypass dnd: 2257 // expected result: areChannelsBypassingDnd = true 2258 channel.setBypassDnd(true); 2259 mHelper.updateNotificationChannel(PKG_N_MR1, uid, channel, true); 2260 assertTrue(mHelper.areChannelsBypassingDnd()); 2261 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2262 resetZenModeHelper(); 2263 2264 // update channel so it can't bypass dnd: 2265 // expected result: areChannelsBypassingDnd = false 2266 channel.setBypassDnd(false); 2267 mHelper.updateNotificationChannel(PKG_N_MR1, uid, channel, true); 2268 assertFalse(mHelper.areChannelsBypassingDnd()); 2269 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2270 resetZenModeHelper(); 2271 } 2272 2273 @Test testSetupNewZenModeHelper_canBypass()2274 public void testSetupNewZenModeHelper_canBypass() { 2275 // start notification policy off with mAreChannelsBypassingDnd = true, but 2276 // RankingHelper should change to false 2277 mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 2278 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0); 2279 when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); 2280 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 2281 mPermissionHelper, mLogger, 2282 mAppOpsManager, mStatsEventBuilderFactory, false); 2283 assertFalse(mHelper.areChannelsBypassingDnd()); 2284 verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any()); 2285 resetZenModeHelper(); 2286 } 2287 2288 @Test testSetupNewZenModeHelper_cannotBypass()2289 public void testSetupNewZenModeHelper_cannotBypass() { 2290 // start notification policy off with mAreChannelsBypassingDnd = false 2291 mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0, 0, 0); 2292 when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy); 2293 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 2294 mPermissionHelper, mLogger, 2295 mAppOpsManager, mStatsEventBuilderFactory, false); 2296 assertFalse(mHelper.areChannelsBypassingDnd()); 2297 verify(mMockZenModeHelper, never()).setNotificationPolicy(any()); 2298 resetZenModeHelper(); 2299 } 2300 2301 @Test testCreateDeletedChannel()2302 public void testCreateDeletedChannel() throws Exception { 2303 long[] vibration = new long[]{100, 67, 145, 156}; 2304 NotificationChannel channel = 2305 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2306 channel.setVibrationPattern(vibration); 2307 2308 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 2309 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId()); 2310 2311 NotificationChannel newChannel = new NotificationChannel( 2312 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 2313 newChannel.setVibrationPattern(new long[]{100}); 2314 2315 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel, true, false); 2316 2317 // No long deleted, using old settings 2318 compareChannels(channel, 2319 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel.getId(), false)); 2320 } 2321 2322 @Test testOnlyHasDefaultChannel()2323 public void testOnlyHasDefaultChannel() throws Exception { 2324 assertTrue(mHelper.onlyHasDefaultChannel(PKG_N_MR1, UID_N_MR1)); 2325 assertFalse(mHelper.onlyHasDefaultChannel(PKG_O, UID_O)); 2326 2327 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, getChannel(), true, false); 2328 assertFalse(mHelper.onlyHasDefaultChannel(PKG_N_MR1, UID_N_MR1)); 2329 } 2330 2331 @Test testCreateChannel_defaultChannelId()2332 public void testCreateChannel_defaultChannelId() throws Exception { 2333 try { 2334 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, new NotificationChannel( 2335 NotificationChannel.DEFAULT_CHANNEL_ID, "ha", IMPORTANCE_HIGH), true, false); 2336 fail("Allowed to create default channel"); 2337 } catch (IllegalArgumentException e) { 2338 // pass 2339 } 2340 } 2341 2342 @Test testCreateChannel_alreadyExists()2343 public void testCreateChannel_alreadyExists() throws Exception { 2344 long[] vibration = new long[]{100, 67, 145, 156}; 2345 NotificationChannel channel = 2346 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2347 channel.setVibrationPattern(vibration); 2348 2349 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false)); 2350 2351 NotificationChannel newChannel = new NotificationChannel( 2352 channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH); 2353 newChannel.setVibrationPattern(new long[]{100}); 2354 newChannel.setAllowBubbles(!channel.canBubble()); 2355 newChannel.setLightColor(Color.BLUE); 2356 newChannel.setSound(Uri.EMPTY, null); 2357 newChannel.setShowBadge(!channel.canShowBadge()); 2358 2359 assertFalse(mHelper.createNotificationChannel( 2360 PKG_N_MR1, UID_N_MR1, newChannel, true, false)); 2361 2362 // Old settings not overridden 2363 compareChannels(channel, 2364 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel.getId(), false)); 2365 2366 assertEquals(1, mLogger.getCalls().size()); 2367 assertEquals( 2368 NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED, 2369 mLogger.get(0).event); 2370 } 2371 2372 @Test testCreateChannel_noOverrideSound()2373 public void testCreateChannel_noOverrideSound() throws Exception { 2374 Uri sound = new Uri.Builder().scheme("test").build(); 2375 final NotificationChannel channel = new NotificationChannel("id2", "name2", 2376 NotificationManager.IMPORTANCE_DEFAULT); 2377 channel.setSound(sound, mAudioAttributes); 2378 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false); 2379 assertEquals(sound, mHelper.getNotificationChannel( 2380 PKG_N_MR1, UID_N_MR1, channel.getId(), false).getSound()); 2381 } 2382 2383 @Test testPermanentlyDeleteChannels()2384 public void testPermanentlyDeleteChannels() throws Exception { 2385 NotificationChannel channel1 = 2386 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 2387 NotificationChannel channel2 = 2388 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2389 2390 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 2391 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false); 2392 2393 mHelper.permanentlyDeleteNotificationChannels(PKG_N_MR1, UID_N_MR1); 2394 2395 // Only default channel remains 2396 assertEquals(1, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList().size()); 2397 } 2398 2399 @Test testDeleteGroup()2400 public void testDeleteGroup() throws Exception { 2401 NotificationChannelGroup notDeleted = new NotificationChannelGroup("not", "deleted"); 2402 NotificationChannelGroup deleted = new NotificationChannelGroup("totally", "deleted"); 2403 NotificationChannel nonGroupedNonDeletedChannel = 2404 new NotificationChannel("no group", "so not deleted", IMPORTANCE_HIGH); 2405 NotificationChannel groupedButNotDeleted = 2406 new NotificationChannel("not deleted", "belongs to notDeleted", IMPORTANCE_DEFAULT); 2407 groupedButNotDeleted.setGroup("not"); 2408 NotificationChannel groupedAndDeleted = 2409 new NotificationChannel("deleted", "belongs to deleted", IMPORTANCE_DEFAULT); 2410 groupedAndDeleted.setGroup("totally"); 2411 2412 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, notDeleted, true); 2413 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, deleted, true); 2414 mHelper.createNotificationChannel( 2415 PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel, true, false); 2416 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedAndDeleted, true, false); 2417 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, groupedButNotDeleted, true, false); 2418 2419 mHelper.deleteNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, deleted.getId()); 2420 2421 assertNull(mHelper.getNotificationChannelGroup(deleted.getId(), PKG_N_MR1, UID_N_MR1)); 2422 assertNotNull( 2423 mHelper.getNotificationChannelGroup(notDeleted.getId(), PKG_N_MR1, UID_N_MR1)); 2424 2425 assertNull(mHelper.getNotificationChannel( 2426 PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), false)); 2427 compareChannels(groupedAndDeleted, mHelper.getNotificationChannel( 2428 PKG_N_MR1, UID_N_MR1, groupedAndDeleted.getId(), true)); 2429 2430 compareChannels(groupedButNotDeleted, mHelper.getNotificationChannel( 2431 PKG_N_MR1, UID_N_MR1, groupedButNotDeleted.getId(), false)); 2432 compareChannels(nonGroupedNonDeletedChannel, mHelper.getNotificationChannel( 2433 PKG_N_MR1, UID_N_MR1, nonGroupedNonDeletedChannel.getId(), false)); 2434 2435 // notDeleted 2436 assertEquals(1, mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).size()); 2437 2438 verify(mHandler, never()).requestSort(); 2439 2440 assertEquals(7, mLogger.getCalls().size()); 2441 assertEquals( 2442 NotificationChannelLogger.NotificationChannelEvent 2443 .NOTIFICATION_CHANNEL_GROUP_DELETED, 2444 mLogger.get(5).event); // Next-to-last log is the deletion of the channel group. 2445 assertEquals( 2446 NotificationChannelLogger.NotificationChannelEvent 2447 .NOTIFICATION_CHANNEL_DELETED, 2448 mLogger.get(6).event); // Final log is the deletion of the channel. 2449 } 2450 2451 @Test testOnUserRemoved()2452 public void testOnUserRemoved() throws Exception { 2453 int[] user0Uids = {98, 235, 16, 3782}; 2454 int[] user1Uids = new int[user0Uids.length]; 2455 for (int i = 0; i < user0Uids.length; i++) { 2456 user1Uids[i] = UserHandle.PER_USER_RANGE + user0Uids[i]; 2457 2458 final ApplicationInfo legacy = new ApplicationInfo(); 2459 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 2460 when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy); 2461 2462 // create records with the default channel for all user 0 and user 1 uids 2463 mHelper.canShowBadge(PKG_N_MR1, user0Uids[i]); 2464 mHelper.canShowBadge(PKG_N_MR1, user1Uids[i]); 2465 } 2466 2467 mHelper.onUserRemoved(1); 2468 2469 // user 0 records remain 2470 for (int i = 0; i < user0Uids.length; i++) { 2471 assertEquals(1, 2472 mHelper.getNotificationChannels(PKG_N_MR1, user0Uids[i], false).getList().size()); 2473 } 2474 // user 1 records are gone 2475 for (int i = 0; i < user1Uids.length; i++) { 2476 assertEquals(0, 2477 mHelper.getNotificationChannels(PKG_N_MR1, user1Uids[i], false).getList().size()); 2478 } 2479 } 2480 2481 @Test testOnPackageChanged_packageRemoval()2482 public void testOnPackageChanged_packageRemoval() throws Exception { 2483 // Deleted 2484 NotificationChannel channel1 = 2485 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 2486 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 2487 2488 assertTrue(mHelper.onPackagesChanged(true, USER_SYSTEM, new String[]{PKG_N_MR1}, 2489 new int[]{UID_N_MR1})); 2490 2491 assertEquals(0, mHelper.getNotificationChannels( 2492 PKG_N_MR1, UID_N_MR1, true).getList().size()); 2493 2494 // Not deleted 2495 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 2496 2497 assertFalse(mHelper.onPackagesChanged(false, USER_SYSTEM, 2498 new String[]{PKG_N_MR1}, new int[]{UID_N_MR1})); 2499 assertEquals(2, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size()); 2500 } 2501 2502 @Test testOnPackageChanged_packageRemoval_groups()2503 public void testOnPackageChanged_packageRemoval_groups() throws Exception { 2504 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 2505 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 2506 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 2507 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); 2508 2509 mHelper.onPackagesChanged(true, USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{ 2510 UID_N_MR1}); 2511 2512 assertEquals(0, mHelper.getNotificationChannelGroups( 2513 PKG_N_MR1, UID_N_MR1, true, true, false).getList().size()); 2514 } 2515 2516 @Test testOnPackageChange_downgradeTargetSdk()2517 public void testOnPackageChange_downgradeTargetSdk() throws Exception { 2518 // create channel as api 26 2519 mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); 2520 2521 // install new app version targeting 25 2522 final ApplicationInfo legacy = new ApplicationInfo(); 2523 legacy.targetSdkVersion = Build.VERSION_CODES.N_MR1; 2524 when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(legacy); 2525 mHelper.onPackagesChanged( 2526 false, USER_SYSTEM, new String[]{PKG_O}, new int[]{UID_O}); 2527 2528 // make sure the default channel was readded 2529 //assertEquals(2, mHelper.getNotificationChannels(PKG_O, UID_O, false).getList().size()); 2530 assertNotNull(mHelper.getNotificationChannel( 2531 PKG_O, UID_O, NotificationChannel.DEFAULT_CHANNEL_ID, false)); 2532 } 2533 2534 @Test testClearData()2535 public void testClearData() { 2536 ArraySet<String> pkg = new ArraySet<>(); 2537 pkg.add(PKG_O); 2538 ArraySet<Pair<String, Integer>> pkgPair = new ArraySet<>(); 2539 pkgPair.add(new Pair(PKG_O, UID_O)); 2540 mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); 2541 mHelper.createNotificationChannelGroup( 2542 PKG_O, UID_O, new NotificationChannelGroup("1", "bye"), true); 2543 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, pkgPair); 2544 mHelper.setNotificationDelegate(PKG_O, UID_O, "", 1); 2545 mHelper.setBubblesAllowed(PKG_O, UID_O, DEFAULT_BUBBLE_PREFERENCE); 2546 mHelper.setShowBadge(PKG_O, UID_O, false); 2547 mHelper.setAppImportanceLocked(PKG_O, UID_O); 2548 2549 mHelper.clearData(PKG_O, UID_O); 2550 2551 assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), DEFAULT_BUBBLE_PREFERENCE); 2552 assertTrue(mHelper.canShowBadge(PKG_O, UID_O)); 2553 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 2554 assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O)); 2555 assertEquals(0, mHelper.getNotificationChannels(PKG_O, UID_O, true).getList().size()); 2556 assertEquals(0, mHelper.getNotificationChannelGroups(PKG_O, UID_O).size()); 2557 2558 NotificationChannel channel = getChannel(); 2559 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 2560 2561 assertTrue(channel.isImportanceLockedByCriticalDeviceFunction()); 2562 } 2563 2564 @Test testRecordDefaults()2565 public void testRecordDefaults() throws Exception { 2566 assertEquals(true, mHelper.canShowBadge(PKG_N_MR1, UID_N_MR1)); 2567 assertEquals(1, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size()); 2568 } 2569 2570 @Test testCreateGroup()2571 public void testCreateGroup() { 2572 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 2573 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 2574 assertEquals(ncg, 2575 mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1).iterator().next()); 2576 verify(mHandler, never()).requestSort(); 2577 assertEquals(1, mLogger.getCalls().size()); 2578 assertEquals( 2579 NotificationChannelLogger.NotificationChannelEvent 2580 .NOTIFICATION_CHANNEL_GROUP_CREATED, 2581 mLogger.get(0).event); 2582 } 2583 2584 @Test testCannotCreateChannel_badGroup()2585 public void testCannotCreateChannel_badGroup() { 2586 NotificationChannel channel1 = 2587 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 2588 channel1.setGroup("garbage"); 2589 try { 2590 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 2591 fail("Created a channel with a bad group"); 2592 } catch (IllegalArgumentException e) { 2593 } 2594 assertEquals(0, mLogger.getCalls().size()); 2595 } 2596 2597 @Test testCannotCreateChannel_goodGroup()2598 public void testCannotCreateChannel_goodGroup() { 2599 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 2600 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 2601 NotificationChannel channel1 = 2602 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 2603 channel1.setGroup(ncg.getId()); 2604 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 2605 2606 assertEquals(ncg.getId(), mHelper.getNotificationChannel( 2607 PKG_N_MR1, UID_N_MR1, channel1.getId(), false).getGroup()); 2608 } 2609 2610 @Test testGetChannelGroups()2611 public void testGetChannelGroups() { 2612 NotificationChannelGroup unused = new NotificationChannelGroup("unused", "s"); 2613 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, unused, true); 2614 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 2615 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 2616 NotificationChannelGroup ncg2 = new NotificationChannelGroup("group2", "name2"); 2617 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true); 2618 2619 NotificationChannel channel1 = 2620 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 2621 channel1.setGroup(ncg.getId()); 2622 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 2623 NotificationChannel channel1a = 2624 new NotificationChannel("id1a", "name1", NotificationManager.IMPORTANCE_HIGH); 2625 channel1a.setGroup(ncg.getId()); 2626 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1a, true, false); 2627 2628 NotificationChannel channel2 = 2629 new NotificationChannel("id2", "name1", NotificationManager.IMPORTANCE_HIGH); 2630 channel2.setGroup(ncg2.getId()); 2631 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true, false); 2632 2633 NotificationChannel channel3 = 2634 new NotificationChannel("id3", "name1", NotificationManager.IMPORTANCE_HIGH); 2635 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, true, false); 2636 2637 List<NotificationChannelGroup> actual = mHelper.getNotificationChannelGroups( 2638 PKG_N_MR1, UID_N_MR1, true, true, false).getList(); 2639 assertEquals(3, actual.size()); 2640 for (NotificationChannelGroup group : actual) { 2641 if (group.getId() == null) { 2642 assertEquals(2, group.getChannels().size()); // misc channel too 2643 assertTrue(channel3.getId().equals(group.getChannels().get(0).getId()) 2644 || channel3.getId().equals(group.getChannels().get(1).getId())); 2645 } else if (group.getId().equals(ncg.getId())) { 2646 assertEquals(2, group.getChannels().size()); 2647 if (group.getChannels().get(0).getId().equals(channel1.getId())) { 2648 assertTrue(group.getChannels().get(1).getId().equals(channel1a.getId())); 2649 } else if (group.getChannels().get(0).getId().equals(channel1a.getId())) { 2650 assertTrue(group.getChannels().get(1).getId().equals(channel1.getId())); 2651 } else { 2652 fail("expected channel not found"); 2653 } 2654 } else if (group.getId().equals(ncg2.getId())) { 2655 assertEquals(1, group.getChannels().size()); 2656 assertEquals(channel2.getId(), group.getChannels().get(0).getId()); 2657 } 2658 } 2659 } 2660 2661 @Test testGetChannelGroups_noSideEffects()2662 public void testGetChannelGroups_noSideEffects() { 2663 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 2664 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 2665 2666 NotificationChannel channel1 = 2667 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 2668 channel1.setGroup(ncg.getId()); 2669 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 2670 mHelper.getNotificationChannelGroups(PKG_N_MR1, UID_N_MR1, true, true, false).getList(); 2671 2672 channel1.setImportance(IMPORTANCE_LOW); 2673 mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true); 2674 2675 List<NotificationChannelGroup> actual = mHelper.getNotificationChannelGroups( 2676 PKG_N_MR1, UID_N_MR1, true, true, false).getList(); 2677 2678 assertEquals(2, actual.size()); 2679 for (NotificationChannelGroup group : actual) { 2680 if (Objects.equals(group.getId(), ncg.getId())) { 2681 assertEquals(1, group.getChannels().size()); 2682 } 2683 } 2684 } 2685 2686 @Test testGetChannelGroups_includeEmptyGroups()2687 public void testGetChannelGroups_includeEmptyGroups() { 2688 NotificationChannelGroup ncg = new NotificationChannelGroup("group1", "name1"); 2689 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true); 2690 NotificationChannelGroup ncgEmpty = new NotificationChannelGroup("group2", "name2"); 2691 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncgEmpty, true); 2692 2693 NotificationChannel channel1 = 2694 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 2695 channel1.setGroup(ncg.getId()); 2696 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false); 2697 2698 List<NotificationChannelGroup> actual = mHelper.getNotificationChannelGroups( 2699 PKG_N_MR1, UID_N_MR1, false, false, true).getList(); 2700 2701 assertEquals(2, actual.size()); 2702 for (NotificationChannelGroup group : actual) { 2703 if (Objects.equals(group.getId(), ncg.getId())) { 2704 assertEquals(1, group.getChannels().size()); 2705 } 2706 if (Objects.equals(group.getId(), ncgEmpty.getId())) { 2707 assertEquals(0, group.getChannels().size()); 2708 } 2709 } 2710 } 2711 2712 @Test testCreateChannel_updateName()2713 public void testCreateChannel_updateName() { 2714 NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); 2715 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false)); 2716 NotificationChannel actual = 2717 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); 2718 assertEquals("hello", actual.getName()); 2719 2720 nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH); 2721 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false)); 2722 2723 actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); 2724 assertEquals("goodbye", actual.getName()); 2725 assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); 2726 2727 verify(mHandler, times(1)).requestSort(); 2728 } 2729 2730 @Test testCreateChannel_addToGroup()2731 public void testCreateChannel_addToGroup() { 2732 NotificationChannelGroup group = new NotificationChannelGroup("group", ""); 2733 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); 2734 NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT); 2735 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false)); 2736 NotificationChannel actual = 2737 mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); 2738 assertNull(actual.getGroup()); 2739 2740 nc = new NotificationChannel("id", "hello", IMPORTANCE_HIGH); 2741 nc.setGroup(group.getId()); 2742 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false)); 2743 2744 actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false); 2745 assertNotNull(actual.getGroup()); 2746 assertEquals(IMPORTANCE_DEFAULT, actual.getImportance()); 2747 2748 verify(mHandler, times(1)).requestSort(); 2749 assertEquals(3, mLogger.getCalls().size()); 2750 assertEquals( 2751 NotificationChannelLogger.NotificationChannelEvent 2752 .NOTIFICATION_CHANNEL_GROUP_CREATED, 2753 mLogger.get(0).event); 2754 assertEquals( 2755 NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED, 2756 mLogger.get(1).event); 2757 assertEquals( 2758 NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_UPDATED, 2759 mLogger.get(2).event); 2760 } 2761 2762 @Test testDumpChannelsJson()2763 public void testDumpChannelsJson() throws Exception { 2764 final ApplicationInfo upgrade = new ApplicationInfo(); 2765 upgrade.targetSdkVersion = Build.VERSION_CODES.O; 2766 try { 2767 when(mPm.getApplicationInfoAsUser( 2768 anyString(), anyInt(), anyInt())).thenReturn(upgrade); 2769 } catch (PackageManager.NameNotFoundException e) { 2770 } 2771 ArrayMap<String, Integer> expectedChannels = new ArrayMap<>(); 2772 int numPackages = ThreadLocalRandom.current().nextInt(1, 5); 2773 for (int i = 0; i < numPackages; i++) { 2774 String pkgName = "pkg" + i; 2775 int numChannels = ThreadLocalRandom.current().nextInt(1, 10); 2776 for (int j = 0; j < numChannels; j++) { 2777 mHelper.createNotificationChannel(pkgName, UID_N_MR1, 2778 new NotificationChannel("" + j, "a", IMPORTANCE_HIGH), true, false); 2779 } 2780 expectedChannels.put(pkgName, numChannels); 2781 } 2782 2783 // delete the first channel of the first package 2784 String pkg = expectedChannels.keyAt(0); 2785 mHelper.deleteNotificationChannel("pkg" + 0, UID_N_MR1, "0"); 2786 // dump should not include deleted channels 2787 int count = expectedChannels.get(pkg); 2788 expectedChannels.put(pkg, count - 1); 2789 2790 JSONArray actual = mHelper.dumpChannelsJson(new NotificationManagerService.DumpFilter()); 2791 assertEquals(numPackages, actual.length()); 2792 for (int i = 0; i < numPackages; i++) { 2793 JSONObject object = actual.getJSONObject(i); 2794 assertTrue(expectedChannels.containsKey(object.get("packageName"))); 2795 assertEquals(expectedChannels.get(object.get("packageName")).intValue(), 2796 object.getInt("channelCount")); 2797 } 2798 } 2799 2800 @Test testDumpJson_postPermissionMigration()2801 public void testDumpJson_postPermissionMigration() throws Exception { 2802 // when getting a json dump, we want to verify that: 2803 // - all notification importance info should come from the permission, even if the data 2804 // isn't there yet but is present in package preferences 2805 // - if there are permissions granted or denied from packages PreferencesHelper doesn't 2806 // know about, those should still be included 2807 2808 // package permissions map to be passed in 2809 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 2810 appPermissions.put(new Pair(1, "first"), new Pair(true, false)); // not in local prefs 2811 appPermissions.put(new Pair(3, "third"), new Pair(false, false)); // not in local prefs 2812 appPermissions.put(new Pair(UID_P, PKG_P), new Pair(true, false)); // in local prefs 2813 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); // in local prefs 2814 2815 NotificationChannel channel1 = 2816 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 2817 NotificationChannel channel2 = 2818 new NotificationChannel("id2", "name2", IMPORTANCE_LOW); 2819 NotificationChannel channel3 = new NotificationChannel("id3", "name3", IMPORTANCE_HIGH); 2820 2821 mHelper.createNotificationChannel(PKG_P, UID_P, channel1, true, false); 2822 mHelper.createNotificationChannel(PKG_P, UID_P, channel2, false, false); 2823 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel3, false, false); 2824 mHelper.createNotificationChannel(PKG_O, UID_O, getChannel(), true, false); 2825 2826 // in the json array, all of the individual package preferences are simply elements in the 2827 // values array. this set is to collect expected outputs for each of our packages. 2828 // the key/value pairs are: (userId, package name) -> expected importance 2829 ArrayMap<Pair<Integer, String>, String> expected = new ArrayMap<>(); 2830 2831 // packages that only exist via the app permissions; should be present 2832 expected.put(new Pair(UserHandle.getUserId(1), "first"), "DEFAULT"); 2833 expected.put(new Pair(UserHandle.getUserId(3), "third"), "NONE"); 2834 2835 // packages that exist in both app permissions & local preferences 2836 expected.put(new Pair(UserHandle.getUserId(UID_P), PKG_P), "DEFAULT"); 2837 expected.put(new Pair(UserHandle.getUserId(UID_O), PKG_O), "NONE"); 2838 2839 // package that only exists in local preferences; expect no importance output 2840 expected.put(new Pair(UserHandle.getUserId(UID_N_MR1), PKG_N_MR1), null); 2841 2842 JSONArray actual = (JSONArray) mHelper.dumpJson( 2843 new NotificationManagerService.DumpFilter(), appPermissions) 2844 .get("PackagePreferencess"); 2845 assertThat(actual.length()).isEqualTo(expected.size()); 2846 for (int i = 0; i < actual.length(); i++) { 2847 JSONObject pkgInfo = actual.getJSONObject(i); 2848 Pair<Integer, String> pkgKey = 2849 new Pair(pkgInfo.getInt("userId"), pkgInfo.getString("packageName")); 2850 assertTrue(expected.containsKey(pkgKey)); 2851 if (pkgInfo.has("importance")) { 2852 assertThat(pkgInfo.getString("importance")).isEqualTo(expected.get(pkgKey)); 2853 } else { 2854 assertThat(expected.get(pkgKey)).isNull(); 2855 } 2856 } 2857 } 2858 2859 @Test testDumpJson_givenNullInput_postMigration()2860 public void testDumpJson_givenNullInput_postMigration() throws Exception { 2861 // simple test just to make sure nothing dies if we pass in null input even post migration 2862 // for some reason, even though in practice this should not be how one calls this method 2863 2864 // some packages exist 2865 mHelper.canShowBadge(PKG_O, UID_O); 2866 mHelper.canShowBadge(PKG_P, UID_P); 2867 2868 JSONArray actual = (JSONArray) mHelper.dumpJson( 2869 new NotificationManagerService.DumpFilter(), null) 2870 .get("PackagePreferencess"); 2871 2872 // there should still be info for the packages 2873 assertThat(actual.length()).isEqualTo(2); 2874 2875 // but they should not have importance info because the migration is enabled and it got 2876 // no info 2877 for (int i = 0; i < actual.length(); i++) { 2878 assertFalse(actual.getJSONObject(i).has("importance")); 2879 } 2880 } 2881 2882 @Test testDumpBansJson_postPermissionMigration()2883 public void testDumpBansJson_postPermissionMigration() throws Exception { 2884 // confirm that the package bans that are in the output include all packages that 2885 // have their permission set to false, and not based on PackagePreferences importance 2886 2887 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 2888 appPermissions.put(new Pair(1, "first"), new Pair(true, false)); // not in local prefs 2889 appPermissions.put(new Pair(3, "third"), new Pair(false, false)); // not in local prefs 2890 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); // in local prefs 2891 2892 mHelper.canShowBadge(PKG_O, UID_O); 2893 2894 // expected output 2895 ArraySet<Pair<Integer, String>> expected = new ArraySet<>(); 2896 expected.add(new Pair(UserHandle.getUserId(3), "third")); 2897 expected.add(new Pair(UserHandle.getUserId(UID_O), PKG_O)); 2898 2899 // make sure that's the only thing in the package ban output 2900 JSONArray actual = mHelper.dumpBansJson( 2901 new NotificationManagerService.DumpFilter(), appPermissions); 2902 assertThat(actual.length()).isEqualTo(expected.size()); 2903 2904 for (int i = 0; i < actual.length(); i++) { 2905 JSONObject ban = actual.getJSONObject(i); 2906 assertTrue(expected.contains( 2907 new Pair(ban.getInt("userId"), ban.getString("packageName")))); 2908 } 2909 } 2910 2911 @Test testDumpBansJson_givenNullInput()2912 public void testDumpBansJson_givenNullInput() throws Exception { 2913 // no one should do this, but... 2914 2915 JSONArray actual = mHelper.dumpBansJson( 2916 new NotificationManagerService.DumpFilter(), null); 2917 assertThat(actual.length()).isEqualTo(0); 2918 } 2919 2920 @Test testDumpString_postPermissionMigration()2921 public void testDumpString_postPermissionMigration() { 2922 // confirm that the string resulting from dumpImpl contains only importances from permission 2923 2924 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 2925 appPermissions.put(new Pair(1, "first"), new Pair(true, false)); // not in local prefs 2926 appPermissions.put(new Pair(3, "third"), new Pair(false, true)); // not in local prefs 2927 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); // in local prefs 2928 2929 // local package preferences 2930 mHelper.canShowBadge(PKG_O, UID_O); 2931 mHelper.canShowBadge(PKG_P, UID_P); 2932 2933 // get dump output as a string so we can inspect the contents later 2934 StringWriter sw = new StringWriter(); 2935 PrintWriter pw = new PrintWriter(sw); 2936 mHelper.dump(pw, "", new NotificationManagerService.DumpFilter(), appPermissions); 2937 pw.flush(); 2938 String actual = sw.toString(); 2939 2940 // expected (substring) output for each preference via permissions 2941 ArrayList<String> expected = new ArrayList<>(); 2942 expected.add("first (1) importance=DEFAULT userSet=false"); 2943 expected.add("third (3) importance=NONE userSet=true"); 2944 expected.add(PKG_O + " (" + UID_O + ") importance=NONE userSet=false"); 2945 expected.add(PKG_P + " (" + UID_P + ")"); 2946 2947 // make sure we don't have package preference info 2948 ArrayList<String> notExpected = new ArrayList<>(); 2949 notExpected.add(PKG_O + " (" + UID_O + ") importance=HIGH"); 2950 notExpected.add(PKG_P + " (" + UID_P + ") importance="); // no importance for PKG_P 2951 2952 for (String exp : expected) { 2953 assertTrue(actual.contains(exp)); 2954 } 2955 2956 for (String notExp : notExpected) { 2957 assertFalse(actual.contains(notExp)); 2958 } 2959 } 2960 2961 @Test testDumpString_givenNullInput()2962 public void testDumpString_givenNullInput() { 2963 // test that this doesn't choke on null input 2964 2965 // local package preferences 2966 mHelper.canShowBadge(PKG_O, UID_O); 2967 mHelper.canShowBadge(PKG_P, UID_P); 2968 2969 // get dump output 2970 StringWriter sw = new StringWriter(); 2971 PrintWriter pw = new PrintWriter(sw); 2972 mHelper.dump(pw, "", new NotificationManagerService.DumpFilter(), null); 2973 pw.flush(); 2974 String actual = sw.toString(); 2975 2976 // nobody gets any importance 2977 assertFalse(actual.contains("importance=")); 2978 } 2979 2980 @Test testDumpProto_postPermissionMigration()2981 public void testDumpProto_postPermissionMigration() throws Exception { 2982 // test that dumping to proto gets the importances from the right place 2983 2984 // permissions -- these should take precedence 2985 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 2986 appPermissions.put(new Pair(1, "first"), new Pair(true, false)); // not in local prefs 2987 appPermissions.put(new Pair(3, "third"), new Pair(false, false)); // not in local prefs 2988 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, false)); // in local prefs 2989 2990 // local package preferences 2991 mHelper.canShowBadge(PKG_O, UID_O); 2992 mHelper.canShowBadge(PKG_P, UID_P); 2993 2994 // expected output: all the packages, but only the ones provided via appPermissions 2995 // should have importance set (aka not PKG_P) 2996 // map format: (uid, package name) -> importance (int) 2997 ArrayMap<Pair<Integer, String>, Integer> expected = new ArrayMap<>(); 2998 expected.put(new Pair(1, "first"), IMPORTANCE_DEFAULT); 2999 expected.put(new Pair(3, "third"), IMPORTANCE_NONE); 3000 expected.put(new Pair(UID_O, PKG_O), IMPORTANCE_NONE); 3001 3002 // unfortunately, due to how nano protos work, there's no distinction between unset 3003 // fields and default-value fields, so we have no choice here but to check for a value of 0. 3004 // at least we can make sure the local importance for PKG_P in this test is not 0 (NONE). 3005 expected.put(new Pair(UID_P, PKG_P), 0); 3006 3007 // get the proto output and inspect its contents 3008 ProtoOutputStream proto = new ProtoOutputStream(); 3009 mHelper.dump(proto, new NotificationManagerService.DumpFilter(), appPermissions); 3010 3011 RankingHelperProto actual = RankingHelperProto.parseFrom(proto.getBytes()); 3012 assertThat(actual.records.length).isEqualTo(expected.size()); 3013 for (int i = 0; i < actual.records.length; i++) { 3014 RankingHelperProto.RecordProto record = actual.records[i]; 3015 Pair<Integer, String> pkgKey = new Pair(record.uid, record.package_); 3016 assertTrue(expected.containsKey(pkgKey)); 3017 assertThat(record.importance).isEqualTo(expected.get(pkgKey)); 3018 } 3019 } 3020 3021 @Test testBadgingOverrideTrue()3022 public void testBadgingOverrideTrue() throws Exception { 3023 Secure.putIntForUser(getContext().getContentResolver(), 3024 Secure.NOTIFICATION_BADGING, 1, 3025 USER.getIdentifier()); 3026 mHelper.updateBadgingEnabled(); // would be called by settings observer 3027 assertTrue(mHelper.badgingEnabled(USER)); 3028 } 3029 3030 @Test testBadgingOverrideFalse()3031 public void testBadgingOverrideFalse() throws Exception { 3032 Secure.putIntForUser(getContext().getContentResolver(), 3033 Secure.NOTIFICATION_BADGING, 0, 3034 USER.getIdentifier()); 3035 mHelper.updateBadgingEnabled(); // would be called by settings observer 3036 assertFalse(mHelper.badgingEnabled(USER)); 3037 } 3038 3039 @Test testBadgingForUserAll()3040 public void testBadgingForUserAll() throws Exception { 3041 try { 3042 mHelper.badgingEnabled(UserHandle.ALL); 3043 } catch (Exception e) { 3044 fail("just don't throw"); 3045 } 3046 } 3047 3048 @Test testBadgingOverrideUserIsolation()3049 public void testBadgingOverrideUserIsolation() throws Exception { 3050 Secure.putIntForUser(getContext().getContentResolver(), 3051 Secure.NOTIFICATION_BADGING, 0, 3052 USER.getIdentifier()); 3053 Secure.putIntForUser(getContext().getContentResolver(), 3054 Secure.NOTIFICATION_BADGING, 1, 3055 USER2.getIdentifier()); 3056 mHelper.updateBadgingEnabled(); // would be called by settings observer 3057 assertFalse(mHelper.badgingEnabled(USER)); 3058 assertTrue(mHelper.badgingEnabled(USER2)); 3059 } 3060 3061 @Test testBubblesOverrideTrue()3062 public void testBubblesOverrideTrue() { 3063 Secure.putIntForUser(getContext().getContentResolver(), 3064 Secure.NOTIFICATION_BUBBLES, 1, 3065 USER.getIdentifier()); 3066 mHelper.updateBubblesEnabled(); // would be called by settings observer 3067 assertTrue(mHelper.bubblesEnabled(USER)); 3068 } 3069 3070 @Test testBubblesOverrideFalse()3071 public void testBubblesOverrideFalse() { 3072 Secure.putIntForUser(getContext().getContentResolver(), 3073 Secure.NOTIFICATION_BUBBLES, 0, 3074 USER.getIdentifier()); 3075 mHelper.updateBubblesEnabled(); // would be called by settings observer 3076 assertFalse(mHelper.bubblesEnabled(USER)); 3077 } 3078 3079 @Test testBubblesOverrideUserIsolation()3080 public void testBubblesOverrideUserIsolation() throws Exception { 3081 Secure.putIntForUser(getContext().getContentResolver(), 3082 Secure.NOTIFICATION_BUBBLES, 0, 3083 USER.getIdentifier()); 3084 Secure.putIntForUser(getContext().getContentResolver(), 3085 Secure.NOTIFICATION_BUBBLES, 1, 3086 USER2.getIdentifier()); 3087 mHelper.updateBubblesEnabled(); // would be called by settings observer 3088 assertFalse(mHelper.bubblesEnabled(USER)); 3089 assertTrue(mHelper.bubblesEnabled(USER2)); 3090 } 3091 3092 @Test testShowQSMediaOverrideTrue()3093 public void testShowQSMediaOverrideTrue() { 3094 Global.putInt(getContext().getContentResolver(), 3095 Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 1); 3096 mHelper.updateMediaNotificationFilteringEnabled(); // would be called by settings observer 3097 assertTrue(mHelper.isMediaNotificationFilteringEnabled()); 3098 } 3099 3100 @Test testShowQSMediaOverrideFalse()3101 public void testShowQSMediaOverrideFalse() { 3102 Global.putInt(getContext().getContentResolver(), 3103 Global.SHOW_MEDIA_ON_QUICK_SETTINGS, 0); 3104 mHelper.updateMediaNotificationFilteringEnabled(); // would be called by settings observer 3105 assertFalse(mHelper.isMediaNotificationFilteringEnabled()); 3106 } 3107 3108 @Test testOnLocaleChanged_updatesDefaultChannels()3109 public void testOnLocaleChanged_updatesDefaultChannels() throws Exception { 3110 String newLabel = "bananas!"; 3111 final NotificationChannel defaultChannel = mHelper.getNotificationChannel(PKG_N_MR1, 3112 UID_N_MR1, 3113 NotificationChannel.DEFAULT_CHANNEL_ID, false); 3114 assertFalse(newLabel.equals(defaultChannel.getName())); 3115 3116 Resources res = mock(Resources.class); 3117 when(mContext.getResources()).thenReturn(res); 3118 when(res.getString(com.android.internal.R.string.default_notification_channel_label)) 3119 .thenReturn(newLabel); 3120 3121 mHelper.onLocaleChanged(mContext, USER.getIdentifier()); 3122 3123 assertEquals(newLabel, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, 3124 NotificationChannel.DEFAULT_CHANNEL_ID, false).getName()); 3125 } 3126 3127 @Test testIsGroupBlocked_noGroup()3128 public void testIsGroupBlocked_noGroup() throws Exception { 3129 assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, null)); 3130 3131 assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, "non existent group")); 3132 } 3133 3134 @Test testIsGroupBlocked_notBlocked()3135 public void testIsGroupBlocked_notBlocked() throws Exception { 3136 NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); 3137 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); 3138 3139 assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); 3140 } 3141 3142 @Test testIsGroupBlocked_blocked()3143 public void testIsGroupBlocked_blocked() throws Exception { 3144 NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); 3145 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); 3146 group.setBlocked(true); 3147 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, false); 3148 3149 assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); 3150 } 3151 3152 @Test testIsGroupBlocked_appCannotCreateAsBlocked()3153 public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception { 3154 NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); 3155 group.setBlocked(true); 3156 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); 3157 assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); 3158 3159 NotificationChannelGroup group3 = group.clone(); 3160 group3.setBlocked(false); 3161 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true); 3162 assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); 3163 } 3164 3165 @Test testIsGroup_appCannotResetBlock()3166 public void testIsGroup_appCannotResetBlock() throws Exception { 3167 NotificationChannelGroup group = new NotificationChannelGroup("id", "name"); 3168 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); 3169 NotificationChannelGroup group2 = group.clone(); 3170 group2.setBlocked(true); 3171 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group2, false); 3172 assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); 3173 3174 NotificationChannelGroup group3 = group.clone(); 3175 group3.setBlocked(false); 3176 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true); 3177 assertTrue(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId())); 3178 } 3179 3180 @Test testGetNotificationChannelGroupWithChannels()3181 public void testGetNotificationChannelGroupWithChannels() throws Exception { 3182 NotificationChannelGroup group = new NotificationChannelGroup("group", ""); 3183 NotificationChannelGroup other = new NotificationChannelGroup("something else", ""); 3184 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true); 3185 mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, other, true); 3186 3187 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_DEFAULT); 3188 a.setGroup(group.getId()); 3189 NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_DEFAULT); 3190 b.setGroup(other.getId()); 3191 NotificationChannel c = new NotificationChannel("c", "c", IMPORTANCE_DEFAULT); 3192 c.setGroup(group.getId()); 3193 NotificationChannel d = new NotificationChannel("d", "d", IMPORTANCE_DEFAULT); 3194 3195 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, a, true, false); 3196 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, b, true, false); 3197 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, c, true, false); 3198 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, d, true, false); 3199 mHelper.deleteNotificationChannel(PKG_N_MR1, UID_N_MR1, c.getId()); 3200 3201 NotificationChannelGroup retrieved = mHelper.getNotificationChannelGroupWithChannels( 3202 PKG_N_MR1, UID_N_MR1, group.getId(), true); 3203 assertEquals(2, retrieved.getChannels().size()); 3204 compareChannels(a, findChannel(retrieved.getChannels(), a.getId())); 3205 compareChannels(c, findChannel(retrieved.getChannels(), c.getId())); 3206 3207 retrieved = mHelper.getNotificationChannelGroupWithChannels( 3208 PKG_N_MR1, UID_N_MR1, group.getId(), false); 3209 assertEquals(1, retrieved.getChannels().size()); 3210 compareChannels(a, findChannel(retrieved.getChannels(), a.getId())); 3211 } 3212 3213 @Test testAndroidPkgCannotBypassDnd_creation()3214 public void testAndroidPkgCannotBypassDnd_creation() { 3215 NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3216 test.setBypassDnd(true); 3217 3218 mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, test, true, false); 3219 3220 assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false) 3221 .canBypassDnd()); 3222 } 3223 3224 @Test testDndPkgCanBypassDnd_creation()3225 public void testDndPkgCanBypassDnd_creation() { 3226 NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3227 test.setBypassDnd(true); 3228 3229 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, test, true, true); 3230 3231 assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "A", false).canBypassDnd()); 3232 } 3233 3234 @Test testNormalPkgCannotBypassDnd_creation()3235 public void testNormalPkgCannotBypassDnd_creation() { 3236 NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3237 test.setBypassDnd(true); 3238 3239 mHelper.createNotificationChannel(PKG_N_MR1, 1000, test, true, false); 3240 3241 assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, 1000, "A", false).canBypassDnd()); 3242 } 3243 3244 @Test testAndroidPkgCannotBypassDnd_update()3245 public void testAndroidPkgCannotBypassDnd_update() throws Exception { 3246 NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3247 mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, test, true, false); 3248 3249 NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3250 update.setBypassDnd(true); 3251 assertFalse(mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, update, true, false)); 3252 3253 assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false) 3254 .canBypassDnd()); 3255 } 3256 3257 @Test testDndPkgCanBypassDnd_update()3258 public void testDndPkgCanBypassDnd_update() throws Exception { 3259 NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3260 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, test, true, true); 3261 3262 NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3263 update.setBypassDnd(true); 3264 assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true, true)); 3265 3266 assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "A", false).canBypassDnd()); 3267 } 3268 3269 @Test testNormalPkgCannotBypassDnd_update()3270 public void testNormalPkgCannotBypassDnd_update() { 3271 NotificationChannel test = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3272 mHelper.createNotificationChannel(PKG_N_MR1, 1000, test, true, false); 3273 NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW); 3274 update.setBypassDnd(true); 3275 mHelper.createNotificationChannel(PKG_N_MR1, 1000, update, true, false); 3276 assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, 1000, "A", false).canBypassDnd()); 3277 } 3278 3279 @Test testXml_statusBarIcons_default()3280 public void testXml_statusBarIcons_default() throws Exception { 3281 String preQXml = "<ranking version=\"1\">\n" 3282 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n" 3283 + "<channel id=\"something\" name=\"name\" importance=\"2\" " 3284 + "show_badge=\"true\" />\n" 3285 + "<channel id=\"miscellaneous\" name=\"Uncategorized\" usage=\"5\" " 3286 + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n" 3287 + "</package>\n" 3288 + "</ranking>\n"; 3289 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3290 mPermissionHelper, mLogger, 3291 mAppOpsManager, mStatsEventBuilderFactory, false); 3292 loadByteArrayXml(preQXml.getBytes(), true, USER_SYSTEM); 3293 3294 assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS, 3295 mHelper.shouldHideSilentStatusIcons()); 3296 } 3297 3298 @Test testXml_statusBarIcons()3299 public void testXml_statusBarIcons() throws Exception { 3300 mHelper.setHideSilentStatusIcons(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS); 3301 3302 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3303 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3304 mPermissionHelper, mLogger, 3305 mAppOpsManager, mStatsEventBuilderFactory, false); 3306 loadStreamXml(baos, false, UserHandle.USER_ALL); 3307 3308 assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS, 3309 mHelper.shouldHideSilentStatusIcons()); 3310 } 3311 3312 @Test testSetNotificationDelegate()3313 public void testSetNotificationDelegate() { 3314 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3315 assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); 3316 } 3317 3318 @Test testRevokeNotificationDelegate()3319 public void testRevokeNotificationDelegate() { 3320 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3321 mHelper.revokeNotificationDelegate(PKG_O, UID_O); 3322 3323 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3324 } 3325 3326 @Test testRevokeNotificationDelegate_noDelegateExistsNoCrash()3327 public void testRevokeNotificationDelegate_noDelegateExistsNoCrash() { 3328 mHelper.revokeNotificationDelegate(PKG_O, UID_O); 3329 3330 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3331 } 3332 3333 @Test testToggleNotificationDelegate()3334 public void testToggleNotificationDelegate() { 3335 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3336 mHelper.toggleNotificationDelegate(PKG_O, UID_O, false); 3337 3338 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3339 3340 mHelper.toggleNotificationDelegate(PKG_O, UID_O, true); 3341 assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); 3342 } 3343 3344 @Test testToggleNotificationDelegate_noDelegateExistsNoCrash()3345 public void testToggleNotificationDelegate_noDelegateExistsNoCrash() { 3346 mHelper.toggleNotificationDelegate(PKG_O, UID_O, false); 3347 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3348 3349 mHelper.toggleNotificationDelegate(PKG_O, UID_O, true); 3350 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3351 } 3352 3353 @Test testIsDelegateAllowed_noSource()3354 public void testIsDelegateAllowed_noSource() { 3355 assertFalse(mHelper.isDelegateAllowed("does not exist", -1, "whatever", 0)); 3356 } 3357 3358 @Test testIsDelegateAllowed_noDelegate()3359 public void testIsDelegateAllowed_noDelegate() { 3360 mHelper.canShowBadge(PKG_O, UID_O); 3361 3362 assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "whatever", 0)); 3363 } 3364 3365 @Test testIsDelegateAllowed_delegateDisabledByApp()3366 public void testIsDelegateAllowed_delegateDisabledByApp() { 3367 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3368 mHelper.revokeNotificationDelegate(PKG_O, UID_O); 3369 3370 assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "other", 53)); 3371 } 3372 3373 @Test testIsDelegateAllowed_wrongDelegate()3374 public void testIsDelegateAllowed_wrongDelegate() { 3375 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3376 mHelper.revokeNotificationDelegate(PKG_O, UID_O); 3377 3378 assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "banana", 27)); 3379 } 3380 3381 @Test testIsDelegateAllowed_delegateDisabledByUser()3382 public void testIsDelegateAllowed_delegateDisabledByUser() { 3383 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3384 mHelper.toggleNotificationDelegate(PKG_O, UID_O, false); 3385 3386 assertFalse(mHelper.isDelegateAllowed(PKG_O, UID_O, "other", 53)); 3387 } 3388 3389 @Test testIsDelegateAllowed()3390 public void testIsDelegateAllowed() { 3391 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3392 3393 assertTrue(mHelper.isDelegateAllowed(PKG_O, UID_O, "other", 53)); 3394 } 3395 3396 @Test testDelegateXml_noDelegate()3397 public void testDelegateXml_noDelegate() throws Exception { 3398 mHelper.canShowBadge(PKG_O, UID_O); 3399 3400 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3401 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3402 mPermissionHelper, mLogger, 3403 mAppOpsManager, mStatsEventBuilderFactory, false); 3404 loadStreamXml(baos, false, UserHandle.USER_ALL); 3405 3406 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3407 } 3408 3409 @Test testDelegateXml_delegate()3410 public void testDelegateXml_delegate() throws Exception { 3411 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3412 3413 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3414 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3415 mPermissionHelper, mLogger, 3416 mAppOpsManager, mStatsEventBuilderFactory, false); 3417 loadStreamXml(baos, false, UserHandle.USER_ALL); 3418 3419 assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); 3420 } 3421 3422 @Test testDelegateXml_disabledDelegate()3423 public void testDelegateXml_disabledDelegate() throws Exception { 3424 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3425 mHelper.revokeNotificationDelegate(PKG_O, UID_O); 3426 3427 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3428 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3429 mPermissionHelper, mLogger, 3430 mAppOpsManager, mStatsEventBuilderFactory, false); 3431 loadStreamXml(baos, false, UserHandle.USER_ALL); 3432 3433 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3434 } 3435 3436 @Test testDelegateXml_userDisabledDelegate()3437 public void testDelegateXml_userDisabledDelegate() throws Exception { 3438 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3439 mHelper.toggleNotificationDelegate(PKG_O, UID_O, false); 3440 3441 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3442 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3443 mPermissionHelper, mLogger, 3444 mAppOpsManager, mStatsEventBuilderFactory, false); 3445 loadStreamXml(baos, false, UserHandle.USER_ALL); 3446 3447 // appears disabled 3448 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3449 3450 // but was loaded and can be toggled back on 3451 mHelper.toggleNotificationDelegate(PKG_O, UID_O, true); 3452 assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); 3453 } 3454 3455 @Test testDelegateXml_entirelyDisabledDelegate()3456 public void testDelegateXml_entirelyDisabledDelegate() throws Exception { 3457 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3458 mHelper.toggleNotificationDelegate(PKG_O, UID_O, false); 3459 mHelper.revokeNotificationDelegate(PKG_O, UID_O); 3460 3461 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3462 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3463 mPermissionHelper, mLogger, 3464 mAppOpsManager, mStatsEventBuilderFactory, false); 3465 loadStreamXml(baos, false, UserHandle.USER_ALL); 3466 3467 // appears disabled 3468 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3469 3470 mHelper.setNotificationDelegate(PKG_O, UID_O, "other", 53); 3471 assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O)); 3472 3473 mHelper.toggleNotificationDelegate(PKG_O, UID_O, true); 3474 assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O)); 3475 } 3476 3477 @Test testBubblePreference_defaults()3478 public void testBubblePreference_defaults() throws Exception { 3479 assertEquals(BUBBLE_PREFERENCE_NONE, mHelper.getBubblePreference(PKG_O, UID_O)); 3480 3481 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3482 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3483 mPermissionHelper, mLogger, 3484 mAppOpsManager, mStatsEventBuilderFactory, false); 3485 loadStreamXml(baos, false, UserHandle.USER_ALL); 3486 3487 assertEquals(BUBBLE_PREFERENCE_NONE, mHelper.getBubblePreference(PKG_O, UID_O)); 3488 assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O)); 3489 } 3490 3491 @Test testBubblePreference_upgradeWithSAWPermission()3492 public void testBubblePreference_upgradeWithSAWPermission() throws Exception { 3493 when(mAppOpsManager.noteOpNoThrow(eq(OP_SYSTEM_ALERT_WINDOW), anyInt(), 3494 anyString(), eq(null), anyString())).thenReturn(MODE_ALLOWED); 3495 3496 final String xml = "<ranking version=\"1\">\n" 3497 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\">\n" 3498 + "<channel id=\"someId\" name=\"hi\"" 3499 + " importance=\"3\"/>" 3500 + "</package>" 3501 + "</ranking>"; 3502 TypedXmlPullParser parser = Xml.newFastPullParser(); 3503 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 3504 null); 3505 parser.nextTag(); 3506 mHelper.readXml(parser, false, UserHandle.USER_ALL); 3507 3508 assertEquals(BUBBLE_PREFERENCE_ALL, mHelper.getBubblePreference(PKG_O, UID_O)); 3509 assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O)); 3510 } 3511 3512 @Test testBubblePreference_upgradeWithSAWThenUserOverride()3513 public void testBubblePreference_upgradeWithSAWThenUserOverride() throws Exception { 3514 when(mAppOpsManager.noteOpNoThrow(eq(OP_SYSTEM_ALERT_WINDOW), anyInt(), 3515 anyString(), eq(null), anyString())).thenReturn(MODE_ALLOWED); 3516 3517 final String xml = "<ranking version=\"1\">\n" 3518 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\">\n" 3519 + "<channel id=\"someId\" name=\"hi\"" 3520 + " importance=\"3\"/>" 3521 + "</package>" 3522 + "</ranking>"; 3523 TypedXmlPullParser parser = Xml.newFastPullParser(); 3524 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 3525 null); 3526 parser.nextTag(); 3527 mHelper.readXml(parser, false, UserHandle.USER_ALL); 3528 3529 assertEquals(BUBBLE_PREFERENCE_ALL, mHelper.getBubblePreference(PKG_O, UID_O)); 3530 assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O)); 3531 3532 mHelper.setBubblesAllowed(PKG_O, UID_O, BUBBLE_PREFERENCE_SELECTED); 3533 assertEquals(BUBBLE_PREFERENCE_SELECTED, mHelper.getBubblePreference(PKG_O, UID_O)); 3534 assertEquals(PreferencesHelper.LockableAppFields.USER_LOCKED_BUBBLE, 3535 mHelper.getAppLockedFields(PKG_O, UID_O)); 3536 3537 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3538 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3539 mPermissionHelper, mLogger, 3540 mAppOpsManager, mStatsEventBuilderFactory, false); 3541 loadStreamXml(baos, false, UserHandle.USER_ALL); 3542 3543 assertEquals(BUBBLE_PREFERENCE_SELECTED, mHelper.getBubblePreference(PKG_O, UID_O)); 3544 assertEquals(PreferencesHelper.LockableAppFields.USER_LOCKED_BUBBLE, 3545 mHelper.getAppLockedFields(PKG_O, UID_O)); 3546 } 3547 3548 @Test testBubblePrefence_noSAWCheckForUnknownUid()3549 public void testBubblePrefence_noSAWCheckForUnknownUid() throws Exception { 3550 final String xml = "<ranking version=\"1\">\n" 3551 + "<package name=\"" + PKG_O + "\" uid=\"" + UNKNOWN_UID + "\">\n" 3552 + "<channel id=\"someId\" name=\"hi\"" 3553 + " importance=\"3\"/>" 3554 + "</package>" 3555 + "</ranking>"; 3556 TypedXmlPullParser parser = Xml.newFastPullParser(); 3557 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 3558 null); 3559 parser.nextTag(); 3560 mHelper.readXml(parser, false, UserHandle.USER_ALL); 3561 3562 assertEquals(DEFAULT_BUBBLE_PREFERENCE, mHelper.getBubblePreference(PKG_O, UID_O)); 3563 assertEquals(0, mHelper.getAppLockedFields(PKG_O, UID_O)); 3564 verify(mAppOpsManager, never()).noteOpNoThrow(eq(OP_SYSTEM_ALERT_WINDOW), anyInt(), 3565 anyString(), eq(null), anyString()); 3566 } 3567 3568 @Test testBubblePreference_xml()3569 public void testBubblePreference_xml() throws Exception { 3570 mHelper.setBubblesAllowed(PKG_O, UID_O, BUBBLE_PREFERENCE_NONE); 3571 assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE); 3572 assertEquals(PreferencesHelper.LockableAppFields.USER_LOCKED_BUBBLE, 3573 mHelper.getAppLockedFields(PKG_O, UID_O)); 3574 3575 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL); 3576 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 3577 mPermissionHelper, mLogger, 3578 mAppOpsManager, mStatsEventBuilderFactory, false); 3579 loadStreamXml(baos, false, UserHandle.USER_ALL); 3580 3581 assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE); 3582 assertEquals(PreferencesHelper.LockableAppFields.USER_LOCKED_BUBBLE, 3583 mHelper.getAppLockedFields(PKG_O, UID_O)); 3584 } 3585 3586 @Test testUpdateNotificationChannel_fixedPermission()3587 public void testUpdateNotificationChannel_fixedPermission() { 3588 List<UserInfo> users = ImmutableList.of(new UserInfo(UserHandle.USER_SYSTEM, "user0", 0)); 3589 when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true); 3590 PackageInfo pm = new PackageInfo(); 3591 pm.packageName = PKG_O; 3592 pm.applicationInfo = new ApplicationInfo(); 3593 pm.applicationInfo.uid = UID_O; 3594 List<PackageInfo> packages = ImmutableList.of(pm); 3595 when(mPm.getInstalledPackagesAsUser(any(), anyInt())).thenReturn(packages); 3596 mHelper.updateFixedImportance(users); 3597 3598 assertTrue(mHelper.isImportanceLocked(PKG_O, UID_O)); 3599 3600 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3601 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3602 3603 NotificationChannel update = new NotificationChannel("a", "a", IMPORTANCE_NONE); 3604 update.setAllowBubbles(false); 3605 3606 mHelper.updateNotificationChannel(PKG_O, UID_O, update, true); 3607 3608 assertEquals(IMPORTANCE_HIGH, 3609 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance()); 3610 assertEquals(false, 3611 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).canBubble()); 3612 } 3613 3614 @Test testUpdateNotificationChannel_defaultApp()3615 public void testUpdateNotificationChannel_defaultApp() { 3616 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3617 toAdd.add(new Pair(PKG_O, UID_O)); 3618 mHelper.updateDefaultApps(0, null, toAdd); 3619 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3620 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3621 3622 NotificationChannel update = new NotificationChannel("a", "a", IMPORTANCE_NONE); 3623 update.setAllowBubbles(false); 3624 3625 mHelper.updateNotificationChannel(PKG_O, UID_O, update, true); 3626 3627 assertEquals(IMPORTANCE_HIGH, 3628 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance()); 3629 assertEquals(false, 3630 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).canBubble()); 3631 } 3632 3633 @Test testUpdateNotificationChannel_fixedPermission_butUserPreviouslyBlockedIt()3634 public void testUpdateNotificationChannel_fixedPermission_butUserPreviouslyBlockedIt() { 3635 when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true); 3636 3637 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_NONE); 3638 mHelper.createNotificationChannel(PKG_O, UID_O, a, false, false); 3639 3640 NotificationChannel update = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3641 update.setAllowBubbles(false); 3642 3643 mHelper.updateNotificationChannel(PKG_O, UID_O, update, true); 3644 3645 assertEquals(IMPORTANCE_HIGH, 3646 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance()); 3647 assertEquals(false, 3648 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).canBubble()); 3649 } 3650 3651 @Test testUpdateNotificationChannel_fixedPermission_butAppAllowsIt()3652 public void testUpdateNotificationChannel_fixedPermission_butAppAllowsIt() { 3653 when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true); 3654 3655 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3656 a.setBlockable(true); 3657 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3658 3659 NotificationChannel update = new NotificationChannel("a", "a", IMPORTANCE_NONE); 3660 update.setAllowBubbles(false); 3661 3662 mHelper.updateNotificationChannel(PKG_O, UID_O, update, true); 3663 3664 assertEquals(IMPORTANCE_NONE, 3665 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance()); 3666 assertEquals(false, 3667 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).canBubble()); 3668 } 3669 3670 @Test testUpdateNotificationChannel_notFixedPermission()3671 public void testUpdateNotificationChannel_notFixedPermission() { 3672 when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(false); 3673 3674 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3675 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3676 3677 NotificationChannel update = new NotificationChannel("a", "a", IMPORTANCE_NONE); 3678 update.setAllowBubbles(false); 3679 3680 mHelper.updateNotificationChannel(PKG_O, UID_O, update, true); 3681 3682 assertEquals(IMPORTANCE_NONE, 3683 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance()); 3684 assertEquals(false, 3685 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).canBubble()); 3686 } 3687 3688 @Test testUpdateFixedImportance_multiUser()3689 public void testUpdateFixedImportance_multiUser() { 3690 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3691 NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW); 3692 NotificationChannel c = new NotificationChannel("c", "c", IMPORTANCE_DEFAULT); 3693 // different uids, same package 3694 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3695 mHelper.createNotificationChannel(PKG_O, UID_O, b, false, false); 3696 mHelper.createNotificationChannel(PKG_O, UserHandle.PER_USER_RANGE + 1, c, true, true); 3697 3698 UserInfo user = new UserInfo(); 3699 user.id = 0; 3700 List<UserInfo> users = ImmutableList.of(user); 3701 when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true); 3702 PackageInfo pm = new PackageInfo(); 3703 pm.packageName = PKG_O; 3704 pm.applicationInfo = new ApplicationInfo(); 3705 pm.applicationInfo.uid = UID_O; 3706 List<PackageInfo> packages = ImmutableList.of(pm); 3707 when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages); 3708 mHelper.updateFixedImportance(users); 3709 3710 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3711 .isImportanceLockedByCriticalDeviceFunction()); 3712 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, b.getId(), false) 3713 .isImportanceLockedByCriticalDeviceFunction()); 3714 assertFalse(mHelper.getNotificationChannel( 3715 PKG_O, UserHandle.PER_USER_RANGE + 1, c.getId(), false) 3716 .isImportanceLockedByCriticalDeviceFunction()); 3717 } 3718 3719 @Test testUpdateFixedImportance_channelDoesNotExistYet()3720 public void testUpdateFixedImportance_channelDoesNotExistYet() { 3721 UserInfo user = new UserInfo(); 3722 user.id = 0; 3723 List<UserInfo> users = ImmutableList.of(user); 3724 when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true); 3725 PackageInfo pm = new PackageInfo(); 3726 pm.packageName = PKG_O; 3727 pm.applicationInfo = new ApplicationInfo(); 3728 pm.applicationInfo.uid = UID_O; 3729 List<PackageInfo> packages = ImmutableList.of(pm); 3730 when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages); 3731 mHelper.updateFixedImportance(users); 3732 3733 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3734 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3735 3736 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3737 .isImportanceLockedByCriticalDeviceFunction()); 3738 } 3739 3740 @Test testUpdateDefaultApps_add_multiUser()3741 public void testUpdateDefaultApps_add_multiUser() { 3742 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3743 NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW); 3744 NotificationChannel c = new NotificationChannel("c", "c", IMPORTANCE_DEFAULT); 3745 // different uids, same package 3746 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3747 mHelper.createNotificationChannel(PKG_O, UID_O, b, false, false); 3748 mHelper.createNotificationChannel(PKG_O, UserHandle.PER_USER_RANGE + 1, c, true, true); 3749 3750 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3751 toAdd.add(new Pair(PKG_O, UID_O)); 3752 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd); 3753 3754 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3755 .isImportanceLockedByCriticalDeviceFunction()); 3756 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, b.getId(), false) 3757 .isImportanceLockedByCriticalDeviceFunction()); 3758 assertFalse(mHelper.getNotificationChannel( 3759 PKG_O, UserHandle.PER_USER_RANGE + 1, c.getId(), false) 3760 .isImportanceLockedByCriticalDeviceFunction()); 3761 } 3762 3763 @Test testUpdateDefaultApps_add_onlyGivenPkg()3764 public void testUpdateDefaultApps_add_onlyGivenPkg() { 3765 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3766 NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW); 3767 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3768 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, b, false, false); 3769 3770 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3771 toAdd.add(new Pair(PKG_O, UID_O)); 3772 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd); 3773 3774 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3775 .isImportanceLockedByCriticalDeviceFunction()); 3776 assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, b.getId(), false) 3777 .isImportanceLockedByCriticalDeviceFunction()); 3778 } 3779 3780 @Test testUpdateDefaultApps_remove()3781 public void testUpdateDefaultApps_remove() { 3782 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3783 NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW); 3784 // different uids, same package 3785 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3786 mHelper.createNotificationChannel(PKG_O, UID_O, b, false, false); 3787 3788 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3789 toAdd.add(new Pair(PKG_O, UID_O)); 3790 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd); 3791 3792 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3793 .isImportanceLockedByCriticalDeviceFunction()); 3794 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, b.getId(), false) 3795 .isImportanceLockedByCriticalDeviceFunction()); 3796 3797 ArraySet<String> toRemove = new ArraySet<>(); 3798 toRemove.add(PKG_O); 3799 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), toRemove, null); 3800 3801 assertFalse(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3802 .isImportanceLockedByCriticalDeviceFunction()); 3803 assertFalse(mHelper.getNotificationChannel(PKG_O, UID_O, b.getId(), false) 3804 .isImportanceLockedByCriticalDeviceFunction()); 3805 } 3806 3807 @Test testUpdateDefaultApps_addAndRemove()3808 public void testUpdateDefaultApps_addAndRemove() { 3809 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3810 NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW); 3811 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3812 mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, b, false, false); 3813 3814 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3815 toAdd.add(new Pair(PKG_O, UID_O)); 3816 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd); 3817 3818 3819 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3820 .isImportanceLockedByCriticalDeviceFunction()); 3821 assertFalse(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, b.getId(), false) 3822 .isImportanceLockedByCriticalDeviceFunction()); 3823 3824 // now the default is PKG_N_MR1 3825 ArraySet<String> toRemove = new ArraySet<>(); 3826 toRemove.add(PKG_O); 3827 toAdd = new ArraySet<>(); 3828 toAdd.add(new Pair(PKG_N_MR1, UID_N_MR1)); 3829 mHelper.updateDefaultApps(USER.getIdentifier(), toRemove, toAdd); 3830 3831 assertFalse(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3832 .isImportanceLockedByCriticalDeviceFunction()); 3833 assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, b.getId(), false) 3834 .isImportanceLockedByCriticalDeviceFunction()); 3835 } 3836 3837 @Test testUpdateDefaultApps_appDoesNotExist_noCrash()3838 public void testUpdateDefaultApps_appDoesNotExist_noCrash() { 3839 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3840 toAdd.add(new Pair(PKG_O, UID_O)); 3841 ArraySet<String> toRemove = new ArraySet<>(); 3842 toRemove.add(PKG_N_MR1); 3843 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), toRemove, toAdd); 3844 } 3845 3846 @Test testUpdateDefaultApps_channelDoesNotExistYet()3847 public void testUpdateDefaultApps_channelDoesNotExistYet() { 3848 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3849 NotificationChannel b = new NotificationChannel("b", "b", IMPORTANCE_LOW); 3850 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3851 3852 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3853 toAdd.add(new Pair(PKG_O, UID_O)); 3854 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd); 3855 3856 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3857 .isImportanceLockedByCriticalDeviceFunction()); 3858 3859 mHelper.createNotificationChannel(PKG_O, UID_O, b, true, false); 3860 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, b.getId(), false) 3861 .isImportanceLockedByCriticalDeviceFunction()); 3862 } 3863 3864 @Test testUpdateNotificationChannel_defaultAppLockedImportance()3865 public void testUpdateNotificationChannel_defaultAppLockedImportance() { 3866 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3867 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3868 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3869 toAdd.add(new Pair(PKG_O, UID_O)); 3870 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd); 3871 3872 NotificationChannel update = new NotificationChannel("a", "a", IMPORTANCE_NONE); 3873 update.setAllowBubbles(false); 3874 3875 mHelper.updateNotificationChannel(PKG_O, UID_O, update, true); 3876 assertEquals(IMPORTANCE_HIGH, 3877 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance()); 3878 assertEquals(false, 3879 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).canBubble()); 3880 3881 mHelper.updateNotificationChannel(PKG_O, UID_O, update, false); 3882 assertEquals(IMPORTANCE_HIGH, 3883 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance()); 3884 3885 NotificationChannel updateImportanceLow = new NotificationChannel("a", "a", 3886 IMPORTANCE_LOW); 3887 mHelper.updateNotificationChannel(PKG_O, UID_O, updateImportanceLow, true); 3888 assertEquals(IMPORTANCE_LOW, 3889 mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false).getImportance()); 3890 } 3891 3892 @Test testDefaultApp_appHasNoSettingsYet()3893 public void testDefaultApp_appHasNoSettingsYet() { 3894 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3895 toAdd.add(new Pair(PKG_O, UID_O)); 3896 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd); 3897 3898 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3899 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3900 3901 assertTrue(a.isImportanceLockedByCriticalDeviceFunction()); 3902 } 3903 3904 @Test testUpdateFixedImportance_thenDefaultAppsRemoves()3905 public void testUpdateFixedImportance_thenDefaultAppsRemoves() { 3906 UserInfo user = new UserInfo(); 3907 user.id = 0; 3908 List<UserInfo> users = ImmutableList.of(user); 3909 when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(true); 3910 PackageInfo pm = new PackageInfo(); 3911 pm.packageName = PKG_O; 3912 pm.applicationInfo = new ApplicationInfo(); 3913 pm.applicationInfo.uid = UID_O; 3914 List<PackageInfo> packages = ImmutableList.of(pm); 3915 when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages); 3916 mHelper.updateFixedImportance(users); 3917 3918 ArraySet<String> toRemove = new ArraySet<>(); 3919 toRemove.add(PKG_O); 3920 mHelper.updateDefaultApps(0, toRemove, null); 3921 3922 assertTrue(mHelper.isImportanceLocked(PKG_O, UID_O)); 3923 3924 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3925 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3926 3927 // Still locked by permission if not role 3928 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3929 .isImportanceLockedByCriticalDeviceFunction()); 3930 } 3931 3932 @Test testUpdateDefaultApps_thenNotFixedPermission()3933 public void testUpdateDefaultApps_thenNotFixedPermission() { 3934 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3935 toAdd.add(new Pair(PKG_O, UID_O)); 3936 mHelper.updateDefaultApps(0, null, toAdd); 3937 3938 UserInfo user = new UserInfo(); 3939 user.id = 0; 3940 List<UserInfo> users = ImmutableList.of(user); 3941 when(mPermissionHelper.isPermissionFixed(PKG_O, 0)).thenReturn(false); 3942 PackageInfo pm = new PackageInfo(); 3943 pm.packageName = PKG_O; 3944 pm.applicationInfo = new ApplicationInfo(); 3945 pm.applicationInfo.uid = UID_O; 3946 List<PackageInfo> packages = ImmutableList.of(pm); 3947 when(mPm.getInstalledPackagesAsUser(any(), eq(0))).thenReturn(packages); 3948 mHelper.updateFixedImportance(users); 3949 3950 assertTrue(mHelper.isImportanceLocked(PKG_O, UID_O)); 3951 3952 NotificationChannel a = new NotificationChannel("a", "a", IMPORTANCE_HIGH); 3953 mHelper.createNotificationChannel(PKG_O, UID_O, a, true, false); 3954 3955 // Still locked by role if not permission 3956 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, a.getId(), false) 3957 .isImportanceLockedByCriticalDeviceFunction()); 3958 } 3959 3960 @Test testChannelXml_backupDefaultApp()3961 public void testChannelXml_backupDefaultApp() throws Exception { 3962 NotificationChannel channel1 = 3963 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH); 3964 3965 mHelper.createNotificationChannel(PKG_O, UID_O, channel1, true, false); 3966 3967 // clear data 3968 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, true, 3969 USER_SYSTEM, channel1.getId(), NotificationChannel.DEFAULT_CHANNEL_ID); 3970 mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG_O}, new int[]{ 3971 UID_O}); 3972 3973 ArraySet<Pair<String, Integer>> toAdd = new ArraySet<>(); 3974 toAdd.add(new Pair(PKG_O, UID_O)); 3975 mHelper.updateDefaultApps(UserHandle.getUserId(UID_O), null, toAdd); 3976 3977 TypedXmlPullParser parser = Xml.newFastPullParser(); 3978 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), 3979 null); 3980 parser.nextTag(); 3981 mHelper.readXml(parser, true, USER_SYSTEM); 3982 3983 assertTrue(mHelper.getNotificationChannel(PKG_O, UID_O, channel1.getId(), false) 3984 .isImportanceLockedByCriticalDeviceFunction()); 3985 } 3986 3987 @Test testSetBubblesAllowed_none()3988 public void testSetBubblesAllowed_none() { 3989 // Change it to non-default first 3990 mHelper.setBubblesAllowed(PKG_O, UID_O, BUBBLE_PREFERENCE_ALL); 3991 assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_ALL); 3992 verify(mHandler, times(1)).requestSort(); 3993 reset(mHandler); 3994 // Now test 3995 mHelper.setBubblesAllowed(PKG_O, UID_O, BUBBLE_PREFERENCE_NONE); 3996 assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE); 3997 verify(mHandler, times(1)).requestSort(); 3998 } 3999 4000 @Test testSetBubblesAllowed_all()4001 public void testSetBubblesAllowed_all() { 4002 mHelper.setBubblesAllowed(PKG_O, UID_O, BUBBLE_PREFERENCE_ALL); 4003 assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_ALL); 4004 verify(mHandler, times(1)).requestSort(); 4005 } 4006 4007 @Test testSetBubblesAllowed_selected()4008 public void testSetBubblesAllowed_selected() { 4009 mHelper.setBubblesAllowed(PKG_O, UID_O, BUBBLE_PREFERENCE_SELECTED); 4010 assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_SELECTED); 4011 verify(mHandler, times(1)).requestSort(); 4012 } 4013 4014 @Test testTooManyChannels()4015 public void testTooManyChannels() { 4016 for (int i = 0; i < NOTIFICATION_CHANNEL_COUNT_LIMIT; i++) { 4017 NotificationChannel channel = new NotificationChannel(String.valueOf(i), 4018 String.valueOf(i), NotificationManager.IMPORTANCE_HIGH); 4019 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true); 4020 } 4021 try { 4022 NotificationChannel channel = new NotificationChannel( 4023 String.valueOf(NOTIFICATION_CHANNEL_COUNT_LIMIT), 4024 String.valueOf(NOTIFICATION_CHANNEL_COUNT_LIMIT), 4025 NotificationManager.IMPORTANCE_HIGH); 4026 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true); 4027 fail("Allowed to create too many notification channels"); 4028 } catch (IllegalStateException e) { 4029 // great 4030 } 4031 } 4032 4033 @Test testTooManyChannels_xml()4034 public void testTooManyChannels_xml() throws Exception { 4035 String extraChannel = "EXTRA"; 4036 String extraChannel1 = "EXTRA1"; 4037 4038 // create first... many... directly so we don't need a big xml blob in this test 4039 for (int i = 0; i < NOTIFICATION_CHANNEL_COUNT_LIMIT; i++) { 4040 NotificationChannel channel = new NotificationChannel(String.valueOf(i), 4041 String.valueOf(i), NotificationManager.IMPORTANCE_HIGH); 4042 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, true); 4043 } 4044 4045 final String xml = "<ranking version=\"1\">\n" 4046 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" 4047 + "<channel id=\"" + extraChannel + "\" name=\"hi\" importance=\"3\"/>" 4048 + "<channel id=\"" + extraChannel1 + "\" name=\"hi\" importance=\"3\"/>" 4049 + "</package>" 4050 + "</ranking>"; 4051 TypedXmlPullParser parser = Xml.newFastPullParser(); 4052 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 4053 null); 4054 parser.nextTag(); 4055 mHelper.readXml(parser, false, UserHandle.USER_ALL); 4056 4057 assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, extraChannel, true)); 4058 assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, extraChannel1, true)); 4059 } 4060 4061 @Test testTooManyGroups()4062 public void testTooManyGroups() { 4063 for (int i = 0; i < NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT; i++) { 4064 NotificationChannelGroup group = new NotificationChannelGroup(String.valueOf(i), 4065 String.valueOf(i)); 4066 mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true); 4067 } 4068 try { 4069 NotificationChannelGroup group = new NotificationChannelGroup( 4070 String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT), 4071 String.valueOf(NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT)); 4072 mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true); 4073 fail("Allowed to create too many notification channel groups"); 4074 } catch (IllegalStateException e) { 4075 // great 4076 } 4077 } 4078 4079 @Test testTooManyGroups_xml()4080 public void testTooManyGroups_xml() throws Exception { 4081 String extraGroup = "EXTRA"; 4082 String extraGroup1 = "EXTRA1"; 4083 4084 // create first... many... directly so we don't need a big xml blob in this test 4085 for (int i = 0; i < NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT; i++) { 4086 NotificationChannelGroup group = new NotificationChannelGroup(String.valueOf(i), 4087 String.valueOf(i)); 4088 mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true); 4089 } 4090 4091 final String xml = "<ranking version=\"1\">\n" 4092 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" 4093 + "<channelGroup id=\"" + extraGroup + "\" name=\"hi\"/>" 4094 + "<channelGroup id=\"" + extraGroup1 + "\" name=\"hi2\"/>" 4095 + "</package>" 4096 + "</ranking>"; 4097 TypedXmlPullParser parser = Xml.newFastPullParser(); 4098 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 4099 null); 4100 parser.nextTag(); 4101 mHelper.readXml(parser, false, UserHandle.USER_ALL); 4102 4103 assertNull(mHelper.getNotificationChannelGroup(extraGroup, PKG_O, UID_O)); 4104 assertNull(mHelper.getNotificationChannelGroup(extraGroup1, PKG_O, UID_O)); 4105 } 4106 4107 @Test testRestoreMultiUser()4108 public void testRestoreMultiUser() throws Exception { 4109 String pkg = "restore_pkg"; 4110 String channelId = "channelId"; 4111 int user0Importance = 3; 4112 int user10Importance = 4; 4113 when(mPm.getPackageUidAsUser(eq(pkg), anyInt())).thenReturn(UserHandle.USER_NULL); 4114 4115 // both users have the same package, but different notification settings 4116 final String xmlUser0 = "<ranking version=\"1\">\n" 4117 + "<package name=\"" + pkg + "\" >\n" 4118 + "<channel id=\"" + channelId + "\" name=\"hi\"" 4119 + " importance=\"" + user0Importance + "\"/>" 4120 + "</package>" 4121 + "</ranking>"; 4122 final String xmlUser10 = "<ranking version=\"1\">\n" 4123 + "<package name=\"" + pkg + "\" >\n" 4124 + "<channel id=\"" + channelId + "\" name=\"hi\"" 4125 + " importance=\"" + user10Importance + "\"/>" 4126 + "</package>" 4127 + "</ranking>"; 4128 4129 // trigger a restore for both users 4130 TypedXmlPullParser parser = Xml.newFastPullParser(); 4131 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xmlUser0.getBytes())), 4132 null); 4133 parser.nextTag(); 4134 mHelper.readXml(parser, true, 0); 4135 parser = Xml.newFastPullParser(); 4136 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xmlUser10.getBytes())), 4137 null); 4138 parser.nextTag(); 4139 mHelper.readXml(parser, true, 10); 4140 4141 // "install" package on both users 4142 String[] pkgList = new String[] {pkg}; 4143 int[] uidList0 = new int[] {UserHandle.PER_USER_RANGE}; 4144 int[] uidList10 = new int[] {UserHandle.PER_USER_RANGE + 1}; 4145 when(mPm.getPackageUidAsUser(pkg, 0)).thenReturn(uidList0[0]); 4146 when(mPm.getPackageUidAsUser(pkg, 10)).thenReturn(uidList10[0]); 4147 ApplicationInfo info = new ApplicationInfo(); 4148 info.targetSdkVersion = Build.VERSION_CODES.Q; 4149 when(mPm.getApplicationInfoAsUser(eq(pkg), anyInt(), anyInt())).thenReturn(info); 4150 4151 mHelper.onPackagesChanged(false, 0, pkgList, uidList0); 4152 mHelper.onPackagesChanged(false, 10, pkgList, uidList10); 4153 4154 assertEquals(user0Importance, 4155 mHelper.getNotificationChannel(pkg, uidList0[0], channelId, false).getImportance()); 4156 assertEquals(user10Importance, mHelper.getNotificationChannel( 4157 pkg, uidList10[0], channelId, false).getImportance()); 4158 } 4159 4160 @Test testGetConversationNotificationChannel()4161 public void testGetConversationNotificationChannel() { 4162 String conversationId = "friend"; 4163 4164 NotificationChannel parent = 4165 new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); 4166 mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); 4167 4168 NotificationChannel friend = new NotificationChannel(String.format( 4169 CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId), 4170 "messages", IMPORTANCE_DEFAULT); 4171 friend.setConversationId(parent.getId(), conversationId); 4172 mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); 4173 4174 compareChannelsParentChild(parent, mHelper.getConversationNotificationChannel( 4175 PKG_O, UID_O, parent.getId(), conversationId, false, false), conversationId); 4176 } 4177 4178 @Test testGetNotificationChannel_conversationProvidedByNotCustomizedYet()4179 public void testGetNotificationChannel_conversationProvidedByNotCustomizedYet() { 4180 String conversationId = "friend"; 4181 4182 NotificationChannel parent = 4183 new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); 4184 mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); 4185 4186 compareChannels(parent, mHelper.getConversationNotificationChannel( 4187 PKG_O, UID_O, parent.getId(), conversationId, true, false)); 4188 } 4189 4190 @Test testConversationNotificationChannelsRequireParents()4191 public void testConversationNotificationChannelsRequireParents() { 4192 String parentId = "does not exist"; 4193 String conversationId = "friend"; 4194 4195 NotificationChannel friend = new NotificationChannel(String.format( 4196 CONVERSATION_CHANNEL_ID_FORMAT, parentId, conversationId), 4197 "messages", IMPORTANCE_DEFAULT); 4198 friend.setConversationId(parentId, conversationId); 4199 4200 try { 4201 mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); 4202 fail("allowed creation of conversation channel without a parent"); 4203 } catch (IllegalArgumentException e) { 4204 // good 4205 } 4206 } 4207 4208 @Test testPlaceholderConversationId_shortcutRequired()4209 public void testPlaceholderConversationId_shortcutRequired() throws Exception { 4210 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4211 mPermissionHelper, mLogger, 4212 mAppOpsManager, mStatsEventBuilderFactory, false); 4213 4214 final String xml = "<ranking version=\"1\">\n" 4215 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" 4216 + "<channel id=\"id\" name=\"hi\" importance=\"3\" conv_id=\"foo:placeholder_id\"/>" 4217 + "</package>" 4218 + "</ranking>"; 4219 TypedXmlPullParser parser = Xml.newFastPullParser(); 4220 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 4221 null); 4222 parser.nextTag(); 4223 mHelper.readXml(parser, false, UserHandle.USER_ALL); 4224 4225 assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, "id", true)); 4226 } 4227 4228 @Test testNormalConversationId_shortcutRequired()4229 public void testNormalConversationId_shortcutRequired() throws Exception { 4230 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4231 mPermissionHelper, mLogger, 4232 mAppOpsManager, mStatsEventBuilderFactory, false); 4233 4234 final String xml = "<ranking version=\"1\">\n" 4235 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" 4236 + "<channel id=\"id\" name=\"hi\" importance=\"3\" conv_id=\"other\"/>" 4237 + "</package>" 4238 + "</ranking>"; 4239 TypedXmlPullParser parser = Xml.newFastPullParser(); 4240 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 4241 null); 4242 parser.nextTag(); 4243 mHelper.readXml(parser, false, UserHandle.USER_ALL); 4244 4245 assertNotNull(mHelper.getNotificationChannel(PKG_O, UID_O, "id", true)); 4246 } 4247 4248 @Test testNoConversationId_shortcutRequired()4249 public void testNoConversationId_shortcutRequired() throws Exception { 4250 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4251 mPermissionHelper, mLogger, 4252 mAppOpsManager, mStatsEventBuilderFactory, false); 4253 4254 final String xml = "<ranking version=\"1\">\n" 4255 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" 4256 + "<channel id=\"id\" name=\"hi\" importance=\"3\"/>" 4257 + "</package>" 4258 + "</ranking>"; 4259 TypedXmlPullParser parser = Xml.newFastPullParser(); 4260 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 4261 null); 4262 parser.nextTag(); 4263 mHelper.readXml(parser, false, UserHandle.USER_ALL); 4264 4265 assertNotNull(mHelper.getNotificationChannel(PKG_O, UID_O, "id", true)); 4266 } 4267 4268 @Test testDeleted_noTime()4269 public void testDeleted_noTime() throws Exception { 4270 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4271 mPermissionHelper, mLogger, 4272 mAppOpsManager, mStatsEventBuilderFactory, false); 4273 4274 final String xml = "<ranking version=\"1\">\n" 4275 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" 4276 + "<channel id=\"id\" name=\"hi\" importance=\"3\" deleted=\"true\"/>" 4277 + "</package>" 4278 + "</ranking>"; 4279 TypedXmlPullParser parser = Xml.newFastPullParser(); 4280 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 4281 null); 4282 parser.nextTag(); 4283 mHelper.readXml(parser, false, UserHandle.USER_ALL); 4284 4285 assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, "id", true)); 4286 } 4287 4288 @Test testDeleted_twice()4289 public void testDeleted_twice() throws Exception { 4290 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4291 mPermissionHelper, mLogger, 4292 mAppOpsManager, mStatsEventBuilderFactory, false); 4293 4294 mHelper.createNotificationChannel( 4295 PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false); 4296 assertTrue(mHelper.deleteNotificationChannel(PKG_P, UID_P, "id")); 4297 assertFalse(mHelper.deleteNotificationChannel(PKG_P, UID_P, "id")); 4298 } 4299 4300 @Test testDeleted_recentTime()4301 public void testDeleted_recentTime() throws Exception { 4302 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4303 mPermissionHelper, mLogger, 4304 mAppOpsManager, mStatsEventBuilderFactory, false); 4305 4306 mHelper.createNotificationChannel( 4307 PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false); 4308 mHelper.deleteNotificationChannel(PKG_P, UID_P, "id"); 4309 NotificationChannel nc1 = mHelper.getNotificationChannel(PKG_P, UID_P, "id", true); 4310 assertTrue(DateUtils.isToday(nc1.getDeletedTimeMs())); 4311 assertTrue(nc1.isDeleted()); 4312 4313 ByteArrayOutputStream baos = writeXmlAndPurge(PKG_P, UID_P, false, 4314 USER_SYSTEM, "id", NotificationChannel.DEFAULT_CHANNEL_ID); 4315 4316 TypedXmlPullParser parser = Xml.newFastPullParser(); 4317 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray())), 4318 null); 4319 parser.nextTag(); 4320 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4321 mPermissionHelper, mLogger, 4322 mAppOpsManager, mStatsEventBuilderFactory, false); 4323 mHelper.readXml(parser, true, USER_SYSTEM); 4324 4325 NotificationChannel nc = mHelper.getNotificationChannel(PKG_P, UID_P, "id", true); 4326 assertTrue(DateUtils.isToday(nc.getDeletedTimeMs())); 4327 assertTrue(nc.isDeleted()); 4328 } 4329 4330 @Test testUnDelete_time()4331 public void testUnDelete_time() throws Exception { 4332 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4333 mPermissionHelper, mLogger, 4334 mAppOpsManager, mStatsEventBuilderFactory, false); 4335 4336 mHelper.createNotificationChannel( 4337 PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false); 4338 mHelper.deleteNotificationChannel(PKG_P, UID_P, "id"); 4339 NotificationChannel nc1 = mHelper.getNotificationChannel(PKG_P, UID_P, "id", true); 4340 assertTrue(DateUtils.isToday(nc1.getDeletedTimeMs())); 4341 assertTrue(nc1.isDeleted()); 4342 4343 mHelper.createNotificationChannel( 4344 PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false); 4345 nc1 = mHelper.getNotificationChannel(PKG_P, UID_P, "id", true); 4346 assertEquals(-1, nc1.getDeletedTimeMs()); 4347 assertFalse(nc1.isDeleted()); 4348 } 4349 4350 @Test testDeleted_longTime()4351 public void testDeleted_longTime() throws Exception { 4352 mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper, 4353 mPermissionHelper, mLogger, 4354 mAppOpsManager, mStatsEventBuilderFactory, false); 4355 4356 long time = System.currentTimeMillis() - (DateUtils.DAY_IN_MILLIS * 30); 4357 4358 final String xml = "<ranking version=\"1\">\n" 4359 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n" 4360 + "<channel id=\"id\" name=\"hi\" importance=\"3\" deleted=\"true\" del_time=\"" 4361 + time + "\"/>" 4362 + "</package>" 4363 + "</ranking>"; 4364 TypedXmlPullParser parser = Xml.newFastPullParser(); 4365 parser.setInput(new BufferedInputStream(new ByteArrayInputStream(xml.getBytes())), 4366 null); 4367 parser.nextTag(); 4368 mHelper.readXml(parser, false, UserHandle.USER_ALL); 4369 4370 NotificationChannel nc = mHelper.getNotificationChannel(PKG_O, UID_O, "id", true); 4371 assertNull(nc); 4372 } 4373 4374 @Test testGetConversations_all()4375 public void testGetConversations_all() { 4376 String convoId = "convo"; 4377 NotificationChannel messages = 4378 new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); 4379 mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); 4380 NotificationChannel calls = 4381 new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT); 4382 mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); 4383 NotificationChannel p = 4384 new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT); 4385 mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false); 4386 4387 NotificationChannel channel = 4388 new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); 4389 channel.setConversationId(messages.getId(), convoId); 4390 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4391 4392 NotificationChannel diffConvo = 4393 new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); 4394 diffConvo.setConversationId(p.getId(), "different convo"); 4395 mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, true, false); 4396 4397 NotificationChannel channel2 = 4398 new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT); 4399 channel2.setConversationId(calls.getId(), convoId); 4400 channel2.setImportantConversation(true); 4401 mHelper.createNotificationChannel(PKG_O, UID_O, channel2, false, false); 4402 4403 List<ConversationChannelWrapper> convos = 4404 mHelper.getConversations(IntArray.wrap(new int[] {0}), false); 4405 4406 assertEquals(3, convos.size()); 4407 assertTrue(conversationWrapperContainsChannel(convos, channel)); 4408 assertTrue(conversationWrapperContainsChannel(convos, diffConvo)); 4409 assertTrue(conversationWrapperContainsChannel(convos, channel2)); 4410 } 4411 4412 @Test testGetConversations_multiUser()4413 public void testGetConversations_multiUser() { 4414 String convoId = "convo"; 4415 NotificationChannel messages = 4416 new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); 4417 mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); 4418 4419 NotificationChannel messagesUser10 = 4420 new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); 4421 mHelper.createNotificationChannel( 4422 PKG_O, UID_O + UserHandle.PER_USER_RANGE, messagesUser10, true, false); 4423 4424 NotificationChannel messagesFromB = 4425 new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); 4426 messagesFromB.setConversationId(messages.getId(), "different convo"); 4427 mHelper.createNotificationChannel(PKG_O, UID_O, messagesFromB, true, false); 4428 4429 NotificationChannel messagesFromBUser10 = 4430 new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); 4431 messagesFromBUser10.setConversationId(messagesUser10.getId(), "different convo"); 4432 mHelper.createNotificationChannel( 4433 PKG_O, UID_O + UserHandle.PER_USER_RANGE, messagesFromBUser10, true, false); 4434 4435 4436 List<ConversationChannelWrapper> convos = 4437 mHelper.getConversations(IntArray.wrap(new int[] {0}), false); 4438 4439 assertEquals(1, convos.size()); 4440 assertTrue(conversationWrapperContainsChannel(convos, messagesFromB)); 4441 4442 convos = 4443 mHelper.getConversations(IntArray.wrap(new int[] {0, UserHandle.getUserId(UID_O + UserHandle.PER_USER_RANGE)}), false); 4444 4445 assertEquals(2, convos.size()); 4446 assertTrue(conversationWrapperContainsChannel(convos, messagesFromB)); 4447 assertTrue(conversationWrapperContainsChannel(convos, messagesFromBUser10)); 4448 } 4449 4450 @Test testGetConversations_notDemoted()4451 public void testGetConversations_notDemoted() { 4452 String convoId = "convo"; 4453 NotificationChannel messages = 4454 new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); 4455 mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); 4456 NotificationChannel calls = 4457 new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT); 4458 mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); 4459 NotificationChannel p = 4460 new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT); 4461 mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false); 4462 4463 NotificationChannel channel = 4464 new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); 4465 channel.setConversationId(messages.getId(), convoId); 4466 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4467 4468 NotificationChannel diffConvo = 4469 new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); 4470 diffConvo.setConversationId(p.getId(), "different convo"); 4471 diffConvo.setDemoted(true); 4472 mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, true, false); 4473 4474 NotificationChannel channel2 = 4475 new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT); 4476 channel2.setConversationId(calls.getId(), convoId); 4477 channel2.setImportantConversation(true); 4478 mHelper.createNotificationChannel(PKG_O, UID_O, channel2, false, false); 4479 4480 List<ConversationChannelWrapper> convos = 4481 mHelper.getConversations(IntArray.wrap(new int[] {0}), false); 4482 4483 assertEquals(2, convos.size()); 4484 assertTrue(conversationWrapperContainsChannel(convos, channel)); 4485 assertFalse(conversationWrapperContainsChannel(convos, diffConvo)); 4486 assertTrue(conversationWrapperContainsChannel(convos, channel2)); 4487 } 4488 4489 @Test testGetConversations_onlyImportant()4490 public void testGetConversations_onlyImportant() { 4491 String convoId = "convo"; 4492 NotificationChannel messages = 4493 new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); 4494 mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); 4495 NotificationChannel calls = 4496 new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT); 4497 mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); 4498 NotificationChannel p = 4499 new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT); 4500 mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false); 4501 4502 NotificationChannel channel = 4503 new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); 4504 channel.setConversationId(messages.getId(), convoId); 4505 channel.setImportantConversation(true); 4506 mHelper.createNotificationChannel(PKG_O, UID_O, channel, false, false); 4507 4508 NotificationChannel diffConvo = 4509 new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); 4510 diffConvo.setConversationId(p.getId(), "different convo"); 4511 diffConvo.setImportantConversation(true); 4512 mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, false, false); 4513 4514 NotificationChannel channel2 = 4515 new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT); 4516 channel2.setConversationId(calls.getId(), convoId); 4517 mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); 4518 4519 List<ConversationChannelWrapper> convos = 4520 mHelper.getConversations(IntArray.wrap(new int[] {0}), true); 4521 4522 assertEquals(2, convos.size()); 4523 assertTrue(conversationWrapperContainsChannel(convos, channel)); 4524 assertTrue(conversationWrapperContainsChannel(convos, diffConvo)); 4525 assertFalse(conversationWrapperContainsChannel(convos, channel2)); 4526 } 4527 4528 @Test testGetConversations_parentDeleted()4529 public void testGetConversations_parentDeleted() { 4530 String convoId = "convo"; 4531 NotificationChannel messages = 4532 new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); 4533 mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); 4534 4535 NotificationChannel channel = 4536 new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); 4537 channel.setConversationId(messages.getId(), convoId); 4538 channel.setImportantConversation(true); 4539 mHelper.createNotificationChannel(PKG_O, UID_O, channel, false, false); 4540 4541 mHelper.permanentlyDeleteNotificationChannel(PKG_O, UID_O, "messages"); 4542 4543 List<ConversationChannelWrapper> convos = 4544 mHelper.getConversations(IntArray.wrap(new int[] {0}), true); 4545 4546 assertEquals(1, convos.size()); 4547 assertTrue(conversationWrapperContainsChannel(convos, channel)); 4548 } 4549 conversationWrapperContainsChannel(List<ConversationChannelWrapper> list, NotificationChannel expected)4550 private boolean conversationWrapperContainsChannel(List<ConversationChannelWrapper> list, 4551 NotificationChannel expected) { 4552 for (ConversationChannelWrapper ccw : list) { 4553 if (ccw.getNotificationChannel().equals(expected)) { 4554 return true; 4555 } 4556 } 4557 4558 return false; 4559 } 4560 4561 @Test testGetConversations_invalidPkg()4562 public void testGetConversations_invalidPkg() { 4563 assertThat(mHelper.getConversations("bad", 1)).isEmpty(); 4564 } 4565 4566 @Test testGetConversations_noConversations()4567 public void testGetConversations_noConversations() { 4568 NotificationChannel channel = 4569 new NotificationChannel("not_convo", "not_convo", IMPORTANCE_DEFAULT); 4570 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4571 4572 assertThat(mHelper.getConversations(PKG_O, UID_O)).isEmpty(); 4573 } 4574 4575 @Test testGetConversations_noDisabledGroups()4576 public void testGetConversations_noDisabledGroups() { 4577 NotificationChannelGroup group = new NotificationChannelGroup("a", "a"); 4578 group.setBlocked(true); 4579 mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, false); 4580 NotificationChannel parent = new NotificationChannel("parent", "p", 1); 4581 mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); 4582 4583 NotificationChannel channel = 4584 new NotificationChannel("convo", "convo", IMPORTANCE_DEFAULT); 4585 channel.setConversationId("parent", "convo"); 4586 channel.setGroup(group.getId()); 4587 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4588 4589 assertThat(mHelper.getConversations(PKG_O, UID_O)).isEmpty(); 4590 } 4591 4592 @Test testGetConversations_noDeleted()4593 public void testGetConversations_noDeleted() { 4594 NotificationChannel parent = new NotificationChannel("parent", "p", 1); 4595 mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); 4596 NotificationChannel channel = 4597 new NotificationChannel("convo", "convo", IMPORTANCE_DEFAULT); 4598 channel.setConversationId("parent", "convo"); 4599 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4600 mHelper.deleteNotificationChannel(PKG_O, UID_O, channel.getId()); 4601 4602 assertThat(mHelper.getConversations(PKG_O, UID_O)).isEmpty(); 4603 } 4604 4605 @Test testGetConversations_noDemoted()4606 public void testGetConversations_noDemoted() { 4607 NotificationChannel parent = new NotificationChannel("parent", "p", 1); 4608 mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); 4609 NotificationChannel channel = 4610 new NotificationChannel("convo", "convo", IMPORTANCE_DEFAULT); 4611 channel.setConversationId("parent", "convo"); 4612 channel.setDemoted(true); 4613 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4614 4615 assertThat(mHelper.getConversations(PKG_O, UID_O)).isEmpty(); 4616 } 4617 4618 @Test testGetConversations()4619 public void testGetConversations() { 4620 NotificationChannelGroup group = new NotificationChannelGroup("acct", "account_name"); 4621 mHelper.createNotificationChannelGroup(PKG_O, UID_O, group, true); 4622 4623 NotificationChannel messages = 4624 new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); 4625 messages.setGroup(group.getId()); 4626 mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); 4627 NotificationChannel calls = 4628 new NotificationChannel("calls", "Calls", IMPORTANCE_HIGH); 4629 mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); 4630 4631 NotificationChannel channel = 4632 new NotificationChannel("A person", "A lovely person", IMPORTANCE_DEFAULT); 4633 channel.setGroup(group.getId()); 4634 channel.setConversationId(messages.getId(), channel.getName().toString()); 4635 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4636 4637 NotificationChannel channel2 = 4638 new NotificationChannel("B person", "B fabulous person", IMPORTANCE_DEFAULT); 4639 channel2.setConversationId(calls.getId(), channel2.getName().toString()); 4640 mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); 4641 4642 Map<String, NotificationChannel> expected = new HashMap<>(); 4643 expected.put(channel.getId(), channel); 4644 expected.put(channel2.getId(), channel2); 4645 4646 Map<String, CharSequence> expectedGroup = new HashMap<>(); 4647 expectedGroup.put(channel.getId(), group.getName()); 4648 expectedGroup.put(channel2.getId(), null); 4649 4650 Map<String, CharSequence> expectedParentLabel= new HashMap<>(); 4651 expectedParentLabel.put(channel.getId(), messages.getName()); 4652 expectedParentLabel.put(channel2.getId(), calls.getName()); 4653 4654 ArrayList<ConversationChannelWrapper> convos = mHelper.getConversations(PKG_O, UID_O); 4655 assertThat(convos).hasSize(2); 4656 4657 for (ConversationChannelWrapper convo : convos) { 4658 assertThat(convo.getNotificationChannel()) 4659 .isEqualTo(expected.get(convo.getNotificationChannel().getId())); 4660 assertThat(convo.getParentChannelLabel()) 4661 .isEqualTo(expectedParentLabel.get(convo.getNotificationChannel().getId())); 4662 assertThat(convo.getGroupLabel()) 4663 .isEqualTo(expectedGroup.get(convo.getNotificationChannel().getId())); 4664 } 4665 } 4666 4667 @Test testDeleteConversations()4668 public void testDeleteConversations() { 4669 String convoId = "convo"; 4670 String convoIdC = "convoC"; 4671 NotificationChannel messages = 4672 new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT); 4673 mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false); 4674 NotificationChannel calls = 4675 new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT); 4676 mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false); 4677 4678 NotificationChannel channel = 4679 new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT); 4680 channel.setConversationId(messages.getId(), convoId); 4681 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4682 4683 NotificationChannel noMatch = 4684 new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT); 4685 noMatch.setConversationId(messages.getId(), "different convo"); 4686 mHelper.createNotificationChannel(PKG_O, UID_O, noMatch, true, false); 4687 4688 NotificationChannel channel2 = 4689 new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT); 4690 channel2.setConversationId(calls.getId(), convoId); 4691 mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false); 4692 4693 NotificationChannel channel3 = 4694 new NotificationChannel("C person msgs", "msgs from C", IMPORTANCE_DEFAULT); 4695 channel3.setConversationId(messages.getId(), convoIdC); 4696 mHelper.createNotificationChannel(PKG_O, UID_O, channel3, true, false); 4697 4698 assertEquals(channel, mHelper.getNotificationChannel(PKG_O, UID_O, channel.getId(), false)); 4699 assertEquals(channel2, 4700 mHelper.getNotificationChannel(PKG_O, UID_O, channel2.getId(), false)); 4701 List<String> deleted = mHelper.deleteConversations(PKG_O, UID_O, Set.of(convoId, convoIdC)); 4702 assertEquals(3, deleted.size()); 4703 4704 assertEquals(messages, 4705 mHelper.getNotificationChannel(PKG_O, UID_O, messages.getId(), false)); 4706 assertEquals(noMatch, 4707 mHelper.getNotificationChannel(PKG_O, UID_O, noMatch.getId(), false)); 4708 4709 assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, channel.getId(), false)); 4710 assertNull(mHelper.getNotificationChannel(PKG_O, UID_O, channel2.getId(), false)); 4711 assertEquals(channel, mHelper.getNotificationChannel(PKG_O, UID_O, channel.getId(), true)); 4712 assertEquals(channel2, 4713 mHelper.getNotificationChannel(PKG_O, UID_O, channel2.getId(), true)); 4714 4715 assertEquals(9, mLogger.getCalls().size()); 4716 assertEquals( 4717 NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED, 4718 mLogger.get(0).event); // Channel messages 4719 assertEquals( 4720 NotificationChannelLogger.NotificationChannelEvent.NOTIFICATION_CHANNEL_CREATED, 4721 mLogger.get(1).event); // Channel calls 4722 assertEquals( 4723 NotificationChannelLogger.NotificationChannelEvent 4724 .NOTIFICATION_CHANNEL_CONVERSATION_CREATED, 4725 mLogger.get(2).event); // Channel channel - Conversation A person msgs 4726 assertEquals( 4727 NotificationChannelLogger.NotificationChannelEvent 4728 .NOTIFICATION_CHANNEL_CONVERSATION_CREATED, 4729 mLogger.get(3).event); // Channel noMatch - Conversation B person msgs 4730 assertEquals( 4731 NotificationChannelLogger.NotificationChannelEvent 4732 .NOTIFICATION_CHANNEL_CONVERSATION_CREATED, 4733 mLogger.get(4).event); // Channel channel2 - Conversation A person calls 4734 assertEquals( 4735 NotificationChannelLogger.NotificationChannelEvent 4736 .NOTIFICATION_CHANNEL_CONVERSATION_CREATED, 4737 mLogger.get(5).event); // Channel channel3 - Conversation C person msgs 4738 assertEquals( 4739 NotificationChannelLogger.NotificationChannelEvent 4740 .NOTIFICATION_CHANNEL_CONVERSATION_DELETED, 4741 mLogger.get(6).event); // Delete Channel channel - Conversation A person msgs 4742 assertEquals( 4743 NotificationChannelLogger.NotificationChannelEvent 4744 .NOTIFICATION_CHANNEL_CONVERSATION_DELETED, 4745 mLogger.get(7).event); // Delete Channel channel2 - Conversation A person calls 4746 assertEquals( 4747 NotificationChannelLogger.NotificationChannelEvent 4748 .NOTIFICATION_CHANNEL_CONVERSATION_DELETED, 4749 mLogger.get(8).event); // Delete Channel channel3 - Conversation C person msgs 4750 } 4751 4752 @Test testInvalidMessageSent()4753 public void testInvalidMessageSent() { 4754 // create package preferences 4755 mHelper.canShowBadge(PKG_P, UID_P); 4756 4757 // check default value 4758 assertFalse(mHelper.isInInvalidMsgState(PKG_P, UID_P)); 4759 4760 // change it 4761 mHelper.setInvalidMessageSent(PKG_P, UID_P); 4762 assertTrue(mHelper.isInInvalidMsgState(PKG_P, UID_P)); 4763 assertTrue(mHelper.hasSentInvalidMsg(PKG_P, UID_P)); 4764 } 4765 4766 @Test testValidMessageSent()4767 public void testValidMessageSent() { 4768 // create package preferences 4769 mHelper.canShowBadge(PKG_P, UID_P); 4770 4771 // get into the bad state 4772 mHelper.setInvalidMessageSent(PKG_P, UID_P); 4773 4774 // and then fix it 4775 mHelper.setValidMessageSent(PKG_P, UID_P); 4776 4777 assertTrue(mHelper.hasSentValidMsg(PKG_P, UID_P)); 4778 assertFalse(mHelper.isInInvalidMsgState(PKG_P, UID_P)); 4779 } 4780 4781 @Test testUserDemotedInvalidMsgApp()4782 public void testUserDemotedInvalidMsgApp() { 4783 // create package preferences 4784 mHelper.canShowBadge(PKG_P, UID_P); 4785 4786 // demotion means nothing before msg notif sent 4787 mHelper.setInvalidMsgAppDemoted(PKG_P, UID_P, true); 4788 assertFalse(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P)); 4789 4790 // it's valid when incomplete msgs have been sent 4791 mHelper.setInvalidMessageSent(PKG_P, UID_P); 4792 assertTrue(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P)); 4793 4794 // and is invalid once complete msgs are sent 4795 mHelper.setValidMessageSent(PKG_P, UID_P); 4796 assertFalse(mHelper.hasUserDemotedInvalidMsgApp(PKG_P, UID_P)); 4797 } 4798 4799 @Test testValidBubbleSent()4800 public void testValidBubbleSent() { 4801 // create package preferences 4802 mHelper.canShowBadge(PKG_P, UID_P); 4803 // false by default 4804 assertFalse(mHelper.hasSentValidBubble(PKG_P, UID_P)); 4805 4806 // set something valid was sent 4807 mHelper.setValidBubbleSent(PKG_P, UID_P); 4808 assertTrue(mHelper.hasSentValidBubble(PKG_P, UID_P)); 4809 } 4810 4811 @Test testPullPackageChannelPreferencesStats()4812 public void testPullPackageChannelPreferencesStats() { 4813 String channelId = "parent"; 4814 String name = "messages"; 4815 NotificationChannel fodderA = new NotificationChannel("a", "a", IMPORTANCE_LOW); 4816 mHelper.createNotificationChannel(PKG_O, UID_O, fodderA, true, false); 4817 NotificationChannel channel = 4818 new NotificationChannel(channelId, name, IMPORTANCE_DEFAULT); 4819 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 4820 NotificationChannel fodderB = new NotificationChannel("b", "b", IMPORTANCE_HIGH); 4821 mHelper.createNotificationChannel(PKG_O, UID_O, fodderB, true, false); 4822 4823 ArrayList<StatsEvent> events = new ArrayList<>(); 4824 mHelper.pullPackageChannelPreferencesStats(events); 4825 4826 int found = 0; 4827 for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { 4828 if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES 4829 && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { 4830 ++found; 4831 assertEquals("uid", UID_O, builder.getValue(UID_FIELD_NUMBER)); 4832 assertTrue("uid annotation", builder.getBooleanAnnotation( 4833 UID_FIELD_NUMBER, ANNOTATION_ID_IS_UID)); 4834 assertEquals("importance", IMPORTANCE_DEFAULT, builder.getValue( 4835 IMPORTANCE_FIELD_NUMBER)); 4836 assertEquals("name", name, builder.getValue(CHANNEL_NAME_FIELD_NUMBER)); 4837 assertFalse("isconv", builder.getBoolean(IS_CONVERSATION_FIELD_NUMBER)); 4838 assertFalse("deleted", builder.getBoolean(IS_DELETED_FIELD_NUMBER)); 4839 } 4840 } 4841 } 4842 4843 @Test testPullPackageChannelPreferencesStats_one_to_one()4844 public void testPullPackageChannelPreferencesStats_one_to_one() { 4845 NotificationChannel channelA = new NotificationChannel("a", "a", IMPORTANCE_LOW); 4846 mHelper.createNotificationChannel(PKG_O, UID_O, channelA, true, false); 4847 NotificationChannel channelB = new NotificationChannel("b", "b", IMPORTANCE_LOW); 4848 mHelper.createNotificationChannel(PKG_O, UID_O, channelB, true, false); 4849 NotificationChannel channelC = new NotificationChannel("c", "c", IMPORTANCE_HIGH); 4850 mHelper.createNotificationChannel(PKG_O, UID_O, channelC, true, false); 4851 4852 List<String> channels = new LinkedList<>(Arrays.asList("a", "b", "c")); 4853 4854 ArrayList<StatsEvent> events = new ArrayList<>(); 4855 mHelper.pullPackageChannelPreferencesStats(events); 4856 4857 int found = 0; 4858 for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { 4859 if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES) { 4860 Object id = builder.getValue(CHANNEL_ID_FIELD_NUMBER); 4861 assertTrue("missing channel in the output", channels.contains(id)); 4862 channels.remove(id); 4863 } 4864 } 4865 assertTrue("unexpected channel in output", channels.isEmpty()); 4866 } 4867 4868 @Test testPullPackageChannelPreferencesStats_conversation()4869 public void testPullPackageChannelPreferencesStats_conversation() { 4870 String conversationId = "friend"; 4871 4872 NotificationChannel parent = 4873 new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); 4874 mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); 4875 4876 String channelId = String.format( 4877 CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), conversationId); 4878 String name = "conversation"; 4879 NotificationChannel friend = new NotificationChannel(channelId, 4880 name, IMPORTANCE_DEFAULT); 4881 friend.setConversationId(parent.getId(), conversationId); 4882 mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); 4883 4884 ArrayList<StatsEvent> events = new ArrayList<>(); 4885 mHelper.pullPackageChannelPreferencesStats(events); 4886 4887 for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { 4888 if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES 4889 && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { 4890 assertTrue("isConveration should be true", builder.getBoolean( 4891 IS_CONVERSATION_FIELD_NUMBER)); 4892 assertFalse("not demoted", builder.getBoolean( 4893 IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); 4894 assertFalse("not important", builder.getBoolean( 4895 IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); 4896 } 4897 } 4898 } 4899 4900 @Test testPullPackageChannelPreferencesStats_conversation_demoted()4901 public void testPullPackageChannelPreferencesStats_conversation_demoted() { 4902 NotificationChannel parent = 4903 new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); 4904 mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); 4905 String channelId = String.format( 4906 CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), "friend"); 4907 NotificationChannel friend = new NotificationChannel(channelId, 4908 "conversation", IMPORTANCE_DEFAULT); 4909 friend.setConversationId(parent.getId(), "friend"); 4910 friend.setDemoted(true); 4911 mHelper.createNotificationChannel(PKG_O, UID_O, friend, true, false); 4912 4913 ArrayList<StatsEvent> events = new ArrayList<>(); 4914 mHelper.pullPackageChannelPreferencesStats(events); 4915 4916 for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { 4917 if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES 4918 && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { 4919 assertTrue("isConveration should be true", builder.getBoolean( 4920 IS_CONVERSATION_FIELD_NUMBER)); 4921 assertTrue("is demoted", builder.getBoolean( 4922 IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); 4923 assertFalse("not important", builder.getBoolean( 4924 IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); 4925 } 4926 } 4927 } 4928 4929 @Test testPullPackageChannelPreferencesStats_conversation_priority()4930 public void testPullPackageChannelPreferencesStats_conversation_priority() { 4931 NotificationChannel parent = 4932 new NotificationChannel("parent", "messages", IMPORTANCE_DEFAULT); 4933 mHelper.createNotificationChannel(PKG_O, UID_O, parent, true, false); 4934 String channelId = String.format( 4935 CONVERSATION_CHANNEL_ID_FORMAT, parent.getId(), "friend"); 4936 NotificationChannel friend = new NotificationChannel(channelId, 4937 "conversation", IMPORTANCE_DEFAULT); 4938 friend.setConversationId(parent.getId(), "friend"); 4939 friend.setImportantConversation(true); 4940 mHelper.createNotificationChannel(PKG_O, UID_O, friend, false, false); 4941 4942 ArrayList<StatsEvent> events = new ArrayList<>(); 4943 mHelper.pullPackageChannelPreferencesStats(events); 4944 4945 for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { 4946 if (builder.getAtomId() == PACKAGE_NOTIFICATION_CHANNEL_PREFERENCES 4947 && channelId.equals(builder.getValue(CHANNEL_ID_FIELD_NUMBER))) { 4948 assertTrue("isConveration should be true", builder.getBoolean( 4949 IS_CONVERSATION_FIELD_NUMBER)); 4950 assertFalse("not demoted", builder.getBoolean( 4951 IS_DEMOTED_CONVERSATION_FIELD_NUMBER)); 4952 assertTrue("is important", builder.getBoolean( 4953 IS_IMPORTANT_CONVERSATION_FIELD_NUMBER)); 4954 } 4955 } 4956 } 4957 4958 @Test testPullPackagePreferencesStats_postPermissionMigration()4959 public void testPullPackagePreferencesStats_postPermissionMigration() { 4960 4961 // build a collection of app permissions that should be passed in but ignored 4962 ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>(); 4963 appPermissions.put(new Pair(1, "first"), new Pair(true, false)); // not in local prefs 4964 appPermissions.put(new Pair(3, "third"), new Pair(false, true)); // not in local prefs 4965 appPermissions.put(new Pair(UID_O, PKG_O), new Pair(false, true)); // in local prefs 4966 4967 // local preferences 4968 mHelper.canShowBadge(PKG_O, UID_O); 4969 mHelper.canShowBadge(PKG_P, UID_P); 4970 4971 // expected output. format: uid -> importance, as only uid (and not package name) 4972 // is in PackageNotificationPreferences 4973 ArrayMap<Integer, Pair<Integer, Boolean>> expected = new ArrayMap<>(); 4974 expected.put(1, new Pair(IMPORTANCE_DEFAULT, false)); 4975 expected.put(3, new Pair(IMPORTANCE_NONE, true)); 4976 expected.put(UID_O, new Pair(IMPORTANCE_NONE, true)); // banned by permissions 4977 expected.put(UID_P, new Pair(IMPORTANCE_NONE, false)); // defaults to none, false 4978 4979 ArrayList<StatsEvent> events = new ArrayList<>(); 4980 mHelper.pullPackagePreferencesStats(events, appPermissions); 4981 4982 for (WrappedSysUiStatsEvent.WrappedBuilder builder : mStatsEventBuilderFactory.builders) { 4983 if (builder.getAtomId() == PACKAGE_NOTIFICATION_PREFERENCES) { 4984 int uid = builder.getInt(PackageNotificationPreferences.UID_FIELD_NUMBER); 4985 boolean userSet = builder.getBoolean( 4986 PackageNotificationPreferences.USER_SET_IMPORTANCE_FIELD_NUMBER); 4987 4988 // if it's one of the expected ids, then make sure the importance matches 4989 assertTrue(expected.containsKey(uid)); 4990 assertThat(expected.get(uid).first).isEqualTo( 4991 builder.getInt(PackageNotificationPreferences.IMPORTANCE_FIELD_NUMBER)); 4992 assertThat(expected.get(uid).second).isEqualTo(userSet); 4993 } 4994 } 4995 } 4996 4997 @Test testUnlockNotificationChannelImportance()4998 public void testUnlockNotificationChannelImportance() { 4999 NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW); 5000 mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false); 5001 channel.lockFields(USER_LOCKED_IMPORTANCE); 5002 assertTrue((channel.getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); 5003 5004 mHelper.unlockNotificationChannelImportance(PKG_O, UID_O, channel.getId()); 5005 assertTrue((channel.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0); 5006 5007 } 5008 5009 @Test testUnlockAllNotificationChannels()5010 public void testUnlockAllNotificationChannels() { 5011 NotificationChannel channelA = new NotificationChannel("a", "a", IMPORTANCE_LOW); 5012 mHelper.createNotificationChannel(PKG_O, UID_O, channelA, true, false); 5013 NotificationChannel channelB = new NotificationChannel("b", "b", IMPORTANCE_DEFAULT); 5014 mHelper.createNotificationChannel(PKG_P, UID_P, channelB, true, false); 5015 NotificationChannel channelC = new NotificationChannel("c", "c", IMPORTANCE_HIGH); 5016 mHelper.createNotificationChannel(PKG_P, UID_O, channelC, false, false); 5017 5018 channelA.lockFields(USER_LOCKED_IMPORTANCE); 5019 channelB.lockFields(USER_LOCKED_IMPORTANCE); 5020 channelC.lockFields(USER_LOCKED_IMPORTANCE); 5021 5022 assertTrue((channelA.getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); 5023 assertTrue((channelB.getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); 5024 assertTrue((channelC.getUserLockedFields() & USER_LOCKED_IMPORTANCE) != 0); 5025 5026 mHelper.unlockAllNotificationChannels(); 5027 assertTrue((channelA.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0); 5028 assertTrue((channelB.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0); 5029 assertTrue((channelC.getUserLockedFields() & USER_LOCKED_IMPORTANCE) == 0); 5030 } 5031 } 5032