• 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.zen;
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_CONVERSATIONS;
22 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_EVENTS;
23 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA;
24 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
25 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS;
26 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
27 import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM;
28 
29 import android.app.Activity;
30 import android.app.Application;
31 import android.app.AutomaticZenRule;
32 import android.app.NotificationManager;
33 import android.app.NotificationManager.Policy;
34 import android.app.settings.SettingsEnums;
35 import android.content.Context;
36 import android.icu.text.MessageFormat;
37 import android.provider.Settings;
38 import android.service.notification.ZenModeConfig;
39 
40 import androidx.annotation.VisibleForTesting;
41 import androidx.fragment.app.Fragment;
42 import androidx.fragment.app.FragmentManager;
43 
44 import com.android.settings.R;
45 import com.android.settingslib.core.AbstractPreferenceController;
46 import com.android.settingslib.core.lifecycle.Lifecycle;
47 
48 import java.util.ArrayList;
49 import java.util.HashMap;
50 import java.util.List;
51 import java.util.Locale;
52 import java.util.Map;
53 import java.util.Map.Entry;
54 import java.util.function.Predicate;
55 
56 public class ZenModeSettings extends ZenModeSettingsBase {
57     @Override
onResume()58     public void onResume() {
59         super.onResume();
60     }
61 
62     @Override
getPreferenceScreenResId()63     protected int getPreferenceScreenResId() {
64         return R.xml.zen_mode_settings;
65     }
66 
67     @Override
getMetricsCategory()68     public int getMetricsCategory() {
69         return SettingsEnums.NOTIFICATION_ZEN_MODE;
70     }
71 
72     @Override
createPreferenceControllers(Context context)73     protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
74         final Activity activity = getActivity();
75         return buildPreferenceControllers(context, getSettingsLifecycle(), getFragmentManager(),
76                 activity != null ? activity.getApplication() : null, this);
77     }
78 
79     @Override
getHelpResource()80     public int getHelpResource() {
81         return R.string.help_uri_interruptions;
82     }
83 
buildPreferenceControllers(Context context, Lifecycle lifecycle, FragmentManager fragmentManager, Application app, Fragment fragment)84     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
85             Lifecycle lifecycle, FragmentManager fragmentManager, Application app,
86             Fragment fragment) {
87         List<AbstractPreferenceController> controllers = new ArrayList<>();
88         controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
89         controllers.add(new ZenModePeoplePreferenceController(context, lifecycle,
90                 "zen_mode_behavior_people"));
91         controllers.add(new ZenModeBypassingAppsPreferenceController(context, app,
92                 fragment, lifecycle));
93         controllers.add(new ZenModeSoundVibrationPreferenceController(context, lifecycle,
94                 "zen_sound_vibration_settings"));
95         controllers.add(new ZenModeAutomationPreferenceController(context));
96         controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
97         controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
98         controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle,
99                 fragmentManager));
100         return controllers;
101     }
102 
103     public static class SummaryBuilder {
104 
105         private Context mContext;
106 
SummaryBuilder(Context context)107         public SummaryBuilder(Context context) {
108             mContext = context;
109         }
110 
111         // these should match NotificationManager.Policy#ALL_PRIORITY_CATEGORIES
112         private static final int[] ALL_PRIORITY_CATEGORIES = {
113                 PRIORITY_CATEGORY_ALARMS,
114                 PRIORITY_CATEGORY_MEDIA,
115                 PRIORITY_CATEGORY_SYSTEM,
116                 PRIORITY_CATEGORY_MESSAGES,
117                 PRIORITY_CATEGORY_CONVERSATIONS,
118                 PRIORITY_CATEGORY_EVENTS,
119                 PRIORITY_CATEGORY_REMINDERS,
120                 PRIORITY_CATEGORY_CALLS,
121                 PRIORITY_CATEGORY_REPEAT_CALLERS,
122         };
123 
getOtherSoundCategoriesSummary(Policy policy)124         String getOtherSoundCategoriesSummary(Policy policy) {
125             List<String> enabledCategories = getEnabledCategories(
126                     policy,
127                     category -> PRIORITY_CATEGORY_ALARMS == category
128                             || PRIORITY_CATEGORY_MEDIA == category
129                             || PRIORITY_CATEGORY_SYSTEM == category
130                             || PRIORITY_CATEGORY_REMINDERS == category
131                             || PRIORITY_CATEGORY_EVENTS == category,
132                     true);
133             int numCategories = enabledCategories.size();
134             MessageFormat msgFormat = new MessageFormat(
135                     mContext.getString(R.string.zen_mode_other_sounds_summary),
136                     Locale.getDefault());
137             Map<String, Object> args = new HashMap<>();
138             args.put("count", numCategories);
139             if (numCategories >= 1) {
140                 args.put("sound_category_1", enabledCategories.get(0));
141                 if (numCategories >= 2) {
142                     args.put("sound_category_2", enabledCategories.get(1));
143                     if (numCategories == 3) {
144                         args.put("sound_category_3", enabledCategories.get(2));
145                     }
146                 }
147             }
148             return msgFormat.format(args);
149         }
150 
getCallsSettingSummary(Policy policy)151         String getCallsSettingSummary(Policy policy) {
152             List<String> enabledCategories = getEnabledCategories(policy,
153                     category -> PRIORITY_CATEGORY_CALLS == category
154                             || PRIORITY_CATEGORY_REPEAT_CALLERS == category, true);
155             int numCategories = enabledCategories.size();
156             if (numCategories == 0) {
157                 return mContext.getString(R.string.zen_mode_none_calls);
158             } else if (numCategories == 1) {
159                 return mContext.getString(R.string.zen_mode_calls_summary_one,
160                         enabledCategories.get(0));
161             } else {
162                 return mContext.getString(R.string.zen_mode_calls_summary_two,
163                         enabledCategories.get(0),
164                         enabledCategories.get(1));
165             }
166         }
167 
getMessagesSettingSummary(Policy policy)168         String getMessagesSettingSummary(Policy policy) {
169             List<String> enabledCategories = getEnabledCategories(policy,
170                     category -> PRIORITY_CATEGORY_MESSAGES == category
171                            || PRIORITY_CATEGORY_CONVERSATIONS == category, true);
172             int numCategories = enabledCategories.size();
173             if (numCategories == 0) {
174                 return mContext.getString(R.string.zen_mode_none_messages);
175             } else if (numCategories == 1) {
176                 return enabledCategories.get(0);
177             } else {
178                 // While this string name seems like a slight misnomer: it's borrowing the analogous
179                 // calls-summary functionality to combine two permissions.
180                 return mContext.getString(R.string.zen_mode_calls_summary_two,
181                         enabledCategories.get(0),
182                         enabledCategories.get(1));
183             }
184         }
185 
getSoundSummary()186         String getSoundSummary() {
187             int zenMode = NotificationManager.from(mContext).getZenMode();
188 
189             if (zenMode != Settings.Global.ZEN_MODE_OFF) {
190                 ZenModeConfig config = NotificationManager.from(mContext).getZenModeConfig();
191                 String description = ZenModeConfig.getDescription(mContext, true, config, false);
192 
193                 if (description == null) {
194                     return mContext.getString(R.string.zen_mode_sound_summary_on);
195                 } else {
196                     return mContext.getString(R.string.zen_mode_sound_summary_on_with_info,
197                             description);
198                 }
199             } else {
200                 MessageFormat msgFormat = new MessageFormat(
201                         mContext.getString(R.string.zen_mode_sound_summary_off),
202                         Locale.getDefault());
203                 Map<String, Object> msgArgs = new HashMap<>();
204                 msgArgs.put("count", getEnabledAutomaticRulesCount());
205                 return msgFormat.format(msgArgs);
206             }
207         }
208 
getBlockedEffectsSummary(Policy policy)209         String getBlockedEffectsSummary(Policy policy) {
210             if (policy.suppressedVisualEffects == 0) {
211                 return mContext.getResources().getString(
212                         R.string.zen_mode_restrict_notifications_summary_muted);
213             } else if (Policy.areAllVisualEffectsSuppressed(policy.suppressedVisualEffects)) {
214                 return mContext.getResources().getString(
215                         R.string.zen_mode_restrict_notifications_summary_hidden);
216             } else {
217                 return mContext.getResources().getString(
218                         R.string.zen_mode_restrict_notifications_summary_custom);
219             }
220         }
221 
getAutomaticRulesSummary()222         String getAutomaticRulesSummary() {
223             MessageFormat msgFormat = new MessageFormat(
224                     mContext.getString(R.string.zen_mode_settings_schedules_summary),
225                     Locale.getDefault());
226             Map<String, Object> msgArgs = new HashMap<>();
227             msgArgs.put("count", getEnabledAutomaticRulesCount());
228             return msgFormat.format(msgArgs);
229         }
230 
231         @VisibleForTesting
getEnabledAutomaticRulesCount()232         int getEnabledAutomaticRulesCount() {
233             int count = 0;
234             final Map<String, AutomaticZenRule> ruleMap =
235                     NotificationManager.from(mContext).getAutomaticZenRules();
236             if (ruleMap != null) {
237                 for (Entry<String, AutomaticZenRule> ruleEntry : ruleMap.entrySet()) {
238                     final AutomaticZenRule rule = ruleEntry.getValue();
239                     if (rule != null && rule.isEnabled()) {
240                         count++;
241                     }
242                 }
243             }
244             return count;
245         }
246 
getEnabledCategories(Policy policy, Predicate<Integer> filteredCategories, boolean capitalizeFirstInList)247         private List<String> getEnabledCategories(Policy policy,
248                 Predicate<Integer> filteredCategories, boolean capitalizeFirstInList) {
249             List<String> enabledCategories = new ArrayList<>();
250             for (int category : ALL_PRIORITY_CATEGORIES) {
251                 boolean isFirst = capitalizeFirstInList && enabledCategories.isEmpty();
252                 if (filteredCategories.test(category) && isCategoryEnabled(policy, category)) {
253                     if (category == Policy.PRIORITY_CATEGORY_REPEAT_CALLERS
254                             && isCategoryEnabled(policy, Policy.PRIORITY_CATEGORY_CALLS)
255                             && policy.priorityCallSenders == Policy.PRIORITY_SENDERS_ANY) {
256                         continue;
257                     }
258 
259                     // For conversations, only the "priority conversations" setting is relevant; any
260                     // other setting is subsumed by the messages-specific messaging.
261                     if (category == Policy.PRIORITY_CATEGORY_CONVERSATIONS
262                             && isCategoryEnabled(policy, Policy.PRIORITY_CATEGORY_CONVERSATIONS)
263                             && policy.priorityConversationSenders
264                                     != Policy.CONVERSATION_SENDERS_IMPORTANT) {
265                         continue;
266                     }
267 
268                     enabledCategories.add(getCategory(category, policy, isFirst));
269                 }
270             }
271             return enabledCategories;
272         }
273 
isCategoryEnabled(Policy policy, int categoryType)274         private boolean isCategoryEnabled(Policy policy, int categoryType) {
275             return (policy.priorityCategories & categoryType) != 0;
276         }
277 
getCategory(int category, Policy policy, boolean isFirst)278         private String getCategory(int category, Policy policy, boolean isFirst) {
279             if (category == PRIORITY_CATEGORY_ALARMS) {
280                 if (isFirst) {
281                     return mContext.getString(R.string.zen_mode_alarms_list_first);
282                 } else {
283                     return mContext.getString(R.string.zen_mode_alarms_list);
284                 }
285             } else if (category == PRIORITY_CATEGORY_MEDIA) {
286                 if (isFirst) {
287                     return mContext.getString(R.string.zen_mode_media_list_first);
288                 } else {
289                     return mContext.getString(R.string.zen_mode_media_list);
290                 }
291             } else if (category == PRIORITY_CATEGORY_SYSTEM) {
292                 if (isFirst) {
293                     return mContext.getString(R.string.zen_mode_system_list_first);
294                 } else {
295                     return mContext.getString(R.string.zen_mode_system_list);
296                 }
297             } else if (category == Policy.PRIORITY_CATEGORY_MESSAGES) {
298                 if (policy.priorityMessageSenders == Policy.PRIORITY_SENDERS_ANY) {
299                     return mContext.getString(R.string.zen_mode_from_anyone);
300                 } else if (policy.priorityMessageSenders == Policy.PRIORITY_SENDERS_CONTACTS) {
301                     return mContext.getString(R.string.zen_mode_from_contacts);
302                 } else {
303                     return mContext.getString(R.string.zen_mode_from_starred);
304                 }
305             } else if (category == Policy.PRIORITY_CATEGORY_CONVERSATIONS
306                     && policy.priorityConversationSenders
307                             == Policy.CONVERSATION_SENDERS_IMPORTANT) {
308                 if (isFirst) {
309                     return mContext.getString(R.string.zen_mode_from_important_conversations);
310                 } else {
311                     return mContext.getString(
312                             R.string.zen_mode_from_important_conversations_second);
313                 }
314             } else if (category == Policy.PRIORITY_CATEGORY_EVENTS) {
315                 if (isFirst) {
316                     return mContext.getString(R.string.zen_mode_events_list_first);
317                 } else {
318                     return mContext.getString(R.string.zen_mode_events_list);
319                 }
320             } else if (category == Policy.PRIORITY_CATEGORY_REMINDERS) {
321                 if (isFirst) {
322                     return mContext.getString(R.string.zen_mode_reminders_list_first);
323                 } else {
324                     return mContext.getString(R.string.zen_mode_reminders_list);
325                 }
326             } else if (category == Policy.PRIORITY_CATEGORY_CALLS) {
327                 if (policy.priorityCallSenders == Policy.PRIORITY_SENDERS_ANY) {
328                     if (isFirst) {
329                         return mContext.getString(R.string.zen_mode_from_anyone);
330                     }
331                     return mContext.getString(R.string.zen_mode_all_callers);
332                 } else if (policy.priorityCallSenders == Policy.PRIORITY_SENDERS_CONTACTS){
333                     if (isFirst) {
334                         return mContext.getString(R.string.zen_mode_from_contacts);
335                     }
336                     return mContext.getString(R.string.zen_mode_contacts_callers);
337                 } else {
338                     if (isFirst) {
339                         return mContext.getString(R.string.zen_mode_from_starred);
340                     }
341                     return mContext.getString(R.string.zen_mode_starred_callers);
342                 }
343             } else if (category == Policy.PRIORITY_CATEGORY_REPEAT_CALLERS) {
344                 if (isFirst) {
345                     return mContext.getString(R.string.zen_mode_repeat_callers);
346                 } else {
347                     return mContext.getString(R.string.zen_mode_repeat_callers_list);
348                 }
349             }
350 
351             return "";
352         }
353     }
354 }
355