blob: 6ab2c43fb9badaad5e5403ec9dc60d97b02d04f9 [file] [log] [blame]
John Spurlock056c5192014-04-20 21:52:01 -04001/**
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
17package com.android.server.notification;
18
John Spurlock056c5192014-04-20 21:52:01 -040019import android.app.AppOpsManager;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040020import android.app.AutomaticZenRule;
Beverly3bae4e52018-02-07 12:32:02 -050021import android.app.Notification;
John Spurlock80774932015-05-07 17:38:50 -040022import android.app.NotificationManager;
John Spurlock1fc476d2015-04-14 16:05:20 -040023import android.app.NotificationManager.Policy;
Beverly3bae4e52018-02-07 12:32:02 -050024import android.app.PendingIntent;
John Spurlock312d1d02014-07-08 10:24:57 -040025import android.content.ComponentName;
John Spurlock056c5192014-04-20 21:52:01 -040026import android.content.ContentResolver;
27import android.content.Context;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -050028import android.content.Intent;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040029import android.content.pm.PackageManager;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -050030import android.content.pm.ResolveInfo;
31import android.content.pm.ServiceInfo;
John Spurlock056c5192014-04-20 21:52:01 -040032import android.content.res.Resources;
33import android.content.res.XmlResourceParser;
34import android.database.ContentObserver;
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -040035import android.graphics.drawable.Icon;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -070036import android.media.AudioAttributes;
John Spurlock056c5192014-04-20 21:52:01 -040037import android.media.AudioManager;
John Spurlock661f2cf2014-11-17 10:29:10 -050038import android.media.AudioManagerInternal;
John Spurlock50ced3f2015-05-11 16:00:09 -040039import android.media.AudioSystem;
John Spurlocka48d7792015-03-03 17:35:57 -050040import android.media.VolumePolicy;
John Spurlock056c5192014-04-20 21:52:01 -040041import android.net.Uri;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040042import android.os.Binder;
John Spurlock2b122f42014-08-27 16:29:47 -040043import android.os.Bundle;
John Spurlock056c5192014-04-20 21:52:01 -040044import android.os.Handler;
John Spurlock661f2cf2014-11-17 10:29:10 -050045import android.os.Looper;
46import android.os.Message;
Julia Reynoldsc8e54e82015-11-30 16:43:05 -050047import android.os.Process;
Chris Wren98d235b2015-05-27 18:25:17 -040048import android.os.SystemClock;
John Spurlockb5e767b2014-07-27 11:53:20 -040049import android.os.UserHandle;
Beverly3bae4e52018-02-07 12:32:02 -050050import android.provider.Settings;
John Spurlock056c5192014-04-20 21:52:01 -040051import android.provider.Settings.Global;
Julia Reynolds520df6e2017-02-13 09:05:10 -050052import android.service.notification.Condition;
Julia Reynolds43b70cd2016-01-14 15:05:34 -050053import android.service.notification.ConditionProviderService;
John Spurlock056c5192014-04-20 21:52:01 -040054import android.service.notification.ZenModeConfig;
John Spurlockcb9aa202015-05-08 17:35:22 -040055import android.service.notification.ZenModeConfig.EventInfo;
John Spurlockb2278d62015-04-07 12:47:12 -040056import android.service.notification.ZenModeConfig.ScheduleInfo;
57import android.service.notification.ZenModeConfig.ZenRule;
Julia Reynolds520df6e2017-02-13 09:05:10 -050058import android.service.notification.ZenModeProto;
Julia Reynolds87c42772016-05-16 09:52:17 -040059import android.util.AndroidRuntimeException;
Beverly4e2f76c2018-03-16 15:43:49 -040060import android.util.ArrayMap;
John Spurlock4db0d982014-08-13 09:19:03 -040061import android.util.Log;
Beverlyd4f96492017-08-02 13:36:11 -040062import android.util.Slog;
John Spurlock21258a32015-05-27 18:22:55 -040063import android.util.SparseArray;
Julia Reynolds520df6e2017-02-13 09:05:10 -050064import android.util.proto.ProtoOutputStream;
John Spurlock056c5192014-04-20 21:52:01 -040065
66import com.android.internal.R;
Beverly04216872017-09-28 10:55:32 -040067import com.android.internal.annotations.VisibleForTesting;
John Spurlock25d01ee2015-06-03 12:17:46 -040068import com.android.internal.logging.MetricsLogger;
Beverly3bae4e52018-02-07 12:32:02 -050069import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
70import com.android.internal.notification.SystemNotificationChannels;
John Spurlock661f2cf2014-11-17 10:29:10 -050071import com.android.server.LocalServices;
John Spurlock056c5192014-04-20 21:52:01 -040072
73import libcore.io.IoUtils;
74
75import org.xmlpull.v1.XmlPullParser;
76import org.xmlpull.v1.XmlPullParserException;
77import org.xmlpull.v1.XmlSerializer;
78
79import java.io.IOException;
80import java.io.PrintWriter;
John Spurlock1c923a32014-04-27 16:42:29 -040081import java.util.ArrayList;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040082import java.util.List;
John Spurlock1fc476d2015-04-14 16:05:20 -040083import java.util.Objects;
John Spurlock056c5192014-04-20 21:52:01 -040084
85/**
86 * NotificationManagerService helper for functionality related to zen mode.
87 */
John Spurlockb2278d62015-04-07 12:47:12 -040088public class ZenModeHelper {
89 static final String TAG = "ZenModeHelper";
90 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlock056c5192014-04-20 21:52:01 -040091
Julia Reynolds5a43aaa2015-12-15 13:54:41 -050092 // 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
John Spurlock056c5192014-04-20 21:52:01 -040095 private final Context mContext;
John Spurlock661f2cf2014-11-17 10:29:10 -050096 private final H mHandler;
John Spurlock056c5192014-04-20 21:52:01 -040097 private final SettingsObserver mSettingsObserver;
Beverly04216872017-09-28 10:55:32 -040098 @VisibleForTesting protected final AppOpsManager mAppOps;
Beverly3bae4e52018-02-07 12:32:02 -050099 @VisibleForTesting protected final NotificationManager mNotificationManager;
Beverlyd4f96492017-08-02 13:36:11 -0400100 protected ZenModeConfig mDefaultConfig;
John Spurlock1c923a32014-04-27 16:42:29 -0400101 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
John Spurlockb2278d62015-04-07 12:47:12 -0400102 private final ZenModeFiltering mFiltering;
Beverlyd6964762018-02-16 14:07:03 -0500103 protected final RingerModeDelegate mRingerModeDelegate = new
104 RingerModeDelegate();
John Spurlockb2278d62015-04-07 12:47:12 -0400105 private final ZenModeConditions mConditions;
John Spurlock21258a32015-05-27 18:22:55 -0400106 private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
Chris Wren98d235b2015-05-27 18:25:17 -0400107 private final Metrics mMetrics = new Metrics();
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500108 private final ConditionProviders.Config mServiceConfig;
John Spurlock056c5192014-04-20 21:52:01 -0400109
Beverly04216872017-09-28 10:55:32 -0400110 @VisibleForTesting protected int mZenMode;
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700111 private int mUser = UserHandle.USER_SYSTEM;
Beverly04216872017-09-28 10:55:32 -0400112 @VisibleForTesting protected ZenModeConfig mConfig;
Beverly85f52412018-02-27 10:41:13 -0500113 @VisibleForTesting protected AudioManagerInternal mAudioManager;
Beverlyd4f96492017-08-02 13:36:11 -0400114 protected PackageManager mPm;
Bryce Lee7219ada2016-04-08 10:54:23 -0700115 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;
John Spurlock056c5192014-04-20 21:52:01 -0400121
Beverly26eba872017-12-04 16:30:11 -0500122 protected String mDefaultRuleEveryNightName;
Beverlyd4f96492017-08-02 13:36:11 -0400123 protected String mDefaultRuleEventsName;
Beverly3bae4e52018-02-07 12:32:02 -0500124 @VisibleForTesting protected boolean mIsBootComplete;
Beverlyd4f96492017-08-02 13:36:11 -0400125
John Spurlockb2278d62015-04-07 12:47:12 -0400126 public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
John Spurlock056c5192014-04-20 21:52:01 -0400127 mContext = context;
John Spurlock661f2cf2014-11-17 10:29:10 -0500128 mHandler = new H(looper);
Chris Wren98d235b2015-05-27 18:25:17 -0400129 addCallback(mMetrics);
John Spurlock056c5192014-04-20 21:52:01 -0400130 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Beverly3bae4e52018-02-07 12:32:02 -0500131 mNotificationManager = context.getSystemService(NotificationManager.class);
Beverlyd4f96492017-08-02 13:36:11 -0400132
133 mDefaultConfig = new ZenModeConfig();
Beverlyd4f96492017-08-02 13:36:11 -0400134 setDefaultZenRules(mContext);
John Spurlock056c5192014-04-20 21:52:01 -0400135 mConfig = mDefaultConfig;
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700136 mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
Beverlyd4f96492017-08-02 13:36:11 -0400137
John Spurlock056c5192014-04-20 21:52:01 -0400138 mSettingsObserver = new SettingsObserver(mHandler);
139 mSettingsObserver.observe();
John Spurlockb2278d62015-04-07 12:47:12 -0400140 mFiltering = new ZenModeFiltering(mContext);
141 mConditions = new ZenModeConditions(this, conditionProviders);
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500142 mServiceConfig = conditionProviders.getConfig();
John Spurlock056c5192014-04-20 21:52:01 -0400143 }
144
John Spurlock1b8b22b2015-05-20 09:47:13 -0400145 public Looper getLooper() {
146 return mHandler.getLooper();
147 }
148
John Spurlockb2278d62015-04-07 12:47:12 -0400149 @Override
150 public String toString() {
151 return TAG;
152 }
153
154 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
155 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400156 synchronized (mConfig) {
157 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle,
Julia Reynoldsc6b371b2016-06-14 08:31:03 -0400158 extras, validator, contactsTimeoutMs, timeoutAffinity);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400159 }
John Spurlockb2278d62015-04-07 12:47:12 -0400160 }
161
162 public boolean isCall(NotificationRecord record) {
163 return mFiltering.isCall(record);
164 }
165
Julia Reynoldsc6b371b2016-06-14 08:31:03 -0400166 public void recordCaller(NotificationRecord record) {
167 mFiltering.recordCall(record);
168 }
169
John Spurlockb2278d62015-04-07 12:47:12 -0400170 public boolean shouldIntercept(NotificationRecord record) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400171 synchronized (mConfig) {
172 return mFiltering.shouldIntercept(mZenMode, mConfig, record);
173 }
John Spurlock056c5192014-04-20 21:52:01 -0400174 }
175
John Spurlock1c923a32014-04-27 16:42:29 -0400176 public void addCallback(Callback callback) {
177 mCallbacks.add(callback);
John Spurlock056c5192014-04-20 21:52:01 -0400178 }
179
John Spurlock530052a2014-11-30 16:26:19 -0500180 public void removeCallback(Callback callback) {
181 mCallbacks.remove(callback);
182 }
183
John Spurlockb2278d62015-04-07 12:47:12 -0400184 public void initZenMode() {
185 if (DEBUG) Log.d(TAG, "initZenMode");
186 evaluateZenMode("init", true /*setRingerMode*/);
187 }
188
John Spurlock661f2cf2014-11-17 10:29:10 -0500189 public void onSystemReady() {
John Spurlockb2278d62015-04-07 12:47:12 -0400190 if (DEBUG) Log.d(TAG, "onSystemReady");
John Spurlock661f2cf2014-11-17 10:29:10 -0500191 mAudioManager = LocalServices.getService(AudioManagerInternal.class);
192 if (mAudioManager != null) {
John Spurlockb2278d62015-04-07 12:47:12 -0400193 mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
John Spurlock661f2cf2014-11-17 10:29:10 -0500194 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500195 mPm = mContext.getPackageManager();
Chris Wren98d235b2015-05-27 18:25:17 -0400196 mHandler.postMetricsTimer();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500197 cleanUpZenRules();
Julia Reynolds8ac63032015-08-31 15:19:43 -0400198 evaluateZenMode("onSystemReady", true);
Beverly3bae4e52018-02-07 12:32:02 -0500199 mIsBootComplete = true;
200 showZenUpgradeNotification(mZenMode);
John Spurlockae641c92014-06-30 18:11:40 -0400201 }
202
John Spurlock21258a32015-05-27 18:22:55 -0400203 public void onUserSwitched(int user) {
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500204 loadConfigForUser(user, "onUserSwitched");
John Spurlock21258a32015-05-27 18:22:55 -0400205 }
206
207 public void onUserRemoved(int user) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700208 if (user < UserHandle.USER_SYSTEM) return;
John Spurlock21258a32015-05-27 18:22:55 -0400209 if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
210 mConfigs.remove(user);
211 }
212
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500213 public void onUserUnlocked(int user) {
214 loadConfigForUser(user, "onUserUnlocked");
215 }
216
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) {
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400228 setConfigLocked(config, null, reason);
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500229 }
230 cleanUpZenRules();
231 }
232
Christoph Studer85a384b2014-08-27 20:16:15 +0200233 public int getZenModeListenerInterruptionFilter() {
John Spurlock80774932015-05-07 17:38:50 -0400234 return NotificationManager.zenModeToInterruptionFilter(mZenMode);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400235 }
236
John Spurlock80774932015-05-07 17:38:50 -0400237 public void requestFromListener(ComponentName name, int filter) {
238 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400239 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400240 setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
John Spurlockb2278d62015-04-07 12:47:12 -0400241 "listener:" + (name != null ? name.flattenToShortString() : null));
John Spurlockd8afe3c2014-08-01 14:04:07 -0400242 }
243 }
244
Bryce Lee7219ada2016-04-08 10:54:23 -0700245 public void setSuppressedEffects(long suppressedEffects) {
246 if (mSuppressedEffects == suppressedEffects) return;
247 mSuppressedEffects = suppressedEffects;
John Spurlock8403b752014-12-10 12:47:01 -0500248 applyRestrictions();
249 }
250
Bryce Lee7219ada2016-04-08 10:54:23 -0700251 public long getSuppressedEffects() {
252 return mSuppressedEffects;
253 }
254
John Spurlock1c923a32014-04-27 16:42:29 -0400255 public int getZenMode() {
256 return mZenMode;
257 }
258
Julia Reynolds361e82d32016-02-26 18:19:49 -0500259 public List<ZenRule> getZenRules() {
260 List<ZenRule> rules = new ArrayList<>();
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400261 synchronized (mConfig) {
262 if (mConfig == null) return rules;
263 for (ZenRule rule : mConfig.automaticRules.values()) {
264 if (canManageAutomaticZenRule(rule)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500265 rules.add(rule);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400266 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400267 }
268 }
269 return rules;
270 }
271
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400272 public AutomaticZenRule getAutomaticZenRule(String id) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400273 ZenRule rule;
274 synchronized (mConfig) {
275 if (mConfig == null) return null;
276 rule = mConfig.automaticRules.get(id);
277 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400278 if (rule == null) return null;
279 if (canManageAutomaticZenRule(rule)) {
280 return createAutomaticZenRule(rule);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400281 }
282 return null;
283 }
284
Julia Reynolds361e82d32016-02-26 18:19:49 -0500285 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500286 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
Julia Reynolds7f2f4412016-03-01 12:33:48 -0500292 int ruleInstanceLimit = -1;
293 if (owner.metaData != null) {
294 ruleInstanceLimit = owner.metaData.getInt(
295 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
296 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500297 if (ruleInstanceLimit > 0 && ruleInstanceLimit
298 < (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) {
299 throw new IllegalArgumentException("Rule instance limit exceeded");
300 }
301 }
302
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400303 ZenModeConfig newConfig;
304 synchronized (mConfig) {
Julia Reynolds87c42772016-05-16 09:52:17 -0400305 if (mConfig == null) {
306 throw new AndroidRuntimeException("Could not create rule");
307 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400308 if (DEBUG) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500309 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400310 }
311 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500312 ZenRule rule = new ZenRule();
313 populateZenRule(automaticZenRule, rule, true);
314 newConfig.automaticRules.put(rule.id, rule);
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400315 if (setConfigLocked(newConfig, reason, rule.component, true)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500316 return rule.id;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500317 } else {
Julia Reynolds87c42772016-05-16 09:52:17 -0400318 throw new AndroidRuntimeException("Could not create rule");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500319 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400320 }
321 }
322
Julia Reynolds361e82d32016-02-26 18:19:49 -0500323 public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
324 String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400325 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();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500333 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 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400342 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500343 populateZenRule(automaticZenRule, rule, false);
344 newConfig.automaticRules.put(ruleId, rule);
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400345 return setConfigLocked(newConfig, reason, rule.component, true);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400346 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400347 }
348
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400349 public boolean removeAutomaticZenRule(String id, String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400350 ZenModeConfig newConfig;
351 synchronized (mConfig) {
352 if (mConfig == null) return false;
353 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500354 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 }
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400363 return setConfigLocked(newConfig, reason, null, true);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400364 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400365 }
366
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500367 public boolean removeAutomaticZenRules(String packageName, String reason) {
368 ZenModeConfig newConfig;
369 synchronized (mConfig) {
370 if (mConfig == null) return false;
371 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500372 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 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500378 }
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400379 return setConfigLocked(newConfig, reason, null, true);
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500380 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500381 }
382
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500383 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
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400395 public boolean canManageAutomaticZenRule(ZenRule rule) {
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500396 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)
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400400 == PackageManager.PERMISSION_GRANTED) {
401 return true;
402 } else {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500403 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400404 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
Beverlyd4f96492017-08-02 13:36:11 -0400416 public void setDefaultZenRules(Context context) {
417 mDefaultConfig = readDefaultConfig(context.getResources());
Beverlyd4f96492017-08-02 13:36:11 -0400418 appendDefaultRules(mDefaultConfig);
419 }
420
421 private void appendDefaultRules (ZenModeConfig config) {
Beverly30bfbca2017-10-17 14:38:20 -0400422 getDefaultRuleNames();
Beverly26eba872017-12-04 16:30:11 -0500423 appendDefaultEveryNightRule(config);
Beverlyd4f96492017-08-02 13:36:11 -0400424 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
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
439 protected void updateDefaultZenRules() {
440 ZenModeConfig configDefaultRules = new ZenModeConfig();
441 appendDefaultRules(configDefaultRules); // "new" localized default rules
Beverly26eba872017-12-04 16:30:11 -0500442 for (String ruleId : ZenModeConfig.DEFAULT_RULE_IDS) {
Beverlyd4f96492017-08-02 13:36:11 -0400443 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);
Beverly83639442017-09-06 10:36:04 -0400453 // ensure enabled state is carried over from current rule
454 defaultAutoRule.setEnabled(currRule.isEnabled());
Beverlyd4f96492017-08-02 13:36:11 -0400455 updateAutomaticZenRule(ruleId, defaultAutoRule,
456 "locale changed");
457 }
458 }
459 }
460 }
461
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500462 private boolean isSystemRule(AutomaticZenRule rule) {
463 return ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
464 }
465
466 private ServiceInfo getServiceInfo(ComponentName owner) {
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500467 Intent queryIntent = new Intent();
468 queryIntent.setComponent(owner);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500469 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500470 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)) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500478 return info;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500479 }
480 }
481 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500482 return null;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500483 }
484
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400485 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
Beverlyd4f96492017-08-02 13:36:11 -0400503 protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400504 return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
Julia Reynolds56106ff2015-09-30 14:42:53 -0400505 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
Julia Reynolds361e82d32016-02-26 18:19:49 -0500506 rule.creationTime);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400507 }
508
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400509 public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
510 setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
Beverly301e92a2018-04-27 09:43:05 -0400511 Settings.Global.putInt(mContext.getContentResolver(), Global.SHOW_ZEN_SETTINGS_SUGGESTION,
512 0);
John Spurlocke77bb362014-04-26 10:24:59 -0400513 }
514
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400515 private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
John Spurlockb2278d62015-04-07 12:47:12 -0400516 boolean setRingerMode) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400517 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();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500525 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 }
John Spurlockb2278d62015-04-07 12:47:12 -0400531 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500532 } else {
533 final ZenRule newRule = new ZenRule();
534 newRule.enabled = true;
535 newRule.zenMode = zenMode;
536 newRule.conditionId = conditionId;
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400537 newRule.enabler = caller;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500538 newConfig.manualRule = newRule;
John Spurlockb2278d62015-04-07 12:47:12 -0400539 }
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400540 setConfigLocked(newConfig, reason, null, setRingerMode);
John Spurlockb2278d62015-04-07 12:47:12 -0400541 }
John Spurlockb2278d62015-04-07 12:47:12 -0400542 }
543
Julia Reynolds520df6e2017-02-13 09:05:10 -0500544 void dump(ProtoOutputStream proto) {
Julia Reynolds520df6e2017-02-13 09:05:10 -0500545 proto.write(ZenModeProto.ZEN_MODE, mZenMode);
546 synchronized (mConfig) {
547 if (mConfig.manualRule != null) {
Kweku Adams99546332018-01-24 17:03:50 -0800548 mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500549 }
550 for (ZenRule rule : mConfig.automaticRules.values()) {
551 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
552 && !rule.snoozing) {
Kweku Adams99546332018-01-24 17:03:50 -0800553 rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500554 }
555 }
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800556 mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500557 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
558 }
559 }
560
John Spurlockb2278d62015-04-07 12:47:12 -0400561 public void dump(PrintWriter pw, String prefix) {
562 pw.print(prefix); pw.print("mZenMode=");
563 pw.println(Global.zenModeToString(mZenMode));
John Spurlock21258a32015-05-27 18:22:55 -0400564 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);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400569 synchronized (mConfig) {
570 dump(pw, prefix, "mConfig", mConfig);
571 }
Bryce Lee7219ada2016-04-08 10:54:23 -0700572
573 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
John Spurlock1d7d2242015-04-10 08:10:22 -0400574 mFiltering.dump(pw, prefix);
John Spurlockb2278d62015-04-07 12:47:12 -0400575 mConditions.dump(pw, prefix);
576 }
577
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 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500584 pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
Julia Reynolds1f580572018-04-27 14:48:36 -0400585 + "messages=%b,messagesFrom=%s,events=%b,reminders=%b)\n",
Beverlyd6964762018-02-16 14:07:03 -0500586 config.allowAlarms, config.allowMedia, config.allowSystem,
Julia Reynolds6ee26172015-09-28 11:34:48 -0400587 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
588 config.allowRepeatCallers, config.allowMessages,
589 ZenModeConfig.sourceToString(config.allowMessagesFrom),
Julia Reynolds1f580572018-04-27 14:48:36 -0400590 config.allowEvents, config.allowReminders);
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500591 pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
John Spurlockb2278d62015-04-07 12:47:12 -0400592 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
John Spurlock35ef0a62015-05-28 11:24:10 -0400601 public void readXml(XmlPullParser parser, boolean forRestore)
602 throws XmlPullParserException, IOException {
Beverly4e2f76c2018-03-16 15:43:49 -0400603 ZenModeConfig config = ZenModeConfig.readXml(parser);
604 String reason = "readXml";
605
John Spurlockb2278d62015-04-07 12:47:12 -0400606 if (config != null) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400607 if (forRestore) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700608 //TODO: http://b/22388012
609 if (config.user != UserHandle.USER_SYSTEM) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400610 return;
611 }
612 config.manualRule = null; // don't restore the manual rule
Beverly4e2f76c2018-03-16 15:43:49 -0400613 }
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) {
John Spurlock995a7492015-05-28 22:13:03 -0400620 // don't restore transient state from restored automatic rules
621 automaticRule.snoozing = false;
622 automaticRule.condition = null;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500623 automaticRule.creationTime = time;
John Spurlock995a7492015-05-28 22:13:03 -0400624 }
Beverly4e2f76c2018-03-16 15:43:49 -0400625 resetToDefaultRules &= !automaticRule.enabled;
John Spurlock995a7492015-05-28 22:13:03 -0400626 }
John Spurlock35ef0a62015-05-28 11:24:10 -0400627 }
Beverly4e2f76c2018-03-16 15:43:49 -0400628
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 }
Beverly301e92a2018-04-27 09:43:05 -0400640 } else {
641 // devices not restoring/upgrading already have updated zen settings
642 Settings.Global.putInt(mContext.getContentResolver(),
643 Global.ZEN_SETTINGS_UPDATED, 1);
Beverly4e2f76c2018-03-16 15:43:49 -0400644 }
645 if (DEBUG) Log.d(TAG, reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500646 synchronized (mConfig) {
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400647 setConfigLocked(config, null, reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500648 }
John Spurlockb2278d62015-04-07 12:47:12 -0400649 }
650 }
651
Beverly4e2f76c2018-03-16 15:43:49 -0400652 public void writeXml(XmlSerializer out, boolean forBackup, Integer version) throws IOException {
John Spurlock21258a32015-05-27 18:22:55 -0400653 final int N = mConfigs.size();
654 for (int i = 0; i < N; i++) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700655 //TODO: http://b/22388012
656 if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400657 continue;
658 }
Beverly4e2f76c2018-03-16 15:43:49 -0400659 mConfigs.valueAt(i).writeXml(out, version);
John Spurlock21258a32015-05-27 18:22:55 -0400660 }
John Spurlockb2278d62015-04-07 12:47:12 -0400661 }
662
John Spurlock1fc476d2015-04-14 16:05:20 -0400663 public Policy getNotificationPolicy() {
664 return getNotificationPolicy(mConfig);
665 }
666
667 private static Policy getNotificationPolicy(ZenModeConfig config) {
668 return config == null ? null : config.toNotificationPolicy();
669 }
670
671 public void setNotificationPolicy(Policy policy) {
672 if (policy == null || mConfig == null) return;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500673 synchronized (mConfig) {
674 final ZenModeConfig newConfig = mConfig.copy();
675 newConfig.applyNotificationPolicy(policy);
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400676 setConfigLocked(newConfig, null, "setNotificationPolicy");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500677 }
John Spurlock1fc476d2015-04-14 16:05:20 -0400678 }
679
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500680 /**
681 * Removes old rule instances whose owner is not installed.
682 */
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 {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700692 mPm.getPackageInfo(rule.component.getPackageName(),
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700693 PackageManager.MATCH_ANY_USER);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500694 } catch (PackageManager.NameNotFoundException e) {
695 newConfig.automaticRules.removeAt(i);
696 }
697 }
698 }
699 }
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400700 setConfigLocked(newConfig, null, "cleanUpZenRules");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500701 }
702 }
703
704 /**
705 * @return a copy of the zen mode configuration
706 */
John Spurlockb2278d62015-04-07 12:47:12 -0400707 public ZenModeConfig getConfig() {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400708 synchronized (mConfig) {
709 return mConfig.copy();
710 }
John Spurlockb2278d62015-04-07 12:47:12 -0400711 }
712
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400713 public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
714 String reason) {
715 return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -0400716 }
717
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400718 public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) {
Julia Reynolds89aeab02016-09-15 11:07:50 -0400719 synchronized (mConfig) {
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400720 setConfigLocked(config, triggeringComponent, reason);
Julia Reynolds89aeab02016-09-15 11:07:50 -0400721 }
Eric Laurente0ced4d2015-09-30 17:44:28 -0700722 }
723
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400724 private boolean setConfigLocked(ZenModeConfig config, String reason,
725 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400726 final long identity = Binder.clearCallingIdentity();
727 try {
728 if (config == null || !config.isValid()) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500729 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400730 return false;
731 }
732 if (config.user != mUser) {
733 // simply store away for background users
734 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500735 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400736 return true;
737 }
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400738 // may modify config
739 mConditions.evaluateConfig(config, null, false /*processSubscriptions*/);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500740 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500741 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500742 ZenLog.traceConfig(reason, mConfig, config);
743 final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
744 getNotificationPolicy(config));
Julia Reynolds9a25da12016-01-06 16:19:28 -0500745 if (!config.equals(mConfig)) {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500746 dispatchOnConfigChanged();
747 }
748 if (policyChanged) {
749 dispatchOnPolicyChanged();
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400750 }
Julia Reynolds9a25da12016-01-06 16:19:28 -0500751 mConfig = config;
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400752 mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode);
John Spurlock21258a32015-05-27 18:22:55 -0400753 return true;
Julia Reynoldscb507b82017-09-07 13:53:40 -0400754 } catch (SecurityException e) {
755 Log.wtf(TAG, "Invalid rule in config", e);
756 return false;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400757 } finally {
758 Binder.restoreCallingIdentity(identity);
John Spurlock21258a32015-05-27 18:22:55 -0400759 }
John Spurlockb2278d62015-04-07 12:47:12 -0400760 }
761
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400762 private void applyConfig(ZenModeConfig config, String reason,
763 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400764 final String val = Integer.toString(config.hashCode());
765 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
766 if (!evaluateZenMode(reason, setRingerMode)) {
767 applyRestrictions(); // evaluateZenMode will also apply restrictions if changed
768 }
Julia Reynolds4bcf9b82018-07-13 15:12:29 -0400769 mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400770 }
771
John Spurlockb2278d62015-04-07 12:47:12 -0400772 private int getZenModeSetting() {
773 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
774 }
775
Beverly3bae4e52018-02-07 12:32:02 -0500776 @VisibleForTesting
777 protected void setZenModeSetting(int zen) {
John Spurlockb2278d62015-04-07 12:47:12 -0400778 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
Beverly3bae4e52018-02-07 12:32:02 -0500779 showZenUpgradeNotification(zen);
John Spurlockb2278d62015-04-07 12:47:12 -0400780 }
781
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400782 private int getPreviousRingerModeSetting() {
783 return Global.getInt(mContext.getContentResolver(),
784 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
785 }
786
787 private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
788 Global.putString(
789 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
790 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
791 }
792
Beverlye4ee1cc2018-03-06 17:21:08 -0500793 @VisibleForTesting
794 protected boolean evaluateZenMode(String reason, boolean setRingerMode) {
John Spurlockb2278d62015-04-07 12:47:12 -0400795 if (DEBUG) Log.d(TAG, "evaluateZenMode");
Jason Monka9927322015-12-13 16:22:37 -0500796 final int zenBefore = mZenMode;
Julia Reynolds8ac63032015-08-31 15:19:43 -0400797 final int zen = computeZenMode();
John Spurlockb2278d62015-04-07 12:47:12 -0400798 ZenLog.traceSetZenMode(zen, reason);
799 mZenMode = zen;
800 setZenModeSetting(mZenMode);
Beverlyd6964762018-02-16 14:07:03 -0500801 updateRingerModeAffectedStreams();
Beverlye4ee1cc2018-03-06 17:21:08 -0500802 if (setRingerMode && zen != zenBefore) {
John Spurlock57627792014-12-11 11:29:54 -0500803 applyZenToRingerMode();
804 }
805 applyRestrictions();
Jason Monka9927322015-12-13 16:22:37 -0500806 if (zen != zenBefore) {
Julia Reynolds8ac63032015-08-31 15:19:43 -0400807 mHandler.postDispatchOnZenModeChanged();
808 }
John Spurlockb2278d62015-04-07 12:47:12 -0400809 return true;
John Spurlock57627792014-12-11 11:29:54 -0500810 }
811
John Spurlock50ced3f2015-05-11 16:00:09 -0400812 private void updateRingerModeAffectedStreams() {
813 if (mAudioManager != null) {
814 mAudioManager.updateRingerModeAffectedStreamsInternal();
815 }
816 }
817
Julia Reynolds8ac63032015-08-31 15:19:43 -0400818 private int computeZenMode() {
Beverlye4ee1cc2018-03-06 17:21:08 -0500819 if (mConfig == null) return Global.ZEN_MODE_OFF;
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400820 synchronized (mConfig) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400821 if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
822 int zen = Global.ZEN_MODE_OFF;
823 for (ZenRule automaticRule : mConfig.automaticRules.values()) {
824 if (automaticRule.isAutomaticActive()) {
825 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
Beverly301e92a2018-04-27 09:43:05 -0400826 // automatic rule triggered dnd and user hasn't seen update dnd dialog
827 if (Settings.Global.getInt(mContext.getContentResolver(),
828 Global.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
829 Settings.Global.putInt(mContext.getContentResolver(),
830 Global.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
831 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400832 zen = automaticRule.zenMode;
833 }
John Spurlockb2278d62015-04-07 12:47:12 -0400834 }
835 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400836 return zen;
John Spurlockb2278d62015-04-07 12:47:12 -0400837 }
John Spurlock8403b752014-12-10 12:47:01 -0500838 }
839
Beverly30bfbca2017-10-17 14:38:20 -0400840 private void getDefaultRuleNames() {
841 // on locale-change, these values differ
Beverly26eba872017-12-04 16:30:11 -0500842 mDefaultRuleEveryNightName = mContext.getResources()
843 .getString(R.string.zen_mode_default_every_night_name);
Beverly30bfbca2017-10-17 14:38:20 -0400844 mDefaultRuleEventsName = mContext.getResources()
845 .getString(R.string.zen_mode_default_events_name);
846 }
847
Beverly04216872017-09-28 10:55:32 -0400848 @VisibleForTesting
849 protected void applyRestrictions() {
Beverlyd820bc22018-01-11 15:28:33 -0500850 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
Beverly925cde82018-01-23 09:31:23 -0500851 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
Beverlyd820bc22018-01-11 15:28:33 -0500852 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
John Spurlock8403b752014-12-10 12:47:01 -0500853
854 // notification restrictions
Bryce Lee7219ada2016-04-08 10:54:23 -0700855 final boolean muteNotifications =
856 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
John Spurlock056c5192014-04-20 21:52:01 -0400857 // call restrictions
Beverlyd820bc22018-01-11 15:28:33 -0500858 final boolean muteCalls = zenAlarmsOnly
859 || (zenPriorityOnly && !mConfig.allowCalls && !mConfig.allowRepeatCallers)
Bryce Lee7219ada2016-04-08 10:54:23 -0700860 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
Beverly04216872017-09-28 10:55:32 -0400861 // alarm restrictions
Beverlyd820bc22018-01-11 15:28:33 -0500862 final boolean muteAlarms = zenPriorityOnly && !mConfig.allowAlarms;
Beverlyd6964762018-02-16 14:07:03 -0500863 // media restrictions
864 final boolean muteMedia = zenPriorityOnly && !mConfig.allowMedia;
865 // system restrictions
866 final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !mConfig.allowSystem);
Julia Reynolds3fe81be2016-02-03 09:10:06 -0500867 // total silence restrictions
Beverlyd820bc22018-01-11 15:28:33 -0500868 final boolean muteEverything = zenSilence
Beverly925cde82018-01-23 09:31:23 -0500869 || (zenPriorityOnly && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConfig));
John Spurlock25d01ee2015-06-03 12:17:46 -0400870
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700871 for (int usage : AudioAttributes.SDK_USAGES) {
872 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700873 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
874 applyRestrictions(false /*mute*/, usage);
875 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700876 applyRestrictions(muteNotifications || muteEverything, usage);
877 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
878 applyRestrictions(muteCalls || muteEverything, usage);
Beverly04216872017-09-28 10:55:32 -0400879 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
880 applyRestrictions(muteAlarms || muteEverything, usage);
Beverlyd6964762018-02-16 14:07:03 -0500881 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
882 applyRestrictions(muteMedia || muteEverything, usage);
883 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
Beverly738bffd2018-03-12 10:46:17 -0400884 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
885 // normally DND will only restrict touch sounds, not haptic feedback/vibrations
886 applyRestrictions(muteSystem || muteEverything, usage,
887 AppOpsManager.OP_PLAY_AUDIO);
888 applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE);
889 } else {
890 applyRestrictions(muteSystem || muteEverything, usage);
891 }
Julia Reynolds3fe81be2016-02-03 09:10:06 -0500892 } else {
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700893 applyRestrictions(muteEverything, usage);
Julia Reynolds3fe81be2016-02-03 09:10:06 -0500894 }
895 }
John Spurlock8403b752014-12-10 12:47:01 -0500896 }
John Spurlockae641c92014-06-30 18:11:40 -0400897
Beverlye2d9a232017-11-08 18:14:59 -0500898
Beverly04216872017-09-28 10:55:32 -0400899 @VisibleForTesting
Beverly738bffd2018-03-12 10:46:17 -0400900 protected void applyRestrictions(boolean mute, int usage, int code) {
John Spurlock8403b752014-12-10 12:47:01 -0500901 final String[] exceptionPackages = null; // none (for now)
Beverlye2d9a232017-11-08 18:14:59 -0500902
Dianne Hackbornbf1b57d2018-03-07 12:42:47 -0800903 // Only do this if we are executing within the system process... otherwise
904 // we are running as test code, so don't have access to the protected call.
905 if (Process.myUid() == Process.SYSTEM_UID) {
906 final long ident = Binder.clearCallingIdentity();
907 try {
908 mAppOps.setRestriction(code, usage,
909 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
910 exceptionPackages);
911 } finally {
912 Binder.restoreCallingIdentity(ident);
913 }
914 }
John Spurlock056c5192014-04-20 21:52:01 -0400915 }
916
Beverly85f52412018-02-27 10:41:13 -0500917 @VisibleForTesting
Beverly738bffd2018-03-12 10:46:17 -0400918 protected void applyRestrictions(boolean mute, int usage) {
919 applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE);
920 applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO);
921 }
922
923
924 @VisibleForTesting
Beverly85f52412018-02-27 10:41:13 -0500925 protected void applyZenToRingerMode() {
John Spurlock661f2cf2014-11-17 10:29:10 -0500926 if (mAudioManager == null) return;
John Spurlock661f2cf2014-11-17 10:29:10 -0500927 // force the ringer mode into compliance
928 final int ringerModeInternal = mAudioManager.getRingerModeInternal();
929 int newRingerModeInternal = ringerModeInternal;
John Spurlock57627792014-12-11 11:29:54 -0500930 switch (mZenMode) {
John Spurlock661f2cf2014-11-17 10:29:10 -0500931 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlock4f1163c2015-04-02 17:41:21 -0400932 case Global.ZEN_MODE_ALARMS:
John Spurlock661f2cf2014-11-17 10:29:10 -0500933 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400934 setPreviousRingerModeSetting(ringerModeInternal);
John Spurlock661f2cf2014-11-17 10:29:10 -0500935 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
John Spurlock8c01d882014-07-28 13:37:13 -0400936 }
John Spurlock661f2cf2014-11-17 10:29:10 -0500937 break;
938 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
Beverly9e4214d2018-03-26 11:10:10 -0400939 // do not apply zen to ringer, streams zen muted in AudioService
Beverly925cde82018-01-23 09:31:23 -0500940 break;
John Spurlock661f2cf2014-11-17 10:29:10 -0500941 case Global.ZEN_MODE_OFF:
942 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400943 newRingerModeInternal = getPreviousRingerModeSetting();
944 setPreviousRingerModeSetting(null);
John Spurlock661f2cf2014-11-17 10:29:10 -0500945 }
946 break;
John Spurlock8c01d882014-07-28 13:37:13 -0400947 }
John Spurlock661f2cf2014-11-17 10:29:10 -0500948 if (newRingerModeInternal != -1) {
949 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
950 }
951 }
952
John Spurlock1c923a32014-04-27 16:42:29 -0400953 private void dispatchOnConfigChanged() {
954 for (Callback callback : mCallbacks) {
955 callback.onConfigChanged();
956 }
957 }
958
John Spurlock1fc476d2015-04-14 16:05:20 -0400959 private void dispatchOnPolicyChanged() {
960 for (Callback callback : mCallbacks) {
961 callback.onPolicyChanged();
962 }
963 }
964
John Spurlock1c923a32014-04-27 16:42:29 -0400965 private void dispatchOnZenModeChanged() {
966 for (Callback callback : mCallbacks) {
967 callback.onZenModeChanged();
968 }
969 }
970
John Spurlockb2278d62015-04-07 12:47:12 -0400971 private ZenModeConfig readDefaultConfig(Resources resources) {
972 XmlResourceParser parser = null;
973 try {
974 parser = resources.getXml(R.xml.default_zen_mode_config);
975 while (parser.next() != XmlPullParser.END_DOCUMENT) {
Julia Reynolds206c7e92016-09-15 10:38:03 -0400976 final ZenModeConfig config = ZenModeConfig.readXml(parser);
John Spurlockb2278d62015-04-07 12:47:12 -0400977 if (config != null) return config;
978 }
979 } catch (Exception e) {
980 Log.w(TAG, "Error reading default zen mode config from resource", e);
981 } finally {
982 IoUtils.closeQuietly(parser);
983 }
984 return new ZenModeConfig();
985 }
986
Beverly26eba872017-12-04 16:30:11 -0500987 private void appendDefaultEveryNightRule(ZenModeConfig config) {
John Spurlockb2278d62015-04-07 12:47:12 -0400988 if (config == null) return;
989
990 final ScheduleInfo weeknights = new ScheduleInfo();
Beverly26eba872017-12-04 16:30:11 -0500991 weeknights.days = ZenModeConfig.ALL_DAYS;
John Spurlockb2278d62015-04-07 12:47:12 -0400992 weeknights.startHour = 22;
993 weeknights.endHour = 7;
Beverly30bfbca2017-10-17 14:38:20 -0400994 weeknights.exitAtAlarm = true;
Beverly26eba872017-12-04 16:30:11 -0500995 final ZenRule rule = new ZenRule();
996 rule.enabled = false;
997 rule.name = mDefaultRuleEveryNightName;
998 rule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
999 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
1000 rule.component = ScheduleConditionProvider.COMPONENT;
1001 rule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
1002 rule.creationTime = System.currentTimeMillis();
1003 config.automaticRules.put(rule.id, rule);
John Spurlockb2278d62015-04-07 12:47:12 -04001004 }
1005
John Spurlockcb9aa202015-05-08 17:35:22 -04001006 private void appendDefaultEventRules(ZenModeConfig config) {
1007 if (config == null) return;
1008
1009 final EventInfo events = new EventInfo();
John Spurlock995a7492015-05-28 22:13:03 -04001010 events.calendar = null; // any calendar
John Spurlockcb9aa202015-05-08 17:35:22 -04001011 events.reply = EventInfo.REPLY_YES_OR_MAYBE;
1012 final ZenRule rule = new ZenRule();
1013 rule.enabled = false;
Beverlyd4f96492017-08-02 13:36:11 -04001014 rule.name = mDefaultRuleEventsName;
John Spurlockcb9aa202015-05-08 17:35:22 -04001015 rule.conditionId = ZenModeConfig.toEventConditionId(events);
Beverlybf16c142017-11-27 16:21:34 -05001016 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -04001017 rule.component = EventConditionProvider.COMPONENT;
Beverly26eba872017-12-04 16:30:11 -05001018 rule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
Julia Reynolds56106ff2015-09-30 14:42:53 -04001019 rule.creationTime = System.currentTimeMillis();
1020 config.automaticRules.put(rule.id, rule);
John Spurlockcb9aa202015-05-08 17:35:22 -04001021 }
1022
John Spurlockb2278d62015-04-07 12:47:12 -04001023 private static int zenSeverity(int zen) {
1024 switch (zen) {
1025 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
1026 case Global.ZEN_MODE_ALARMS: return 2;
1027 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
1028 default: return 0;
1029 }
1030 }
1031
Beverly85f52412018-02-27 10:41:13 -05001032 @VisibleForTesting
1033 protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
John Spurlockb2278d62015-04-07 12:47:12 -04001034 @Override
1035 public String toString() {
1036 return TAG;
1037 }
1038
1039 @Override
1040 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
1041 int ringerModeExternal, VolumePolicy policy) {
1042 final boolean isChange = ringerModeOld != ringerModeNew;
1043
1044 int ringerModeExternalOut = ringerModeNew;
1045
Beverlye4ee1cc2018-03-06 17:21:08 -05001046 if (mZenMode == Global.ZEN_MODE_OFF
1047 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1048 && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) {
1049 // in priority only with ringer not muted, save ringer mode changes
1050 // in dnd off, save ringer mode changes
1051 setPreviousRingerModeSetting(ringerModeNew);
1052 }
John Spurlockb2278d62015-04-07 12:47:12 -04001053 int newZen = -1;
1054 switch (ringerModeNew) {
1055 case AudioManager.RINGER_MODE_SILENT:
1056 if (isChange && policy.doNotDisturbWhenSilent) {
Beverly925cde82018-01-23 09:31:23 -05001057 if (mZenMode == Global.ZEN_MODE_OFF) {
Julia Reynoldsf3252be2018-01-17 09:26:21 -05001058 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
John Spurlockb2278d62015-04-07 12:47:12 -04001059 }
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001060 setPreviousRingerModeSetting(ringerModeOld);
John Spurlockb2278d62015-04-07 12:47:12 -04001061 }
1062 break;
1063 case AudioManager.RINGER_MODE_VIBRATE:
1064 case AudioManager.RINGER_MODE_NORMAL:
1065 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
1066 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
Beverly925cde82018-01-23 09:31:23 -05001067 || mZenMode == Global.ZEN_MODE_ALARMS
1068 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1069 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
Beverlyd6964762018-02-16 14:07:03 -05001070 mConfig)))) {
John Spurlockb2278d62015-04-07 12:47:12 -04001071 newZen = Global.ZEN_MODE_OFF;
1072 } else if (mZenMode != Global.ZEN_MODE_OFF) {
1073 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
1074 }
1075 break;
1076 }
Beverly85f52412018-02-27 10:41:13 -05001077
John Spurlockb2278d62015-04-07 12:47:12 -04001078 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001079 setManualZenMode(newZen, null, "ringerModeInternal", null,
1080 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001081 }
John Spurlockb2278d62015-04-07 12:47:12 -04001082 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
1083 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
1084 ringerModeExternal, ringerModeExternalOut);
1085 }
1086 return ringerModeExternalOut;
1087 }
1088
1089 @Override
1090 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
1091 int ringerModeInternal, VolumePolicy policy) {
1092 int ringerModeInternalOut = ringerModeNew;
1093 final boolean isChange = ringerModeOld != ringerModeNew;
1094 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
1095
1096 int newZen = -1;
1097 switch (ringerModeNew) {
1098 case AudioManager.RINGER_MODE_SILENT:
1099 if (isChange) {
1100 if (mZenMode == Global.ZEN_MODE_OFF) {
Julia Reynoldsf3252be2018-01-17 09:26:21 -05001101 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
John Spurlockb2278d62015-04-07 12:47:12 -04001102 }
1103 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
John Spurlock05715ec2015-05-13 11:19:19 -04001104 : AudioManager.RINGER_MODE_SILENT;
John Spurlockb2278d62015-04-07 12:47:12 -04001105 } else {
1106 ringerModeInternalOut = ringerModeInternal;
1107 }
1108 break;
1109 case AudioManager.RINGER_MODE_VIBRATE:
1110 case AudioManager.RINGER_MODE_NORMAL:
1111 if (mZenMode != Global.ZEN_MODE_OFF) {
1112 newZen = Global.ZEN_MODE_OFF;
1113 }
1114 break;
1115 }
1116 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001117 setManualZenMode(newZen, null, "ringerModeExternal", caller,
1118 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001119 }
1120
1121 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
1122 ringerModeInternal, ringerModeInternalOut);
1123 return ringerModeInternalOut;
1124 }
John Spurlockd9c75db2015-04-28 11:19:13 -04001125
1126 @Override
1127 public boolean canVolumeDownEnterSilent() {
1128 return mZenMode == Global.ZEN_MODE_OFF;
1129 }
John Spurlock50ced3f2015-05-11 16:00:09 -04001130
1131 @Override
1132 public int getRingerModeAffectedStreams(int streams) {
Beverlyd6964762018-02-16 14:07:03 -05001133 // ringtone and notification streams are always affected by ringer mode
1134 // system stream is affected by ringer mode when not in priority-only
John Spurlock50ced3f2015-05-11 16:00:09 -04001135 streams |= (1 << AudioSystem.STREAM_RING) |
Beverlyd6964762018-02-16 14:07:03 -05001136 (1 << AudioSystem.STREAM_NOTIFICATION) |
1137 (1 << AudioSystem.STREAM_SYSTEM);
John Spurlock50ced3f2015-05-11 16:00:09 -04001138
John Spurlock50ced3f2015-05-11 16:00:09 -04001139 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
Beverly925cde82018-01-23 09:31:23 -05001140 // alarm and music streams affected by ringer mode when in total silence
John Spurlock50ced3f2015-05-11 16:00:09 -04001141 streams |= (1 << AudioSystem.STREAM_ALARM) |
Beverlyd6964762018-02-16 14:07:03 -05001142 (1 << AudioSystem.STREAM_MUSIC);
John Spurlock50ced3f2015-05-11 16:00:09 -04001143 } else {
1144 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
Beverlyd6964762018-02-16 14:07:03 -05001145 (1 << AudioSystem.STREAM_MUSIC));
1146 }
1147
1148 if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1149 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) {
1150 // system stream is not affected by ringer mode in priority only when the ringer
1151 // is zen muted (all other notification categories are muted)
1152 streams &= ~(1 << AudioSystem.STREAM_SYSTEM);
1153 } else {
1154 streams |= (1 << AudioSystem.STREAM_SYSTEM);
John Spurlock50ced3f2015-05-11 16:00:09 -04001155 }
1156 return streams;
1157 }
John Spurlockb2278d62015-04-07 12:47:12 -04001158 }
1159
1160 private final class SettingsObserver extends ContentObserver {
John Spurlock056c5192014-04-20 21:52:01 -04001161 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1162
1163 public SettingsObserver(Handler handler) {
1164 super(handler);
1165 }
1166
1167 public void observe() {
1168 final ContentResolver resolver = mContext.getContentResolver();
1169 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1170 update(null);
1171 }
1172
1173 @Override
1174 public void onChange(boolean selfChange, Uri uri) {
1175 update(uri);
1176 }
1177
1178 public void update(Uri uri) {
1179 if (ZEN_MODE.equals(uri)) {
John Spurlockb2278d62015-04-07 12:47:12 -04001180 if (mZenMode != getZenModeSetting()) {
1181 if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1182 setZenModeSetting(mZenMode);
1183 }
John Spurlock056c5192014-04-20 21:52:01 -04001184 }
1185 }
1186 }
1187
Beverly3bae4e52018-02-07 12:32:02 -05001188 private void showZenUpgradeNotification(int zen) {
1189 final boolean showNotification = mIsBootComplete
Julia Reynolds76bfa602018-04-23 09:38:47 -04001190 && zen != Global.ZEN_MODE_OFF
Beverly3bae4e52018-02-07 12:32:02 -05001191 && Settings.Global.getInt(mContext.getContentResolver(),
1192 Settings.Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0;
1193
1194 if (showNotification) {
1195 mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
1196 createZenUpgradeNotification());
1197 Settings.Global.putInt(mContext.getContentResolver(),
1198 Global.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
1199 }
1200 }
1201
1202 @VisibleForTesting
1203 protected Notification createZenUpgradeNotification() {
Beverly3bae4e52018-02-07 12:32:02 -05001204 final Bundle extras = new Bundle();
1205 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
1206 mContext.getResources().getString(R.string.global_action_settings));
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001207 int title = R.string.zen_upgrade_notification_title;
1208 int content = R.string.zen_upgrade_notification_content;
Julia Reynolds76bfa602018-04-23 09:38:47 -04001209 int drawable = R.drawable.ic_zen_24dp;
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001210 if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
1211 getNotificationPolicy().suppressedVisualEffects)) {
1212 title = R.string.zen_upgrade_notification_visd_title;
1213 content = R.string.zen_upgrade_notification_visd_content;
Julia Reynolds76bfa602018-04-23 09:38:47 -04001214 drawable = R.drawable.ic_dnd_block_notifications;
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001215 }
Julia Reynolds76bfa602018-04-23 09:38:47 -04001216
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001217 Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
1218 onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001219 return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001220 .setAutoCancel(true)
Beverlyd8b15ee2018-02-13 14:37:38 -05001221 .setSmallIcon(R.drawable.ic_settings_24dp)
Julia Reynolds76bfa602018-04-23 09:38:47 -04001222 .setLargeIcon(Icon.createWithResource(mContext, drawable))
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001223 .setContentTitle(mContext.getResources().getString(title))
1224 .setContentText(mContext.getResources().getString(content))
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001225 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
1226 PendingIntent.FLAG_UPDATE_CURRENT))
Beverly3bae4e52018-02-07 12:32:02 -05001227 .setAutoCancel(true)
1228 .setLocalOnly(true)
1229 .addExtras(extras)
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001230 .setStyle(new Notification.BigTextStyle())
Beverly3bae4e52018-02-07 12:32:02 -05001231 .build();
1232 }
1233
Chris Wren98d235b2015-05-27 18:25:17 -04001234 private final class Metrics extends Callback {
1235 private static final String COUNTER_PREFIX = "dnd_mode_";
1236 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1237
1238 private int mPreviousZenMode = -1;
1239 private long mBeginningMs = 0L;
1240
1241 @Override
1242 void onZenModeChanged() {
1243 emit();
1244 }
1245
1246 private void emit() {
1247 mHandler.postMetricsTimer();
1248 final long now = SystemClock.elapsedRealtime();
1249 final long since = (now - mBeginningMs);
1250 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1251 if (mPreviousZenMode != -1) {
1252 MetricsLogger.count(mContext, COUNTER_PREFIX + mPreviousZenMode, (int) since);
1253 }
1254 mPreviousZenMode = mZenMode;
1255 mBeginningMs = now;
1256 }
1257 }
1258 }
1259
John Spurlockb2278d62015-04-07 12:47:12 -04001260 private final class H extends Handler {
John Spurlock57627792014-12-11 11:29:54 -05001261 private static final int MSG_DISPATCH = 1;
Chris Wren98d235b2015-05-27 18:25:17 -04001262 private static final int MSG_METRICS = 2;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001263 private static final int MSG_APPLY_CONFIG = 4;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001264
1265 private final class ConfigMessageData {
1266 public final ZenModeConfig config;
Julia Reynolds4bcf9b82018-07-13 15:12:29 -04001267 public ComponentName triggeringComponent;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001268 public final String reason;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001269 public final boolean setRingerMode;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001270
Julia Reynolds4bcf9b82018-07-13 15:12:29 -04001271 ConfigMessageData(ZenModeConfig config, String reason,
1272 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001273 this.config = config;
1274 this.reason = reason;
1275 this.setRingerMode = setRingerMode;
Julia Reynolds4bcf9b82018-07-13 15:12:29 -04001276 this.triggeringComponent = triggeringComponent;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001277 }
1278 }
Chris Wren98d235b2015-05-27 18:25:17 -04001279
1280 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
John Spurlock661f2cf2014-11-17 10:29:10 -05001281
1282 private H(Looper looper) {
1283 super(looper);
John Spurlock056c5192014-04-20 21:52:01 -04001284 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001285
John Spurlock57627792014-12-11 11:29:54 -05001286 private void postDispatchOnZenModeChanged() {
1287 removeMessages(MSG_DISPATCH);
1288 sendEmptyMessage(MSG_DISPATCH);
John Spurlock661f2cf2014-11-17 10:29:10 -05001289 }
1290
Chris Wren98d235b2015-05-27 18:25:17 -04001291 private void postMetricsTimer() {
1292 removeMessages(MSG_METRICS);
1293 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1294 }
1295
Julia Reynolds4bcf9b82018-07-13 15:12:29 -04001296 private void postApplyConfig(ZenModeConfig config, String reason,
1297 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001298 sendMessage(obtainMessage(MSG_APPLY_CONFIG,
Julia Reynolds4bcf9b82018-07-13 15:12:29 -04001299 new ConfigMessageData(config, reason, triggeringComponent, setRingerMode)));
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001300 }
1301
John Spurlock661f2cf2014-11-17 10:29:10 -05001302 @Override
1303 public void handleMessage(Message msg) {
John Spurlock57627792014-12-11 11:29:54 -05001304 switch (msg.what) {
1305 case MSG_DISPATCH:
1306 dispatchOnZenModeChanged();
John Spurlock661f2cf2014-11-17 10:29:10 -05001307 break;
Chris Wren98d235b2015-05-27 18:25:17 -04001308 case MSG_METRICS:
1309 mMetrics.emit();
1310 break;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001311 case MSG_APPLY_CONFIG:
1312 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1313 applyConfig(applyConfigData.config, applyConfigData.reason,
Julia Reynolds4bcf9b82018-07-13 15:12:29 -04001314 applyConfigData.triggeringComponent, applyConfigData.setRingerMode);
John Spurlock661f2cf2014-11-17 10:29:10 -05001315 }
1316 }
1317 }
John Spurlock056c5192014-04-20 21:52:01 -04001318
John Spurlock1c923a32014-04-27 16:42:29 -04001319 public static class Callback {
1320 void onConfigChanged() {}
1321 void onZenModeChanged() {}
John Spurlock1fc476d2015-04-14 16:05:20 -04001322 void onPolicyChanged() {}
John Spurlock056c5192014-04-20 21:52:01 -04001323 }
John Spurlockb2278d62015-04-07 12:47:12 -04001324
John Spurlock056c5192014-04-20 21:52:01 -04001325}