• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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