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