1 /* 2 * Copyright (C) 2023 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 17 package android.app.notification.current.cts; 18 19 import static android.Manifest.permission.POST_NOTIFICATIONS; 20 import static android.Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL; 21 import static android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS; 22 import static android.app.NotificationManager.ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED; 23 import static android.app.NotificationManager.ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED; 24 import static android.app.NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED; 25 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ACTIVATED; 26 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DEACTIVATED; 27 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED; 28 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED; 29 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_UNKNOWN; 30 import static android.app.NotificationManager.EXTRA_AUTOMATIC_ZEN_RULE_ID; 31 import static android.app.NotificationManager.EXTRA_AUTOMATIC_ZEN_RULE_STATUS; 32 import static android.app.NotificationManager.INTERRUPTION_FILTER_ALARMS; 33 import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL; 34 import static android.app.NotificationManager.INTERRUPTION_FILTER_NONE; 35 import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; 36 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE; 37 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT; 38 import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE; 39 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS; 40 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS; 41 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS; 42 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_EVENTS; 43 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA; 44 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES; 45 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS; 46 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS; 47 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM; 48 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED; 49 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT; 50 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 51 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS; 52 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST; 53 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK; 54 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF; 55 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON; 56 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; 57 import static android.content.pm.PackageManager.FEATURE_AUTOMOTIVE; 58 import static android.content.pm.PackageManager.FEATURE_WATCH; 59 import static android.content.pm.PackageManager.MATCH_DEFAULT_ONLY; 60 import static android.service.notification.Condition.STATE_FALSE; 61 import static android.service.notification.Condition.STATE_TRUE; 62 63 import static com.google.common.base.Preconditions.checkNotNull; 64 import static com.google.common.truth.Truth.assertThat; 65 66 import static org.junit.Assert.assertEquals; 67 import static org.junit.Assert.assertFalse; 68 import static org.junit.Assert.assertNotNull; 69 import static org.junit.Assert.assertNull; 70 import static org.junit.Assert.assertThrows; 71 import static org.junit.Assert.assertTrue; 72 import static org.junit.Assume.assumeFalse; 73 import static org.junit.Assume.assumeTrue; 74 75 import android.Manifest; 76 import android.app.AutomaticZenRule; 77 import android.app.Flags; 78 import android.app.Notification; 79 import android.app.NotificationChannel; 80 import android.app.NotificationManager; 81 import android.app.UiModeManager; 82 import android.app.WallpaperManager; 83 import android.app.compat.CompatChanges; 84 import android.app.cts.CtsAppTestUtils; 85 import android.app.stubs.AutomaticZenRuleActivity; 86 import android.app.stubs.GetResultActivity; 87 import android.app.stubs.R; 88 import android.app.stubs.shared.NotificationHelper.SEARCH_TYPE; 89 import android.content.ComponentName; 90 import android.content.ContentProviderOperation; 91 import android.content.Intent; 92 import android.content.OperationApplicationException; 93 import android.content.pm.PackageManager; 94 import android.content.pm.ResolveInfo; 95 import android.database.Cursor; 96 import android.hardware.display.ColorDisplayManager; 97 import android.media.AudioAttributes; 98 import android.media.AudioManager; 99 import android.net.Uri; 100 import android.os.Build; 101 import android.os.PowerManager; 102 import android.os.RemoteException; 103 import android.permission.PermissionManager; 104 import android.permission.cts.PermissionUtils; 105 import android.platform.test.annotations.RequiresFlagsDisabled; 106 import android.platform.test.annotations.RequiresFlagsEnabled; 107 import android.provider.ContactsContract; 108 import android.provider.Settings; 109 import android.service.notification.Condition; 110 import android.service.notification.NotificationListenerService; 111 import android.service.notification.StatusBarNotification; 112 import android.service.notification.ZenDeviceEffects; 113 import android.service.notification.ZenPolicy; 114 import android.util.Log; 115 116 import androidx.test.platform.app.InstrumentationRegistry; 117 import androidx.test.runner.AndroidJUnit4; 118 import androidx.test.uiautomator.UiDevice; 119 120 import com.android.bedstead.harrier.DeviceState; 121 import com.android.bedstead.multiuser.annotations.RequireNotVisibleBackgroundUsers; 122 import com.android.bedstead.multiuser.annotations.RequireRunNotOnVisibleBackgroundNonProfileUser; 123 import com.android.compatibility.common.util.ScreenUtils; 124 import com.android.compatibility.common.util.SystemUtil; 125 import com.android.modules.utils.build.SdkLevel; 126 127 import com.google.common.collect.ImmutableSet; 128 import com.google.common.collect.Iterables; 129 130 import org.junit.After; 131 import org.junit.Before; 132 import org.junit.ClassRule; 133 import org.junit.Rule; 134 import org.junit.Test; 135 import org.junit.runner.RunWith; 136 137 import java.time.Duration; 138 import java.util.ArrayList; 139 import java.util.List; 140 import java.util.Map; 141 import java.util.Objects; 142 143 /** 144 * Tests zen/dnd related logic in NotificationManager. 145 */ 146 @RunWith(AndroidJUnit4.class) 147 // TODO(b/355106764): Remove the annotation once zen/dnd supports visible background users. 148 @RequireRunNotOnVisibleBackgroundNonProfileUser(reason = "zen/dnd does not support visible" 149 + " background users at the moment") 150 public class NotificationManagerZenTest extends BaseNotificationManagerTest { 151 152 private static final String TAG = NotificationManagerZenTest.class.getSimpleName(); 153 154 @ClassRule 155 @Rule 156 public static final DeviceState sDeviceState = new DeviceState(); 157 158 private static final String NOTIFICATION_CHANNEL_ID = TAG; 159 private static final String NOTIFICATION_CHANNEL_ID_NOISY = TAG + "/noisy"; 160 private static final String NOTIFICATION_CHANNEL_ID_MEDIA = TAG + "/media"; 161 private static final String NOTIFICATION_CHANNEL_ID_GAME = TAG + "/game"; 162 private static final String NOTIFICATION_CHANNEL_ID_PRIORITY = TAG + "/priority"; 163 private static final String ALICE = "Alice"; 164 private static final String ALICE_PHONE = "+16175551212"; 165 private static final String ALICE_EMAIL = "alice@_foo._bar"; 166 private static final String BOB = "Bob"; 167 private static final String BOB_PHONE = "+16505551212"; 168 private static final String BOB_EMAIL = "bob@_foo._bar"; 169 private static final String CHARLIE = "Charlie"; 170 private static final String CHARLIE_PHONE = "+13305551212"; 171 private static final String CHARLIE_EMAIL = "charlie@_foo._bar"; 172 private static final int MODE_URI = 1; 173 private static final int MODE_PHONE = 2; 174 private static final int MODE_EMAIL = 3; 175 private static final int SEND_A = 0x1; 176 private static final int SEND_B = 0x2; 177 private static final int SEND_C = 0x4; 178 private static final int SEND_ALL = SEND_A | SEND_B | SEND_C; 179 private static final int MATCHES_CALL_FILTER_NOT_PERMITTED = 0; 180 private static final int MATCHES_CALL_FILTER_PERMITTED = 1; 181 private static final String MATCHES_CALL_FILTER_CLASS = 182 TEST_APP + ".MatchesCallFilterTestActivity"; 183 private static final String MINIMAL_LISTENER_CLASS = TEST_APP + ".TestNotificationListener"; 184 private static final int ZEN_EFFECTS_WAIT_MS = 600; 185 186 private final String NAME = "name"; 187 private ComponentName CONFIG_ACTIVITY; 188 private final ZenPolicy POLICY = new ZenPolicy.Builder().allowAlarms(true).build(); 189 private final Uri CONDITION_ID = new Uri.Builder().scheme("scheme") 190 .authority("authority") 191 .appendPath("path") 192 .appendPath("test") 193 .build(); 194 private static final String TRIGGER_DESC = "Triggered mysteriously"; 195 private static final int UNRESTRICTED_TYPE = AutomaticZenRule.TYPE_IMMERSIVE; // Freely usable. 196 private static final boolean ALLOW_MANUAL = true; 197 private static final int ICON_RES_ID = 198 android.app.notification.current.cts.R.drawable.ic_android; 199 private NotificationManager.Policy mOriginalPolicy; 200 private ZenPolicy mDefaultPolicy; 201 202 @Before setUp()203 public void setUp() throws Exception { 204 PermissionUtils.grantPermission(mContext.getPackageName(), POST_NOTIFICATIONS); 205 206 CONFIG_ACTIVITY = new ComponentName(mContext, AutomaticZenRuleActivity.class); 207 208 mListener = mNotificationHelper.enableListener(STUB_PACKAGE_NAME); 209 assertNotNull(mListener); 210 211 createChannels(); 212 213 // Set up a known DND state for all tests: 214 // * DND off. 215 // * Alarms, Media, Calls (starred), Messages (starred), Repeat Calls, Conversations 216 // (starred) allowed. 217 // * Some suppressed visual effects. 218 // (using the SystemUI permission so we're certain to update global state). 219 runAsSystemUi(() -> { 220 mOriginalPolicy = mNotificationManager.getNotificationPolicy(); 221 222 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 223 PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_CALLS 224 | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_REPEAT_CALLERS 225 | PRIORITY_CATEGORY_CONVERSATIONS, PRIORITY_SENDERS_STARRED, 226 PRIORITY_SENDERS_STARRED, 227 SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_LIGHTS 228 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT, 229 CONVERSATION_SENDERS_IMPORTANT)); 230 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL); 231 232 // Also get and cache the default policy for comparison later. 233 if (Flags.modesApi()) { 234 if (Flags.modesUi()) { 235 mDefaultPolicy = mNotificationManager.getDefaultZenPolicy(); 236 } else { 237 // Pre-modes_ui, the "default policy" (for the purposes of merging with missing 238 // or underspecified policies) is actually the manual policy. Thus we construct 239 // a ZenPolicy matching the previous setNotificationPolicy() call. 240 mDefaultPolicy = new ZenPolicy.Builder() 241 .allowPriorityChannels(true) 242 .disallowAllSounds() 243 .allowAlarms(true) 244 .allowMedia(true) 245 .allowCalls(ZenPolicy.PEOPLE_TYPE_STARRED) 246 .allowMessages(ZenPolicy.PEOPLE_TYPE_STARRED) 247 .allowConversations(ZenPolicy.CONVERSATION_SENDERS_IMPORTANT) 248 .allowRepeatCallers(true) 249 .showAllVisualEffects() 250 .showInAmbientDisplay(false) 251 .showPeeking(false) 252 .showLights(false) 253 .showFullScreenIntent(false) 254 .build(); 255 } 256 } 257 }); 258 } 259 260 @After tearDown()261 public void tearDown() throws Exception { 262 // Use test API to prevent PermissionManager from killing the test process when revoking 263 // permission. 264 SystemUtil.runWithShellPermissionIdentity( 265 () -> mContext.getSystemService(PermissionManager.class) 266 .revokePostNotificationPermissionWithoutKillForTest( 267 mContext.getPackageName(), 268 android.os.Process.myUserHandle().getIdentifier()), 269 REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL, 270 REVOKE_RUNTIME_PERMISSIONS); 271 272 // Restore to the previous DND state. 273 runAsSystemUi(() -> { 274 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL); 275 if (mOriginalPolicy != null) { 276 mNotificationManager.setNotificationPolicy(mOriginalPolicy); 277 } 278 }); 279 280 final ArrayList<ContentProviderOperation> operationList = new ArrayList<>(); 281 Uri aliceUri = lookupContact(ALICE_PHONE); 282 if (aliceUri != null) { 283 operationList.add(ContentProviderOperation.newDelete(aliceUri).build()); 284 } 285 Uri bobUri = lookupContact(BOB_PHONE); 286 if (bobUri != null) { 287 operationList.add(ContentProviderOperation.newDelete(bobUri).build()); 288 } 289 Uri charlieUri = lookupContact(CHARLIE_PHONE); 290 if (charlieUri != null) { 291 operationList.add(ContentProviderOperation.newDelete(charlieUri).build()); 292 } 293 if (aliceUri != null || bobUri != null || charlieUri != null) { 294 try { 295 mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList); 296 } catch (RemoteException e) { 297 Log.e(TAG, String.format("%s: %s", e, e.getMessage())); 298 } catch (OperationApplicationException e) { 299 Log.e(TAG, String.format("%s: %s", e, e.getMessage())); 300 } 301 } 302 303 deleteAllAutomaticZenRules(); 304 305 if (mListener != null) { 306 // setUp asserts mListener isn't null, but tearDown will still run after that assertion 307 // failure. 308 mListener.resetData(); 309 mNotificationHelper.disableListener(STUB_PACKAGE_NAME); 310 } 311 312 deleteChannels(); 313 } 314 sleep()315 private void sleep() { 316 try { 317 Thread.sleep(500); 318 } catch (InterruptedException ignored) { 319 } 320 } 321 // usePriorities true: B, C, A 322 // usePriorities false: 323 // MODE_NONE: C, B, A 324 // otherwise: A, B ,C sendNotifications(int uriMode, boolean usePriorities, boolean noisy)325 private void sendNotifications(int uriMode, boolean usePriorities, boolean noisy) { 326 sendNotifications(SEND_ALL, uriMode, usePriorities, noisy); 327 } 328 sendNotifications(int which, int uriMode, boolean usePriorities, boolean noisy)329 private void sendNotifications(int which, int uriMode, boolean usePriorities, boolean noisy) { 330 // C, B, A when sorted by time. Times must be in the past 331 long whenA = System.currentTimeMillis() - 4000000L; 332 long whenB = System.currentTimeMillis() - 2000000L; 333 long whenC = System.currentTimeMillis() - 1000000L; 334 335 // B, C, A when sorted by priorities 336 int priorityA = usePriorities ? Notification.PRIORITY_MIN : Notification.PRIORITY_DEFAULT; 337 int priorityB = usePriorities ? Notification.PRIORITY_MAX : Notification.PRIORITY_DEFAULT; 338 int priorityC = usePriorities ? Notification.PRIORITY_LOW : Notification.PRIORITY_DEFAULT; 339 340 final String channelId = noisy ? NOTIFICATION_CHANNEL_ID_NOISY : NOTIFICATION_CHANNEL_ID; 341 342 Uri aliceUri = lookupContact(ALICE_PHONE); 343 Uri bobUri = lookupContact(BOB_PHONE); 344 Uri charlieUri = lookupContact(CHARLIE_PHONE); 345 if ((which & SEND_B) != 0) { 346 Notification.Builder bob = new Notification.Builder(mContext, channelId) 347 .setContentTitle(BOB) 348 .setContentText(BOB) 349 .setSmallIcon(android.R.drawable.sym_def_app_icon) 350 .setPriority(priorityB) 351 .setCategory(Notification.CATEGORY_MESSAGE) 352 .setWhen(whenB); 353 addPerson(uriMode, bob, bobUri, BOB_PHONE, BOB_EMAIL); 354 mNotificationManager.notify(BOB, 2, bob.build()); 355 } 356 if ((which & SEND_C) != 0) { 357 Notification.Builder charlie = 358 new Notification.Builder(mContext, channelId) 359 .setContentTitle(CHARLIE) 360 .setContentText(CHARLIE) 361 .setSmallIcon(android.R.drawable.sym_def_app_icon) 362 .setPriority(priorityC) 363 .setCategory(Notification.CATEGORY_MESSAGE) 364 .setWhen(whenC); 365 addPerson(uriMode, charlie, charlieUri, CHARLIE_PHONE, CHARLIE_EMAIL); 366 mNotificationManager.notify(CHARLIE, 3, charlie.build()); 367 } 368 if ((which & SEND_A) != 0) { 369 Notification.Builder alice = new Notification.Builder(mContext, channelId) 370 .setContentTitle(ALICE) 371 .setContentText(ALICE) 372 .setSmallIcon(android.R.drawable.sym_def_app_icon) 373 .setPriority(priorityA) 374 .setCategory(Notification.CATEGORY_MESSAGE) 375 .setWhen(whenA); 376 addPerson(uriMode, alice, aliceUri, ALICE_PHONE, ALICE_EMAIL); 377 mNotificationManager.notify(ALICE, 1, alice.build()); 378 } 379 380 mNotificationHelper.findPostedNotification(ALICE, 1, SEARCH_TYPE.POSTED); 381 mNotificationHelper.findPostedNotification(BOB, 2, SEARCH_TYPE.POSTED); 382 mNotificationHelper.findPostedNotification(CHARLIE, 3, SEARCH_TYPE.POSTED); 383 } 384 sendEventAlarmReminderNotifications(int which)385 private void sendEventAlarmReminderNotifications(int which) { 386 long when = System.currentTimeMillis() - 4000000L; 387 final String channelId = NOTIFICATION_CHANNEL_ID; 388 389 // Event notification to Alice 390 if ((which & SEND_A) != 0) { 391 Notification.Builder alice = new Notification.Builder(mContext, channelId) 392 .setContentTitle(ALICE) 393 .setContentText(ALICE) 394 .setSmallIcon(android.R.drawable.sym_def_app_icon) 395 .setCategory(Notification.CATEGORY_EVENT) 396 .setWhen(when); 397 mNotificationManager.notify(ALICE, 4, alice.build()); 398 } 399 400 // Alarm notification to Bob 401 if ((which & SEND_B) != 0) { 402 Notification.Builder bob = new Notification.Builder(mContext, channelId) 403 .setContentTitle(BOB) 404 .setContentText(BOB) 405 .setSmallIcon(android.R.drawable.sym_def_app_icon) 406 .setCategory(Notification.CATEGORY_ALARM) 407 .setWhen(when); 408 mNotificationManager.notify(BOB, 5, bob.build()); 409 } 410 411 // Reminder notification to Charlie 412 if ((which & SEND_C) != 0) { 413 Notification.Builder charlie = 414 new Notification.Builder(mContext, channelId) 415 .setContentTitle(CHARLIE) 416 .setContentText(CHARLIE) 417 .setSmallIcon(android.R.drawable.sym_def_app_icon) 418 .setCategory(Notification.CATEGORY_REMINDER) 419 .setWhen(when); 420 mNotificationManager.notify(CHARLIE, 6, charlie.build()); 421 } 422 423 mNotificationHelper.findPostedNotification(ALICE, 4, SEARCH_TYPE.POSTED); 424 mNotificationHelper.findPostedNotification(BOB, 5, SEARCH_TYPE.POSTED); 425 mNotificationHelper.findPostedNotification(CHARLIE, 6, SEARCH_TYPE.POSTED); 426 } 427 sendAlarmOtherMediaNotifications(int which)428 private void sendAlarmOtherMediaNotifications(int which) { 429 long when = System.currentTimeMillis() - 4000000L; 430 final String channelId = NOTIFICATION_CHANNEL_ID; 431 432 // Alarm notification to Alice 433 if ((which & SEND_A) != 0) { 434 Notification.Builder alice = new Notification.Builder(mContext, channelId) 435 .setContentTitle(ALICE) 436 .setContentText(ALICE) 437 .setSmallIcon(android.R.drawable.sym_def_app_icon) 438 .setCategory(Notification.CATEGORY_ALARM) 439 .setWhen(when); 440 mNotificationManager.notify(ALICE, 7, alice.build()); 441 } 442 443 // "Other" notification to Bob 444 if ((which & SEND_B) != 0) { 445 Notification.Builder bob = new Notification.Builder(mContext, 446 NOTIFICATION_CHANNEL_ID_GAME) 447 .setContentTitle(BOB) 448 .setContentText(BOB) 449 .setSmallIcon(android.R.drawable.sym_def_app_icon) 450 .setWhen(when); 451 mNotificationManager.notify(BOB, 8, bob.build()); 452 } 453 454 // Media notification to Charlie 455 if ((which & SEND_C) != 0) { 456 Notification.Builder charlie = 457 new Notification.Builder(mContext, NOTIFICATION_CHANNEL_ID_MEDIA) 458 .setContentTitle(CHARLIE) 459 .setContentText(CHARLIE) 460 .setSmallIcon(android.R.drawable.sym_def_app_icon) 461 .setWhen(when); 462 mNotificationManager.notify(CHARLIE, 9, charlie.build()); 463 } 464 465 mNotificationHelper.findPostedNotification(ALICE, 7, SEARCH_TYPE.POSTED); 466 mNotificationHelper.findPostedNotification(BOB, 8, SEARCH_TYPE.POSTED); 467 mNotificationHelper.findPostedNotification(CHARLIE, 9, SEARCH_TYPE.POSTED); 468 } 469 hasReadContactsPermission(String pkgName)470 private boolean hasReadContactsPermission(String pkgName) { 471 return mPackageManager.checkPermission(Manifest.permission.READ_CONTACTS, pkgName) 472 == PackageManager.PERMISSION_GRANTED; 473 } 474 toggleReadContactsPermission(String pkgName, boolean on)475 private void toggleReadContactsPermission(String pkgName, boolean on) { 476 SystemUtil.runWithShellPermissionIdentity(() -> { 477 if (on) { 478 mInstrumentation.getUiAutomation().grantRuntimePermission(pkgName, 479 Manifest.permission.READ_CONTACTS); 480 } else { 481 mInstrumentation.getUiAutomation().revokeRuntimePermission(pkgName, 482 Manifest.permission.READ_CONTACTS); 483 } 484 }); 485 } 486 487 // Creates a GetResultActivity into which one can call startActivityForResult with 488 // in order to test the outcome of an activity that returns a result code. setUpGetResultActivity()489 private GetResultActivity setUpGetResultActivity() { 490 final Intent intent = new Intent(mContext, GetResultActivity.class); 491 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 492 GetResultActivity activity = (GetResultActivity) mInstrumentation.startActivitySync(intent); 493 mInstrumentation.waitForIdleSync(); 494 activity.clearResult(); 495 return activity; 496 } 497 addPerson(int mode, Notification.Builder note, Uri uri, String phone, String email)498 private void addPerson(int mode, Notification.Builder note, 499 Uri uri, String phone, String email) { 500 if (mode == MODE_URI && uri != null) { 501 note.addPerson(uri.toString()); 502 } else if (mode == MODE_PHONE) { 503 note.addPerson(Uri.fromParts("tel", phone, null).toString()); 504 } else if (mode == MODE_EMAIL) { 505 note.addPerson(Uri.fromParts("mailto", email, null).toString()); 506 } 507 } 508 insertSingleContact(String name, String phone, String email, boolean starred)509 private void insertSingleContact(String name, String phone, String email, boolean starred) { 510 final ArrayList<ContentProviderOperation> operationList = 511 new ArrayList<ContentProviderOperation>(); 512 ContentProviderOperation.Builder builder = 513 ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI); 514 builder.withValue(ContactsContract.RawContacts.STARRED, starred ? 1 : 0); 515 operationList.add(builder.build()); 516 517 builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); 518 builder.withValueBackReference( 519 ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0); 520 builder.withValue(ContactsContract.Data.MIMETYPE, 521 ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE); 522 builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name); 523 operationList.add(builder.build()); 524 525 if (phone != null) { 526 builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); 527 builder.withValueBackReference( 528 ContactsContract.CommonDataKinds.Phone.RAW_CONTACT_ID, 0); 529 builder.withValue(ContactsContract.Data.MIMETYPE, 530 ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE); 531 builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, 532 ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE); 533 builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, phone); 534 builder.withValue(ContactsContract.Data.IS_PRIMARY, 1); 535 operationList.add(builder.build()); 536 } 537 if (email != null) { 538 builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI); 539 builder.withValueBackReference( 540 ContactsContract.CommonDataKinds.Email.RAW_CONTACT_ID, 0); 541 builder.withValue(ContactsContract.Data.MIMETYPE, 542 ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE); 543 builder.withValue(ContactsContract.CommonDataKinds.Email.TYPE, 544 ContactsContract.CommonDataKinds.Email.TYPE_HOME); 545 builder.withValue(ContactsContract.CommonDataKinds.Email.DATA, email); 546 operationList.add(builder.build()); 547 } 548 549 try { 550 mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList); 551 } catch (RemoteException e) { 552 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); 553 } catch (OperationApplicationException e) { 554 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); 555 } 556 } 557 lookupContact(String phone)558 private Uri lookupContact(String phone) { 559 Cursor c = null; 560 try { 561 Uri phoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, 562 Uri.encode(phone)); 563 String[] projection = new String[] { ContactsContract.Contacts._ID, 564 ContactsContract.Contacts.LOOKUP_KEY }; 565 c = mContext.getContentResolver().query(phoneUri, projection, null, null, null); 566 if (c != null && c.getCount() > 0) { 567 c.moveToFirst(); 568 int lookupIdx = c.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY); 569 int idIdx = c.getColumnIndex(ContactsContract.Contacts._ID); 570 String lookupKey = c.getString(lookupIdx); 571 long contactId = c.getLong(idIdx); 572 return ContactsContract.Contacts.getLookupUri(contactId, lookupKey); 573 } 574 } catch (Throwable t) { 575 Log.w(TAG, "Problem getting content resolver or performing contacts query.", t); 576 } finally { 577 if (c != null) { 578 c.close(); 579 } 580 } 581 return null; 582 } 583 isStarred(Uri uri)584 private boolean isStarred(Uri uri) { 585 Cursor c = null; 586 boolean starred = false; 587 try { 588 String[] projection = new String[] { ContactsContract.Contacts.STARRED }; 589 c = mContext.getContentResolver().query(uri, projection, null, null, null); 590 if (c != null && c.getCount() > 0) { 591 int starredIdx = c.getColumnIndex(ContactsContract.Contacts.STARRED); 592 while (c.moveToNext()) { 593 starred |= c.getInt(starredIdx) == 1; 594 } 595 } 596 } catch (Throwable t) { 597 Log.w(TAG, "Problem getting content resolver or performing contacts query.", t); 598 } finally { 599 if (c != null) { 600 c.close(); 601 } 602 } 603 return starred; 604 } 605 createChannels()606 private void createChannels() { 607 NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, 608 NOTIFICATION_CHANNEL_ID, NotificationManager.IMPORTANCE_MIN); 609 mNotificationManager.createNotificationChannel(channel); 610 NotificationChannel noisyChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID_NOISY, 611 NOTIFICATION_CHANNEL_ID_NOISY, NotificationManager.IMPORTANCE_HIGH); 612 noisyChannel.enableVibration(true); 613 mNotificationManager.createNotificationChannel(noisyChannel); 614 NotificationChannel mediaChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID_MEDIA, 615 NOTIFICATION_CHANNEL_ID_MEDIA, NotificationManager.IMPORTANCE_HIGH); 616 AudioAttributes.Builder aa = new AudioAttributes.Builder() 617 .setUsage(AudioAttributes.USAGE_MEDIA); 618 mediaChannel.setSound(null, aa.build()); 619 mNotificationManager.createNotificationChannel(mediaChannel); 620 NotificationChannel gameChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID_GAME, 621 NOTIFICATION_CHANNEL_ID_GAME, NotificationManager.IMPORTANCE_HIGH); 622 AudioAttributes.Builder aa2 = new AudioAttributes.Builder() 623 .setUsage(AudioAttributes.USAGE_GAME); 624 gameChannel.setSound(null, aa2.build()); 625 mNotificationManager.createNotificationChannel(gameChannel); 626 if (Flags.modesApi()) { 627 // "Priority" channel has canBypassDnd set to true. 628 NotificationChannel priorityChannel = new NotificationChannel( 629 NOTIFICATION_CHANNEL_ID_PRIORITY, NOTIFICATION_CHANNEL_ID_PRIORITY, 630 NotificationManager.IMPORTANCE_HIGH); 631 priorityChannel.setBypassDnd(true); 632 mNotificationManager.createNotificationChannel(priorityChannel); 633 } 634 } 635 deleteChannels()636 private void deleteChannels() { 637 mNotificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID); 638 mNotificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID_NOISY); 639 mNotificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID_MEDIA); 640 mNotificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID_GAME); 641 if (Flags.modesApi()) { 642 mNotificationManager.deleteNotificationChannel(NOTIFICATION_CHANNEL_ID_PRIORITY); 643 } 644 } 645 deleteAllAutomaticZenRules()646 private void deleteAllAutomaticZenRules() { 647 Map<String, AutomaticZenRule> rules = mNotificationManager.getAutomaticZenRules(); 648 for (String ruleId : rules.keySet()) { 649 // Delete rules "as system" so they are not preserved. 650 // Otherwise, if updated with fromUser=true and then deleted "as app", they might be 651 // resurrected by other tests, making the outcome order-dependent. 652 runAsSystemUi(() -> mNotificationManager.removeAutomaticZenRule(ruleId)); 653 } 654 } 655 deleteSingleContact(Uri uri)656 private void deleteSingleContact(Uri uri) { 657 final ArrayList<ContentProviderOperation> operationList = 658 new ArrayList<ContentProviderOperation>(); 659 operationList.add(ContentProviderOperation.newDelete(uri).build()); 660 try { 661 mContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operationList); 662 } catch (RemoteException e) { 663 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); 664 } catch (OperationApplicationException e) { 665 Log.e(TAG, String.format("%s: %s", e.toString(), e.getMessage())); 666 } 667 } 668 findTagInKeys(String tag, List<String> orderedKeys)669 private int findTagInKeys(String tag, List<String> orderedKeys) { 670 for (int i = 0; i < orderedKeys.size(); i++) { 671 if (orderedKeys.get(i).contains(tag)) { 672 return i; 673 } 674 } 675 return -1; 676 } 677 678 // Simple helper function to take a phone number's string representation and make a tel: uri makePhoneUri(String phone)679 private Uri makePhoneUri(String phone) { 680 return new Uri.Builder() 681 .scheme("tel") 682 .encodedOpaquePart(phone) // don't re-encode anything passed in 683 .build(); 684 } 685 686 // Returns whether ZenPolicies are equivalent after any unset fields are set to the defaults. doPoliciesMatchWithDefaults(ZenPolicy a, ZenPolicy b)687 private boolean doPoliciesMatchWithDefaults(ZenPolicy a, ZenPolicy b) { 688 return Objects.equals(mDefaultPolicy.overwrittenWith(a), mDefaultPolicy.overwrittenWith(b)); 689 } 690 createRule(String name, int filter)691 private AutomaticZenRule createRule(String name, int filter) { 692 return new AutomaticZenRule(name, null, 693 new ComponentName(mContext, AutomaticZenRuleActivity.class), 694 new Uri.Builder().scheme("scheme") 695 .appendPath("path") 696 .appendQueryParameter("fake_rule", "fake_value") 697 .build(), null, filter, true); 698 } 699 createRule(String name)700 private AutomaticZenRule createRule(String name) { 701 return createRule(name, INTERRUPTION_FILTER_PRIORITY); 702 } 703 704 // TESTS START 705 706 @Test 707 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) 708 @RequiresFlagsDisabled(Flags.FLAG_MODES_UI) testAreAutomaticZenRulesUserManaged_flagsOff()709 public void testAreAutomaticZenRulesUserManaged_flagsOff() { 710 assertFalse(mNotificationManager.areAutomaticZenRulesUserManaged()); 711 } 712 713 @Test 714 @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI}) testAreAutomaticZenRulesUserManaged_flagsOn()715 public void testAreAutomaticZenRulesUserManaged_flagsOn() { 716 if (mPackageManager.hasSystemFeature(FEATURE_AUTOMOTIVE) 717 || mPackageManager.hasSystemFeature(FEATURE_WATCH)) { 718 assertFalse(mNotificationManager.areAutomaticZenRulesUserManaged()); 719 } else { 720 assertTrue(mNotificationManager.areAutomaticZenRulesUserManaged()); 721 } 722 } 723 724 @Test testNotificationPolicyVisualEffectsEqual()725 public void testNotificationPolicyVisualEffectsEqual() { 726 NotificationManager.Policy policy = new NotificationManager.Policy(0, 0, 0, 727 SUPPRESSED_EFFECT_SCREEN_ON); 728 NotificationManager.Policy policy2 = new NotificationManager.Policy(0, 0, 0, 729 SUPPRESSED_EFFECT_PEEK); 730 assertTrue(policy.equals(policy2)); 731 assertTrue(policy2.equals(policy)); 732 733 policy = new NotificationManager.Policy(0, 0, 0, 734 SUPPRESSED_EFFECT_SCREEN_ON); 735 policy2 = new NotificationManager.Policy(0, 0, 0, 736 0); 737 assertFalse(policy.equals(policy2)); 738 assertFalse(policy2.equals(policy)); 739 740 policy = new NotificationManager.Policy(0, 0, 0, 741 SUPPRESSED_EFFECT_SCREEN_OFF); 742 policy2 = new NotificationManager.Policy(0, 0, 0, 743 SUPPRESSED_EFFECT_FULL_SCREEN_INTENT | SUPPRESSED_EFFECT_AMBIENT 744 | SUPPRESSED_EFFECT_LIGHTS); 745 assertTrue(policy.equals(policy2)); 746 assertTrue(policy2.equals(policy)); 747 748 policy = new NotificationManager.Policy(0, 0, 0, 749 SUPPRESSED_EFFECT_SCREEN_OFF); 750 policy2 = new NotificationManager.Policy(0, 0, 0, 751 SUPPRESSED_EFFECT_LIGHTS); 752 assertFalse(policy.equals(policy2)); 753 assertFalse(policy2.equals(policy)); 754 } 755 756 @Test testGetSuppressedVisualEffectsOff_ranking()757 public void testGetSuppressedVisualEffectsOff_ranking() throws Exception { 758 mListener = mNotificationHelper.enableListener(STUB_PACKAGE_NAME); 759 assertNotNull(mListener); 760 761 final int notificationId = 1; 762 sendNotification(notificationId, R.drawable.black); 763 Thread.sleep(500); // wait for notification listener to receive notification 764 765 NotificationListenerService.RankingMap rankingMap = mListener.mRankingMap; 766 NotificationListenerService.Ranking outRanking = 767 new NotificationListenerService.Ranking(); 768 769 for (String key : rankingMap.getOrderedKeys()) { 770 if (key.contains(mListener.getPackageName())) { 771 rankingMap.getRanking(key, outRanking); 772 773 // check notification key match 774 assertEquals(0, outRanking.getSuppressedVisualEffects()); 775 } 776 } 777 } 778 779 @Test testGetSuppressedVisualEffects_ranking()780 public void testGetSuppressedVisualEffects_ranking() throws Exception { 781 final int originalFilter = mNotificationManager.getCurrentInterruptionFilter(); 782 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 783 try { 784 mListener = mNotificationHelper.enableListener(STUB_PACKAGE_NAME); 785 assertNotNull(mListener); 786 787 toggleNotificationPolicyAccess(mContext.getPackageName(), 788 InstrumentationRegistry.getInstrumentation(), true); 789 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) { 790 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0, 791 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK)); 792 } else { 793 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0, 794 SUPPRESSED_EFFECT_SCREEN_ON)); 795 } 796 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 797 798 final int notificationId = 1; 799 // update notification 800 sendNotification(notificationId, R.drawable.black); 801 Thread.sleep(500); // wait for notification listener to receive notification 802 803 NotificationListenerService.RankingMap rankingMap = mListener.mRankingMap; 804 NotificationListenerService.Ranking outRanking = 805 new NotificationListenerService.Ranking(); 806 807 for (String key : rankingMap.getOrderedKeys()) { 808 if (key.contains(mListener.getPackageName())) { 809 rankingMap.getRanking(key, outRanking); 810 811 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) { 812 assertEquals(SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_PEEK, 813 outRanking.getSuppressedVisualEffects()); 814 } else { 815 assertEquals(SUPPRESSED_EFFECT_SCREEN_ON, 816 outRanking.getSuppressedVisualEffects()); 817 } 818 } 819 } 820 } finally { 821 // reset notification policy 822 mNotificationManager.setInterruptionFilter(originalFilter); 823 mNotificationManager.setNotificationPolicy(origPolicy); 824 } 825 826 } 827 828 @Test testConsolidatedNotificationPolicy()829 public void testConsolidatedNotificationPolicy() throws Exception { 830 final int originalFilter = mNotificationManager.getCurrentInterruptionFilter(); 831 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 832 try { 833 toggleNotificationPolicyAccess(mContext.getPackageName(), 834 InstrumentationRegistry.getInstrumentation(), true); 835 836 // no custom ZenPolicy, so consolidatedPolicy should equal the default notif policy 837 assertEquals(mNotificationManager.getConsolidatedNotificationPolicy(), 838 mNotificationManager.getNotificationPolicy()); 839 840 // setup custom ZenPolicy for an automatic rule 841 AutomaticZenRule rule = createRule("test_consolidated_policy", 842 INTERRUPTION_FILTER_PRIORITY); 843 rule.setZenPolicy(new ZenPolicy.Builder() 844 .allowReminders(true) 845 .allowMedia(false) 846 .build()); 847 String id = mNotificationManager.addAutomaticZenRule(rule); 848 // set condition of the automatic rule to TRUE 849 Condition condition = new Condition(rule.getConditionId(), "summary", 850 Condition.STATE_TRUE); 851 mNotificationManager.setAutomaticZenRuleState(id, condition); 852 853 Thread.sleep(300); // wait for rules to be applied - it's done asynchronously 854 855 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 856 857 NotificationManager.Policy consolidatedPolicy = 858 mNotificationManager.getConsolidatedNotificationPolicy(); 859 860 if (Flags.modesApi()) { 861 // Expect the final consolidated policy to be effectively equivalent to the 862 // specified custom policy with remaining fields filled in by defaults. 863 ZenPolicy fullySpecified = mDefaultPolicy.overwrittenWith(rule.getZenPolicy()); 864 assertPolicyCategoriesMatchZenPolicy(consolidatedPolicy, fullySpecified); 865 } else { 866 // reminders is allowed from the automatic rule's custom ZenPolicy 867 assertTrue( 868 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_REMINDERS) != 0); 869 870 // media is disallowed from the automatic rule's custom ZenPolicy 871 assertFalse((consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_MEDIA) != 0); 872 873 // other stuff is from the default notification policy (see #setUp) 874 assertTrue((consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_ALARMS) != 0); 875 assertTrue((consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_CONVERSATIONS) 876 != 0); 877 assertTrue((consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_CALLS) != 0); 878 assertTrue( 879 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_REPEAT_CALLERS) 880 != 0); 881 assertTrue( 882 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_MESSAGES) != 0); 883 assertFalse( 884 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_SYSTEM) != 0); 885 assertFalse( 886 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_EVENTS) != 0); 887 } 888 } finally { 889 mNotificationManager.setInterruptionFilter(originalFilter); 890 mNotificationManager.setNotificationPolicy(origPolicy); 891 } 892 } 893 894 @Test testConsolidatedNotificationPolicyMultiRules()895 public void testConsolidatedNotificationPolicyMultiRules() throws Exception { 896 final int originalFilter = mNotificationManager.getCurrentInterruptionFilter(); 897 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 898 try { 899 toggleNotificationPolicyAccess(mContext.getPackageName(), 900 InstrumentationRegistry.getInstrumentation(), true); 901 902 // setup custom ZenPolicy for two automatic rules 903 AutomaticZenRule rule1 = createRule("test_consolidated_policyq", 904 INTERRUPTION_FILTER_PRIORITY); 905 rule1.setZenPolicy(new ZenPolicy.Builder() 906 .allowReminders(false) 907 .allowSystem(true) 908 .allowAlarms(false) 909 .build()); 910 AutomaticZenRule rule2 = createRule("test_consolidated_policy2", 911 INTERRUPTION_FILTER_PRIORITY); 912 rule2.setZenPolicy(new ZenPolicy.Builder() 913 .allowReminders(true) 914 .allowSystem(true) 915 .allowMedia(true) 916 .build()); 917 String id1 = mNotificationManager.addAutomaticZenRule(rule1); 918 String id2 = mNotificationManager.addAutomaticZenRule(rule2); 919 Condition onCondition1 = new Condition(rule1.getConditionId(), "summary", 920 Condition.STATE_TRUE); 921 Condition onCondition2 = new Condition(rule2.getConditionId(), "summary", 922 Condition.STATE_TRUE); 923 mNotificationManager.setAutomaticZenRuleState(id1, onCondition1); 924 mNotificationManager.setAutomaticZenRuleState(id2, onCondition2); 925 926 Thread.sleep(300); // wait for rules to be applied - it's done asynchronously 927 928 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 929 930 NotificationManager.Policy consolidatedPolicy = 931 mNotificationManager.getConsolidatedNotificationPolicy(); 932 933 if (Flags.modesApi()) { 934 // if modesApi is enabled, confirm that these settings match depending on the device 935 // defaults. Each rule inherits default values for any unset fields, so for fields 936 // where only one rule has expressed an explicit opinion about the setting, the 937 // default setting may be more restrictive and win. 938 ZenPolicy expectedCombined = new ZenPolicy.Builder() 939 .allowReminders(false) // rule1 wins over rule2 940 .allowSystem(true) // both active rules set this 941 .allowAlarms(false) // opinion only from rule1 942 // media opinion only from rule2 (to be allowed); therefore it depends on 943 // default settings 944 .allowMedia( 945 mDefaultPolicy.getPriorityCategoryAlarms() == ZenPolicy.STATE_ALLOW) 946 .build(); 947 948 // The rest are entirely from the default policy. 949 ZenPolicy fullySpecified = mDefaultPolicy.overwrittenWith(expectedCombined); 950 assertPolicyCategoriesMatchZenPolicy(consolidatedPolicy, fullySpecified); 951 } else { 952 // reminders aren't allowed from rule1 overriding rule2 953 // (not allowed takes precedence over allowed) 954 assertTrue( 955 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_REMINDERS) == 0); 956 957 // system allowed from both 958 assertTrue((consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_SYSTEM) != 0); 959 960 // alarms aren't allowed from rule1, so that alarm setting will always win 961 assertTrue((consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_ALARMS) == 0); 962 963 // media is allowed from rule2 964 assertTrue((consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_MEDIA) != 0); 965 966 // other stuff is from the default notification policy (see #setUp) 967 assertTrue( 968 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_CONVERSATIONS) 969 != 0); 970 assertTrue((consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_CALLS) != 0); 971 assertTrue( 972 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_MESSAGES) != 0); 973 assertFalse( 974 (consolidatedPolicy.priorityCategories & PRIORITY_CATEGORY_EVENTS) != 0); 975 } 976 } finally { 977 mNotificationManager.setInterruptionFilter(originalFilter); 978 mNotificationManager.setNotificationPolicy(origPolicy); 979 } 980 } 981 982 @Test 983 @RequiresFlagsEnabled({Flags.FLAG_MODES_API}) testConsolidatedNotificationPolicy_broadcasts()984 public void testConsolidatedNotificationPolicy_broadcasts() throws Exception { 985 // Setup also changes Policy and creates a DND-bypassing channel, so we might get 1-2 986 // extra broadcasts. Make sure they are out of the way. 987 Thread.sleep(500); 988 assertThat(mNotificationManager.getConsolidatedNotificationPolicy().priorityCategories 989 & PRIORITY_CATEGORY_ALARMS).isNotEqualTo(0); 990 991 // Set up a rule with a custom ZenPolicy. 992 AutomaticZenRule rule = createRule("testRule"); 993 rule.setZenPolicy(new ZenPolicy.Builder() 994 .allowReminders(false) 995 .allowSystem(true) 996 .allowAlarms(false) 997 .build()); 998 String id = mNotificationManager.addAutomaticZenRule(rule); 999 1000 // Enable rule, and check for broadcast. 1001 NotificationManagerBroadcastReceiver brOn = new NotificationManagerBroadcastReceiver(); 1002 brOn.register(mContext, ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED, 1); 1003 Condition conditionOn = 1004 new Condition(rule.getConditionId(), "on", Condition.STATE_TRUE); 1005 mNotificationManager.setAutomaticZenRuleState(id, conditionOn); 1006 1007 brOn.assertBroadcastsReceivedWithin(Duration.ofMillis(500)); 1008 NotificationManager.Policy ruleOnPolicy = (NotificationManager.Policy) brOn.getExtra( 1009 NotificationManager.EXTRA_NOTIFICATION_POLICY, 0, 0); 1010 assertThat(ruleOnPolicy.priorityCategories & PRIORITY_CATEGORY_ALARMS).isEqualTo(0); 1011 1012 // TODO: b/324376849 - Registered BR in a DND-access pkg gets broadcast twice. 1013 // Thread.sleep(500); 1014 // assertThat(brOn.results).hasSize(1); // Also no *extra* broadcasts received. 1015 brOn.unregister(); 1016 1017 // Disable rule, and check for broadcast. 1018 NotificationManagerBroadcastReceiver brOff = new NotificationManagerBroadcastReceiver(); 1019 brOff.register(mContext, ACTION_CONSOLIDATED_NOTIFICATION_POLICY_CHANGED, 1); 1020 Condition conditionOff = 1021 new Condition(rule.getConditionId(), "on", Condition.STATE_FALSE); 1022 mNotificationManager.setAutomaticZenRuleState(id, conditionOff); 1023 1024 brOff.assertBroadcastsReceivedWithin(Duration.ofMillis(500)); 1025 NotificationManager.Policy ruleOffPolicy = (NotificationManager.Policy) brOff.getExtra( 1026 NotificationManager.EXTRA_NOTIFICATION_POLICY, 0, 0); 1027 assertThat(ruleOffPolicy.priorityCategories & PRIORITY_CATEGORY_ALARMS).isNotEqualTo(0); 1028 1029 // TODO: b/324376849 - Registered BR in a DND-access pkg gets broadcast twice. 1030 // Thread.sleep(500); 1031 // assertThat(brOff.results).hasSize(1); // Also no *extra* broadcasts received. 1032 brOff.unregister(); 1033 } 1034 1035 @Test testNotificationPolicy_broadcasts()1036 public void testNotificationPolicy_broadcasts() throws Exception { 1037 // Setup also changes Policy and creates a DND-bypassing channel, so we might get 1-2 1038 // extra broadcasts. Make sure they are out of the way. 1039 Thread.sleep(500); 1040 assertThat(mNotificationManager.getNotificationPolicy().priorityCategories 1041 & PRIORITY_CATEGORY_ALARMS).isNotEqualTo(0); 1042 NotificationManagerBroadcastReceiver br = new NotificationManagerBroadcastReceiver(); 1043 br.register(mContext, ACTION_NOTIFICATION_POLICY_CHANGED, 1); 1044 1045 NotificationManager.Policy updatePolicy = new NotificationManager.Policy(0, 0, 0); 1046 runAsSystemUi(() -> mNotificationManager.setNotificationPolicy(updatePolicy)); 1047 1048 br.assertBroadcastsReceivedWithin(Duration.ofMillis(500)); 1049 if (Flags.modesApi()) { 1050 NotificationManager.Policy broadcastPolicy = (NotificationManager.Policy) br.getExtra( 1051 NotificationManager.EXTRA_NOTIFICATION_POLICY, 0, 0); 1052 assertThat(broadcastPolicy.priorityCategories & PRIORITY_CATEGORY_ALARMS).isEqualTo(0); 1053 } 1054 } 1055 1056 @Test 1057 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) testConsolidatedNotificationPolicy_mergesAllowPriorityChannels()1058 public void testConsolidatedNotificationPolicy_mergesAllowPriorityChannels() throws Exception { 1059 toggleNotificationPolicyAccess(mContext.getPackageName(), 1060 InstrumentationRegistry.getInstrumentation(), true); 1061 1062 // setup custom ZenPolicy for an automatic rule 1063 AutomaticZenRule rule = createRule("test_consolidated_policy_priority_channels", 1064 INTERRUPTION_FILTER_PRIORITY); 1065 rule.setZenPolicy(new ZenPolicy.Builder() 1066 .allowPriorityChannels(true) 1067 .build()); 1068 String id = mNotificationManager.addAutomaticZenRule(rule); 1069 // set condition of the automatic rule to TRUE 1070 Condition condition = new Condition(rule.getConditionId(), "summary", 1071 Condition.STATE_TRUE); 1072 mNotificationManager.setAutomaticZenRuleState(id, condition); 1073 1074 Thread.sleep(300); // wait for rules to be applied - it's done asynchronously 1075 1076 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 1077 1078 NotificationManager.Policy consolidatedPolicy = 1079 mNotificationManager.getConsolidatedNotificationPolicy(); 1080 1081 // channels are permitted as set by the rule 1082 assertTrue(consolidatedPolicy.allowPriorityChannels()); 1083 1084 // new rule that disallows channels 1085 AutomaticZenRule rule2 = createRule("test_consolidated_policy_no_channels", 1086 INTERRUPTION_FILTER_PRIORITY); 1087 rule2.setZenPolicy(new ZenPolicy.Builder() 1088 .allowPriorityChannels(false) 1089 .build()); 1090 String id2 = mNotificationManager.addAutomaticZenRule(rule2); 1091 Condition onCondition2 = new Condition(rule2.getConditionId(), "summary", 1092 Condition.STATE_TRUE); 1093 mNotificationManager.setAutomaticZenRuleState(id2, onCondition2); 1094 1095 // now priority channels are disallowed because "no channels" overrides "priority" 1096 consolidatedPolicy = 1097 mNotificationManager.getConsolidatedNotificationPolicy(); 1098 assertFalse(consolidatedPolicy.allowPriorityChannels()); 1099 } 1100 1101 @Test testPostPCanToggleAlarmsMediaSystemTest()1102 public void testPostPCanToggleAlarmsMediaSystemTest() throws Exception { 1103 toggleNotificationPolicyAccess(mContext.getPackageName(), 1104 InstrumentationRegistry.getInstrumentation(), true); 1105 1106 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1107 try { 1108 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) { 1109 // Post-P can toggle alarms, media, system 1110 // toggle on alarms, media, system: 1111 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1112 PRIORITY_CATEGORY_ALARMS 1113 | PRIORITY_CATEGORY_MEDIA 1114 | PRIORITY_CATEGORY_SYSTEM, 0, 0)); 1115 NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy(); 1116 assertTrue((policy.priorityCategories & PRIORITY_CATEGORY_ALARMS) != 0); 1117 assertTrue((policy.priorityCategories & PRIORITY_CATEGORY_MEDIA) != 0); 1118 assertTrue((policy.priorityCategories & PRIORITY_CATEGORY_SYSTEM) != 0); 1119 1120 // toggle off alarms, media, system 1121 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy(0, 0, 0)); 1122 policy = mNotificationManager.getNotificationPolicy(); 1123 assertTrue((policy.priorityCategories & PRIORITY_CATEGORY_ALARMS) == 0); 1124 assertTrue((policy.priorityCategories & PRIORITY_CATEGORY_MEDIA) == 0); 1125 assertTrue((policy.priorityCategories & PRIORITY_CATEGORY_SYSTEM) == 0); 1126 } 1127 } finally { 1128 mNotificationManager.setNotificationPolicy(origPolicy); 1129 } 1130 } 1131 1132 @Test testPostRCanToggleConversationsTest()1133 public void testPostRCanToggleConversationsTest() throws Exception { 1134 toggleNotificationPolicyAccess(mContext.getPackageName(), 1135 InstrumentationRegistry.getInstrumentation(), true); 1136 1137 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1138 1139 try { 1140 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1141 0, 0, 0, 0)); 1142 NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy(); 1143 assertEquals(0, (policy.priorityCategories & PRIORITY_CATEGORY_CONVERSATIONS)); 1144 assertEquals(CONVERSATION_SENDERS_NONE, policy.priorityConversationSenders); 1145 1146 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1147 PRIORITY_CATEGORY_CONVERSATIONS, 0, 0, 0, CONVERSATION_SENDERS_ANYONE)); 1148 policy = mNotificationManager.getNotificationPolicy(); 1149 assertTrue((policy.priorityCategories & PRIORITY_CATEGORY_CONVERSATIONS) != 0); 1150 assertEquals(CONVERSATION_SENDERS_ANYONE, policy.priorityConversationSenders); 1151 1152 } finally { 1153 mNotificationManager.setNotificationPolicy(origPolicy); 1154 } 1155 } 1156 1157 @Test testTotalSilenceOnlyMuteStreams()1158 public void testTotalSilenceOnlyMuteStreams() throws Exception { 1159 assumeFalse("Skipping test on automotive platform", 1160 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)); 1161 1162 toggleNotificationPolicyAccess(mContext.getPackageName(), 1163 InstrumentationRegistry.getInstrumentation(), true); 1164 1165 // ensure volume is not muted/0 to start test 1166 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0); 1167 // exception for presidential alert 1168 //mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, 1, 0); 1169 mAudioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, 1, 0); 1170 mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 1, 0); 1171 1172 AutomaticZenRule rule = createRule("test_total_silence", INTERRUPTION_FILTER_NONE); 1173 String id = mNotificationManager.addAutomaticZenRule(rule); 1174 Condition condition = 1175 new Condition(rule.getConditionId(), "summary", Condition.STATE_TRUE); 1176 mNotificationManager.setAutomaticZenRuleState(id, condition); 1177 if (!SdkLevel.isAtLeastV()) { 1178 runAsSystemUi( 1179 () -> mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)); 1180 } 1181 1182 // delay for streams to get into correct mute states 1183 Thread.sleep(1000); 1184 assertTrue("Music (media) stream should be muted", 1185 mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)); 1186 assertTrue("System stream should be muted", 1187 mAudioManager.isStreamMute(AudioManager.STREAM_SYSTEM)); 1188 // exception for presidential alert 1189 //assertTrue("Alarm stream should be muted", 1190 // mAudioManager.isStreamMute(AudioManager.STREAM_ALARM)); 1191 1192 if (SdkLevel.isAtLeastV()) { 1193 // For the audio stream to be muted correctly, we need the priority channels setting; 1194 // otherwise, pre-V, we cannot guarantee that no channels are bypassing DND. 1195 assertTrue("Ringer stream should be muted", 1196 mAudioManager.isStreamMute(AudioManager.STREAM_RING)); 1197 } 1198 } 1199 1200 @Test testAlarmsOnlyMuteStreams()1201 public void testAlarmsOnlyMuteStreams() throws Exception { 1202 assumeFalse("Skipping test on automotive platform", 1203 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)); 1204 1205 toggleNotificationPolicyAccess(mContext.getPackageName(), 1206 InstrumentationRegistry.getInstrumentation(), true); 1207 1208 // ensure volume is not muted/0 to start test 1209 mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0); 1210 mAudioManager.setStreamVolume(AudioManager.STREAM_ALARM, 1, 0); 1211 mAudioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, 1, 0); 1212 mAudioManager.setStreamVolume(AudioManager.STREAM_RING, 1, 0); 1213 1214 if (!SdkLevel.isAtLeastV()) { 1215 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1216 PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_MEDIA, 0, 0)); 1217 } 1218 AutomaticZenRule rule = createRule("test_alarms", INTERRUPTION_FILTER_ALARMS); 1219 String id = mNotificationManager.addAutomaticZenRule(rule); 1220 Condition condition = 1221 new Condition(rule.getConditionId(), "summary", Condition.STATE_TRUE); 1222 mNotificationManager.setAutomaticZenRuleState(id, condition); 1223 if (!SdkLevel.isAtLeastV()) { 1224 runAsSystemUi( 1225 () -> mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY)); 1226 } 1227 1228 // delay for streams to get into correct mute states 1229 Thread.sleep(1000); 1230 assertFalse("Music (media) stream should not be muted", 1231 mAudioManager.isStreamMute(AudioManager.STREAM_MUSIC)); 1232 assertTrue("System stream should be muted", 1233 mAudioManager.isStreamMute(AudioManager.STREAM_SYSTEM)); 1234 assertFalse("Alarm stream should not be muted", 1235 mAudioManager.isStreamMute(AudioManager.STREAM_ALARM)); 1236 1237 if (SdkLevel.isAtLeastV()) { 1238 // For the audio stream to be muted correctly, we need the priority channels setting; 1239 // otherwise, pre-V, we cannot guarantee that no channels are bypassing DND. 1240 assertTrue("Ringer stream should be muted", 1241 mAudioManager.isStreamMute(AudioManager.STREAM_RING)); 1242 } 1243 } 1244 1245 @Test testAddAutomaticZenRule_configActivity()1246 public void testAddAutomaticZenRule_configActivity() throws Exception { 1247 toggleNotificationPolicyAccess(mContext.getPackageName(), 1248 InstrumentationRegistry.getInstrumentation(), true); 1249 1250 AutomaticZenRule ruleToCreate = createRule("Rule"); 1251 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 1252 1253 assertNotNull(id); 1254 assertRulesEqual(ruleToCreate, mNotificationManager.getAutomaticZenRule(id)); 1255 } 1256 1257 @Test testUpdateAutomaticZenRule_configActivity()1258 public void testUpdateAutomaticZenRule_configActivity() throws Exception { 1259 toggleNotificationPolicyAccess(mContext.getPackageName(), 1260 InstrumentationRegistry.getInstrumentation(), true); 1261 1262 AutomaticZenRule ruleToCreate = createRule("Rule"); 1263 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 1264 ruleToCreate.setEnabled(false); 1265 mNotificationManager.updateAutomaticZenRule(id, ruleToCreate); 1266 1267 assertNotNull(id); 1268 assertRulesEqual(ruleToCreate, mNotificationManager.getAutomaticZenRule(id)); 1269 } 1270 1271 @Test testRemoveAutomaticZenRule_configActivity()1272 public void testRemoveAutomaticZenRule_configActivity() throws Exception { 1273 toggleNotificationPolicyAccess(mContext.getPackageName(), 1274 InstrumentationRegistry.getInstrumentation(), true); 1275 1276 AutomaticZenRule ruleToCreate = createRule("Rule"); 1277 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 1278 1279 assertNotNull(id); 1280 mNotificationManager.removeAutomaticZenRule(id); 1281 1282 assertNull(mNotificationManager.getAutomaticZenRule(id)); 1283 assertEquals(0, mNotificationManager.getAutomaticZenRules().size()); 1284 } 1285 1286 @Test testSetAutomaticZenRuleState()1287 public void testSetAutomaticZenRuleState() throws Exception { 1288 toggleNotificationPolicyAccess(mContext.getPackageName(), 1289 InstrumentationRegistry.getInstrumentation(), true); 1290 1291 AutomaticZenRule ruleToCreate = createRule("Rule"); 1292 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 1293 1294 // make sure DND is off 1295 assertExpectedDndState(INTERRUPTION_FILTER_ALL); 1296 1297 // enable DND 1298 Condition condition = 1299 new Condition(ruleToCreate.getConditionId(), "summary", Condition.STATE_TRUE); 1300 mNotificationManager.setAutomaticZenRuleState(id, condition); 1301 1302 assertExpectedDndState(ruleToCreate.getInterruptionFilter()); 1303 } 1304 1305 @Test testSetAutomaticZenRuleState_turnOff()1306 public void testSetAutomaticZenRuleState_turnOff() throws Exception { 1307 toggleNotificationPolicyAccess(mContext.getPackageName(), 1308 InstrumentationRegistry.getInstrumentation(), true); 1309 1310 AutomaticZenRule ruleToCreate = createRule("Rule"); 1311 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 1312 1313 // make sure DND is off 1314 // make sure DND is off 1315 assertExpectedDndState(INTERRUPTION_FILTER_ALL); 1316 1317 // enable DND 1318 Condition condition = 1319 new Condition(ruleToCreate.getConditionId(), "on", Condition.STATE_TRUE); 1320 mNotificationManager.setAutomaticZenRuleState(id, condition); 1321 1322 assertExpectedDndState(ruleToCreate.getInterruptionFilter()); 1323 1324 // disable DND 1325 condition = new Condition(ruleToCreate.getConditionId(), "off", Condition.STATE_FALSE); 1326 1327 mNotificationManager.setAutomaticZenRuleState(id, condition); 1328 1329 // make sure DND is off 1330 assertExpectedDndState(INTERRUPTION_FILTER_ALL); 1331 } 1332 1333 @Test testSetAutomaticZenRuleState_deletedRule()1334 public void testSetAutomaticZenRuleState_deletedRule() throws Exception { 1335 toggleNotificationPolicyAccess(mContext.getPackageName(), 1336 InstrumentationRegistry.getInstrumentation(), true); 1337 1338 AutomaticZenRule ruleToCreate = createRule("Rule"); 1339 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 1340 1341 // make sure DND is off 1342 assertExpectedDndState(INTERRUPTION_FILTER_ALL); 1343 1344 // enable DND 1345 Condition condition = 1346 new Condition(ruleToCreate.getConditionId(), "summary", Condition.STATE_TRUE); 1347 mNotificationManager.setAutomaticZenRuleState(id, condition); 1348 1349 assertExpectedDndState(ruleToCreate.getInterruptionFilter()); 1350 1351 mNotificationManager.removeAutomaticZenRule(id); 1352 1353 // make sure DND is off 1354 assertExpectedDndState(INTERRUPTION_FILTER_ALL); 1355 } 1356 1357 @Test testSetAutomaticZenRuleState_multipleRules()1358 public void testSetAutomaticZenRuleState_multipleRules() throws Exception { 1359 toggleNotificationPolicyAccess(mContext.getPackageName(), 1360 InstrumentationRegistry.getInstrumentation(), true); 1361 1362 AutomaticZenRule ruleToCreate = createRule("Rule"); 1363 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 1364 1365 AutomaticZenRule secondRuleToCreate = createRule("Rule 2"); 1366 secondRuleToCreate.setInterruptionFilter(INTERRUPTION_FILTER_NONE); 1367 String secondId = mNotificationManager.addAutomaticZenRule(secondRuleToCreate); 1368 1369 // make sure DND is off 1370 assertExpectedDndState(INTERRUPTION_FILTER_ALL); 1371 1372 // enable DND 1373 Condition condition = 1374 new Condition(ruleToCreate.getConditionId(), "summary", Condition.STATE_TRUE); 1375 mNotificationManager.setAutomaticZenRuleState(id, condition); 1376 Condition secondCondition = 1377 new Condition(secondRuleToCreate.getConditionId(), "summary", Condition.STATE_TRUE); 1378 mNotificationManager.setAutomaticZenRuleState(secondId, secondCondition); 1379 1380 // the second rule has a 'more silent' DND filter, so the system wide DND should be 1381 // using its filter 1382 assertExpectedDndState(secondRuleToCreate.getInterruptionFilter()); 1383 1384 // remove intense rule, system should fallback to other rule 1385 mNotificationManager.removeAutomaticZenRule(secondId); 1386 assertExpectedDndState(ruleToCreate.getInterruptionFilter()); 1387 } 1388 1389 @Test testSetNotificationPolicy_P_setOldFields()1390 public void testSetNotificationPolicy_P_setOldFields() throws Exception { 1391 toggleNotificationPolicyAccess(mContext.getPackageName(), 1392 InstrumentationRegistry.getInstrumentation(), true); 1393 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1394 try { 1395 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) { 1396 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 1397 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF); 1398 mNotificationManager.setNotificationPolicy(appPolicy); 1399 1400 int expected = SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_SCREEN_OFF 1401 | SUPPRESSED_EFFECT_PEEK | SUPPRESSED_EFFECT_AMBIENT 1402 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 1403 1404 assertEquals(expected, 1405 mNotificationManager.getNotificationPolicy().suppressedVisualEffects); 1406 } 1407 } finally { 1408 mNotificationManager.setNotificationPolicy(origPolicy); 1409 } 1410 } 1411 1412 @Test testSetNotificationPolicy_P_setNewFields()1413 public void testSetNotificationPolicy_P_setNewFields() throws Exception { 1414 toggleNotificationPolicyAccess(mContext.getPackageName(), 1415 InstrumentationRegistry.getInstrumentation(), true); 1416 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1417 try { 1418 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) { 1419 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 1420 SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_AMBIENT 1421 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 1422 mNotificationManager.setNotificationPolicy(appPolicy); 1423 1424 int expected = SUPPRESSED_EFFECT_NOTIFICATION_LIST | SUPPRESSED_EFFECT_SCREEN_OFF 1425 | SUPPRESSED_EFFECT_AMBIENT | SUPPRESSED_EFFECT_LIGHTS 1426 | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 1427 assertEquals(expected, 1428 mNotificationManager.getNotificationPolicy().suppressedVisualEffects); 1429 } 1430 } finally { 1431 mNotificationManager.setNotificationPolicy(origPolicy); 1432 } 1433 } 1434 1435 @Test testSetNotificationPolicy_P_setOldNewFields()1436 public void testSetNotificationPolicy_P_setOldNewFields() throws Exception { 1437 toggleNotificationPolicyAccess(mContext.getPackageName(), 1438 InstrumentationRegistry.getInstrumentation(), true); 1439 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1440 try { 1441 if (mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.P) { 1442 1443 NotificationManager.Policy appPolicy = new NotificationManager.Policy(0, 0, 0, 1444 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_STATUS_BAR); 1445 mNotificationManager.setNotificationPolicy(appPolicy); 1446 1447 int expected = SUPPRESSED_EFFECT_STATUS_BAR; 1448 assertEquals(expected, 1449 mNotificationManager.getNotificationPolicy().suppressedVisualEffects); 1450 1451 appPolicy = new NotificationManager.Policy(0, 0, 0, 1452 SUPPRESSED_EFFECT_SCREEN_ON | SUPPRESSED_EFFECT_AMBIENT 1453 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT); 1454 mNotificationManager.setNotificationPolicy(appPolicy); 1455 1456 expected = SUPPRESSED_EFFECT_SCREEN_OFF | SUPPRESSED_EFFECT_AMBIENT 1457 | SUPPRESSED_EFFECT_LIGHTS | SUPPRESSED_EFFECT_FULL_SCREEN_INTENT; 1458 assertEquals(expected, 1459 mNotificationManager.getNotificationPolicy().suppressedVisualEffects); 1460 } 1461 } finally { 1462 mNotificationManager.setNotificationPolicy(origPolicy); 1463 } 1464 } 1465 1466 1467 @Test testMatchesCallFilter_noPermissions()1468 public void testMatchesCallFilter_noPermissions() { 1469 // make sure we definitely don't have contacts access 1470 boolean hadReadPerm = hasReadContactsPermission(TEST_APP); 1471 try { 1472 toggleReadContactsPermission(TEST_APP, false); 1473 1474 // start an activity that has no permissions, which will run matchesCallFilter on 1475 // a meaningless uri. The result code indicates whether or not the method call was 1476 // permitted. 1477 final Intent mcfIntent = new Intent(Intent.ACTION_MAIN); 1478 mcfIntent.setClassName(TEST_APP, MATCHES_CALL_FILTER_CLASS); 1479 GetResultActivity grActivity = setUpGetResultActivity(); 1480 grActivity.startActivityForResult(mcfIntent, REQUEST_CODE); 1481 UiDevice.getInstance(mInstrumentation).waitForIdle(); 1482 1483 // with no permissions, this call should not have been permitted 1484 GetResultActivity.Result result = grActivity.getResult(); 1485 assertEquals(REQUEST_CODE, result.requestCode); 1486 assertEquals(MATCHES_CALL_FILTER_NOT_PERMITTED, result.resultCode); 1487 grActivity.finishActivity(REQUEST_CODE); 1488 } finally { 1489 toggleReadContactsPermission(TEST_APP, hadReadPerm); 1490 } 1491 } 1492 1493 @Test testMatchesCallFilter_listenerPermissionOnly()1494 public void testMatchesCallFilter_listenerPermissionOnly() throws Exception { 1495 boolean hadReadPerm = hasReadContactsPermission(TEST_APP); 1496 // minimal listener service so that it can be given listener permissions 1497 final ComponentName listenerComponent = 1498 new ComponentName(TEST_APP, MINIMAL_LISTENER_CLASS); 1499 try { 1500 // make surethat we don't for some reason have contacts access 1501 toggleReadContactsPermission(TEST_APP, false); 1502 1503 // grant the notification app package notification listener access; 1504 // give it time to succeed 1505 toggleExternalListenerAccess(listenerComponent, true); 1506 Thread.sleep(500); 1507 1508 // set up & run intent 1509 final Intent mcfIntent = new Intent(Intent.ACTION_MAIN); 1510 mcfIntent.setClassName(TEST_APP, MATCHES_CALL_FILTER_CLASS); 1511 GetResultActivity grActivity = setUpGetResultActivity(); 1512 grActivity.startActivityForResult(mcfIntent, REQUEST_CODE); 1513 UiDevice.getInstance(mInstrumentation).waitForIdle(); 1514 1515 // with just listener permissions, this call should have been permitted 1516 GetResultActivity.Result result = grActivity.getResult(); 1517 assertEquals(REQUEST_CODE, result.requestCode); 1518 assertEquals(MATCHES_CALL_FILTER_PERMITTED, result.resultCode); 1519 grActivity.finishActivity(REQUEST_CODE); 1520 } finally { 1521 // clean up listener access, reset read contacts access 1522 toggleExternalListenerAccess(listenerComponent, false); 1523 toggleReadContactsPermission(TEST_APP, hadReadPerm); 1524 } 1525 } 1526 1527 @Test testMatchesCallFilter_contactsPermissionOnly()1528 public void testMatchesCallFilter_contactsPermissionOnly() throws Exception { 1529 // grant the notification app package contacts read access 1530 boolean hadReadPerm = hasReadContactsPermission(TEST_APP); 1531 try { 1532 toggleReadContactsPermission(TEST_APP, true); 1533 1534 // set up & run intent 1535 final Intent mcfIntent = new Intent(Intent.ACTION_MAIN); 1536 mcfIntent.setClassName(TEST_APP, MATCHES_CALL_FILTER_CLASS); 1537 GetResultActivity grActivity = setUpGetResultActivity(); 1538 grActivity.startActivityForResult(mcfIntent, REQUEST_CODE); 1539 UiDevice.getInstance(mInstrumentation).waitForIdle(); 1540 1541 // with just contacts read permissions, this call should have been permitted 1542 GetResultActivity.Result result = grActivity.getResult(); 1543 assertEquals(REQUEST_CODE, result.requestCode); 1544 assertEquals(MATCHES_CALL_FILTER_PERMITTED, result.resultCode); 1545 grActivity.finishActivity(REQUEST_CODE); 1546 } finally { 1547 // clean up contacts access 1548 toggleReadContactsPermission(TEST_APP, hadReadPerm); 1549 } 1550 } 1551 1552 @Test testMatchesCallFilter_zenOff()1553 public void testMatchesCallFilter_zenOff() throws Exception { 1554 // zen mode is not on so nothing is filtered; matchesCallFilter should always pass 1555 toggleNotificationPolicyAccess(mContext.getPackageName(), 1556 InstrumentationRegistry.getInstrumentation(), true); 1557 int origFilter = mNotificationManager.getCurrentInterruptionFilter(); 1558 try { 1559 // allowed from anyone: nothing is filtered, and make sure change went through 1560 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL); 1561 assertExpectedDndState(INTERRUPTION_FILTER_ALL); 1562 1563 // create a phone URI from which to receive a call 1564 Uri phoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, 1565 Uri.encode("+16175551212")); 1566 assertTrue(mNotificationManager.matchesCallFilter(phoneUri)); 1567 } finally { 1568 mNotificationManager.setInterruptionFilter(origFilter); 1569 } 1570 } 1571 1572 @Test testMatchesCallFilter_noCallInterruptions()1573 public void testMatchesCallFilter_noCallInterruptions() throws Exception { 1574 // when no call interruptions are allowed at all, or only alarms, matchesCallFilter 1575 // should always fail 1576 toggleNotificationPolicyAccess(mContext.getPackageName(), 1577 InstrumentationRegistry.getInstrumentation(), true); 1578 int origFilter = mNotificationManager.getCurrentInterruptionFilter(); 1579 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1580 try { 1581 // create a phone URI from which to receive a call 1582 Uri phoneUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, 1583 Uri.encode("+16175551212")); 1584 1585 // no interruptions allowed at all 1586 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_NONE); 1587 assertExpectedDndState(INTERRUPTION_FILTER_NONE); 1588 assertFalse(mNotificationManager.matchesCallFilter(phoneUri)); 1589 1590 // only alarms 1591 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALARMS); 1592 assertExpectedDndState(INTERRUPTION_FILTER_ALARMS); 1593 assertFalse(mNotificationManager.matchesCallFilter(phoneUri)); 1594 1595 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1596 PRIORITY_CATEGORY_MESSAGES, 0, 0)); 1597 // turn on manual DND 1598 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 1599 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 1600 assertFalse(mNotificationManager.matchesCallFilter(phoneUri)); 1601 } finally { 1602 mNotificationManager.setInterruptionFilter(origFilter); 1603 mNotificationManager.setNotificationPolicy(origPolicy); 1604 } 1605 } 1606 1607 @Test testMatchesCallFilter_someCallers()1608 public void testMatchesCallFilter_someCallers() throws Exception { 1609 // zen mode is active; check various configurations where some calls, but not all calls, 1610 // are allowed 1611 toggleNotificationPolicyAccess(mContext.getPackageName(), 1612 InstrumentationRegistry.getInstrumentation(), true); 1613 int origFilter = mNotificationManager.getCurrentInterruptionFilter(); 1614 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1615 1616 // for storing lookup URIs for deleting the contacts afterwards 1617 Uri aliceUri = null; 1618 Uri bobUri = null; 1619 try { 1620 // set up phone numbers: one starred, one regular, one unknown number 1621 // starred contact from whom to receive a call 1622 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, true); 1623 aliceUri = lookupContact(ALICE_PHONE); 1624 Uri alicePhoneUri = makePhoneUri(ALICE_PHONE); 1625 1626 // non-starred contact from whom to also receive a call 1627 insertSingleContact(BOB, BOB_PHONE, BOB_EMAIL, false); 1628 bobUri = lookupContact(BOB_PHONE); 1629 Uri bobPhoneUri = makePhoneUri(BOB_PHONE); 1630 1631 // non-contact phone URI 1632 Uri phoneUri = makePhoneUri("+16175555656"); 1633 1634 // set up: any contacts are allowed to call. 1635 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1636 PRIORITY_CATEGORY_CALLS, 1637 NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS, 0)); 1638 1639 // turn on manual DND 1640 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 1641 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 1642 1643 // in this case Alice and Bob should get through but not the unknown number. 1644 assertTrue(mNotificationManager.matchesCallFilter(alicePhoneUri)); 1645 assertTrue(mNotificationManager.matchesCallFilter(bobPhoneUri)); 1646 assertFalse(mNotificationManager.matchesCallFilter(phoneUri)); 1647 1648 // set up: only starred contacts are allowed to call. 1649 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1650 PRIORITY_CATEGORY_CALLS, 1651 PRIORITY_SENDERS_STARRED, 0)); 1652 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 1653 1654 // now only Alice should be allowed to get through 1655 assertTrue(mNotificationManager.matchesCallFilter(alicePhoneUri)); 1656 assertFalse(mNotificationManager.matchesCallFilter(bobPhoneUri)); 1657 assertFalse(mNotificationManager.matchesCallFilter(phoneUri)); 1658 } finally { 1659 mNotificationManager.setInterruptionFilter(origFilter); 1660 mNotificationManager.setNotificationPolicy(origPolicy); 1661 if (aliceUri != null) { 1662 // delete the contact 1663 deleteSingleContact(aliceUri); 1664 } 1665 if (bobUri != null) { 1666 deleteSingleContact(bobUri); 1667 } 1668 } 1669 } 1670 1671 @Test testMatchesCallFilter_repeatCallers()1672 public void testMatchesCallFilter_repeatCallers() throws Exception { 1673 // if repeat callers are allowed, an unknown number calling twice should go through 1674 toggleNotificationPolicyAccess(mContext.getPackageName(), 1675 InstrumentationRegistry.getInstrumentation(), true); 1676 int origFilter = mNotificationManager.getCurrentInterruptionFilter(); 1677 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1678 long startTime = System.currentTimeMillis(); 1679 try { 1680 // create phone URIs from which to receive a call; one US, one non-US, 1681 // both fully specified 1682 Uri phoneUri = makePhoneUri("+16175551212"); 1683 Uri phoneUri2 = makePhoneUri("+81 75 350 6006"); 1684 1685 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1686 PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0)); 1687 // turn on manual DND 1688 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 1689 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 1690 1691 // not repeat callers yet, so it shouldn't be allowed 1692 assertFalse(mNotificationManager.matchesCallFilter(phoneUri)); 1693 assertFalse(mNotificationManager.matchesCallFilter(phoneUri2)); 1694 1695 // register a call from number 1, then cancel the notification, which is when 1696 // a call is actually recorded. 1697 sendNotification(1, null, R.drawable.blue, true, phoneUri); 1698 cancelAndPoll(1); 1699 1700 // now this number should count as a repeat caller 1701 assertTrue(mNotificationManager.matchesCallFilter(phoneUri)); 1702 assertFalse(mNotificationManager.matchesCallFilter(phoneUri2)); 1703 1704 // also, any other variants of this phone number should also count as a repeat caller 1705 Uri[] variants = { makePhoneUri(Uri.encode("+1-617-555-1212")), 1706 makePhoneUri("+1 (617) 555-1212") }; 1707 for (int i = 0; i < variants.length; i++) { 1708 assertTrue("phone variant " + variants[i] + " should still match", 1709 mNotificationManager.matchesCallFilter(variants[i])); 1710 } 1711 1712 // register call 2 1713 sendNotification(2, null, R.drawable.blue, true, phoneUri2); 1714 cancelAndPoll(2); 1715 1716 // now this should be a repeat caller 1717 assertTrue(mNotificationManager.matchesCallFilter(phoneUri2)); 1718 1719 Uri[] variants2 = { makePhoneUri(Uri.encode("+81 75 350 6006")), 1720 makePhoneUri("+81753506006")}; 1721 for (int j = 0; j < variants2.length; j++) { 1722 assertTrue("phone variant " + variants2[j] + " should still match", 1723 mNotificationManager.matchesCallFilter(variants2[j])); 1724 } 1725 } finally { 1726 mNotificationManager.setInterruptionFilter(origFilter); 1727 mNotificationManager.setNotificationPolicy(origPolicy); 1728 1729 // make sure we clean up the recent call, otherwise future runs of this will fail 1730 // and we'll have a fake call still kicking around somewhere. 1731 SystemUtil.runWithShellPermissionIdentity(() -> 1732 mNotificationManager.cleanUpCallersAfter(startTime)); 1733 } 1734 } 1735 1736 @Test testMatchesCallFilter_repeatCallers_fromContact()1737 public void testMatchesCallFilter_repeatCallers_fromContact() throws Exception { 1738 // set up such that only repeat callers (and not any individuals) are allowed; make sure 1739 // that a call registered with a contact's lookup URI will return the correct info 1740 // when matchesCallFilter is called with their phone number 1741 toggleNotificationPolicyAccess(mContext.getPackageName(), 1742 InstrumentationRegistry.getInstrumentation(), true); 1743 int origFilter = mNotificationManager.getCurrentInterruptionFilter(); 1744 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1745 Uri aliceUri = null; 1746 long startTime = System.currentTimeMillis(); 1747 try { 1748 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1749 PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0)); 1750 // turn on manual DND 1751 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 1752 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 1753 1754 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, false); 1755 aliceUri = lookupContact(ALICE_PHONE); 1756 Uri alicePhoneUri = makePhoneUri(ALICE_PHONE); 1757 1758 // no one has called; matchesCallFilter should return false for both URIs 1759 assertFalse(mNotificationManager.matchesCallFilter(aliceUri)); 1760 assertFalse(mNotificationManager.matchesCallFilter(alicePhoneUri)); 1761 1762 assertTrue(aliceUri.toString() 1763 .startsWith(ContactsContract.Contacts.CONTENT_LOOKUP_URI.toString())); 1764 1765 // register a call from Alice via the contact lookup URI, then cancel so the call is 1766 // recorded accordingly. 1767 sendNotification(1, null, R.drawable.blue, true, aliceUri); 1768 // wait for contact lookup of number to finish; this can take a while because it runs 1769 // in the background, so give it a fair bit of time 1770 Thread.sleep(3000); 1771 cancelAndPoll(1); 1772 1773 // now a phone call from Alice's phone number should match the repeat callers list 1774 assertTrue(mNotificationManager.matchesCallFilter(alicePhoneUri)); 1775 } finally { 1776 mNotificationManager.setInterruptionFilter(origFilter); 1777 mNotificationManager.setNotificationPolicy(origPolicy); 1778 if (aliceUri != null) { 1779 // delete the contact 1780 deleteSingleContact(aliceUri); 1781 } 1782 1783 // clean up the recorded calls 1784 SystemUtil.runWithShellPermissionIdentity(() -> 1785 mNotificationManager.cleanUpCallersAfter(startTime)); 1786 } 1787 } 1788 1789 @Test testRepeatCallers_repeatCallNotIntercepted_contactAfterPhone()1790 public void testRepeatCallers_repeatCallNotIntercepted_contactAfterPhone() throws Exception { 1791 mListener = mNotificationHelper.enableListener(STUB_PACKAGE_NAME); 1792 assertNotNull(mListener); 1793 1794 // if a call is recorded with just phone number info (not a contact's uri), which may 1795 // happen when the same contact calls across multiple apps (or if the contact uri provided 1796 // is otherwise inconsistent), check for the contact's phone number 1797 toggleNotificationPolicyAccess(mContext.getPackageName(), 1798 InstrumentationRegistry.getInstrumentation(), true); 1799 int origFilter = mNotificationManager.getCurrentInterruptionFilter(); 1800 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1801 Uri aliceUri = null; 1802 long startTime = System.currentTimeMillis(); 1803 try { 1804 mNotificationManager.setNotificationPolicy(new NotificationManager.Policy( 1805 PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0)); 1806 // turn on manual DND 1807 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 1808 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 1809 1810 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, false); 1811 aliceUri = lookupContact(ALICE_PHONE); 1812 Uri alicePhoneUri = makePhoneUri(ALICE_PHONE); 1813 1814 // no one has called; matchesCallFilter should return false for both URIs 1815 assertFalse(mNotificationManager.matchesCallFilter(aliceUri)); 1816 assertFalse(mNotificationManager.matchesCallFilter(alicePhoneUri)); 1817 1818 // register a call from Alice via just the phone number 1819 sendNotification(1, null, R.drawable.blue, true, alicePhoneUri); 1820 Thread.sleep(1000); // give the listener some time to receive info 1821 1822 // check that the first notification is intercepted 1823 StatusBarNotification sbn = mNotificationHelper.findPostedNotification(null, 1, 1824 SEARCH_TYPE.POSTED); 1825 assertNotNull(sbn); 1826 assertTrue(mListener.mIntercepted.containsKey(sbn.getKey())); 1827 assertTrue(mListener.mIntercepted.get(sbn.getKey())); // should be intercepted 1828 1829 // cancel first notification 1830 cancelAndPoll(1); 1831 1832 // now send a call with only Alice's contact Uri as the info 1833 // Note that this is a test of the repeat caller check, not matchesCallFilter itself 1834 sendNotification(2, null, R.drawable.blue, true, aliceUri); 1835 // wait for contact lookup, which may take a while 1836 Thread.sleep(3000); 1837 1838 // now check that the second notification is not intercepted 1839 StatusBarNotification sbn2 = mNotificationHelper.findPostedNotification(null, 2, 1840 SEARCH_TYPE.POSTED); 1841 assertTrue(mListener.mIntercepted.containsKey(sbn2.getKey())); 1842 assertFalse(mListener.mIntercepted.get(sbn2.getKey())); // should not be intercepted 1843 1844 // cancel second notification 1845 cancelAndPoll(2); 1846 } finally { 1847 mNotificationManager.setInterruptionFilter(origFilter); 1848 mNotificationManager.setNotificationPolicy(origPolicy); 1849 if (aliceUri != null) { 1850 // delete the contact 1851 deleteSingleContact(aliceUri); 1852 } 1853 1854 // clean up the recorded calls 1855 SystemUtil.runWithShellPermissionIdentity(() -> 1856 mNotificationManager.cleanUpCallersAfter(startTime)); 1857 } 1858 } 1859 1860 @Test testMatchesCallFilter_allCallers()1861 public void testMatchesCallFilter_allCallers() throws Exception { 1862 // allow all callers 1863 toggleNotificationPolicyAccess(mContext.getPackageName(), 1864 InstrumentationRegistry.getInstrumentation(), true); 1865 int origFilter = mNotificationManager.getCurrentInterruptionFilter(); 1866 NotificationManager.Policy origPolicy = mNotificationManager.getNotificationPolicy(); 1867 Uri aliceUri = null; // for deletion after the test is done 1868 try { 1869 NotificationManager.Policy currPolicy = mNotificationManager.getNotificationPolicy(); 1870 NotificationManager.Policy newPolicy = new NotificationManager.Policy( 1871 NotificationManager.Policy.PRIORITY_CATEGORY_CALLS 1872 | PRIORITY_CATEGORY_REPEAT_CALLERS, 1873 NotificationManager.Policy.PRIORITY_SENDERS_ANY, 1874 currPolicy.priorityMessageSenders, 1875 currPolicy.suppressedVisualEffects); 1876 mNotificationManager.setNotificationPolicy(newPolicy); 1877 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 1878 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 1879 1880 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, false); 1881 aliceUri = lookupContact(ALICE_PHONE); 1882 1883 Uri alicePhoneUri = makePhoneUri(ALICE_PHONE); 1884 assertTrue(mNotificationManager.matchesCallFilter(alicePhoneUri)); 1885 } finally { 1886 mNotificationManager.setInterruptionFilter(origFilter); 1887 mNotificationManager.setNotificationPolicy(origPolicy); 1888 if (aliceUri != null) { 1889 // delete the contact 1890 deleteSingleContact(aliceUri); 1891 } 1892 } 1893 } 1894 1895 @Test testInterruptionFilterNoneInterceptsMessages()1896 public void testInterruptionFilterNoneInterceptsMessages() throws Exception { 1897 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, true); 1898 insertSingleContact(BOB, BOB_PHONE, BOB_EMAIL, false); 1899 // Not Charlie 1900 1901 mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE); 1902 sendNotifications(MODE_URI, false, false); 1903 1904 StatusBarNotification alice = mNotificationHelper.findPostedNotification(ALICE, 1, 1905 SEARCH_TYPE.POSTED); 1906 StatusBarNotification bob = mNotificationHelper.findPostedNotification(BOB, 2, 1907 SEARCH_TYPE.POSTED); 1908 StatusBarNotification charlie = mNotificationHelper.findPostedNotification(CHARLIE, 3, 1909 SEARCH_TYPE.POSTED); 1910 1911 assertTrue(mListener.mIntercepted.get(alice.getKey())); 1912 assertTrue(mListener.mIntercepted.get(bob.getKey())); 1913 assertTrue(mListener.mIntercepted.get(charlie.getKey())); 1914 } 1915 1916 @Test testInterruptionFilterNoneInterceptsEventAlarmReminder()1917 public void testInterruptionFilterNoneInterceptsEventAlarmReminder() throws Exception { 1918 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, true); 1919 insertSingleContact(BOB, BOB_PHONE, BOB_EMAIL, false); 1920 // Not Charlie 1921 1922 mNotificationManager.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE); 1923 sendEventAlarmReminderNotifications(SEND_ALL); 1924 1925 StatusBarNotification alice = mNotificationHelper.findPostedNotification(ALICE, 4, 1926 SEARCH_TYPE.POSTED); 1927 StatusBarNotification bob = mNotificationHelper.findPostedNotification(BOB, 5, 1928 SEARCH_TYPE.POSTED); 1929 StatusBarNotification charlie = mNotificationHelper.findPostedNotification(CHARLIE, 6, 1930 SEARCH_TYPE.POSTED); 1931 1932 assertTrue(mListener.mIntercepted.get(alice.getKey())); 1933 assertTrue(mListener.mIntercepted.get(bob.getKey())); 1934 assertTrue(mListener.mIntercepted.get(charlie.getKey())); 1935 } 1936 1937 @Test testInterruptionFilterAllInterceptsNothing()1938 public void testInterruptionFilterAllInterceptsNothing() throws Exception { 1939 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, true); 1940 insertSingleContact(BOB, BOB_PHONE, BOB_EMAIL, false); 1941 // Not Charlie 1942 1943 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL); 1944 sendNotifications(MODE_URI, false, false); 1945 sendEventAlarmReminderNotifications(SEND_ALL); 1946 sendAlarmOtherMediaNotifications(SEND_ALL); 1947 1948 StatusBarNotification alice = mNotificationHelper.findPostedNotification(ALICE, 1, 1949 SEARCH_TYPE.POSTED); 1950 StatusBarNotification bob = mNotificationHelper.findPostedNotification(BOB, 2, 1951 SEARCH_TYPE.POSTED); 1952 StatusBarNotification charlie = mNotificationHelper.findPostedNotification(CHARLIE, 3, 1953 SEARCH_TYPE.POSTED); 1954 1955 StatusBarNotification aliceEvent = mNotificationHelper.findPostedNotification(ALICE, 4, 1956 SEARCH_TYPE.POSTED); 1957 StatusBarNotification bobAlarm = mNotificationHelper.findPostedNotification(BOB, 5, 1958 SEARCH_TYPE.POSTED); 1959 StatusBarNotification charlieReminder = mNotificationHelper.findPostedNotification(CHARLIE, 6, 1960 SEARCH_TYPE.POSTED); 1961 1962 StatusBarNotification aliceAlarm = mNotificationHelper.findPostedNotification(ALICE, 7, 1963 SEARCH_TYPE.POSTED); 1964 StatusBarNotification bobOther = mNotificationHelper.findPostedNotification(BOB, 8, 1965 SEARCH_TYPE.POSTED); 1966 StatusBarNotification charlieMedia = mNotificationHelper.findPostedNotification(CHARLIE, 9, 1967 SEARCH_TYPE.POSTED); 1968 1969 assertFalse(mListener.mIntercepted.get(alice.getKey())); 1970 assertFalse(mListener.mIntercepted.get(bob.getKey())); 1971 assertFalse(mListener.mIntercepted.get(charlie.getKey())); 1972 assertFalse(mListener.mIntercepted.get(aliceEvent.getKey())); 1973 assertFalse(mListener.mIntercepted.get(bobAlarm.getKey())); 1974 assertFalse(mListener.mIntercepted.get(charlieReminder.getKey())); 1975 assertFalse(mListener.mIntercepted.get(aliceAlarm.getKey())); 1976 assertFalse(mListener.mIntercepted.get(bobOther.getKey())); 1977 assertFalse(mListener.mIntercepted.get(charlieMedia.getKey())); 1978 } 1979 1980 @Test testPriorityStarredMessages()1981 public void testPriorityStarredMessages() throws Exception { 1982 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, true); 1983 assertTrue(isStarred(lookupContact(ALICE_PHONE))); 1984 insertSingleContact(BOB, BOB_PHONE, BOB_EMAIL, false); 1985 // Not Charlie 1986 1987 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 1988 NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy(); 1989 policy = new NotificationManager.Policy( 1990 NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES, 1991 policy.priorityCallSenders, 1992 PRIORITY_SENDERS_STARRED); 1993 mNotificationManager.setNotificationPolicy(policy); 1994 sendNotifications(MODE_URI, false, false); 1995 1996 StatusBarNotification alice = mNotificationHelper.findPostedNotification(ALICE, 1, 1997 SEARCH_TYPE.POSTED); 1998 StatusBarNotification bob = mNotificationHelper.findPostedNotification(BOB, 2, 1999 SEARCH_TYPE.POSTED); 2000 StatusBarNotification charlie = mNotificationHelper.findPostedNotification(CHARLIE, 3, 2001 SEARCH_TYPE.POSTED); 2002 2003 // wait for contacts lookup in NMS to finish so we have the correct interception info 2004 boolean isAliceIntercepted = true; 2005 for (int i = 0; i < 6; i++) { 2006 isAliceIntercepted = mListener.mIntercepted.get(alice.getKey()); 2007 if (!isAliceIntercepted) { 2008 break; 2009 } 2010 sleep(); 2011 } 2012 assertFalse(isAliceIntercepted); 2013 assertTrue(mListener.mIntercepted.get(bob.getKey())); 2014 assertTrue(mListener.mIntercepted.get(charlie.getKey())); 2015 } 2016 2017 @Test testPriorityInterceptsAlarms()2018 public void testPriorityInterceptsAlarms() throws Exception { 2019 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, true); 2020 insertSingleContact(BOB, BOB_PHONE, BOB_EMAIL, false); 2021 // Not Charlie 2022 2023 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 2024 NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy(); 2025 policy = new NotificationManager.Policy( 2026 NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS, 2027 policy.priorityCallSenders, 2028 policy.priorityMessageSenders); 2029 mNotificationManager.setNotificationPolicy(policy); 2030 sendEventAlarmReminderNotifications(SEND_ALL); 2031 2032 StatusBarNotification alice = mNotificationHelper.findPostedNotification(ALICE, 4, 2033 SEARCH_TYPE.POSTED); 2034 StatusBarNotification bob = mNotificationHelper.findPostedNotification(BOB, 5, 2035 SEARCH_TYPE.POSTED); 2036 StatusBarNotification charlie = mNotificationHelper.findPostedNotification(CHARLIE, 6, 2037 SEARCH_TYPE.POSTED); 2038 2039 boolean isBobIntercepted = true; 2040 for (int i = 0; i < 6; i++) { 2041 isBobIntercepted = mListener.mIntercepted.get(bob.getKey()); 2042 if (!isBobIntercepted) { 2043 break; 2044 } 2045 sleep(); 2046 } 2047 assertFalse(isBobIntercepted); 2048 2049 assertTrue(mListener.mIntercepted.get(alice.getKey())); 2050 assertTrue(mListener.mIntercepted.get(charlie.getKey())); 2051 } 2052 2053 @Test testPriorityInterceptsMediaSystemOther()2054 public void testPriorityInterceptsMediaSystemOther() throws Exception { 2055 insertSingleContact(ALICE, ALICE_PHONE, ALICE_EMAIL, true); 2056 insertSingleContact(BOB, BOB_PHONE, BOB_EMAIL, false); 2057 // Not Charlie 2058 2059 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 2060 NotificationManager.Policy policy = mNotificationManager.getNotificationPolicy(); 2061 policy = new NotificationManager.Policy( 2062 NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA, 2063 policy.priorityCallSenders, 2064 policy.priorityMessageSenders); 2065 mNotificationManager.setNotificationPolicy(policy); 2066 sendAlarmOtherMediaNotifications(SEND_ALL); 2067 2068 StatusBarNotification alice = mNotificationHelper.findPostedNotification(ALICE, 7, 2069 SEARCH_TYPE.POSTED); 2070 StatusBarNotification bob = mNotificationHelper.findPostedNotification(BOB, 8, 2071 SEARCH_TYPE.POSTED); 2072 StatusBarNotification charlie = mNotificationHelper.findPostedNotification(CHARLIE, 9, 2073 SEARCH_TYPE.POSTED); 2074 2075 boolean isBobIntercepted = true; 2076 for (int i = 0; i < 6; i++) { 2077 isBobIntercepted = mListener.mIntercepted.get(bob.getKey()); 2078 if (!isBobIntercepted) { 2079 break; 2080 } 2081 sleep(); 2082 } 2083 assertFalse(isBobIntercepted); 2084 2085 2086 boolean isCharlieIntercepted = true; 2087 for (int i = 0; i < 6; i++) { 2088 isCharlieIntercepted = mListener.mIntercepted.get(charlie.getKey()); 2089 if (!isCharlieIntercepted) { 2090 break; 2091 } 2092 sleep(); 2093 } 2094 if (android.app.Flags.restrictAudioAttributesMedia()) { 2095 // media notifications are moved to notification stream, so they should be intercepted 2096 assertTrue(isCharlieIntercepted); 2097 } else { 2098 assertFalse(isCharlieIntercepted); 2099 } 2100 2101 assertTrue(mListener.mIntercepted.get(alice.getKey())); 2102 } 2103 2104 @Test 2105 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) testPriorityChannelNotInterceptedByDefault()2106 public void testPriorityChannelNotInterceptedByDefault() throws Exception { 2107 toggleNotificationPolicyAccess(mContext.getPackageName(), 2108 InstrumentationRegistry.getInstrumentation(), true); 2109 2110 // Setup: no contacts, so nobody counts as "priority" in terms of senders. 2111 // Construct a policy that doesn't allow anything except priority channels through; 2112 // apply it via zen rule 2113 AutomaticZenRule rule = createRule("test_channel_bypass", 2114 INTERRUPTION_FILTER_PRIORITY); 2115 rule.setZenPolicy(new ZenPolicy.Builder().disallowAllSounds().build()); 2116 String id = mNotificationManager.addAutomaticZenRule(rule); 2117 2118 // enable rule 2119 Condition condition = new Condition(rule.getConditionId(), "summary", 2120 Condition.STATE_TRUE); 2121 mNotificationManager.setAutomaticZenRuleState(id, condition); 2122 2123 Thread.sleep(300); // wait for rules to be applied - it's done asynchronously 2124 2125 // Create a notification under the PRIORITY (set to bypass DND) channel and send. 2126 Notification.Builder notif = new Notification.Builder(mContext, 2127 NOTIFICATION_CHANNEL_ID_PRIORITY) 2128 .setContentTitle(NAME) 2129 .setContentText("content") 2130 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2131 .setCategory(Notification.CATEGORY_MESSAGE) 2132 .setWhen(System.currentTimeMillis() - 1000000L); 2133 mNotificationManager.notify(NAME, 1, notif.build()); 2134 2135 StatusBarNotification sbn = mNotificationHelper.findPostedNotification(NAME, 1, 2136 SEARCH_TYPE.POSTED); 2137 2138 // should not be intercepted because priority channels are allowed. 2139 assertFalse(mListener.mIntercepted.get(sbn.getKey())); 2140 } 2141 2142 @Test 2143 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) testPriorityChannelInterceptedWhenChannelsDisallowed()2144 public void testPriorityChannelInterceptedWhenChannelsDisallowed() throws Exception { 2145 toggleNotificationPolicyAccess(mContext.getPackageName(), 2146 InstrumentationRegistry.getInstrumentation(), true); 2147 2148 // Setup: no contacts, so nobody counts as "priority" in terms of senders, not that the 2149 // policy allows senders anyway. 2150 // Construct a policy that doesn't allow anything through and also disallows channels. 2151 AutomaticZenRule rule = createRule("test_channels_disallowed", 2152 INTERRUPTION_FILTER_PRIORITY); 2153 rule.setZenPolicy(new ZenPolicy.Builder() 2154 .disallowAllSounds() 2155 .allowPriorityChannels(false) 2156 .build()); 2157 String id = mNotificationManager.addAutomaticZenRule(rule); 2158 2159 // enable rule 2160 Condition condition = new Condition(rule.getConditionId(), "summary", 2161 Condition.STATE_TRUE); 2162 mNotificationManager.setAutomaticZenRuleState(id, condition); 2163 Thread.sleep(300); // wait for rules to be applied - it's done asynchronously 2164 2165 // Send notification under the priority channel. 2166 Notification.Builder notif = new Notification.Builder(mContext, 2167 NOTIFICATION_CHANNEL_ID_PRIORITY) 2168 .setContentTitle(NAME) 2169 .setContentText("content") 2170 .setSmallIcon(android.R.drawable.sym_def_app_icon) 2171 .setCategory(Notification.CATEGORY_MESSAGE) 2172 .setWhen(System.currentTimeMillis() - 1000000L); 2173 mNotificationManager.notify(NAME, 1, notif.build()); 2174 2175 StatusBarNotification sbn = mNotificationHelper.findPostedNotification(NAME, 1, 2176 SEARCH_TYPE.POSTED); 2177 2178 // Notification should be intercepted now 2179 assertTrue(mListener.mIntercepted.get(sbn.getKey())); 2180 } 2181 2182 @Test 2183 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) testAddAutomaticZenRule_includesModesApiFields()2184 public void testAddAutomaticZenRule_includesModesApiFields() throws Exception { 2185 toggleNotificationPolicyAccess(mContext.getPackageName(), 2186 InstrumentationRegistry.getInstrumentation(), true); 2187 2188 AutomaticZenRule ruleToCreate = new AutomaticZenRule.Builder(NAME, CONDITION_ID) 2189 .setZenPolicy(POLICY) 2190 .setManualInvocationAllowed(ALLOW_MANUAL) 2191 .setOwner(null) 2192 .setType(UNRESTRICTED_TYPE) 2193 .setConfigurationActivity(CONFIG_ACTIVITY) 2194 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) 2195 .setTriggerDescription(TRIGGER_DESC) 2196 .setIconResId(ICON_RES_ID) 2197 .build(); 2198 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 2199 2200 assertNotNull(id); 2201 assertRulesEqual(ruleToCreate, mNotificationManager.getAutomaticZenRule(id)); 2202 } 2203 2204 @Test testSnoozeRule()2205 public void testSnoozeRule() throws Exception { 2206 if (!Flags.modesApi() || !CompatChanges.isChangeEnabled(308673617)) { 2207 Log.d(TAG, "Skipping testSnoozeRule() " 2208 + Flags.modesApi() + " " + Build.VERSION.SDK_INT); 2209 return; 2210 } 2211 NotificationManagerBroadcastReceiver br = new NotificationManagerBroadcastReceiver(); 2212 br.register(mContext, ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED, 2); 2213 2214 toggleNotificationPolicyAccess(mContext.getPackageName(), 2215 InstrumentationRegistry.getInstrumentation(), true); 2216 2217 AutomaticZenRule ruleToCreate = createRule("testSnoozeRule"); 2218 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 2219 2220 // enable DND 2221 Condition condition = 2222 new Condition(ruleToCreate.getConditionId(), "summary", Condition.STATE_TRUE); 2223 mNotificationManager.setAutomaticZenRuleState(id, condition); 2224 2225 // snooze the rule 2226 runAsSystemUi(() -> mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL)); 2227 2228 assertEquals(AUTOMATIC_RULE_STATUS_ACTIVATED, 2229 br.getExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, 0, 500)); 2230 assertEquals(AUTOMATIC_RULE_STATUS_DEACTIVATED, 2231 br.getExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, 1, 500)); 2232 br.unregister(); 2233 } 2234 2235 @Test testUnsnoozeRule_disableEnable()2236 public void testUnsnoozeRule_disableEnable() throws Exception { 2237 if (!Flags.modesApi()) { 2238 Log.d(TAG, "Skipping testUnsnoozeRule_disableEnable() " + Flags.modesApi() 2239 + " " + Build.VERSION.SDK_INT); 2240 return; 2241 } 2242 NotificationManagerBroadcastReceiver br = new NotificationManagerBroadcastReceiver(); 2243 br.register(mContext, ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED, 3); 2244 2245 toggleNotificationPolicyAccess(mContext.getPackageName(), 2246 InstrumentationRegistry.getInstrumentation(), true); 2247 2248 // No broadcast expected on creation 2249 AutomaticZenRule ruleToCreate = createRule("testUnsnoozeRule_disableEnable"); 2250 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 2251 2252 // enable DND 2253 Condition condition = 2254 new Condition(ruleToCreate.getConditionId(), "summary", Condition.STATE_TRUE); 2255 // triggers ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED: Enabled 2256 mNotificationManager.setAutomaticZenRuleState(id, condition); 2257 2258 // snooze the rule by pretending the user turned off the mode from SystemUI 2259 // triggers ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED: Deactivated 2260 runAsSystemUi(() -> mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL)); 2261 assertExpectedDndState(INTERRUPTION_FILTER_ALL); 2262 2263 // disable the rule. should unsnooze. 2264 ruleToCreate.setEnabled(false); 2265 mNotificationManager.updateAutomaticZenRule(id, ruleToCreate); 2266 2267 assertEquals(AUTOMATIC_RULE_STATUS_DISABLED, 2268 br.getExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, 2, 500)); 2269 br.unregister(); 2270 2271 br = new NotificationManagerBroadcastReceiver(); 2272 br.register(mContext, ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED, 2); 2273 2274 // re-enable and activate 2275 ruleToCreate.setEnabled(true); 2276 mNotificationManager.updateAutomaticZenRule(id, ruleToCreate); 2277 mNotificationManager.setAutomaticZenRuleState(id, condition); 2278 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 2279 2280 assertEquals(AUTOMATIC_RULE_STATUS_ENABLED, 2281 br.getExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, 0, 500)); 2282 if (CompatChanges.isChangeEnabled(308673617)) { 2283 assertEquals(AUTOMATIC_RULE_STATUS_ACTIVATED, 2284 br.getExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, 1, 500)); 2285 } else { 2286 assertEquals(AUTOMATIC_RULE_STATUS_UNKNOWN, 2287 br.getExtra(EXTRA_AUTOMATIC_ZEN_RULE_STATUS, 1, 500)); 2288 } 2289 br.unregister(); 2290 } 2291 2292 @Test testGetAutomaticZenRules()2293 public void testGetAutomaticZenRules() { 2294 assertThat(mNotificationManager.getAutomaticZenRules()).isEmpty(); 2295 2296 AutomaticZenRule rule1 = createRule("One"); 2297 AutomaticZenRule rule2 = createRule("Two"); 2298 if (Flags.modesApi()) { 2299 rule1 = new AutomaticZenRule.Builder(rule1) 2300 .setType(AutomaticZenRule.TYPE_DRIVING) 2301 .setManualInvocationAllowed(true) 2302 .build(); 2303 rule2 = new AutomaticZenRule.Builder(rule2) 2304 .setTriggerDescription("On the twelfth day of Christmas") 2305 .setIconResId(R.drawable.icon_green) 2306 .build(); 2307 } 2308 String ruleId1 = mNotificationManager.addAutomaticZenRule(rule1); 2309 String ruleId2 = mNotificationManager.addAutomaticZenRule(rule2); 2310 2311 Map<String, AutomaticZenRule> rules = mNotificationManager.getAutomaticZenRules(); 2312 2313 assertThat(rules).hasSize(2); 2314 assertRulesEqual(rules.get(ruleId1), rule1); 2315 assertRulesEqual(rules.get(ruleId2), rule2); 2316 } 2317 assertRulesEqual(AutomaticZenRule r1, AutomaticZenRule r2)2318 private void assertRulesEqual(AutomaticZenRule r1, AutomaticZenRule r2) { 2319 // Cannot test for exact equality because some extra fields (e.g. packageName, 2320 // creationTime) come back. So we verify everything that the client app can set. 2321 assertThat(r1.getConditionId()).isEqualTo(r2.getConditionId()); 2322 assertThat(r1.getConfigurationActivity()).isEqualTo(r2.getConfigurationActivity()); 2323 assertThat(r1.getInterruptionFilter()).isEqualTo(r2.getInterruptionFilter()); 2324 assertThat(r1.getName()).isEqualTo(r2.getName()); 2325 assertThat(r1.getOwner()).isEqualTo(r2.getOwner()); 2326 assertThat(r1.isEnabled()).isEqualTo(r2.isEnabled()); 2327 2328 if (Flags.modesApi()) { 2329 assertThat(r1.getDeviceEffects()).isEqualTo(r2.getDeviceEffects()); 2330 assertThat(doPoliciesMatchWithDefaults(r1.getZenPolicy(), r2.getZenPolicy())).isTrue(); 2331 2332 assertThat(r1.getIconResId()).isEqualTo(r2.getIconResId()); 2333 assertThat(r1.getTriggerDescription()).isEqualTo(r2.getTriggerDescription()); 2334 assertThat(r1.getType()).isEqualTo(r2.getType()); 2335 assertThat(r1.isManualInvocationAllowed()).isEqualTo(r2.isManualInvocationAllowed()); 2336 } else { 2337 assertThat(r1.getZenPolicy()).isEqualTo(r2.getZenPolicy()); 2338 } 2339 } 2340 2341 // Checks that the priority categories in the provided NotificationManager.Policy match 2342 // those of the provided ZenPolicy. Does not check call/message/conversation senders or 2343 // visual effects. assertPolicyCategoriesMatchZenPolicy( NotificationManager.Policy nmPolicy, ZenPolicy zenPolicy)2344 private void assertPolicyCategoriesMatchZenPolicy( 2345 NotificationManager.Policy nmPolicy, ZenPolicy zenPolicy) { 2346 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_ALARMS) != 0) 2347 .isEqualTo(zenPolicy.getPriorityCategoryAlarms() == ZenPolicy.STATE_ALLOW); 2348 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_CALLS) != 0) 2349 .isEqualTo(zenPolicy.getPriorityCategoryCalls() == ZenPolicy.STATE_ALLOW); 2350 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_CONVERSATIONS) != 0) 2351 .isEqualTo(zenPolicy.getPriorityCategoryConversations() == ZenPolicy.STATE_ALLOW); 2352 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_EVENTS) != 0) 2353 .isEqualTo(zenPolicy.getPriorityCategoryEvents() == ZenPolicy.STATE_ALLOW); 2354 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_MEDIA) != 0) 2355 .isEqualTo(zenPolicy.getPriorityCategoryMedia() == ZenPolicy.STATE_ALLOW); 2356 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_MESSAGES) != 0) 2357 .isEqualTo(zenPolicy.getPriorityCategoryMessages() == ZenPolicy.STATE_ALLOW); 2358 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_REMINDERS) != 0) 2359 .isEqualTo(zenPolicy.getPriorityCategoryReminders() == ZenPolicy.STATE_ALLOW); 2360 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_REPEAT_CALLERS) != 0) 2361 .isEqualTo(zenPolicy.getPriorityCategoryRepeatCallers() == ZenPolicy.STATE_ALLOW); 2362 assertThat((nmPolicy.priorityCategories & PRIORITY_CATEGORY_SYSTEM) != 0) 2363 .isEqualTo(zenPolicy.getPriorityCategorySystem() == ZenPolicy.STATE_ALLOW); 2364 } 2365 2366 @Test 2367 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) addAutomaticZenRule_withInterruptionFilterAll_canBeUsed()2368 public void addAutomaticZenRule_withInterruptionFilterAll_canBeUsed() 2369 throws InterruptedException { 2370 AutomaticZenRule rule = createRule("Without filter", INTERRUPTION_FILTER_ALL); 2371 rule.setDeviceEffects( 2372 new ZenDeviceEffects.Builder().setShouldDisplayGrayscale(true).build()); 2373 2374 String ruleId = mNotificationManager.addAutomaticZenRule(rule); 2375 2376 AutomaticZenRule savedRule = mNotificationManager.getAutomaticZenRule(ruleId); 2377 assertThat(savedRule).isNotNull(); 2378 assertThat(savedRule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_ALL); 2379 2380 // Simple update, just to verify no validation errors. 2381 savedRule.setName("Still without filter"); 2382 mNotificationManager.updateAutomaticZenRule(ruleId, savedRule); 2383 2384 mNotificationManager.setAutomaticZenRuleState(ruleId, 2385 new Condition(rule.getConditionId(), "summary", Condition.STATE_TRUE)); 2386 assertThat(mNotificationManager.getCurrentInterruptionFilter()).isEqualTo( 2387 INTERRUPTION_FILTER_ALL); 2388 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2389 assertThat(isColorDisplayManagerSaturationActivated()).isTrue(); 2390 2391 mNotificationManager.setAutomaticZenRuleState(ruleId, 2392 new Condition(rule.getConditionId(), "summary", Condition.STATE_FALSE)); 2393 assertThat(mNotificationManager.getCurrentInterruptionFilter()).isEqualTo( 2394 INTERRUPTION_FILTER_ALL); 2395 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2396 assertThat(isColorDisplayManagerSaturationActivated()).isFalse(); 2397 2398 mNotificationManager.removeAutomaticZenRule(ruleId); 2399 assertThat(mNotificationManager.getAutomaticZenRules()).isEmpty(); 2400 } 2401 2402 @Test 2403 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) addAutomaticZenRule_fromUser_onlyAcceptedFromSystem()2404 public void addAutomaticZenRule_fromUser_onlyAcceptedFromSystem() { 2405 AutomaticZenRule newRule = createRule("Test"); 2406 2407 String rule1 = mNotificationManager.addAutomaticZenRule(newRule, /* fromUser= */ false); 2408 2409 assertThrows(SecurityException.class, 2410 () -> mNotificationManager.addAutomaticZenRule(newRule, /* fromUser= */ true)); 2411 2412 String rule2 = callAsSystemUi( 2413 () -> mNotificationManager.addAutomaticZenRule(newRule, /* fromUser= */ true)); 2414 2415 assertThat(mNotificationManager.getAutomaticZenRule(rule1)).isNotNull(); 2416 assertThat(mNotificationManager.getAutomaticZenRule(rule2)).isNotNull(); 2417 } 2418 2419 @Test 2420 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) updateAutomaticZenRule_fromUser_updatesRuleFully()2421 public void updateAutomaticZenRule_fromUser_updatesRuleFully() { 2422 AutomaticZenRule original = new AutomaticZenRule.Builder("Original", CONDITION_ID) 2423 .setConfigurationActivity(CONFIG_ACTIVITY) 2424 .setType(AutomaticZenRule.TYPE_IMMERSIVE) 2425 .setIconResId(android.app.notification.current.cts.R.drawable.ic_android) 2426 .setTriggerDescription("Immerse yourself") 2427 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) 2428 .setZenPolicy(new ZenPolicy.Builder() 2429 .allowRepeatCallers(false) 2430 .allowAlarms(false) 2431 .build()) 2432 .setDeviceEffects(new ZenDeviceEffects.Builder() 2433 .setShouldDisplayGrayscale(true) 2434 .build()) 2435 .build(); 2436 String ruleId = mNotificationManager.addAutomaticZenRule(original); 2437 ZenPolicy combinedPolicy = original.getZenPolicy(); 2438 2439 // Update the rule "from user" once. 2440 // Set settings for events & calls that do not match the default so we're certain these 2441 // changes will reflect that the "user" actually changed the fields. 2442 AutomaticZenRule firstUserUpdate = new AutomaticZenRule.Builder(original) 2443 .setName("First update") 2444 .setZenPolicy(new ZenPolicy.Builder() 2445 .allowEvents( 2446 mDefaultPolicy.getPriorityCategoryEvents() != ZenPolicy.STATE_ALLOW) 2447 .allowCalls(mDefaultPolicy.getPriorityCallSenders() 2448 == ZenPolicy.PEOPLE_TYPE_ANYONE 2449 ? ZenPolicy.PEOPLE_TYPE_CONTACTS 2450 : ZenPolicy.PEOPLE_TYPE_ANYONE) 2451 .build()) 2452 .build(); 2453 runAsSystemUi( 2454 () -> mNotificationManager.updateAutomaticZenRule(ruleId, firstUserUpdate, 2455 /* fromUser= */ true)); 2456 2457 // Verify the update succeeded. 2458 combinedPolicy = combinedPolicy.overwrittenWith(firstUserUpdate.getZenPolicy()); 2459 AutomaticZenRule firstUserUpdateResult = mNotificationManager.getAutomaticZenRule(ruleId); 2460 AutomaticZenRule expectedRuleAfterFirstUpdate = 2461 new AutomaticZenRule.Builder(firstUserUpdate) 2462 .setZenPolicy(combinedPolicy) 2463 .build(); 2464 assertRulesEqual(expectedRuleAfterFirstUpdate, firstUserUpdateResult); 2465 2466 // Update the rule "from user" a second time. 2467 AutomaticZenRule secondUserUpdate = new AutomaticZenRule.Builder(original) 2468 // User changes 2469 .setName("Updated again") 2470 .setEnabled(false) 2471 .setZenPolicy(new ZenPolicy.Builder() 2472 .allowMedia(true) 2473 .allowCalls(ZenPolicy.PEOPLE_TYPE_CONTACTS) 2474 .build()) 2475 .setDeviceEffects(new ZenDeviceEffects.Builder(original.getDeviceEffects()) 2476 .setShouldDimWallpaper(true) 2477 .build()) 2478 // Technically nothing stops this API call from also updating fields that should be 2479 // the purview of the app. 2480 .setType(AutomaticZenRule.TYPE_DRIVING) 2481 .setTriggerDescription("While driving") 2482 .setIconResId(android.R.drawable.sym_def_app_icon) 2483 .build(); 2484 runAsSystemUi( 2485 () -> mNotificationManager.updateAutomaticZenRule(ruleId, secondUserUpdate, 2486 /* fromUser= */ true)); 2487 2488 // The second update succeeded as well. 2489 combinedPolicy = combinedPolicy.overwrittenWith(secondUserUpdate.getZenPolicy()); 2490 AutomaticZenRule secondUserUpdateResult = mNotificationManager.getAutomaticZenRule(ruleId); 2491 AutomaticZenRule expectedRuleAfterSecondUpdate = 2492 new AutomaticZenRule.Builder(secondUserUpdate) 2493 .setZenPolicy(combinedPolicy) 2494 .build(); 2495 assertRulesEqual(expectedRuleAfterSecondUpdate, secondUserUpdateResult); 2496 } 2497 2498 @Test 2499 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) updateAutomaticZenRule_fromApp_forNonUserModifiedRule_allFieldsUpdated()2500 public void updateAutomaticZenRule_fromApp_forNonUserModifiedRule_allFieldsUpdated() { 2501 AutomaticZenRule original = new AutomaticZenRule.Builder("Original", CONDITION_ID) 2502 .setConfigurationActivity(CONFIG_ACTIVITY) 2503 .setType(AutomaticZenRule.TYPE_IMMERSIVE) 2504 .setIconResId(android.app.notification.current.cts.R.drawable.ic_android) 2505 .setTriggerDescription("Immerse yourself") 2506 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) 2507 .setZenPolicy(new ZenPolicy.Builder() 2508 .allowRepeatCallers(false) 2509 .allowAlarms(false) 2510 .build()) 2511 .setDeviceEffects(new ZenDeviceEffects.Builder() 2512 .setShouldDisplayGrayscale(true) 2513 .build()) 2514 .build(); 2515 String ruleId = mNotificationManager.addAutomaticZenRule(original); 2516 2517 // Update the rule "from app". 2518 AutomaticZenRule appUpdate = new AutomaticZenRule.Builder(original) 2519 .setName("Updated") 2520 .setType(AutomaticZenRule.TYPE_DRIVING) 2521 .setTriggerDescription("While driving") 2522 .setIconResId(android.R.drawable.sym_def_app_icon) 2523 .setEnabled(false) 2524 .setZenPolicy(new ZenPolicy.Builder(original.getZenPolicy()) 2525 .allowMedia(true) 2526 .allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE) 2527 .build()) 2528 .setDeviceEffects(new ZenDeviceEffects.Builder(original.getDeviceEffects()) 2529 .setShouldDimWallpaper(true) 2530 .build()) 2531 .build(); 2532 mNotificationManager.updateAutomaticZenRule(ruleId, appUpdate); 2533 2534 // Verify the update succeeded. 2535 AutomaticZenRule result = mNotificationManager.getAutomaticZenRule(ruleId); 2536 assertRulesEqual(appUpdate, result); 2537 } 2538 2539 @Test 2540 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) updateAutomaticZenRule_fromApp_forUserModifiedRule_onlySomeFieldsUpdated()2541 public void updateAutomaticZenRule_fromApp_forUserModifiedRule_onlySomeFieldsUpdated() { 2542 AutomaticZenRule original = new AutomaticZenRule.Builder("Original", CONDITION_ID) 2543 .setConfigurationActivity(CONFIG_ACTIVITY) 2544 .setType(AutomaticZenRule.TYPE_IMMERSIVE) 2545 .setIconResId(android.app.notification.current.cts.R.drawable.ic_android) 2546 .setTriggerDescription("Immerse yourself") 2547 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) 2548 .setZenPolicy(new ZenPolicy.Builder() 2549 .allowRepeatCallers(false) 2550 .allowAlarms(false) 2551 .build()) 2552 .setDeviceEffects(new ZenDeviceEffects.Builder() 2553 .setShouldDisplayGrayscale(true) 2554 .build()) 2555 .build(); 2556 String ruleId = mNotificationManager.addAutomaticZenRule(original); 2557 2558 // Minimally update the rule "from user". 2559 AutomaticZenRule userUpdate = new AutomaticZenRule.Builder(original) 2560 // User changes 2561 .setName("Updated by user") 2562 .build(); 2563 runAsSystemUi( 2564 () -> mNotificationManager.updateAutomaticZenRule(ruleId, userUpdate, 2565 /* fromUser= */ true)); 2566 2567 // Now try to update again "from app". 2568 AutomaticZenRule appUpdate = new AutomaticZenRule.Builder(original) 2569 .setName("Updated") 2570 .setType(AutomaticZenRule.TYPE_DRIVING) 2571 .setTriggerDescription("While driving") 2572 .setIconResId(android.R.drawable.sym_def_app_icon) 2573 .setEnabled(false) 2574 .setZenPolicy(new ZenPolicy.Builder(original.getZenPolicy()) 2575 .allowAlarms(true) 2576 .allowCalls(ZenPolicy.PEOPLE_TYPE_ANYONE) 2577 .build()) 2578 .setDeviceEffects(new ZenDeviceEffects.Builder(original.getDeviceEffects()) 2579 .setShouldDimWallpaper(true) 2580 .build()) 2581 .build(); 2582 mNotificationManager.updateAutomaticZenRule(ruleId, appUpdate); 2583 2584 // The app-controlled fields should be updated. 2585 AutomaticZenRule result = mNotificationManager.getAutomaticZenRule(ruleId); 2586 assertThat(result.getType()).isEqualTo(appUpdate.getType()); 2587 assertThat(result.getTriggerDescription()).isEqualTo(appUpdate.getTriggerDescription()); 2588 if (!Flags.modesUi()) { 2589 assertThat(result.getIconResId()).isEqualTo(appUpdate.getIconResId()); 2590 } 2591 assertThat(result.isEnabled()).isEqualTo(appUpdate.isEnabled()); 2592 2593 // ... but nothing else should (even though those fields were not _specifically_ modified by 2594 // the user). 2595 assertThat(result.getName()).isEqualTo(userUpdate.getName()); 2596 if (Flags.modesUi()) { 2597 assertThat(result.getIconResId()).isEqualTo(userUpdate.getIconResId()); 2598 } 2599 assertThat(doPoliciesMatchWithDefaults(result.getZenPolicy(), original.getZenPolicy())) 2600 .isTrue(); 2601 assertThat(result.getDeviceEffects()).isEqualTo(original.getDeviceEffects()); 2602 } 2603 2604 @Test 2605 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) addAutomaticZenRule_forDeletedAndPreviouslyUserModifiedRule_restoresRule()2606 public void addAutomaticZenRule_forDeletedAndPreviouslyUserModifiedRule_restoresRule() { 2607 AutomaticZenRule original = new AutomaticZenRule.Builder("Original", CONDITION_ID) 2608 .setConfigurationActivity(CONFIG_ACTIVITY) 2609 .setType(AutomaticZenRule.TYPE_IMMERSIVE) 2610 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) 2611 .build(); 2612 String ruleId = mNotificationManager.addAutomaticZenRule(original); 2613 2614 // Rename it "from user". 2615 AutomaticZenRule userUpdate = new AutomaticZenRule.Builder(original) 2616 // User changes 2617 .setName("Updated by user") 2618 .build(); 2619 runAsSystemUi( 2620 () -> mNotificationManager.updateAutomaticZenRule(ruleId, userUpdate, 2621 /* fromUser= */ true)); 2622 2623 // Now delete it "from app". 2624 mNotificationManager.removeAutomaticZenRule(ruleId); 2625 assertThat(mNotificationManager.getAutomaticZenRule(ruleId)).isNull(); 2626 2627 // Now create it "from app" again, with a new name. 2628 AutomaticZenRule reAddRule = new AutomaticZenRule.Builder(original) 2629 .setName("Here we go again") 2630 .build(); 2631 String newRuleId = mNotificationManager.addAutomaticZenRule(reAddRule); 2632 2633 // The rule was added, but the user's customization was restored. 2634 AutomaticZenRule finalRule = mNotificationManager.getAutomaticZenRule(newRuleId); 2635 assertThat(finalRule).isNotNull(); 2636 assertThat(finalRule.getName()).isEqualTo("Updated by user"); 2637 } 2638 2639 @Test 2640 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) addAutomaticZenRule_withDeviceEffects_stored()2641 public void addAutomaticZenRule_withDeviceEffects_stored() { 2642 ZenDeviceEffects effects = new ZenDeviceEffects.Builder() 2643 .setShouldDisplayGrayscale(true) 2644 .setShouldUseNightMode(true) 2645 .build(); 2646 2647 AutomaticZenRule newRule = createRule("With effects"); 2648 newRule.setDeviceEffects(effects); 2649 2650 String ruleId = mNotificationManager.addAutomaticZenRule(newRule); 2651 AutomaticZenRule readRule = mNotificationManager.getAutomaticZenRule(ruleId); 2652 2653 assertThat(readRule.getDeviceEffects()).isEqualTo(effects); 2654 } 2655 2656 @Test 2657 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) addAutomaticZenRule_withDeviceExtraEffects_storedFromSystem()2658 public void addAutomaticZenRule_withDeviceExtraEffects_storedFromSystem() { 2659 ZenDeviceEffects effects = new ZenDeviceEffects.Builder() 2660 .setShouldDisplayGrayscale(true) 2661 .setShouldUseNightMode(true) 2662 .setExtraEffects(ImmutableSet.of("TIME_TRAVEL", "DINOSAUR_CLONING")) 2663 .build(); 2664 AutomaticZenRule newRule = createRule("With effects"); 2665 newRule.setDeviceEffects(effects); 2666 2667 String ruleId = callAsSystemUi(() -> mNotificationManager.addAutomaticZenRule(newRule)); 2668 2669 AutomaticZenRule readRule = mNotificationManager.getAutomaticZenRule(ruleId); 2670 assertThat(readRule.getDeviceEffects()).isEqualTo(effects); 2671 } 2672 2673 @Test 2674 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) addAutomaticZenRule_withUnderspecifiedPolicies_filledIn()2675 public void addAutomaticZenRule_withUnderspecifiedPolicies_filledIn() { 2676 AutomaticZenRule noPolicy = new AutomaticZenRule.Builder("no policy", CONDITION_ID) 2677 .setConfigurationActivity(CONFIG_ACTIVITY) 2678 .setType(AutomaticZenRule.TYPE_IMMERSIVE) 2679 .setIconResId(android.app.notification.current.cts.R.drawable.ic_android) 2680 .setTriggerDescription("whatever") 2681 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) 2682 .setZenPolicy(null) // not really necessary, but doing so explicitly anyway. 2683 .build(); 2684 String noPolicyRuleId = mNotificationManager.addAutomaticZenRule(noPolicy); 2685 2686 // The resulting actual policy on the rule should be equivalent to the default, with all 2687 // fields fully filled in (rather than being left as null). 2688 AutomaticZenRule readRule = mNotificationManager.getAutomaticZenRule(noPolicyRuleId); 2689 assertThat(readRule.getZenPolicy()).isEqualTo(mDefaultPolicy); 2690 2691 AutomaticZenRule underspecified = new AutomaticZenRule.Builder("some policy", CONDITION_ID) 2692 .setConfigurationActivity(CONFIG_ACTIVITY) 2693 .setType(AutomaticZenRule.TYPE_IMMERSIVE) 2694 .setIconResId(android.app.notification.current.cts.R.drawable.ic_android) 2695 .setTriggerDescription("whatever") 2696 .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) 2697 .setZenPolicy(new ZenPolicy.Builder() 2698 .allowAlarms(true) 2699 .allowMedia(false) 2700 .build()) 2701 .build(); 2702 String underspecRuleId = mNotificationManager.addAutomaticZenRule(underspecified); 2703 2704 AutomaticZenRule readRule2 = mNotificationManager.getAutomaticZenRule(underspecRuleId); 2705 assertThat(readRule2.getZenPolicy()).isEqualTo( 2706 mDefaultPolicy.overwrittenWith(underspecified.getZenPolicy())); 2707 } 2708 2709 @Test 2710 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) getAutomaticZenRuleState_returnsRuleState()2711 public void getAutomaticZenRuleState_returnsRuleState() { 2712 AutomaticZenRule rule = createRule("Test"); 2713 2714 String ruleId = mNotificationManager.addAutomaticZenRule(rule); 2715 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo( 2716 Condition.STATE_FALSE); 2717 2718 mNotificationManager.setAutomaticZenRuleState(ruleId, 2719 new Condition(rule.getConditionId(), "", Condition.STATE_TRUE)); 2720 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo( 2721 Condition.STATE_TRUE); 2722 2723 mNotificationManager.setAutomaticZenRuleState(ruleId, 2724 new Condition(rule.getConditionId(), "", Condition.STATE_FALSE)); 2725 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo( 2726 Condition.STATE_FALSE); 2727 2728 mNotificationManager.removeAutomaticZenRule(ruleId); 2729 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo( 2730 Condition.STATE_UNKNOWN); 2731 } 2732 2733 @Test 2734 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) setAutomaticZenRuleState_ruleWithGrayscale_applied()2735 public void setAutomaticZenRuleState_ruleWithGrayscale_applied() throws Exception { 2736 assertThat(isColorDisplayManagerSaturationActivated()).isFalse(); 2737 2738 AutomaticZenRule rule = createRule("Grayscale"); 2739 rule.setDeviceEffects(new ZenDeviceEffects.Builder() 2740 .setShouldDisplayGrayscale(true) 2741 .build()); 2742 String ruleId = mNotificationManager.addAutomaticZenRule(rule); 2743 2744 mNotificationManager.setAutomaticZenRuleState(ruleId, 2745 new Condition(rule.getConditionId(), "yeah", Condition.STATE_TRUE)); 2746 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2747 assertThat(isColorDisplayManagerSaturationActivated()).isTrue(); 2748 2749 mNotificationManager.setAutomaticZenRuleState(ruleId, 2750 new Condition(rule.getConditionId(), "nope", Condition.STATE_FALSE)); 2751 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2752 assertThat(isColorDisplayManagerSaturationActivated()).isFalse(); 2753 } 2754 2755 @Test 2756 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) setAutomaticZenRuleState_ruleWithDimWallpaper_applied()2757 public void setAutomaticZenRuleState_ruleWithDimWallpaper_applied() throws Exception { 2758 assumeTrue(mContext.getSystemService(WallpaperManager.class).isWallpaperSupported()); 2759 assertThat(getWallpaperManagerDimAmount()).isZero(); 2760 2761 AutomaticZenRule rule = createRule("Dim wallpaper"); 2762 rule.setDeviceEffects(new ZenDeviceEffects.Builder().setShouldDimWallpaper(true).build()); 2763 String ruleId = mNotificationManager.addAutomaticZenRule(rule); 2764 2765 mNotificationManager.setAutomaticZenRuleState(ruleId, 2766 new Condition(rule.getConditionId(), "yeah", Condition.STATE_TRUE)); 2767 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2768 assertThat(getWallpaperManagerDimAmount()).isNonZero(); 2769 2770 mNotificationManager.setAutomaticZenRuleState(ruleId, 2771 new Condition(rule.getConditionId(), "nope", Condition.STATE_FALSE)); 2772 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2773 assertThat(getWallpaperManagerDimAmount()).isZero(); 2774 } 2775 2776 @Test 2777 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) setAutomaticZenRuleState_ruleWithDisableAmbientDisplay_applied()2778 public void setAutomaticZenRuleState_ruleWithDisableAmbientDisplay_applied() throws Exception { 2779 assertThat(isPowerManagerAmbientDisplaySuppressed()).isFalse(); 2780 2781 AutomaticZenRule rule = createRule("Disable ambient display"); 2782 rule.setDeviceEffects(new ZenDeviceEffects.Builder() 2783 .setShouldSuppressAmbientDisplay(true) 2784 .build()); 2785 String ruleId = mNotificationManager.addAutomaticZenRule(rule); 2786 2787 mNotificationManager.setAutomaticZenRuleState(ruleId, 2788 new Condition(rule.getConditionId(), "yeah", Condition.STATE_TRUE)); 2789 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2790 assertThat(isPowerManagerAmbientDisplaySuppressed()).isTrue(); 2791 2792 mNotificationManager.setAutomaticZenRuleState(ruleId, 2793 new Condition(rule.getConditionId(), "nope", Condition.STATE_FALSE)); 2794 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2795 assertThat(isPowerManagerAmbientDisplaySuppressed()).isFalse(); 2796 } 2797 2798 @Test 2799 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) setAutomaticZenRuleState_ruleWithNightMode_appliedImmediately()2800 public void setAutomaticZenRuleState_ruleWithNightMode_appliedImmediately() throws Exception { 2801 assertThat(isUiModeManagerThemeOverlayActive()).isFalse(); 2802 2803 AutomaticZenRule rule = createRule("Grayscale"); 2804 rule.setDeviceEffects(new ZenDeviceEffects.Builder() 2805 .setShouldUseNightMode(true) 2806 .build()); 2807 String ruleId = mNotificationManager.addAutomaticZenRule(rule); 2808 2809 mNotificationManager.setAutomaticZenRuleState(ruleId, 2810 new Condition(rule.getConditionId(), "yeah", Condition.STATE_TRUE, 2811 Condition.SOURCE_USER_ACTION)); 2812 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2813 assertThat(isUiModeManagerThemeOverlayActive()).isTrue(); 2814 2815 mNotificationManager.setAutomaticZenRuleState(ruleId, 2816 new Condition(rule.getConditionId(), "nope", Condition.STATE_FALSE, 2817 Condition.SOURCE_USER_ACTION)); 2818 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2819 assertThat(isUiModeManagerThemeOverlayActive()).isFalse(); 2820 } 2821 2822 @RequireNotVisibleBackgroundUsers(reason = 2823 "Visible background user devices (primarily Android auto) currently don't support " 2824 + "per display interactiveness. So when the screen Off event is sent, " 2825 + "PowerManager#IsInteractive is still true while driver screen is off as passenger " 2826 + "screens are on. It also doesn't trigger the code path related to global " 2827 + "wakefulness in power manager. The test will be enabled once per display " 2828 + "interactiveness is supported on MUMD. relevant bugs: b/370631032") 2829 @Test 2830 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) setAutomaticZenRuleState_ruleWithNightMode_appliedOnScreenOff()2831 public void setAutomaticZenRuleState_ruleWithNightMode_appliedOnScreenOff() throws Exception { 2832 assertThat(isUiModeManagerThemeOverlayActive()).isFalse(); 2833 2834 AutomaticZenRule rule = createRule("Grayscale"); 2835 rule.setDeviceEffects(new ZenDeviceEffects.Builder() 2836 .setShouldUseNightMode(true) 2837 .build()); 2838 String ruleId = mNotificationManager.addAutomaticZenRule(rule); 2839 2840 mNotificationManager.setAutomaticZenRuleState(ruleId, 2841 new Condition(rule.getConditionId(), "yeah", Condition.STATE_TRUE, 2842 Condition.SOURCE_SCHEDULE)); 2843 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2844 2845 assertThat(isUiModeManagerThemeOverlayActive()).isFalse(); // Not yet applied. 2846 2847 // Have you tried turning it off and on again? 2848 turnScreenOffAndOn(); 2849 assertThat(isUiModeManagerThemeOverlayActive()).isTrue(); 2850 2851 mNotificationManager.setAutomaticZenRuleState(ruleId, 2852 new Condition(rule.getConditionId(), "nope", Condition.STATE_FALSE, 2853 Condition.SOURCE_SCHEDULE)); 2854 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2855 2856 assertThat(isUiModeManagerThemeOverlayActive()).isTrue(); // Not yet applied. 2857 2858 turnScreenOffAndOn(); 2859 assertThat(isUiModeManagerThemeOverlayActive()).isFalse(); 2860 } 2861 2862 @Test 2863 @RequiresFlagsEnabled(Flags.FLAG_MODES_API) setAutomaticZenRuleState_multipleRulesWithDeviceEffects_effectsMerged()2864 public void setAutomaticZenRuleState_multipleRulesWithDeviceEffects_effectsMerged() 2865 throws Exception { 2866 AutomaticZenRule withDisableAmbientDisplay = createRule("Disable ambient display"); 2867 withDisableAmbientDisplay.setDeviceEffects(new ZenDeviceEffects.Builder() 2868 .setShouldSuppressAmbientDisplay(true) 2869 .build()); 2870 String withDisableAmbientDisplayId = mNotificationManager.addAutomaticZenRule( 2871 withDisableAmbientDisplay); 2872 2873 AutomaticZenRule withGrayscale = createRule("With grayscale"); 2874 withGrayscale.setDeviceEffects(new ZenDeviceEffects.Builder() 2875 .setShouldDisplayGrayscale(true) 2876 .build()); 2877 String withGrayscaleId = mNotificationManager.addAutomaticZenRule(withGrayscale); 2878 2879 mNotificationManager.setAutomaticZenRuleState(withDisableAmbientDisplayId, 2880 new Condition(withDisableAmbientDisplay.getConditionId(), "ad", 2881 Condition.STATE_TRUE)); 2882 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2883 assertThat(isPowerManagerAmbientDisplaySuppressed()).isTrue(); 2884 assertThat(isColorDisplayManagerSaturationActivated()).isFalse(); 2885 2886 mNotificationManager.setAutomaticZenRuleState(withGrayscaleId, 2887 new Condition(withGrayscale.getConditionId(), "gs", Condition.STATE_TRUE)); 2888 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2889 assertThat(isPowerManagerAmbientDisplaySuppressed()).isTrue(); 2890 assertThat(isColorDisplayManagerSaturationActivated()).isTrue(); 2891 2892 mNotificationManager.setAutomaticZenRuleState(withDisableAmbientDisplayId, 2893 new Condition(withDisableAmbientDisplay.getConditionId(), "ad", 2894 Condition.STATE_FALSE)); 2895 Thread.sleep(ZEN_EFFECTS_WAIT_MS); // Effects are applied asynchronously. 2896 assertThat(isPowerManagerAmbientDisplaySuppressed()).isFalse(); 2897 assertThat(isColorDisplayManagerSaturationActivated()).isTrue(); 2898 } 2899 getWallpaperManagerDimAmount()2900 private float getWallpaperManagerDimAmount() { 2901 WallpaperManager wallpaperManager = checkNotNull( 2902 mContext.getSystemService(WallpaperManager.class)); 2903 return SystemUtil.runWithShellPermissionIdentity( 2904 () -> wallpaperManager.getWallpaperDimAmount(), 2905 Manifest.permission.SET_WALLPAPER_DIM_AMOUNT); 2906 } 2907 isPowerManagerAmbientDisplaySuppressed()2908 private boolean isPowerManagerAmbientDisplaySuppressed() { 2909 PowerManager powerManager = checkNotNull(mContext.getSystemService(PowerManager.class)); 2910 return SystemUtil.runWithShellPermissionIdentity( 2911 () -> powerManager.isAmbientDisplaySuppressed(), 2912 Manifest.permission.READ_DREAM_STATE); 2913 } 2914 isColorDisplayManagerSaturationActivated()2915 private boolean isColorDisplayManagerSaturationActivated() { 2916 ColorDisplayManager colorDisplayManager = checkNotNull( 2917 mContext.getSystemService(ColorDisplayManager.class)); 2918 return SystemUtil.runWithShellPermissionIdentity( 2919 () -> colorDisplayManager.isSaturationActivated(), 2920 Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS); 2921 } 2922 isUiModeManagerThemeOverlayActive()2923 private boolean isUiModeManagerThemeOverlayActive() { 2924 UiModeManager uiModeManager = checkNotNull(mContext.getSystemService(UiModeManager.class)); 2925 return SystemUtil.runWithShellPermissionIdentity( 2926 () -> uiModeManager.getAttentionModeThemeOverlay() 2927 == UiModeManager.MODE_ATTENTION_THEME_OVERLAY_NIGHT, 2928 Manifest.permission.MODIFY_DAY_NIGHT_MODE); 2929 } 2930 turnScreenOffAndOn()2931 private void turnScreenOffAndOn() throws Exception { 2932 ScreenUtils.setScreenOn(false); 2933 CtsAppTestUtils.turnScreenOn(mInstrumentation, mContext); 2934 } 2935 2936 @Test testSetInterruptionFilter_usesAutomaticZenRule()2937 public void testSetInterruptionFilter_usesAutomaticZenRule() throws Exception { 2938 // NMS: MANAGE_GLOBAL_ZEN_VIA_IMPLICIT_RULES 2939 if (!android.app.Flags.modesApi() || !CompatChanges.isChangeEnabled(308670109L)) { 2940 return; 2941 } 2942 assertThat(mNotificationManager.getAutomaticZenRules()).isEmpty(); 2943 2944 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 2945 2946 // The filter was applied, but through a rule. 2947 assertExpectedDndState(INTERRUPTION_FILTER_PRIORITY); 2948 Map<String, AutomaticZenRule> zenRules = mNotificationManager.getAutomaticZenRules(); 2949 assertThat(zenRules).hasSize(1); 2950 AutomaticZenRule rule = Iterables.getOnlyElement(zenRules.values()); 2951 assertThat(rule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_PRIORITY); 2952 } 2953 2954 @Test testSetNotificationPolicy_usesAutomaticZenRule()2955 public void testSetNotificationPolicy_usesAutomaticZenRule() { 2956 // NMS: MANAGE_GLOBAL_ZEN_VIA_IMPLICIT_RULES 2957 if (!android.app.Flags.modesApi() || !CompatChanges.isChangeEnabled(308670109L)) { 2958 return; 2959 } 2960 assertThat(mNotificationManager.getAutomaticZenRules()).isEmpty(); 2961 2962 NotificationManager.Policy policy = new NotificationManager.Policy( 2963 PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_REPEAT_CALLERS, 2964 0, 0); 2965 mNotificationManager.setNotificationPolicy(policy); 2966 2967 // The policy was mapped to a rule. 2968 Map<String, AutomaticZenRule> zenRules = mNotificationManager.getAutomaticZenRules(); 2969 assertThat(zenRules).hasSize(1); 2970 ZenPolicy ruleZen = Iterables.getOnlyElement(zenRules.values()).getZenPolicy(); 2971 assertThat(ruleZen).isNotNull(); 2972 2973 assertThat(ruleZen.getPriorityCategoryAlarms()).isEqualTo(ZenPolicy.STATE_ALLOW); 2974 assertThat(ruleZen.getPriorityCategoryRepeatCallers()).isEqualTo(ZenPolicy.STATE_ALLOW); 2975 assertThat(ruleZen.getPriorityCategoryCalls()).isEqualTo(ZenPolicy.STATE_DISALLOW); 2976 assertThat(ruleZen.getPriorityCategoryMedia()).isEqualTo(ZenPolicy.STATE_DISALLOW); 2977 assertThat(ruleZen.getPriorityCategorySystem()).isEqualTo(ZenPolicy.STATE_DISALLOW); 2978 } 2979 2980 @Test testSetInterruptionFilter_withSetNotificationPolicy_sharesAutomaticZenRule()2981 public void testSetInterruptionFilter_withSetNotificationPolicy_sharesAutomaticZenRule() { 2982 // NMS: MANAGE_GLOBAL_ZEN_VIA_IMPLICIT_RULES 2983 if (!android.app.Flags.modesApi() || !CompatChanges.isChangeEnabled(308670109L)) { 2984 return; 2985 } 2986 assertThat(mNotificationManager.getAutomaticZenRules()).isEmpty(); 2987 2988 NotificationManager.Policy policy = new NotificationManager.Policy( 2989 PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_REPEAT_CALLERS, 2990 0, 0); 2991 mNotificationManager.setNotificationPolicy(policy); 2992 mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 2993 2994 // The policy and interruption filter were mapped to the same rule. 2995 Map<String, AutomaticZenRule> zenRules = mNotificationManager.getAutomaticZenRules(); 2996 assertThat(zenRules).hasSize(1); 2997 AutomaticZenRule rule = Iterables.getOnlyElement(zenRules.values()); 2998 assertThat(rule.getInterruptionFilter()).isEqualTo(INTERRUPTION_FILTER_PRIORITY); 2999 ZenPolicy ruleZen = rule.getZenPolicy(); 3000 assertThat(ruleZen).isNotNull(); 3001 assertThat(ruleZen.getPriorityCategoryAlarms()).isEqualTo(ZenPolicy.STATE_ALLOW); 3002 assertThat(ruleZen.getPriorityCategoryCalls()).isEqualTo(ZenPolicy.STATE_DISALLOW); 3003 3004 // The rule was turned on, and is working. 3005 assertThat(mNotificationManager.getCurrentInterruptionFilter()).isEqualTo( 3006 INTERRUPTION_FILTER_PRIORITY); 3007 NotificationManager.Policy activePolicy = 3008 mNotificationManager.getConsolidatedNotificationPolicy(); 3009 assertThat(activePolicy.priorityCategories & PRIORITY_CATEGORY_ALARMS).isNotEqualTo(0); 3010 assertThat(activePolicy.priorityCategories & PRIORITY_CATEGORY_CALLS).isEqualTo(0); 3011 } 3012 3013 @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI}) 3014 @Test testIndividualRuleIntent_resolvesToActivity()3015 public void testIndividualRuleIntent_resolvesToActivity() { 3016 assumeTrue(mNotificationManager.areAutomaticZenRulesUserManaged()); 3017 3018 AutomaticZenRule ruleToCreate = createRule("testIndividualRuleIntent_resolvesToActivity"); 3019 String id = mNotificationManager.addAutomaticZenRule(ruleToCreate); 3020 final PackageManager pm = mContext.getPackageManager(); 3021 final Intent intent = new Intent(Settings.ACTION_AUTOMATIC_ZEN_RULE_SETTINGS); 3022 intent.putExtra(EXTRA_AUTOMATIC_ZEN_RULE_ID, id); 3023 3024 final ResolveInfo resolveInfo = pm.resolveActivity(intent, MATCH_DEFAULT_ONLY); 3025 assertNotNull(resolveInfo); 3026 } 3027 3028 @Test 3029 @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_TEST}) setAutomaticZenRuleState_manualActivation()3030 public void setAutomaticZenRuleState_manualActivation() { 3031 AutomaticZenRule ruleToCreate = createRule("rule"); 3032 String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate); 3033 Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on", 3034 STATE_TRUE, Condition.SOURCE_USER_ACTION); 3035 Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off", 3036 STATE_FALSE, Condition.SOURCE_USER_ACTION); 3037 Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on", 3038 STATE_TRUE); 3039 Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off", 3040 STATE_FALSE); 3041 3042 // User manually activates -> it's active. 3043 runAsSystemUi( 3044 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate)); 3045 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3046 3047 // User manually deactivates -> it's inactive. 3048 runAsSystemUi( 3049 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate)); 3050 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3051 3052 // And app can activate and deactivate. 3053 mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate); 3054 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3055 mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate); 3056 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3057 } 3058 3059 @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_TEST}) 3060 @Test setAutomaticZenRuleState_manualDeactivation()3061 public void setAutomaticZenRuleState_manualDeactivation() { 3062 AutomaticZenRule ruleToCreate = createRule("rule"); 3063 String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate); 3064 Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on", 3065 STATE_TRUE, Condition.SOURCE_USER_ACTION); 3066 Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off", 3067 STATE_FALSE, Condition.SOURCE_USER_ACTION); 3068 Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on", 3069 STATE_TRUE); 3070 Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off", 3071 STATE_FALSE); 3072 3073 // App activates rule. 3074 mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate); 3075 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3076 3077 // User manually deactivates -> it's inactive. 3078 runAsSystemUi( 3079 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate)); 3080 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3081 3082 // User manually reactivates -> it's active. 3083 runAsSystemUi( 3084 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate)); 3085 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3086 3087 // That manual activation removed the override-deactivate, but didn't put an 3088 // override-activate, so app can deactivate when its natural schedule ends. 3089 mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate); 3090 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3091 } 3092 3093 @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_TEST}) 3094 @Test setAutomaticZenRuleState_respectsManuallyActivated()3095 public void setAutomaticZenRuleState_respectsManuallyActivated() { 3096 AutomaticZenRule ruleToCreate = createRule("rule"); 3097 String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate); 3098 Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on", 3099 STATE_TRUE, Condition.SOURCE_USER_ACTION); 3100 Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on", 3101 STATE_TRUE); 3102 Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off", 3103 STATE_FALSE); 3104 3105 // App thinks rule should be inactive. 3106 mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate); 3107 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3108 3109 // Manually activate -> it's active. 3110 runAsSystemUi(() -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate)); 3111 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3112 3113 // App says it should be inactive, but it's ignored. 3114 mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate); 3115 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3116 3117 // App says it should be active. No change now... 3118 mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate); 3119 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3120 3121 // ... but when the app wants to deactivate next time, it works. 3122 mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate); 3123 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3124 } 3125 3126 @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_TEST}) 3127 @Test setAutomaticZenRuleState_respectsManuallyDeactivated()3128 public void setAutomaticZenRuleState_respectsManuallyDeactivated() { 3129 AutomaticZenRule ruleToCreate = createRule("rule"); 3130 String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate); 3131 Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off", 3132 STATE_FALSE, Condition.SOURCE_USER_ACTION); 3133 Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on", 3134 STATE_TRUE); 3135 Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off", 3136 STATE_FALSE); 3137 3138 // App activates rule. 3139 mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate); 3140 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3141 3142 // User manually deactivates -> it's inactive. 3143 runAsSystemUi( 3144 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate)); 3145 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3146 3147 // App says it should be active, but it's ignored. 3148 mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate); 3149 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3150 3151 // App says it should be inactive. No change now... 3152 mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate); 3153 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3154 3155 // ... but when the app wants to activate next time, it works. 3156 mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate); 3157 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3158 } 3159 3160 @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_TEST}) 3161 @Test setAutomaticZenRuleState_manualActivationFromApp()3162 public void setAutomaticZenRuleState_manualActivationFromApp() { 3163 AutomaticZenRule ruleToCreate = createRule("rule"); 3164 String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate); 3165 Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-off", 3166 STATE_TRUE, Condition.SOURCE_USER_ACTION); 3167 Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off", 3168 STATE_FALSE, Condition.SOURCE_USER_ACTION); 3169 Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on", 3170 STATE_TRUE); 3171 Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off", 3172 STATE_FALSE); 3173 3174 // App activates rule. 3175 mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate); 3176 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3177 3178 // User manually deactivates from SysUI -> it's inactive. 3179 runAsSystemUi( 3180 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate)); 3181 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3182 3183 // User manually activates from App -> it's active. 3184 mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate); 3185 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3186 3187 // And app can automatically deactivate it later. 3188 mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate); 3189 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3190 } 3191 3192 @RequiresFlagsEnabled({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_TEST}) 3193 @Test setAutomaticZenRuleState_manualDeactivationFromApp()3194 public void setAutomaticZenRuleState_manualDeactivationFromApp() { 3195 AutomaticZenRule ruleToCreate = createRule("rule"); 3196 String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate); 3197 Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-off", 3198 STATE_TRUE, Condition.SOURCE_USER_ACTION); 3199 Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off", 3200 STATE_FALSE, Condition.SOURCE_USER_ACTION); 3201 Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on", 3202 STATE_TRUE); 3203 3204 // User manually activates from SysUI -> it's active. 3205 runAsSystemUi( 3206 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate)); 3207 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3208 3209 // User manually deactivates from App -> it's inactive. 3210 mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate); 3211 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE); 3212 3213 // And app can automatically activate it later. 3214 mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate); 3215 assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE); 3216 } 3217 3218 } 3219