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 
22 import androidx.annotation.VisibleForTesting;
23 import androidx.fragment.app.Fragment;
24 import androidx.preference.Preference;
25 import androidx.preference.PreferenceCategory;
26 import androidx.preference.PreferenceScreen;
27 
28 import com.android.settingslib.core.lifecycle.Lifecycle;
29 
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.Objects;
33 
34 public class ZenModeAutomaticRulesPreferenceController extends
35         AbstractZenModeAutomaticRulePreferenceController {
36 
37     protected static final String KEY = "zen_mode_automatic_rules";
38 
39     Map.Entry<String, AutomaticZenRule>[] mSortedRules;
40 
ZenModeAutomaticRulesPreferenceController(Context context, Fragment parent, Lifecycle lifecycle, ZenModeBackend backend)41     public ZenModeAutomaticRulesPreferenceController(Context context, Fragment parent, Lifecycle
42             lifecycle, ZenModeBackend backend) {
43         super(context, KEY, parent, lifecycle);
44         mBackend = backend;
45     }
46 
47     @Override
getPreferenceKey()48     public String getPreferenceKey() {
49         return KEY;
50     }
51 
52     @Override
isAvailable()53     public boolean isAvailable() {
54         return true;
55     }
56 
57     @Override
displayPreference(PreferenceScreen screen)58     public void displayPreference(PreferenceScreen screen) {
59         super.displayPreference(screen);
60         PreferenceCategory preferenceCategory = screen.findPreference(getPreferenceKey());
61         preferenceCategory.setPersistent(false);
62         mSortedRules = getRules();
63         updateRules(preferenceCategory);
64     }
65 
66     @Override
updateState(Preference preference)67     public void updateState(Preference preference) {
68         Map.Entry<String, AutomaticZenRule>[] sortedRules = getRules();
69         boolean rulesChanged = false;
70         if (sortedRules.length != mSortedRules.length) {
71             rulesChanged = true;
72         } else {
73             for (int i = 0; i < mSortedRules.length; i++) {
74                 if (!Objects.equals(mSortedRules[i].getKey(), sortedRules[i].getKey())
75                 || !Objects.equals(mSortedRules[i].getValue(), sortedRules[i].getValue())) {
76                     rulesChanged = true;
77                     break;
78                 }
79             }
80         }
81 
82         if (rulesChanged) {
83             mSortedRules = sortedRules;
84             updateRules((PreferenceCategory) preference);
85         }
86     }
87 
updateRules(PreferenceCategory preferenceCategory)88     private void updateRules(PreferenceCategory preferenceCategory) {
89         Map<String, ZenRulePreference> originalPreferences = new HashMap<>();
90         for (int i = 0; i < preferenceCategory.getPreferenceCount(); i++) {
91             ZenRulePreference pref = (ZenRulePreference) preferenceCategory.getPreference(i);
92             originalPreferences.put(pref.getKey(), pref);
93         }
94 
95         // Loop through each rule, either updating the existing rule or creating the rule's
96         // preference
97         for (int i = 0; i < mSortedRules.length; i++) {
98             String key = mSortedRules[i].getKey();
99 
100             if (originalPreferences.containsKey(key)) {
101                 // existing rule; update its info if it's changed since the last display
102                 AutomaticZenRule rule = mSortedRules[i].getValue();
103                 originalPreferences.get(key).updatePreference(rule);
104             } else {
105                 // new rule; create a new ZenRulePreference & add it to the preference category
106                 ZenRulePreference pref = createZenRulePreference(
107                         mSortedRules[i], preferenceCategory);
108                 preferenceCategory.addPreference(pref);
109             }
110 
111             originalPreferences.remove(key);
112         }
113         // Remove preferences that no longer have a rule
114         for (String key : originalPreferences.keySet()) {
115             preferenceCategory.removePreferenceRecursively(key);
116         }
117     }
118 
119     @VisibleForTesting
createZenRulePreference(Map.Entry<String, AutomaticZenRule> rule, PreferenceCategory preferenceCategory)120     ZenRulePreference createZenRulePreference(Map.Entry<String, AutomaticZenRule> rule,
121             PreferenceCategory preferenceCategory) {
122         return new ZenRulePreference(preferenceCategory.getContext(),
123                 rule, mParent, mMetricsFeatureProvider, mBackend);
124     }
125 }
126