• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.settings.notification;
18 
19 import static android.provider.Settings.Global.ZEN_MODE;
20 import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
21 import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
22 import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
23 import static android.provider.Settings.Global.ZEN_MODE_OFF;
24 import static junit.framework.Assert.assertTrue;
25 import static org.junit.Assert.assertFalse;
26 import static org.mockito.Mockito.mock;
27 import static org.mockito.Mockito.spy;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
30 
31 import android.app.NotificationManager;
32 import android.content.ComponentName;
33 import android.content.ContentResolver;
34 import android.content.Context;
35 import android.net.Uri;
36 import android.provider.Settings;
37 import android.service.notification.ZenModeConfig;
38 import android.service.notification.ZenModeConfig.ZenRule;
39 import android.support.v7.preference.Preference;
40 import android.support.v7.preference.PreferenceScreen;
41 import android.util.ArrayMap;
42 
43 import com.android.settings.notification.AbstractZenModePreferenceController.ZenModeConfigWrapper;
44 import com.android.settings.testutils.SettingsRobolectricTestRunner;
45 import com.android.settingslib.core.lifecycle.Lifecycle;
46 
47 import org.junit.Before;
48 import org.junit.Test;
49 import org.junit.runner.RunWith;
50 import org.mockito.Mock;
51 import org.mockito.MockitoAnnotations;
52 import org.robolectric.RuntimeEnvironment;
53 import org.robolectric.shadows.ShadowApplication;
54 import org.robolectric.util.ReflectionHelpers;
55 
56 @RunWith(SettingsRobolectricTestRunner.class)
57 public class ZenModeSettingsFooterPreferenceControllerTest {
58 
59     private static final String TEST_APP_NAME = "test_app";
60     private static final String TEST_RULE_NAME = "test_rule_name";
61     private static final String MANUAL_RULE_FIELD = "manualRule";
62     private static final String AUTOMATIC_RULES_FIELD = "automaticRules";
63 
64     private ZenModeSettingsFooterPreferenceController mController;
65 
66     private final ArrayMap<String, ZenRule> mInjectedAutomaticRules = new ArrayMap<>();
67 
68     @Mock
69     private NotificationManager mNotificationManager;
70     @Mock
71     private Preference mockPref;
72     @Mock
73     private ZenModeConfig mZenModeConfig;
74     @Mock
75     private PreferenceScreen mPreferenceScreen;
76     @Mock
77     private ZenModeConfigWrapper mConfigWrapper;
78 
79     private Context mContext;
80     private ContentResolver mContentResolver;
81 
82     @Before
setup()83     public void setup() {
84         MockitoAnnotations.initMocks(this);
85         ShadowApplication shadowApplication = ShadowApplication.getInstance();
86         shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
87 
88         mContext = shadowApplication.getApplicationContext();
89         mContentResolver = RuntimeEnvironment.application.getContentResolver();
90         when(mNotificationManager.getZenModeConfig()).thenReturn(mZenModeConfig);
91 
92         mController =
93             new ZenModeSettingsFooterPreferenceController(mContext, mock(Lifecycle.class));
94         ReflectionHelpers.setField(mZenModeConfig, AUTOMATIC_RULES_FIELD, mInjectedAutomaticRules);
95         ReflectionHelpers.setField(mController, "mZenModeConfigWrapper", mConfigWrapper);
96 
97         when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
98         mController.displayPreference(mPreferenceScreen);
99     }
100 
101     @Test
totalSilence_footerIsAvailable()102     public void totalSilence_footerIsAvailable() {
103         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_NO_INTERRUPTIONS);
104         assertTrue(mController.isAvailable());
105     }
106 
107     @Test
alarmsOnly_footerIsAvailable()108     public void alarmsOnly_footerIsAvailable() {
109         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_ALARMS);
110         assertTrue(mController.isAvailable());
111     }
112 
113     @Test
priorityOnly_footerIsAvailable()114     public void priorityOnly_footerIsAvailable() {
115         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
116         assertTrue(mController.isAvailable());
117     }
118 
119     @Test
zenModeOff_footerIsNotAvailable()120     public void zenModeOff_footerIsNotAvailable() {
121         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_OFF);
122         assertFalse(mController.isAvailable());
123     }
124 
125     @Test
app_manualRule_setFooterTitle()126     public void app_manualRule_setFooterTitle() {
127         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
128         injectManualRuleFromApp();
129         mController.updateState(mockPref);
130 
131         verify(mockPref).setTitle(mContext.getString(
132                 com.android.settings.R.string.zen_mode_settings_dnd_automatic_rule_app,
133                 TEST_APP_NAME));
134     }
135 
136     @Test
time_manualRule_setFooterTitle()137     public void time_manualRule_setFooterTitle() {
138         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
139         String placeholder = "placeholder";
140         injectManualRuleWithTimeCountdown(1000, placeholder);
141         mController.updateState(mockPref);
142 
143         verify(mockPref).setTitle(mContext.getString(
144                 com.android.settings.R.string.zen_mode_settings_dnd_manual_end_time, placeholder));
145     }
146 
147     @Test
forever_manualRule_setFooterTitle()148     public void forever_manualRule_setFooterTitle() {
149         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
150         injectManualRuleWithIndefiniteEnd();
151         mController.updateState(mockPref);
152 
153         verify(mockPref).setTitle(mContext.getString(
154                 com.android.settings.R.string.zen_mode_settings_dnd_manual_indefinite));
155     }
156 
157     @Test
automaticRule_noManualRule_setFooterTitle()158     public void automaticRule_noManualRule_setFooterTitle() {
159         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
160         // no manual rule
161         ReflectionHelpers.setField(mZenModeConfig, MANUAL_RULE_FIELD, null);
162 
163         // adding automatic rule
164         injectNewAutomaticRule(TEST_RULE_NAME, true, false);
165 
166         mController.updateState(mockPref);
167 
168         verify(mockPref).setTitle(mContext.getString(
169                 com.android.settings.R.string.zen_mode_settings_dnd_automatic_rule,
170                 TEST_RULE_NAME));
171     }
172 
173     @Test
manualRuleEndsLast_hasAutomaticRule_setFooterTitle()174     public void manualRuleEndsLast_hasAutomaticRule_setFooterTitle() {
175         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
176         // manual rule that ends after automatic rule ends
177         injectManualRuleWithIndefiniteEnd();
178 
179         // automatic rule that ends before manual rule ends
180         injectNewAutomaticRule(TEST_RULE_NAME, true, false);
181 
182         mController.updateState(mockPref);
183 
184         // manual rule end time is after automatic rule end time, so it is displayed
185         verify(mockPref).setTitle(mContext.getString(
186                 com.android.settings.R.string.zen_mode_settings_dnd_manual_indefinite));
187     }
188 
189     @Test
automaticRuleEndsLast_hasManualRule_setFooterTitle()190     public void automaticRuleEndsLast_hasManualRule_setFooterTitle() {
191         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
192         // manual rule that ends before automatic rule ends
193         injectManualRuleWithTimeCountdown(1000, "");
194 
195         // automatic rule that ends after manual rule ends
196         ZenRule rule = injectNewAutomaticRule(TEST_RULE_NAME, true, false);
197         when(mConfigWrapper.parseAutomaticRuleEndTime(rule.conditionId)).thenReturn(2000L);
198 
199         mController.updateState(mockPref);
200 
201         // automatic rule end time is after manual rule end time, so it is displayed
202         verify(mockPref).setTitle(mContext.getString(
203                 com.android.settings.R.string.zen_mode_settings_dnd_automatic_rule,
204                 TEST_RULE_NAME));
205     }
206 
207     @Test
multipleAutomaticRules_appAutoRuleautomaticRuleApp_setFooterTitle()208     public void multipleAutomaticRules_appAutoRuleautomaticRuleApp_setFooterTitle() {
209         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
210 
211         // automatic rule that ends after manual rule ends
212         ZenRule rule1 = injectNewAutomaticRule(TEST_RULE_NAME + "1", false, false);
213         when(mConfigWrapper.parseAutomaticRuleEndTime(rule1.conditionId)).thenReturn(10000L);
214 
215         ZenRule rule2 = injectNewAutomaticRule(TEST_RULE_NAME + "2", true, true);
216 
217         ZenRule rule3 = injectNewAutomaticRule(TEST_RULE_NAME + "3", true, false);
218         when(mConfigWrapper.parseAutomaticRuleEndTime(rule3.conditionId)).thenReturn(9000L);
219 
220         mController.updateState(mockPref);
221 
222         // automatic rule from app is displayed
223         verify(mockPref).setTitle(mContext.getString(
224                 com.android.settings.R.string.zen_mode_settings_dnd_automatic_rule,
225                 TEST_RULE_NAME + "2"));
226     }
227 
228     @Test
multipleAutomaticRules_setFooterTitle()229     public void multipleAutomaticRules_setFooterTitle() {
230         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
231 
232         // automatic rule that ends after manual rule ends
233         ZenRule rule1 = injectNewAutomaticRule(TEST_RULE_NAME + "1", true, false);
234         when(mConfigWrapper.parseAutomaticRuleEndTime(rule1.conditionId)).thenReturn(2000L);
235 
236         ZenRule rule2 = injectNewAutomaticRule(TEST_RULE_NAME + "2", true, false);
237         when(mConfigWrapper.parseAutomaticRuleEndTime(rule2.conditionId)).thenReturn(8000L);
238 
239         ZenRule rule3 = injectNewAutomaticRule(TEST_RULE_NAME + "3", false, false);
240         when(mConfigWrapper.parseAutomaticRuleEndTime(rule3.conditionId)).thenReturn(12000L);
241 
242         mController.updateState(mockPref);
243 
244         // active automatic rule with the latest end time will display
245         verify(mockPref).setTitle(mContext.getString(
246                 com.android.settings.R.string.zen_mode_settings_dnd_automatic_rule,
247                 TEST_RULE_NAME + "2"));
248     }
249 
250     // manual rule that has no end condition (forever)
injectManualRuleWithIndefiniteEnd()251     private void injectManualRuleWithIndefiniteEnd() {
252         ZenRule injectedManualRule = new ZenRule();
253         injectedManualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
254         injectedManualRule.conditionId = null;
255         injectedManualRule.enabler = null;
256         ReflectionHelpers.setField(mZenModeConfig, MANUAL_RULE_FIELD, injectedManualRule);
257     }
258 
259     // manual rule triggered by an app
injectManualRuleFromApp()260     private void injectManualRuleFromApp() {
261         ZenRule injectedManualRule = new ZenRule();
262         injectedManualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
263         injectedManualRule.enabler = TEST_APP_NAME;
264         when(mConfigWrapper.getOwnerCaption(injectedManualRule.enabler)).thenReturn(TEST_APP_NAME);
265         ReflectionHelpers.setField(mZenModeConfig, MANUAL_RULE_FIELD, injectedManualRule);
266     }
267 
268     // manual rule that ends in specified time
injectManualRuleWithTimeCountdown(long time, String timePlaceholder)269     private void injectManualRuleWithTimeCountdown(long time, String timePlaceholder) {
270         ZenRule injectedManualRule = new ZenRule();
271         injectedManualRule.zenMode = ZEN_MODE_IMPORTANT_INTERRUPTIONS;
272         injectedManualRule.enabler = null;
273         injectedManualRule.conditionId = mock(Uri.class);
274         when(mConfigWrapper.parseManualRuleTime(injectedManualRule.conditionId)).thenReturn(time);
275         when(mConfigWrapper.getFormattedTime(time, mContext.getUserId()))
276             .thenReturn(timePlaceholder);
277         ReflectionHelpers.setField(mZenModeConfig, MANUAL_RULE_FIELD, injectedManualRule);
278     }
279 
280     // manual rule that ends in time
injectNewAutomaticRule(String nameAndId, boolean isActive, boolean isApp)281     private ZenRule injectNewAutomaticRule(String nameAndId, boolean isActive, boolean isApp) {
282         ZenRule injectedRule = spy(new ZenRule());
283         injectedRule.zenMode = ZEN_MODE_NO_INTERRUPTIONS;
284         injectedRule.component = mock(ComponentName.class);
285         injectedRule.name = nameAndId;
286         injectedRule.conditionId = new Uri.Builder().authority(nameAndId).build(); // unique uri
287         when(injectedRule.isAutomaticActive()).thenReturn(isActive);
288         when(mConfigWrapper.isTimeRule(injectedRule.conditionId)).thenReturn(!isApp);
289         if (isApp) {
290             when(injectedRule.component.getPackageName()).thenReturn(TEST_APP_NAME);
291         }
292         mInjectedAutomaticRules.put(nameAndId, injectedRule);
293 
294         return injectedRule;
295     }
296 }
297