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.media.AudioAttributes.USAGE_NOTIFICATION;
20 import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
21 import static android.media.AudioAttributes.USAGE_UNKNOWN;
22 import static android.media.AudioAttributes.USAGE_VIRTUAL_SOURCE;
23 
24 import android.app.AppOpsManager;
25 import android.app.AutomaticZenRule;
26 import android.app.NotificationManager;
27 import android.app.NotificationManager.Policy;
28 import android.content.ComponentName;
29 import android.content.ContentResolver;
30 import android.content.Context;
31 import android.content.Intent;
32 import android.content.pm.PackageManager;
33 import android.content.pm.ResolveInfo;
34 import android.content.pm.ServiceInfo;
35 import android.content.res.Resources;
36 import android.content.res.XmlResourceParser;
37 import android.database.ContentObserver;
38 import android.media.AudioAttributes;
39 import android.media.AudioManager;
40 import android.media.AudioManagerInternal;
41 import android.media.AudioSystem;
42 import android.media.VolumePolicy;
43 import android.net.Uri;
44 import android.os.Binder;
45 import android.os.Bundle;
46 import android.os.Handler;
47 import android.os.Looper;
48 import android.os.Message;
49 import android.os.Process;
50 import android.os.SystemClock;
51 import android.os.UserHandle;
52 import android.provider.Settings.Global;
53 import android.service.notification.Condition;
54 import android.service.notification.ConditionProviderService;
55 import android.service.notification.NotificationServiceDumpProto;
56 import android.service.notification.ZenModeConfig;
57 import android.service.notification.ZenModeConfig.EventInfo;
58 import android.service.notification.ZenModeConfig.ScheduleInfo;
59 import android.service.notification.ZenModeConfig.ZenRule;
60 import android.service.notification.ZenModeProto;
61 import android.util.AndroidRuntimeException;
62 import android.util.Log;
63 import android.util.SparseArray;
64 import android.util.proto.ProtoOutputStream;
65 
66 import com.android.internal.R;
67 import com.android.internal.logging.MetricsLogger;
68 import com.android.server.LocalServices;
69 
70 import libcore.io.IoUtils;
71 
72 import org.xmlpull.v1.XmlPullParser;
73 import org.xmlpull.v1.XmlPullParserException;
74 import org.xmlpull.v1.XmlSerializer;
75 
76 import java.io.IOException;
77 import java.io.PrintWriter;
78 import java.util.ArrayList;
79 import java.util.List;
80 import java.util.Objects;
81 
82 /**
83  * NotificationManagerService helper for functionality related to zen mode.
84  */
85 public class ZenModeHelper {
86     static final String TAG = "ZenModeHelper";
87     static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
88 
89     // The amount of time rules instances can exist without their owning app being installed.
90     private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
91 
92     private final Context mContext;
93     private final H mHandler;
94     private final SettingsObserver mSettingsObserver;
95     private final AppOpsManager mAppOps;
96     private final ZenModeConfig mDefaultConfig;
97     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
98     private final ZenModeFiltering mFiltering;
99     private final RingerModeDelegate mRingerModeDelegate = new RingerModeDelegate();
100     private final ZenModeConditions mConditions;
101     private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
102     private final Metrics mMetrics = new Metrics();
103     private final ConditionProviders.Config mServiceConfig;
104 
105     private int mZenMode;
106     private int mUser = UserHandle.USER_SYSTEM;
107     private ZenModeConfig mConfig;
108     private AudioManagerInternal mAudioManager;
109     private PackageManager mPm;
110     private long mSuppressedEffects;
111 
112     public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
113     public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
114     public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
115             | SUPPRESSED_EFFECT_NOTIFICATIONS;
116 
ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders)117     public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
118         mContext = context;
119         mHandler = new H(looper);
120         addCallback(mMetrics);
121         mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
122         mDefaultConfig = readDefaultConfig(context.getResources());
123         appendDefaultScheduleRules(mDefaultConfig);
124         appendDefaultEventRules(mDefaultConfig);
125         mConfig = mDefaultConfig;
126         mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
127         mSettingsObserver = new SettingsObserver(mHandler);
128         mSettingsObserver.observe();
129         mFiltering = new ZenModeFiltering(mContext);
130         mConditions = new ZenModeConditions(this, conditionProviders);
131         mServiceConfig = conditionProviders.getConfig();
132     }
133 
getLooper()134     public Looper getLooper() {
135         return mHandler.getLooper();
136     }
137 
138     @Override
toString()139     public String toString() {
140         return TAG;
141     }
142 
matchesCallFilter(UserHandle userHandle, Bundle extras, ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity)143     public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
144             ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
145         synchronized (mConfig) {
146             return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle,
147                     extras, validator, contactsTimeoutMs, timeoutAffinity);
148         }
149     }
150 
isCall(NotificationRecord record)151     public boolean isCall(NotificationRecord record) {
152         return mFiltering.isCall(record);
153     }
154 
recordCaller(NotificationRecord record)155     public void recordCaller(NotificationRecord record) {
156         mFiltering.recordCall(record);
157     }
158 
shouldIntercept(NotificationRecord record)159     public boolean shouldIntercept(NotificationRecord record) {
160         synchronized (mConfig) {
161             return mFiltering.shouldIntercept(mZenMode, mConfig, record);
162         }
163     }
164 
shouldSuppressWhenScreenOff()165     public boolean shouldSuppressWhenScreenOff() {
166         synchronized (mConfig) {
167             return !mConfig.allowWhenScreenOff;
168         }
169     }
170 
shouldSuppressWhenScreenOn()171     public boolean shouldSuppressWhenScreenOn() {
172         synchronized (mConfig) {
173             return !mConfig.allowWhenScreenOn;
174         }
175     }
176 
addCallback(Callback callback)177     public void addCallback(Callback callback) {
178         mCallbacks.add(callback);
179     }
180 
removeCallback(Callback callback)181     public void removeCallback(Callback callback) {
182         mCallbacks.remove(callback);
183     }
184 
initZenMode()185     public void initZenMode() {
186         if (DEBUG) Log.d(TAG, "initZenMode");
187         evaluateZenMode("init", true /*setRingerMode*/);
188     }
189 
onSystemReady()190     public void onSystemReady() {
191         if (DEBUG) Log.d(TAG, "onSystemReady");
192         mAudioManager = LocalServices.getService(AudioManagerInternal.class);
193         if (mAudioManager != null) {
194             mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
195         }
196         mPm = mContext.getPackageManager();
197         mHandler.postMetricsTimer();
198         cleanUpZenRules();
199         evaluateZenMode("onSystemReady", true);
200     }
201 
onUserSwitched(int user)202     public void onUserSwitched(int user) {
203         loadConfigForUser(user, "onUserSwitched");
204     }
205 
onUserRemoved(int user)206     public void onUserRemoved(int user) {
207         if (user < UserHandle.USER_SYSTEM) return;
208         if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
209         mConfigs.remove(user);
210     }
211 
onUserUnlocked(int user)212     public void onUserUnlocked(int user) {
213         loadConfigForUser(user, "onUserUnlocked");
214     }
215 
loadConfigForUser(int user, String reason)216     private void loadConfigForUser(int user, String reason) {
217         if (mUser == user || user < UserHandle.USER_SYSTEM) return;
218         mUser = user;
219         if (DEBUG) Log.d(TAG, reason + " u=" + user);
220         ZenModeConfig config = mConfigs.get(user);
221         if (config == null) {
222             if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user);
223             config = mDefaultConfig.copy();
224             config.user = user;
225         }
226         synchronized (mConfig) {
227             setConfigLocked(config, reason);
228         }
229         cleanUpZenRules();
230     }
231 
getZenModeListenerInterruptionFilter()232     public int getZenModeListenerInterruptionFilter() {
233         return NotificationManager.zenModeToInterruptionFilter(mZenMode);
234     }
235 
requestFromListener(ComponentName name, int filter)236     public void requestFromListener(ComponentName name, int filter) {
237         final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
238         if (newZen != -1) {
239             setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
240                     "listener:" + (name != null ? name.flattenToShortString() : null));
241         }
242     }
243 
setSuppressedEffects(long suppressedEffects)244     public void setSuppressedEffects(long suppressedEffects) {
245         if (mSuppressedEffects == suppressedEffects) return;
246         mSuppressedEffects = suppressedEffects;
247         applyRestrictions();
248     }
249 
getSuppressedEffects()250     public long getSuppressedEffects() {
251         return mSuppressedEffects;
252     }
253 
getZenMode()254     public int getZenMode() {
255         return mZenMode;
256     }
257 
getZenRules()258     public List<ZenRule> getZenRules() {
259         List<ZenRule> rules = new ArrayList<>();
260         synchronized (mConfig) {
261             if (mConfig == null) return rules;
262             for (ZenRule rule : mConfig.automaticRules.values()) {
263                 if (canManageAutomaticZenRule(rule)) {
264                     rules.add(rule);
265                 }
266             }
267         }
268         return rules;
269     }
270 
getAutomaticZenRule(String id)271     public AutomaticZenRule getAutomaticZenRule(String id) {
272         ZenRule rule;
273         synchronized (mConfig) {
274             if (mConfig == null) return null;
275              rule = mConfig.automaticRules.get(id);
276         }
277         if (rule == null) return null;
278         if (canManageAutomaticZenRule(rule)) {
279              return createAutomaticZenRule(rule);
280         }
281         return null;
282     }
283 
addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason)284     public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
285         if (!isSystemRule(automaticZenRule)) {
286             ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner());
287             if (owner == null) {
288                 throw new IllegalArgumentException("Owner is not a condition provider service");
289             }
290 
291             int ruleInstanceLimit = -1;
292             if (owner.metaData != null) {
293                 ruleInstanceLimit = owner.metaData.getInt(
294                         ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
295             }
296             if (ruleInstanceLimit > 0 && ruleInstanceLimit
297                     < (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) {
298                 throw new IllegalArgumentException("Rule instance limit exceeded");
299             }
300         }
301 
302         ZenModeConfig newConfig;
303         synchronized (mConfig) {
304             if (mConfig == null) {
305                 throw new AndroidRuntimeException("Could not create rule");
306             }
307             if (DEBUG) {
308                 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
309             }
310             newConfig = mConfig.copy();
311             ZenRule rule = new ZenRule();
312             populateZenRule(automaticZenRule, rule, true);
313             newConfig.automaticRules.put(rule.id, rule);
314             if (setConfigLocked(newConfig, reason, true)) {
315                 return rule.id;
316             } else {
317                 throw new AndroidRuntimeException("Could not create rule");
318             }
319         }
320     }
321 
updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule, String reason)322     public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
323             String reason) {
324         ZenModeConfig newConfig;
325         synchronized (mConfig) {
326             if (mConfig == null) return false;
327             if (DEBUG) {
328                 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule
329                         + " reason=" + reason);
330             }
331             newConfig = mConfig.copy();
332             ZenModeConfig.ZenRule rule;
333             if (ruleId == null) {
334                 throw new IllegalArgumentException("Rule doesn't exist");
335             } else {
336                 rule = newConfig.automaticRules.get(ruleId);
337                 if (rule == null || !canManageAutomaticZenRule(rule)) {
338                     throw new SecurityException(
339                             "Cannot update rules not owned by your condition provider");
340                 }
341             }
342             populateZenRule(automaticZenRule, rule, false);
343             newConfig.automaticRules.put(ruleId, rule);
344             return setConfigLocked(newConfig, reason, true);
345         }
346     }
347 
removeAutomaticZenRule(String id, String reason)348     public boolean removeAutomaticZenRule(String id, String reason) {
349         ZenModeConfig newConfig;
350         synchronized (mConfig) {
351             if (mConfig == null) return false;
352             newConfig = mConfig.copy();
353             ZenRule rule = newConfig.automaticRules.get(id);
354             if (rule == null) return false;
355             if (canManageAutomaticZenRule(rule)) {
356                 newConfig.automaticRules.remove(id);
357                 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
358             } else {
359                 throw new SecurityException(
360                         "Cannot delete rules not owned by your condition provider");
361             }
362             return setConfigLocked(newConfig, reason, true);
363         }
364     }
365 
removeAutomaticZenRules(String packageName, String reason)366     public boolean removeAutomaticZenRules(String packageName, String reason) {
367         ZenModeConfig newConfig;
368         synchronized (mConfig) {
369             if (mConfig == null) return false;
370             newConfig = mConfig.copy();
371             for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
372                 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
373                 if (rule.component.getPackageName().equals(packageName)
374                         && canManageAutomaticZenRule(rule)) {
375                     newConfig.automaticRules.removeAt(i);
376                 }
377             }
378             return setConfigLocked(newConfig, reason, true);
379         }
380     }
381 
getCurrentInstanceCount(ComponentName owner)382     public int getCurrentInstanceCount(ComponentName owner) {
383         int count = 0;
384         synchronized (mConfig) {
385             for (ZenRule rule : mConfig.automaticRules.values()) {
386                 if (rule.component != null && rule.component.equals(owner)) {
387                     count++;
388                 }
389             }
390         }
391         return count;
392     }
393 
canManageAutomaticZenRule(ZenRule rule)394     public boolean canManageAutomaticZenRule(ZenRule rule) {
395         final int callingUid = Binder.getCallingUid();
396         if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
397             return true;
398         } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
399                 == PackageManager.PERMISSION_GRANTED) {
400             return true;
401         } else {
402             String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
403             if (packages != null) {
404                 final int packageCount = packages.length;
405                 for (int i = 0; i < packageCount; i++) {
406                     if (packages[i].equals(rule.component.getPackageName())) {
407                         return true;
408                     }
409                 }
410             }
411             return false;
412         }
413     }
414 
isSystemRule(AutomaticZenRule rule)415     private boolean isSystemRule(AutomaticZenRule rule) {
416         return ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
417     }
418 
getServiceInfo(ComponentName owner)419     private ServiceInfo getServiceInfo(ComponentName owner) {
420         Intent queryIntent = new Intent();
421         queryIntent.setComponent(owner);
422         List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
423                 queryIntent,
424                 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
425                 UserHandle.getCallingUserId());
426         if (installedServices != null) {
427             for (int i = 0, count = installedServices.size(); i < count; i++) {
428                 ResolveInfo resolveInfo = installedServices.get(i);
429                 ServiceInfo info = resolveInfo.serviceInfo;
430                 if (mServiceConfig.bindPermission.equals(info.permission)) {
431                     return info;
432                 }
433             }
434         }
435         return null;
436     }
437 
populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew)438     private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
439         if (isNew) {
440             rule.id = ZenModeConfig.newRuleId();
441             rule.creationTime = System.currentTimeMillis();
442             rule.component = automaticZenRule.getOwner();
443         }
444 
445         if (rule.enabled != automaticZenRule.isEnabled()) {
446             rule.snoozing = false;
447         }
448         rule.name = automaticZenRule.getName();
449         rule.condition = null;
450         rule.conditionId = automaticZenRule.getConditionId();
451         rule.enabled = automaticZenRule.isEnabled();
452         rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
453                 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
454     }
455 
createAutomaticZenRule(ZenRule rule)456     private AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
457         return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
458                 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
459                 rule.creationTime);
460     }
461 
setManualZenMode(int zenMode, Uri conditionId, String caller, String reason)462     public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
463         setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
464     }
465 
setManualZenMode(int zenMode, Uri conditionId, String reason, String caller, boolean setRingerMode)466     private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
467             boolean setRingerMode) {
468         ZenModeConfig newConfig;
469         synchronized (mConfig) {
470             if (mConfig == null) return;
471             if (!Global.isValidZenMode(zenMode)) return;
472             if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode)
473                     + " conditionId=" + conditionId + " reason=" + reason
474                     + " setRingerMode=" + setRingerMode);
475             newConfig = mConfig.copy();
476             if (zenMode == Global.ZEN_MODE_OFF) {
477                 newConfig.manualRule = null;
478                 for (ZenRule automaticRule : newConfig.automaticRules.values()) {
479                     if (automaticRule.isAutomaticActive()) {
480                         automaticRule.snoozing = true;
481                     }
482                 }
483             } else {
484                 final ZenRule newRule = new ZenRule();
485                 newRule.enabled = true;
486                 newRule.zenMode = zenMode;
487                 newRule.conditionId = conditionId;
488                 newRule.enabler = caller;
489                 newConfig.manualRule = newRule;
490             }
491             setConfigLocked(newConfig, reason, setRingerMode);
492         }
493     }
494 
dump(ProtoOutputStream proto)495     void dump(ProtoOutputStream proto) {
496 
497         proto.write(ZenModeProto.ZEN_MODE, mZenMode);
498         synchronized (mConfig) {
499             if (mConfig.manualRule != null) {
500                 proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, mConfig.manualRule.toString());
501             }
502             for (ZenRule rule : mConfig.automaticRules.values()) {
503                 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
504                         && !rule.snoozing) {
505                     proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, rule.toString());
506                 }
507             }
508             proto.write(ZenModeProto.POLICY, mConfig.toNotificationPolicy().toString());
509             proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
510         }
511     }
512 
dump(PrintWriter pw, String prefix)513     public void dump(PrintWriter pw, String prefix) {
514         pw.print(prefix); pw.print("mZenMode=");
515         pw.println(Global.zenModeToString(mZenMode));
516         final int N = mConfigs.size();
517         for (int i = 0; i < N; i++) {
518             dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
519         }
520         pw.print(prefix); pw.print("mUser="); pw.println(mUser);
521         synchronized (mConfig) {
522             dump(pw, prefix, "mConfig", mConfig);
523         }
524 
525         pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
526         mFiltering.dump(pw, prefix);
527         mConditions.dump(pw, prefix);
528     }
529 
dump(PrintWriter pw, String prefix, String var, ZenModeConfig config)530     private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) {
531         pw.print(prefix); pw.print(var); pw.print('=');
532         if (config == null) {
533             pw.println(config);
534             return;
535         }
536         pw.printf("allow(calls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s,"
537                 + "events=%b,reminders=%b,whenScreenOff=%b,whenScreenOn=%b)\n",
538                 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
539                 config.allowRepeatCallers, config.allowMessages,
540                 ZenModeConfig.sourceToString(config.allowMessagesFrom),
541                 config.allowEvents, config.allowReminders, config.allowWhenScreenOff,
542                 config.allowWhenScreenOn);
543         pw.print(prefix); pw.print("  manualRule="); pw.println(config.manualRule);
544         if (config.automaticRules.isEmpty()) return;
545         final int N = config.automaticRules.size();
546         for (int i = 0; i < N; i++) {
547             pw.print(prefix); pw.print(i == 0 ? "  automaticRules=" : "                 ");
548             pw.println(config.automaticRules.valueAt(i));
549         }
550     }
551 
readXml(XmlPullParser parser, boolean forRestore)552     public void readXml(XmlPullParser parser, boolean forRestore)
553             throws XmlPullParserException, IOException {
554         final ZenModeConfig config = ZenModeConfig.readXml(parser);
555         if (config != null) {
556             if (forRestore) {
557                 //TODO: http://b/22388012
558                 if (config.user != UserHandle.USER_SYSTEM) {
559                     return;
560                 }
561                 config.manualRule = null;  // don't restore the manual rule
562                 long time = System.currentTimeMillis();
563                 if (config.automaticRules != null) {
564                     for (ZenRule automaticRule : config.automaticRules.values()) {
565                         // don't restore transient state from restored automatic rules
566                         automaticRule.snoozing = false;
567                         automaticRule.condition = null;
568                         automaticRule.creationTime = time;
569                     }
570                 }
571             }
572             if (DEBUG) Log.d(TAG, "readXml");
573             synchronized (mConfig) {
574                 setConfigLocked(config, "readXml");
575             }
576         }
577     }
578 
writeXml(XmlSerializer out, boolean forBackup)579     public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
580         final int N = mConfigs.size();
581         for (int i = 0; i < N; i++) {
582             //TODO: http://b/22388012
583             if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) {
584                 continue;
585             }
586             mConfigs.valueAt(i).writeXml(out);
587         }
588     }
589 
getNotificationPolicy()590     public Policy getNotificationPolicy() {
591         return getNotificationPolicy(mConfig);
592     }
593 
getNotificationPolicy(ZenModeConfig config)594     private static Policy getNotificationPolicy(ZenModeConfig config) {
595         return config == null ? null : config.toNotificationPolicy();
596     }
597 
setNotificationPolicy(Policy policy)598     public void setNotificationPolicy(Policy policy) {
599         if (policy == null || mConfig == null) return;
600         synchronized (mConfig) {
601             final ZenModeConfig newConfig = mConfig.copy();
602             newConfig.applyNotificationPolicy(policy);
603             setConfigLocked(newConfig, "setNotificationPolicy");
604         }
605     }
606 
607     /**
608      * Removes old rule instances whose owner is not installed.
609      */
cleanUpZenRules()610     private void cleanUpZenRules() {
611         long currentTime = System.currentTimeMillis();
612         synchronized (mConfig) {
613             final ZenModeConfig newConfig = mConfig.copy();
614             if (newConfig.automaticRules != null) {
615                 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
616                     ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
617                     if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
618                         try {
619                             mPm.getPackageInfo(rule.component.getPackageName(),
620                                     PackageManager.MATCH_ANY_USER);
621                         } catch (PackageManager.NameNotFoundException e) {
622                             newConfig.automaticRules.removeAt(i);
623                         }
624                     }
625                 }
626             }
627             setConfigLocked(newConfig, "cleanUpZenRules");
628         }
629     }
630 
631     /**
632      * @return a copy of the zen mode configuration
633      */
getConfig()634     public ZenModeConfig getConfig() {
635         synchronized (mConfig) {
636             return mConfig.copy();
637         }
638     }
639 
setConfigLocked(ZenModeConfig config, String reason)640     public boolean setConfigLocked(ZenModeConfig config, String reason) {
641         return setConfigLocked(config, reason, true /*setRingerMode*/);
642     }
643 
setConfig(ZenModeConfig config, String reason)644     public void setConfig(ZenModeConfig config, String reason) {
645         synchronized (mConfig) {
646             setConfigLocked(config, reason);
647         }
648     }
649 
setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode)650     private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) {
651         final long identity = Binder.clearCallingIdentity();
652         try {
653             if (config == null || !config.isValid()) {
654                 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
655                 return false;
656             }
657             if (config.user != mUser) {
658                 // simply store away for background users
659                 mConfigs.put(config.user, config);
660                 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
661                 return true;
662             }
663             mConditions.evaluateConfig(config, false /*processSubscriptions*/);  // may modify config
664             mConfigs.put(config.user, config);
665             if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
666             ZenLog.traceConfig(reason, mConfig, config);
667             final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
668                     getNotificationPolicy(config));
669             if (!config.equals(mConfig)) {
670                 dispatchOnConfigChanged();
671             }
672             if (policyChanged) {
673                 dispatchOnPolicyChanged();
674             }
675             mConfig = config;
676             mHandler.postApplyConfig(config, reason, setRingerMode);
677             return true;
678         } finally {
679             Binder.restoreCallingIdentity(identity);
680         }
681     }
682 
applyConfig(ZenModeConfig config, String reason, boolean setRingerMode)683     private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
684         final String val = Integer.toString(config.hashCode());
685         Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
686         if (!evaluateZenMode(reason, setRingerMode)) {
687             applyRestrictions();  // evaluateZenMode will also apply restrictions if changed
688         }
689         mConditions.evaluateConfig(config, true /*processSubscriptions*/);
690     }
691 
getZenModeSetting()692     private int getZenModeSetting() {
693         return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
694     }
695 
setZenModeSetting(int zen)696     private void setZenModeSetting(int zen) {
697         Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
698     }
699 
getPreviousRingerModeSetting()700     private int getPreviousRingerModeSetting() {
701         return Global.getInt(mContext.getContentResolver(),
702                 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
703     }
704 
setPreviousRingerModeSetting(Integer previousRingerLevel)705     private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
706         Global.putString(
707                 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
708                 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
709     }
710 
evaluateZenMode(String reason, boolean setRingerMode)711     private boolean evaluateZenMode(String reason, boolean setRingerMode) {
712         if (DEBUG) Log.d(TAG, "evaluateZenMode");
713         final int zenBefore = mZenMode;
714         final int zen = computeZenMode();
715         ZenLog.traceSetZenMode(zen, reason);
716         mZenMode = zen;
717         updateRingerModeAffectedStreams();
718         setZenModeSetting(mZenMode);
719         if (setRingerMode) {
720             applyZenToRingerMode();
721         }
722         applyRestrictions();
723         if (zen != zenBefore) {
724             mHandler.postDispatchOnZenModeChanged();
725         }
726         return true;
727     }
728 
updateRingerModeAffectedStreams()729     private void updateRingerModeAffectedStreams() {
730         if (mAudioManager != null) {
731             mAudioManager.updateRingerModeAffectedStreamsInternal();
732         }
733     }
734 
computeZenMode()735     private int computeZenMode() {
736         synchronized (mConfig) {
737             if (mConfig == null) return Global.ZEN_MODE_OFF;
738             if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
739             int zen = Global.ZEN_MODE_OFF;
740             for (ZenRule automaticRule : mConfig.automaticRules.values()) {
741                 if (automaticRule.isAutomaticActive()) {
742                     if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
743                         zen = automaticRule.zenMode;
744                     }
745                 }
746             }
747             return zen;
748         }
749     }
750 
applyRestrictions()751     private void applyRestrictions() {
752         final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
753 
754         // notification restrictions
755         final boolean muteNotifications =
756                 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
757         // call restrictions
758         final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
759                 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
760         // total silence restrictions
761         final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
762 
763         for (int usage : AudioAttributes.SDK_USAGES) {
764             final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
765             if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
766                 applyRestrictions(false /*mute*/, usage);
767             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
768                 applyRestrictions(muteNotifications || muteEverything, usage);
769             } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
770                 applyRestrictions(muteCalls || muteEverything, usage);
771             } else {
772                 applyRestrictions(muteEverything, usage);
773             }
774         }
775     }
776 
applyRestrictions(boolean mute, int usage)777     private void applyRestrictions(boolean mute, int usage) {
778         final String[] exceptionPackages = null; // none (for now)
779         mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage,
780                 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
781                 exceptionPackages);
782         mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, usage,
783                 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
784                 exceptionPackages);
785     }
786 
applyZenToRingerMode()787     private void applyZenToRingerMode() {
788         if (mAudioManager == null) return;
789         // force the ringer mode into compliance
790         final int ringerModeInternal = mAudioManager.getRingerModeInternal();
791         int newRingerModeInternal = ringerModeInternal;
792         switch (mZenMode) {
793             case Global.ZEN_MODE_NO_INTERRUPTIONS:
794             case Global.ZEN_MODE_ALARMS:
795                 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
796                     setPreviousRingerModeSetting(ringerModeInternal);
797                     newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
798                 }
799                 break;
800             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
801             case Global.ZEN_MODE_OFF:
802                 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
803                     newRingerModeInternal = getPreviousRingerModeSetting();
804                     setPreviousRingerModeSetting(null);
805                 }
806                 break;
807         }
808         if (newRingerModeInternal != -1) {
809             mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
810         }
811     }
812 
dispatchOnConfigChanged()813     private void dispatchOnConfigChanged() {
814         for (Callback callback : mCallbacks) {
815             callback.onConfigChanged();
816         }
817     }
818 
dispatchOnPolicyChanged()819     private void dispatchOnPolicyChanged() {
820         for (Callback callback : mCallbacks) {
821             callback.onPolicyChanged();
822         }
823     }
824 
dispatchOnZenModeChanged()825     private void dispatchOnZenModeChanged() {
826         for (Callback callback : mCallbacks) {
827             callback.onZenModeChanged();
828         }
829     }
830 
readDefaultConfig(Resources resources)831     private ZenModeConfig readDefaultConfig(Resources resources) {
832         XmlResourceParser parser = null;
833         try {
834             parser = resources.getXml(R.xml.default_zen_mode_config);
835             while (parser.next() != XmlPullParser.END_DOCUMENT) {
836                 final ZenModeConfig config = ZenModeConfig.readXml(parser);
837                 if (config != null) return config;
838             }
839         } catch (Exception e) {
840             Log.w(TAG, "Error reading default zen mode config from resource", e);
841         } finally {
842             IoUtils.closeQuietly(parser);
843         }
844         return new ZenModeConfig();
845     }
846 
appendDefaultScheduleRules(ZenModeConfig config)847     private void appendDefaultScheduleRules(ZenModeConfig config) {
848         if (config == null) return;
849 
850         final ScheduleInfo weeknights = new ScheduleInfo();
851         weeknights.days = ZenModeConfig.WEEKNIGHT_DAYS;
852         weeknights.startHour = 22;
853         weeknights.endHour = 7;
854         final ZenRule rule1 = new ZenRule();
855         rule1.enabled = false;
856         rule1.name = mContext.getResources()
857                 .getString(R.string.zen_mode_default_weeknights_name);
858         rule1.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
859         rule1.zenMode = Global.ZEN_MODE_ALARMS;
860         rule1.component = ScheduleConditionProvider.COMPONENT;
861         rule1.id = ZenModeConfig.newRuleId();
862         rule1.creationTime = System.currentTimeMillis();
863         config.automaticRules.put(rule1.id, rule1);
864 
865         final ScheduleInfo weekends = new ScheduleInfo();
866         weekends.days = ZenModeConfig.WEEKEND_DAYS;
867         weekends.startHour = 23;
868         weekends.startMinute = 30;
869         weekends.endHour = 10;
870         final ZenRule rule2 = new ZenRule();
871         rule2.enabled = false;
872         rule2.name = mContext.getResources()
873                 .getString(R.string.zen_mode_default_weekends_name);
874         rule2.conditionId = ZenModeConfig.toScheduleConditionId(weekends);
875         rule2.zenMode = Global.ZEN_MODE_ALARMS;
876         rule2.component = ScheduleConditionProvider.COMPONENT;
877         rule2.id = ZenModeConfig.newRuleId();
878         rule2.creationTime = System.currentTimeMillis();
879         config.automaticRules.put(rule2.id, rule2);
880     }
881 
appendDefaultEventRules(ZenModeConfig config)882     private void appendDefaultEventRules(ZenModeConfig config) {
883         if (config == null) return;
884 
885         final EventInfo events = new EventInfo();
886         events.calendar = null; // any calendar
887         events.reply = EventInfo.REPLY_YES_OR_MAYBE;
888         final ZenRule rule = new ZenRule();
889         rule.enabled = false;
890         rule.name = mContext.getResources().getString(R.string.zen_mode_default_events_name);
891         rule.conditionId = ZenModeConfig.toEventConditionId(events);
892         rule.zenMode = Global.ZEN_MODE_ALARMS;
893         rule.component = EventConditionProvider.COMPONENT;
894         rule.id = ZenModeConfig.newRuleId();
895         rule.creationTime = System.currentTimeMillis();
896         config.automaticRules.put(rule.id, rule);
897     }
898 
zenSeverity(int zen)899     private static int zenSeverity(int zen) {
900         switch (zen) {
901             case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
902             case Global.ZEN_MODE_ALARMS: return 2;
903             case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
904             default: return 0;
905         }
906     }
907 
908     private final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
909         @Override
toString()910         public String toString() {
911             return TAG;
912         }
913 
914         @Override
onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeExternal, VolumePolicy policy)915         public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
916                 int ringerModeExternal, VolumePolicy policy) {
917             final boolean isChange = ringerModeOld != ringerModeNew;
918 
919             int ringerModeExternalOut = ringerModeNew;
920 
921             int newZen = -1;
922             switch (ringerModeNew) {
923                 case AudioManager.RINGER_MODE_SILENT:
924                     if (isChange && policy.doNotDisturbWhenSilent) {
925                         if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS
926                                 && mZenMode != Global.ZEN_MODE_ALARMS) {
927                             newZen = Global.ZEN_MODE_ALARMS;
928                         }
929                         setPreviousRingerModeSetting(ringerModeOld);
930                     }
931                     break;
932                 case AudioManager.RINGER_MODE_VIBRATE:
933                 case AudioManager.RINGER_MODE_NORMAL:
934                     if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
935                             && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
936                                     || mZenMode == Global.ZEN_MODE_ALARMS)) {
937                         newZen = Global.ZEN_MODE_OFF;
938                     } else if (mZenMode != Global.ZEN_MODE_OFF) {
939                         ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
940                     }
941                     break;
942             }
943             if (newZen != -1) {
944                 setManualZenMode(newZen, null, "ringerModeInternal", null,
945                         false /*setRingerMode*/);
946             }
947 
948             if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
949                 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
950                         ringerModeExternal, ringerModeExternalOut);
951             }
952             return ringerModeExternalOut;
953         }
954 
955         @Override
onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller, int ringerModeInternal, VolumePolicy policy)956         public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
957                 int ringerModeInternal, VolumePolicy policy) {
958             int ringerModeInternalOut = ringerModeNew;
959             final boolean isChange = ringerModeOld != ringerModeNew;
960             final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
961 
962             int newZen = -1;
963             switch (ringerModeNew) {
964                 case AudioManager.RINGER_MODE_SILENT:
965                     if (isChange) {
966                         if (mZenMode == Global.ZEN_MODE_OFF) {
967                             newZen = Global.ZEN_MODE_ALARMS;
968                         }
969                         ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
970                                 : AudioManager.RINGER_MODE_SILENT;
971                     } else {
972                         ringerModeInternalOut = ringerModeInternal;
973                     }
974                     break;
975                 case AudioManager.RINGER_MODE_VIBRATE:
976                 case AudioManager.RINGER_MODE_NORMAL:
977                     if (mZenMode != Global.ZEN_MODE_OFF) {
978                         newZen = Global.ZEN_MODE_OFF;
979                     }
980                     break;
981             }
982             if (newZen != -1) {
983                 setManualZenMode(newZen, null, "ringerModeExternal", caller,
984                         false /*setRingerMode*/);
985             }
986 
987             ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
988                     ringerModeInternal, ringerModeInternalOut);
989             return ringerModeInternalOut;
990         }
991 
992         @Override
canVolumeDownEnterSilent()993         public boolean canVolumeDownEnterSilent() {
994             return mZenMode == Global.ZEN_MODE_OFF;
995         }
996 
997         @Override
getRingerModeAffectedStreams(int streams)998         public int getRingerModeAffectedStreams(int streams) {
999             // ringtone, notification and system streams are always affected by ringer mode
1000             streams |= (1 << AudioSystem.STREAM_RING) |
1001                        (1 << AudioSystem.STREAM_NOTIFICATION) |
1002                        (1 << AudioSystem.STREAM_SYSTEM);
1003 
1004             // alarm and music streams are only affected by ringer mode when in total silence
1005             if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
1006                 streams |= (1 << AudioSystem.STREAM_ALARM) |
1007                            (1 << AudioSystem.STREAM_MUSIC);
1008             } else {
1009                 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
1010                              (1 << AudioSystem.STREAM_MUSIC));
1011             }
1012             return streams;
1013         }
1014     }
1015 
1016     private final class SettingsObserver extends ContentObserver {
1017         private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1018 
SettingsObserver(Handler handler)1019         public SettingsObserver(Handler handler) {
1020             super(handler);
1021         }
1022 
observe()1023         public void observe() {
1024             final ContentResolver resolver = mContext.getContentResolver();
1025             resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1026             update(null);
1027         }
1028 
1029         @Override
onChange(boolean selfChange, Uri uri)1030         public void onChange(boolean selfChange, Uri uri) {
1031             update(uri);
1032         }
1033 
update(Uri uri)1034         public void update(Uri uri) {
1035             if (ZEN_MODE.equals(uri)) {
1036                 if (mZenMode != getZenModeSetting()) {
1037                     if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1038                     setZenModeSetting(mZenMode);
1039                 }
1040             }
1041         }
1042     }
1043 
1044     private final class Metrics extends Callback {
1045         private static final String COUNTER_PREFIX = "dnd_mode_";
1046         private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1047 
1048         private int mPreviousZenMode = -1;
1049         private long mBeginningMs = 0L;
1050 
1051         @Override
onZenModeChanged()1052         void onZenModeChanged() {
1053             emit();
1054         }
1055 
emit()1056         private void emit() {
1057             mHandler.postMetricsTimer();
1058             final long now = SystemClock.elapsedRealtime();
1059             final long since = (now - mBeginningMs);
1060             if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1061                 if (mPreviousZenMode != -1) {
1062                     MetricsLogger.count(mContext, COUNTER_PREFIX + mPreviousZenMode, (int) since);
1063                 }
1064                 mPreviousZenMode = mZenMode;
1065                 mBeginningMs = now;
1066             }
1067         }
1068     }
1069 
1070     private final class H extends Handler {
1071         private static final int MSG_DISPATCH = 1;
1072         private static final int MSG_METRICS = 2;
1073         private static final int MSG_APPLY_CONFIG = 4;
1074 
1075         private final class ConfigMessageData {
1076             public final ZenModeConfig config;
1077             public final String reason;
1078             public final boolean setRingerMode;
1079 
ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode)1080             ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) {
1081                 this.config = config;
1082                 this.reason = reason;
1083                 this.setRingerMode = setRingerMode;
1084             }
1085         }
1086 
1087         private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
1088 
H(Looper looper)1089         private H(Looper looper) {
1090             super(looper);
1091         }
1092 
postDispatchOnZenModeChanged()1093         private void postDispatchOnZenModeChanged() {
1094             removeMessages(MSG_DISPATCH);
1095             sendEmptyMessage(MSG_DISPATCH);
1096         }
1097 
postMetricsTimer()1098         private void postMetricsTimer() {
1099             removeMessages(MSG_METRICS);
1100             sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1101         }
1102 
postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode)1103         private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
1104             sendMessage(obtainMessage(MSG_APPLY_CONFIG,
1105                     new ConfigMessageData(config, reason, setRingerMode)));
1106         }
1107 
1108         @Override
handleMessage(Message msg)1109         public void handleMessage(Message msg) {
1110             switch (msg.what) {
1111                 case MSG_DISPATCH:
1112                     dispatchOnZenModeChanged();
1113                     break;
1114                 case MSG_METRICS:
1115                     mMetrics.emit();
1116                     break;
1117                 case MSG_APPLY_CONFIG:
1118                     ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1119                     applyConfig(applyConfigData.config, applyConfigData.reason,
1120                             applyConfigData.setRingerMode);
1121             }
1122         }
1123     }
1124 
1125     public static class Callback {
onConfigChanged()1126         void onConfigChanged() {}
onZenModeChanged()1127         void onZenModeChanged() {}
onPolicyChanged()1128         void onPolicyChanged() {}
1129     }
1130 
1131 }
1132