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