• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.app.NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS;
20 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
21 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_EVENTS;
22 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA;
23 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
24 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS;
25 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
26 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM;
27 
28 import android.app.AutomaticZenRule;
29 import android.app.FragmentManager;
30 import android.app.NotificationManager;
31 import android.app.NotificationManager.Policy;
32 import android.content.Context;
33 import android.icu.text.ListFormatter;
34 import android.provider.SearchIndexableResource;
35 import android.provider.Settings;
36 import android.service.notification.ZenModeConfig;
37 import android.support.annotation.VisibleForTesting;
38 
39 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
40 import com.android.settings.R;
41 import com.android.settings.search.BaseSearchIndexProvider;
42 import com.android.settings.search.Indexable;
43 import com.android.settingslib.core.AbstractPreferenceController;
44 import com.android.settingslib.core.lifecycle.Lifecycle;
45 
46 import java.util.ArrayList;
47 import java.util.Arrays;
48 import java.util.List;
49 import java.util.Map;
50 import java.util.Map.Entry;
51 import java.util.function.Predicate;
52 
53 public class ZenModeSettings extends ZenModeSettingsBase {
54     @Override
onResume()55     public void onResume() {
56         super.onResume();
57     }
58 
59     @Override
getPreferenceScreenResId()60     protected int getPreferenceScreenResId() {
61         return R.xml.zen_mode_settings;
62     }
63 
64     @Override
getMetricsCategory()65     public int getMetricsCategory() {
66         return MetricsEvent.NOTIFICATION_ZEN_MODE;
67     }
68 
69     @Override
createPreferenceControllers(Context context)70     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
71         return buildPreferenceControllers(context, getLifecycle(), getFragmentManager());
72     }
73 
74     @Override
getHelpResource()75     public int getHelpResource() {
76         return R.string.help_uri_interruptions;
77     }
78 
buildPreferenceControllers(Context context, Lifecycle lifecycle, FragmentManager fragmentManager)79     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
80             Lifecycle lifecycle, FragmentManager fragmentManager) {
81         List<AbstractPreferenceController> controllers = new ArrayList<>();
82         controllers.add(new ZenModeBehaviorMsgEventReminderPreferenceController(context, lifecycle));
83         controllers.add(new ZenModeBehaviorSoundPreferenceController(context, lifecycle));
84         controllers.add(new ZenModeBehaviorCallsPreferenceController(context, lifecycle));
85         controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
86         controllers.add(new ZenModeDurationPreferenceController(context, lifecycle,
87                 fragmentManager));
88         controllers.add(new ZenModeAutomationPreferenceController(context));
89         controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
90         controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle));
91         return controllers;
92     }
93 
94     public static class SummaryBuilder {
95 
96         private Context mContext;
97 
SummaryBuilder(Context context)98         public SummaryBuilder(Context context) {
99             mContext = context;
100         }
101 
102         // these should match NotificationManager.Policy#ALL_PRIORITY_CATEGORIES
103         private static final int[] ALL_PRIORITY_CATEGORIES = {
104                 PRIORITY_CATEGORY_ALARMS,
105                 PRIORITY_CATEGORY_MEDIA,
106                 PRIORITY_CATEGORY_SYSTEM,
107                 PRIORITY_CATEGORY_MESSAGES,
108                 PRIORITY_CATEGORY_EVENTS,
109                 PRIORITY_CATEGORY_REMINDERS,
110                 PRIORITY_CATEGORY_CALLS,
111                 PRIORITY_CATEGORY_REPEAT_CALLERS,
112         };
113 
getSoundSettingSummary(Policy policy)114         String getSoundSettingSummary(Policy policy) {
115             List<String> enabledCategories = getEnabledCategories(policy,
116                     category -> PRIORITY_CATEGORY_ALARMS == category
117                             || PRIORITY_CATEGORY_MEDIA == category
118                             || PRIORITY_CATEGORY_SYSTEM == category);
119             int numCategories = enabledCategories.size();
120             if (numCategories == 0) {
121                 return mContext.getString(R.string.zen_sound_all_muted);
122             } else if (numCategories == 1) {
123                 return mContext.getString(R.string.zen_sound_one_allowed,
124                         enabledCategories.get(0).toLowerCase());
125             } else if (numCategories == 2) {
126                 return mContext.getString(R.string.zen_sound_two_allowed,
127                         enabledCategories.get(0).toLowerCase(),
128                         enabledCategories.get(1).toLowerCase());
129             } else if (numCategories == 3) {
130                 return mContext.getString(R.string.zen_sound_three_allowed,
131                         enabledCategories.get(0).toLowerCase(),
132                         enabledCategories.get(1).toLowerCase(),
133                         enabledCategories.get(2).toLowerCase());
134             } else {
135                 return mContext.getString(R.string.zen_sound_none_muted);
136             }
137         }
138 
getCallsSettingSummary(Policy policy)139         String getCallsSettingSummary(Policy policy) {
140             List<String> enabledCategories = getEnabledCategories(policy,
141                     category -> PRIORITY_CATEGORY_CALLS == category
142                             || PRIORITY_CATEGORY_REPEAT_CALLERS == category);
143             int numCategories = enabledCategories.size();
144             if (numCategories == 0) {
145                 return mContext.getString(R.string.zen_mode_no_exceptions);
146             } else if (numCategories == 1) {
147                 return mContext.getString(R.string.zen_mode_calls_summary_one,
148                         enabledCategories.get(0).toLowerCase());
149             } else {
150                 return mContext.getString(R.string.zen_mode_calls_summary_two,
151                         enabledCategories.get(0).toLowerCase(),
152                         enabledCategories.get(1).toLowerCase());
153             }
154         }
155 
getMsgEventReminderSettingSummary(Policy policy)156         String getMsgEventReminderSettingSummary(Policy policy) {
157             List<String> enabledCategories = getEnabledCategories(policy,
158                     category -> PRIORITY_CATEGORY_EVENTS == category
159                             || PRIORITY_CATEGORY_REMINDERS == category
160                             || PRIORITY_CATEGORY_MESSAGES == category);
161             int numCategories = enabledCategories.size();
162             if (numCategories == 0) {
163                 return mContext.getString(R.string.zen_mode_no_exceptions);
164             } else if (numCategories == 1) {
165                 return enabledCategories.get(0);
166             } else if (numCategories == 2) {
167                 return mContext.getString(R.string.join_two_items, enabledCategories.get(0),
168                         enabledCategories.get(1).toLowerCase());
169             } else if (numCategories == 3){
170                 final List<String> summaries = new ArrayList<>();
171                 summaries.add(enabledCategories.get(0));
172                 summaries.add(enabledCategories.get(1).toLowerCase());
173                 summaries.add(enabledCategories.get(2).toLowerCase());
174 
175                 return ListFormatter.getInstance().format(summaries);
176             } else {
177                 final List<String> summaries = new ArrayList<>();
178                 summaries.add(enabledCategories.get(0));
179                 summaries.add(enabledCategories.get(1).toLowerCase());
180                 summaries.add(enabledCategories.get(2).toLowerCase());
181                 summaries.add(mContext.getString(R.string.zen_mode_other_options));
182 
183                 return ListFormatter.getInstance().format(summaries);
184             }
185         }
186 
getSoundSummary()187         String getSoundSummary() {
188             int zenMode = NotificationManager.from(mContext).getZenMode();
189 
190             if (zenMode != Settings.Global.ZEN_MODE_OFF) {
191                 ZenModeConfig config = NotificationManager.from(mContext).getZenModeConfig();
192                 String description = ZenModeConfig.getDescription(mContext, true, config, false);
193 
194                 if (description == null) {
195                     return mContext.getString(R.string.zen_mode_sound_summary_on);
196                 } else {
197                     return mContext.getString(R.string.zen_mode_sound_summary_on_with_info,
198                             description);
199                 }
200             } else {
201                 final int count = getEnabledAutomaticRulesCount();
202                 if (count > 0) {
203                     return mContext.getString(R.string.zen_mode_sound_summary_off_with_info,
204                             mContext.getResources().getQuantityString(
205                                     R.plurals.zen_mode_sound_summary_summary_off_info,
206                                     count, count));
207                 }
208 
209                 return mContext.getString(R.string.zen_mode_sound_summary_off);
210             }
211         }
212 
getBlockedEffectsSummary(Policy policy)213         String getBlockedEffectsSummary(Policy policy) {
214             if (policy.suppressedVisualEffects == 0) {
215                 return mContext.getResources().getString(
216                         R.string.zen_mode_restrict_notifications_summary_muted);
217             } else if (Policy.areAllVisualEffectsSuppressed(policy.suppressedVisualEffects)) {
218                 return mContext.getResources().getString(
219                         R.string.zen_mode_restrict_notifications_summary_hidden);
220             } else {
221                 return mContext.getResources().getString(
222                         R.string.zen_mode_restrict_notifications_summary_custom);
223             }
224         }
225 
getAutomaticRulesSummary()226         String getAutomaticRulesSummary() {
227             final int count = getEnabledAutomaticRulesCount();
228             return count == 0 ? mContext.getString(R.string.zen_mode_settings_summary_off)
229                 : mContext.getResources().getQuantityString(
230                     R.plurals.zen_mode_settings_summary_on, count, count);
231         }
232 
233         @VisibleForTesting
getEnabledAutomaticRulesCount()234         int getEnabledAutomaticRulesCount() {
235             int count = 0;
236             final Map<String, AutomaticZenRule> ruleMap =
237                 NotificationManager.from(mContext).getAutomaticZenRules();
238             if (ruleMap != null) {
239                 for (Entry<String, AutomaticZenRule> ruleEntry : ruleMap.entrySet()) {
240                     final AutomaticZenRule rule = ruleEntry.getValue();
241                     if (rule != null && rule.isEnabled()) {
242                         count++;
243                     }
244                 }
245             }
246             return count;
247         }
248 
getEnabledCategories(Policy policy, Predicate<Integer> filteredCategories)249         private List<String> getEnabledCategories(Policy policy,
250                 Predicate<Integer> filteredCategories) {
251             List<String> enabledCategories = new ArrayList<>();
252             for (int category : ALL_PRIORITY_CATEGORIES) {
253                 if (filteredCategories.test(category) && isCategoryEnabled(policy, category)) {
254                     if (category == PRIORITY_CATEGORY_ALARMS) {
255                         enabledCategories.add(mContext.getString(R.string.zen_mode_alarms));
256                     } else if (category == PRIORITY_CATEGORY_MEDIA) {
257                         enabledCategories.add(mContext.getString(
258                                 R.string.zen_mode_media));
259                     } else if (category == PRIORITY_CATEGORY_SYSTEM) {
260                         enabledCategories.add(mContext.getString(
261                                 R.string.zen_mode_system));
262                     } else if (category == Policy.PRIORITY_CATEGORY_MESSAGES) {
263                         if (policy.priorityMessageSenders == Policy.PRIORITY_SENDERS_ANY) {
264                             enabledCategories.add(mContext.getString(
265                                     R.string.zen_mode_all_messages));
266                         } else {
267                             enabledCategories.add(mContext.getString(
268                                     R.string.zen_mode_selected_messages));
269                         }
270                     } else if (category == Policy.PRIORITY_CATEGORY_EVENTS) {
271                         enabledCategories.add(mContext.getString(R.string.zen_mode_events));
272                     } else if (category == Policy.PRIORITY_CATEGORY_REMINDERS) {
273                         enabledCategories.add(mContext.getString(R.string.zen_mode_reminders));
274                     } else if (category == Policy.PRIORITY_CATEGORY_CALLS) {
275                         if (policy.priorityCallSenders == Policy.PRIORITY_SENDERS_ANY) {
276                             enabledCategories.add(mContext.getString(
277                                     R.string.zen_mode_all_callers));
278                         } else if (policy.priorityCallSenders == Policy.PRIORITY_SENDERS_CONTACTS){
279                             enabledCategories.add(mContext.getString(
280                                     R.string.zen_mode_contacts_callers));
281                         } else {
282                             enabledCategories.add(mContext.getString(
283                                     R.string.zen_mode_starred_callers));
284                         }
285                     } else if (category == Policy.PRIORITY_CATEGORY_REPEAT_CALLERS) {
286                         if (!enabledCategories.contains(mContext.getString(
287                                 R.string.zen_mode_all_callers))) {
288                             enabledCategories.add(mContext.getString(
289                                     R.string.zen_mode_repeat_callers));
290                         }
291                     }
292                 }
293             }
294             return enabledCategories;
295         }
296 
isCategoryEnabled(Policy policy, int categoryType)297         private boolean isCategoryEnabled(Policy policy, int categoryType) {
298             return (policy.priorityCategories & categoryType) != 0;
299         }
300     }
301 
302     /**
303      * For Search.
304      */
305     public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
306             new BaseSearchIndexProvider() {
307 
308                 @Override
309                 public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
310                         boolean enabled) {
311                     final SearchIndexableResource sir = new SearchIndexableResource(context);
312                     sir.xmlResId = R.xml.zen_mode_settings;
313                     return Arrays.asList(sir);
314                 }
315 
316                 @Override
317                 public List<String> getNonIndexableKeys(Context context) {
318                     List<String> keys = super.getNonIndexableKeys(context);
319                     keys.add(ZenModeDurationPreferenceController.KEY);
320                     keys.add(ZenModeButtonPreferenceController.KEY);
321                     return keys;
322                 }
323 
324                 @Override
325                 public List<AbstractPreferenceController> createPreferenceControllers(Context
326                         context) {
327                     return buildPreferenceControllers(context, null, null);
328                 }
329             };
330 }
331