1 /* 2 * Copyright (C) 2015 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 com.android.cts.verifier.notifications; 18 19 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED; 20 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED; 21 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED; 22 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_UNKNOWN; 23 import static android.app.NotificationManager.INTERRUPTION_FILTER_PRIORITY; 24 25 import android.app.AutomaticZenRule; 26 import android.app.NotificationManager; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.SharedPreferences; 31 import android.net.Uri; 32 import android.provider.Settings; 33 import android.service.notification.ZenPolicy; 34 import android.text.TextUtils; 35 import android.util.Log; 36 import android.view.View; 37 import android.view.ViewGroup; 38 import android.widget.Button; 39 40 import com.android.cts.verifier.R; 41 42 import java.util.ArrayList; 43 import java.util.List; 44 import java.util.Map; 45 import java.util.Objects; 46 47 public class ConditionProviderVerifierActivity extends InteractiveVerifierActivity 48 implements Runnable { 49 private static final String TAG = "CPVerifier"; 50 protected static final String CP_PACKAGE = "com.android.cts.verifier"; 51 protected static final String CP_PATH = CP_PACKAGE + 52 "/com.android.cts.verifier.notifications.MockConditionProvider"; 53 54 protected static final String PREFS = "zen_prefs"; 55 private static final String BROADCAST_RULE_NAME = "123"; 56 57 @Override getTitleResource()58 protected int getTitleResource() { 59 return R.string.cp_test; 60 } 61 62 @Override getInstructionsResource()63 protected int getInstructionsResource() { 64 return R.string.cp_info; 65 } 66 67 // Test Setup 68 69 @Override createTestItems()70 protected List<InteractiveTestCase> createTestItems() { 71 List<InteractiveTestCase> tests = new ArrayList<>(9); 72 tests.add(new IsEnabledTest()); 73 tests.add(new ServiceStartedTest()); 74 tests.add(new CreateAutomaticZenRuleTest()); 75 tests.add(new CreateAutomaticZenRuleWithZenPolicyTest()); 76 tests.add(new UpdateAutomaticZenRuleTest()); 77 tests.add(new UpdateAutomaticZenRuleWithZenPolicyTest()); 78 tests.add(new GetAutomaticZenRuleTest()); 79 tests.add(new GetAutomaticZenRulesTest()); 80 tests.add(new VerifyRulesIntent()); 81 tests.add(new VerifyRulesAvailableToUsers()); 82 tests.add(new ReceiveRuleDisableNoticeTest()); 83 tests.add(new ReceiveRuleEnabledNoticeTest()); 84 tests.add(new ReceiveRuleDeletedNoticeTest()); 85 tests.add(new SubscribeAutomaticZenRuleTest()); 86 tests.add(new DeleteAutomaticZenRuleTest()); 87 tests.add(new UnsubscribeAutomaticZenRuleTest()); 88 tests.add(new RequestUnbindTest()); 89 tests.add(new RequestBindTest()); 90 tests.add(new IsDisabledTest()); 91 tests.add(new ServiceStoppedTest()); 92 return tests; 93 } 94 95 protected class IsEnabledTest extends InteractiveTestCase { 96 @Override inflate(ViewGroup parent)97 protected View inflate(ViewGroup parent) { 98 return createSettingsItem(parent, R.string.cp_enable_service); 99 } 100 101 @Override autoStart()102 boolean autoStart() { 103 return true; 104 } 105 106 @Override test()107 protected void test() { 108 Intent settings = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); 109 if (settings.resolveActivity(mPackageManager) == null) { 110 logFail("no settings activity"); 111 status = FAIL; 112 } else { 113 if (mNm.isNotificationPolicyAccessGranted()) { 114 status = PASS; 115 } else { 116 status = WAIT_FOR_USER; 117 } 118 next(); 119 } 120 } 121 tearDown()122 protected void tearDown() { 123 // wait for the service to start 124 delay(); 125 } 126 127 @Override getIntent()128 protected Intent getIntent() { 129 return new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); 130 } 131 } 132 133 protected class ServiceStartedTest extends InteractiveTestCase { 134 int mRetries = 5; 135 @Override inflate(ViewGroup parent)136 protected View inflate(ViewGroup parent) { 137 return createAutoItem(parent, R.string.cp_service_started); 138 } 139 140 @Override test()141 protected void test() { 142 if (MockConditionProvider.getInstance().isConnected() 143 && MockConditionProvider.getInstance().isBound()) { 144 status = PASS; 145 next(); 146 } else { 147 if (--mRetries > 0) { 148 status = RETEST; 149 next(); 150 } else { 151 logFail(); 152 status = FAIL; 153 } 154 } 155 } 156 } 157 158 private class RequestUnbindTest extends InteractiveTestCase { 159 int mRetries = 5; 160 161 @Override inflate(ViewGroup parent)162 protected View inflate(ViewGroup parent) { 163 return createAutoItem(parent, R.string.nls_snooze); 164 165 } 166 167 @Override setUp()168 protected void setUp() { 169 status = READY; 170 } 171 172 @Override test()173 protected void test() { 174 if (status == READY) { 175 MockConditionProvider.getInstance().requestUnbind(); 176 status = RETEST; 177 } else { 178 if (MockConditionProvider.getInstance() == null || 179 !MockConditionProvider.getInstance().isConnected()) { 180 status = PASS; 181 } else { 182 if (--mRetries > 0) { 183 status = RETEST; 184 } else { 185 logFail(); 186 status = FAIL; 187 } 188 } 189 next(); 190 } 191 } 192 } 193 194 private class RequestBindTest extends InteractiveTestCase { 195 int mRetries = 5; 196 197 @Override inflate(ViewGroup parent)198 protected View inflate(ViewGroup parent) { 199 return createAutoItem(parent, R.string.nls_unsnooze); 200 201 } 202 203 @Override test()204 protected void test() { 205 if (status == READY) { 206 MockConditionProvider.requestRebind(MockConditionProvider.COMPONENT_NAME); 207 status = RETEST; 208 } else { 209 if (MockConditionProvider.getInstance().isConnected() 210 && MockConditionProvider.getInstance().isBound()) { 211 status = PASS; 212 next(); 213 } else { 214 if (--mRetries > 0) { 215 status = RETEST; 216 next(); 217 } else { 218 logFail(); 219 status = FAIL; 220 } 221 } 222 } 223 } 224 } 225 226 227 private class CreateAutomaticZenRuleTest extends InteractiveTestCase { 228 private String id = null; 229 230 @Override inflate(ViewGroup parent)231 protected View inflate(ViewGroup parent) { 232 return createAutoItem(parent, R.string.cp_create_rule); 233 } 234 235 @Override test()236 protected void test() { 237 AutomaticZenRule ruleToCreate = 238 createRule("Rule", "value", NotificationManager.INTERRUPTION_FILTER_ALARMS); 239 id = mNm.addAutomaticZenRule(ruleToCreate); 240 241 if (!TextUtils.isEmpty(id)) { 242 status = PASS; 243 } else { 244 logFail(); 245 status = FAIL; 246 } 247 next(); 248 } 249 250 @Override tearDown()251 protected void tearDown() { 252 if (id != null) { 253 mNm.removeAutomaticZenRule(id); 254 } 255 MockConditionProvider.getInstance().resetData(); 256 } 257 } 258 259 private class CreateAutomaticZenRuleWithZenPolicyTest extends InteractiveTestCase { 260 private String id = null; 261 262 @Override inflate(ViewGroup parent)263 protected View inflate(ViewGroup parent) { 264 return createAutoItem(parent, R.string.cp_create_rule_with_zen_policy); 265 } 266 267 @Override test()268 protected void test() { 269 AutomaticZenRule ruleToCreate = 270 createRuleWithZenPolicy("Rule", "value", 271 new ZenPolicy.Builder().allowReminders(true).build()); 272 id = mNm.addAutomaticZenRule(ruleToCreate); 273 274 if (!TextUtils.isEmpty(id)) { 275 AutomaticZenRule rule = mNm.getAutomaticZenRule(id); 276 if (rule != null && ruleToCreate.getName().equals(rule.getName()) 277 && ruleToCreate.getOwner().equals(rule.getOwner()) 278 && ruleToCreate.getConditionId().equals(rule.getConditionId()) 279 && ruleToCreate.isEnabled() == rule.isEnabled() 280 && ruleToCreate.getInterruptionFilter() == rule.getInterruptionFilter() 281 && Objects.equals(ruleToCreate.getConfigurationActivity(), 282 rule.getConfigurationActivity()) 283 && Objects.equals(ruleToCreate.getZenPolicy(), rule.getZenPolicy())) { 284 status = PASS; 285 } else { 286 logFail("created rule doesn't equal actual rule"); 287 status = FAIL; 288 } 289 } else { 290 logFail("rule wasn't created"); 291 status = FAIL; 292 } 293 next(); 294 } 295 296 @Override tearDown()297 protected void tearDown() { 298 if (id != null) { 299 mNm.removeAutomaticZenRule(id); 300 } 301 MockConditionProvider.getInstance().resetData(); 302 } 303 } 304 305 private class UpdateAutomaticZenRuleTest extends InteractiveTestCase { 306 private String id = null; 307 308 @Override inflate(ViewGroup parent)309 protected View inflate(ViewGroup parent) { 310 return createAutoItem(parent, R.string.cp_update_rule); 311 } 312 313 @Override setUp()314 protected void setUp() { 315 id = mNm.addAutomaticZenRule(createRule("BeforeUpdate", "beforeValue", 316 NotificationManager.INTERRUPTION_FILTER_ALARMS)); 317 status = READY; 318 delay(); 319 } 320 321 @Override test()322 protected void test() { 323 AutomaticZenRule updated = mNm.getAutomaticZenRule(id); 324 updated.setName("AfterUpdate"); 325 updated.setConditionId(MockConditionProvider.toConditionId("afterValue")); 326 updated.setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_NONE); 327 328 try { 329 boolean success = mNm.updateAutomaticZenRule(id, updated); 330 if (success && updated.equals(mNm.getAutomaticZenRule(id))) { 331 status = PASS; 332 } else { 333 logFail(); 334 status = FAIL; 335 } 336 } catch (Exception e) { 337 logFail("update failed", e); 338 status = FAIL; 339 } 340 next(); 341 } 342 343 @Override tearDown()344 protected void tearDown() { 345 if (id != null) { 346 mNm.removeAutomaticZenRule(id); 347 } 348 MockConditionProvider.getInstance().resetData(); 349 } 350 } 351 352 private class UpdateAutomaticZenRuleWithZenPolicyTest extends InteractiveTestCase { 353 private String id1 = null; // no zen policy 354 private String id2 = null; // has zen policy 355 356 @Override inflate(ViewGroup parent)357 protected View inflate(ViewGroup parent) { 358 return createAutoItem(parent, R.string.cp_update_rule_use_zen_policy); 359 } 360 361 @Override setUp()362 protected void setUp() { 363 // create rule without a zen policy 364 id1 = mNm.addAutomaticZenRule(createRule("BeforeUpdate1", 365 "beforeValue1", NotificationManager.INTERRUPTION_FILTER_ALARMS)); 366 id2 = mNm.addAutomaticZenRule(createRuleWithZenPolicy( 367 "BeforeUpdate2", "beforeValue2", 368 new ZenPolicy.Builder().allowReminders(true).build())); 369 status = READY; 370 delay(); 371 } 372 373 @Override test()374 protected void test() { 375 ZenPolicy.Builder builder = new ZenPolicy.Builder().allowAlarms(true); 376 377 // update rule with zen policy 378 AutomaticZenRule updated1 = mNm.getAutomaticZenRule(id1); 379 updated1.setName("AfterUpdate1"); 380 updated1.setConditionId(MockConditionProvider.toConditionId("afterValue1")); 381 updated1.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 382 updated1.setZenPolicy(builder.build()); 383 384 AutomaticZenRule updated2 = mNm.getAutomaticZenRule(id2); 385 updated2.setName("AfterUpdate2"); 386 updated2.setConditionId(MockConditionProvider.toConditionId("afterValue2")); 387 updated2.setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY); 388 updated2.setZenPolicy(builder.build()); 389 390 try { 391 boolean success1 = mNm.updateAutomaticZenRule(id1, updated1); 392 boolean success2 = mNm.updateAutomaticZenRule(id2, updated2); 393 if (success1 && success2) { 394 boolean rule1UpdateSuccess = 395 updated1.equals(mNm.getAutomaticZenRule(id1)); 396 boolean rule2UpdateSuccess = 397 updated2.equals(mNm.getAutomaticZenRule(id2)); 398 if (rule1UpdateSuccess && rule2UpdateSuccess) { 399 status = PASS; 400 } else { 401 if (!rule1UpdateSuccess) { 402 logFail("Updated rule1 is not expected expected=" + updated1.toString() 403 + " actual=" + mNm.getAutomaticZenRule(id1)); 404 } 405 if (!rule2UpdateSuccess) { 406 logFail("Updated rule2 is not expected expected=" + updated2.toString() 407 + " actual=" + mNm.getAutomaticZenRule(id2)); 408 } 409 status = FAIL; 410 } 411 } else { 412 logFail("Did not successfully update rules"); 413 status = FAIL; 414 } 415 } catch (Exception e) { 416 logFail("update failed", e); 417 status = FAIL; 418 } 419 next(); 420 } 421 422 @Override tearDown()423 protected void tearDown() { 424 if (id1 != null) { 425 mNm.removeAutomaticZenRule(id1); 426 } 427 428 if (id2 != null) { 429 mNm.removeAutomaticZenRule(id2); 430 } 431 MockConditionProvider.getInstance().resetData(); 432 } 433 } 434 435 private class SubscribeAutomaticZenRuleTest extends InteractiveTestCase { 436 private String id = null; 437 private AutomaticZenRule ruleToCreate; 438 private int mRetries = 3; 439 440 @Override inflate(ViewGroup parent)441 protected View inflate(ViewGroup parent) { 442 return createAutoItem(parent, R.string.cp_subscribe_rule); 443 } 444 445 @Override setUp()446 protected void setUp() { 447 ruleToCreate = createRule("RuleSubscribe", "Subscribevalue", 448 NotificationManager.INTERRUPTION_FILTER_ALARMS); 449 id = mNm.addAutomaticZenRule(ruleToCreate); 450 status = READY; 451 delay(); 452 } 453 454 @Override test()455 protected void test() { 456 boolean foundMatch = false; 457 List<Uri> subscriptions = MockConditionProvider.getInstance().getSubscriptions(); 458 for (Uri actual : subscriptions) { 459 if (ruleToCreate.getConditionId().equals(actual)) { 460 status = PASS; 461 foundMatch = true; 462 break; 463 } 464 } 465 if (foundMatch) { 466 status = PASS; 467 next(); 468 } else if (--mRetries > 0) { 469 setFailed(); 470 } else { 471 status = RETEST; 472 next(); 473 } 474 } 475 476 @Override tearDown()477 protected void tearDown() { 478 if (id != null) { 479 mNm.removeAutomaticZenRule(id); 480 } 481 MockConditionProvider.getInstance().resetData(); 482 } 483 } 484 485 private class GetAutomaticZenRuleTest extends InteractiveTestCase { 486 private String id1 = null; 487 private String id2 = null; 488 private AutomaticZenRule ruleToCreate1; // no zen policy 489 private AutomaticZenRule ruleToCreate2; // has zen policy 490 491 @Override inflate(ViewGroup parent)492 protected View inflate(ViewGroup parent) { 493 return createAutoItem(parent, R.string.cp_get_rule); 494 } 495 496 @Override setUp()497 protected void setUp() { 498 ruleToCreate1 = createRule("RuleGet no zen policy", "valueGet", 499 NotificationManager.INTERRUPTION_FILTER_ALARMS); 500 ruleToCreate2 = createRuleWithZenPolicy("RuleGet zen policy", "valueGet", 501 new ZenPolicy.Builder().allowReminders(true).build()); 502 id1 = mNm.addAutomaticZenRule(ruleToCreate1); 503 id2 = mNm.addAutomaticZenRule(ruleToCreate2); 504 status = READY; 505 delay(); 506 } 507 508 @Override test()509 protected void test() { 510 AutomaticZenRule queriedRule1 = mNm.getAutomaticZenRule(id1); 511 AutomaticZenRule queriedRule2 = mNm.getAutomaticZenRule(id2); 512 if (queriedRule1 != null 513 && ruleToCreate1.getName().equals(queriedRule1.getName()) 514 && ruleToCreate1.getOwner().equals(queriedRule1.getOwner()) 515 && ruleToCreate1.getConditionId().equals(queriedRule1.getConditionId()) 516 && ruleToCreate1.isEnabled() == queriedRule1.isEnabled() 517 && Objects.equals(ruleToCreate1.getZenPolicy(), queriedRule1.getZenPolicy()) 518 && queriedRule2 != null 519 && ruleToCreate2.getName().equals(queriedRule2.getName()) 520 && ruleToCreate2.getOwner().equals(queriedRule2.getOwner()) 521 && ruleToCreate2.getConditionId().equals(queriedRule2.getConditionId()) 522 && ruleToCreate2.isEnabled() == queriedRule2.isEnabled() 523 && Objects.equals(ruleToCreate2.getZenPolicy(), queriedRule2.getZenPolicy())) { 524 status = PASS; 525 } else { 526 logFail(); 527 status = FAIL; 528 } 529 next(); 530 } 531 532 @Override tearDown()533 protected void tearDown() { 534 if (id1 != null) { 535 mNm.removeAutomaticZenRule(id1); 536 } 537 538 if (id2 != null) { 539 mNm.removeAutomaticZenRule(id2); 540 } 541 MockConditionProvider.getInstance().resetData(); 542 } 543 } 544 545 private class GetAutomaticZenRulesTest extends InteractiveTestCase { 546 private List<String> ids = new ArrayList<>(); 547 private AutomaticZenRule rule1; // no ZenPolicy 548 private AutomaticZenRule rule2; // has ZenPolicy 549 550 @Override inflate(ViewGroup parent)551 protected View inflate(ViewGroup parent) { 552 return createAutoItem(parent, R.string.cp_get_rules); 553 } 554 555 @Override setUp()556 protected void setUp() { 557 rule1 = createRule("Rule without ZenPolicy", "value1", 558 NotificationManager.INTERRUPTION_FILTER_ALARMS); 559 rule2 = createRuleWithZenPolicy("Rule with ZenPolicy", "value2", 560 new ZenPolicy.Builder().allowReminders(true).build()); 561 ids.add(mNm.addAutomaticZenRule(rule1)); 562 ids.add(mNm.addAutomaticZenRule(rule2)); 563 status = READY; 564 delay(); 565 } 566 567 @Override test()568 protected void test() { 569 Map<String, AutomaticZenRule> rules = mNm.getAutomaticZenRules(); 570 571 if (rules == null || rules.size() != 2) { 572 logFail(); 573 status = FAIL; 574 next(); 575 return; 576 } 577 578 for (AutomaticZenRule createdRule : rules.values()) { 579 if (!compareRules(createdRule, rule1) && !compareRules(createdRule, rule2)) { 580 logFail(); 581 status = FAIL; 582 break; 583 } 584 } 585 status = PASS; 586 next(); 587 } 588 589 @Override tearDown()590 protected void tearDown() { 591 for (String id : ids) { 592 mNm.removeAutomaticZenRule(id); 593 } 594 MockConditionProvider.getInstance().resetData(); 595 } 596 } 597 598 protected class VerifyRulesIntent extends InteractiveTestCase { 599 @Override inflate(ViewGroup parent)600 protected View inflate(ViewGroup parent) { 601 return createSettingsItem(parent, R.string.cp_show_rules); 602 } 603 604 @Override autoStart()605 boolean autoStart() { 606 return true; 607 } 608 609 @Override test()610 protected void test() { 611 Intent settings = new Intent(Settings.ACTION_CONDITION_PROVIDER_SETTINGS); 612 if (settings.resolveActivity(mPackageManager) == null) { 613 logFail("no settings activity"); 614 status = FAIL; 615 } else { 616 if (buttonPressed) { 617 status = PASS; 618 } else { 619 status = RETEST_AFTER_LONG_DELAY; 620 } 621 next(); 622 } 623 } 624 tearDown()625 protected void tearDown() { 626 // wait for the service to start 627 delay(); 628 } 629 630 @Override getIntent()631 protected Intent getIntent() { 632 return new Intent(Settings.ACTION_CONDITION_PROVIDER_SETTINGS); 633 } 634 } 635 636 protected class VerifyRulesAvailableToUsers extends InteractiveTestCase { 637 @Override inflate(ViewGroup parent)638 protected View inflate(ViewGroup parent) { 639 return createPassFailItem(parent, R.string.cp_show_rules_verification); 640 } 641 642 @Override autoStart()643 boolean autoStart() { 644 return true; 645 } 646 647 @Override test()648 protected void test() { 649 status = WAIT_FOR_USER; 650 next(); 651 } 652 } 653 654 /** 655 * Sends the user to settings to disable the rule. Waits to receive the broadcast that the rule 656 * was disabled, and confirms that the broadcast contains the correct extras. 657 */ 658 protected class ReceiveRuleDisableNoticeTest extends InteractiveTestCase { 659 private final int EXPECTED_STATUS = AUTOMATIC_RULE_STATUS_DISABLED; 660 private int mRetries = 2; 661 private View mView; 662 private String mId; 663 @Override inflate(ViewGroup parent)664 protected View inflate(ViewGroup parent) { 665 mView = createNlsSettingsItem(parent, R.string.cp_disable_rule); 666 Button button = mView.findViewById(R.id.nls_action_button); 667 button.setEnabled(false); 668 return mView; 669 } 670 671 @Override setUp()672 protected void setUp() { 673 status = READY; 674 // create enabled so it's ready to be disabled in app 675 AutomaticZenRule rule = new AutomaticZenRule(BROADCAST_RULE_NAME, null, 676 new ComponentName(CP_PACKAGE, 677 ConditionProviderVerifierActivity.this.getClass().getName()), 678 Uri.EMPTY, null, INTERRUPTION_FILTER_PRIORITY, true); 679 mId = mNm.addAutomaticZenRule(rule); 680 Button button = mView.findViewById(R.id.nls_action_button); 681 button.setEnabled(true); 682 } 683 684 @Override autoStart()685 boolean autoStart() { 686 return true; 687 } 688 689 @Override test()690 protected void test() { 691 SharedPreferences prefs = mContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE); 692 693 AutomaticZenRule rule = mNm.getAutomaticZenRule(mId); 694 695 if (!rule.isEnabled()) { 696 Log.d(TAG, "Check pref for broadcast " + prefs.contains(mId) 697 + " " + prefs.getInt(mId, AUTOMATIC_RULE_STATUS_UNKNOWN)); 698 if (prefs.contains(mId) 699 && EXPECTED_STATUS == prefs.getInt(mId, AUTOMATIC_RULE_STATUS_UNKNOWN)) { 700 status = PASS; 701 } else { 702 if (mRetries > 0) { 703 mRetries--; 704 status = RETEST; 705 } else { 706 status = FAIL; 707 } 708 } 709 } else { 710 Log.d(TAG, "Waiting for user"); 711 // user hasn't jumped to settings yet 712 status = WAIT_FOR_USER; 713 } 714 715 next(); 716 } 717 tearDown()718 protected void tearDown() { 719 mNm.removeAutomaticZenRule(mId); 720 SharedPreferences prefs = mContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE); 721 prefs.edit().clear().commit(); 722 } 723 724 @Override getIntent()725 protected Intent getIntent() { 726 return new Intent(Settings.ACTION_CONDITION_PROVIDER_SETTINGS) 727 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 728 } 729 } 730 731 /** 732 * Sends the user to settings to enable the rule. Waits to receive the broadcast that the rule 733 * was enabled, and confirms that the broadcast contains the correct extras. 734 */ 735 protected class ReceiveRuleEnabledNoticeTest extends InteractiveTestCase { 736 private final int EXPECTED_STATUS = AUTOMATIC_RULE_STATUS_ENABLED; 737 private int mRetries = 2; 738 private View mView; 739 private String mId; 740 @Override inflate(ViewGroup parent)741 protected View inflate(ViewGroup parent) { 742 mView = createNlsSettingsItem(parent, R.string.cp_enable_rule); 743 Button button = mView.findViewById(R.id.nls_action_button); 744 button.setEnabled(false); 745 return mView; 746 } 747 748 @Override setUp()749 protected void setUp() { 750 status = READY; 751 // create disabled so it's ready to be enabled in Settings 752 AutomaticZenRule rule = new AutomaticZenRule(BROADCAST_RULE_NAME, null, 753 new ComponentName(CP_PACKAGE, 754 ConditionProviderVerifierActivity.this.getClass().getName()), 755 Uri.EMPTY, null, INTERRUPTION_FILTER_PRIORITY, false); 756 mId = mNm.addAutomaticZenRule(rule); 757 Button button = mView.findViewById(R.id.nls_action_button); 758 button.setEnabled(true); 759 } 760 761 @Override autoStart()762 boolean autoStart() { 763 return true; 764 } 765 766 @Override test()767 protected void test() { 768 SharedPreferences prefs = mContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE); 769 770 AutomaticZenRule rule = mNm.getAutomaticZenRule(mId); 771 772 if (rule.isEnabled()) { 773 Log.d(TAG, "Check pref for broadcast " + prefs.contains(mId) 774 + " " + prefs.getInt(mId, AUTOMATIC_RULE_STATUS_UNKNOWN)); 775 if (prefs.contains(mId) 776 && EXPECTED_STATUS == prefs.getInt(mId, AUTOMATIC_RULE_STATUS_UNKNOWN)) { 777 status = PASS; 778 } else { 779 if (mRetries > 0) { 780 mRetries--; 781 status = RETEST; 782 } else { 783 status = FAIL; 784 } 785 } 786 } else { 787 Log.d(TAG, "Waiting for user"); 788 // user hasn't jumped to settings yet 789 status = WAIT_FOR_USER; 790 } 791 792 next(); 793 } 794 tearDown()795 protected void tearDown() { 796 mNm.removeAutomaticZenRule(mId); 797 SharedPreferences prefs = mContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE); 798 prefs.edit().clear().commit(); 799 } 800 801 @Override getIntent()802 protected Intent getIntent() { 803 return new Intent(Settings.ACTION_CONDITION_PROVIDER_SETTINGS) 804 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 805 } 806 } 807 808 /** 809 * Sends the user to settings to delete the rule. Waits to receive the broadcast that the rule 810 * was deleted, and confirms that the broadcast contains the correct extras. 811 */ 812 protected class ReceiveRuleDeletedNoticeTest extends InteractiveTestCase { 813 private final int EXPECTED_STATUS = AUTOMATIC_RULE_STATUS_REMOVED; 814 private int mRetries = 2; 815 private View mView; 816 private String mId; 817 @Override inflate(ViewGroup parent)818 protected View inflate(ViewGroup parent) { 819 mView = createNlsSettingsItem(parent, R.string.cp_delete_rule_broadcast); 820 Button button = mView.findViewById(R.id.nls_action_button); 821 button.setEnabled(false); 822 return mView; 823 } 824 825 @Override setUp()826 protected void setUp() { 827 status = READY; 828 AutomaticZenRule rule = new AutomaticZenRule(BROADCAST_RULE_NAME, null, 829 new ComponentName(CP_PACKAGE, 830 ConditionProviderVerifierActivity.this.getClass().getName()), 831 Uri.EMPTY, null, INTERRUPTION_FILTER_PRIORITY, true); 832 mId = mNm.addAutomaticZenRule(rule); 833 Button button = mView.findViewById(R.id.nls_action_button); 834 button.setEnabled(true); 835 } 836 837 @Override autoStart()838 boolean autoStart() { 839 return true; 840 } 841 842 @Override test()843 protected void test() { 844 SharedPreferences prefs = mContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE); 845 846 AutomaticZenRule rule = mNm.getAutomaticZenRule(mId); 847 848 if (rule == null) { 849 Log.d(TAG, "Check pref for broadcast " + prefs.contains(mId) 850 + " " + prefs.getInt(mId, AUTOMATIC_RULE_STATUS_UNKNOWN)); 851 if (prefs.contains(mId) 852 && EXPECTED_STATUS == prefs.getInt(mId, AUTOMATIC_RULE_STATUS_UNKNOWN)) { 853 status = PASS; 854 } else { 855 if (mRetries > 0) { 856 mRetries--; 857 status = RETEST; 858 } else { 859 status = FAIL; 860 } 861 } 862 } else { 863 Log.d(TAG, "Waiting for user"); 864 // user hasn't jumped to settings yet 865 status = WAIT_FOR_USER; 866 } 867 868 next(); 869 } 870 tearDown()871 protected void tearDown() { 872 mNm.removeAutomaticZenRule(mId); 873 SharedPreferences prefs = mContext.getSharedPreferences(PREFS, Context.MODE_PRIVATE); 874 prefs.edit().clear().commit(); 875 } 876 877 @Override getIntent()878 protected Intent getIntent() { 879 return new Intent(Settings.ACTION_CONDITION_PROVIDER_SETTINGS) 880 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); 881 } 882 } 883 884 private class DeleteAutomaticZenRuleTest extends InteractiveTestCase { 885 private String id1 = null; 886 private String id2 = null; 887 888 @Override inflate(ViewGroup parent)889 protected View inflate(ViewGroup parent) { 890 return createAutoItem(parent, R.string.cp_delete_rule); 891 } 892 893 @Override test()894 protected void test() { 895 AutomaticZenRule ruleToCreate1 = createRule("RuleDelete without ZenPolicy", 896 "Deletevalue", NotificationManager.INTERRUPTION_FILTER_ALARMS); 897 AutomaticZenRule ruleToCreate2 = createRule("RuleDelete with ZenPolicy", 898 "Deletevalue", NotificationManager.INTERRUPTION_FILTER_ALARMS); 899 id1 = mNm.addAutomaticZenRule(ruleToCreate1); 900 id2 = mNm.addAutomaticZenRule(ruleToCreate2); 901 902 if (id1 != null && id2 != null) { 903 if (mNm.removeAutomaticZenRule(id1) && mNm.removeAutomaticZenRule(id2)) { 904 if (mNm.getAutomaticZenRule(id1) == null 905 && mNm.getAutomaticZenRule(id2) == null) { 906 status = PASS; 907 } else { 908 logFail(); 909 status = FAIL; 910 } 911 } else { 912 logFail(); 913 status = FAIL; 914 } 915 } else { 916 logFail("Couldn't test rule deletion; creation failed."); 917 status = FAIL; 918 } 919 next(); 920 } 921 922 @Override tearDown()923 protected void tearDown() { 924 MockConditionProvider.getInstance().resetData(); 925 delay(); 926 } 927 } 928 929 private class UnsubscribeAutomaticZenRuleTest extends InteractiveTestCase { 930 private String id = null; 931 private AutomaticZenRule ruleToCreate; 932 private int mSubscribeRetries = 3; 933 private int mUnsubscribeRetries = 3; 934 private boolean mSubscribing = true; 935 936 @Override inflate(ViewGroup parent)937 protected View inflate(ViewGroup parent) { 938 return createAutoItem(parent, R.string.cp_unsubscribe_rule); 939 } 940 941 @Override setUp()942 protected void setUp() { 943 ruleToCreate = createRule("RuleUnsubscribe", "valueUnsubscribe", 944 INTERRUPTION_FILTER_PRIORITY); 945 id = mNm.addAutomaticZenRule(ruleToCreate); 946 status = READY; 947 delay(); 948 } 949 950 @Override test()951 protected void test() { 952 if (mSubscribing) { 953 // trying to subscribe 954 boolean foundMatch = false; 955 List<Uri> subscriptions = MockConditionProvider.getInstance().getSubscriptions(); 956 for (Uri actual : subscriptions) { 957 if (ruleToCreate.getConditionId().equals(actual)) { 958 status = PASS; 959 foundMatch = true; 960 break; 961 } 962 } 963 if (foundMatch) { 964 // Now that it's subscribed, remove the rule and verify that it 965 // unsubscribes. 966 Log.d(MockConditionProvider.TAG, "Found subscription, removing"); 967 mNm.removeAutomaticZenRule(id); 968 969 mSubscribing = false; 970 status = RETEST; 971 next(); 972 } else if (--mSubscribeRetries > 0) { 973 setFailed(); 974 } else { 975 status = RETEST; 976 next(); 977 } 978 } else { 979 // trying to unsubscribe 980 List<Uri> continuingSubscriptions 981 = MockConditionProvider.getInstance().getSubscriptions(); 982 boolean stillFoundMatch = false; 983 for (Uri actual : continuingSubscriptions) { 984 if (ruleToCreate.getConditionId().equals(actual)) { 985 stillFoundMatch = true; 986 break; 987 } 988 } 989 if (!stillFoundMatch) { 990 status = PASS; 991 next(); 992 } else if (stillFoundMatch && --mUnsubscribeRetries > 0) { 993 Log.d(MockConditionProvider.TAG, "Still found subscription, retrying"); 994 status = RETEST; 995 next(); 996 } else { 997 setFailed(); 998 } 999 } 1000 } 1001 1002 @Override tearDown()1003 protected void tearDown() { 1004 mNm.removeAutomaticZenRule(id); 1005 MockConditionProvider.getInstance().resetData(); 1006 } 1007 } 1008 1009 private class IsDisabledTest extends InteractiveTestCase { 1010 @Override inflate(ViewGroup parent)1011 protected View inflate(ViewGroup parent) { 1012 return createSettingsItem(parent, R.string.cp_disable_service); 1013 } 1014 1015 @Override autoStart()1016 boolean autoStart() { 1017 return true; 1018 } 1019 1020 @Override test()1021 protected void test() { 1022 if (!mNm.isNotificationPolicyAccessGranted()) { 1023 status = PASS; 1024 } else { 1025 status = WAIT_FOR_USER; 1026 } 1027 next(); 1028 } 1029 1030 @Override getIntent()1031 protected Intent getIntent() { 1032 return new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); 1033 } 1034 } 1035 1036 private class ServiceStoppedTest extends InteractiveTestCase { 1037 int mRetries = 5; 1038 1039 @Override inflate(ViewGroup parent)1040 protected View inflate(ViewGroup parent) { 1041 return createAutoItem(parent, R.string.cp_service_stopped); 1042 } 1043 1044 @Override test()1045 protected void test() { 1046 if (MockConditionProvider.getInstance() == null || 1047 !MockConditionProvider.getInstance().isConnected()) { 1048 status = PASS; 1049 } else { 1050 if (--mRetries > 0) { 1051 status = RETEST; 1052 } else { 1053 logFail(); 1054 status = FAIL; 1055 } 1056 } 1057 next(); 1058 } 1059 } 1060 createRule(String name, String queryValue, int status)1061 private AutomaticZenRule createRule(String name, String queryValue, int status) { 1062 return new AutomaticZenRule(name, 1063 ComponentName.unflattenFromString(CP_PATH), 1064 MockConditionProvider.toConditionId(queryValue), status, true); 1065 } 1066 createRuleWithZenPolicy(String name, String queryValue, ZenPolicy policy)1067 private AutomaticZenRule createRuleWithZenPolicy(String name, String queryValue, 1068 ZenPolicy policy) { 1069 return new AutomaticZenRule(name, 1070 ComponentName.unflattenFromString(CP_PATH), null, 1071 MockConditionProvider.toConditionId(queryValue), policy, 1072 INTERRUPTION_FILTER_PRIORITY, true); 1073 } 1074 compareRules(AutomaticZenRule rule1, AutomaticZenRule rule2)1075 private boolean compareRules(AutomaticZenRule rule1, AutomaticZenRule rule2) { 1076 return rule1.isEnabled() == rule2.isEnabled() 1077 && Objects.equals(rule1.getName(), rule2.getName()) 1078 && rule1.getInterruptionFilter() == rule2.getInterruptionFilter() 1079 && Objects.equals(rule1.getConditionId(), rule2.getConditionId()) 1080 && Objects.equals(rule1.getOwner(), rule2.getOwner()) 1081 && Objects.equals(rule1.getZenPolicy(), rule2.getZenPolicy()); 1082 } 1083 createSettingsItem(ViewGroup parent, int messageId)1084 protected View createSettingsItem(ViewGroup parent, int messageId) { 1085 return createUserItem(parent, R.string.cp_start_settings, messageId); 1086 } 1087 } 1088