• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2014, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.notification;
18 
19 import static android.app.AutomaticZenRule.TYPE_DRIVING;
20 import static android.app.AutomaticZenRule.TYPE_UNKNOWN;
21 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ACTIVATED;
22 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DEACTIVATED;
23 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED;
24 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
25 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
26 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_UNKNOWN;
27 import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
28 import static android.app.backup.NotificationLoggingConstants.DATA_TYPE_ZEN_CONFIG;
29 import static android.app.backup.NotificationLoggingConstants.ERROR_XML_PARSING;
30 import static android.service.notification.Condition.SOURCE_UNKNOWN;
31 import static android.service.notification.Condition.SOURCE_USER_ACTION;
32 import static android.service.notification.Condition.STATE_FALSE;
33 import static android.service.notification.Condition.STATE_TRUE;
34 import static android.service.notification.NotificationServiceProto.ROOT_CONFIG;
35 import static android.service.notification.ZenModeConfig.ORIGIN_APP;
36 import static android.service.notification.ZenModeConfig.ORIGIN_INIT;
37 import static android.service.notification.ZenModeConfig.ORIGIN_INIT_USER;
38 import static android.service.notification.ZenModeConfig.ORIGIN_RESTORE_BACKUP;
39 import static android.service.notification.ZenModeConfig.ORIGIN_SYSTEM;
40 import static android.service.notification.ZenModeConfig.ORIGIN_UNKNOWN;
41 import static android.service.notification.ZenModeConfig.ORIGIN_USER_IN_APP;
42 import static android.service.notification.ZenModeConfig.ORIGIN_USER_IN_SYSTEMUI;
43 import static android.service.notification.ZenModeConfig.ZenRule.OVERRIDE_ACTIVATE;
44 import static android.service.notification.ZenModeConfig.ZenRule.OVERRIDE_DEACTIVATE;
45 import static android.service.notification.ZenModeConfig.implicitRuleId;
46 import static android.service.notification.ZenModeConfig.isImplicitRuleId;
47 
48 import static com.android.internal.util.FrameworkStatsLog.DND_MODE_RULE;
49 import static com.android.internal.util.Preconditions.checkArgument;
50 import static com.android.server.notification.Flags.preventZenDeviceEffectsWhileDriving;
51 
52 import static java.util.Objects.requireNonNull;
53 
54 import android.annotation.DrawableRes;
55 import android.annotation.NonNull;
56 import android.annotation.Nullable;
57 import android.annotation.SuppressLint;
58 import android.annotation.UserIdInt;
59 import android.app.AppOpsManager;
60 import android.app.AutomaticZenRule;
61 import android.app.Flags;
62 import android.app.NotificationManager;
63 import android.app.NotificationManager.Policy;
64 import android.app.backup.BackupRestoreEventLogger;
65 import android.app.compat.CompatChanges;
66 import android.compat.annotation.ChangeId;
67 import android.compat.annotation.EnabledSince;
68 import android.content.ComponentName;
69 import android.content.ContentResolver;
70 import android.content.Context;
71 import android.content.Intent;
72 import android.content.pm.ActivityInfo;
73 import android.content.pm.ApplicationInfo;
74 import android.content.pm.PackageItemInfo;
75 import android.content.pm.PackageManager;
76 import android.content.pm.ResolveInfo;
77 import android.content.pm.ServiceInfo;
78 import android.content.res.Resources;
79 import android.content.res.XmlResourceParser;
80 import android.database.ContentObserver;
81 import android.media.AudioAttributes;
82 import android.media.AudioManager;
83 import android.media.AudioManagerInternal;
84 import android.media.AudioSystem;
85 import android.media.VolumePolicy;
86 import android.net.Uri;
87 import android.os.Binder;
88 import android.os.Build;
89 import android.os.Bundle;
90 import android.os.Handler;
91 import android.os.Looper;
92 import android.os.Message;
93 import android.os.Process;
94 import android.os.SystemClock;
95 import android.os.UserHandle;
96 import android.provider.Settings.Global;
97 import android.service.notification.Condition;
98 import android.service.notification.ConditionProviderService;
99 import android.service.notification.DeviceEffectsApplier;
100 import android.service.notification.SystemZenRules;
101 import android.service.notification.ZenAdapters;
102 import android.service.notification.ZenDeviceEffects;
103 import android.service.notification.ZenModeConfig;
104 import android.service.notification.ZenModeConfig.ConfigOrigin;
105 import android.service.notification.ZenModeConfig.ZenRule;
106 import android.service.notification.ZenModeProto;
107 import android.service.notification.ZenPolicy;
108 import android.text.TextUtils;
109 import android.util.AndroidRuntimeException;
110 import android.util.ArrayMap;
111 import android.util.Log;
112 import android.util.Slog;
113 import android.util.SparseArray;
114 import android.util.StatsEvent;
115 import android.util.proto.ProtoOutputStream;
116 
117 import androidx.annotation.VisibleForTesting;
118 
119 import com.android.internal.R;
120 import com.android.internal.annotations.GuardedBy;
121 import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
122 import com.android.internal.logging.MetricsLogger;
123 import com.android.internal.util.FrameworkStatsLog;
124 import com.android.internal.util.XmlUtils;
125 import com.android.modules.utils.TypedXmlPullParser;
126 import com.android.modules.utils.TypedXmlSerializer;
127 import com.android.server.LocalServices;
128 
129 import libcore.io.IoUtils;
130 
131 import org.xmlpull.v1.XmlPullParser;
132 import org.xmlpull.v1.XmlPullParserException;
133 
134 import java.io.IOException;
135 import java.io.PrintWriter;
136 import java.time.Clock;
137 import java.time.Duration;
138 import java.time.Instant;
139 import java.util.ArrayList;
140 import java.util.Collections;
141 import java.util.HashMap;
142 import java.util.List;
143 import java.util.Map;
144 import java.util.Objects;
145 
146 /**
147  * NotificationManagerService helper for functionality related to zen mode.
148  */
149 public class ZenModeHelper {
150     static final String TAG = "ZenModeHelper";
151     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
152 
153     private static final String PACKAGE_ANDROID = "android";
154 
155     // The amount of time rules instances can exist without their owning app being installed.
156     private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
157     static final int RULE_LIMIT_PER_PACKAGE = 100;
158     private static final Duration DELETED_RULE_KEPT_FOR = Duration.ofDays(30);
159 
160     /**
161      * Amount of time since last activation after which implicit rules that have never been
162      * customized by the user are automatically cleaned up.
163      */
164     private static final Duration IMPLICIT_RULE_KEPT_FOR = Duration.ofDays(30);
165 
166     private static final int MAX_ICON_RESOURCE_NAME_LENGTH = 1000;
167 
168     /**
169      * Send new activation AutomaticZenRule statuses to apps with a min target SDK version
170      */
171     @ChangeId
172     @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
173     static final long SEND_ACTIVATION_AZR_STATUSES = 308673617L;
174 
175     // pkg|userId => uid
176     @VisibleForTesting protected final ArrayMap<String, Integer> mRulesUidCache = new ArrayMap<>();
177 
178     private final Context mContext;
179     private final H mHandler;
180     private final Clock mClock;
181     private final SettingsObserver mSettingsObserver;
182     private final AppOpsManager mAppOps;
183     private final ZenModeConfig mDefaultConfig;
184     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
185     private final ZenModeFiltering mFiltering;
186     private final RingerModeDelegate mRingerModeDelegate = new
187             RingerModeDelegate();
188     @VisibleForTesting protected final ZenModeConditions mConditions;
189     @GuardedBy("mConfigLock")
190     @VisibleForTesting final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
191     private final Metrics mMetrics = new Metrics();
192     private final ConditionProviders.Config mServiceConfig;
193     private final SystemUiSystemPropertiesFlags.FlagResolver mFlagResolver;
194     private final ZenModeEventLogger mZenModeEventLogger;
195 
196     @VisibleForTesting protected int mZenMode;
197     @VisibleForTesting protected NotificationManager.Policy mConsolidatedPolicy;
198     @GuardedBy("mConfigLock")
199     private ZenDeviceEffects mConsolidatedDeviceEffects = new ZenDeviceEffects.Builder().build();
200     private int mUser = UserHandle.USER_SYSTEM;
201 
202     private final Object mConfigLock = new Object();
203     @GuardedBy("mConfigLock")
204     @VisibleForTesting protected ZenModeConfig mConfig;
205     @VisibleForTesting protected AudioManagerInternal mAudioManager;
206     protected PackageManager mPm;
207     @GuardedBy("mConfigLock")
208     private DeviceEffectsApplier mDeviceEffectsApplier;
209     private long mSuppressedEffects;
210 
211     public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
212     public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
213     public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
214             | SUPPRESSED_EFFECT_NOTIFICATIONS;
215 
216     @VisibleForTesting protected boolean mIsSystemServicesReady;
217 
218     private String[] mPriorityOnlyDndExemptPackages;
219 
ZenModeHelper(Context context, Looper looper, Clock clock, ConditionProviders conditionProviders, SystemUiSystemPropertiesFlags.FlagResolver flagResolver, ZenModeEventLogger zenModeEventLogger)220     public ZenModeHelper(Context context, Looper looper, Clock clock,
221             ConditionProviders conditionProviders,
222             SystemUiSystemPropertiesFlags.FlagResolver flagResolver,
223             ZenModeEventLogger zenModeEventLogger) {
224         mContext = context;
225         mHandler = new H(looper);
226         mClock = clock;
227         addCallback(mMetrics);
228         mAppOps = context.getSystemService(AppOpsManager.class);
229 
230         mDefaultConfig = Flags.modesUi()
231                 ? ZenModeConfig.getDefaultConfig()
232                 : readDefaultConfig(mContext.getResources());
233         updateDefaultConfig(mContext, mDefaultConfig);
234 
235         synchronized (mConfigLock) {
236             mConfig = mDefaultConfig.copy();
237             mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
238         }
239         mConsolidatedPolicy = mConfig.toNotificationPolicy();
240 
241         mSettingsObserver = new SettingsObserver(mHandler);
242         mSettingsObserver.observe();
243         mFiltering = new ZenModeFiltering(mContext);
244         mConditions = new ZenModeConditions(this, conditionProviders);
245         mServiceConfig = conditionProviders.getConfig();
246         mFlagResolver = flagResolver;
247         mZenModeEventLogger = zenModeEventLogger;
248     }
249 
250     @Override
toString()251     public String toString() {
252         return TAG;
253     }
254 
matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity, int callingUid)255     public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
256             ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity,
257             int callingUid) {
258         synchronized (mConfigLock) {
259             return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConsolidatedPolicy,
260                     userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity,
261                     callingUid);
262         }
263     }
264 
isCall(NotificationRecord record)265     public boolean isCall(NotificationRecord record) {
266         return mFiltering.isCall(record);
267     }
268 
recordCaller(NotificationRecord record)269     public void recordCaller(NotificationRecord record) {
270         mFiltering.recordCall(record);
271     }
272 
cleanUpCallersAfter(long timeThreshold)273     protected void cleanUpCallersAfter(long timeThreshold) {
274         mFiltering.cleanUpCallersAfter(timeThreshold);
275     }
276 
shouldIntercept(NotificationRecord record)277     public boolean shouldIntercept(NotificationRecord record) {
278         synchronized (mConfigLock) {
279             return mFiltering.shouldIntercept(mZenMode, mConsolidatedPolicy, record);
280         }
281     }
282 
addCallback(Callback callback)283     public void addCallback(Callback callback) {
284         mCallbacks.add(callback);
285     }
286 
removeCallback(Callback callback)287     public void removeCallback(Callback callback) {
288         mCallbacks.remove(callback);
289     }
290 
291     @VisibleForTesting(otherwise = VisibleForTesting.NONE)
getCallbacks()292     public List<Callback> getCallbacks() {
293         return mCallbacks;
294     }
295 
initZenMode()296     public void initZenMode() {
297         if (DEBUG) Log.d(TAG, "initZenMode");
298         synchronized (mConfigLock) {
299             // "update" config to itself, which will have no effect in the case where a config
300             // was read in via XML, but will initialize zen mode if nothing was read in and the
301             // config remains the default.
302             updateConfigAndZenModeLocked(mConfig, ORIGIN_INIT, "init",
303                     true /*setRingerMode*/, Process.SYSTEM_UID /* callingUid */);
304         }
305     }
306 
onSystemReady()307     public void onSystemReady() {
308         if (DEBUG) Log.d(TAG, "onSystemReady");
309         mAudioManager = LocalServices.getService(AudioManagerInternal.class);
310         if (mAudioManager != null) {
311             mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
312         }
313         mPm = mContext.getPackageManager();
314         mHandler.postMetricsTimer();
315         cleanUpZenRules();
316         mIsSystemServicesReady = true;
317     }
318 
319     /**
320      * @return whether a {@link DeviceEffectsApplier} has already been set or not
321      */
hasDeviceEffectsApplier()322     boolean hasDeviceEffectsApplier() {
323         synchronized (mConfigLock) {
324             return mDeviceEffectsApplier != null;
325         }
326     }
327 
328     /**
329      * Set the {@link DeviceEffectsApplier} used to apply the consolidated effects.
330      *
331      * <p>Previously calculated effects (as loaded from the user's {@link ZenModeConfig}) will be
332      * applied immediately.
333      */
setDeviceEffectsApplier(@onNull DeviceEffectsApplier deviceEffectsApplier)334     void setDeviceEffectsApplier(@NonNull DeviceEffectsApplier deviceEffectsApplier) {
335         synchronized (mConfigLock) {
336             if (mDeviceEffectsApplier != null) {
337                 throw new IllegalStateException("Already set up a DeviceEffectsApplier!");
338             }
339             mDeviceEffectsApplier = deviceEffectsApplier;
340         }
341         applyConsolidatedDeviceEffects(ORIGIN_INIT);
342     }
343 
onUserSwitched(int user)344     public void onUserSwitched(int user) {
345         loadConfigForUser(user, "onUserSwitched");
346     }
347 
onUserRemoved(int user)348     public void onUserRemoved(int user) {
349         if (user < UserHandle.USER_SYSTEM) return;
350         if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
351         synchronized (mConfigLock) {
352             mConfigs.remove(user);
353         }
354     }
355 
setPriorityOnlyDndExemptPackages(String[] packages)356     void setPriorityOnlyDndExemptPackages(String[] packages) {
357         mPriorityOnlyDndExemptPackages = packages;
358     }
359 
loadConfigForUser(int user, String reason)360     private void loadConfigForUser(int user, String reason) {
361         if (mUser == user || user < UserHandle.USER_SYSTEM) return;
362         mUser = user;
363         if (DEBUG) Log.d(TAG, reason + " u=" + user);
364         ZenModeConfig config = null;
365         synchronized (mConfigLock) {
366             if (mConfigs.get(user) != null) {
367                 config = mConfigs.get(user).copy();
368             }
369         }
370         if (config == null) {
371             if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user);
372             config = mDefaultConfig.copy();
373             config.user = user;
374         }
375         synchronized (mConfigLock) {
376             setConfigLocked(config, null, ORIGIN_INIT_USER, reason,
377                     Process.SYSTEM_UID);
378         }
379         cleanUpZenRules();
380     }
381 
getZenModeListenerInterruptionFilter()382     public int getZenModeListenerInterruptionFilter() {
383         return NotificationManager.zenModeToInterruptionFilter(mZenMode);
384     }
385 
setSuppressedEffects(long suppressedEffects)386     public void setSuppressedEffects(long suppressedEffects) {
387         if (mSuppressedEffects == suppressedEffects) return;
388         mSuppressedEffects = suppressedEffects;
389         applyRestrictions();
390     }
391 
getSuppressedEffects()392     public long getSuppressedEffects() {
393         return mSuppressedEffects;
394     }
395 
getZenMode()396     public int getZenMode() {
397         return mZenMode;
398     }
399 
400     /**
401      * Get the list of {@link AutomaticZenRule} instances that the calling package can manage
402      * (which means the owned rules for a regular app, and every rule for system callers) together
403      * with their ids.
404      */
getAutomaticZenRules(UserHandle user, int callingUid)405     Map<String, AutomaticZenRule> getAutomaticZenRules(UserHandle user, int callingUid) {
406         HashMap<String, AutomaticZenRule> rules = new HashMap<>();
407         synchronized (mConfigLock) {
408             ZenModeConfig config = getConfigLocked(user);
409             if (config == null) return rules;
410 
411             for (ZenRule rule : config.automaticRules.values()) {
412                 if (canManageAutomaticZenRule(rule, callingUid)) {
413                     rules.put(rule.id, zenRuleToAutomaticZenRule(rule));
414                 }
415             }
416             return rules;
417         }
418     }
419 
getAutomaticZenRule(UserHandle user, String id, int callingUid)420     public AutomaticZenRule getAutomaticZenRule(UserHandle user, String id, int callingUid) {
421         ZenRule rule;
422         synchronized (mConfigLock) {
423             ZenModeConfig config = getConfigLocked(user);
424             if (config == null) return null;
425             rule = config.automaticRules.get(id);
426         }
427         if (rule == null) return null;
428         if (canManageAutomaticZenRule(rule, callingUid)) {
429             return zenRuleToAutomaticZenRule(rule);
430         }
431         return null;
432     }
433 
addAutomaticZenRule(UserHandle user, String pkg, AutomaticZenRule automaticZenRule, @ConfigOrigin int origin, String reason, int callingUid)434     public String addAutomaticZenRule(UserHandle user, String pkg,
435             AutomaticZenRule automaticZenRule, @ConfigOrigin int origin, String reason,
436             int callingUid) {
437         checkManageRuleOrigin("addAutomaticZenRule", origin);
438         if (!ZenModeConfig.SYSTEM_AUTHORITY.equals(pkg)) {
439             PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
440             if (component == null) {
441                 component = getActivityInfo(automaticZenRule.getConfigurationActivity());
442             }
443             if (component == null) {
444                 throw new IllegalArgumentException("Lacking enabled CPS or config activity");
445             }
446             int ruleInstanceLimit = -1;
447             if (component.metaData != null) {
448                 ruleInstanceLimit = component.metaData.getInt(
449                         ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
450             }
451             int newRuleInstanceCount = getCurrentInstanceCount(user, automaticZenRule.getOwner())
452                     + getCurrentInstanceCount(user, automaticZenRule.getConfigurationActivity())
453                     + 1;
454             int newPackageRuleCount = getPackageRuleCount(user, pkg) + 1;
455             if (newPackageRuleCount > RULE_LIMIT_PER_PACKAGE
456                     || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) {
457                 throw new IllegalArgumentException("Rule instance limit exceeded");
458             }
459         }
460 
461         ZenModeConfig newConfig;
462         synchronized (mConfigLock) {
463             ZenModeConfig config = getConfigLocked(user);
464             if (config == null) {
465                 throw new AndroidRuntimeException("Could not create rule");
466             }
467             if (DEBUG) {
468                 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
469             }
470             newConfig = config.copy();
471             ZenRule rule = new ZenRule();
472             populateZenRule(pkg, automaticZenRule, newConfig, rule, origin, /* isNew= */ true);
473             rule = maybeRestoreRemovedRule(newConfig, pkg, rule, automaticZenRule, origin);
474             newConfig.automaticRules.put(rule.id, rule);
475             maybeReplaceDefaultRule(newConfig, null, automaticZenRule);
476 
477             if (setConfigLocked(newConfig, origin, reason, rule.component, true, callingUid)) {
478                 return rule.id;
479             } else {
480                 throw new AndroidRuntimeException("Could not create rule");
481             }
482         }
483     }
484 
485     @GuardedBy("mConfigLock")
maybeRestoreRemovedRule(ZenModeConfig config, String pkg, ZenRule ruleToAdd, AutomaticZenRule azrToAdd, @ConfigOrigin int origin)486     private ZenRule maybeRestoreRemovedRule(ZenModeConfig config, String pkg, ZenRule ruleToAdd,
487             AutomaticZenRule azrToAdd, @ConfigOrigin int origin) {
488         String deletedKey = ZenModeConfig.deletedRuleKey(ruleToAdd);
489         if (deletedKey == null) {
490             // Couldn't calculate the deletedRuleKey (condition or pkg null?). This should
491             // never happen for an app-provided rule because NMS validates both.
492             return ruleToAdd;
493         }
494         ZenRule ruleToRestore = config.deletedRules.get(deletedKey);
495         if (ruleToRestore == null) {
496             return ruleToAdd; // Cannot restore.
497         }
498 
499         // We have found a previous rule to maybe restore. Whether we do that or not, we don't need
500         // to keep it around (if not restored now, it won't be in future calls either).
501         config.deletedRules.remove(deletedKey);
502         ruleToRestore.deletionInstant = null;
503 
504         if (origin != ORIGIN_APP) {
505             return ruleToAdd; // Okay to create anew.
506         }
507         if (Flags.modesUi()) {
508             if (!Objects.equals(ruleToRestore.pkg, pkg)
509                     || !Objects.equals(ruleToRestore.component, azrToAdd.getOwner())) {
510                 // Apps are not allowed to change the owner via updateAutomaticZenRule(). Thus, if
511                 // they have to, delete+add is their only option.
512                 return ruleToAdd;
513             }
514         }
515 
516         // "Preserve" the previous rule by considering the azrToAdd an update instead.
517         // Only app-modifiable fields will actually be modified.
518         populateZenRule(pkg, azrToAdd, config, ruleToRestore, origin, /* isNew= */ false);
519         return ruleToRestore;
520     }
521 
522     /**
523      * Possibly delete built-in rules if a more suitable rule is added or updated.
524      *
525      * <p>Today, this is done in one case: delete a disabled "Sleeping" rule if a Bedtime Mode is
526      * added (or an existing mode is turned into {@link AutomaticZenRule#TYPE_BEDTIME}, when
527      * upgrading). Because only the {@code config_systemWellbeing} package is allowed to use rules
528      * of this type, this will not trigger wantonly.
529      *
530      * @param oldRule If non-null, {@code rule} is updating {@code oldRule}. Otherwise,
531      *                {@code rule} is being added.
532      */
maybeReplaceDefaultRule(ZenModeConfig config, @Nullable ZenRule oldRule, AutomaticZenRule rule)533     private static void maybeReplaceDefaultRule(ZenModeConfig config, @Nullable ZenRule oldRule,
534             AutomaticZenRule rule) {
535         if (rule.getType() == AutomaticZenRule.TYPE_BEDTIME
536                 && (oldRule == null || oldRule.type != rule.getType())) {
537             // Note: we must not verify canManageAutomaticZenRule here, since most likely they
538             // won't have the same owner (sleeping - system; bedtime - DWB).
539             ZenRule sleepingRule = config.automaticRules.get(
540                     ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID);
541             if (sleepingRule != null
542                     && !sleepingRule.enabled
543                     && !sleepingRule.isUserModified()) {
544                 config.automaticRules.remove(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID);
545             }
546         }
547     }
548 
updateAutomaticZenRule(UserHandle user, String ruleId, AutomaticZenRule automaticZenRule, @ConfigOrigin int origin, String reason, int callingUid)549     public boolean updateAutomaticZenRule(UserHandle user, String ruleId,
550             AutomaticZenRule automaticZenRule, @ConfigOrigin int origin, String reason,
551             int callingUid) {
552         checkManageRuleOrigin("updateAutomaticZenRule", origin);
553         if (ruleId == null) {
554             throw new IllegalArgumentException("ruleId cannot be null");
555         }
556         synchronized (mConfigLock) {
557             ZenModeConfig config = getConfigLocked(user);
558             if (config == null) return false;
559             if (DEBUG) {
560                 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule
561                         + " reason=" + reason);
562             }
563             ZenModeConfig.ZenRule oldRule = config.automaticRules.get(ruleId);
564             if (oldRule == null || !canManageAutomaticZenRule(oldRule, callingUid)) {
565                 throw new SecurityException(
566                         "Cannot update rules not owned by your condition provider");
567             }
568             ZenModeConfig newConfig = config.copy();
569             ZenModeConfig.ZenRule newRule = requireNonNull(newConfig.automaticRules.get(ruleId));
570 
571             boolean updated = populateZenRule(newRule.pkg, automaticZenRule, newConfig, newRule,
572                     origin, /* isNew= */ false);
573             if (!updated) {
574                 // Bail out so we don't have the side effects of updating a rule (i.e. dropping
575                 // condition) when no changes happen.
576                 return true;
577             }
578 
579             if (Flags.modesUi()) {
580                 maybeReplaceDefaultRule(newConfig, oldRule, automaticZenRule);
581             }
582             return setConfigLocked(newConfig, origin, reason,
583                     newRule.component, true, callingUid);
584         }
585     }
586 
587     /**
588      * Create (or activate, or deactivate) an "implicit" {@link ZenRule} when an app that has
589      * Notification Policy Access but is not allowed to manage the global zen state
590      * calls {@link NotificationManager#setInterruptionFilter}.
591      *
592      * <p>When the {@code zenMode} is {@link Global#ZEN_MODE_OFF}, an existing implicit rule will be
593      * deactivated (if there is no implicit rule, the call will be ignored). For other modes, the
594      * rule's interruption filter will match the supplied {@code zenMode}. The policy of the last
595      * call to {@link NotificationManager#setNotificationPolicy} will be used (or, if never called,
596      * the global policy).
597      *
598      * <p>The created rule is owned by the calling package, but it has neither a
599      * {@link ConditionProviderService} nor an associated
600      * {@link AutomaticZenRule#configurationActivity}.
601      *
602      * @param zenMode one of the {@code Global#ZEN_MODE_x} values
603      */
applyGlobalZenModeAsImplicitZenRule(UserHandle user, String callingPkg, int callingUid, int zenMode)604     void applyGlobalZenModeAsImplicitZenRule(UserHandle user, String callingPkg, int callingUid,
605             int zenMode) {
606         synchronized (mConfigLock) {
607             ZenModeConfig config = getConfigLocked(user);
608             if (config == null) {
609                 return;
610             }
611             ZenModeConfig newConfig = config.copy();
612             ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg));
613             if (zenMode == Global.ZEN_MODE_OFF) {
614                 // Deactivate implicit rule if it exists and is active; otherwise ignore.
615                 if (rule != null) {
616                     Condition deactivated = new Condition(rule.conditionId,
617                             mContext.getString(R.string.zen_mode_implicit_deactivated),
618                             STATE_FALSE);
619                     setAutomaticZenRuleStateLocked(newConfig, Collections.singletonList(rule),
620                             deactivated, ORIGIN_APP,
621                             "applyGlobalZenModeAsImplicitZenRule: " + callingPkg, callingUid);
622                 }
623             } else {
624                 // Either create a new rule with a default ZenPolicy, or update an existing rule's
625                 // filter value. In both cases, also activate (and unsnooze) it.
626                 if (rule == null) {
627                     rule = newImplicitZenRule(callingPkg);
628 
629                     // For new implicit rules, create a policy matching the current global
630                     // (manual rule) settings, for consistency with the policy that
631                     // would apply if changing the global interruption filter. We only do this
632                     // for newly created rules, as existing rules have a pre-existing policy
633                     // (whether initialized here or set via app or user).
634                     rule.zenPolicy = config.getZenPolicy().copy();
635                     newConfig.automaticRules.put(rule.id, rule);
636                 } else {
637                     if (Flags.modesUi()) {
638                         updateImplicitZenRuleNameAndDescription(rule);
639                     }
640                 }
641 
642                 // If the user has changed the rule's *zenMode*, then don't let app overwrite it.
643                 // We allow the update if the user has only changed other aspects of the rule.
644                 if ((rule.userModifiedFields & AutomaticZenRule.FIELD_INTERRUPTION_FILTER) == 0) {
645                     rule.zenMode = zenMode;
646                 }
647                 rule.condition = new Condition(rule.conditionId,
648                         mContext.getString(R.string.zen_mode_implicit_activated),
649                         STATE_TRUE);
650                 rule.resetConditionOverride();
651 
652                 setConfigLocked(newConfig, /* triggeringComponent= */ null, ORIGIN_APP,
653                         "applyGlobalZenModeAsImplicitZenRule", callingUid);
654             }
655         }
656     }
657 
658     /**
659      * Create (or update) an "implicit" {@link ZenRule} when an app that has Notification Policy
660      * Access but is not allowed to manage the global zen state calls
661      * {@link NotificationManager#setNotificationPolicy}.
662      *
663      * <p>The created rule is owned by the calling package and has the {@link ZenPolicy}
664      * corresponding to the supplied {@code policy}, but it has neither a
665      * {@link ConditionProviderService} nor an associated
666      * {@link AutomaticZenRule#configurationActivity}. Its zen mode will be set to
667      * {@link Global#ZEN_MODE_IMPORTANT_INTERRUPTIONS}.
668      */
applyGlobalPolicyAsImplicitZenRule(UserHandle user, String callingPkg, int callingUid, NotificationManager.Policy policy)669     void applyGlobalPolicyAsImplicitZenRule(UserHandle user, String callingPkg, int callingUid,
670             NotificationManager.Policy policy) {
671         synchronized (mConfigLock) {
672             ZenModeConfig config = getConfigLocked(user);
673             if (config == null) {
674                 return;
675             }
676             ZenModeConfig newConfig = config.copy();
677             boolean isNew = false;
678             ZenRule rule = newConfig.automaticRules.get(implicitRuleId(callingPkg));
679             if (rule == null) {
680                 isNew = true;
681                 rule = newImplicitZenRule(callingPkg);
682                 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
683                 newConfig.automaticRules.put(rule.id, rule);
684             } else {
685                 if (Flags.modesUi()) {
686                     updateImplicitZenRuleNameAndDescription(rule);
687                 }
688             }
689 
690             // If the user has changed the rule's *ZenPolicy*, then don't let app overwrite it.
691             // We allow the update if the user has only changed other aspects of the rule.
692             if (rule.zenPolicyUserModifiedFields == 0) {
693                 ZenPolicy newZenPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy);
694                 if (isNew) {
695                     // For new rules only, fill anything underspecified in the new policy with
696                     // values from the global configuration, for consistency with the policy that
697                     // would take effect if changing the global policy.
698                     // Note that NotificationManager.Policy cannot have any unset priority
699                     // categories, but *can* have unset visual effects, which is why we do this.
700                     newZenPolicy = config.getZenPolicy().overwrittenWith(newZenPolicy);
701                 }
702                 updatePolicy(
703                         newConfig,
704                         rule,
705                         newZenPolicy,
706                         /* updateBitmask= */ false,
707                         isNew);
708 
709                 setConfigLocked(newConfig, /* triggeringComponent= */ null, ORIGIN_APP,
710                         "applyGlobalPolicyAsImplicitZenRule", callingUid);
711             }
712         }
713     }
714 
715     /**
716      * Returns the {@link Policy} associated to the "implicit" {@link ZenRule} of a package that has
717      * Notification Policy Access but is not allowed to manage the global zen state.
718      *
719      * <p>If the implicit rule doesn't exist, or it doesn't specify a {@link ZenPolicy} (because the
720      * app never called {@link NotificationManager#setNotificationPolicy}) then the default policy
721      * is returned (i.e. same as {@link #getNotificationPolicy}.
722      *
723      * <p>Any unset values in the {@link ZenPolicy} will be mapped to their current defaults.
724      */
725     @Nullable
getNotificationPolicyFromImplicitZenRule(UserHandle user, String callingPkg)726     Policy getNotificationPolicyFromImplicitZenRule(UserHandle user, String callingPkg) {
727         synchronized (mConfigLock) {
728             ZenModeConfig config = getConfigLocked(user);
729             if (config == null) {
730                 return null;
731             }
732             ZenRule implicitRule = config.automaticRules.get(implicitRuleId(callingPkg));
733             if (implicitRule != null && implicitRule.zenPolicy != null) {
734                 // toNotificationPolicy takes defaults from config, and technically those are not
735                 // the defaults that would apply if any fields were unset. However, all rules should
736                 // have all fields set in their ZenPolicy objects upon rule creation, so in
737                 // practice, this is only filling in the areChannelsBypassingDnd field, which is a
738                 // state rather than a part of the policy.
739                 return config.toNotificationPolicy(implicitRule.zenPolicy);
740             } else {
741                 return getNotificationPolicy(user);
742             }
743         }
744     }
745 
746     /**
747      * Creates an empty {@link ZenRule} to be used as the implicit rule for {@code pkg}.
748      * Both {@link ZenRule#zenMode} and {@link ZenRule#zenPolicy} are unset.
749      */
newImplicitZenRule(String pkg)750     private ZenRule newImplicitZenRule(String pkg) {
751         ZenRule rule = new ZenRule();
752         rule.id = implicitRuleId(pkg);
753         rule.pkg = pkg;
754         rule.creationTime = mClock.millis();
755         updateImplicitZenRuleNameAndDescription(rule);
756         rule.type = AutomaticZenRule.TYPE_OTHER;
757         rule.condition = null;
758         rule.conditionId = new Uri.Builder()
759                 .scheme(Condition.SCHEME)
760                 .authority(PACKAGE_ANDROID)
761                 .appendPath("implicit")
762                 .appendPath(pkg)
763                 .build();
764         rule.enabled = true;
765         rule.component = null;
766         rule.configurationActivity = null;
767         return rule;
768     }
769 
updateImplicitZenRuleNameAndDescription(ZenRule rule)770     private void updateImplicitZenRuleNameAndDescription(ZenRule rule) {
771         checkArgument(isImplicitRuleId(rule.id));
772         requireNonNull(rule.pkg, "Implicit rule is not associated to package yet!");
773 
774         String pkgAppName = Binder.withCleanCallingIdentity(() -> {
775             try {
776                 ApplicationInfo applicationInfo = mPm.getApplicationInfo(rule.pkg, 0);
777                 return applicationInfo.loadLabel(mPm).toString();
778             } catch (PackageManager.NameNotFoundException e) {
779                 // Should not happen. When creating it's the app calling us, and when updating
780                 // the rule would've been deleted if the package was removed.
781                 Slog.e(TAG, "Package not found when updating implicit zen rule name", e);
782                 return null;
783             }
784         });
785 
786         if (pkgAppName != null) {
787             if ((rule.userModifiedFields & AutomaticZenRule.FIELD_NAME) == 0) {
788                 if (Flags.modesUi()) {
789                     rule.name = mContext.getString(R.string.zen_mode_implicit_name, pkgAppName);
790                 } else {
791                     rule.name = pkgAppName;
792                 }
793             }
794             rule.triggerDescription = mContext.getString(
795                     R.string.zen_mode_implicit_trigger_description, pkgAppName);
796         } else if (rule.name == null) {
797             // We must give a new rule SOME name. But this path should never be hit.
798             rule.name = "Unknown";
799         }
800     }
801 
removeAutomaticZenRule(UserHandle user, String id, @ConfigOrigin int origin, String reason, int callingUid)802     boolean removeAutomaticZenRule(UserHandle user, String id, @ConfigOrigin int origin,
803             String reason, int callingUid) {
804         checkManageRuleOrigin("removeAutomaticZenRule", origin);
805         ZenModeConfig newConfig;
806         synchronized (mConfigLock) {
807             ZenModeConfig config = getConfigLocked(user);
808             if (config == null) return false;
809             newConfig = config.copy();
810             ZenRule ruleToRemove = newConfig.automaticRules.get(id);
811             if (ruleToRemove == null) return false;
812             if (canManageAutomaticZenRule(ruleToRemove, callingUid)) {
813                 newConfig.automaticRules.remove(id);
814                 maybePreserveRemovedRule(newConfig, ruleToRemove, origin);
815                 if (ruleToRemove.getPkg() != null
816                         && !PACKAGE_ANDROID.equals(ruleToRemove.getPkg())) {
817                     for (ZenRule currRule : newConfig.automaticRules.values()) {
818                         if (currRule.getPkg() != null
819                                 && currRule.getPkg().equals(ruleToRemove.getPkg())) {
820                             break; // no need to remove from cache
821                         }
822                     }
823                     mRulesUidCache.remove(getPackageUserKey(ruleToRemove.getPkg(), newConfig.user));
824                 }
825                 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
826             } else {
827                 throw new SecurityException(
828                         "Cannot delete rules not owned by your condition provider");
829             }
830             dispatchOnAutomaticRuleStatusChanged(
831                     config.user, ruleToRemove.getPkg(), id, AUTOMATIC_RULE_STATUS_REMOVED);
832             return setConfigLocked(newConfig, origin, reason, null, true, callingUid);
833         }
834     }
835 
removeAutomaticZenRules(UserHandle user, String packageName, @ConfigOrigin int origin, String reason, int callingUid)836     boolean removeAutomaticZenRules(UserHandle user, String packageName, @ConfigOrigin int origin,
837             String reason, int callingUid) {
838         checkManageRuleOrigin("removeAutomaticZenRules", origin);
839         ZenModeConfig newConfig;
840         synchronized (mConfigLock) {
841             ZenModeConfig config = getConfigLocked(user);
842             if (config == null) return false;
843             newConfig = config.copy();
844             for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
845                 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
846                 if (Objects.equals(rule.getPkg(), packageName)
847                         && canManageAutomaticZenRule(rule, callingUid)) {
848                     newConfig.automaticRules.removeAt(i);
849                     maybePreserveRemovedRule(newConfig, rule, origin);
850                 }
851             }
852             // If the system is clearing all rules this means DND access is revoked or the package
853             // was uninstalled, so also clear the preserved-deleted rules.
854             if (origin == ORIGIN_SYSTEM) {
855                 for (int i = newConfig.deletedRules.size() - 1; i >= 0; i--) {
856                     ZenRule rule = newConfig.deletedRules.get(newConfig.deletedRules.keyAt(i));
857                     if (Objects.equals(rule.getPkg(), packageName)) {
858                         newConfig.deletedRules.removeAt(i);
859                     }
860                 }
861             }
862             return setConfigLocked(newConfig, origin, reason, null, true, callingUid);
863         }
864     }
865 
maybePreserveRemovedRule(ZenModeConfig config, ZenRule ruleToRemove, @ConfigOrigin int origin)866     private void maybePreserveRemovedRule(ZenModeConfig config, ZenRule ruleToRemove,
867             @ConfigOrigin int origin) {
868         // If an app deletes a previously customized rule, keep it around to preserve
869         // the user's customization when/if it's recreated later.
870         // We don't try to preserve system-owned rules because their conditionIds (used as
871         // deletedRuleKey) are not stable. This is almost moot anyway because an app cannot
872         // delete a system-owned rule.
873         if (origin == ORIGIN_APP && ruleToRemove.isUserModified()
874                 && !PACKAGE_ANDROID.equals(ruleToRemove.pkg)) {
875             String deletedKey = ZenModeConfig.deletedRuleKey(ruleToRemove);
876             if (deletedKey != null) {
877                 ZenRule deletedRule = ruleToRemove.copy();
878                 deletedRule.deletionInstant = Instant.now(mClock);
879                 // If the rule is restored it shouldn't be active (or snoozed).
880                 deletedRule.condition = null;
881                 deletedRule.resetConditionOverride();
882                 // Overwrites a previously-deleted rule with the same conditionId, but that's okay.
883                 config.deletedRules.put(deletedKey, deletedRule);
884             }
885         }
886     }
887 
888     @Condition.State
getAutomaticZenRuleState(UserHandle user, String id, int callingUid)889     int getAutomaticZenRuleState(UserHandle user, String id, int callingUid) {
890         synchronized (mConfigLock) {
891             ZenModeConfig config = getConfigLocked(user);
892             if (config == null) {
893                 return Condition.STATE_UNKNOWN;
894             }
895             ZenRule rule = config.automaticRules.get(id);
896             if (rule == null || !canManageAutomaticZenRule(rule, callingUid)) {
897                 return Condition.STATE_UNKNOWN;
898             }
899             if (Flags.modesUi()) {
900                 return rule.isActive() ? STATE_TRUE : STATE_FALSE;
901             } else {
902                 // Buggy, does not consider snoozing!
903                 return rule.condition != null ? rule.condition.state : STATE_FALSE;
904             }
905         }
906     }
907 
setAutomaticZenRuleState(UserHandle user, String id, Condition condition, @ConfigOrigin int origin, int callingUid)908     void setAutomaticZenRuleState(UserHandle user, String id, Condition condition,
909             @ConfigOrigin int origin, int callingUid) {
910         checkSetRuleStateOrigin("setAutomaticZenRuleState(String id)", origin);
911         ZenModeConfig newConfig;
912         synchronized (mConfigLock) {
913             ZenModeConfig config = getConfigLocked(user);
914             if (config == null) return;
915 
916             newConfig = config.copy();
917             ZenRule rule = newConfig.automaticRules.get(id);
918             if (rule != null && canManageAutomaticZenRule(rule, callingUid)) {
919                 setAutomaticZenRuleStateLocked(newConfig, Collections.singletonList(rule),
920                         condition, origin, "setAzrState: " + rule.id, callingUid);
921             }
922         }
923     }
924 
setAutomaticZenRuleStateFromConditionProvider(UserHandle user, Uri ruleConditionId, Condition condition, @ConfigOrigin int origin, int callingUid)925     void setAutomaticZenRuleStateFromConditionProvider(UserHandle user, Uri ruleConditionId,
926             Condition condition, @ConfigOrigin int origin, int callingUid) {
927         checkSetRuleStateOrigin("setAutomaticZenRuleStateFromConditionProvider", origin);
928         ZenModeConfig newConfig;
929         synchronized (mConfigLock) {
930             ZenModeConfig config = getConfigLocked(user);
931             if (config == null) return;
932             newConfig = config.copy();
933 
934             List<ZenRule> matchingRules = findMatchingRules(newConfig, ruleConditionId, condition);
935             for (int i = matchingRules.size() - 1; i >= 0; i--) {
936                 if (!canManageAutomaticZenRule(matchingRules.get(i), callingUid)) {
937                     matchingRules.remove(i);
938                 }
939             }
940 
941             setAutomaticZenRuleStateLocked(newConfig, matchingRules, condition, origin,
942                     "setAzrStateFromCps: " + ruleConditionId, callingUid);
943         }
944     }
945 
946     @GuardedBy("mConfigLock")
setAutomaticZenRuleStateLocked(ZenModeConfig config, List<ZenRule> rules, Condition condition, @ConfigOrigin int origin, String reason, int callingUid)947     private void setAutomaticZenRuleStateLocked(ZenModeConfig config, List<ZenRule> rules,
948             Condition condition, @ConfigOrigin int origin, String reason, int callingUid) {
949         if (rules == null || rules.isEmpty()) return;
950 
951         if (!Flags.modesUi()) {
952             if (condition.source == SOURCE_USER_ACTION) {
953                 origin = ORIGIN_USER_IN_APP; // Although coming from app, it's actually from user.
954             }
955         }
956 
957         for (ZenRule rule : rules) {
958             applyConditionAndReconsiderOverride(rule, condition, origin);
959             setConfigLocked(config, rule.component, origin, reason, callingUid);
960         }
961     }
962 
applyConditionAndReconsiderOverride(ZenRule rule, Condition condition, int origin)963     private static void applyConditionAndReconsiderOverride(ZenRule rule, Condition condition,
964             int origin) {
965         if (Flags.modesUi()) {
966             if (isImplicitRuleId(rule.id)) {
967                 // Implicit rules do not use overrides, and always apply conditions directly.
968                 // This is compatible with the previous behavior (where the package set the
969                 // interruption filter, and no "snoozing" took place if the user changed it later).
970                 rule.condition = condition;
971                 rule.resetConditionOverride();
972             } else if (origin == ORIGIN_USER_IN_SYSTEMUI && condition != null
973                     && condition.source == SOURCE_USER_ACTION) {
974                 // Apply as override, instead of actual condition.
975                 // If the new override is the reverse of a previous (still active) override, try
976                 // removing the previous override, as long as the resulting state, based on the
977                 // previous owner-provided condition, is the desired one (active or inactive).
978                 // This allows the rule owner to resume controlling the rule after
979                 // snoozing-unsnoozing or activating-stopping.
980                 if (condition.state == STATE_TRUE) {
981                     rule.resetConditionOverride();
982                     if (!rule.isActive()) {
983                         rule.setConditionOverride(OVERRIDE_ACTIVATE);
984                     }
985                 } else if (condition.state == STATE_FALSE) {
986                     rule.resetConditionOverride();
987                     if (rule.isActive()) {
988                         rule.setConditionOverride(OVERRIDE_DEACTIVATE);
989                     }
990                 }
991             } else if (origin == ORIGIN_USER_IN_APP && condition != null
992                     && condition.source == SOURCE_USER_ACTION) {
993                 // Remove override and just apply the condition. Since the app is reporting that the
994                 // user asked for it, by definition it knows that, and will adjust its automatic
995                 // behavior accordingly -> no need to override.
996                 rule.condition = condition;
997                 rule.resetConditionOverride();
998             } else {
999                 // Update the condition, and check whether we can remove the override (if automatic
1000                 // and manual decisions agree).
1001                 rule.condition = condition;
1002                 rule.reconsiderConditionOverride();
1003             }
1004         } else {
1005             rule.condition = condition;
1006             rule.reconsiderConditionOverride();
1007         }
1008     }
1009 
findMatchingRules(ZenModeConfig config, Uri id, Condition condition)1010     private static List<ZenRule> findMatchingRules(ZenModeConfig config, Uri id,
1011             Condition condition) {
1012         List<ZenRule> matchingRules = new ArrayList<>();
1013         if (ruleMatches(id, condition, config.manualRule)) {
1014             matchingRules.add(config.manualRule);
1015         } else {
1016             for (ZenRule automaticRule : config.automaticRules.values()) {
1017                 if (ruleMatches(id, condition, automaticRule)) {
1018                     matchingRules.add(automaticRule);
1019                 }
1020             }
1021         }
1022         return matchingRules;
1023     }
1024 
ruleMatches(Uri id, Condition condition, ZenRule rule)1025     private static boolean ruleMatches(Uri id, Condition condition, ZenRule rule) {
1026         if (id == null || rule == null || rule.conditionId == null) return false;
1027         if (!rule.conditionId.equals(id)) return false;
1028         if (Objects.equals(condition, rule.condition)) return false;
1029         return true;
1030     }
1031 
getCurrentInstanceCount(UserHandle user, ComponentName cn)1032     public int getCurrentInstanceCount(UserHandle user, ComponentName cn) {
1033         if (cn == null) {
1034             return 0;
1035         }
1036         int count = 0;
1037         synchronized (mConfigLock) {
1038             ZenModeConfig config = getConfigLocked(user);
1039             if (config == null) return 0;
1040 
1041             for (ZenRule rule : config.automaticRules.values()) {
1042                 if (cn.equals(rule.component) || cn.equals(rule.configurationActivity)) {
1043                     count++;
1044                 }
1045             }
1046         }
1047         return count;
1048     }
1049 
1050     // Equivalent method to getCurrentInstanceCount, but for all rules associated with a specific
1051     // package rather than a condition provider service or activity.
getPackageRuleCount(UserHandle user, String pkg)1052     private int getPackageRuleCount(UserHandle user, String pkg) {
1053         if (pkg == null) {
1054             return 0;
1055         }
1056         int count = 0;
1057         synchronized (mConfigLock) {
1058             ZenModeConfig config = getConfigLocked(user);
1059             if (config == null) return 0;
1060 
1061             for (ZenRule rule : config.automaticRules.values()) {
1062                 if (pkg.equals(rule.getPkg())) {
1063                     count++;
1064                 }
1065             }
1066         }
1067         return count;
1068     }
1069 
canManageAutomaticZenRule(ZenRule rule, int callingUid)1070     public boolean canManageAutomaticZenRule(ZenRule rule, int callingUid) {
1071         if (!com.android.server.notification.Flags.fixCallingUidFromCps()) {
1072             // Old behavior: ignore supplied callingUid and instead obtain it here. Will be
1073             // incorrect if not currently handling a Binder call.
1074             callingUid = Binder.getCallingUid();
1075         }
1076 
1077         if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
1078             // Checked specifically, because checkCallingPermission() will fail.
1079             return true;
1080         } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
1081                 == PackageManager.PERMISSION_GRANTED) {
1082             return true;
1083         } else {
1084             String[] packages = mPm.getPackagesForUid(callingUid);
1085             if (packages != null) {
1086                 final int packageCount = packages.length;
1087                 for (int i = 0; i < packageCount; i++) {
1088                     if (packages[i].equals(rule.getPkg())) {
1089                         return true;
1090                     }
1091                 }
1092             }
1093             return false;
1094         }
1095     }
1096 
updateZenRulesOnLocaleChange()1097     void updateZenRulesOnLocaleChange() {
1098         updateRuleStringsForCurrentLocale(mContext, mDefaultConfig);
1099         synchronized (mConfigLock) {
1100             ZenModeConfig config = getConfigLocked(UserHandle.CURRENT);
1101             if (config == null) {
1102                 return;
1103             }
1104 
1105             ZenModeConfig newConfig = config.copy();
1106             boolean updated = false;
1107             for (ZenRule defaultRule : mDefaultConfig.automaticRules.values()) {
1108                 ZenRule currRule = newConfig.automaticRules.get(defaultRule.id);
1109                 // if default rule wasn't user-modified use localized name
1110                 // instead of previous system name
1111                 if (currRule != null
1112                         && (currRule.userModifiedFields & AutomaticZenRule.FIELD_NAME) == 0
1113                         && !defaultRule.name.equals(currRule.name)) {
1114                     if (DEBUG) {
1115                         Slog.d(TAG, "Locale change - updating default zen rule name "
1116                                 + "from " + currRule.name + " to " + defaultRule.name);
1117                     }
1118                     currRule.name = defaultRule.name;
1119                     updated = true;
1120                 }
1121             }
1122             if (Flags.modesUi()) {
1123                 for (ZenRule rule : newConfig.automaticRules.values()) {
1124                     if (SystemZenRules.isSystemOwnedRule(rule)) {
1125                         updated |= SystemZenRules.updateTriggerDescription(mContext, rule);
1126                     } else if (isImplicitRuleId(rule.id)) {
1127                         updateImplicitZenRuleNameAndDescription(rule);
1128                     }
1129                 }
1130             }
1131             if (updated) {
1132                 setConfigLocked(newConfig, null, ORIGIN_SYSTEM,
1133                         "updateZenRulesOnLocaleChange", Process.SYSTEM_UID);
1134             }
1135         }
1136     }
1137 
getServiceInfo(ComponentName owner)1138     private ServiceInfo getServiceInfo(ComponentName owner) {
1139         Intent queryIntent = new Intent();
1140         queryIntent.setComponent(owner);
1141         List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
1142                 queryIntent,
1143                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
1144                 UserHandle.getCallingUserId());
1145         if (installedServices != null) {
1146             for (int i = 0, count = installedServices.size(); i < count; i++) {
1147                 ResolveInfo resolveInfo = installedServices.get(i);
1148                 ServiceInfo info = resolveInfo.serviceInfo;
1149                 if (mServiceConfig.bindPermission.equals(info.permission)) {
1150                     return info;
1151                 }
1152             }
1153         }
1154         return null;
1155     }
1156 
getActivityInfo(ComponentName configActivity)1157     private ActivityInfo getActivityInfo(ComponentName configActivity) {
1158         Intent queryIntent = new Intent();
1159         queryIntent.setComponent(configActivity);
1160         List<ResolveInfo> installedComponents = mPm.queryIntentActivitiesAsUser(
1161                 queryIntent,
1162                 PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA,
1163                 UserHandle.getCallingUserId());
1164         if (installedComponents != null) {
1165             for (int i = 0, count = installedComponents.size(); i < count; i++) {
1166                 ResolveInfo resolveInfo = installedComponents.get(i);
1167                 return resolveInfo.activityInfo;
1168             }
1169         }
1170         return null;
1171     }
1172 
1173     /**
1174      * Populates a {@code ZenRule} with the content of the {@link AutomaticZenRule}. Can be used for
1175      * both rule creation or update (distinguished by the {@code isNew} parameter. The change is
1176      * applied differently depending on the origin; for example app-provided changes might be
1177      * ignored (if the rule was previously customized by the user), while user-provided changes
1178      * update the user-modified bitmasks for any modifications.
1179      *
1180      * <p>Returns {@code true} if the rule was modified. Note that this is not equivalent to
1181      * {@link ZenRule#equals} or {@link AutomaticZenRule#equals}, for various reasons:
1182      * <ul>
1183      *     <li>some metadata-related fields are not considered
1184      *     <li>some fields (like {@code condition} are normally reset, and ignored for this result
1185      *     <li>an app may provide changes that are not actually applied, as described above
1186      * </ul>
1187      *
1188      * <p>The rule's {@link ZenRule#condition} is cleared (meaning that an active rule will be
1189      * deactivated) unless the update has origin == {@link ZenModeConfig#ORIGIN_USER_IN_SYSTEMUI}.
1190      */
1191     @GuardedBy("mConfigLock")
populateZenRule(String pkg, AutomaticZenRule azr, ZenModeConfig config, ZenRule rule, @ConfigOrigin int origin, boolean isNew)1192     private boolean populateZenRule(String pkg, AutomaticZenRule azr, ZenModeConfig config,
1193             ZenRule rule, @ConfigOrigin int origin, boolean isNew) {
1194 
1195         boolean modified = false;
1196         // These values can always be edited by the app, so we apply changes immediately.
1197         if (isNew) {
1198             rule.id = ZenModeConfig.newRuleId();
1199             rule.creationTime = mClock.millis();
1200             rule.component = azr.getOwner();
1201             rule.pkg = pkg;
1202             modified = true;
1203         }
1204 
1205         // Allow updating the CPS backing system rules (e.g. for custom manual -> schedule)
1206         if (Flags.modesUi()
1207                 && (origin == ORIGIN_SYSTEM || origin == ORIGIN_USER_IN_SYSTEMUI)
1208                 && Objects.equals(rule.pkg, SystemZenRules.PACKAGE_ANDROID)
1209                 && !Objects.equals(rule.component, azr.getOwner())) {
1210             rule.component = azr.getOwner();
1211             modified = true;
1212         }
1213 
1214         if (Flags.modesUi()) {
1215             if (!azr.isEnabled() && (isNew || rule.enabled)) {
1216                 // Creating a rule as disabled, or disabling a previously enabled rule.
1217                 // Record whodunit.
1218                 rule.disabledOrigin = origin;
1219             } else if (azr.isEnabled()) {
1220                 // Enabling or previously enabled. Clear disabler.
1221                 rule.disabledOrigin = ORIGIN_UNKNOWN;
1222             }
1223         }
1224 
1225         if (!Objects.equals(rule.conditionId, azr.getConditionId())) {
1226             rule.conditionId = azr.getConditionId();
1227             modified = true;
1228         }
1229         // This can be removed when {@link Flags#modesUi} is fully ramped up
1230         final boolean isWatch =
1231                 mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_WATCH);
1232         boolean shouldPreserveCondition =
1233                 (Flags.modesUi() || isWatch)
1234                         && !isNew
1235                         && origin == ORIGIN_USER_IN_SYSTEMUI
1236                         && rule.enabled == azr.isEnabled()
1237                         && rule.conditionId != null
1238                         && rule.condition != null
1239                         && rule.conditionId.equals(rule.condition.id);
1240         if (!shouldPreserveCondition) {
1241             // Do not update 'modified'. If only this changes we treat it as a no-op updateAZR.
1242             rule.condition = null;
1243         }
1244 
1245         if (rule.enabled != azr.isEnabled()) {
1246             rule.enabled = azr.isEnabled();
1247             rule.resetConditionOverride();
1248             modified = true;
1249         }
1250         if (!Objects.equals(rule.configurationActivity, azr.getConfigurationActivity())) {
1251             rule.configurationActivity = azr.getConfigurationActivity();
1252             modified = true;
1253         }
1254         if (rule.allowManualInvocation != azr.isManualInvocationAllowed()) {
1255             rule.allowManualInvocation = azr.isManualInvocationAllowed();
1256             modified = true;
1257         }
1258         if (!Flags.modesUi()) {
1259             String iconResName = drawableResIdToResName(rule.pkg, azr.getIconResId());
1260             if (!Objects.equals(rule.iconResName, iconResName)) {
1261                 rule.iconResName = iconResName;
1262                 modified = true;
1263             }
1264         }
1265         if (!Objects.equals(rule.triggerDescription, azr.getTriggerDescription())) {
1266             rule.triggerDescription = azr.getTriggerDescription();
1267             modified = true;
1268         }
1269         if (rule.type != azr.getType()) {
1270             rule.type = azr.getType();
1271             modified = true;
1272         }
1273 
1274         // Name is treated differently than other values:
1275         // App is allowed to update name if the name was not modified by the user (even if
1276         // other values have been modified). In this way, if the locale of an app changes,
1277         // i18n of the rule name can still occur even if the user has customized the rule
1278         // contents.
1279         String previousName = rule.name;
1280         if (isNew || doesOriginAlwaysUpdateValues(origin)
1281                 || (rule.userModifiedFields & AutomaticZenRule.FIELD_NAME) == 0) {
1282             rule.name = azr.getName();
1283             modified |= !Objects.equals(rule.name, previousName);
1284         }
1285 
1286         // For the remaining values, rules can always have all values updated if:
1287         // * the rule is newly added, or
1288         // * the request comes from an origin that can always update values, like the user, or
1289         // * the rule has not yet been user modified, and thus can be updated by the app.
1290         boolean updateValues = isNew || doesOriginAlwaysUpdateValues(origin)
1291                 || !rule.isUserModified();
1292 
1293         // For all other values, if updates are not allowed, we discard the update.
1294         if (!updateValues) {
1295             return modified;
1296         }
1297 
1298         // Updates the bitmasks if the origin of the change is the user.
1299         boolean updateBitmask = (origin == ORIGIN_USER_IN_SYSTEMUI);
1300 
1301         if (updateBitmask && !TextUtils.equals(previousName, azr.getName())) {
1302             rule.userModifiedFields |= AutomaticZenRule.FIELD_NAME;
1303         }
1304         int newZenMode = NotificationManager.zenModeFromInterruptionFilter(
1305                 azr.getInterruptionFilter(), Global.ZEN_MODE_OFF);
1306         if (rule.zenMode != newZenMode) {
1307             rule.zenMode = newZenMode;
1308             if (updateBitmask) {
1309                 rule.userModifiedFields |= AutomaticZenRule.FIELD_INTERRUPTION_FILTER;
1310             }
1311             modified = true;
1312         }
1313 
1314         if (Flags.modesUi()) {
1315             String iconResName = drawableResIdToResName(rule.pkg, azr.getIconResId());
1316             if (!Objects.equals(rule.iconResName, iconResName)) {
1317                 rule.iconResName = iconResName;
1318                 if (updateBitmask) {
1319                     rule.userModifiedFields |= AutomaticZenRule.FIELD_ICON;
1320                 }
1321                 modified = true;
1322             }
1323         }
1324 
1325         // Updates the bitmask and values for all policy fields, based on the origin.
1326         modified |= updatePolicy(config, rule, azr.getZenPolicy(), updateBitmask, isNew);
1327 
1328         // Updates the bitmask and values for all device effect fields, based on the origin.
1329         modified |= updateZenDeviceEffects(rule, azr.getDeviceEffects(),
1330                 origin == ORIGIN_APP, updateBitmask);
1331 
1332         return modified;
1333     }
1334 
1335     /**
1336      * Returns true when fields can always be updated, based on the provided origin of an AZR
1337      * change. (Note that regardless of origin, fields can always be updated if they're not already
1338      * user modified.)
1339      */
doesOriginAlwaysUpdateValues(@onfigOrigin int origin)1340     private static boolean doesOriginAlwaysUpdateValues(@ConfigOrigin int origin) {
1341         return origin == ORIGIN_USER_IN_SYSTEMUI || origin == ORIGIN_SYSTEM;
1342     }
1343 
1344     /**
1345      * Modifies the {@link ZenPolicy} associated to a new or updated ZenRule.
1346      *
1347      * <p>The update takes any set fields in {@code newPolicy} as new policy settings for the
1348      * provided {@code ZenRule}, keeping any pre-existing settings from {@code zenRule.zenPolicy}
1349      * for any unset policy fields in {@code newPolicy}. The user-modified bitmask is updated to
1350      * reflect the changes being applied (if applicable, i.e. if the update is from the user).
1351      *
1352      * <p>Returns {@code true} if the policy of the rule was modified.
1353      */
1354     @GuardedBy("mConfigLock")
updatePolicy(ZenModeConfig config, ZenRule zenRule, @Nullable ZenPolicy newPolicy, boolean updateBitmask, boolean isNew)1355     private boolean updatePolicy(ZenModeConfig config, ZenRule zenRule,
1356             @Nullable ZenPolicy newPolicy, boolean updateBitmask, boolean isNew) {
1357         if (newPolicy == null) {
1358             if (isNew) {
1359                 // Newly created rule with no provided policy; fill in with the default.
1360                 zenRule.zenPolicy =
1361                         (Flags.modesUi() ? mDefaultConfig.getZenPolicy() : config.getZenPolicy())
1362                                 .copy();
1363                 return true;
1364             }
1365             // Otherwise, a null policy means no policy changes, so we can stop here.
1366             return false;
1367         }
1368 
1369         // If oldPolicy is null, we compare against the default policy when determining which
1370         // fields in the bitmask should be marked as updated.
1371         ZenPolicy oldPolicy = zenRule.zenPolicy != null
1372                 ? zenRule.zenPolicy
1373                 : (Flags.modesUi() ? mDefaultConfig.getZenPolicy() : config.getZenPolicy());
1374 
1375         // If this is updating a rule rather than creating a new one, keep any fields from the
1376         // old policy if they are unspecified in the new policy. For newly created rules, oldPolicy
1377         // has been set to the default settings above, so any unspecified fields in a newly created
1378         // policy are filled with default values. Then use the fully-specified version of the new
1379         // policy for comparison below.
1380         //
1381         // Although we do not expect a policy update from the user to contain any unset fields,
1382         // filling in fields here also guards against any unset fields counting as a "diff" when
1383         // comparing fields for bitmask editing below.
1384         newPolicy = oldPolicy.overwrittenWith(newPolicy);
1385         zenRule.zenPolicy = newPolicy;
1386 
1387         if (updateBitmask) {
1388             int userModifiedFields = zenRule.zenPolicyUserModifiedFields;
1389             if (oldPolicy.getPriorityMessageSenders() != newPolicy.getPriorityMessageSenders()) {
1390                 userModifiedFields |= ZenPolicy.FIELD_MESSAGES;
1391             }
1392             if (oldPolicy.getPriorityCallSenders() != newPolicy.getPriorityCallSenders()) {
1393                 userModifiedFields |= ZenPolicy.FIELD_CALLS;
1394             }
1395             if (oldPolicy.getPriorityConversationSenders()
1396                     != newPolicy.getPriorityConversationSenders()) {
1397                 userModifiedFields |= ZenPolicy.FIELD_CONVERSATIONS;
1398             }
1399             if (oldPolicy.getPriorityChannelsAllowed() != newPolicy.getPriorityChannelsAllowed()) {
1400                 userModifiedFields |= ZenPolicy.FIELD_ALLOW_CHANNELS;
1401             }
1402             if (oldPolicy.getPriorityCategoryReminders()
1403                     != newPolicy.getPriorityCategoryReminders()) {
1404                 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_REMINDERS;
1405             }
1406             if (oldPolicy.getPriorityCategoryEvents() != newPolicy.getPriorityCategoryEvents()) {
1407                 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_EVENTS;
1408             }
1409             if (oldPolicy.getPriorityCategoryRepeatCallers()
1410                     != newPolicy.getPriorityCategoryRepeatCallers()) {
1411                 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_REPEAT_CALLERS;
1412             }
1413             if (oldPolicy.getPriorityCategoryAlarms() != newPolicy.getPriorityCategoryAlarms()) {
1414                 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_ALARMS;
1415             }
1416             if (oldPolicy.getPriorityCategoryMedia() != newPolicy.getPriorityCategoryMedia()) {
1417                 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_MEDIA;
1418             }
1419             if (oldPolicy.getPriorityCategorySystem() != newPolicy.getPriorityCategorySystem()) {
1420                 userModifiedFields |= ZenPolicy.FIELD_PRIORITY_CATEGORY_SYSTEM;
1421             }
1422             // Visual effects
1423             if (oldPolicy.getVisualEffectFullScreenIntent()
1424                     != newPolicy.getVisualEffectFullScreenIntent()) {
1425                 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_FULL_SCREEN_INTENT;
1426             }
1427             if (oldPolicy.getVisualEffectLights() != newPolicy.getVisualEffectLights()) {
1428                 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_LIGHTS;
1429             }
1430             if (oldPolicy.getVisualEffectPeek() != newPolicy.getVisualEffectPeek()) {
1431                 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_PEEK;
1432             }
1433             if (oldPolicy.getVisualEffectStatusBar() != newPolicy.getVisualEffectStatusBar()) {
1434                 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_STATUS_BAR;
1435             }
1436             if (oldPolicy.getVisualEffectBadge() != newPolicy.getVisualEffectBadge()) {
1437                 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_BADGE;
1438             }
1439             if (oldPolicy.getVisualEffectAmbient() != newPolicy.getVisualEffectAmbient()) {
1440                 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_AMBIENT;
1441             }
1442             if (oldPolicy.getVisualEffectNotificationList()
1443                     != newPolicy.getVisualEffectNotificationList()) {
1444                 userModifiedFields |= ZenPolicy.FIELD_VISUAL_EFFECT_NOTIFICATION_LIST;
1445             }
1446             zenRule.zenPolicyUserModifiedFields = userModifiedFields;
1447         }
1448 
1449         return !newPolicy.equals(oldPolicy);
1450     }
1451 
1452     /**
1453      * Modifies the {@link ZenDeviceEffects} associated to a new or updated ZenRule.
1454      *
1455      * <p>The new value is {@code newEffects}, while the user-modified bitmask is updated to reflect
1456      * the changes being applied (if applicable, i.e. if the update is from the user).
1457      *
1458      * <p>Apps cannot turn on hidden effects (those tagged as {@code @hide}), so those fields are
1459      * treated especially: for a new rule, they are blanked out; for an updated rule, previous
1460      * values are preserved.
1461      *
1462      * <p>Returns {@code true} if the device effects of the rule were modified.
1463      */
updateZenDeviceEffects(ZenRule zenRule, @Nullable ZenDeviceEffects newEffects, boolean isFromApp, boolean updateBitmask)1464     private static boolean updateZenDeviceEffects(ZenRule zenRule,
1465             @Nullable ZenDeviceEffects newEffects, boolean isFromApp, boolean updateBitmask) {
1466         // Same as with ZenPolicy, supplying null effects means keeping the previous ones.
1467         if (newEffects == null) {
1468             return false;
1469         }
1470 
1471         ZenDeviceEffects oldEffects = zenRule.zenDeviceEffects != null
1472                 ? zenRule.zenDeviceEffects
1473                 : new ZenDeviceEffects.Builder().build();
1474 
1475         if (isFromApp) {
1476             // Don't allow apps to toggle hidden (non-public-API) effects.
1477             newEffects =
1478                     new ZenDeviceEffects.Builder(newEffects)
1479                             .setShouldDisableAutoBrightness(
1480                                     oldEffects.shouldDisableAutoBrightness())
1481                             .setShouldDisableTapToWake(oldEffects.shouldDisableTapToWake())
1482                             .setShouldDisableTiltToWake(oldEffects.shouldDisableTiltToWake())
1483                             .setShouldDisableTouch(oldEffects.shouldDisableTouch())
1484                             .setShouldMinimizeRadioUsage(oldEffects.shouldMinimizeRadioUsage())
1485                             .setShouldMaximizeDoze(oldEffects.shouldMaximizeDoze())
1486                             .setShouldUseNightLight(oldEffects.shouldUseNightLight())
1487                             .setExtraEffects(oldEffects.getExtraEffects())
1488                             .build();
1489         }
1490 
1491         zenRule.zenDeviceEffects = newEffects;
1492 
1493         if (updateBitmask) {
1494             int userModifiedFields = zenRule.zenDeviceEffectsUserModifiedFields;
1495             if (oldEffects.shouldDisplayGrayscale() != newEffects.shouldDisplayGrayscale()) {
1496                 userModifiedFields |= ZenDeviceEffects.FIELD_GRAYSCALE;
1497             }
1498             if (oldEffects.shouldSuppressAmbientDisplay()
1499                     != newEffects.shouldSuppressAmbientDisplay()) {
1500                 userModifiedFields |= ZenDeviceEffects.FIELD_SUPPRESS_AMBIENT_DISPLAY;
1501             }
1502             if (oldEffects.shouldDimWallpaper() != newEffects.shouldDimWallpaper()) {
1503                 userModifiedFields |= ZenDeviceEffects.FIELD_DIM_WALLPAPER;
1504             }
1505             if (oldEffects.shouldUseNightMode() != newEffects.shouldUseNightMode()) {
1506                 userModifiedFields |= ZenDeviceEffects.FIELD_NIGHT_MODE;
1507             }
1508             if (oldEffects.shouldDisableAutoBrightness()
1509                     != newEffects.shouldDisableAutoBrightness()) {
1510                 userModifiedFields |= ZenDeviceEffects.FIELD_DISABLE_AUTO_BRIGHTNESS;
1511             }
1512             if (oldEffects.shouldDisableTapToWake() != newEffects.shouldDisableTapToWake()) {
1513                 userModifiedFields |= ZenDeviceEffects.FIELD_DISABLE_TAP_TO_WAKE;
1514             }
1515             if (oldEffects.shouldDisableTiltToWake() != newEffects.shouldDisableTiltToWake()) {
1516                 userModifiedFields |= ZenDeviceEffects.FIELD_DISABLE_TILT_TO_WAKE;
1517             }
1518             if (oldEffects.shouldDisableTouch() != newEffects.shouldDisableTouch()) {
1519                 userModifiedFields |= ZenDeviceEffects.FIELD_DISABLE_TOUCH;
1520             }
1521             if (oldEffects.shouldMinimizeRadioUsage() != newEffects.shouldMinimizeRadioUsage()) {
1522                 userModifiedFields |= ZenDeviceEffects.FIELD_MINIMIZE_RADIO_USAGE;
1523             }
1524             if (oldEffects.shouldMaximizeDoze() != newEffects.shouldMaximizeDoze()) {
1525                 userModifiedFields |= ZenDeviceEffects.FIELD_MAXIMIZE_DOZE;
1526             }
1527             if (oldEffects.shouldUseNightLight() != newEffects.shouldUseNightLight()) {
1528                 userModifiedFields |= ZenDeviceEffects.FIELD_NIGHT_LIGHT;
1529             }
1530             if (!Objects.equals(oldEffects.getExtraEffects(), newEffects.getExtraEffects())) {
1531                 userModifiedFields |= ZenDeviceEffects.FIELD_EXTRA_EFFECTS;
1532             }
1533             zenRule.zenDeviceEffectsUserModifiedFields = userModifiedFields;
1534         }
1535 
1536         return !newEffects.equals(oldEffects);
1537     }
1538 
zenRuleToAutomaticZenRule(ZenRule rule)1539     private AutomaticZenRule zenRuleToAutomaticZenRule(ZenRule rule) {
1540         return new AutomaticZenRule.Builder(rule.name, rule.conditionId)
1541                 .setManualInvocationAllowed(rule.allowManualInvocation)
1542                 .setPackage(rule.pkg)
1543                 .setCreationTime(rule.creationTime)
1544                 .setIconResId(drawableResNameToResId(rule.pkg, rule.iconResName))
1545                 .setType(rule.type)
1546                 .setZenPolicy(rule.zenPolicy)
1547                 .setDeviceEffects(rule.zenDeviceEffects)
1548                 .setEnabled(rule.enabled)
1549                 .setInterruptionFilter(
1550                         NotificationManager.zenModeToInterruptionFilter(rule.zenMode))
1551                 .setOwner(rule.component)
1552                 .setConfigurationActivity(rule.configurationActivity)
1553                 .setTriggerDescription(rule.triggerDescription)
1554                 .build();
1555     }
1556 
1557     // Update only the hasPriorityChannels state (aka areChannelsBypassingDnd) without modifying
1558     // any of the rest of the existing policy. This allows components that only want to modify
1559     // this bit (PreferencesHelper) to not have to adjust the rest of the policy.
updateHasPriorityChannels(UserHandle user, boolean hasPriorityChannels)1560     protected void updateHasPriorityChannels(UserHandle user, boolean hasPriorityChannels) {
1561         if (!Flags.modesUi()) {
1562             Log.wtf(TAG, "updateHasPriorityChannels called without modes_ui");
1563         }
1564         synchronized (mConfigLock) {
1565             ZenModeConfig config = getConfigLocked(user);
1566             if (config == null) return;
1567 
1568             // If it already matches, do nothing
1569             if (config.hasPriorityChannels == hasPriorityChannels) {
1570                 return;
1571             }
1572 
1573             ZenModeConfig newConfig = config.copy();
1574             newConfig.hasPriorityChannels = hasPriorityChannels;
1575             // The updated calculation of whether there are priority channels is always done by
1576             // the system, even if the event causing the calculation had a different origin.
1577             setConfigLocked(newConfig, null, ORIGIN_SYSTEM, "updateHasPriorityChannels",
1578                     Process.SYSTEM_UID);
1579         }
1580     }
1581 
1582     @SuppressLint("MissingPermission")
scheduleActivationBroadcast(String pkg, @UserIdInt int userId, String ruleId, boolean activated)1583     void scheduleActivationBroadcast(String pkg, @UserIdInt int userId, String ruleId,
1584             boolean activated) {
1585         if (CompatChanges.isChangeEnabled(
1586                 SEND_ACTIVATION_AZR_STATUSES, pkg, UserHandle.of(userId))) {
1587             dispatchOnAutomaticRuleStatusChanged(userId, pkg, ruleId, activated
1588                     ? AUTOMATIC_RULE_STATUS_ACTIVATED
1589                     : AUTOMATIC_RULE_STATUS_DEACTIVATED);
1590         } else {
1591             dispatchOnAutomaticRuleStatusChanged(
1592                     userId, pkg, ruleId, AUTOMATIC_RULE_STATUS_UNKNOWN);
1593         }
1594     }
1595 
scheduleEnabledBroadcast(String pkg, @UserIdInt int userId, String ruleId, boolean enabled)1596     void scheduleEnabledBroadcast(String pkg, @UserIdInt int userId, String ruleId,
1597             boolean enabled) {
1598         dispatchOnAutomaticRuleStatusChanged(userId, pkg, ruleId, enabled
1599                 ? AUTOMATIC_RULE_STATUS_ENABLED
1600                 : AUTOMATIC_RULE_STATUS_DISABLED);
1601     }
1602 
setManualZenMode(UserHandle user, int zenMode, Uri conditionId, @ConfigOrigin int origin, String reason, @Nullable String caller, int callingUid)1603     void setManualZenMode(UserHandle user, int zenMode, Uri conditionId, @ConfigOrigin int origin,
1604             String reason, @Nullable String caller, int callingUid) {
1605         setManualZenMode(user, zenMode, conditionId, origin, reason, caller, true /*setRingerMode*/,
1606                 callingUid);
1607     }
1608 
setManualZenMode(UserHandle user, int zenMode, Uri conditionId, @ConfigOrigin int origin, String reason, @Nullable String caller, boolean setRingerMode, int callingUid)1609     private void setManualZenMode(UserHandle user, int zenMode, Uri conditionId,
1610             @ConfigOrigin int origin, String reason, @Nullable String caller, boolean setRingerMode,
1611             int callingUid) {
1612         ZenModeConfig newConfig;
1613         synchronized (mConfigLock) {
1614             ZenModeConfig config = getConfigLocked(user);
1615             if (config == null) return;
1616 
1617             if (!Global.isValidZenMode(zenMode)) return;
1618             if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode)
1619                     + " conditionId=" + conditionId + " reason=" + reason
1620                     + " setRingerMode=" + setRingerMode);
1621             newConfig = config.copy();
1622             if (Flags.modesUi()) {
1623                 newConfig.manualRule.enabler = caller;
1624                 newConfig.manualRule.conditionId = conditionId != null ? conditionId : Uri.EMPTY;
1625                 newConfig.manualRule.pkg = PACKAGE_ANDROID;
1626                 newConfig.manualRule.zenMode = zenMode;
1627                 newConfig.manualRule.condition = new Condition(newConfig.manualRule.conditionId, "",
1628                         zenMode == Global.ZEN_MODE_OFF ? STATE_FALSE : STATE_TRUE,
1629                         origin == ORIGIN_USER_IN_SYSTEMUI ? SOURCE_USER_ACTION : SOURCE_UNKNOWN);
1630                 if (zenMode == Global.ZEN_MODE_OFF && origin != ORIGIN_USER_IN_SYSTEMUI) {
1631                     // User deactivation of DND means just turning off the manual DND rule.
1632                     // For API calls (different origin) keep old behavior of snoozing all rules.
1633                     for (ZenRule automaticRule : newConfig.automaticRules.values()) {
1634                         if (automaticRule.isActive()) {
1635                             automaticRule.setConditionOverride(OVERRIDE_DEACTIVATE);
1636                         }
1637                     }
1638                 }
1639             } else {
1640                 if (zenMode == Global.ZEN_MODE_OFF) {
1641                     newConfig.manualRule = null;
1642                     for (ZenRule automaticRule : newConfig.automaticRules.values()) {
1643                         if (automaticRule.isActive()) {
1644                             automaticRule.setConditionOverride(OVERRIDE_DEACTIVATE);
1645                         }
1646                     }
1647 
1648                 } else {
1649                     final ZenRule newRule = new ZenRule();
1650                     newRule.enabled = true;
1651                     newRule.zenMode = zenMode;
1652                     newRule.conditionId = conditionId;
1653                     newRule.enabler = caller;
1654                     newRule.allowManualInvocation = true;
1655                     newConfig.manualRule = newRule;
1656                 }
1657             }
1658             setConfigLocked(newConfig, origin, reason, null, setRingerMode, callingUid);
1659         }
1660     }
1661 
setManualZenRuleDeviceEffects(UserHandle user, ZenDeviceEffects deviceEffects, @ConfigOrigin int origin, String reason, int callingUid)1662     public void setManualZenRuleDeviceEffects(UserHandle user, ZenDeviceEffects deviceEffects,
1663             @ConfigOrigin int origin, String reason, int callingUid) {
1664         if (!Flags.modesUi()) {
1665             return;
1666         }
1667         ZenModeConfig newConfig;
1668         synchronized (mConfigLock) {
1669             ZenModeConfig config = getConfigLocked(user);
1670             if (config == null) return;
1671 
1672             if (DEBUG) Log.d(TAG, "updateManualRule " + deviceEffects
1673                     + " reason=" + reason
1674                     + " callingUid=" + callingUid);
1675             newConfig = config.copy();
1676 
1677             newConfig.manualRule.pkg = PACKAGE_ANDROID;
1678             newConfig.manualRule.zenDeviceEffects = deviceEffects;
1679             setConfigLocked(newConfig, origin, reason, null, true, callingUid);
1680         }
1681     }
1682 
dump(ProtoOutputStream proto)1683     void dump(ProtoOutputStream proto) {
1684         proto.write(ZenModeProto.ZEN_MODE, mZenMode);
1685         synchronized (mConfigLock) {
1686             if (mConfig.isManualActive()) {
1687                 mConfig.manualRule.dumpDebug(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
1688             }
1689             for (ZenRule rule : mConfig.automaticRules.values()) {
1690                 if (rule.isActive()) {
1691                     rule.dumpDebug(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
1692                 }
1693             }
1694             mConfig.toNotificationPolicy().dumpDebug(proto, ZenModeProto.POLICY);
1695             proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
1696         }
1697     }
1698 
dump(PrintWriter pw, String prefix)1699     public void dump(PrintWriter pw, String prefix) {
1700         pw.print(prefix);
1701         pw.print("mZenMode=");
1702         pw.println(Global.zenModeToString(mZenMode));
1703         pw.print(prefix);
1704         pw.println("mConsolidatedPolicy=" + mConsolidatedPolicy.toString());
1705         synchronized (mConfigLock) {
1706             final int N = mConfigs.size();
1707             for (int i = 0; i < N; i++) {
1708                 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
1709             }
1710         }
1711         pw.print(prefix); pw.print("mUser="); pw.println(mUser);
1712         synchronized (mConfigLock) {
1713             dump(pw, prefix, "mConfig", mConfig);
1714         }
1715 
1716         pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
1717         mFiltering.dump(pw, prefix);
1718         mConditions.dump(pw, prefix);
1719     }
1720 
dump(PrintWriter pw, String prefix, String var, ZenModeConfig config)1721     private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) {
1722         pw.print(prefix); pw.print(var); pw.print('=');
1723         pw.println(config);
1724     }
1725 
readXml(TypedXmlPullParser parser, boolean forRestore, int userId, @Nullable BackupRestoreEventLogger logger)1726     public boolean readXml(TypedXmlPullParser parser, boolean forRestore, int userId,
1727             @Nullable BackupRestoreEventLogger logger) throws XmlPullParserException, IOException {
1728         ZenModeConfig config = ZenModeConfig.readXml(parser, logger);
1729         String reason = "readXml";
1730         if (config != null) {
1731             if (forRestore) {
1732                 config.user = userId;
1733                 if (Flags.modesUi()) {
1734                     if (config.manualRule != null) {
1735                         config.manualRule.condition = null; // don't restore transient state
1736                     }
1737                 } else {
1738                     config.manualRule = null;  // don't restore the manual rule
1739                 }
1740             }
1741 
1742             // booleans to determine whether to reset the rules to the default rules
1743             boolean allRulesDisabled = true;
1744             boolean hasDefaultRules = config.automaticRules.containsAll(
1745                     ZenModeConfig.getDefaultRuleIds());
1746 
1747             long time = mClock.millis();
1748             if (config.automaticRules != null && config.automaticRules.size() > 0) {
1749                 for (ZenRule automaticRule : config.automaticRules.values()) {
1750                     if (forRestore) {
1751                         // don't restore transient state from restored automatic rules
1752                         automaticRule.condition = null;
1753                         automaticRule.resetConditionOverride();
1754                         automaticRule.creationTime = time;
1755                     }
1756 
1757                     allRulesDisabled &= !automaticRule.enabled;
1758 
1759                     // Upon upgrading to a version with modes_api enabled, keep all behaviors of
1760                     // rules with null ZenPolicies explicitly as a copy of the global policy.
1761                     if (config.version < ZenModeConfig.XML_VERSION_MODES_API) {
1762                         // Keep the manual ("global") policy that from config.
1763                         ZenPolicy manualRulePolicy = config.getZenPolicy();
1764                         if (automaticRule.zenPolicy == null) {
1765                             automaticRule.zenPolicy = manualRulePolicy;
1766                         } else {
1767                             // newPolicy is a policy with all unset fields in the rule's zenPolicy
1768                             // set to their values from the values in config. Then convert that back
1769                             // to ZenPolicy to store with the automatic zen rule.
1770                             automaticRule.zenPolicy =
1771                                     manualRulePolicy.overwrittenWith(automaticRule.zenPolicy);
1772                         }
1773                     }
1774 
1775                     if (Flags.modesUi() && config.version < ZenModeConfig.XML_VERSION_MODES_UI) {
1776                         // Clear icons from implicit rules. App icons are not suitable for some
1777                         // surfaces, so juse use a default (the user can select a different one).
1778                         if (ZenModeConfig.isImplicitRuleId(automaticRule.id)) {
1779                             automaticRule.iconResName = null;
1780                         }
1781                     }
1782                 }
1783             }
1784 
1785             if (!hasDefaultRules && allRulesDisabled
1786                     && (forRestore || config.version < ZenModeConfig.XML_VERSION_ZEN_UPGRADE)) {
1787                 // reset zen automatic rules to default on restore or upgrade if:
1788                 // - doesn't already have default rules and
1789                 // - all previous automatic rules were disabled
1790                 //
1791                 // Note: we don't need to check to avoid restoring the Sleeping rule if there is a
1792                 // TYPE_BEDTIME rule because the config is from an old version and thus by
1793                 // definition cannot have a rule with TYPE_BEDTIME (or any other type).
1794                 config.automaticRules = new ArrayMap<>();
1795                 for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
1796                     config.automaticRules.put(rule.id, rule.copy());
1797                 }
1798                 reason += ", reset to default rules";
1799             }
1800 
1801             if (Flags.modesUi()) {
1802                 SystemZenRules.maybeUpgradeRules(mContext, config);
1803             }
1804 
1805             if (forRestore) {
1806                 // Note: forBackup doesn't write deletedRules, but just in case.
1807                 config.deletedRules.clear();
1808             }
1809 
1810             if (Flags.modesUi() && config.automaticRules != null) {
1811                 ZenRule obsoleteEventsRule = config.automaticRules.get(
1812                         ZenModeConfig.EVENTS_OBSOLETE_RULE_ID);
1813                 if (obsoleteEventsRule != null && !obsoleteEventsRule.enabled) {
1814                     config.automaticRules.remove(ZenModeConfig.EVENTS_OBSOLETE_RULE_ID);
1815                 }
1816             }
1817 
1818             if (DEBUG) Log.d(TAG, reason);
1819             synchronized (mConfigLock) {
1820                 return setConfigLocked(config, null,
1821                         forRestore ? ORIGIN_RESTORE_BACKUP : ORIGIN_INIT, reason,
1822                         Process.SYSTEM_UID);
1823             }
1824         }
1825         return false;
1826     }
1827 
writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId, @Nullable BackupRestoreEventLogger logger)1828     public void writeXml(TypedXmlSerializer out, boolean forBackup, Integer version, int userId,
1829             @Nullable BackupRestoreEventLogger logger) throws IOException {
1830         synchronized (mConfigLock) {
1831             int successfulWrites = 0;
1832             int unsuccessfulWrites = 0;
1833             final int n = mConfigs.size();
1834             for (int i = 0; i < n; i++) {
1835                 if (forBackup && mConfigs.keyAt(i) != userId) {
1836                     continue;
1837                 }
1838                 try {
1839                     mConfigs.valueAt(i).writeXml(out, version, forBackup, logger);
1840                     successfulWrites++;
1841                 } catch (Exception e) {
1842                     Slog.e(TAG, "failed to write config", e);
1843                     unsuccessfulWrites++;
1844                 }
1845             }
1846             if (logger != null) {
1847                 logger.logItemsBackedUp(DATA_TYPE_ZEN_CONFIG, successfulWrites);
1848                 if (unsuccessfulWrites > 0) {
1849                     logger.logItemsBackupFailed(DATA_TYPE_ZEN_CONFIG,
1850                             unsuccessfulWrites, ERROR_XML_PARSING);
1851                 }
1852             }
1853         }
1854     }
1855 
1856     /**
1857      * @return user-specified default notification policy for priority only do not disturb
1858      */
1859     @Nullable
getNotificationPolicy(UserHandle user)1860     public Policy getNotificationPolicy(UserHandle user) {
1861         synchronized (mConfigLock) {
1862             if (Flags.modesMultiuser()) {
1863                 // Return a fallback (default) policy for users without a zen config.
1864                 // Note that zen updates (setPolicy, setFilter) won't be applied, so this is mostly
1865                 // about preventing NPEs for careless callers.
1866                 ZenModeConfig config = getConfigLocked(user);
1867                 return config != null
1868                         ? getNotificationPolicy(config)
1869                         : getNotificationPolicy(mDefaultConfig);
1870             } else {
1871                 return getNotificationPolicy(getConfigLocked(user));
1872             }
1873         }
1874     }
1875 
1876     @Nullable
getNotificationPolicy(@ullable ZenModeConfig config)1877     private static Policy getNotificationPolicy(@Nullable ZenModeConfig config) {
1878         return config == null ? null : config.toNotificationPolicy();
1879     }
1880 
1881     /**
1882      * Sets the global notification policy used for priority only do not disturb
1883      */
setNotificationPolicy(UserHandle user, Policy policy, @ConfigOrigin int origin, int callingUid)1884     public void setNotificationPolicy(UserHandle user, Policy policy, @ConfigOrigin int origin,
1885             int callingUid) {
1886         synchronized (mConfigLock) {
1887             if (policy == null) return;
1888             ZenModeConfig config = getConfigLocked(user);
1889             if (config == null) return;
1890 
1891             final ZenModeConfig newConfig = config.copy();
1892             if (!Flags.modesUi()) {
1893                 // Fix for b/337193321 -- propagate changes to notificationPolicy to rules where
1894                 // the user cannot edit zen policy to emulate the previous "inheritance".
1895                 ZenPolicy previousPolicy = ZenAdapters.notificationPolicyToZenPolicy(
1896                         newConfig.toNotificationPolicy());
1897                 ZenPolicy newPolicy = ZenAdapters.notificationPolicyToZenPolicy(policy);
1898 
1899                 newConfig.applyNotificationPolicy(policy);
1900 
1901                 if (!previousPolicy.equals(newPolicy)) {
1902                     for (ZenRule rule : newConfig.automaticRules.values()) {
1903                         if (!SystemZenRules.isSystemOwnedRule(rule)
1904                                 && rule.zenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1905                                 && (rule.zenPolicy == null || rule.zenPolicy.equals(previousPolicy)
1906                                         || rule.zenPolicy.equals(getDefaultZenPolicy()))) {
1907                             rule.zenPolicy = newPolicy;
1908                         }
1909                     }
1910                 }
1911             } else {
1912                 newConfig.applyNotificationPolicy(policy);
1913             }
1914             setConfigLocked(newConfig, null, origin, "setNotificationPolicy", callingUid);
1915         }
1916     }
1917 
1918     /**
1919      * Cleans up obsolete rules in the current {@link ZenModeConfig}.
1920      * <ul>
1921      *     <li>Rule instances whose owner is not installed.
1922      *     <li>Deleted rules that were deleted more than 30 days ago.
1923      *     <li>Implicit rules that haven't been used in 30 days (and have not been customized).
1924      * </ul>
1925      */
cleanUpZenRules()1926     private void cleanUpZenRules() {
1927         Instant keptRuleThreshold = mClock.instant().minus(DELETED_RULE_KEPT_FOR);
1928         synchronized (mConfigLock) {
1929             final ZenModeConfig newConfig = mConfig.copy();
1930 
1931             deleteRulesWithoutOwner(newConfig.automaticRules);
1932             deleteRulesWithoutOwner(newConfig.deletedRules);
1933 
1934             for (int i = newConfig.deletedRules.size() - 1; i >= 0; i--) {
1935                 ZenRule deletedRule = newConfig.deletedRules.valueAt(i);
1936                 if (deletedRule.deletionInstant == null
1937                         || deletedRule.deletionInstant.isBefore(keptRuleThreshold)) {
1938                     newConfig.deletedRules.removeAt(i);
1939                 }
1940             }
1941 
1942             if (Flags.modesUi() && Flags.modesCleanupImplicit()) {
1943                 deleteUnusedImplicitRules(newConfig.automaticRules);
1944             }
1945 
1946             if (!newConfig.equals(mConfig)) {
1947                 setConfigLocked(newConfig, null, ORIGIN_SYSTEM,
1948                         "cleanUpZenRules", Process.SYSTEM_UID);
1949             }
1950         }
1951     }
1952 
deleteRulesWithoutOwner(ArrayMap<String, ZenRule> ruleList)1953     private void deleteRulesWithoutOwner(ArrayMap<String, ZenRule> ruleList) {
1954         long currentTime = mClock.millis();
1955         if (ruleList != null) {
1956             for (int i = ruleList.size() - 1; i >= 0; i--) {
1957                 ZenRule rule = ruleList.valueAt(i);
1958                 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
1959                     try {
1960                         if (rule.getPkg() != null) {
1961                             mPm.getPackageInfo(rule.getPkg(), PackageManager.MATCH_ANY_USER);
1962                         }
1963                     } catch (PackageManager.NameNotFoundException e) {
1964                         ruleList.removeAt(i);
1965                     }
1966                 }
1967             }
1968         }
1969     }
1970 
deleteUnusedImplicitRules(ArrayMap<String, ZenRule> ruleList)1971     private void deleteUnusedImplicitRules(ArrayMap<String, ZenRule> ruleList) {
1972         if (ruleList == null) {
1973             return;
1974         }
1975         Instant deleteIfUnusedSince = mClock.instant().minus(IMPLICIT_RULE_KEPT_FOR);
1976 
1977         for (int i = ruleList.size() - 1; i >= 0; i--) {
1978             ZenRule rule = ruleList.valueAt(i);
1979             if (isImplicitRuleId(rule.id) && !rule.isUserModified()) {
1980                 if (rule.lastActivation == null) {
1981                     // This rule existed before we started tracking activation time. It *might* be
1982                     // in use. Set lastActivation=now so it has some time (IMPLICIT_RULE_KEPT_FOR)
1983                     // before being removed if truly unused.
1984                     rule.lastActivation = mClock.instant();
1985                 }
1986 
1987                 if (rule.lastActivation.isBefore(deleteIfUnusedSince)) {
1988                     ruleList.removeAt(i);
1989                 }
1990             }
1991         }
1992     }
1993 
1994     /**
1995      * @return a copy of the zen mode configuration
1996      */
getConfig()1997     public ZenModeConfig getConfig() {
1998         synchronized (mConfigLock) {
1999             return mConfig.copy();
2000         }
2001     }
2002 
2003     /**
2004      * @return a copy of the zen mode consolidated policy
2005      */
getConsolidatedNotificationPolicy()2006     public Policy getConsolidatedNotificationPolicy() {
2007         return mConsolidatedPolicy.copy();
2008     }
2009 
2010     /**
2011      * Returns a copy of the device default policy as a ZenPolicy object.
2012      */
2013     @VisibleForTesting
getDefaultZenPolicy()2014     protected ZenPolicy getDefaultZenPolicy() {
2015         return mDefaultConfig.getZenPolicy();
2016     }
2017 
2018     /**
2019      * Returns the {@link ZenModeConfig} corresponding to the supplied {@link UserHandle}.
2020      * The result will be {@link #mConfig} if the user is {@link UserHandle#CURRENT}, or the same
2021      * as {@link #mUser}, otherwise will be the corresponding entry in {@link #mConfigs}.
2022      *
2023      * <p>Remember to continue holding {@link #mConfigLock} while operating on the returned value.
2024      */
2025     @Nullable
2026     @GuardedBy("mConfigLock")
getConfigLocked(@onNull UserHandle user)2027     private ZenModeConfig getConfigLocked(@NonNull UserHandle user) {
2028         if (Flags.modesMultiuser()) {
2029             if (user.getIdentifier() == UserHandle.USER_CURRENT || user.getIdentifier() == mUser) {
2030                 return mConfig;
2031             } else {
2032                 return mConfigs.get(user.getIdentifier());
2033             }
2034         } else {
2035             return mConfig;
2036         }
2037     }
2038 
2039     @GuardedBy("mConfigLock")
setConfigLocked(ZenModeConfig config, @Nullable ComponentName triggeringComponent, @ConfigOrigin int origin, String reason, int callingUid)2040     private boolean setConfigLocked(ZenModeConfig config,
2041             @Nullable ComponentName triggeringComponent, @ConfigOrigin int origin, String reason,
2042             int callingUid) {
2043         return setConfigLocked(config, origin, reason, triggeringComponent, true /*setRingerMode*/,
2044                 callingUid);
2045     }
2046 
setConfig(ZenModeConfig config, @Nullable ComponentName triggeringComponent, @ConfigOrigin int origin, String reason, int callingUid)2047     void setConfig(ZenModeConfig config, @Nullable ComponentName triggeringComponent,
2048             @ConfigOrigin int origin, String reason, int callingUid) {
2049         synchronized (mConfigLock) {
2050             setConfigLocked(config, triggeringComponent, origin, reason, callingUid);
2051         }
2052     }
2053 
2054     @GuardedBy("mConfigLock")
setConfigLocked(ZenModeConfig config, @ConfigOrigin int origin, String reason, @Nullable ComponentName triggeringComponent, boolean setRingerMode, int callingUid)2055     private boolean setConfigLocked(ZenModeConfig config, @ConfigOrigin int origin,
2056             String reason, @Nullable ComponentName triggeringComponent, boolean setRingerMode,
2057             int callingUid) {
2058         final long identity = Binder.clearCallingIdentity();
2059         try {
2060             if (config == null || !config.isValid()) {
2061                 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
2062                 return false;
2063             }
2064             if (config.user != mUser) {
2065                 // simply store away for background users
2066                 synchronized (mConfigLock) {
2067                     mConfigs.put(config.user, config);
2068                 }
2069                 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
2070                 return true;
2071             }
2072             // handle CPS backed conditions - danger! may modify config
2073             mConditions.evaluateConfig(config, null, false /*processSubscriptions*/);
2074 
2075             synchronized (mConfigLock) {
2076                 mConfigs.put(config.user, config);
2077             }
2078             if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
2079             ZenLog.traceConfig(origin, reason, triggeringComponent, mConfig, config, callingUid);
2080 
2081             // send some broadcasts
2082             Policy newPolicy = getNotificationPolicy(config);
2083             boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig), newPolicy);
2084             if (policyChanged) {
2085                 dispatchOnPolicyChanged(newPolicy);
2086             }
2087             updateConfigAndZenModeLocked(config, origin, reason, setRingerMode, callingUid);
2088             mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
2089             return true;
2090         } catch (SecurityException e) {
2091             Log.wtf(TAG, "Invalid rule in config", e);
2092             return false;
2093         } finally {
2094             Binder.restoreCallingIdentity(identity);
2095         }
2096     }
2097 
2098     /**
2099      * Carries out a config update (if needed) and (re-)evaluates the zen mode value afterwards.
2100      * If logging is enabled, will also request logging of the outcome of this change if needed.
2101      */
2102     @GuardedBy("mConfigLock")
updateConfigAndZenModeLocked(ZenModeConfig config, @ConfigOrigin int origin, String reason, boolean setRingerMode, int callingUid)2103     private void updateConfigAndZenModeLocked(ZenModeConfig config, @ConfigOrigin int origin,
2104             String reason, boolean setRingerMode, int callingUid) {
2105         final boolean logZenModeEvents = mFlagResolver.isEnabled(
2106                 SystemUiSystemPropertiesFlags.NotificationFlags.LOG_DND_STATE_EVENTS);
2107         // Store (a copy of) all config and zen mode info prior to any changes taking effect
2108         ZenModeEventLogger.ZenModeInfo prevInfo = new ZenModeEventLogger.ZenModeInfo(
2109                 mZenMode, mConfig, mConsolidatedPolicy);
2110         if (!config.equals(mConfig)) {
2111             // Schedule broadcasts. Cannot be sent during boot, though.
2112             if (origin != ORIGIN_INIT) {
2113                 for (ZenRule rule : config.automaticRules.values()) {
2114                     ZenRule original = mConfig.automaticRules.get(rule.id);
2115                     if (original != null) {
2116                         if (original.enabled != rule.enabled) {
2117                             scheduleEnabledBroadcast(
2118                                     rule.getPkg(), config.user, rule.id, rule.enabled);
2119                         }
2120                         if (original.isActive() != rule.isActive()) {
2121                             scheduleActivationBroadcast(
2122                                     rule.getPkg(), config.user, rule.id, rule.isActive());
2123                         }
2124                     }
2125                 }
2126             }
2127 
2128             // Update last activation for rules that are being activated.
2129             if (Flags.modesUi() && Flags.modesCleanupImplicit()) {
2130                 Instant now = mClock.instant();
2131                 if (!mConfig.isManualActive() && config.isManualActive()) {
2132                     config.manualRule.lastActivation = now;
2133                 }
2134                 for (ZenRule rule : config.automaticRules.values()) {
2135                     ZenRule previousRule = mConfig.automaticRules.get(rule.id);
2136                     if (rule.isActive() && (previousRule == null || !previousRule.isActive())) {
2137                         rule.lastActivation = now;
2138                     }
2139                 }
2140             }
2141 
2142             mConfig = config;
2143             dispatchOnConfigChanged();
2144             updateAndApplyConsolidatedPolicyAndDeviceEffects(origin, reason);
2145         }
2146         final String val = Integer.toString(config.hashCode());
2147         Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
2148         evaluateZenModeLocked(origin, reason, setRingerMode);
2149         // After all changes have occurred, log if requested
2150         if (logZenModeEvents) {
2151             ZenModeEventLogger.ZenModeInfo newInfo = new ZenModeEventLogger.ZenModeInfo(
2152                     mZenMode, mConfig, mConsolidatedPolicy);
2153             mZenModeEventLogger.maybeLogZenChange(prevInfo, newInfo, callingUid,
2154                     origin);
2155         }
2156     }
2157 
getZenModeSetting()2158     private int getZenModeSetting() {
2159         return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
2160     }
2161 
2162     @VisibleForTesting
setZenModeSetting(int zen)2163     protected void setZenModeSetting(int zen) {
2164         Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
2165         ZenLog.traceSetZenMode(Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, -1),
2166                 "updated setting");
2167     }
2168 
getPreviousRingerModeSetting()2169     private int getPreviousRingerModeSetting() {
2170         return Global.getInt(mContext.getContentResolver(),
2171                 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
2172     }
2173 
setPreviousRingerModeSetting(Integer previousRingerLevel)2174     private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
2175         Global.putString(
2176                 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
2177                 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
2178     }
2179 
2180     @VisibleForTesting
2181     @GuardedBy("mConfigLock")
evaluateZenModeLocked(@onfigOrigin int origin, String reason, boolean setRingerMode)2182     protected void evaluateZenModeLocked(@ConfigOrigin int origin, String reason,
2183             boolean setRingerMode) {
2184         if (DEBUG) Log.d(TAG, "evaluateZenMode");
2185         if (mConfig == null) return;
2186         final int policyHashBefore = mConsolidatedPolicy == null ? 0
2187                 : mConsolidatedPolicy.hashCode();
2188         final int zenBefore = mZenMode;
2189         final int zen = computeZenMode();
2190         ZenLog.traceSetZenMode(zen, reason);
2191         mZenMode = zen;
2192         setZenModeSetting(mZenMode);
2193         updateAndApplyConsolidatedPolicyAndDeviceEffects(origin, reason);
2194         boolean shouldApplyToRinger = setRingerMode && (zen != zenBefore || (
2195                 zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
2196                         && policyHashBefore != mConsolidatedPolicy.hashCode()));
2197         mHandler.postUpdateRingerAndAudio(shouldApplyToRinger);
2198         if (zen != zenBefore) {
2199             mHandler.postDispatchOnZenModeChanged();
2200         }
2201     }
2202 
updateRingerAndAudio(boolean shouldApplyToRinger)2203     private void updateRingerAndAudio(boolean shouldApplyToRinger) {
2204         if (mAudioManager != null) {
2205             mAudioManager.updateRingerModeAffectedStreamsInternal();
2206         }
2207         if (shouldApplyToRinger) {
2208             applyZenToRingerMode();
2209         }
2210         applyRestrictions();
2211     }
2212 
computeZenMode()2213     private int computeZenMode() {
2214         synchronized (mConfigLock) {
2215             if (mConfig == null) return Global.ZEN_MODE_OFF;
2216             if (mConfig.isManualActive()) return mConfig.manualRule.zenMode;
2217             int zen = Global.ZEN_MODE_OFF;
2218             for (ZenRule automaticRule : mConfig.automaticRules.values()) {
2219                 if (automaticRule.isActive()) {
2220                     if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
2221                         zen = automaticRule.zenMode;
2222                     }
2223                 }
2224             }
2225             return zen;
2226         }
2227     }
2228 
2229     @GuardedBy("mConfigLock")
applyCustomPolicy(ZenModeConfig config, ZenPolicy policy, ZenRule rule, boolean useManualConfig)2230     private void applyCustomPolicy(ZenModeConfig config, ZenPolicy policy, ZenRule rule,
2231             boolean useManualConfig) {
2232         if (rule.zenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
2233             if (Flags.modesUi()) {
2234                 policy.apply(ZenPolicy.getBasePolicyInterruptionFilterNone());
2235             } else {
2236                 policy.apply(new ZenPolicy.Builder()
2237                         .disallowAllSounds()
2238                         .allowPriorityChannels(false)
2239                         .build());
2240             }
2241         } else if (rule.zenMode == Global.ZEN_MODE_ALARMS) {
2242             if (Flags.modesUi()) {
2243                 policy.apply(ZenPolicy.getBasePolicyInterruptionFilterAlarms());
2244             } else {
2245                 policy.apply(new ZenPolicy.Builder()
2246                         .disallowAllSounds()
2247                         .allowAlarms(true)
2248                         .allowMedia(true)
2249                         .allowPriorityChannels(false)
2250                         .build());
2251             }
2252         } else if (rule.zenPolicy != null) {
2253             policy.apply(rule.zenPolicy);
2254         } else {
2255             if (useManualConfig) {
2256                 // manual rule is configured using the settings stored directly in ZenModeConfig
2257                 policy.apply(config.getZenPolicy());
2258             } else {
2259                 // An active automatic rule with no specified policy inherits the device default
2260                 // settings as stored in mDefaultConfig. While the rule's policy fields should be
2261                 // set upon creation, this is a fallback to catch any that may have fallen through
2262                 // the cracks.
2263                 Log.wtf(TAG, "active automatic rule found with no specified policy: " + rule);
2264                 policy.apply(Flags.modesUi()
2265                         ? mDefaultConfig.getZenPolicy() : config.getZenPolicy());
2266             }
2267         }
2268     }
2269 
2270     @GuardedBy("mConfigLock")
updateAndApplyConsolidatedPolicyAndDeviceEffects(@onfigOrigin int origin, String reason)2271     private void updateAndApplyConsolidatedPolicyAndDeviceEffects(@ConfigOrigin int origin,
2272             String reason) {
2273         synchronized (mConfigLock) {
2274             if (mConfig == null) return;
2275             ZenPolicy policy = new ZenPolicy();
2276             ZenDeviceEffects.Builder deviceEffectsBuilder = new ZenDeviceEffects.Builder();
2277             if (mConfig.isManualActive()) {
2278                 applyCustomPolicy(mConfig, policy, mConfig.manualRule, true);
2279                 deviceEffectsBuilder.add(mConfig.manualRule.zenDeviceEffects);
2280             }
2281 
2282             for (ZenRule automaticRule : mConfig.automaticRules.values()) {
2283                 if (automaticRule.isActive()) {
2284                     // Active rules with INTERRUPTION_FILTER_ALL are not included in consolidated
2285                     // policy. This is relevant in case some other active rule has a more
2286                     // restrictive INTERRUPTION_FILTER but a more lenient ZenPolicy!
2287                     if (automaticRule.zenMode != Global.ZEN_MODE_OFF) {
2288                         applyCustomPolicy(mConfig, policy, automaticRule, false);
2289                     }
2290                     deviceEffectsBuilder.add(automaticRule.zenDeviceEffects);
2291                 }
2292             }
2293 
2294             // While mConfig.toNotificationPolicy fills in any unset fields from the provided
2295             // config (which, in this case is the manual "global" config), under modes API changes,
2296             // we should have no remaining unset fields: the manual policy gets every field from
2297             // the global policy, and each automatic rule has all policy fields filled in on
2298             // creation or update.
2299             // However, the piece of information that comes from mConfig that we must keep is the
2300             // areChannelsBypassingDnd bit, which is a state, rather than a policy, and even when
2301             // all policy fields are set, this state comes to the new policy from this call.
2302             Policy newPolicy = mConfig.toNotificationPolicy(policy);
2303             if (!Objects.equals(mConsolidatedPolicy, newPolicy)) {
2304                 mConsolidatedPolicy = newPolicy;
2305                 dispatchOnConsolidatedPolicyChanged(newPolicy);
2306                 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason);
2307             }
2308 
2309             // Prevent other rules from applying grayscale if Driving is active (but allow it
2310             // if _Driving itself_ wants grayscale).
2311             if (Flags.modesUi() && preventZenDeviceEffectsWhileDriving()) {
2312                 boolean hasActiveDriving = false;
2313                 boolean hasActiveDrivingWithGrayscale = false;
2314                 for (ZenRule rule : mConfig.automaticRules.values()) {
2315                     if (rule.isActive() && rule.type == TYPE_DRIVING) {
2316                         hasActiveDriving = true;
2317                         if (rule.zenDeviceEffects != null
2318                                 && rule.zenDeviceEffects.shouldDisplayGrayscale()) {
2319                             hasActiveDrivingWithGrayscale = true;
2320                             break; // Further rules won't affect decision.
2321                         }
2322                     }
2323                 }
2324                 if (hasActiveDriving && !hasActiveDrivingWithGrayscale) {
2325                     deviceEffectsBuilder.setShouldDisplayGrayscale(false);
2326                 }
2327             }
2328 
2329             ZenDeviceEffects deviceEffects = deviceEffectsBuilder.build();
2330             if (!deviceEffects.equals(mConsolidatedDeviceEffects)) {
2331                 mConsolidatedDeviceEffects = deviceEffects;
2332                 mHandler.postApplyDeviceEffects(origin);
2333             }
2334         }
2335     }
2336 
applyConsolidatedDeviceEffects(@onfigOrigin int source)2337     private void applyConsolidatedDeviceEffects(@ConfigOrigin int source) {
2338         DeviceEffectsApplier applier;
2339         ZenDeviceEffects effects;
2340         synchronized (mConfigLock) {
2341             applier = mDeviceEffectsApplier;
2342             effects = mConsolidatedDeviceEffects;
2343         }
2344         if (applier != null) {
2345             applier.apply(effects, source);
2346         }
2347     }
2348 
2349     /**
2350      * Apply changes to the <em>default</em> {@link ZenModeConfig} so that the rules included by
2351      * default (Events / Sleeping) support the latest Zen features and are ready for new users.
2352      *
2353      * <p>This includes: setting a fully populated ZenPolicy, setting correct type and
2354      * allowManualInvocation=true, and ensuring default names and trigger descriptions correspond
2355      * to the current locale.
2356      */
updateDefaultConfig(Context context, ZenModeConfig defaultConfig)2357     private static void updateDefaultConfig(Context context, ZenModeConfig defaultConfig) {
2358         updateDefaultAutomaticRulePolicies(defaultConfig);
2359         if (Flags.modesUi()) {
2360             SystemZenRules.maybeUpgradeRules(context, defaultConfig);
2361         }
2362         updateRuleStringsForCurrentLocale(context, defaultConfig);
2363     }
2364 
updateRuleStringsForCurrentLocale(Context context, ZenModeConfig defaultConfig)2365     private static void updateRuleStringsForCurrentLocale(Context context,
2366             ZenModeConfig defaultConfig) {
2367         for (ZenRule rule : defaultConfig.automaticRules.values()) {
2368             if (ZenModeConfig.EVENTS_OBSOLETE_RULE_ID.equals(rule.id)) {
2369                 rule.name = context.getResources()
2370                         .getString(R.string.zen_mode_default_events_name);
2371             } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) {
2372                 rule.name = context.getResources()
2373                         .getString(R.string.zen_mode_default_every_night_name);
2374             }
2375             if (Flags.modesUi()) {
2376                 SystemZenRules.updateTriggerDescription(context, rule);
2377             }
2378         }
2379     }
2380 
2381     // Updates the policies in the default automatic rules (provided via default XML config) to
2382     // be fully filled in default values.
updateDefaultAutomaticRulePolicies(ZenModeConfig defaultConfig)2383     private static void updateDefaultAutomaticRulePolicies(ZenModeConfig defaultConfig) {
2384         ZenPolicy defaultPolicy = defaultConfig.getZenPolicy();
2385         for (ZenRule rule : defaultConfig.automaticRules.values()) {
2386             if (ZenModeConfig.getDefaultRuleIds().contains(rule.id) && rule.zenPolicy == null) {
2387                 rule.zenPolicy = defaultPolicy.copy();
2388             }
2389         }
2390     }
2391 
2392     @VisibleForTesting
applyRestrictions()2393     protected void applyRestrictions() {
2394         final boolean zenOn = mZenMode != Global.ZEN_MODE_OFF;
2395         final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
2396         final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
2397         final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
2398         final boolean allowCalls = mConsolidatedPolicy.allowCalls()
2399                 && mConsolidatedPolicy.allowCallsFrom() == PRIORITY_SENDERS_ANY;
2400         final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
2401         final boolean allowSystem = mConsolidatedPolicy.allowSystem();
2402         final boolean allowMedia = mConsolidatedPolicy.allowMedia();
2403         final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();
2404 
2405         // notification restrictions
2406         final boolean muteNotifications = zenOn
2407                 || (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
2408         // call restrictions
2409         final boolean muteCalls = zenAlarmsOnly
2410                 || (zenPriorityOnly && (!allowCalls || !allowRepeatCallers))
2411                 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
2412         // alarm restrictions
2413         final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
2414         // media restrictions
2415         final boolean muteMedia = zenPriorityOnly && !allowMedia;
2416         // system restrictions
2417         final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem);
2418         // total silence restrictions
2419         final boolean muteEverything = zenSilence || (zenPriorityOnly
2420                 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
2421 
2422         for (int usage : AudioAttributes.SDK_USAGES.toArray()) {
2423             final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
2424             if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
2425                 applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
2426             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
2427                 applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage);
2428             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
2429                 applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage);
2430             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
2431                 applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage);
2432             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
2433                 applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage);
2434             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
2435                 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
2436                     // normally DND will only restrict touch sounds, not haptic feedback/vibrations
2437                     applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage,
2438                             AppOpsManager.OP_PLAY_AUDIO);
2439                     applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE);
2440                 } else {
2441                     applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage);
2442                 }
2443             } else {
2444                 applyRestrictions(zenPriorityOnly, muteEverything, usage);
2445             }
2446         }
2447     }
2448 
2449 
2450     @VisibleForTesting
applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code)2451     protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) {
2452         final long ident = Binder.clearCallingIdentity();
2453         try {
2454             mAppOps.setRestriction(code, usage,
2455                     mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
2456                     zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);
2457         } finally {
2458             Binder.restoreCallingIdentity(ident);
2459         }
2460     }
2461 
2462     @VisibleForTesting
applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage)2463     protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) {
2464         applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE);
2465         applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO);
2466     }
2467 
2468 
2469     @VisibleForTesting
applyZenToRingerMode()2470     protected void applyZenToRingerMode() {
2471         if (mAudioManager == null) return;
2472         // force the ringer mode into compliance
2473         final int ringerModeInternal = mAudioManager.getRingerModeInternal();
2474         int newRingerModeInternal = ringerModeInternal;
2475         switch (mZenMode) {
2476             case Global.ZEN_MODE_NO_INTERRUPTIONS:
2477             case Global.ZEN_MODE_ALARMS:
2478                 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
2479                     setPreviousRingerModeSetting(ringerModeInternal);
2480                     newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
2481                 }
2482                 break;
2483             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
2484                 // do not apply zen to ringer, streams zen muted in AudioService
2485                 break;
2486             case Global.ZEN_MODE_OFF:
2487                 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
2488                     newRingerModeInternal = getPreviousRingerModeSetting();
2489                     setPreviousRingerModeSetting(null);
2490                 }
2491                 break;
2492         }
2493         if (newRingerModeInternal != -1) {
2494             mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
2495         }
2496     }
2497 
dispatchOnConfigChanged()2498     private void dispatchOnConfigChanged() {
2499         for (Callback callback : mCallbacks) {
2500             callback.onConfigChanged();
2501         }
2502     }
2503 
dispatchOnPolicyChanged(Policy newPolicy)2504     private void dispatchOnPolicyChanged(Policy newPolicy) {
2505         for (Callback callback : mCallbacks) {
2506             callback.onPolicyChanged(newPolicy);
2507         }
2508     }
2509 
dispatchOnConsolidatedPolicyChanged(Policy newConsolidatedPolicy)2510     private void dispatchOnConsolidatedPolicyChanged(Policy newConsolidatedPolicy) {
2511         for (Callback callback : mCallbacks) {
2512             callback.onConsolidatedPolicyChanged(newConsolidatedPolicy);
2513         }
2514     }
2515 
dispatchOnZenModeChanged()2516     private void dispatchOnZenModeChanged() {
2517         for (Callback callback : mCallbacks) {
2518             callback.onZenModeChanged();
2519         }
2520     }
2521 
dispatchOnAutomaticRuleStatusChanged(int userId, String pkg, String id, int status)2522     private void dispatchOnAutomaticRuleStatusChanged(int userId, String pkg, String id,
2523             int status) {
2524         for (Callback callback : mCallbacks) {
2525             callback.onAutomaticRuleStatusChanged(userId, pkg, id, status);
2526         }
2527     }
2528 
2529     // TODO: b/368247671 - Delete this method AND default_zen_mode_config.xml when inlining modes_ui
readDefaultConfig(Resources resources)2530     private ZenModeConfig readDefaultConfig(Resources resources) {
2531         XmlResourceParser parser = null;
2532         try {
2533             parser = resources.getXml(R.xml.default_zen_mode_config);
2534             while (parser.next() != XmlPullParser.END_DOCUMENT) {
2535                 final ZenModeConfig config =
2536                         ZenModeConfig.readXml(XmlUtils.makeTyped(parser), null);
2537                 if (config != null) return config;
2538             }
2539         } catch (Exception e) {
2540             Log.w(TAG, "Error reading default zen mode config from resource", e);
2541         } finally {
2542             IoUtils.closeQuietly(parser);
2543         }
2544         return new ZenModeConfig();
2545     }
2546 
zenSeverity(int zen)2547     private static int zenSeverity(int zen) {
2548         switch (zen) {
2549             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
2550             case Global.ZEN_MODE_ALARMS: return 2;
2551             case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
2552             default: return 0;
2553         }
2554     }
2555 
2556     /**
2557      * Generate pulled atoms about do not disturb configurations.
2558      */
pullRules(List<StatsEvent> events)2559     public void pullRules(List<StatsEvent> events) {
2560         synchronized (mConfigLock) {
2561             final int numConfigs = mConfigs.size();
2562             for (int i = 0; i < numConfigs; i++) {
2563                 final int user = mConfigs.keyAt(i);
2564                 final ZenModeConfig config = mConfigs.valueAt(i);
2565                 events.add(FrameworkStatsLog.buildStatsEvent(DND_MODE_RULE,
2566                         /* optional int32 user = 1 */ user,
2567                         /* optional bool enabled = 2 */ config.isManualActive(),
2568                         /* optional bool channels_bypassing = 3 */ config.hasPriorityChannels,
2569                         /* optional LoggedZenMode zen_mode = 4 */ ROOT_CONFIG,
2570                         /* optional string id = 5 */ "", // empty for root config
2571                         /* optional int32 uid = 6 */ Process.SYSTEM_UID, // system owns root config
2572                         /* optional DNDPolicyProto policy = 7 */ config.getZenPolicy().toProto(),
2573                         /* optional int32 rule_modified_fields = 8 */ 0,
2574                         /* optional int32 policy_modified_fields = 9 */ 0,
2575                         /* optional int32 device_effects_modified_fields = 10 */ 0,
2576                         /* optional ActiveRuleType rule_type = 11 */ TYPE_UNKNOWN));
2577                 if (config.isManualActive()) {
2578                     ruleToProtoLocked(user, config.manualRule, true, events);
2579                 }
2580                 for (ZenRule rule : config.automaticRules.values()) {
2581                     ruleToProtoLocked(user, rule, false, events);
2582                 }
2583             }
2584         }
2585     }
2586 
2587     @GuardedBy("mConfigLock")
ruleToProtoLocked(int user, ZenRule rule, boolean isManualRule, List<StatsEvent> events)2588     private void ruleToProtoLocked(int user, ZenRule rule, boolean isManualRule,
2589             List<StatsEvent> events) {
2590         // Make the ID safe.
2591         String id = rule.id == null ? "" : rule.id;
2592         if (!ZenModeConfig.getDefaultRuleIds().contains(id)) {
2593             id = "";
2594         }
2595 
2596         // Look for packages and enablers, enablers get priority.
2597         String pkg = rule.getPkg() == null ? "" : rule.getPkg();
2598         if (rule.enabler != null) {
2599             pkg = rule.enabler;
2600         }
2601 
2602         int ruleType = rule.type;
2603         if (isManualRule) {
2604             id = ZenModeConfig.MANUAL_RULE_ID;
2605             ruleType = ZenModeEventLogger.ACTIVE_RULE_TYPE_MANUAL;
2606         }
2607 
2608         SysUiStatsEvent.Builder data;
2609         byte[] policyProto = new byte[]{};
2610         if (rule.zenPolicy != null) {
2611             policyProto = rule.zenPolicy.toProto();
2612         }
2613         events.add(FrameworkStatsLog.buildStatsEvent(DND_MODE_RULE,
2614                 /* optional int32 user = 1 */ user,
2615                 /* optional bool enabled = 2 */ rule.enabled,
2616                 /* optional bool channels_bypassing = 3 */ false, // unused for rules
2617                 /* optional android.stats.dnd.ZenMode zen_mode = 4 */ rule.zenMode,
2618                 /* optional string id = 5 */ id,
2619                 /* optional int32 uid = 6 */ getPackageUid(pkg, user),
2620                 /* optional DNDPolicyProto policy = 7 */ policyProto,
2621                 /* optional int32 rule_modified_fields = 8 */ rule.userModifiedFields,
2622                 /* optional int32 policy_modified_fields = 9 */ rule.zenPolicyUserModifiedFields,
2623                 /* optional int32 device_effects_modified_fields = 10 */
2624                 rule.zenDeviceEffectsUserModifiedFields,
2625                 /* optional ActiveRuleType rule_type = 11 */ ruleType));
2626     }
2627 
getPackageUid(String pkg, int user)2628     private int getPackageUid(String pkg, int user) {
2629         if ("android".equals(pkg)) {
2630             return Process.SYSTEM_UID;
2631         }
2632         final String key = getPackageUserKey(pkg, user);
2633         if (mRulesUidCache.get(key) == null) {
2634             try {
2635                 mRulesUidCache.put(key, mPm.getPackageUidAsUser(pkg, user));
2636             } catch (PackageManager.NameNotFoundException e) {
2637             }
2638         }
2639         return mRulesUidCache.getOrDefault(key, -1);
2640     }
2641 
getPackageUserKey(String pkg, int user)2642     private static String getPackageUserKey(String pkg, int user) {
2643         return pkg + "|" + user;
2644     }
2645 
2646     @VisibleForTesting
2647     protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
2648         @Override
toString()2649         public String toString() {
2650             return TAG;
2651         }
2652 
2653         @Override
onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, @Nullable String caller, int ringerModeExternal, VolumePolicy policy)2654         public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew,
2655                 @Nullable String caller, int ringerModeExternal, VolumePolicy policy) {
2656             final boolean isChange = ringerModeOld != ringerModeNew;
2657 
2658             int ringerModeExternalOut = ringerModeNew;
2659 
2660             if (mZenMode == Global.ZEN_MODE_OFF
2661                     || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
2662                     && !areAllPriorityOnlyRingerSoundsMuted())) {
2663                 // in priority only with ringer not muted, save ringer mode changes
2664                 // in dnd off, save ringer mode changes
2665                 setPreviousRingerModeSetting(ringerModeNew);
2666             }
2667             int newZen = -1;
2668             switch (ringerModeNew) {
2669                 case AudioManager.RINGER_MODE_SILENT:
2670                     if (isChange && policy.doNotDisturbWhenSilent) {
2671                         if (mZenMode == Global.ZEN_MODE_OFF) {
2672                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
2673                         }
2674                         setPreviousRingerModeSetting(ringerModeOld);
2675                     }
2676                     break;
2677                 case AudioManager.RINGER_MODE_VIBRATE:
2678                 case AudioManager.RINGER_MODE_NORMAL:
2679                     if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
2680                             && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
2681                             || mZenMode == Global.ZEN_MODE_ALARMS
2682                             || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
2683                             && areAllPriorityOnlyRingerSoundsMuted()))) {
2684                         newZen = Global.ZEN_MODE_OFF;
2685                     } else if (mZenMode != Global.ZEN_MODE_OFF) {
2686                         ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
2687                     }
2688                     break;
2689             }
2690 
2691             if (newZen != -1) {
2692                 setManualZenMode(UserHandle.CURRENT, newZen, null, ORIGIN_SYSTEM,
2693                         "ringerModeInternal", /* caller= */ null, /* setRingerMode= */ false,
2694                         Process.SYSTEM_UID);
2695             }
2696             if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
2697                 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
2698                         ringerModeExternal, ringerModeExternalOut);
2699             }
2700             return ringerModeExternalOut;
2701         }
2702 
areAllPriorityOnlyRingerSoundsMuted()2703         private boolean areAllPriorityOnlyRingerSoundsMuted() {
2704             synchronized (mConfigLock) {
2705                 return ZenModeConfig.areAllPriorityOnlyRingerSoundsMuted(mConfig);
2706             }
2707         }
2708 
2709         @Override
onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, @Nullable String caller, int ringerModeInternal, VolumePolicy policy)2710         public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew,
2711                 @Nullable String caller, int ringerModeInternal, VolumePolicy policy) {
2712             int ringerModeInternalOut = ringerModeNew;
2713             final boolean isChange = ringerModeOld != ringerModeNew;
2714             final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
2715 
2716             int newZen = -1;
2717             switch (ringerModeNew) {
2718                 case AudioManager.RINGER_MODE_SILENT:
2719                     if (isChange) {
2720                         if (mZenMode == Global.ZEN_MODE_OFF) {
2721                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
2722                         }
2723                         ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
2724                                 : AudioManager.RINGER_MODE_SILENT;
2725                     } else {
2726                         ringerModeInternalOut = ringerModeInternal;
2727                     }
2728                     break;
2729                 case AudioManager.RINGER_MODE_VIBRATE:
2730                 case AudioManager.RINGER_MODE_NORMAL:
2731                     if (mZenMode != Global.ZEN_MODE_OFF) {
2732                         newZen = Global.ZEN_MODE_OFF;
2733                     }
2734                     break;
2735             }
2736             if (newZen != -1) {
2737                 setManualZenMode(UserHandle.CURRENT, newZen, null, ORIGIN_SYSTEM,
2738                         "ringerModeExternal", caller, false /*setRingerMode*/, Process.SYSTEM_UID);
2739             }
2740 
2741             ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
2742                     ringerModeInternal, ringerModeInternalOut);
2743             return ringerModeInternalOut;
2744         }
2745 
2746         @Override
canVolumeDownEnterSilent()2747         public boolean canVolumeDownEnterSilent() {
2748             return mZenMode == Global.ZEN_MODE_OFF;
2749         }
2750 
2751         @Override
getRingerModeAffectedStreams(int streams)2752         public int getRingerModeAffectedStreams(int streams) {
2753             // ringtone, notification and system streams are always affected by ringer mode
2754             // zen muting is handled in AudioService.java's mZenModeAffectedStreams
2755             streams |= (1 << AudioSystem.STREAM_RING) |
2756                     (1 << AudioSystem.STREAM_NOTIFICATION) |
2757                     (1 << AudioSystem.STREAM_SYSTEM);
2758 
2759             if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
2760                 // alarm and music and streams affected by ringer mode (cannot be adjusted) when in
2761                 // total silence
2762                 streams |= (1 << AudioSystem.STREAM_ALARM) |
2763                         (1 << AudioSystem.STREAM_MUSIC) |
2764                         (1 << AudioSystem.STREAM_ASSISTANT);
2765             } else {
2766                 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
2767                         (1 << AudioSystem.STREAM_MUSIC) |
2768                         (1 << AudioSystem.STREAM_ASSISTANT)
2769                 );
2770             }
2771             return streams;
2772         }
2773     }
2774 
2775     private final class SettingsObserver extends ContentObserver {
2776         private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
2777 
SettingsObserver(Handler handler)2778         public SettingsObserver(Handler handler) {
2779             super(handler);
2780         }
2781 
observe()2782         public void observe() {
2783             final ContentResolver resolver = mContext.getContentResolver();
2784             resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
2785             update(null);
2786         }
2787 
2788         @Override
onChange(boolean selfChange, Uri uri)2789         public void onChange(boolean selfChange, Uri uri) {
2790             update(uri);
2791         }
2792 
update(Uri uri)2793         public void update(Uri uri) {
2794             if (ZEN_MODE.equals(uri)) {
2795                 if (mZenMode != getZenModeSetting()) {
2796                     if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
2797                     setZenModeSetting(mZenMode);
2798                 }
2799             }
2800         }
2801     }
2802 
drawableResNameToResId(String packageName, String resourceName)2803     private int drawableResNameToResId(String packageName, String resourceName) {
2804         if (TextUtils.isEmpty(resourceName)) {
2805             return 0;
2806         }
2807         try {
2808             final Resources res = mPm.getResourcesForApplication(packageName);
2809             return res.getIdentifier(resourceName, null, null);
2810         } catch (PackageManager.NameNotFoundException e) {
2811             Slog.w(TAG, "cannot load rule icon for pkg", e);
2812         }
2813         return 0;
2814     }
2815 
drawableResIdToResName(String packageName, @DrawableRes int resId)2816     private String drawableResIdToResName(String packageName, @DrawableRes int resId) {
2817         if (resId == 0) {
2818             return null;
2819         }
2820         requireNonNull(packageName);
2821         try {
2822             final Resources res = mPm.getResourcesForApplication(packageName);
2823             String resourceName = res.getResourceName(resId);
2824             if (resourceName != null && resourceName.length() > MAX_ICON_RESOURCE_NAME_LENGTH) {
2825                 Slog.e(TAG, "Resource name for ID=" + resId + " in package " + packageName
2826                         + " is too long (" + resourceName.length() + "); ignoring it");
2827                 return null;
2828             }
2829             return resourceName;
2830         } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
2831             Slog.e(TAG, "Resource name for ID=" + resId + " not found in package " + packageName
2832                     + ". Resource IDs may change when the application is upgraded, and the system"
2833                     + " may not be able to find the correct resource.");
2834             return null;
2835         }
2836     }
2837 
2838     /**
2839      * Checks that the {@code origin} supplied to ZenModeHelper rule-management API methods
2840      * ({@link #addAutomaticZenRule}, {@link #removeAutomaticZenRule}, etc, makes sense.
2841      */
checkManageRuleOrigin(String method, @ConfigOrigin int origin)2842     private static void checkManageRuleOrigin(String method, @ConfigOrigin int origin) {
2843         checkArgument(origin == ORIGIN_APP || origin == ORIGIN_SYSTEM
2844                         || origin == ORIGIN_USER_IN_SYSTEMUI,
2845                 "Expected one of ORIGIN_APP, ORIGIN_SYSTEM, or "
2846                         + "ORIGIN_USER_IN_SYSTEMUI for %s, but received '%s'.",
2847                 method, origin);
2848     }
2849 
2850     /**
2851      * Checks that the {@code origin} supplied to {@link #setAutomaticZenRuleState} or
2852      * {@link #setAutomaticZenRuleStateFromConditionProvider} makes sense.
2853      */
checkSetRuleStateOrigin(String method, @ConfigOrigin int origin)2854     private static void checkSetRuleStateOrigin(String method, @ConfigOrigin int origin) {
2855         checkArgument(origin == ORIGIN_APP || origin == ORIGIN_USER_IN_APP
2856                         || origin == ORIGIN_SYSTEM || origin == ORIGIN_USER_IN_SYSTEMUI,
2857                 "Expected one of ORIGIN_APP, ORIGIN_USER_IN_APP, ORIGIN_SYSTEM, or "
2858                         + "ORIGIN_USER_IN_SYSTEMUI for %s, but received '%s'.",
2859                 method, origin);
2860     }
2861 
2862     private final class Metrics extends Callback {
2863         private static final String COUNTER_MODE_PREFIX = "dnd_mode_";
2864         private static final String COUNTER_TYPE_PREFIX = "dnd_type_";
2865         private static final int DND_OFF = 0;
2866         private static final int DND_ON_MANUAL = 1;
2867         private static final int DND_ON_AUTOMATIC = 2;
2868         private static final String COUNTER_RULE = "dnd_rule_count";
2869         private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
2870 
2871         // Total silence, alarms only, priority only
2872         private int mPreviousZenMode = -1;
2873         private long mModeLogTimeMs = 0L;
2874 
2875         private int mNumZenRules = -1;
2876         private long mRuleCountLogTime = 0L;
2877 
2878         // automatic (1) vs manual (0) vs dnd off (2)
2879         private int mPreviousZenType = -1;
2880         private long mTypeLogTimeMs = 0L;
2881 
2882         @Override
onZenModeChanged()2883         void onZenModeChanged() {
2884             emit();
2885         }
2886 
2887         @Override
onConfigChanged()2888         void onConfigChanged() {
2889             emit();
2890         }
2891 
emit()2892         private void emit() {
2893             mHandler.postMetricsTimer();
2894             emitZenMode();
2895             emitRules();
2896             emitDndType();
2897         }
2898 
emitZenMode()2899         private void emitZenMode() {
2900             final long now = SystemClock.elapsedRealtime();
2901             final long since = (now - mModeLogTimeMs);
2902             if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
2903                 if (mPreviousZenMode != -1) {
2904                     MetricsLogger.count(
2905                             mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since);
2906                 }
2907                 mPreviousZenMode = mZenMode;
2908                 mModeLogTimeMs = now;
2909             }
2910         }
2911 
emitRules()2912         private void emitRules() {
2913             final long now = SystemClock.elapsedRealtime();
2914             final long since = (now - mRuleCountLogTime);
2915             synchronized (mConfigLock) {
2916                 int numZenRules = mConfig.automaticRules.size();
2917                 if (mNumZenRules != numZenRules
2918                         || since > MINIMUM_LOG_PERIOD_MS) {
2919                     if (mNumZenRules != -1) {
2920                         MetricsLogger.count(mContext, COUNTER_RULE,
2921                                 numZenRules - mNumZenRules);
2922                     }
2923                     mNumZenRules = numZenRules;
2924 
2925                     mRuleCountLogTime = since;
2926                 }
2927             }
2928         }
2929 
emitDndType()2930         private void emitDndType() {
2931             final long now = SystemClock.elapsedRealtime();
2932             final long since = (now - mTypeLogTimeMs);
2933             synchronized (mConfigLock) {
2934                 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF;
2935                 int zenType = !dndOn ? DND_OFF
2936                         : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC;
2937                 if (zenType != mPreviousZenType
2938                         || since > MINIMUM_LOG_PERIOD_MS) {
2939                     if (mPreviousZenType != -1) {
2940                         MetricsLogger.count(
2941                                 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since);
2942                     }
2943                     mTypeLogTimeMs = now;
2944                     mPreviousZenType = zenType;
2945                 }
2946             }
2947         }
2948     }
2949 
2950     private final class H extends Handler {
2951         private static final int MSG_DISPATCH = 1;
2952         private static final int MSG_METRICS = 2;
2953         private static final int MSG_APPLY_EFFECTS = 6;
2954         private static final int MSG_AUDIO_APPLIED_TO_RINGER = 7;
2955         private static final int MSG_AUDIO_NOT_APPLIED_TO_RINGER = 8;
2956 
2957         private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
2958 
H(Looper looper)2959         private H(Looper looper) {
2960             super(looper);
2961         }
2962 
postDispatchOnZenModeChanged()2963         private void postDispatchOnZenModeChanged() {
2964             removeMessages(MSG_DISPATCH);
2965             sendEmptyMessage(MSG_DISPATCH);
2966         }
2967 
postMetricsTimer()2968         private void postMetricsTimer() {
2969             removeMessages(MSG_METRICS);
2970             sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
2971         }
2972 
postUpdateRingerAndAudio(boolean shouldApplyToRinger)2973         private void postUpdateRingerAndAudio(boolean shouldApplyToRinger) {
2974             if (shouldApplyToRinger) {
2975                 removeMessages(MSG_AUDIO_APPLIED_TO_RINGER);
2976                 sendEmptyMessage(MSG_AUDIO_APPLIED_TO_RINGER);
2977             } else {
2978                 removeMessages(MSG_AUDIO_NOT_APPLIED_TO_RINGER);
2979                 sendEmptyMessage(MSG_AUDIO_NOT_APPLIED_TO_RINGER);
2980             }
2981         }
2982 
postApplyDeviceEffects(@onfigOrigin int origin)2983         private void postApplyDeviceEffects(@ConfigOrigin int origin) {
2984             removeMessages(MSG_APPLY_EFFECTS);
2985             sendMessage(obtainMessage(MSG_APPLY_EFFECTS, origin, 0));
2986         }
2987 
2988         @Override
handleMessage(Message msg)2989         public void handleMessage(Message msg) {
2990             switch (msg.what) {
2991                 case MSG_DISPATCH:
2992                     dispatchOnZenModeChanged();
2993                     break;
2994                 case MSG_METRICS:
2995                     mMetrics.emit();
2996                     break;
2997                 case MSG_AUDIO_APPLIED_TO_RINGER:
2998                     updateRingerAndAudio(/* shouldApplyToRinger= */ true);
2999                     break;
3000                 case MSG_AUDIO_NOT_APPLIED_TO_RINGER:
3001                     updateRingerAndAudio(/* shouldApplyToRinger= */ false);
3002                     break;
3003                 case MSG_APPLY_EFFECTS:
3004                     @ConfigOrigin int origin = msg.arg1;
3005                     applyConsolidatedDeviceEffects(origin);
3006                     break;
3007             }
3008         }
3009     }
3010 
3011     public static class Callback {
onConfigChanged()3012         void onConfigChanged() {}
onZenModeChanged()3013         void onZenModeChanged() {}
onPolicyChanged(Policy newPolicy)3014         void onPolicyChanged(Policy newPolicy) {}
onConsolidatedPolicyChanged(Policy newConsolidatedPolicy)3015         void onConsolidatedPolicyChanged(Policy newConsolidatedPolicy) {}
onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status)3016         void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {}
3017     }
3018 }
3019