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