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