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.server.notification;
18 
19 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED;
20 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
21 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
22 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
23 import static android.service.notification.DNDModeProto.ROOT_CONFIG;
24 import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
25 
26 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
27 
28 import android.app.AppOpsManager;
29 import android.app.AutomaticZenRule;
30 import android.app.Notification;
31 import android.app.NotificationManager;
32 import android.app.NotificationManager.Policy;
33 import android.app.PendingIntent;
34 import android.content.ComponentName;
35 import android.content.ContentResolver;
36 import android.content.Context;
37 import android.content.Intent;
38 import android.content.pm.ActivityInfo;
39 import android.content.pm.PackageItemInfo;
40 import android.content.pm.PackageManager;
41 import android.content.pm.ResolveInfo;
42 import android.content.pm.ServiceInfo;
43 import android.content.res.Resources;
44 import android.content.res.XmlResourceParser;
45 import android.database.ContentObserver;
46 import android.graphics.drawable.Icon;
47 import android.media.AudioAttributes;
48 import android.media.AudioManager;
49 import android.media.AudioManagerInternal;
50 import android.media.AudioSystem;
51 import android.media.VolumePolicy;
52 import android.net.Uri;
53 import android.os.Binder;
54 import android.os.Bundle;
55 import android.os.Handler;
56 import android.os.Looper;
57 import android.os.Message;
58 import android.os.Process;
59 import android.os.SystemClock;
60 import android.os.UserHandle;
61 import android.provider.Settings;
62 import android.provider.Settings.Global;
63 import android.service.notification.Condition;
64 import android.service.notification.ConditionProviderService;
65 import android.service.notification.ZenModeConfig;
66 import android.service.notification.ZenModeConfig.ZenRule;
67 import android.service.notification.ZenModeProto;
68 import android.service.notification.ZenPolicy;
69 import android.util.AndroidRuntimeException;
70 import android.util.ArrayMap;
71 import android.util.Log;
72 import android.util.Slog;
73 import android.util.SparseArray;
74 import android.util.StatsEvent;
75 import android.util.TypedXmlPullParser;
76 import android.util.TypedXmlSerializer;
77 import android.util.proto.ProtoOutputStream;
78 
79 import com.android.internal.R;
80 import com.android.internal.annotations.VisibleForTesting;
81 import com.android.internal.logging.MetricsLogger;
82 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
83 import com.android.internal.notification.SystemNotificationChannels;
84 import com.android.internal.util.XmlUtils;
85 import com.android.server.LocalServices;
86 
87 import libcore.io.IoUtils;
88 
89 import org.xmlpull.v1.XmlPullParser;
90 import org.xmlpull.v1.XmlPullParserException;
91 
92 import java.io.IOException;
93 import java.io.PrintWriter;
94 import java.util.ArrayList;
95 import java.util.List;
96 import java.util.Objects;
97 
98 /**
99  * NotificationManagerService helper for functionality related to zen mode.
100  */
101 public class ZenModeHelper {
102     static final String TAG = "ZenModeHelper";
103     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
104 
105     // The amount of time rules instances can exist without their owning app being installed.
106     private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
107     static final int RULE_LIMIT_PER_PACKAGE = 100;
108 
109     // pkg|userId => uid
110     protected final ArrayMap<String, Integer> mRulesUidCache = new ArrayMap<>();
111 
112     private final Context mContext;
113     private final H mHandler;
114     private final SettingsObserver mSettingsObserver;
115     private final AppOpsManager mAppOps;
116     @VisibleForTesting protected final NotificationManager mNotificationManager;
117     private final SysUiStatsEvent.BuilderFactory mStatsEventBuilderFactory;
118     @VisibleForTesting protected ZenModeConfig mDefaultConfig;
119     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
120     private final ZenModeFiltering mFiltering;
121     protected final RingerModeDelegate mRingerModeDelegate = new
122             RingerModeDelegate();
123     @VisibleForTesting protected final ZenModeConditions mConditions;
124     @VisibleForTesting final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
125     private final Metrics mMetrics = new Metrics();
126     private final ConditionProviders.Config mServiceConfig;
127 
128     @VisibleForTesting protected int mZenMode;
129     @VisibleForTesting protected NotificationManager.Policy mConsolidatedPolicy;
130     private int mUser = UserHandle.USER_SYSTEM;
131     @VisibleForTesting protected ZenModeConfig mConfig;
132     @VisibleForTesting protected AudioManagerInternal mAudioManager;
133     protected PackageManager mPm;
134     private long mSuppressedEffects;
135 
136     public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
137     public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
138     public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
139             | SUPPRESSED_EFFECT_NOTIFICATIONS;
140 
141     @VisibleForTesting protected boolean mIsBootComplete;
142 
143     private String[] mPriorityOnlyDndExemptPackages;
144 
ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders, SysUiStatsEvent.BuilderFactory statsEventBuilderFactory)145     public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders,
146             SysUiStatsEvent.BuilderFactory statsEventBuilderFactory) {
147         mContext = context;
148         mHandler = new H(looper);
149         addCallback(mMetrics);
150         mAppOps = context.getSystemService(AppOpsManager.class);
151         mNotificationManager = context.getSystemService(NotificationManager.class);
152 
153         mDefaultConfig = readDefaultConfig(mContext.getResources());
154         updateDefaultAutomaticRuleNames();
155         mConfig = mDefaultConfig.copy();
156         mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
157         mConsolidatedPolicy = mConfig.toNotificationPolicy();
158 
159         mSettingsObserver = new SettingsObserver(mHandler);
160         mSettingsObserver.observe();
161         mFiltering = new ZenModeFiltering(mContext);
162         mConditions = new ZenModeConditions(this, conditionProviders);
163         mServiceConfig = conditionProviders.getConfig();
164         mStatsEventBuilderFactory = statsEventBuilderFactory;
165     }
166 
getLooper()167     public Looper getLooper() {
168         return mHandler.getLooper();
169     }
170 
171     @Override
toString()172     public String toString() {
173         return TAG;
174     }
175 
matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity)176     public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
177             ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
178         synchronized (mConfig) {
179             return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConsolidatedPolicy,
180                     userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity);
181         }
182     }
183 
isCall(NotificationRecord record)184     public boolean isCall(NotificationRecord record) {
185         return mFiltering.isCall(record);
186     }
187 
recordCaller(NotificationRecord record)188     public void recordCaller(NotificationRecord record) {
189         mFiltering.recordCall(record);
190     }
191 
shouldIntercept(NotificationRecord record)192     public boolean shouldIntercept(NotificationRecord record) {
193         synchronized (mConfig) {
194             return mFiltering.shouldIntercept(mZenMode, mConsolidatedPolicy, record);
195         }
196     }
197 
addCallback(Callback callback)198     public void addCallback(Callback callback) {
199         mCallbacks.add(callback);
200     }
201 
removeCallback(Callback callback)202     public void removeCallback(Callback callback) {
203         mCallbacks.remove(callback);
204     }
205 
initZenMode()206     public void initZenMode() {
207         if (DEBUG) Log.d(TAG, "initZenMode");
208         evaluateZenMode("init", true /*setRingerMode*/);
209     }
210 
onSystemReady()211     public void onSystemReady() {
212         if (DEBUG) Log.d(TAG, "onSystemReady");
213         mAudioManager = LocalServices.getService(AudioManagerInternal.class);
214         if (mAudioManager != null) {
215             mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
216         }
217         mPm = mContext.getPackageManager();
218         mHandler.postMetricsTimer();
219         cleanUpZenRules();
220         evaluateZenMode("onSystemReady", true);
221         mIsBootComplete = true;
222         showZenUpgradeNotification(mZenMode);
223     }
224 
onUserSwitched(int user)225     public void onUserSwitched(int user) {
226         loadConfigForUser(user, "onUserSwitched");
227     }
228 
onUserRemoved(int user)229     public void onUserRemoved(int user) {
230         if (user < UserHandle.USER_SYSTEM) return;
231         if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
232         mConfigs.remove(user);
233     }
234 
onUserUnlocked(int user)235     public void onUserUnlocked(int user) {
236         loadConfigForUser(user, "onUserUnlocked");
237     }
238 
setPriorityOnlyDndExemptPackages(String[] packages)239     void setPriorityOnlyDndExemptPackages(String[] packages) {
240         mPriorityOnlyDndExemptPackages = packages;
241     }
242 
loadConfigForUser(int user, String reason)243     private void loadConfigForUser(int user, String reason) {
244         if (mUser == user || user < UserHandle.USER_SYSTEM) return;
245         mUser = user;
246         if (DEBUG) Log.d(TAG, reason + " u=" + user);
247         ZenModeConfig config = mConfigs.get(user);
248         if (config == null) {
249             if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user);
250             config = mDefaultConfig.copy();
251             config.user = user;
252         }
253         synchronized (mConfig) {
254             setConfigLocked(config, null, reason);
255         }
256         cleanUpZenRules();
257     }
258 
getZenModeListenerInterruptionFilter()259     public int getZenModeListenerInterruptionFilter() {
260         return NotificationManager.zenModeToInterruptionFilter(mZenMode);
261     }
262 
requestFromListener(ComponentName name, int filter)263     public void requestFromListener(ComponentName name, int filter) {
264         final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
265         if (newZen != -1) {
266             setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
267                     "listener:" + (name != null ? name.flattenToShortString() : null));
268         }
269     }
270 
setSuppressedEffects(long suppressedEffects)271     public void setSuppressedEffects(long suppressedEffects) {
272         if (mSuppressedEffects == suppressedEffects) return;
273         mSuppressedEffects = suppressedEffects;
274         applyRestrictions();
275     }
276 
getSuppressedEffects()277     public long getSuppressedEffects() {
278         return mSuppressedEffects;
279     }
280 
getZenMode()281     public int getZenMode() {
282         return mZenMode;
283     }
284 
getZenRules()285     public List<ZenRule> getZenRules() {
286         List<ZenRule> rules = new ArrayList<>();
287         synchronized (mConfig) {
288             if (mConfig == null) return rules;
289             for (ZenRule rule : mConfig.automaticRules.values()) {
290                 if (canManageAutomaticZenRule(rule)) {
291                     rules.add(rule);
292                 }
293             }
294         }
295         return rules;
296     }
297 
getAutomaticZenRule(String id)298     public AutomaticZenRule getAutomaticZenRule(String id) {
299         ZenRule rule;
300         synchronized (mConfig) {
301             if (mConfig == null) return null;
302              rule = mConfig.automaticRules.get(id);
303         }
304         if (rule == null) return null;
305         if (canManageAutomaticZenRule(rule)) {
306              return createAutomaticZenRule(rule);
307         }
308         return null;
309     }
310 
addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule, String reason)311     public String addAutomaticZenRule(String pkg, AutomaticZenRule automaticZenRule,
312             String reason) {
313         if (!isSystemRule(automaticZenRule)) {
314             PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
315             if (component == null) {
316                 component = getActivityInfo(automaticZenRule.getConfigurationActivity());
317             }
318             if (component == null) {
319                 throw new IllegalArgumentException("Lacking enabled CPS or config activity");
320             }
321             int ruleInstanceLimit = -1;
322             if (component.metaData != null) {
323                 ruleInstanceLimit = component.metaData.getInt(
324                         ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
325             }
326             int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
327                     + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
328                     + 1;
329             if (newRuleInstanceCount > RULE_LIMIT_PER_PACKAGE
330                     || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) {
331                 throw new IllegalArgumentException("Rule instance limit exceeded");
332             }
333         }
334 
335         ZenModeConfig newConfig;
336         synchronized (mConfig) {
337             if (mConfig == null) {
338                 throw new AndroidRuntimeException("Could not create rule");
339             }
340             if (DEBUG) {
341                 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
342             }
343             newConfig = mConfig.copy();
344             ZenRule rule = new ZenRule();
345             populateZenRule(pkg, automaticZenRule, rule, true);
346             newConfig.automaticRules.put(rule.id, rule);
347             if (setConfigLocked(newConfig, reason, rule.component, true)) {
348                 return rule.id;
349             } else {
350                 throw new AndroidRuntimeException("Could not create rule");
351             }
352         }
353     }
354 
updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, String reason)355     public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
356             String reason) {
357         ZenModeConfig newConfig;
358         synchronized (mConfig) {
359             if (mConfig == null) return false;
360             if (DEBUG) {
361                 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule
362                         + " reason=" + reason);
363             }
364             newConfig = mConfig.copy();
365             ZenModeConfig.ZenRule rule;
366             if (ruleId == null) {
367                 throw new IllegalArgumentException("Rule doesn't exist");
368             } else {
369                 rule = newConfig.automaticRules.get(ruleId);
370                 if (rule == null || !canManageAutomaticZenRule(rule)) {
371                     throw new SecurityException(
372                             "Cannot update rules not owned by your condition provider");
373                 }
374             }
375             if (rule.enabled != automaticZenRule.isEnabled()) {
376                 dispatchOnAutomaticRuleStatusChanged(mConfig.user, rule.getPkg(), ruleId,
377                         automaticZenRule.isEnabled()
378                                 ? AUTOMATIC_RULE_STATUS_ENABLED : AUTOMATIC_RULE_STATUS_DISABLED);
379             }
380 
381             populateZenRule(rule.pkg, automaticZenRule, rule, false);
382             return setConfigLocked(newConfig, reason, rule.component, true);
383         }
384     }
385 
removeAutomaticZenRule(String id, String reason)386     public boolean removeAutomaticZenRule(String id, String reason) {
387         ZenModeConfig newConfig;
388         synchronized (mConfig) {
389             if (mConfig == null) return false;
390             newConfig = mConfig.copy();
391             ZenRule ruleToRemove = newConfig.automaticRules.get(id);
392             if (ruleToRemove == null) return false;
393             if (canManageAutomaticZenRule(ruleToRemove)) {
394                 newConfig.automaticRules.remove(id);
395                 if (ruleToRemove.getPkg() != null && !"android".equals(ruleToRemove.getPkg())) {
396                     for (ZenRule currRule : newConfig.automaticRules.values()) {
397                         if (currRule.getPkg() != null
398                                 && currRule.getPkg().equals(ruleToRemove.getPkg())) {
399                             break; // no need to remove from cache
400                         }
401                     }
402                     mRulesUidCache.remove(getPackageUserKey(ruleToRemove.getPkg(), newConfig.user));
403                 }
404                 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
405             } else {
406                 throw new SecurityException(
407                         "Cannot delete rules not owned by your condition provider");
408             }
409             dispatchOnAutomaticRuleStatusChanged(
410                     mConfig.user, ruleToRemove.getPkg(), id, AUTOMATIC_RULE_STATUS_REMOVED);
411             return setConfigLocked(newConfig, reason, null, true);
412         }
413     }
414 
removeAutomaticZenRules(String packageName, String reason)415     public boolean removeAutomaticZenRules(String packageName, String reason) {
416         ZenModeConfig newConfig;
417         synchronized (mConfig) {
418             if (mConfig == null) return false;
419             newConfig = mConfig.copy();
420             for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
421                 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
422                 if (Objects.equals(rule.getPkg(), packageName) && canManageAutomaticZenRule(rule)) {
423                     newConfig.automaticRules.removeAt(i);
424                 }
425             }
426             return setConfigLocked(newConfig, reason, null, true);
427         }
428     }
429 
setAutomaticZenRuleState(String id, Condition condition)430     public void setAutomaticZenRuleState(String id, Condition condition) {
431         ZenModeConfig newConfig;
432         synchronized (mConfig) {
433             if (mConfig == null) return;
434 
435             newConfig = mConfig.copy();
436             ArrayList<ZenRule> rules = new ArrayList<>();
437             rules.add(newConfig.automaticRules.get(id));
438             setAutomaticZenRuleStateLocked(newConfig, rules, condition);
439         }
440     }
441 
setAutomaticZenRuleState(Uri ruleDefinition, Condition condition)442     public void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition) {
443         ZenModeConfig newConfig;
444         synchronized (mConfig) {
445             if (mConfig == null) return;
446             newConfig = mConfig.copy();
447 
448             setAutomaticZenRuleStateLocked(newConfig,
449                     findMatchingRules(newConfig, ruleDefinition, condition),
450                     condition);
451         }
452     }
453 
setAutomaticZenRuleStateLocked(ZenModeConfig config, List<ZenRule> rules, Condition condition)454     private void setAutomaticZenRuleStateLocked(ZenModeConfig config, List<ZenRule> rules,
455             Condition condition) {
456         if (rules == null || rules.isEmpty()) return;
457 
458         for (ZenRule rule : rules) {
459             rule.condition = condition;
460             updateSnoozing(rule);
461             setConfigLocked(config, rule.component, "conditionChanged");
462         }
463     }
464 
findMatchingRules(ZenModeConfig config, Uri id, Condition condition)465     private List<ZenRule> findMatchingRules(ZenModeConfig config, Uri id, Condition condition) {
466         List<ZenRule> matchingRules= new ArrayList<>();
467         if (ruleMatches(id, condition, config.manualRule)) {
468             matchingRules.add(config.manualRule);
469         } else {
470             for (ZenRule automaticRule : config.automaticRules.values()) {
471                 if (ruleMatches(id, condition, automaticRule)) {
472                     matchingRules.add(automaticRule);
473                 }
474             }
475         }
476         return matchingRules;
477     }
478 
ruleMatches(Uri id, Condition condition, ZenRule rule)479     private boolean ruleMatches(Uri id, Condition condition, ZenRule rule) {
480         if (id == null || rule == null || rule.conditionId == null) return false;
481         if (!rule.conditionId.equals(id)) return false;
482         if (Objects.equals(condition, rule.condition)) return false;
483         return true;
484     }
485 
updateSnoozing(ZenRule rule)486     private boolean updateSnoozing(ZenRule rule) {
487         if (rule != null && rule.snoozing && !rule.isTrueOrUnknown()) {
488             rule.snoozing = false;
489             if (DEBUG) Log.d(TAG, "Snoozing reset for " + rule.conditionId);
490             return true;
491         }
492         return false;
493     }
494 
getCurrentInstanceCount(ComponentName cn)495     public int getCurrentInstanceCount(ComponentName cn) {
496         if (cn == null) {
497             return 0;
498         }
499         int count = 0;
500         synchronized (mConfig) {
501             for (ZenRule rule : mConfig.automaticRules.values()) {
502                 if (cn.equals(rule.component) || cn.equals(rule.configurationActivity)) {
503                     count++;
504                 }
505             }
506         }
507         return count;
508     }
509 
canManageAutomaticZenRule(ZenRule rule)510     public boolean canManageAutomaticZenRule(ZenRule rule) {
511         final int callingUid = Binder.getCallingUid();
512         if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
513             return true;
514         } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
515                 == PackageManager.PERMISSION_GRANTED) {
516             return true;
517         } else {
518             String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
519             if (packages != null) {
520                 final int packageCount = packages.length;
521                 for (int i = 0; i < packageCount; i++) {
522                     if (packages[i].equals(rule.getPkg())) {
523                         return true;
524                     }
525                 }
526             }
527             return false;
528         }
529     }
530 
updateDefaultZenRules()531     protected void updateDefaultZenRules() {
532         updateDefaultAutomaticRuleNames();
533         for (ZenRule defaultRule : mDefaultConfig.automaticRules.values()) {
534             ZenRule currRule = mConfig.automaticRules.get(defaultRule.id);
535             // if default rule wasn't user-modified nor enabled, use localized name
536             // instead of previous system name
537             if (currRule != null && !currRule.modified && !currRule.enabled
538                     && !defaultRule.name.equals(currRule.name)) {
539                 if (canManageAutomaticZenRule(currRule)) {
540                     if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name "
541                             + "from " + currRule.name + " to " + defaultRule.name);
542                     // update default rule (if locale changed, name of rule will change)
543                     currRule.name = defaultRule.name;
544                     updateAutomaticZenRule(defaultRule.id, createAutomaticZenRule(currRule),
545                             "locale changed");
546                 }
547             }
548         }
549     }
550 
isSystemRule(AutomaticZenRule rule)551     private boolean isSystemRule(AutomaticZenRule rule) {
552         return rule.getOwner() != null
553                 && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
554     }
555 
getServiceInfo(ComponentName owner)556     private ServiceInfo getServiceInfo(ComponentName owner) {
557         Intent queryIntent = new Intent();
558         queryIntent.setComponent(owner);
559         List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
560                 queryIntent,
561                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
562                 UserHandle.getCallingUserId());
563         if (installedServices != null) {
564             for (int i = 0, count = installedServices.size(); i < count; i++) {
565                 ResolveInfo resolveInfo = installedServices.get(i);
566                 ServiceInfo info = resolveInfo.serviceInfo;
567                 if (mServiceConfig.bindPermission.equals(info.permission)) {
568                     return info;
569                 }
570             }
571         }
572         return null;
573     }
574 
getActivityInfo(ComponentName configActivity)575     private ActivityInfo getActivityInfo(ComponentName configActivity) {
576         Intent queryIntent = new Intent();
577         queryIntent.setComponent(configActivity);
578         List<ResolveInfo> installedComponents = mPm.queryIntentActivitiesAsUser(
579                 queryIntent,
580                 PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA,
581                 UserHandle.getCallingUserId());
582         if (installedComponents != null) {
583             for (int i = 0, count = installedComponents.size(); i < count; i++) {
584                 ResolveInfo resolveInfo = installedComponents.get(i);
585                 return resolveInfo.activityInfo;
586             }
587         }
588         return null;
589     }
590 
populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew)591     private void populateZenRule(String pkg, AutomaticZenRule automaticZenRule, ZenRule rule,
592             boolean isNew) {
593         rule.name = automaticZenRule.getName();
594         rule.condition = null;
595         rule.conditionId = automaticZenRule.getConditionId();
596         rule.enabled = automaticZenRule.isEnabled();
597         rule.modified = automaticZenRule.isModified();
598         rule.zenPolicy = automaticZenRule.getZenPolicy();
599         rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
600                 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
601         rule.configurationActivity = automaticZenRule.getConfigurationActivity();
602 
603         if (isNew) {
604             rule.id = ZenModeConfig.newRuleId();
605             rule.creationTime = System.currentTimeMillis();
606             rule.component = automaticZenRule.getOwner();
607             rule.pkg = pkg;
608         }
609 
610         if (rule.enabled != automaticZenRule.isEnabled()) {
611             rule.snoozing = false;
612         }
613     }
614 
createAutomaticZenRule(ZenRule rule)615     protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
616         AutomaticZenRule azr =  new AutomaticZenRule(rule.name, rule.component,
617                 rule.configurationActivity,
618                 rule.conditionId, rule.zenPolicy,
619                 NotificationManager.zenModeToInterruptionFilter(rule.zenMode),
620                 rule.enabled, rule.creationTime);
621         azr.setPackageName(rule.pkg);
622         return azr;
623     }
624 
setManualZenMode(int zenMode, Uri conditionId, String caller, String reason)625     public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
626         setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
627         Settings.Secure.putInt(mContext.getContentResolver(),
628                 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0);
629     }
630 
setManualZenMode(int zenMode, Uri conditionId, String reason, String caller, boolean setRingerMode)631     private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
632             boolean setRingerMode) {
633         ZenModeConfig newConfig;
634         synchronized (mConfig) {
635             if (mConfig == null) return;
636             if (!Global.isValidZenMode(zenMode)) return;
637             if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode)
638                     + " conditionId=" + conditionId + " reason=" + reason
639                     + " setRingerMode=" + setRingerMode);
640             newConfig = mConfig.copy();
641             if (zenMode == Global.ZEN_MODE_OFF) {
642                 newConfig.manualRule = null;
643                 for (ZenRule automaticRule : newConfig.automaticRules.values()) {
644                     if (automaticRule.isAutomaticActive()) {
645                         automaticRule.snoozing = true;
646                     }
647                 }
648             } else {
649                 final ZenRule newRule = new ZenRule();
650                 newRule.enabled = true;
651                 newRule.zenMode = zenMode;
652                 newRule.conditionId = conditionId;
653                 newRule.enabler = caller;
654                 newConfig.manualRule = newRule;
655             }
656             setConfigLocked(newConfig, reason, null, setRingerMode);
657         }
658     }
659 
dump(ProtoOutputStream proto)660     void dump(ProtoOutputStream proto) {
661         proto.write(ZenModeProto.ZEN_MODE, mZenMode);
662         synchronized (mConfig) {
663             if (mConfig.manualRule != null) {
664                 mConfig.manualRule.dumpDebug(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
665             }
666             for (ZenRule rule : mConfig.automaticRules.values()) {
667                 if (rule.enabled && rule.condition != null
668                         && rule.condition.state == Condition.STATE_TRUE
669                         && !rule.snoozing) {
670                     rule.dumpDebug(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
671                 }
672             }
673             mConfig.toNotificationPolicy().dumpDebug(proto, ZenModeProto.POLICY);
674             proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
675         }
676     }
677 
dump(PrintWriter pw, String prefix)678     public void dump(PrintWriter pw, String prefix) {
679         pw.print(prefix);
680         pw.print("mZenMode=");
681         pw.println(Global.zenModeToString(mZenMode));
682         pw.print(prefix);
683         pw.println("mConsolidatedPolicy=" + mConsolidatedPolicy.toString());
684         final int N = mConfigs.size();
685         for (int i = 0; i < N; i++) {
686             dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
687         }
688         pw.print(prefix); pw.print("mUser="); pw.println(mUser);
689         synchronized (mConfig) {
690             dump(pw, prefix, "mConfig", mConfig);
691         }
692 
693         pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
694         mFiltering.dump(pw, prefix);
695         mConditions.dump(pw, prefix);
696     }
697 
dump(PrintWriter pw, String prefix, String var, ZenModeConfig config)698     private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) {
699         pw.print(prefix); pw.print(var); pw.print('=');
700         if (config == null) {
701             pw.println(config);
702             return;
703         }
704         pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
705                 + "messages=%b,messagesFrom=%s,conversations=%b,conversationsFrom=%s,"
706                         + "events=%b,reminders=%b)\n",
707                 config.allowAlarms, config.allowMedia, config.allowSystem,
708                 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
709                 config.allowRepeatCallers, config.allowMessages,
710                 ZenModeConfig.sourceToString(config.allowMessagesFrom),
711                 config.allowConversations,
712                 ZenPolicy.conversationTypeToString(config.allowConversationsFrom),
713                 config.allowEvents, config.allowReminders);
714         pw.print(prefix);
715         pw.printf("  disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
716         pw.print(prefix); pw.print("  manualRule="); pw.println(config.manualRule);
717         if (config.automaticRules.isEmpty()) return;
718         final int N = config.automaticRules.size();
719         for (int i = 0; i < N; i++) {
720             pw.print(prefix); pw.print(i == 0 ? "  automaticRules=" : "                 ");
721             pw.println(config.automaticRules.valueAt(i));
722         }
723     }
724 
readXml(TypedXmlPullParser parser, boolean forRestore, int userId)725     public void readXml(TypedXmlPullParser parser, boolean forRestore, int userId)
726             throws XmlPullParserException, IOException {
727         ZenModeConfig config = ZenModeConfig.readXml(parser);
728         String reason = "readXml";
729 
730         if (config != null) {
731             if (forRestore) {
732                 config.user = userId;
733                 config.manualRule = null;  // don't restore the manual rule
734             }
735 
736             // booleans to determine whether to reset the rules to the default rules
737             boolean allRulesDisabled = true;
738             boolean hasDefaultRules = config.automaticRules.containsAll(
739                     ZenModeConfig.DEFAULT_RULE_IDS);
740 
741             long time = System.currentTimeMillis();
742             if (config.automaticRules != null && config.automaticRules.size() > 0) {
743                 for (ZenRule automaticRule : config.automaticRules.values()) {
744                     if (forRestore) {
745                         // don't restore transient state from restored automatic rules
746                         automaticRule.snoozing = false;
747                         automaticRule.condition = null;
748                         automaticRule.creationTime = time;
749                     }
750 
751                     allRulesDisabled &= !automaticRule.enabled;
752                 }
753             }
754 
755             if (!hasDefaultRules && allRulesDisabled
756                     && (forRestore || config.version < ZenModeConfig.XML_VERSION)) {
757                 // reset zen automatic rules to default on restore or upgrade if:
758                 // - doesn't already have default rules and
759                 // - all previous automatic rules were disabled
760                 config.automaticRules = new ArrayMap<>();
761                 for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
762                     config.automaticRules.put(rule.id, rule);
763                 }
764                 reason += ", reset to default rules";
765             }
766 
767             // Resolve user id for settings.
768             userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
769             if (config.version < ZenModeConfig.XML_VERSION) {
770                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
771                         Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId);
772             } else {
773                 // devices not restoring/upgrading already have updated zen settings
774                 Settings.Secure.putIntForUser(mContext.getContentResolver(),
775                         Settings.Secure.ZEN_SETTINGS_UPDATED, 1, userId);
776             }
777             if (DEBUG) Log.d(TAG, reason);
778             synchronized (mConfig) {
779                 setConfigLocked(config, null, reason);
780             }
781         }
782     }
783 
writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId)784     public void writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId)
785             throws IOException {
786         synchronized (mConfigs) {
787             final int n = mConfigs.size();
788             for (int i = 0; i < n; i++) {
789                 if (forBackup && mConfigs.keyAt(i) != userId) {
790                     continue;
791                 }
792                 mConfigs.valueAt(i).writeXml(out, version);
793             }
794         }
795     }
796 
797     /**
798      * @return user-specified default notification policy for priority only do not disturb
799      */
getNotificationPolicy()800     public Policy getNotificationPolicy() {
801         return getNotificationPolicy(mConfig);
802     }
803 
getNotificationPolicy(ZenModeConfig config)804     private static Policy getNotificationPolicy(ZenModeConfig config) {
805         return config == null ? null : config.toNotificationPolicy();
806     }
807 
808     /**
809      * Sets the global notification policy used for priority only do not disturb
810      */
setNotificationPolicy(Policy policy)811     public void setNotificationPolicy(Policy policy) {
812         if (policy == null || mConfig == null) return;
813         synchronized (mConfig) {
814             final ZenModeConfig newConfig = mConfig.copy();
815             newConfig.applyNotificationPolicy(policy);
816             setConfigLocked(newConfig, null, "setNotificationPolicy");
817         }
818     }
819 
820     /**
821      * Removes old rule instances whose owner is not installed.
822      */
cleanUpZenRules()823     private void cleanUpZenRules() {
824         long currentTime = System.currentTimeMillis();
825         synchronized (mConfig) {
826             final ZenModeConfig newConfig = mConfig.copy();
827             if (newConfig.automaticRules != null) {
828                 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
829                     ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
830                     if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
831                         try {
832                             if (rule.getPkg() != null) {
833                                 mPm.getPackageInfo(rule.getPkg(), PackageManager.MATCH_ANY_USER);
834                             }
835                         } catch (PackageManager.NameNotFoundException e) {
836                             newConfig.automaticRules.removeAt(i);
837                         }
838                     }
839                 }
840             }
841             setConfigLocked(newConfig, null, "cleanUpZenRules");
842         }
843     }
844 
845     /**
846      * @return a copy of the zen mode configuration
847      */
getConfig()848     public ZenModeConfig getConfig() {
849         synchronized (mConfig) {
850             return mConfig.copy();
851         }
852     }
853 
854     /**
855      * @return a copy of the zen mode consolidated policy
856      */
getConsolidatedNotificationPolicy()857     public Policy getConsolidatedNotificationPolicy() {
858         return mConsolidatedPolicy.copy();
859     }
860 
setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent, String reason)861     public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
862             String reason) {
863         return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/);
864     }
865 
setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason)866     public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) {
867         synchronized (mConfig) {
868             setConfigLocked(config, triggeringComponent, reason);
869         }
870     }
871 
setConfigLocked(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)872     private boolean setConfigLocked(ZenModeConfig config, String reason,
873             ComponentName triggeringComponent, boolean setRingerMode) {
874         final long identity = Binder.clearCallingIdentity();
875         try {
876             if (config == null || !config.isValid()) {
877                 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
878                 return false;
879             }
880             if (config.user != mUser) {
881                 // simply store away for background users
882                 mConfigs.put(config.user, config);
883                 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
884                 return true;
885             }
886             // handle CPS backed conditions - danger! may modify config
887             mConditions.evaluateConfig(config, null, false /*processSubscriptions*/);
888 
889             mConfigs.put(config.user, config);
890             if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
891             ZenLog.traceConfig(reason, mConfig, config);
892 
893             // send some broadcasts
894             final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
895                     getNotificationPolicy(config));
896             if (!config.equals(mConfig)) {
897                 mConfig = config;
898                 dispatchOnConfigChanged();
899                 updateConsolidatedPolicy(reason);
900             }
901             if (policyChanged) {
902                 dispatchOnPolicyChanged();
903             }
904             mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode);
905             return true;
906         } catch (SecurityException e) {
907             Log.wtf(TAG, "Invalid rule in config", e);
908             return false;
909         } finally {
910             Binder.restoreCallingIdentity(identity);
911         }
912     }
913 
applyConfig(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)914     private void applyConfig(ZenModeConfig config, String reason,
915             ComponentName triggeringComponent, boolean setRingerMode) {
916         final String val = Integer.toString(config.hashCode());
917         Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
918         evaluateZenMode(reason, setRingerMode);
919         mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
920     }
921 
getZenModeSetting()922     private int getZenModeSetting() {
923         return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
924     }
925 
926     @VisibleForTesting
setZenModeSetting(int zen)927     protected void setZenModeSetting(int zen) {
928         Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
929         showZenUpgradeNotification(zen);
930     }
931 
getPreviousRingerModeSetting()932     private int getPreviousRingerModeSetting() {
933         return Global.getInt(mContext.getContentResolver(),
934                 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
935     }
936 
setPreviousRingerModeSetting(Integer previousRingerLevel)937     private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
938         Global.putString(
939                 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
940                 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
941     }
942 
943     @VisibleForTesting
evaluateZenMode(String reason, boolean setRingerMode)944     protected void evaluateZenMode(String reason, boolean setRingerMode) {
945         if (DEBUG) Log.d(TAG, "evaluateZenMode");
946         if (mConfig == null) return;
947         final int policyHashBefore = mConsolidatedPolicy == null ? 0
948                 : mConsolidatedPolicy.hashCode();
949         final int zenBefore = mZenMode;
950         final int zen = computeZenMode();
951         ZenLog.traceSetZenMode(zen, reason);
952         mZenMode = zen;
953         setZenModeSetting(mZenMode);
954         updateConsolidatedPolicy(reason);
955         updateRingerModeAffectedStreams();
956         if (setRingerMode && (zen != zenBefore || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
957                 && policyHashBefore != mConsolidatedPolicy.hashCode()))) {
958             applyZenToRingerMode();
959         }
960         applyRestrictions();
961         if (zen != zenBefore) {
962             mHandler.postDispatchOnZenModeChanged();
963         }
964     }
965 
updateRingerModeAffectedStreams()966     private void updateRingerModeAffectedStreams() {
967         if (mAudioManager != null) {
968             mAudioManager.updateRingerModeAffectedStreamsInternal();
969         }
970     }
971 
computeZenMode()972     private int computeZenMode() {
973         if (mConfig == null) return Global.ZEN_MODE_OFF;
974         synchronized (mConfig) {
975             if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
976             int zen = Global.ZEN_MODE_OFF;
977             for (ZenRule automaticRule : mConfig.automaticRules.values()) {
978                 if (automaticRule.isAutomaticActive()) {
979                     if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
980                         // automatic rule triggered dnd and user hasn't seen update dnd dialog
981                         if (Settings.Secure.getInt(mContext.getContentResolver(),
982                                 Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
983                             Settings.Secure.putInt(mContext.getContentResolver(),
984                                     Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
985                         }
986                         zen = automaticRule.zenMode;
987                     }
988                 }
989             }
990             return zen;
991         }
992     }
993 
applyCustomPolicy(ZenPolicy policy, ZenRule rule)994     private void applyCustomPolicy(ZenPolicy policy, ZenRule rule) {
995         if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
996             policy.apply(new ZenPolicy.Builder()
997                     .disallowAllSounds()
998                     .build());
999         } else if (rule.zenMode == Global.ZEN_MODE_ALARMS) {
1000             policy.apply(new ZenPolicy.Builder()
1001                     .disallowAllSounds()
1002                     .allowAlarms(true)
1003                     .allowMedia(true)
1004                     .build());
1005         } else {
1006             policy.apply(rule.zenPolicy);
1007         }
1008     }
1009 
updateConsolidatedPolicy(String reason)1010     private void updateConsolidatedPolicy(String reason) {
1011         if (mConfig == null) return;
1012         synchronized (mConfig) {
1013             ZenPolicy policy = new ZenPolicy();
1014             if (mConfig.manualRule != null) {
1015                 applyCustomPolicy(policy, mConfig.manualRule);
1016             }
1017 
1018             for (ZenRule automaticRule : mConfig.automaticRules.values()) {
1019                 if (automaticRule.isAutomaticActive()) {
1020                     applyCustomPolicy(policy, automaticRule);
1021                 }
1022             }
1023             Policy newPolicy = mConfig.toNotificationPolicy(policy);
1024             if (!Objects.equals(mConsolidatedPolicy, newPolicy)) {
1025                 mConsolidatedPolicy = newPolicy;
1026                 dispatchOnConsolidatedPolicyChanged();
1027                 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason);
1028             }
1029         }
1030     }
1031 
updateDefaultAutomaticRuleNames()1032     private void updateDefaultAutomaticRuleNames() {
1033         for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
1034             if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) {
1035                 rule.name = mContext.getResources()
1036                         .getString(R.string.zen_mode_default_events_name);
1037             } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) {
1038                 rule.name = mContext.getResources()
1039                         .getString(R.string.zen_mode_default_every_night_name);
1040             }
1041         }
1042     }
1043 
1044     @VisibleForTesting
applyRestrictions()1045     protected void applyRestrictions() {
1046         final boolean zenOn = mZenMode != Global.ZEN_MODE_OFF;
1047         final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1048         final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
1049         final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
1050         final boolean allowCalls = mConsolidatedPolicy.allowCalls()
1051                 && mConsolidatedPolicy.allowCallsFrom() == PRIORITY_SENDERS_ANY;
1052         final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
1053         final boolean allowSystem = mConsolidatedPolicy.allowSystem();
1054         final boolean allowMedia = mConsolidatedPolicy.allowMedia();
1055         final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();
1056 
1057         // notification restrictions
1058         final boolean muteNotifications = zenOn
1059                 || (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
1060         // call restrictions
1061         final boolean muteCalls = zenAlarmsOnly
1062                 || (zenPriorityOnly && !(allowCalls || allowRepeatCallers))
1063                 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
1064         // alarm restrictions
1065         final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
1066         // media restrictions
1067         final boolean muteMedia = zenPriorityOnly && !allowMedia;
1068         // system restrictions
1069         final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem);
1070         // total silence restrictions
1071         final boolean muteEverything = zenSilence || (zenPriorityOnly
1072                 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
1073 
1074         for (int usage : AudioAttributes.SDK_USAGES) {
1075             final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
1076             if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
1077                 applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
1078             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
1079                 applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage);
1080             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
1081                 applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage);
1082             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
1083                 applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage);
1084             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
1085                 applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage);
1086             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
1087                 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
1088                     // normally DND will only restrict touch sounds, not haptic feedback/vibrations
1089                     applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage,
1090                             AppOpsManager.OP_PLAY_AUDIO);
1091                     applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE);
1092                 } else {
1093                     applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage);
1094                 }
1095             } else {
1096                 applyRestrictions(zenPriorityOnly, muteEverything, usage);
1097             }
1098         }
1099     }
1100 
1101 
1102     @VisibleForTesting
applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code)1103     protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) {
1104         final long ident = Binder.clearCallingIdentity();
1105         try {
1106             mAppOps.setRestriction(code, usage,
1107                     mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
1108                     zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);
1109         } finally {
1110             Binder.restoreCallingIdentity(ident);
1111         }
1112     }
1113 
1114     @VisibleForTesting
applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage)1115     protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) {
1116         applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE);
1117         applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO);
1118     }
1119 
1120 
1121     @VisibleForTesting
applyZenToRingerMode()1122     protected void applyZenToRingerMode() {
1123         if (mAudioManager == null) return;
1124         // force the ringer mode into compliance
1125         final int ringerModeInternal = mAudioManager.getRingerModeInternal();
1126         int newRingerModeInternal = ringerModeInternal;
1127         switch (mZenMode) {
1128             case Global.ZEN_MODE_NO_INTERRUPTIONS:
1129             case Global.ZEN_MODE_ALARMS:
1130                 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
1131                     setPreviousRingerModeSetting(ringerModeInternal);
1132                     newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
1133                 }
1134                 break;
1135             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
1136                 // do not apply zen to ringer, streams zen muted in AudioService
1137                 break;
1138             case Global.ZEN_MODE_OFF:
1139                 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
1140                     newRingerModeInternal = getPreviousRingerModeSetting();
1141                     setPreviousRingerModeSetting(null);
1142                 }
1143                 break;
1144         }
1145         if (newRingerModeInternal != -1) {
1146             mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
1147         }
1148     }
1149 
dispatchOnConfigChanged()1150     private void dispatchOnConfigChanged() {
1151         for (Callback callback : mCallbacks) {
1152             callback.onConfigChanged();
1153         }
1154     }
1155 
dispatchOnPolicyChanged()1156     private void dispatchOnPolicyChanged() {
1157         for (Callback callback : mCallbacks) {
1158             callback.onPolicyChanged();
1159         }
1160     }
1161 
dispatchOnConsolidatedPolicyChanged()1162     private void dispatchOnConsolidatedPolicyChanged() {
1163         for (Callback callback : mCallbacks) {
1164             callback.onConsolidatedPolicyChanged();
1165         }
1166     }
1167 
dispatchOnZenModeChanged()1168     private void dispatchOnZenModeChanged() {
1169         for (Callback callback : mCallbacks) {
1170             callback.onZenModeChanged();
1171         }
1172     }
1173 
dispatchOnAutomaticRuleStatusChanged(int userId, String pkg, String id, int status)1174     private void dispatchOnAutomaticRuleStatusChanged(int userId, String pkg, String id,
1175             int status) {
1176         for (Callback callback : mCallbacks) {
1177             callback.onAutomaticRuleStatusChanged(userId, pkg, id, status);
1178         }
1179     }
1180 
readDefaultConfig(Resources resources)1181     private ZenModeConfig readDefaultConfig(Resources resources) {
1182         XmlResourceParser parser = null;
1183         try {
1184             parser = resources.getXml(R.xml.default_zen_mode_config);
1185             while (parser.next() != XmlPullParser.END_DOCUMENT) {
1186                 final ZenModeConfig config = ZenModeConfig.readXml(XmlUtils.makeTyped(parser));
1187                 if (config != null) return config;
1188             }
1189         } catch (Exception e) {
1190             Log.w(TAG, "Error reading default zen mode config from resource", e);
1191         } finally {
1192             IoUtils.closeQuietly(parser);
1193         }
1194         return new ZenModeConfig();
1195     }
1196 
zenSeverity(int zen)1197     private static int zenSeverity(int zen) {
1198         switch (zen) {
1199             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
1200             case Global.ZEN_MODE_ALARMS: return 2;
1201             case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
1202             default: return 0;
1203         }
1204     }
1205 
1206     /**
1207      * Generate pulled atoms about do not disturb configurations.
1208      */
pullRules(List<StatsEvent> events)1209     public void pullRules(List<StatsEvent> events) {
1210         synchronized (mConfig) {
1211             final int numConfigs = mConfigs.size();
1212             for (int i = 0; i < numConfigs; i++) {
1213                 final int user = mConfigs.keyAt(i);
1214                 final ZenModeConfig config = mConfigs.valueAt(i);
1215                 SysUiStatsEvent.Builder data = mStatsEventBuilderFactory.newBuilder()
1216                         .setAtomId(DND_MODE_RULE)
1217                         .writeInt(user)
1218                         .writeBoolean(config.manualRule != null) // enabled
1219                         .writeBoolean(config.areChannelsBypassingDnd)
1220                         .writeInt(ROOT_CONFIG)
1221                         .writeString("") // name, empty for root config
1222                         .writeInt(Process.SYSTEM_UID) // system owns root config
1223                         .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true)
1224                         .writeByteArray(config.toZenPolicy().toProto());
1225                 events.add(data.build());
1226                 if (config.manualRule != null && config.manualRule.enabler != null) {
1227                     ruleToProtoLocked(user, config.manualRule, events);
1228                 }
1229                 for (ZenRule rule : config.automaticRules.values()) {
1230                     ruleToProtoLocked(user, rule, events);
1231                 }
1232             }
1233         }
1234     }
1235 
ruleToProtoLocked(int user, ZenRule rule, List<StatsEvent> events)1236     private void ruleToProtoLocked(int user, ZenRule rule, List<StatsEvent> events) {
1237         // Make the ID safe.
1238         String id = rule.id == null ? "" : rule.id;
1239         if (!ZenModeConfig.DEFAULT_RULE_IDS.contains(id)) {
1240             id = "";
1241         }
1242 
1243         // Look for packages and enablers, enablers get priority.
1244         String pkg = rule.getPkg() == null ? "" : rule.getPkg();
1245         if (rule.enabler != null) {
1246             pkg = rule.enabler;
1247             id = ZenModeConfig.MANUAL_RULE_ID;
1248         }
1249 
1250         SysUiStatsEvent.Builder data;
1251         data = mStatsEventBuilderFactory.newBuilder()
1252                 .setAtomId(DND_MODE_RULE)
1253                 .writeInt(user)
1254                 .writeBoolean(rule.enabled)
1255                 .writeBoolean(false) // channels_bypassing unused for rules
1256                 .writeInt(rule.zenMode)
1257                 .writeString(id)
1258                 .writeInt(getPackageUid(pkg, user))
1259                 .addBooleanAnnotation(ANNOTATION_ID_IS_UID, true);
1260         byte[] policyProto = new byte[]{};
1261         if (rule.zenPolicy != null) {
1262             policyProto = rule.zenPolicy.toProto();
1263         }
1264         data.writeByteArray(policyProto);
1265         events.add(data.build());
1266     }
1267 
getPackageUid(String pkg, int user)1268     private int getPackageUid(String pkg, int user) {
1269         if ("android".equals(pkg)) {
1270             return Process.SYSTEM_UID;
1271         }
1272         final String key = getPackageUserKey(pkg, user);
1273         if (mRulesUidCache.get(key) == null) {
1274             try {
1275                 mRulesUidCache.put(key, mPm.getPackageUidAsUser(pkg, user));
1276             } catch (PackageManager.NameNotFoundException e) {
1277             }
1278         }
1279         return mRulesUidCache.getOrDefault(key, -1);
1280     }
1281 
getPackageUserKey(String pkg, int user)1282     private static String getPackageUserKey(String pkg, int user) {
1283         return pkg + "|" + user;
1284     }
1285 
1286     @VisibleForTesting
1287     protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
1288         @Override
toString()1289         public String toString() {
1290             return TAG;
1291         }
1292 
1293         @Override
onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeExternal, VolumePolicy policy)1294         public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
1295                 int ringerModeExternal, VolumePolicy policy) {
1296             final boolean isChange = ringerModeOld != ringerModeNew;
1297 
1298             int ringerModeExternalOut = ringerModeNew;
1299 
1300             if (mZenMode == Global.ZEN_MODE_OFF
1301                     || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1302                     && !ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(mConfig))) {
1303                 // in priority only with ringer not muted, save ringer mode changes
1304                 // in dnd off, save ringer mode changes
1305                 setPreviousRingerModeSetting(ringerModeNew);
1306             }
1307             int newZen = -1;
1308             switch (ringerModeNew) {
1309                 case AudioManager.RINGER_MODE_SILENT:
1310                     if (isChange && policy.doNotDisturbWhenSilent) {
1311                         if (mZenMode == Global.ZEN_MODE_OFF) {
1312                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1313                         }
1314                         setPreviousRingerModeSetting(ringerModeOld);
1315                     }
1316                     break;
1317                 case AudioManager.RINGER_MODE_VIBRATE:
1318                 case AudioManager.RINGER_MODE_NORMAL:
1319                     if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
1320                             && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
1321                             || mZenMode == Global.ZEN_MODE_ALARMS
1322                             || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1323                             && ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(
1324                             mConfig)))) {
1325                         newZen = Global.ZEN_MODE_OFF;
1326                     } else if (mZenMode != Global.ZEN_MODE_OFF) {
1327                         ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
1328                     }
1329                     break;
1330             }
1331 
1332             if (newZen != -1) {
1333                 setManualZenMode(newZen, null, "ringerModeInternal", null,
1334                         false /*setRingerMode*/);
1335             }
1336             if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
1337                 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
1338                         ringerModeExternal, ringerModeExternalOut);
1339             }
1340             return ringerModeExternalOut;
1341         }
1342 
1343         @Override
onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeInternal, VolumePolicy policy)1344         public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
1345                 int ringerModeInternal, VolumePolicy policy) {
1346             int ringerModeInternalOut = ringerModeNew;
1347             final boolean isChange = ringerModeOld != ringerModeNew;
1348             final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
1349 
1350             int newZen = -1;
1351             switch (ringerModeNew) {
1352                 case AudioManager.RINGER_MODE_SILENT:
1353                     if (isChange) {
1354                         if (mZenMode == Global.ZEN_MODE_OFF) {
1355                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1356                         }
1357                         ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
1358                                 : AudioManager.RINGER_MODE_SILENT;
1359                     } else {
1360                         ringerModeInternalOut = ringerModeInternal;
1361                     }
1362                     break;
1363                 case AudioManager.RINGER_MODE_VIBRATE:
1364                 case AudioManager.RINGER_MODE_NORMAL:
1365                     if (mZenMode != Global.ZEN_MODE_OFF) {
1366                         newZen = Global.ZEN_MODE_OFF;
1367                     }
1368                     break;
1369             }
1370             if (newZen != -1) {
1371                 setManualZenMode(newZen, null, "ringerModeExternal", caller,
1372                         false /*setRingerMode*/);
1373             }
1374 
1375             ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
1376                     ringerModeInternal, ringerModeInternalOut);
1377             return ringerModeInternalOut;
1378         }
1379 
1380         @Override
canVolumeDownEnterSilent()1381         public boolean canVolumeDownEnterSilent() {
1382             return mZenMode == Global.ZEN_MODE_OFF;
1383         }
1384 
1385         @Override
getRingerModeAffectedStreams(int streams)1386         public int getRingerModeAffectedStreams(int streams) {
1387             // ringtone, notification and system streams are always affected by ringer mode
1388             // zen muting is handled in AudioService.java's mZenModeAffectedStreams
1389             streams |= (1 << AudioSystem.STREAM_RING) |
1390                     (1 << AudioSystem.STREAM_NOTIFICATION) |
1391                     (1 << AudioSystem.STREAM_SYSTEM);
1392 
1393             if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
1394                 // alarm and music and streams affected by ringer mode (cannot be adjusted) when in
1395                 // total silence
1396                 streams |= (1 << AudioSystem.STREAM_ALARM) |
1397                         (1 << AudioSystem.STREAM_MUSIC) |
1398                         (1 << AudioSystem.STREAM_ASSISTANT);
1399             } else {
1400                 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
1401                         (1 << AudioSystem.STREAM_MUSIC) |
1402                         (1 << AudioSystem.STREAM_ASSISTANT)
1403                 );
1404             }
1405             return streams;
1406         }
1407     }
1408 
1409     private final class SettingsObserver extends ContentObserver {
1410         private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1411 
SettingsObserver(Handler handler)1412         public SettingsObserver(Handler handler) {
1413             super(handler);
1414         }
1415 
observe()1416         public void observe() {
1417             final ContentResolver resolver = mContext.getContentResolver();
1418             resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1419             update(null);
1420         }
1421 
1422         @Override
onChange(boolean selfChange, Uri uri)1423         public void onChange(boolean selfChange, Uri uri) {
1424             update(uri);
1425         }
1426 
update(Uri uri)1427         public void update(Uri uri) {
1428             if (ZEN_MODE.equals(uri)) {
1429                 if (mZenMode != getZenModeSetting()) {
1430                     if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1431                     setZenModeSetting(mZenMode);
1432                 }
1433             }
1434         }
1435     }
1436 
showZenUpgradeNotification(int zen)1437     private void showZenUpgradeNotification(int zen) {
1438         final boolean isWatch = mContext.getPackageManager().hasSystemFeature(
1439             PackageManager.FEATURE_WATCH);
1440         final boolean showNotification = mIsBootComplete
1441                 && zen != Global.ZEN_MODE_OFF
1442                 && !isWatch
1443                 && Settings.Secure.getInt(mContext.getContentResolver(),
1444                 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
1445                 && Settings.Secure.getInt(mContext.getContentResolver(),
1446                 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
1447 
1448         if (isWatch) {
1449             Settings.Secure.putInt(mContext.getContentResolver(),
1450                     Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
1451         }
1452 
1453         if (showNotification) {
1454             mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
1455                     createZenUpgradeNotification());
1456             Settings.Secure.putInt(mContext.getContentResolver(),
1457                     Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
1458         }
1459     }
1460 
1461     @VisibleForTesting
createZenUpgradeNotification()1462     protected Notification createZenUpgradeNotification() {
1463         final Bundle extras = new Bundle();
1464         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
1465                 mContext.getResources().getString(R.string.global_action_settings));
1466         int title = R.string.zen_upgrade_notification_title;
1467         int content = R.string.zen_upgrade_notification_content;
1468         int drawable = R.drawable.ic_zen_24dp;
1469         if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
1470                 getConsolidatedNotificationPolicy().suppressedVisualEffects)) {
1471             title = R.string.zen_upgrade_notification_visd_title;
1472             content = R.string.zen_upgrade_notification_visd_content;
1473             drawable = R.drawable.ic_dnd_block_notifications;
1474         }
1475 
1476         Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
1477         onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1478         return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
1479                 .setAutoCancel(true)
1480                 .setSmallIcon(R.drawable.ic_settings_24dp)
1481                 .setLargeIcon(Icon.createWithResource(mContext, drawable))
1482                 .setContentTitle(mContext.getResources().getString(title))
1483                 .setContentText(mContext.getResources().getString(content))
1484                 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
1485                         PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
1486                 .setAutoCancel(true)
1487                 .setLocalOnly(true)
1488                 .addExtras(extras)
1489                 .setStyle(new Notification.BigTextStyle())
1490                 .build();
1491     }
1492 
1493     private final class Metrics extends Callback {
1494         private static final String COUNTER_MODE_PREFIX = "dnd_mode_";
1495         private static final String COUNTER_TYPE_PREFIX = "dnd_type_";
1496         private static final int DND_OFF = 0;
1497         private static final int DND_ON_MANUAL = 1;
1498         private static final int DND_ON_AUTOMATIC = 2;
1499         private static final String COUNTER_RULE = "dnd_rule_count";
1500         private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1501 
1502         // Total silence, alarms only, priority only
1503         private int mPreviousZenMode = -1;
1504         private long mModeLogTimeMs = 0L;
1505 
1506         private int mNumZenRules = -1;
1507         private long mRuleCountLogTime = 0L;
1508 
1509         // automatic (1) vs manual (0) vs dnd off (2)
1510         private int mPreviousZenType = -1;
1511         private long mTypeLogTimeMs = 0L;
1512 
1513         @Override
onZenModeChanged()1514         void onZenModeChanged() {
1515             emit();
1516         }
1517 
1518         @Override
onConfigChanged()1519         void onConfigChanged() {
1520             emit();
1521         }
1522 
emit()1523         private void emit() {
1524             mHandler.postMetricsTimer();
1525             emitZenMode();
1526             emitRules();
1527             emitDndType();
1528         }
1529 
emitZenMode()1530         private void emitZenMode() {
1531             final long now = SystemClock.elapsedRealtime();
1532             final long since = (now - mModeLogTimeMs);
1533             if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1534                 if (mPreviousZenMode != -1) {
1535                     MetricsLogger.count(
1536                             mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since);
1537                 }
1538                 mPreviousZenMode = mZenMode;
1539                 mModeLogTimeMs = now;
1540             }
1541         }
1542 
emitRules()1543         private void emitRules() {
1544             final long now = SystemClock.elapsedRealtime();
1545             final long since = (now - mRuleCountLogTime);
1546             synchronized (mConfig) {
1547                 int numZenRules = mConfig.automaticRules.size();
1548                 if (mNumZenRules != numZenRules
1549                         || since > MINIMUM_LOG_PERIOD_MS) {
1550                     if (mNumZenRules != -1) {
1551                         MetricsLogger.count(mContext, COUNTER_RULE,
1552                                 numZenRules - mNumZenRules);
1553                     }
1554                     mNumZenRules = numZenRules;
1555 
1556                     mRuleCountLogTime = since;
1557                 }
1558             }
1559         }
1560 
emitDndType()1561         private void emitDndType() {
1562             final long now = SystemClock.elapsedRealtime();
1563             final long since = (now - mTypeLogTimeMs);
1564             synchronized (mConfig) {
1565                 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF;
1566                 int zenType = !dndOn ? DND_OFF
1567                         : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC;
1568                 if (zenType != mPreviousZenType
1569                         || since > MINIMUM_LOG_PERIOD_MS) {
1570                     if (mPreviousZenType != -1) {
1571                         MetricsLogger.count(
1572                                 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since);
1573                     }
1574                     mTypeLogTimeMs = now;
1575                     mPreviousZenType = zenType;
1576                 }
1577             }
1578         }
1579     }
1580 
1581     private final class H extends Handler {
1582         private static final int MSG_DISPATCH = 1;
1583         private static final int MSG_METRICS = 2;
1584         private static final int MSG_APPLY_CONFIG = 4;
1585 
1586         private final class ConfigMessageData {
1587             public final ZenModeConfig config;
1588             public ComponentName triggeringComponent;
1589             public final String reason;
1590             public final boolean setRingerMode;
1591 
ConfigMessageData(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)1592             ConfigMessageData(ZenModeConfig config, String reason,
1593                     ComponentName triggeringComponent, boolean setRingerMode) {
1594                 this.config = config;
1595                 this.reason = reason;
1596                 this.setRingerMode = setRingerMode;
1597                 this.triggeringComponent = triggeringComponent;
1598             }
1599         }
1600 
1601         private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
1602 
H(Looper looper)1603         private H(Looper looper) {
1604             super(looper);
1605         }
1606 
postDispatchOnZenModeChanged()1607         private void postDispatchOnZenModeChanged() {
1608             removeMessages(MSG_DISPATCH);
1609             sendEmptyMessage(MSG_DISPATCH);
1610         }
1611 
postMetricsTimer()1612         private void postMetricsTimer() {
1613             removeMessages(MSG_METRICS);
1614             sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1615         }
1616 
postApplyConfig(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)1617         private void postApplyConfig(ZenModeConfig config, String reason,
1618                 ComponentName triggeringComponent, boolean setRingerMode) {
1619             sendMessage(obtainMessage(MSG_APPLY_CONFIG,
1620                     new ConfigMessageData(config, reason, triggeringComponent, setRingerMode)));
1621         }
1622 
1623         @Override
handleMessage(Message msg)1624         public void handleMessage(Message msg) {
1625             switch (msg.what) {
1626                 case MSG_DISPATCH:
1627                     dispatchOnZenModeChanged();
1628                     break;
1629                 case MSG_METRICS:
1630                     mMetrics.emit();
1631                     break;
1632                 case MSG_APPLY_CONFIG:
1633                     ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1634                     applyConfig(applyConfigData.config, applyConfigData.reason,
1635                             applyConfigData.triggeringComponent, applyConfigData.setRingerMode);
1636             }
1637         }
1638     }
1639 
1640     public static class Callback {
onConfigChanged()1641         void onConfigChanged() {}
onZenModeChanged()1642         void onZenModeChanged() {}
onPolicyChanged()1643         void onPolicyChanged() {}
onConsolidatedPolicyChanged()1644         void onConsolidatedPolicyChanged() {}
onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status)1645         void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {}
1646     }
1647 }
1648