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 55 public void onResume() { 56 super.onResume(); 57 } 58 59 @Override 60 protected int getPreferenceScreenResId() { 61 return R.xml.zen_mode_settings; 62 } 63 64 @Override 65 public int getMetricsCategory() { 66 return MetricsEvent.NOTIFICATION_ZEN_MODE; 67 } 68 69 @Override 70 protected List<AbstractPreferenceController> createPreferenceControllers(Context context) { 71 return buildPreferenceControllers(context, getLifecycle(), getFragmentManager()); 72 } 73 74 @Override 75 public int getHelpResource() { 76 return R.string.help_uri_interruptions; 77 } 78 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 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 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 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 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 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 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 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 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 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 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