Home | History | Annotate | Download | only in notification
      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
     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
    102     public void totalSilence_footerIsAvailable() {
    103         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_NO_INTERRUPTIONS);
    104         assertTrue(mController.isAvailable());
    105     }
    106 
    107     @Test
    108     public void alarmsOnly_footerIsAvailable() {
    109         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_ALARMS);
    110         assertTrue(mController.isAvailable());
    111     }
    112 
    113     @Test
    114     public void priorityOnly_footerIsAvailable() {
    115         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
    116         assertTrue(mController.isAvailable());
    117     }
    118 
    119     @Test
    120     public void zenModeOff_footerIsNotAvailable() {
    121         Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_OFF);
    122         assertFalse(mController.isAvailable());
    123     }
    124 
    125     @Test
    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
    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
    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
    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
    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
    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
    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
    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)
    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
    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
    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
    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