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