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