• 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 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                 dispatchOnConfigChanged();
848                 updateConsolidatedPolicy(reason);
849             }
850             if (policyChanged) {
851                 dispatchOnPolicyChanged();
852             }
853             mConfig = config;
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 == NotificationManager.INTERRUPTION_FILTER_NONE) {
946             policy.apply(new ZenPolicy.Builder()
947                     .disallowAllSounds()
948                     .build());
949         } else if (rule.zenMode
950                 == NotificationManager.INTERRUPTION_FILTER_ALARMS) {
951             policy.apply(new ZenPolicy.Builder()
952                     .disallowAllSounds()
953                     .allowAlarms(true)
954                     .allowMedia(true)
955                     .build());
956         } else {
957             policy.apply(rule.zenPolicy);
958         }
959     }
960 
updateConsolidatedPolicy(String reason)961     private void updateConsolidatedPolicy(String reason) {
962         if (mConfig == null) return;
963         synchronized (mConfig) {
964             ZenPolicy policy = new ZenPolicy();
965             if (mConfig.manualRule != null) {
966                 applyCustomPolicy(policy, mConfig.manualRule);
967             }
968 
969             for (ZenRule automaticRule : mConfig.automaticRules.values()) {
970                 if (automaticRule.isAutomaticActive()) {
971                     applyCustomPolicy(policy, automaticRule);
972                 }
973             }
974             Policy newPolicy = mConfig.toNotificationPolicy(policy);
975             if (!Objects.equals(mConsolidatedPolicy, newPolicy)) {
976                 mConsolidatedPolicy = newPolicy;
977                 dispatchOnConsolidatedPolicyChanged();
978                 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason);
979             }
980         }
981     }
982 
updateDefaultAutomaticRuleNames()983     private void updateDefaultAutomaticRuleNames() {
984         for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
985             if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) {
986                 rule.name = mContext.getResources()
987                         .getString(R.string.zen_mode_default_events_name);
988             } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) {
989                 rule.name = mContext.getResources()
990                         .getString(R.string.zen_mode_default_every_night_name);
991             }
992         }
993     }
994 
995     @VisibleForTesting
applyRestrictions()996     protected void applyRestrictions() {
997         final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
998         final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
999         final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
1000         final boolean allowCalls = mConsolidatedPolicy.allowCalls();
1001         final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
1002         final boolean allowSystem = mConsolidatedPolicy.allowSystem();
1003         final boolean allowMedia = mConsolidatedPolicy.allowMedia();
1004         final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();
1005 
1006         // notification restrictions
1007         final boolean muteNotifications =
1008                 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
1009         // call restrictions
1010         final boolean muteCalls = zenAlarmsOnly
1011                 || (zenPriorityOnly && !allowCalls && !allowRepeatCallers)
1012                 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
1013         // alarm restrictions
1014         final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
1015         // media restrictions
1016         final boolean muteMedia = zenPriorityOnly && !allowMedia;
1017         // system restrictions
1018         final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem);
1019         // total silence restrictions
1020         final boolean muteEverything = zenSilence || (zenPriorityOnly
1021                 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
1022 
1023         for (int usage : AudioAttributes.SDK_USAGES) {
1024             final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
1025             if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
1026                 applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
1027             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
1028                 applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage);
1029             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
1030                 applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage);
1031             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
1032                 applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage);
1033             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
1034                 applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage);
1035             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
1036                 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
1037                     // normally DND will only restrict touch sounds, not haptic feedback/vibrations
1038                     applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage,
1039                             AppOpsManager.OP_PLAY_AUDIO);
1040                     applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE);
1041                 } else {
1042                     applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage);
1043                 }
1044             } else {
1045                 applyRestrictions(zenPriorityOnly, muteEverything, usage);
1046             }
1047         }
1048     }
1049 
1050 
1051     @VisibleForTesting
applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code)1052     protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) {
1053         final long ident = Binder.clearCallingIdentity();
1054         try {
1055             mAppOps.setRestriction(code, usage,
1056                     mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
1057                     zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);
1058         } finally {
1059             Binder.restoreCallingIdentity(ident);
1060         }
1061     }
1062 
1063     @VisibleForTesting
applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage)1064     protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) {
1065         applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE);
1066         applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO);
1067     }
1068 
1069 
1070     @VisibleForTesting
applyZenToRingerMode()1071     protected void applyZenToRingerMode() {
1072         if (mAudioManager == null) return;
1073         // force the ringer mode into compliance
1074         final int ringerModeInternal = mAudioManager.getRingerModeInternal();
1075         int newRingerModeInternal = ringerModeInternal;
1076         switch (mZenMode) {
1077             case Global.ZEN_MODE_NO_INTERRUPTIONS:
1078             case Global.ZEN_MODE_ALARMS:
1079                 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
1080                     setPreviousRingerModeSetting(ringerModeInternal);
1081                     newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
1082                 }
1083                 break;
1084             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
1085                 // do not apply zen to ringer, streams zen muted in AudioService
1086                 break;
1087             case Global.ZEN_MODE_OFF:
1088                 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
1089                     newRingerModeInternal = getPreviousRingerModeSetting();
1090                     setPreviousRingerModeSetting(null);
1091                 }
1092                 break;
1093         }
1094         if (newRingerModeInternal != -1) {
1095             mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
1096         }
1097     }
1098 
dispatchOnConfigChanged()1099     private void dispatchOnConfigChanged() {
1100         for (Callback callback : mCallbacks) {
1101             callback.onConfigChanged();
1102         }
1103     }
1104 
dispatchOnPolicyChanged()1105     private void dispatchOnPolicyChanged() {
1106         for (Callback callback : mCallbacks) {
1107             callback.onPolicyChanged();
1108         }
1109     }
1110 
dispatchOnConsolidatedPolicyChanged()1111     private void dispatchOnConsolidatedPolicyChanged() {
1112         for (Callback callback : mCallbacks) {
1113             callback.onConsolidatedPolicyChanged();
1114         }
1115     }
1116 
dispatchOnZenModeChanged()1117     private void dispatchOnZenModeChanged() {
1118         for (Callback callback : mCallbacks) {
1119             callback.onZenModeChanged();
1120         }
1121     }
1122 
readDefaultConfig(Resources resources)1123     private ZenModeConfig readDefaultConfig(Resources resources) {
1124         XmlResourceParser parser = null;
1125         try {
1126             parser = resources.getXml(R.xml.default_zen_mode_config);
1127             while (parser.next() != XmlPullParser.END_DOCUMENT) {
1128                 final ZenModeConfig config = ZenModeConfig.readXml(parser);
1129                 if (config != null) return config;
1130             }
1131         } catch (Exception e) {
1132             Log.w(TAG, "Error reading default zen mode config from resource", e);
1133         } finally {
1134             IoUtils.closeQuietly(parser);
1135         }
1136         return new ZenModeConfig();
1137     }
1138 
zenSeverity(int zen)1139     private static int zenSeverity(int zen) {
1140         switch (zen) {
1141             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
1142             case Global.ZEN_MODE_ALARMS: return 2;
1143             case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
1144             default: return 0;
1145         }
1146     }
1147 
1148     @VisibleForTesting
1149     protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
1150         @Override
toString()1151         public String toString() {
1152             return TAG;
1153         }
1154 
1155         @Override
onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeExternal, VolumePolicy policy)1156         public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
1157                 int ringerModeExternal, VolumePolicy policy) {
1158             final boolean isChange = ringerModeOld != ringerModeNew;
1159 
1160             int ringerModeExternalOut = ringerModeNew;
1161 
1162             if (mZenMode == Global.ZEN_MODE_OFF
1163                     || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1164                     && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) {
1165                 // in priority only with ringer not muted, save ringer mode changes
1166                 // in dnd off, save ringer mode changes
1167                 setPreviousRingerModeSetting(ringerModeNew);
1168             }
1169             int newZen = -1;
1170             switch (ringerModeNew) {
1171                 case AudioManager.RINGER_MODE_SILENT:
1172                     if (isChange && policy.doNotDisturbWhenSilent) {
1173                         if (mZenMode == Global.ZEN_MODE_OFF) {
1174                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1175                         }
1176                         setPreviousRingerModeSetting(ringerModeOld);
1177                     }
1178                     break;
1179                 case AudioManager.RINGER_MODE_VIBRATE:
1180                 case AudioManager.RINGER_MODE_NORMAL:
1181                     if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
1182                             && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
1183                             || mZenMode == Global.ZEN_MODE_ALARMS
1184                             || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1185                             && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
1186                             mConfig)))) {
1187                         newZen = Global.ZEN_MODE_OFF;
1188                     } else if (mZenMode != Global.ZEN_MODE_OFF) {
1189                         ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
1190                     }
1191                     break;
1192             }
1193 
1194             if (newZen != -1) {
1195                 setManualZenMode(newZen, null, "ringerModeInternal", null,
1196                         false /*setRingerMode*/);
1197             }
1198             if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
1199                 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
1200                         ringerModeExternal, ringerModeExternalOut);
1201             }
1202             return ringerModeExternalOut;
1203         }
1204 
1205         @Override
onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeInternal, VolumePolicy policy)1206         public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
1207                 int ringerModeInternal, VolumePolicy policy) {
1208             int ringerModeInternalOut = ringerModeNew;
1209             final boolean isChange = ringerModeOld != ringerModeNew;
1210             final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
1211 
1212             int newZen = -1;
1213             switch (ringerModeNew) {
1214                 case AudioManager.RINGER_MODE_SILENT:
1215                     if (isChange) {
1216                         if (mZenMode == Global.ZEN_MODE_OFF) {
1217                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1218                         }
1219                         ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
1220                                 : AudioManager.RINGER_MODE_SILENT;
1221                     } else {
1222                         ringerModeInternalOut = ringerModeInternal;
1223                     }
1224                     break;
1225                 case AudioManager.RINGER_MODE_VIBRATE:
1226                 case AudioManager.RINGER_MODE_NORMAL:
1227                     if (mZenMode != Global.ZEN_MODE_OFF) {
1228                         newZen = Global.ZEN_MODE_OFF;
1229                     }
1230                     break;
1231             }
1232             if (newZen != -1) {
1233                 setManualZenMode(newZen, null, "ringerModeExternal", caller,
1234                         false /*setRingerMode*/);
1235             }
1236 
1237             ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
1238                     ringerModeInternal, ringerModeInternalOut);
1239             return ringerModeInternalOut;
1240         }
1241 
1242         @Override
canVolumeDownEnterSilent()1243         public boolean canVolumeDownEnterSilent() {
1244             return mZenMode == Global.ZEN_MODE_OFF;
1245         }
1246 
1247         @Override
getRingerModeAffectedStreams(int streams)1248         public int getRingerModeAffectedStreams(int streams) {
1249             // ringtone and notification streams are always affected by ringer mode
1250             // system stream is affected by ringer mode when not in priority-only
1251             streams |= (1 << AudioSystem.STREAM_RING) |
1252                     (1 << AudioSystem.STREAM_NOTIFICATION) |
1253                     (1 << AudioSystem.STREAM_SYSTEM);
1254 
1255             if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
1256                 // alarm and music streams affected by ringer mode when in total silence
1257                 streams |= (1 << AudioSystem.STREAM_ALARM) |
1258                         (1 << AudioSystem.STREAM_MUSIC);
1259             } else {
1260                 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
1261                         (1 << AudioSystem.STREAM_MUSIC));
1262             }
1263 
1264             if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1265                     && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) {
1266                 // system stream is not affected by ringer mode in priority only when the ringer
1267                 // is zen muted (all other notification categories are muted)
1268                 streams &= ~(1 << AudioSystem.STREAM_SYSTEM);
1269             } else {
1270                 streams |= (1 << AudioSystem.STREAM_SYSTEM);
1271             }
1272             return streams;
1273         }
1274     }
1275 
1276     private final class SettingsObserver extends ContentObserver {
1277         private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1278 
SettingsObserver(Handler handler)1279         public SettingsObserver(Handler handler) {
1280             super(handler);
1281         }
1282 
observe()1283         public void observe() {
1284             final ContentResolver resolver = mContext.getContentResolver();
1285             resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1286             update(null);
1287         }
1288 
1289         @Override
onChange(boolean selfChange, Uri uri)1290         public void onChange(boolean selfChange, Uri uri) {
1291             update(uri);
1292         }
1293 
update(Uri uri)1294         public void update(Uri uri) {
1295             if (ZEN_MODE.equals(uri)) {
1296                 if (mZenMode != getZenModeSetting()) {
1297                     if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1298                     setZenModeSetting(mZenMode);
1299                 }
1300             }
1301         }
1302     }
1303 
showZenUpgradeNotification(int zen)1304     private void showZenUpgradeNotification(int zen) {
1305         final boolean isWatch = mContext.getPackageManager().hasSystemFeature(
1306             PackageManager.FEATURE_WATCH);
1307         final boolean showNotification = mIsBootComplete
1308                 && zen != Global.ZEN_MODE_OFF
1309                 && !isWatch
1310                 && Settings.Secure.getInt(mContext.getContentResolver(),
1311                 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
1312                 && Settings.Secure.getInt(mContext.getContentResolver(),
1313                 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
1314 
1315         if (isWatch) {
1316             Settings.Secure.putInt(mContext.getContentResolver(),
1317                     Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
1318         }
1319 
1320         if (showNotification) {
1321             mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
1322                     createZenUpgradeNotification());
1323             Settings.Secure.putInt(mContext.getContentResolver(),
1324                     Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
1325         }
1326     }
1327 
1328     @VisibleForTesting
createZenUpgradeNotification()1329     protected Notification createZenUpgradeNotification() {
1330         final Bundle extras = new Bundle();
1331         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
1332                 mContext.getResources().getString(R.string.global_action_settings));
1333         int title = R.string.zen_upgrade_notification_title;
1334         int content = R.string.zen_upgrade_notification_content;
1335         int drawable = R.drawable.ic_zen_24dp;
1336         if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
1337                 getConsolidatedNotificationPolicy().suppressedVisualEffects)) {
1338             title = R.string.zen_upgrade_notification_visd_title;
1339             content = R.string.zen_upgrade_notification_visd_content;
1340             drawable = R.drawable.ic_dnd_block_notifications;
1341         }
1342 
1343         Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
1344         onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1345         return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
1346                 .setAutoCancel(true)
1347                 .setSmallIcon(R.drawable.ic_settings_24dp)
1348                 .setLargeIcon(Icon.createWithResource(mContext, drawable))
1349                 .setContentTitle(mContext.getResources().getString(title))
1350                 .setContentText(mContext.getResources().getString(content))
1351                 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
1352                         PendingIntent.FLAG_UPDATE_CURRENT))
1353                 .setAutoCancel(true)
1354                 .setLocalOnly(true)
1355                 .addExtras(extras)
1356                 .setStyle(new Notification.BigTextStyle())
1357                 .build();
1358     }
1359 
1360     private final class Metrics extends Callback {
1361         private static final String COUNTER_MODE_PREFIX = "dnd_mode_";
1362         private static final String COUNTER_TYPE_PREFIX = "dnd_type_";
1363         private static final int DND_OFF = 0;
1364         private static final int DND_ON_MANUAL = 1;
1365         private static final int DND_ON_AUTOMATIC = 2;
1366         private static final String COUNTER_RULE = "dnd_rule_count";
1367         private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1368 
1369         // Total silence, alarms only, priority only
1370         private int mPreviousZenMode = -1;
1371         private long mModeLogTimeMs = 0L;
1372 
1373         private int mNumZenRules = -1;
1374         private long mRuleCountLogTime = 0L;
1375 
1376         // automatic (1) vs manual (0) vs dnd off (2)
1377         private int mPreviousZenType = -1;
1378         private long mTypeLogTimeMs = 0L;
1379 
1380         @Override
onZenModeChanged()1381         void onZenModeChanged() {
1382             emit();
1383         }
1384 
1385         @Override
onConfigChanged()1386         void onConfigChanged() {
1387             emit();
1388         }
1389 
emit()1390         private void emit() {
1391             mHandler.postMetricsTimer();
1392             emitZenMode();
1393             emitRules();
1394             emitDndType();
1395         }
1396 
emitZenMode()1397         private void emitZenMode() {
1398             final long now = SystemClock.elapsedRealtime();
1399             final long since = (now - mModeLogTimeMs);
1400             if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1401                 if (mPreviousZenMode != -1) {
1402                     MetricsLogger.count(
1403                             mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since);
1404                 }
1405                 mPreviousZenMode = mZenMode;
1406                 mModeLogTimeMs = now;
1407             }
1408         }
1409 
emitRules()1410         private void emitRules() {
1411             final long now = SystemClock.elapsedRealtime();
1412             final long since = (now - mRuleCountLogTime);
1413             synchronized (mConfig) {
1414                 int numZenRules = mConfig.automaticRules.size();
1415                 if (mNumZenRules != numZenRules
1416                         || since > MINIMUM_LOG_PERIOD_MS) {
1417                     if (mNumZenRules != -1) {
1418                         MetricsLogger.count(mContext, COUNTER_RULE,
1419                                 numZenRules - mNumZenRules);
1420                     }
1421                     mNumZenRules = numZenRules;
1422 
1423                     mRuleCountLogTime = since;
1424                 }
1425             }
1426         }
1427 
emitDndType()1428         private void emitDndType() {
1429             final long now = SystemClock.elapsedRealtime();
1430             final long since = (now - mTypeLogTimeMs);
1431             synchronized (mConfig) {
1432                 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF;
1433                 int zenType = !dndOn ? DND_OFF
1434                         : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC;
1435                 if (zenType != mPreviousZenType
1436                         || since > MINIMUM_LOG_PERIOD_MS) {
1437                     if (mPreviousZenType != -1) {
1438                         MetricsLogger.count(
1439                                 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since);
1440                     }
1441                     mTypeLogTimeMs = now;
1442                     mPreviousZenType = zenType;
1443                 }
1444             }
1445         }
1446     }
1447 
1448     private final class H extends Handler {
1449         private static final int MSG_DISPATCH = 1;
1450         private static final int MSG_METRICS = 2;
1451         private static final int MSG_APPLY_CONFIG = 4;
1452 
1453         private final class ConfigMessageData {
1454             public final ZenModeConfig config;
1455             public ComponentName triggeringComponent;
1456             public final String reason;
1457             public final boolean setRingerMode;
1458 
ConfigMessageData(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)1459             ConfigMessageData(ZenModeConfig config, String reason,
1460                     ComponentName triggeringComponent, boolean setRingerMode) {
1461                 this.config = config;
1462                 this.reason = reason;
1463                 this.setRingerMode = setRingerMode;
1464                 this.triggeringComponent = triggeringComponent;
1465             }
1466         }
1467 
1468         private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
1469 
H(Looper looper)1470         private H(Looper looper) {
1471             super(looper);
1472         }
1473 
postDispatchOnZenModeChanged()1474         private void postDispatchOnZenModeChanged() {
1475             removeMessages(MSG_DISPATCH);
1476             sendEmptyMessage(MSG_DISPATCH);
1477         }
1478 
postMetricsTimer()1479         private void postMetricsTimer() {
1480             removeMessages(MSG_METRICS);
1481             sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1482         }
1483 
postApplyConfig(ZenModeConfig config, String reason, ComponentName triggeringComponent, boolean setRingerMode)1484         private void postApplyConfig(ZenModeConfig config, String reason,
1485                 ComponentName triggeringComponent, boolean setRingerMode) {
1486             sendMessage(obtainMessage(MSG_APPLY_CONFIG,
1487                     new ConfigMessageData(config, reason, triggeringComponent, setRingerMode)));
1488         }
1489 
1490         @Override
handleMessage(Message msg)1491         public void handleMessage(Message msg) {
1492             switch (msg.what) {
1493                 case MSG_DISPATCH:
1494                     dispatchOnZenModeChanged();
1495                     break;
1496                 case MSG_METRICS:
1497                     mMetrics.emit();
1498                     break;
1499                 case MSG_APPLY_CONFIG:
1500                     ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1501                     applyConfig(applyConfigData.config, applyConfigData.reason,
1502                             applyConfigData.triggeringComponent, applyConfigData.setRingerMode);
1503             }
1504         }
1505     }
1506 
1507     public static class Callback {
onConfigChanged()1508         void onConfigChanged() {}
onZenModeChanged()1509         void onZenModeChanged() {}
onPolicyChanged()1510         void onPolicyChanged() {}
onConsolidatedPolicyChanged()1511         void onConsolidatedPolicyChanged() {}
1512     }
1513 }
1514