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 com.android.cts.verifier.R; 20 21 import android.app.AutomaticZenRule; 22 import android.app.NotificationManager; 23 import android.content.ComponentName; 24 import android.content.Intent; 25 import android.net.Uri; 26 import android.os.Parcelable; 27 import android.provider.Settings; 28 import android.provider.Settings.Secure; 29 import android.text.TextUtils; 30 import android.util.Log; 31 import android.view.View; 32 import android.view.ViewGroup; 33 34 import java.util.ArrayList; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.Objects; 38 39 public class ConditionProviderVerifierActivity extends InteractiveVerifierActivity 40 implements Runnable { 41 protected static final String CP_PACKAGE = "com.android.cts.verifier"; 42 protected static final String CP_PATH = CP_PACKAGE + 43 "/com.android.cts.verifier.notifications.MockConditionProvider"; 44 45 @Override getTitleResource()46 int getTitleResource() { 47 return R.string.cp_test; 48 } 49 50 @Override getInstructionsResource()51 int getInstructionsResource() { 52 return R.string.cp_info; 53 } 54 55 // Test Setup 56 57 @Override createTestItems()58 protected List<InteractiveTestCase> createTestItems() { 59 List<InteractiveTestCase> tests = new ArrayList<>(9); 60 tests.add(new IsEnabledTest()); 61 tests.add(new ServiceStartedTest()); 62 tests.add(new CreateAutomaticZenRuleTest()); 63 tests.add(new GetAutomaticZenRuleTest()); 64 tests.add(new GetAutomaticZenRulesTest()); 65 tests.add(new SubscribeAutomaticZenRuleTest()); 66 tests.add(new DeleteAutomaticZenRuleTest()); 67 tests.add(new UnsubscribeAutomaticZenRuleTest()); 68 tests.add(new IsDisabledTest()); 69 tests.add(new ServiceStoppedTest()); 70 return tests; 71 } 72 73 protected class IsEnabledTest extends InteractiveTestCase { 74 @Override inflate(ViewGroup parent)75 View inflate(ViewGroup parent) { 76 return createSettingsItem(parent, R.string.cp_enable_service); 77 } 78 79 @Override autoStart()80 boolean autoStart() { 81 return true; 82 } 83 84 @Override test()85 void test() { 86 Intent settings = new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS); 87 if (settings.resolveActivity(mPackageManager) == null) { 88 logFail("no settings activity"); 89 status = FAIL; 90 } else { 91 String cpPackages = Secure.getString(getContentResolver(), 92 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES); 93 if (cpPackages != null && cpPackages.contains(CP_PACKAGE)) { 94 status = PASS; 95 } else { 96 status = WAIT_FOR_USER; 97 } 98 next(); 99 } 100 } 101 tearDown()102 void tearDown() { 103 // wait for the service to start 104 delay(); 105 } 106 } 107 108 protected class ServiceStartedTest extends InteractiveTestCase { 109 @Override inflate(ViewGroup parent)110 View inflate(ViewGroup parent) { 111 return createAutoItem(parent, R.string.cp_service_started); 112 } 113 114 @Override test()115 void test() { 116 MockConditionProvider.probeConnected(mContext, 117 new MockConditionProvider.BooleanResultCatcher() { 118 @Override 119 public void accept(boolean result) { 120 if (result) { 121 status = PASS; 122 } else { 123 logFail(); 124 status = RETEST; 125 delay(); 126 } 127 next(); 128 } 129 }); 130 delay(); // in case the catcher never returns 131 } 132 133 @Override tearDown()134 void tearDown() { 135 MockConditionProvider.resetData(mContext); 136 delay(); 137 } 138 } 139 140 private class CreateAutomaticZenRuleTest extends InteractiveTestCase { 141 private String id = null; 142 143 @Override inflate(ViewGroup parent)144 View inflate(ViewGroup parent) { 145 return createAutoItem(parent, R.string.cp_create_rule); 146 } 147 148 @Override test()149 void test() { 150 long now = System.currentTimeMillis(); 151 AutomaticZenRule ruleToCreate = 152 createRule("Rule", "value", NotificationManager.INTERRUPTION_FILTER_ALARMS); 153 id = mNm.addAutomaticZenRule(ruleToCreate); 154 155 if (!TextUtils.isEmpty(id)) { 156 status = PASS; 157 } else { 158 logFail(); 159 status = FAIL; 160 } 161 next(); 162 } 163 164 @Override tearDown()165 void tearDown() { 166 if (id != null) { 167 mNm.removeAutomaticZenRule(id); 168 } 169 MockConditionProvider.resetData(mContext); 170 delay(); 171 } 172 } 173 174 private class SubscribeAutomaticZenRuleTest extends InteractiveTestCase { 175 private String id = null; 176 private AutomaticZenRule ruleToCreate; 177 178 @Override inflate(ViewGroup parent)179 View inflate(ViewGroup parent) { 180 return createAutoItem(parent, R.string.cp_subscribe_rule); 181 } 182 183 @Override setUp()184 void setUp() { 185 ruleToCreate = createRule("RuleSubscribe", "Subscribevalue", 186 NotificationManager.INTERRUPTION_FILTER_ALARMS); 187 id = mNm.addAutomaticZenRule(ruleToCreate); 188 status = READY; 189 delay(); 190 } 191 192 @Override test()193 void test() { 194 195 MockConditionProvider.probeSubscribe(mContext, 196 new MockConditionProvider.ParcelableListResultCatcher() { 197 @Override 198 public void accept(List<Parcelable> result) { 199 boolean foundMatch = false; 200 for (Parcelable p : result) { 201 Uri uri = (Uri) p; 202 if (ruleToCreate.getConditionId().equals(uri)) { 203 foundMatch = true; 204 break; 205 } 206 } 207 if (foundMatch) { 208 status = PASS; 209 } else { 210 logFail(); 211 status = RETEST; 212 } 213 next(); 214 } 215 }); 216 delay(); // in case the catcher never returns 217 } 218 219 @Override tearDown()220 void tearDown() { 221 if (id != null) { 222 mNm.removeAutomaticZenRule(id); 223 } 224 MockConditionProvider.resetData(mContext); 225 // wait for intent to move through the system 226 delay(); 227 } 228 } 229 230 private class GetAutomaticZenRuleTest extends InteractiveTestCase { 231 private String id = null; 232 private AutomaticZenRule ruleToCreate; 233 234 @Override inflate(ViewGroup parent)235 View inflate(ViewGroup parent) { 236 return createAutoItem(parent, R.string.cp_get_rule); 237 } 238 239 @Override setUp()240 void setUp() { 241 ruleToCreate = createRule("RuleGet", "valueGet", 242 NotificationManager.INTERRUPTION_FILTER_ALARMS); 243 id = mNm.addAutomaticZenRule(ruleToCreate); 244 status = READY; 245 delay(); 246 } 247 248 @Override test()249 void test() { 250 AutomaticZenRule queriedRule = mNm.getAutomaticZenRule(id); 251 if (queriedRule != null 252 && ruleToCreate.getName().equals(queriedRule.getName()) 253 && ruleToCreate.getOwner().equals(queriedRule.getOwner()) 254 && ruleToCreate.getConditionId().equals(queriedRule.getConditionId()) 255 && ruleToCreate.isEnabled() == queriedRule.isEnabled()) { 256 status = PASS; 257 } else { 258 logFail(); 259 status = FAIL; 260 } 261 next(); 262 } 263 264 @Override tearDown()265 void tearDown() { 266 if (id != null) { 267 mNm.removeAutomaticZenRule(id); 268 } 269 MockConditionProvider.resetData(mContext); 270 delay(); 271 } 272 } 273 274 private class GetAutomaticZenRulesTest extends InteractiveTestCase { 275 private List<String> ids = new ArrayList<>(); 276 private AutomaticZenRule rule1; 277 private AutomaticZenRule rule2; 278 279 @Override inflate(ViewGroup parent)280 View inflate(ViewGroup parent) { 281 return createAutoItem(parent, R.string.cp_get_rules); 282 } 283 284 @Override setUp()285 void setUp() { 286 rule1 = createRule("Rule1", "value1", NotificationManager.INTERRUPTION_FILTER_ALARMS); 287 rule2 = createRule("Rule2", "value2", NotificationManager.INTERRUPTION_FILTER_NONE); 288 ids.add(mNm.addAutomaticZenRule(rule1)); 289 ids.add(mNm.addAutomaticZenRule(rule2)); 290 status = READY; 291 delay(); 292 } 293 294 @Override test()295 void test() { 296 Map<String, AutomaticZenRule> rules = mNm.getAutomaticZenRules(); 297 298 if (rules == null || rules.size() != 2) { 299 logFail(); 300 status = FAIL; 301 next(); 302 return; 303 } 304 305 for (AutomaticZenRule createdRule : rules.values()) { 306 if (!compareRules(createdRule, rule1) && !compareRules(createdRule, rule2)) { 307 logFail(); 308 status = FAIL; 309 break; 310 } 311 } 312 status = PASS; 313 next(); 314 } 315 316 @Override tearDown()317 void tearDown() { 318 for (String id : ids) { 319 mNm.removeAutomaticZenRule(id); 320 } 321 MockConditionProvider.resetData(mContext); 322 delay(); 323 } 324 } 325 326 private class DeleteAutomaticZenRuleTest extends InteractiveTestCase { 327 private String id = null; 328 329 @Override inflate(ViewGroup parent)330 View inflate(ViewGroup parent) { 331 return createAutoItem(parent, R.string.cp_delete_rule); 332 } 333 334 @Override test()335 void test() { 336 AutomaticZenRule ruleToCreate = createRule("RuleDelete", "Deletevalue", 337 NotificationManager.INTERRUPTION_FILTER_ALARMS); 338 id = mNm.addAutomaticZenRule(ruleToCreate); 339 340 if (id != null) { 341 if (mNm.removeAutomaticZenRule(id)) { 342 if (mNm.getAutomaticZenRule(id) == null) { 343 status = PASS; 344 } else { 345 logFail(); 346 status = FAIL; 347 } 348 } else { 349 logFail(); 350 status = FAIL; 351 } 352 } else { 353 logFail("Couldn't test rule deletion; creation failed."); 354 status = FAIL; 355 } 356 next(); 357 } 358 359 @Override tearDown()360 void tearDown() { 361 MockConditionProvider.resetData(mContext); 362 delay(); 363 } 364 } 365 366 private class UnsubscribeAutomaticZenRuleTest extends InteractiveTestCase { 367 private String id = null; 368 private AutomaticZenRule ruleToCreate; 369 370 @Override inflate(ViewGroup parent)371 View inflate(ViewGroup parent) { 372 return createAutoItem(parent, R.string.cp_unsubscribe_rule); 373 } 374 375 @Override setUp()376 void setUp() { 377 ruleToCreate = createRule("RuleUnsubscribe", "valueUnsubscribe", 378 NotificationManager.INTERRUPTION_FILTER_PRIORITY); 379 id = mNm.addAutomaticZenRule(ruleToCreate); 380 status = READY; 381 delay(); 382 } 383 384 @Override test()385 void test() { 386 MockConditionProvider.probeSubscribe(mContext, 387 new MockConditionProvider.ParcelableListResultCatcher() { 388 @Override 389 public void accept(List<Parcelable> result) { 390 boolean foundMatch = false; 391 for (Parcelable p : result) { 392 Uri uri = (Uri) p; 393 if (ruleToCreate.getConditionId().equals(uri)) { 394 foundMatch = true; 395 break; 396 } 397 } 398 if (foundMatch) { 399 // Now that it's subscribed, remove the rule and verify that it 400 // unsubscribes. 401 mNm.removeAutomaticZenRule(id); 402 MockConditionProvider.probeSubscribe(mContext, 403 new MockConditionProvider.ParcelableListResultCatcher() { 404 @Override 405 public void accept(List<Parcelable> result) { 406 boolean foundMatch = false; 407 for (Parcelable p : result) { 408 Uri uri = (Uri) p; 409 if (ruleToCreate.getConditionId().equals(uri)) { 410 foundMatch = true; 411 break; 412 } 413 } 414 if (foundMatch) { 415 logFail(); 416 status = RETEST; 417 } else { 418 status = PASS; 419 } 420 next(); 421 } 422 }); 423 } else { 424 logFail("Couldn't test unsubscribe; subscribe failed."); 425 status = RETEST; 426 next(); 427 } 428 } 429 }); 430 delay(); // in case the catcher never returns 431 } 432 433 @Override tearDown()434 void tearDown() { 435 mNm.removeAutomaticZenRule(id); 436 MockConditionProvider.resetData(mContext); 437 // wait for intent to move through the system 438 delay(); 439 } 440 } 441 442 private class IsDisabledTest extends InteractiveTestCase { 443 @Override inflate(ViewGroup parent)444 View inflate(ViewGroup parent) { 445 return createSettingsItem(parent, R.string.cp_disable_service); 446 } 447 448 @Override autoStart()449 boolean autoStart() { 450 return true; 451 } 452 453 @Override test()454 void test() { 455 String cpPackages = Secure.getString(getContentResolver(), 456 Settings.Secure.ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES); 457 if (cpPackages == null || !cpPackages.contains(CP_PACKAGE)) { 458 status = PASS; 459 } else { 460 status = WAIT_FOR_USER; 461 } 462 next(); 463 } 464 465 @Override tearDown()466 void tearDown() { 467 MockConditionProvider.resetData(mContext); 468 delay(); 469 } 470 } 471 472 private class ServiceStoppedTest extends InteractiveTestCase { 473 @Override inflate(ViewGroup parent)474 View inflate(ViewGroup parent) { 475 return createAutoItem(parent, R.string.cp_service_stopped); 476 } 477 478 @Override test()479 void test() { 480 MockConditionProvider.probeConnected(mContext, 481 new MockConditionProvider.BooleanResultCatcher() { 482 @Override 483 public void accept(boolean result) { 484 if (result) { 485 logFail(); 486 status = RETEST; 487 delay(); 488 } else { 489 status = PASS; 490 } 491 next(); 492 } 493 }); 494 delay(); // in case the catcher never returns 495 } 496 497 @Override tearDown()498 void tearDown() { 499 MockConditionProvider.resetData(mContext); 500 // wait for intent to move through the system 501 delay(); 502 } 503 } 504 createRule(String name, String queryValue, int status)505 private AutomaticZenRule createRule(String name, String queryValue, int status) { 506 return new AutomaticZenRule(name, 507 ComponentName.unflattenFromString(CP_PATH), 508 MockConditionProvider.toConditionId(queryValue), 509 status, 510 true); 511 } 512 compareRules(AutomaticZenRule rule1, AutomaticZenRule rule2)513 private boolean compareRules(AutomaticZenRule rule1, AutomaticZenRule rule2) { 514 return rule1.isEnabled() == rule2.isEnabled() 515 && Objects.equals(rule1.getName(), rule2.getName()) 516 && rule1.getInterruptionFilter() == rule2.getInterruptionFilter() 517 && Objects.equals(rule1.getConditionId(), rule2.getConditionId()) 518 && Objects.equals(rule1.getOwner(), rule2.getOwner()); 519 } 520 createSettingsItem(ViewGroup parent, int messageId)521 protected View createSettingsItem(ViewGroup parent, int messageId) { 522 return createUserItem(parent, R.string.cp_start_settings, messageId); 523 } 524 launchSettings()525 public void launchSettings() { 526 startActivity(new Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)); 527 } 528 actionPressed(View v)529 public void actionPressed(View v) { 530 Object tag = v.getTag(); 531 if (tag instanceof Integer) { 532 int id = ((Integer) tag).intValue(); 533 if (id == R.string.cp_start_settings) { 534 launchSettings(); 535 } else if (id == R.string.attention_ready) { 536 mCurrentTest.status = READY; 537 next(); 538 } 539 } 540 } 541 } 542