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