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