• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.app;
18 
19 import static android.app.NotificationManager.INTERRUPTION_FILTER_ALL;
20 import static android.app.NotificationSystemUtil.runAsSystemUi;
21 import static android.app.NotificationSystemUtil.toggleNotificationPolicyAccess;
22 import static android.service.notification.Condition.STATE_FALSE;
23 import static android.service.notification.Condition.STATE_TRUE;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.net.Uri;
30 import android.platform.test.annotations.RequiresFlagsEnabled;
31 import android.platform.test.flag.junit.CheckFlagsRule;
32 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
33 import android.service.notification.Condition;
34 
35 import androidx.test.core.app.ApplicationProvider;
36 import androidx.test.ext.junit.runners.AndroidJUnit4;
37 
38 import org.junit.After;
39 import org.junit.Before;
40 import org.junit.Rule;
41 import org.junit.Test;
42 import org.junit.runner.RunWith;
43 
44 import java.util.Map;
45 
46 @RunWith(AndroidJUnit4.class)
47 public class NotificationManagerZenTest {
48 
49     private Context mContext;
50     private NotificationManager mNotificationManager;
51 
52     @Rule
53     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
54 
55     @Before
setUp()56     public void setUp() throws Exception {
57         mContext = ApplicationProvider.getApplicationContext();
58         mNotificationManager = mContext.getSystemService(NotificationManager.class);
59 
60         toggleNotificationPolicyAccess(mContext, mContext.getPackageName(), true);
61         runAsSystemUi(() -> mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL));
62         removeAutomaticZenRules();
63     }
64 
65     @After
tearDown()66     public void tearDown() {
67         runAsSystemUi(() -> mNotificationManager.setInterruptionFilter(INTERRUPTION_FILTER_ALL));
68         removeAutomaticZenRules();
69     }
70 
removeAutomaticZenRules()71     private void removeAutomaticZenRules() {
72         // Delete AZRs created by this test (query "as app", then delete "as system" so they are
73         // not preserved to be restored later).
74         Map<String, AutomaticZenRule> rules = mNotificationManager.getAutomaticZenRules();
75         runAsSystemUi(() -> {
76             for (String ruleId : rules.keySet()) {
77                 mNotificationManager.removeAutomaticZenRule(ruleId);
78             }
79         });
80     }
81 
82     @Test
83     @RequiresFlagsEnabled(Flags.FLAG_MODES_UI)
setAutomaticZenRuleState_manualActivation()84     public void setAutomaticZenRuleState_manualActivation() {
85         AutomaticZenRule ruleToCreate = createZenRule("rule");
86         String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
87         Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on",
88                 STATE_TRUE, Condition.SOURCE_USER_ACTION);
89         Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
90                 STATE_FALSE, Condition.SOURCE_USER_ACTION);
91         Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
92                 STATE_TRUE);
93         Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
94                 STATE_FALSE);
95 
96         // User manually activates -> it's active.
97         runAsSystemUi(
98                 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate));
99         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
100 
101         // User manually deactivates -> it's inactive.
102         runAsSystemUi(
103                 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate));
104         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
105 
106         // And app can activate and deactivate.
107         mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
108         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
109         mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
110         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
111     }
112 
113     @Test
114     @RequiresFlagsEnabled(Flags.FLAG_MODES_UI)
setAutomaticZenRuleState_manualDeactivation()115     public void setAutomaticZenRuleState_manualDeactivation() {
116         AutomaticZenRule ruleToCreate = createZenRule("rule");
117         String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
118         Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on",
119                 STATE_TRUE, Condition.SOURCE_USER_ACTION);
120         Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
121                 STATE_FALSE, Condition.SOURCE_USER_ACTION);
122         Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
123                 STATE_TRUE);
124         Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
125                 STATE_FALSE);
126 
127         // App activates rule.
128         mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
129         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
130 
131         // User manually deactivates -> it's inactive.
132         runAsSystemUi(
133                 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate));
134         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
135 
136         // User manually reactivates -> it's active.
137         runAsSystemUi(
138                 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate));
139         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
140 
141         // That manual activation removed the override-deactivate, but didn't put an
142         // override-activate, so app can deactivate when its natural schedule ends.
143         mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
144         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
145     }
146 
147     @Test
148     @RequiresFlagsEnabled(Flags.FLAG_MODES_UI)
setAutomaticZenRuleState_respectsManuallyActivated()149     public void setAutomaticZenRuleState_respectsManuallyActivated() {
150         AutomaticZenRule ruleToCreate = createZenRule("rule");
151         String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
152         Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-on",
153                 STATE_TRUE, Condition.SOURCE_USER_ACTION);
154         Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
155                 STATE_TRUE);
156         Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
157                 STATE_FALSE);
158 
159         // App thinks rule should be inactive.
160         mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
161         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
162 
163         // Manually activate -> it's active.
164         runAsSystemUi(() -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate));
165         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
166 
167         // App says it should be inactive, but it's ignored.
168         mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
169         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
170 
171         // App says it should be active. No change now...
172         mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
173         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
174 
175         // ... but when the app wants to deactivate next time, it works.
176         mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
177         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
178     }
179 
180     @Test
181     @RequiresFlagsEnabled(Flags.FLAG_MODES_UI)
setAutomaticZenRuleState_respectsManuallyDeactivated()182     public void setAutomaticZenRuleState_respectsManuallyDeactivated() {
183         AutomaticZenRule ruleToCreate = createZenRule("rule");
184         String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
185         Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
186                 STATE_FALSE, Condition.SOURCE_USER_ACTION);
187         Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
188                 STATE_TRUE);
189         Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
190                 STATE_FALSE);
191 
192         // App activates rule.
193         mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
194         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
195 
196         // User manually deactivates -> it's inactive.
197         runAsSystemUi(
198                 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate));
199         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
200 
201         // App says it should be active, but it's ignored.
202         mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
203         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
204 
205         // App says it should be inactive. No change now...
206         mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
207         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
208 
209         // ... but when the app wants to activate next time, it works.
210         mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
211         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
212     }
213 
214     @Test
215     @RequiresFlagsEnabled(Flags.FLAG_MODES_UI)
setAutomaticZenRuleState_manualActivationFromApp()216     public void setAutomaticZenRuleState_manualActivationFromApp() {
217         AutomaticZenRule ruleToCreate = createZenRule("rule");
218         String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
219         Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
220                 STATE_TRUE, Condition.SOURCE_USER_ACTION);
221         Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
222                 STATE_FALSE, Condition.SOURCE_USER_ACTION);
223         Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
224                 STATE_TRUE);
225         Condition autoDeactivate = new Condition(ruleToCreate.getConditionId(), "auto-off",
226                 STATE_FALSE);
227 
228         // App activates rule.
229         mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
230         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
231 
232         // User manually deactivates from SysUI -> it's inactive.
233         runAsSystemUi(
234                 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate));
235         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
236 
237         // User manually activates from App -> it's active.
238         mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate);
239         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
240 
241         // And app can automatically deactivate it later.
242         mNotificationManager.setAutomaticZenRuleState(ruleId, autoDeactivate);
243         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
244     }
245 
246     @Test
247     @RequiresFlagsEnabled(Flags.FLAG_MODES_UI)
setAutomaticZenRuleState_manualDeactivationFromApp()248     public void setAutomaticZenRuleState_manualDeactivationFromApp() {
249         AutomaticZenRule ruleToCreate = createZenRule("rule");
250         String ruleId = mNotificationManager.addAutomaticZenRule(ruleToCreate);
251         Condition manualActivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
252                 STATE_TRUE, Condition.SOURCE_USER_ACTION);
253         Condition manualDeactivate = new Condition(ruleToCreate.getConditionId(), "manual-off",
254                 STATE_FALSE, Condition.SOURCE_USER_ACTION);
255         Condition autoActivate = new Condition(ruleToCreate.getConditionId(), "auto-on",
256                 STATE_TRUE);
257 
258         // User manually activates from SysUI -> it's active.
259         runAsSystemUi(
260                 () -> mNotificationManager.setAutomaticZenRuleState(ruleId, manualActivate));
261         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
262 
263         // User manually deactivates from App -> it's inactive.
264         mNotificationManager.setAutomaticZenRuleState(ruleId, manualDeactivate);
265         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_FALSE);
266 
267         // And app can automatically activate it later.
268         mNotificationManager.setAutomaticZenRuleState(ruleId, autoActivate);
269         assertThat(mNotificationManager.getAutomaticZenRuleState(ruleId)).isEqualTo(STATE_TRUE);
270     }
271 
createZenRule(String name)272     private AutomaticZenRule createZenRule(String name) {
273         return createZenRule(name, NotificationManager.INTERRUPTION_FILTER_PRIORITY);
274     }
275 
createZenRule(String name, int filter)276     private AutomaticZenRule createZenRule(String name, int filter) {
277         return new AutomaticZenRule(name, null,
278                 new ComponentName(mContext, ExampleActivity.class),
279                 new Uri.Builder().scheme("scheme")
280                         .appendPath("path")
281                         .appendQueryParameter("fake_rule", "fake_value")
282                         .build(), null, filter, true);
283     }
284 }
285