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