• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2015, 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.server.notification;
18 
19 import android.content.ComponentName;
20 import android.net.Uri;
21 import android.service.notification.Condition;
22 import android.service.notification.IConditionListener;
23 import android.service.notification.IConditionProvider;
24 import android.service.notification.ZenModeConfig;
25 import android.service.notification.ZenModeConfig.ZenRule;
26 import android.util.ArrayMap;
27 import android.util.ArraySet;
28 import android.util.Log;
29 
30 import java.io.PrintWriter;
31 import java.util.Objects;
32 
33 public class ZenModeConditions implements ConditionProviders.Callback {
34     private static final String TAG = ZenModeHelper.TAG;
35     private static final boolean DEBUG = ZenModeHelper.DEBUG;
36 
37     private final ZenModeHelper mHelper;
38     private final ConditionProviders mConditionProviders;
39     private final ArrayMap<Uri, ComponentName> mSubscriptions = new ArrayMap<>();
40 
41     private boolean mFirstEvaluation = true;
42 
ZenModeConditions(ZenModeHelper helper, ConditionProviders conditionProviders)43     public ZenModeConditions(ZenModeHelper helper, ConditionProviders conditionProviders) {
44         mHelper = helper;
45         mConditionProviders = conditionProviders;
46         if (mConditionProviders.isSystemProviderEnabled(ZenModeConfig.COUNTDOWN_PATH)) {
47             mConditionProviders.addSystemProvider(new CountdownConditionProvider());
48         }
49         if (mConditionProviders.isSystemProviderEnabled(ZenModeConfig.SCHEDULE_PATH)) {
50             mConditionProviders.addSystemProvider(new ScheduleConditionProvider());
51         }
52         if (mConditionProviders.isSystemProviderEnabled(ZenModeConfig.EVENT_PATH)) {
53             mConditionProviders.addSystemProvider(new EventConditionProvider());
54         }
55         mConditionProviders.setCallback(this);
56     }
57 
dump(PrintWriter pw, String prefix)58     public void dump(PrintWriter pw, String prefix) {
59         pw.print(prefix); pw.print("mSubscriptions="); pw.println(mSubscriptions);
60     }
61 
evaluateConfig(ZenModeConfig config, boolean processSubscriptions)62     public void evaluateConfig(ZenModeConfig config, boolean processSubscriptions) {
63         if (config == null) return;
64         if (config.manualRule != null && config.manualRule.condition != null
65                 && !config.manualRule.isTrueOrUnknown()) {
66             if (DEBUG) Log.d(TAG, "evaluateConfig: clearing manual rule");
67             config.manualRule = null;
68         }
69         final ArraySet<Uri> current = new ArraySet<>();
70         evaluateRule(config.manualRule, current, processSubscriptions);
71         for (ZenRule automaticRule : config.automaticRules.values()) {
72             evaluateRule(automaticRule, current, processSubscriptions);
73             updateSnoozing(automaticRule);
74         }
75         final int N = mSubscriptions.size();
76         for (int i = N - 1; i >= 0; i--) {
77             final Uri id = mSubscriptions.keyAt(i);
78             final ComponentName component = mSubscriptions.valueAt(i);
79             if (processSubscriptions) {
80                 if (!current.contains(id)) {
81                     mConditionProviders.unsubscribeIfNecessary(component, id);
82                     mSubscriptions.removeAt(i);
83                 }
84             }
85         }
86         mFirstEvaluation = false;
87     }
88 
89     @Override
onBootComplete()90     public void onBootComplete() {
91         // noop
92     }
93 
94     @Override
onUserSwitched()95     public void onUserSwitched() {
96         // noop
97     }
98 
99     @Override
onServiceAdded(ComponentName component)100     public void onServiceAdded(ComponentName component) {
101         if (DEBUG) Log.d(TAG, "onServiceAdded " + component);
102         mHelper.setConfigAsync(mHelper.getConfig(), "zmc.onServiceAdded");
103     }
104 
105     @Override
onConditionChanged(Uri id, Condition condition)106     public void onConditionChanged(Uri id, Condition condition) {
107         if (DEBUG) Log.d(TAG, "onConditionChanged " + id + " " + condition);
108         ZenModeConfig config = mHelper.getConfig();
109         if (config == null) return;
110         boolean updated = updateCondition(id, condition, config.manualRule);
111         for (ZenRule automaticRule : config.automaticRules.values()) {
112             updated |= updateCondition(id, condition, automaticRule);
113             updated |= updateSnoozing(automaticRule);
114         }
115         if (updated) {
116             mHelper.setConfigAsync(config, "conditionChanged");
117         }
118     }
119 
evaluateRule(ZenRule rule, ArraySet<Uri> current, boolean processSubscriptions)120     private void evaluateRule(ZenRule rule, ArraySet<Uri> current, boolean processSubscriptions) {
121         if (rule == null || rule.conditionId == null) return;
122         final Uri id = rule.conditionId;
123         boolean isSystemCondition = false;
124         for (SystemConditionProviderService sp : mConditionProviders.getSystemProviders()) {
125             if (sp.isValidConditionId(id)) {
126                 mConditionProviders.ensureRecordExists(sp.getComponent(), id, sp.asInterface());
127                 rule.component = sp.getComponent();
128                 isSystemCondition = true;
129             }
130         }
131         if (!isSystemCondition) {
132             final IConditionProvider cp = mConditionProviders.findConditionProvider(rule.component);
133             if (DEBUG) Log.d(TAG, "Ensure external rule exists: " + (cp != null) + " for " + id);
134             if (cp != null) {
135                 mConditionProviders.ensureRecordExists(rule.component, id, cp);
136             }
137         }
138         if (rule.component == null) {
139             Log.w(TAG, "No component found for automatic rule: " + rule.conditionId);
140             rule.enabled = false;
141             return;
142         }
143         if (current != null) {
144             current.add(id);
145         }
146         if (processSubscriptions) {
147             if (mConditionProviders.subscribeIfNecessary(rule.component, rule.conditionId)) {
148                 mSubscriptions.put(rule.conditionId, rule.component);
149             } else {
150                 rule.condition = null;
151                 if (DEBUG) Log.d(TAG, "zmc failed to subscribe");
152             }
153         }
154         if (rule.condition == null) {
155             rule.condition = mConditionProviders.findCondition(rule.component, rule.conditionId);
156             if (rule.condition != null && DEBUG) Log.d(TAG, "Found existing condition for: "
157                     + rule.conditionId);
158         }
159     }
160 
isAutomaticActive(ComponentName component)161     private boolean isAutomaticActive(ComponentName component) {
162         if (component == null) return false;
163         final ZenModeConfig config = mHelper.getConfig();
164         if (config == null) return false;
165         for (ZenRule rule : config.automaticRules.values()) {
166             if (component.equals(rule.component) && rule.isAutomaticActive()) {
167                 return true;
168             }
169         }
170         return false;
171     }
172 
updateSnoozing(ZenRule rule)173     private boolean updateSnoozing(ZenRule rule) {
174         if (rule != null && rule.snoozing && (mFirstEvaluation || !rule.isTrueOrUnknown())) {
175             rule.snoozing = false;
176             if (DEBUG) Log.d(TAG, "Snoozing reset for " + rule.conditionId);
177             return true;
178         }
179         return false;
180     }
181 
updateCondition(Uri id, Condition condition, ZenRule rule)182     private boolean updateCondition(Uri id, Condition condition, ZenRule rule) {
183         if (id == null || rule == null || rule.conditionId == null) return false;
184         if (!rule.conditionId.equals(id)) return false;
185         if (Objects.equals(condition, rule.condition)) return false;
186         rule.condition = condition;
187         return true;
188     }
189 
190 }
191