1 /* 2 * Copyright (C) 2017 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 android.app.AutomaticZenRule; 20 import android.content.Context; 21 import android.util.ArrayMap; 22 23 import androidx.annotation.VisibleForTesting; 24 import androidx.fragment.app.Fragment; 25 import androidx.preference.Preference; 26 import androidx.preference.PreferenceCategory; 27 import androidx.preference.PreferenceScreen; 28 29 import com.android.settingslib.core.lifecycle.Lifecycle; 30 31 import java.util.Map; 32 33 public class ZenModeAutomaticRulesPreferenceController extends 34 AbstractZenModeAutomaticRulePreferenceController { 35 36 protected static final String KEY = "zen_mode_automatic_rules"; 37 38 @VisibleForTesting 39 protected PreferenceCategory mPreferenceCategory; 40 41 // Map of rule key -> preference so that we can update each preference as needed 42 @VisibleForTesting 43 protected Map<String, ZenRulePreference> mZenRulePreferences = new ArrayMap<>(); 44 ZenModeAutomaticRulesPreferenceController(Context context, Fragment parent, Lifecycle lifecycle)45 public ZenModeAutomaticRulesPreferenceController(Context context, Fragment parent, Lifecycle 46 lifecycle) { 47 super(context, KEY, parent, lifecycle); 48 } 49 50 @Override getPreferenceKey()51 public String getPreferenceKey() { 52 return KEY; 53 } 54 55 @Override isAvailable()56 public boolean isAvailable() { 57 return true; 58 } 59 60 @Override displayPreference(PreferenceScreen screen)61 public void displayPreference(PreferenceScreen screen) { 62 super.displayPreference(screen); 63 mPreferenceCategory = screen.findPreference(getPreferenceKey()); 64 mPreferenceCategory.setPersistent(false); 65 66 // if mPreferenceCategory was un-set, make sure to clear out mZenRulePreferences too, just 67 // in case 68 if (mPreferenceCategory.getPreferenceCount() == 0) { 69 mZenRulePreferences.clear(); 70 } 71 } 72 73 @Override updateState(Preference preference)74 public void updateState(Preference preference) { 75 super.updateState(preference); 76 Map.Entry<String, AutomaticZenRule>[] sortedRules = getRules(); 77 78 // refresh the whole preference category list if the total number of rules has changed, or 79 // if any individual rules have changed, so we can rebuild the list & keep things in sync 80 boolean refreshPrefs = false; 81 if (mPreferenceCategory.getPreferenceCount() != sortedRules.length) { 82 refreshPrefs = true; 83 } else { 84 // check whether any rules in sortedRules are not in mZenRulePreferences; that should 85 // be enough to see whether something has changed 86 for (int i = 0; i < sortedRules.length; i++) { 87 if (!mZenRulePreferences.containsKey(sortedRules[i].getKey())) { 88 refreshPrefs = true; 89 break; 90 } 91 } 92 } 93 94 // if we need to refresh the whole list, clear the preference category and also start a 95 // new map of preferences according to the preference category contents 96 // we need to not update the existing one yet, as we'll need to know what preferences 97 // previously existed in order to update and re-attach them to the preference category 98 Map<String, ZenRulePreference> newPrefs = new ArrayMap<>(); 99 if (refreshPrefs) { 100 mPreferenceCategory.removeAll(); 101 } 102 103 // Loop through each rule, either updating the existing rule or creating the rule's 104 // preference if needed (and, in the case where we need to rebuild the preference category 105 // list, do so as well) 106 for (int i = 0; i < sortedRules.length; i++) { 107 String key = sortedRules[i].getKey(); 108 if (mZenRulePreferences.containsKey(key)) { 109 // existing rule; update its info if it's changed since the last display 110 AutomaticZenRule rule = sortedRules[i].getValue(); 111 ZenRulePreference pref = mZenRulePreferences.get(key); 112 pref.updatePreference(rule); 113 114 // only add to preference category if the overall set of rules has changed so this 115 // needs to be rearranged 116 if (refreshPrefs) { 117 mPreferenceCategory.addPreference(pref); 118 newPrefs.put(key, pref); 119 } 120 } else { 121 // new rule; create a new ZenRulePreference & add it to the preference category 122 // and the map so we'll know about it later 123 ZenRulePreference pref = createZenRulePreference(sortedRules[i]); 124 mPreferenceCategory.addPreference(pref); 125 newPrefs.put(key, pref); 126 } 127 } 128 129 // If anything was new, then make sure we overwrite mZenRulePreferences with our new data 130 if (refreshPrefs) { 131 mZenRulePreferences = newPrefs; 132 } 133 } 134 135 @VisibleForTesting createZenRulePreference(Map.Entry<String, AutomaticZenRule> rule)136 ZenRulePreference createZenRulePreference(Map.Entry<String, AutomaticZenRule> rule) { 137 return new ZenRulePreference(mPreferenceCategory.getContext(), 138 rule, mParent, mMetricsFeatureProvider); 139 } 140 } 141