1 /**
2  * Copyright (c) 2014, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.notification;
18 
19 import android.app.AppOpsManager;
20 import android.app.AutomaticZenRule;
21 import android.app.Notification;
22 import android.app.NotificationManager;
23 import android.app.NotificationManager.Policy;
24 import android.app.PendingIntent;
25 import android.content.ComponentName;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.Intent;
29 import android.content.pm.PackageManager;
30 import android.content.pm.ResolveInfo;
31 import android.content.pm.ServiceInfo;
32 import android.content.res.Resources;
33 import android.content.res.XmlResourceParser;
34 import android.database.ContentObserver;
35 import android.graphics.drawable.Icon;
36 import android.media.AudioAttributes;
37 import android.media.AudioManager;
38 import android.media.AudioManagerInternal;
39 import android.media.AudioSystem;
40 import android.media.VolumePolicy;
41 import android.net.Uri;
42 import android.os.Binder;
43 import android.os.Bundle;
44 import android.os.Handler;
45 import android.os.Looper;
46 import android.os.Message;
47 import android.os.Process;
48 import android.os.SystemClock;
49 import android.os.UserHandle;
50 import android.provider.Settings;
51 import android.provider.Settings.Global;
52 import android.service.notification.Condition;
53 import android.service.notification.ConditionProviderService;
54 import android.service.notification.ZenModeConfig;
55 import android.service.notification.ZenModeConfig.EventInfo;
56 import android.service.notification.ZenModeConfig.ScheduleInfo;
57 import android.service.notification.ZenModeConfig.ZenRule;
58 import android.service.notification.ZenModeProto;
59 import android.util.AndroidRuntimeException;
60 import android.util.ArrayMap;
61 import android.util.Log;
62 import android.util.Slog;
63 import android.util.SparseArray;
64 import android.util.proto.ProtoOutputStream;
65 
66 import com.android.internal.R;
67 import com.android.internal.annotations.VisibleForTesting;
68 import com.android.internal.logging.MetricsLogger;
69 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
70 import com.android.internal.notification.SystemNotificationChannels;
71 import com.android.server.LocalServices;
72 
73 import libcore.io.IoUtils;
74 
75 import org.xmlpull.v1.XmlPullParser;
76 import org.xmlpull.v1.XmlPullParserException;
77 import org.xmlpull.v1.XmlSerializer;
78 
79 import java.io.IOException;
80 import java.io.PrintWriter;
81 import java.util.ArrayList;
82 import java.util.List;
83 import java.util.Objects;
84 
85 /**
86  * NotificationManagerService helper for functionality related to zen mode.
87  */
88 public class ZenModeHelper {
89     static final String TAG = "ZenModeHelper";
90     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
91 
92     // The amount of time rules instances can exist without their owning app being installed.
93     private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
94 
95     private final Context mContext;
96     private final H mHandler;
97     private final SettingsObserver mSettingsObserver;
98     @VisibleForTesting protected final AppOpsManager mAppOps;
99     @VisibleForTesting protected final NotificationManager mNotificationManager;
100     protected ZenModeConfig mDefaultConfig;
101     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
102     private final ZenModeFiltering mFiltering;
103     protected final RingerModeDelegate mRingerModeDelegate = new
104             RingerModeDelegate();
105     private final ZenModeConditions mConditions;
106     private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
107     private final Metrics mMetrics = new Metrics();
108     private final ConditionProviders.Config mServiceConfig;
109 
110     @VisibleForTesting protected int mZenMode;
111     private int mUser = UserHandle.USER_SYSTEM;
112     @VisibleForTesting protected ZenModeConfig mConfig;
113     @VisibleForTesting protected AudioManagerInternal mAudioManager;
114     protected PackageManager mPm;
115     private long mSuppressedEffects;
116 
117     public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
118     public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
119     public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
120             | SUPPRESSED_EFFECT_NOTIFICATIONS;
121 
122     protected String mDefaultRuleEveryNightName;
123     protected String mDefaultRuleEventsName;
124     @VisibleForTesting protected boolean mIsBootComplete;
125 
ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders)126     public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
127         mContext = context;
128         mHandler = new H(looper);
129         addCallback(mMetrics);
130         mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
131         mNotificationManager =  context.getSystemService(NotificationManager.class);
132 
133         mDefaultConfig = new ZenModeConfig();
134         setDefaultZenRules(mContext);
135         mConfig = mDefaultConfig;
136         mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
137 
138         mSettingsObserver = new SettingsObserver(mHandler);
139         mSettingsObserver.observe();
140         mFiltering = new ZenModeFiltering(mContext);
141         mConditions = new ZenModeConditions(this, conditionProviders);
142         mServiceConfig = conditionProviders.getConfig();
143     }
144 
getLooper()145     public Looper getLooper() {
146         return mHandler.getLooper();
147     }
148 
149     @Override
toString()150     public String toString() {
151         return TAG;
152     }
153 
matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity)154     public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
155             ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
156         synchronized (mConfig) {
157             return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle,
158                     extras, validator, contactsTimeoutMs, timeoutAffinity);
159         }
160     }
161 
isCall(NotificationRecord record)162     public boolean isCall(NotificationRecord record) {
163         return mFiltering.isCall(record);
164     }
165 
recordCaller(NotificationRecord record)166     public void recordCaller(NotificationRecord record) {
167         mFiltering.recordCall(record);
168     }
169 
shouldIntercept(NotificationRecord record)170     public boolean shouldIntercept(NotificationRecord record) {
171         synchronized (mConfig) {
172             return mFiltering.shouldIntercept(mZenMode, mConfig, record);
173         }
174     }
175 
addCallback(Callback callback)176     public void addCallback(Callback callback) {
177         mCallbacks.add(callback);
178     }
179 
removeCallback(Callback callback)180     public void removeCallback(Callback callback) {
181         mCallbacks.remove(callback);
182     }
183 
initZenMode()184     public void initZenMode() {
185         if (DEBUG) Log.d(TAG, "initZenMode");
186         evaluateZenMode("init", true /*setRingerMode*/);
187     }
188 
onSystemReady()189     public void onSystemReady() {
190         if (DEBUG) Log.d(TAG, "onSystemReady");
191         mAudioManager = LocalServices.getService(AudioManagerInternal.class);
192         if (mAudioManager != null) {
193             mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
194         }
195         mPm = mContext.getPackageManager();
196         mHandler.postMetricsTimer();
197         cleanUpZenRules();
198         evaluateZenMode("onSystemReady", true);
199         mIsBootComplete = true;
200         showZenUpgradeNotification(mZenMode);
201     }
202 
onUserSwitched(int user)203     public void onUserSwitched(int user) {
204         loadConfigForUser(user, "onUserSwitched");
205     }
206 
onUserRemoved(int user)207     public void onUserRemoved(int user) {
208         if (user < UserHandle.USER_SYSTEM) return;
209         if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
210         mConfigs.remove(user);
211     }
212 
onUserUnlocked(int user)213     public void onUserUnlocked(int user) {
214         loadConfigForUser(user, "onUserUnlocked");
215     }
216 
loadConfigForUser(int user, String reason)217     private void loadConfigForUser(int user, String reason) {
218         if (mUser == user || user < UserHandle.USER_SYSTEM) return;
219         mUser = user;
220         if (DEBUG) Log.d(TAG, reason + " u=" + user);
221         ZenModeConfig config = mConfigs.get(user);
222         if (config == null) {
223             if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user);
224             config = mDefaultConfig.copy();
225             config.user = user;
226         }
227         synchronized (mConfig) {
228             setConfigLocked(config, reason);
229         }
230         cleanUpZenRules();
231     }
232 
getZenModeListenerInterruptionFilter()233     public int getZenModeListenerInterruptionFilter() {
234         return NotificationManager.zenModeToInterruptionFilter(mZenMode);
235     }
236 
requestFromListener(ComponentName name, int filter)237     public void requestFromListener(ComponentName name, int filter) {
238         final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
239         if (newZen != -1) {
240             setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
241                     "listener:" + (name != null ? name.flattenToShortString() : null));
242         }
243     }
244 
setSuppressedEffects(long suppressedEffects)245     public void setSuppressedEffects(long suppressedEffects) {
246         if (mSuppressedEffects == suppressedEffects) return;
247         mSuppressedEffects = suppressedEffects;
248         applyRestrictions();
249     }
250 
getSuppressedEffects()251     public long getSuppressedEffects() {
252         return mSuppressedEffects;
253     }
254 
getZenMode()255     public int getZenMode() {
256         return mZenMode;
257     }
258 
getZenRules()259     public List<ZenRule> getZenRules() {
260         List<ZenRule> rules = new ArrayList<>();
261         synchronized (mConfig) {
262             if (mConfig == null) return rules;
263             for (ZenRule rule : mConfig.automaticRules.values()) {
264                 if (canManageAutomaticZenRule(rule)) {
265                     rules.add(rule);
266                 }
267             }
268         }
269         return rules;
270     }
271 
getAutomaticZenRule(String id)272     public AutomaticZenRule getAutomaticZenRule(String id) {
273         ZenRule rule;
274         synchronized (mConfig) {
275             if (mConfig == null) return null;
276              rule = mConfig.automaticRules.get(id);
277         }
278         if (rule == null) return null;
279         if (canManageAutomaticZenRule(rule)) {
280              return createAutomaticZenRule(rule);
281         }
282         return null;
283     }
284 
addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason)285     public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
286         if (!isSystemRule(automaticZenRule)) {
287             ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner());
288             if (owner == null) {
289                 throw new IllegalArgumentException("Owner is not a condition provider service");
290             }
291 
292             int ruleInstanceLimit = -1;
293             if (owner.metaData != null) {
294                 ruleInstanceLimit = owner.metaData.getInt(
295                         ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
296             }
297             if (ruleInstanceLimit > 0 && ruleInstanceLimit
298                     < (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) {
299                 throw new IllegalArgumentException("Rule instance limit exceeded");
300             }
301         }
302 
303         ZenModeConfig newConfig;
304         synchronized (mConfig) {
305             if (mConfig == null) {
306                 throw new AndroidRuntimeException("Could not create rule");
307             }
308             if (DEBUG) {
309                 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
310             }
311             newConfig = mConfig.copy();
312             ZenRule rule = new ZenRule();
313             populateZenRule(automaticZenRule, rule, true);
314             newConfig.automaticRules.put(rule.id, rule);
315             if (setConfigLocked(newConfig, reason, true)) {
316                 return rule.id;
317             } else {
318                 throw new AndroidRuntimeException("Could not create rule");
319             }
320         }
321     }
322 
updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, String reason)323     public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
324             String reason) {
325         ZenModeConfig newConfig;
326         synchronized (mConfig) {
327             if (mConfig == null) return false;
328             if (DEBUG) {
329                 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule
330                         + " reason=" + reason);
331             }
332             newConfig = mConfig.copy();
333             ZenModeConfig.ZenRule rule;
334             if (ruleId == null) {
335                 throw new IllegalArgumentException("Rule doesn't exist");
336             } else {
337                 rule = newConfig.automaticRules.get(ruleId);
338                 if (rule == null || !canManageAutomaticZenRule(rule)) {
339                     throw new SecurityException(
340                             "Cannot update rules not owned by your condition provider");
341                 }
342             }
343             populateZenRule(automaticZenRule, rule, false);
344             newConfig.automaticRules.put(ruleId, rule);
345             return setConfigLocked(newConfig, reason, true);
346         }
347     }
348 
removeAutomaticZenRule(String id, String reason)349     public boolean removeAutomaticZenRule(String id, String reason) {
350         ZenModeConfig newConfig;
351         synchronized (mConfig) {
352             if (mConfig == null) return false;
353             newConfig = mConfig.copy();
354             ZenRule rule = newConfig.automaticRules.get(id);
355             if (rule == null) return false;
356             if (canManageAutomaticZenRule(rule)) {
357                 newConfig.automaticRules.remove(id);
358                 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
359             } else {
360                 throw new SecurityException(
361                         "Cannot delete rules not owned by your condition provider");
362             }
363             return setConfigLocked(newConfig, reason, true);
364         }
365     }
366 
removeAutomaticZenRules(String packageName, String reason)367     public boolean removeAutomaticZenRules(String packageName, String reason) {
368         ZenModeConfig newConfig;
369         synchronized (mConfig) {
370             if (mConfig == null) return false;
371             newConfig = mConfig.copy();
372             for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
373                 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
374                 if (rule.component.getPackageName().equals(packageName)
375                         && canManageAutomaticZenRule(rule)) {
376                     newConfig.automaticRules.removeAt(i);
377                 }
378             }
379             return setConfigLocked(newConfig, reason, true);
380         }
381     }
382 
getCurrentInstanceCount(ComponentName owner)383     public int getCurrentInstanceCount(ComponentName owner) {
384         int count = 0;
385         synchronized (mConfig) {
386             for (ZenRule rule : mConfig.automaticRules.values()) {
387                 if (rule.component != null && rule.component.equals(owner)) {
388                     count++;
389                 }
390             }
391         }
392         return count;
393     }
394 
canManageAutomaticZenRule(ZenRule rule)395     public boolean canManageAutomaticZenRule(ZenRule rule) {
396         final int callingUid = Binder.getCallingUid();
397         if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
398             return true;
399         } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
400                 == PackageManager.PERMISSION_GRANTED) {
401             return true;
402         } else {
403             String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
404             if (packages != null) {
405                 final int packageCount = packages.length;
406                 for (int i = 0; i < packageCount; i++) {
407                     if (packages[i].equals(rule.component.getPackageName())) {
408                         return true;
409                     }
410                 }
411             }
412             return false;
413         }
414     }
415 
setDefaultZenRules(Context context)416     public void setDefaultZenRules(Context context) {
417         mDefaultConfig = readDefaultConfig(context.getResources());
418         appendDefaultRules(mDefaultConfig);
419     }
420 
appendDefaultRules(ZenModeConfig config)421     private void appendDefaultRules (ZenModeConfig config) {
422         getDefaultRuleNames();
423         appendDefaultEveryNightRule(config);
424         appendDefaultEventRules(config);
425     }
426 
427     // Checks zen rule properties are the same (doesn't check creation time, name nor enabled)
428     // used to check if default rules were customized or not
ruleValuesEqual(AutomaticZenRule rule, ZenRule defaultRule)429     private boolean ruleValuesEqual(AutomaticZenRule rule, ZenRule defaultRule) {
430         if (rule == null || defaultRule == null) {
431             return false;
432         }
433         return rule.getInterruptionFilter() ==
434                 NotificationManager.zenModeToInterruptionFilter(defaultRule.zenMode)
435                 && rule.getConditionId().equals(defaultRule.conditionId)
436                 && rule.getOwner().equals(defaultRule.component);
437     }
438 
updateDefaultZenRules()439     protected void updateDefaultZenRules() {
440         ZenModeConfig configDefaultRules = new ZenModeConfig();
441         appendDefaultRules(configDefaultRules); // "new" localized default rules
442         for (String ruleId : ZenModeConfig.DEFAULT_RULE_IDS) {
443             AutomaticZenRule currRule = getAutomaticZenRule(ruleId);
444             ZenRule defaultRule = configDefaultRules.automaticRules.get(ruleId);
445             // if default rule wasn't customized, use localized name instead of previous
446             if (ruleValuesEqual(currRule, defaultRule) &&
447                     !defaultRule.name.equals(currRule.getName())) {
448                 if (canManageAutomaticZenRule(defaultRule)) {
449                     if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name "
450                             + "from " + currRule.getName() + " to " + defaultRule.name);
451                     // update default rule (if locale changed, name of rule will change)
452                     AutomaticZenRule defaultAutoRule = createAutomaticZenRule(defaultRule);
453                     // ensure enabled state is carried over from current rule
454                     defaultAutoRule.setEnabled(currRule.isEnabled());
455                     updateAutomaticZenRule(ruleId, defaultAutoRule,
456                             "locale changed");
457                 }
458             }
459         }
460     }
461 
isSystemRule(AutomaticZenRule rule)462     private boolean isSystemRule(AutomaticZenRule rule) {
463         return ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
464     }
465 
getServiceInfo(ComponentName owner)466     private ServiceInfo getServiceInfo(ComponentName owner) {
467         Intent queryIntent = new Intent();
468         queryIntent.setComponent(owner);
469         List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
470                 queryIntent,
471                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
472                 UserHandle.getCallingUserId());
473         if (installedServices != null) {
474             for (int i = 0, count = installedServices.size(); i < count; i++) {
475                 ResolveInfo resolveInfo = installedServices.get(i);
476                 ServiceInfo info = resolveInfo.serviceInfo;
477                 if (mServiceConfig.bindPermission.equals(info.permission)) {
478                     return info;
479                 }
480             }
481         }
482         return null;
483     }
484 
populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew)485     private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
486         if (isNew) {
487             rule.id = ZenModeConfig.newRuleId();
488             rule.creationTime = System.currentTimeMillis();
489             rule.component = automaticZenRule.getOwner();
490         }
491 
492         if (rule.enabled != automaticZenRule.isEnabled()) {
493             rule.snoozing = false;
494         }
495         rule.name = automaticZenRule.getName();
496         rule.condition = null;
497         rule.conditionId = automaticZenRule.getConditionId();
498         rule.enabled = automaticZenRule.isEnabled();
499         rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
500                 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
501     }
502 
createAutomaticZenRule(ZenRule rule)503     protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
504         return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
505                 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
506                 rule.creationTime);
507     }
508 
setManualZenMode(int zenMode, Uri conditionId, String caller, String reason)509     public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
510         setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
511         Settings.Global.putInt(mContext.getContentResolver(), Global.SHOW_ZEN_SETTINGS_SUGGESTION,
512                 0);
513     }
514 
setManualZenMode(int zenMode, Uri conditionId, String reason, String caller, boolean setRingerMode)515     private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
516             boolean setRingerMode) {
517         ZenModeConfig newConfig;
518         synchronized (mConfig) {
519             if (mConfig == null) return;
520             if (!Global.isValidZenMode(zenMode)) return;
521             if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode)
522                     + " conditionId=" + conditionId + " reason=" + reason
523                     + " setRingerMode=" + setRingerMode);
524             newConfig = mConfig.copy();
525             if (zenMode == Global.ZEN_MODE_OFF) {
526                 newConfig.manualRule = null;
527                 for (ZenRule automaticRule : newConfig.automaticRules.values()) {
528                     if (automaticRule.isAutomaticActive()) {
529                         automaticRule.snoozing = true;
530                     }
531                 }
532             } else {
533                 final ZenRule newRule = new ZenRule();
534                 newRule.enabled = true;
535                 newRule.zenMode = zenMode;
536                 newRule.conditionId = conditionId;
537                 newRule.enabler = caller;
538                 newConfig.manualRule = newRule;
539             }
540             setConfigLocked(newConfig, reason, setRingerMode);
541         }
542     }
543 
dump(ProtoOutputStream proto)544     void dump(ProtoOutputStream proto) {
545         proto.write(ZenModeProto.ZEN_MODE, mZenMode);
546         synchronized (mConfig) {
547             if (mConfig.manualRule != null) {
548                 mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
549             }
550             for (ZenRule rule : mConfig.automaticRules.values()) {
551                 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
552                         && !rule.snoozing) {
553                     rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
554                 }
555             }
556             mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY);
557             proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
558         }
559     }
560 
dump(PrintWriter pw, String prefix)561     public void dump(PrintWriter pw, String prefix) {
562         pw.print(prefix); pw.print("mZenMode=");
563         pw.println(Global.zenModeToString(mZenMode));
564         final int N = mConfigs.size();
565         for (int i = 0; i < N; i++) {
566             dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
567         }
568         pw.print(prefix); pw.print("mUser="); pw.println(mUser);
569         synchronized (mConfig) {
570             dump(pw, prefix, "mConfig", mConfig);
571         }
572 
573         pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
574         mFiltering.dump(pw, prefix);
575         mConditions.dump(pw, prefix);
576     }
577 
dump(PrintWriter pw, String prefix, String var, ZenModeConfig config)578     private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) {
579         pw.print(prefix); pw.print(var); pw.print('=');
580         if (config == null) {
581             pw.println(config);
582             return;
583         }
584         pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
585                 + "messages=%b,messagesFrom=%s,events=%b,reminders=%b)\n",
586                 config.allowAlarms, config.allowMedia, config.allowSystem,
587                 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
588                 config.allowRepeatCallers, config.allowMessages,
589                 ZenModeConfig.sourceToString(config.allowMessagesFrom),
590                 config.allowEvents, config.allowReminders);
591         pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
592         pw.print(prefix); pw.print("  manualRule="); pw.println(config.manualRule);
593         if (config.automaticRules.isEmpty()) return;
594         final int N = config.automaticRules.size();
595         for (int i = 0; i < N; i++) {
596             pw.print(prefix); pw.print(i == 0 ? "  automaticRules=" : "                 ");
597             pw.println(config.automaticRules.valueAt(i));
598         }
599     }
600 
readXml(XmlPullParser parser, boolean forRestore)601     public void readXml(XmlPullParser parser, boolean forRestore)
602             throws XmlPullParserException, IOException {
603         ZenModeConfig config = ZenModeConfig.readXml(parser);
604         String reason = "readXml";
605 
606         if (config != null) {
607             if (forRestore) {
608                 //TODO: http://b/22388012
609                 if (config.user != UserHandle.USER_SYSTEM) {
610                     return;
611                 }
612                 config.manualRule = null;  // don't restore the manual rule
613             }
614 
615             boolean resetToDefaultRules = true;
616             long time = System.currentTimeMillis();
617             if (config.automaticRules != null && config.automaticRules.size() > 0) {
618                 for (ZenRule automaticRule : config.automaticRules.values()) {
619                     if (forRestore) {
620                         // don't restore transient state from restored automatic rules
621                         automaticRule.snoozing = false;
622                         automaticRule.condition = null;
623                         automaticRule.creationTime = time;
624                     }
625                     resetToDefaultRules &= !automaticRule.enabled;
626                 }
627             }
628 
629             if (config.version < ZenModeConfig.XML_VERSION || forRestore) {
630                 Settings.Global.putInt(mContext.getContentResolver(),
631                         Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
632 
633                 // resets zen automatic rules to default
634                 // if all prev auto rules were disabled on update
635                 if (resetToDefaultRules) {
636                     config.automaticRules = new ArrayMap<>();
637                     appendDefaultRules(config);
638                     reason += ", reset to default rules";
639                 }
640             } else {
641                 // devices not restoring/upgrading already have updated zen settings
642                 Settings.Global.putInt(mContext.getContentResolver(),
643                         Global.ZEN_SETTINGS_UPDATED, 1);
644             }
645             if (DEBUG) Log.d(TAG, reason);
646             synchronized (mConfig) {
647                 setConfigLocked(config, reason);
648             }
649         }
650     }
651 
writeXml(XmlSerializer out, boolean forBackup, Integer version)652     public void writeXml(XmlSerializer out, boolean forBackup, Integer version) throws IOException {
653         final int N = mConfigs.size();
654         for (int i = 0; i < N; i++) {
655             //TODO: http://b/22388012
656             if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) {
657                 continue;
658             }
659             mConfigs.valueAt(i).writeXml(out, version);
660         }
661     }
662 
getNotificationPolicy()663     public Policy getNotificationPolicy() {
664         return getNotificationPolicy(mConfig);
665     }
666 
getNotificationPolicy(ZenModeConfig config)667     private static Policy getNotificationPolicy(ZenModeConfig config) {
668         return config == null ? null : config.toNotificationPolicy();
669     }
670 
setNotificationPolicy(Policy policy)671     public void setNotificationPolicy(Policy policy) {
672         if (policy == null || mConfig == null) return;
673         synchronized (mConfig) {
674             final ZenModeConfig newConfig = mConfig.copy();
675             newConfig.applyNotificationPolicy(policy);
676             setConfigLocked(newConfig, "setNotificationPolicy");
677         }
678     }
679 
680     /**
681      * Removes old rule instances whose owner is not installed.
682      */
cleanUpZenRules()683     private void cleanUpZenRules() {
684         long currentTime = System.currentTimeMillis();
685         synchronized (mConfig) {
686             final ZenModeConfig newConfig = mConfig.copy();
687             if (newConfig.automaticRules != null) {
688                 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
689                     ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
690                     if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
691                         try {
692                             mPm.getPackageInfo(rule.component.getPackageName(),
693                                     PackageManager.MATCH_ANY_USER);
694                         } catch (PackageManager.NameNotFoundException e) {
695                             newConfig.automaticRules.removeAt(i);
696                         }
697                     }
698                 }
699             }
700             setConfigLocked(newConfig, "cleanUpZenRules");
701         }
702     }
703 
704     /**
705      * @return a copy of the zen mode configuration
706      */
getConfig()707     public ZenModeConfig getConfig() {
708         synchronized (mConfig) {
709             return mConfig.copy();
710         }
711     }
712 
setConfigLocked(ZenModeConfig config, String reason)713     public boolean setConfigLocked(ZenModeConfig config, String reason) {
714         return setConfigLocked(config, reason, true /*setRingerMode*/);
715     }
716 
setConfig(ZenModeConfig config, String reason)717     public void setConfig(ZenModeConfig config, String reason) {
718         synchronized (mConfig) {
719             setConfigLocked(config, reason);
720         }
721     }
722 
setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode)723     private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) {
724         final long identity = Binder.clearCallingIdentity();
725         try {
726             if (config == null || !config.isValid()) {
727                 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
728                 return false;
729             }
730             if (config.user != mUser) {
731                 // simply store away for background users
732                 mConfigs.put(config.user, config);
733                 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
734                 return true;
735             }
736             mConditions.evaluateConfig(config, false /*processSubscriptions*/);  // may modify config
737             mConfigs.put(config.user, config);
738             if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
739             ZenLog.traceConfig(reason, mConfig, config);
740             final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
741                     getNotificationPolicy(config));
742             if (!config.equals(mConfig)) {
743                 dispatchOnConfigChanged();
744             }
745             if (policyChanged) {
746                 dispatchOnPolicyChanged();
747             }
748             mConfig = config;
749             mHandler.postApplyConfig(config, reason, setRingerMode);
750             return true;
751         } catch (SecurityException e) {
752             Log.wtf(TAG, "Invalid rule in config", e);
753             return false;
754         } finally {
755             Binder.restoreCallingIdentity(identity);
756         }
757     }
758 
applyConfig(ZenModeConfig config, String reason, boolean setRingerMode)759     private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
760         final String val = Integer.toString(config.hashCode());
761         Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
762         if (!evaluateZenMode(reason, setRingerMode)) {
763             applyRestrictions();  // evaluateZenMode will also apply restrictions if changed
764         }
765         mConditions.evaluateConfig(config, true /*processSubscriptions*/);
766     }
767 
getZenModeSetting()768     private int getZenModeSetting() {
769         return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
770     }
771 
772     @VisibleForTesting
setZenModeSetting(int zen)773     protected void setZenModeSetting(int zen) {
774         Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
775         showZenUpgradeNotification(zen);
776     }
777 
getPreviousRingerModeSetting()778     private int getPreviousRingerModeSetting() {
779         return Global.getInt(mContext.getContentResolver(),
780                 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
781     }
782 
setPreviousRingerModeSetting(Integer previousRingerLevel)783     private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
784         Global.putString(
785                 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
786                 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
787     }
788 
789     @VisibleForTesting
evaluateZenMode(String reason, boolean setRingerMode)790     protected boolean evaluateZenMode(String reason, boolean setRingerMode) {
791         if (DEBUG) Log.d(TAG, "evaluateZenMode");
792         final int zenBefore = mZenMode;
793         final int zen = computeZenMode();
794         ZenLog.traceSetZenMode(zen, reason);
795         mZenMode = zen;
796         setZenModeSetting(mZenMode);
797         updateRingerModeAffectedStreams();
798         if (setRingerMode && zen != zenBefore) {
799             applyZenToRingerMode();
800         }
801         applyRestrictions();
802         if (zen != zenBefore) {
803             mHandler.postDispatchOnZenModeChanged();
804         }
805         return true;
806     }
807 
updateRingerModeAffectedStreams()808     private void updateRingerModeAffectedStreams() {
809         if (mAudioManager != null) {
810             mAudioManager.updateRingerModeAffectedStreamsInternal();
811         }
812     }
813 
computeZenMode()814     private int computeZenMode() {
815         if (mConfig == null) return Global.ZEN_MODE_OFF;
816         synchronized (mConfig) {
817             if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
818             int zen = Global.ZEN_MODE_OFF;
819             for (ZenRule automaticRule : mConfig.automaticRules.values()) {
820                 if (automaticRule.isAutomaticActive()) {
821                     if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
822                         // automatic rule triggered dnd and user hasn't seen update dnd dialog
823                         if (Settings.Global.getInt(mContext.getContentResolver(),
824                                 Global.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
825                             Settings.Global.putInt(mContext.getContentResolver(),
826                                     Global.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
827                         }
828                         zen = automaticRule.zenMode;
829                     }
830                 }
831             }
832             return zen;
833         }
834     }
835 
getDefaultRuleNames()836     private void getDefaultRuleNames() {
837         // on locale-change, these values differ
838         mDefaultRuleEveryNightName = mContext.getResources()
839                 .getString(R.string.zen_mode_default_every_night_name);
840         mDefaultRuleEventsName = mContext.getResources()
841                 .getString(R.string.zen_mode_default_events_name);
842     }
843 
844     @VisibleForTesting
applyRestrictions()845     protected void applyRestrictions() {
846         final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
847         final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
848         final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
849 
850         // notification restrictions
851         final boolean muteNotifications =
852                 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
853         // call restrictions
854         final boolean muteCalls = zenAlarmsOnly
855                 || (zenPriorityOnly && !mConfig.allowCalls && !mConfig.allowRepeatCallers)
856                 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
857         // alarm restrictions
858         final boolean muteAlarms = zenPriorityOnly && !mConfig.allowAlarms;
859         // media restrictions
860         final boolean muteMedia = zenPriorityOnly && !mConfig.allowMedia;
861         // system restrictions
862         final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !mConfig.allowSystem);
863         // total silence restrictions
864         final boolean muteEverything = zenSilence
865                 || (zenPriorityOnly && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConfig));
866 
867         for (int usage : AudioAttributes.SDK_USAGES) {
868             final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
869             if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
870                 applyRestrictions(false /*mute*/, usage);
871             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
872                 applyRestrictions(muteNotifications || muteEverything, usage);
873             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
874                 applyRestrictions(muteCalls || muteEverything, usage);
875             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
876                 applyRestrictions(muteAlarms || muteEverything, usage);
877             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
878                 applyRestrictions(muteMedia || muteEverything, usage);
879             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
880                 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
881                     // normally DND will only restrict touch sounds, not haptic feedback/vibrations
882                     applyRestrictions(muteSystem || muteEverything, usage,
883                             AppOpsManager.OP_PLAY_AUDIO);
884                     applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE);
885                 } else {
886                     applyRestrictions(muteSystem || muteEverything, usage);
887                 }
888             } else {
889                 applyRestrictions(muteEverything, usage);
890             }
891         }
892     }
893 
894 
895     @VisibleForTesting
applyRestrictions(boolean mute, int usage, int code)896     protected void applyRestrictions(boolean mute, int usage, int code) {
897         final String[] exceptionPackages = null; // none (for now)
898 
899         // Only do this if we are executing within the system process...  otherwise
900         // we are running as test code, so don't have access to the protected call.
901         if (Process.myUid() == Process.SYSTEM_UID) {
902             final long ident = Binder.clearCallingIdentity();
903             try {
904                 mAppOps.setRestriction(code, usage,
905                         mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
906                         exceptionPackages);
907             } finally {
908                 Binder.restoreCallingIdentity(ident);
909             }
910         }
911     }
912 
913     @VisibleForTesting
applyRestrictions(boolean mute, int usage)914     protected void applyRestrictions(boolean mute, int usage) {
915         applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE);
916         applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO);
917     }
918 
919 
920     @VisibleForTesting
applyZenToRingerMode()921     protected void applyZenToRingerMode() {
922         if (mAudioManager == null) return;
923         // force the ringer mode into compliance
924         final int ringerModeInternal = mAudioManager.getRingerModeInternal();
925         int newRingerModeInternal = ringerModeInternal;
926         switch (mZenMode) {
927             case Global.ZEN_MODE_NO_INTERRUPTIONS:
928             case Global.ZEN_MODE_ALARMS:
929                 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
930                     setPreviousRingerModeSetting(ringerModeInternal);
931                     newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
932                 }
933                 break;
934             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
935                 // do not apply zen to ringer, streams zen muted in AudioService
936                 break;
937             case Global.ZEN_MODE_OFF:
938                 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
939                     newRingerModeInternal = getPreviousRingerModeSetting();
940                     setPreviousRingerModeSetting(null);
941                 }
942                 break;
943         }
944         if (newRingerModeInternal != -1) {
945             mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
946         }
947     }
948 
dispatchOnConfigChanged()949     private void dispatchOnConfigChanged() {
950         for (Callback callback : mCallbacks) {
951             callback.onConfigChanged();
952         }
953     }
954 
dispatchOnPolicyChanged()955     private void dispatchOnPolicyChanged() {
956         for (Callback callback : mCallbacks) {
957             callback.onPolicyChanged();
958         }
959     }
960 
dispatchOnZenModeChanged()961     private void dispatchOnZenModeChanged() {
962         for (Callback callback : mCallbacks) {
963             callback.onZenModeChanged();
964         }
965     }
966 
readDefaultConfig(Resources resources)967     private ZenModeConfig readDefaultConfig(Resources resources) {
968         XmlResourceParser parser = null;
969         try {
970             parser = resources.getXml(R.xml.default_zen_mode_config);
971             while (parser.next() != XmlPullParser.END_DOCUMENT) {
972                 final ZenModeConfig config = ZenModeConfig.readXml(parser);
973                 if (config != null) return config;
974             }
975         } catch (Exception e) {
976             Log.w(TAG, "Error reading default zen mode config from resource", e);
977         } finally {
978             IoUtils.closeQuietly(parser);
979         }
980         return new ZenModeConfig();
981     }
982 
appendDefaultEveryNightRule(ZenModeConfig config)983     private void appendDefaultEveryNightRule(ZenModeConfig config) {
984         if (config == null) return;
985 
986         final ScheduleInfo weeknights = new ScheduleInfo();
987         weeknights.days = ZenModeConfig.ALL_DAYS;
988         weeknights.startHour = 22;
989         weeknights.endHour = 7;
990         weeknights.exitAtAlarm = true;
991         final ZenRule rule = new ZenRule();
992         rule.enabled = false;
993         rule.name = mDefaultRuleEveryNightName;
994         rule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
995         rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
996         rule.component = ScheduleConditionProvider.COMPONENT;
997         rule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
998         rule.creationTime = System.currentTimeMillis();
999         config.automaticRules.put(rule.id, rule);
1000     }
1001 
appendDefaultEventRules(ZenModeConfig config)1002     private void appendDefaultEventRules(ZenModeConfig config) {
1003         if (config == null) return;
1004 
1005         final EventInfo events = new EventInfo();
1006         events.calendar = null; // any calendar
1007         events.reply = EventInfo.REPLY_YES_OR_MAYBE;
1008         final ZenRule rule = new ZenRule();
1009         rule.enabled = false;
1010         rule.name = mDefaultRuleEventsName;
1011         rule.conditionId = ZenModeConfig.toEventConditionId(events);
1012         rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1013         rule.component = EventConditionProvider.COMPONENT;
1014         rule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
1015         rule.creationTime = System.currentTimeMillis();
1016         config.automaticRules.put(rule.id, rule);
1017     }
1018 
zenSeverity(int zen)1019     private static int zenSeverity(int zen) {
1020         switch (zen) {
1021             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
1022             case Global.ZEN_MODE_ALARMS: return 2;
1023             case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
1024             default: return 0;
1025         }
1026     }
1027 
1028     @VisibleForTesting
1029     protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
1030         @Override
toString()1031         public String toString() {
1032             return TAG;
1033         }
1034 
1035         @Override
onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeExternal, VolumePolicy policy)1036         public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
1037                 int ringerModeExternal, VolumePolicy policy) {
1038             final boolean isChange = ringerModeOld != ringerModeNew;
1039 
1040             int ringerModeExternalOut = ringerModeNew;
1041 
1042             if (mZenMode == Global.ZEN_MODE_OFF
1043                     || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1044                     && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) {
1045                 // in priority only with ringer not muted, save ringer mode changes
1046                 // in dnd off, save ringer mode changes
1047                 setPreviousRingerModeSetting(ringerModeNew);
1048             }
1049             int newZen = -1;
1050             switch (ringerModeNew) {
1051                 case AudioManager.RINGER_MODE_SILENT:
1052                     if (isChange && policy.doNotDisturbWhenSilent) {
1053                         if (mZenMode == Global.ZEN_MODE_OFF) {
1054                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1055                         }
1056                         setPreviousRingerModeSetting(ringerModeOld);
1057                     }
1058                     break;
1059                 case AudioManager.RINGER_MODE_VIBRATE:
1060                 case AudioManager.RINGER_MODE_NORMAL:
1061                     if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
1062                             && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
1063                             || mZenMode == Global.ZEN_MODE_ALARMS
1064                             || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1065                             && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
1066                             mConfig)))) {
1067                         newZen = Global.ZEN_MODE_OFF;
1068                     } else if (mZenMode != Global.ZEN_MODE_OFF) {
1069                         ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
1070                     }
1071                     break;
1072             }
1073 
1074             if (newZen != -1) {
1075                 setManualZenMode(newZen, null, "ringerModeInternal", null,
1076                         false /*setRingerMode*/);
1077             }
1078             if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
1079                 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
1080                         ringerModeExternal, ringerModeExternalOut);
1081             }
1082             return ringerModeExternalOut;
1083         }
1084 
1085         @Override
onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeInternal, VolumePolicy policy)1086         public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
1087                 int ringerModeInternal, VolumePolicy policy) {
1088             int ringerModeInternalOut = ringerModeNew;
1089             final boolean isChange = ringerModeOld != ringerModeNew;
1090             final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
1091 
1092             int newZen = -1;
1093             switch (ringerModeNew) {
1094                 case AudioManager.RINGER_MODE_SILENT:
1095                     if (isChange) {
1096                         if (mZenMode == Global.ZEN_MODE_OFF) {
1097                             newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1098                         }
1099                         ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
1100                                 : AudioManager.RINGER_MODE_SILENT;
1101                     } else {
1102                         ringerModeInternalOut = ringerModeInternal;
1103                     }
1104                     break;
1105                 case AudioManager.RINGER_MODE_VIBRATE:
1106                 case AudioManager.RINGER_MODE_NORMAL:
1107                     if (mZenMode != Global.ZEN_MODE_OFF) {
1108                         newZen = Global.ZEN_MODE_OFF;
1109                     }
1110                     break;
1111             }
1112             if (newZen != -1) {
1113                 setManualZenMode(newZen, null, "ringerModeExternal", caller,
1114                         false /*setRingerMode*/);
1115             }
1116 
1117             ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
1118                     ringerModeInternal, ringerModeInternalOut);
1119             return ringerModeInternalOut;
1120         }
1121 
1122         @Override
canVolumeDownEnterSilent()1123         public boolean canVolumeDownEnterSilent() {
1124             return mZenMode == Global.ZEN_MODE_OFF;
1125         }
1126 
1127         @Override
getRingerModeAffectedStreams(int streams)1128         public int getRingerModeAffectedStreams(int streams) {
1129             // ringtone and notification streams are always affected by ringer mode
1130             // system stream is affected by ringer mode when not in priority-only
1131             streams |= (1 << AudioSystem.STREAM_RING) |
1132                     (1 << AudioSystem.STREAM_NOTIFICATION) |
1133                     (1 << AudioSystem.STREAM_SYSTEM);
1134 
1135             if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
1136                 // alarm and music streams affected by ringer mode when in total silence
1137                 streams |= (1 << AudioSystem.STREAM_ALARM) |
1138                         (1 << AudioSystem.STREAM_MUSIC);
1139             } else {
1140                 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
1141                         (1 << AudioSystem.STREAM_MUSIC));
1142             }
1143 
1144             if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1145                     && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) {
1146                 // system stream is not affected by ringer mode in priority only when the ringer
1147                 // is zen muted (all other notification categories are muted)
1148                 streams &= ~(1 << AudioSystem.STREAM_SYSTEM);
1149             } else {
1150                 streams |= (1 << AudioSystem.STREAM_SYSTEM);
1151             }
1152             return streams;
1153         }
1154     }
1155 
1156     private final class SettingsObserver extends ContentObserver {
1157         private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1158 
SettingsObserver(Handler handler)1159         public SettingsObserver(Handler handler) {
1160             super(handler);
1161         }
1162 
observe()1163         public void observe() {
1164             final ContentResolver resolver = mContext.getContentResolver();
1165             resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1166             update(null);
1167         }
1168 
1169         @Override
onChange(boolean selfChange, Uri uri)1170         public void onChange(boolean selfChange, Uri uri) {
1171             update(uri);
1172         }
1173 
update(Uri uri)1174         public void update(Uri uri) {
1175             if (ZEN_MODE.equals(uri)) {
1176                 if (mZenMode != getZenModeSetting()) {
1177                     if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1178                     setZenModeSetting(mZenMode);
1179                 }
1180             }
1181         }
1182     }
1183 
showZenUpgradeNotification(int zen)1184     private void showZenUpgradeNotification(int zen) {
1185         final boolean showNotification = mIsBootComplete
1186                 && zen != Global.ZEN_MODE_OFF
1187                 && Settings.Global.getInt(mContext.getContentResolver(),
1188                 Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0;
1189 
1190         if (showNotification) {
1191             mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
1192                     createZenUpgradeNotification());
1193             Settings.Global.putInt(mContext.getContentResolver(),
1194                     Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
1195         }
1196     }
1197 
1198     @VisibleForTesting
createZenUpgradeNotification()1199     protected Notification createZenUpgradeNotification() {
1200         final Bundle extras = new Bundle();
1201         extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
1202                 mContext.getResources().getString(R.string.global_action_settings));
1203         int title = R.string.zen_upgrade_notification_title;
1204         int content = R.string.zen_upgrade_notification_content;
1205         int drawable = R.drawable.ic_zen_24dp;
1206         if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
1207                 getNotificationPolicy().suppressedVisualEffects)) {
1208             title = R.string.zen_upgrade_notification_visd_title;
1209             content = R.string.zen_upgrade_notification_visd_content;
1210             drawable = R.drawable.ic_dnd_block_notifications;
1211         }
1212 
1213         Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
1214         onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
1215         return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
1216                 .setAutoCancel(true)
1217                 .setSmallIcon(R.drawable.ic_settings_24dp)
1218                 .setLargeIcon(Icon.createWithResource(mContext, drawable))
1219                 .setContentTitle(mContext.getResources().getString(title))
1220                 .setContentText(mContext.getResources().getString(content))
1221                 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
1222                         PendingIntent.FLAG_UPDATE_CURRENT))
1223                 .setAutoCancel(true)
1224                 .setLocalOnly(true)
1225                 .addExtras(extras)
1226                 .setStyle(new Notification.BigTextStyle())
1227                 .build();
1228     }
1229 
1230     private final class Metrics extends Callback {
1231         private static final String COUNTER_PREFIX = "dnd_mode_";
1232         private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1233 
1234         private int mPreviousZenMode = -1;
1235         private long mBeginningMs = 0L;
1236 
1237         @Override
onZenModeChanged()1238         void onZenModeChanged() {
1239             emit();
1240         }
1241 
emit()1242         private void emit() {
1243             mHandler.postMetricsTimer();
1244             final long now = SystemClock.elapsedRealtime();
1245             final long since = (now - mBeginningMs);
1246             if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1247                 if (mPreviousZenMode != -1) {
1248                     MetricsLogger.count(mContext, COUNTER_PREFIX + mPreviousZenMode, (int) since);
1249                 }
1250                 mPreviousZenMode = mZenMode;
1251                 mBeginningMs = now;
1252             }
1253         }
1254     }
1255 
1256     private final class H extends Handler {
1257         private static final int MSG_DISPATCH = 1;
1258         private static final int MSG_METRICS = 2;
1259         private static final int MSG_APPLY_CONFIG = 4;
1260 
1261         private final class ConfigMessageData {
1262             public final ZenModeConfig config;
1263             public final String reason;
1264             public final boolean setRingerMode;
1265 
ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode)1266             ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) {
1267                 this.config = config;
1268                 this.reason = reason;
1269                 this.setRingerMode = setRingerMode;
1270             }
1271         }
1272 
1273         private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
1274 
H(Looper looper)1275         private H(Looper looper) {
1276             super(looper);
1277         }
1278 
postDispatchOnZenModeChanged()1279         private void postDispatchOnZenModeChanged() {
1280             removeMessages(MSG_DISPATCH);
1281             sendEmptyMessage(MSG_DISPATCH);
1282         }
1283 
postMetricsTimer()1284         private void postMetricsTimer() {
1285             removeMessages(MSG_METRICS);
1286             sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1287         }
1288 
postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode)1289         private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
1290             sendMessage(obtainMessage(MSG_APPLY_CONFIG,
1291                     new ConfigMessageData(config, reason, setRingerMode)));
1292         }
1293 
1294         @Override
handleMessage(Message msg)1295         public void handleMessage(Message msg) {
1296             switch (msg.what) {
1297                 case MSG_DISPATCH:
1298                     dispatchOnZenModeChanged();
1299                     break;
1300                 case MSG_METRICS:
1301                     mMetrics.emit();
1302                     break;
1303                 case MSG_APPLY_CONFIG:
1304                     ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1305                     applyConfig(applyConfigData.config, applyConfigData.reason,
1306                             applyConfigData.setRingerMode);
1307             }
1308         }
1309     }
1310 
1311     public static class Callback {
onConfigChanged()1312         void onConfigChanged() {}
onZenModeChanged()1313         void onZenModeChanged() {}
onPolicyChanged()1314         void onPolicyChanged() {}
1315     }
1316 
1317 }
1318