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