blob: f81015dae4685fd98f3f9c8bb5d41af0a97d6cd3 [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 Reynolds68062072018-08-06 15:38:21 -040029import android.content.pm.ActivityInfo;
30import android.content.pm.PackageItemInfo;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040031import android.content.pm.PackageManager;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -050032import android.content.pm.ResolveInfo;
33import android.content.pm.ServiceInfo;
John Spurlock056c5192014-04-20 21:52:01 -040034import android.content.res.Resources;
35import android.content.res.XmlResourceParser;
36import android.database.ContentObserver;
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -040037import android.graphics.drawable.Icon;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -070038import android.media.AudioAttributes;
John Spurlock056c5192014-04-20 21:52:01 -040039import android.media.AudioManager;
John Spurlock661f2cf2014-11-17 10:29:10 -050040import android.media.AudioManagerInternal;
John Spurlock50ced3f2015-05-11 16:00:09 -040041import android.media.AudioSystem;
John Spurlocka48d7792015-03-03 17:35:57 -050042import android.media.VolumePolicy;
John Spurlock056c5192014-04-20 21:52:01 -040043import android.net.Uri;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040044import android.os.Binder;
John Spurlock2b122f42014-08-27 16:29:47 -040045import android.os.Bundle;
John Spurlock056c5192014-04-20 21:52:01 -040046import android.os.Handler;
John Spurlock661f2cf2014-11-17 10:29:10 -050047import android.os.Looper;
48import android.os.Message;
Julia Reynoldsc8e54e82015-11-30 16:43:05 -050049import android.os.Process;
Chris Wren98d235b2015-05-27 18:25:17 -040050import android.os.SystemClock;
John Spurlockb5e767b2014-07-27 11:53:20 -040051import android.os.UserHandle;
Beverly3bae4e52018-02-07 12:32:02 -050052import android.provider.Settings;
John Spurlock056c5192014-04-20 21:52:01 -040053import android.provider.Settings.Global;
Julia Reynolds520df6e2017-02-13 09:05:10 -050054import android.service.notification.Condition;
Julia Reynolds43b70cd2016-01-14 15:05:34 -050055import android.service.notification.ConditionProviderService;
John Spurlock056c5192014-04-20 21:52:01 -040056import android.service.notification.ZenModeConfig;
John Spurlockb2278d62015-04-07 12:47:12 -040057import android.service.notification.ZenModeConfig.ZenRule;
Julia Reynolds520df6e2017-02-13 09:05:10 -050058import android.service.notification.ZenModeProto;
Beverlyff2df9b2018-10-10 16:54:10 -040059import android.service.notification.ZenPolicy;
Julia Reynolds87c42772016-05-16 09:52:17 -040060import android.util.AndroidRuntimeException;
Beverly4e2f76c2018-03-16 15:43:49 -040061import android.util.ArrayMap;
John Spurlock4db0d982014-08-13 09:19:03 -040062import android.util.Log;
Beverlyd4f96492017-08-02 13:36:11 -040063import android.util.Slog;
John Spurlock21258a32015-05-27 18:22:55 -040064import android.util.SparseArray;
Julia Reynolds520df6e2017-02-13 09:05:10 -050065import android.util.proto.ProtoOutputStream;
John Spurlock056c5192014-04-20 21:52:01 -040066
67import com.android.internal.R;
Beverly04216872017-09-28 10:55:32 -040068import com.android.internal.annotations.VisibleForTesting;
John Spurlock25d01ee2015-06-03 12:17:46 -040069import com.android.internal.logging.MetricsLogger;
Beverly3bae4e52018-02-07 12:32:02 -050070import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
71import com.android.internal.notification.SystemNotificationChannels;
John Spurlock661f2cf2014-11-17 10:29:10 -050072import com.android.server.LocalServices;
John Spurlock056c5192014-04-20 21:52:01 -040073
74import libcore.io.IoUtils;
75
76import org.xmlpull.v1.XmlPullParser;
77import org.xmlpull.v1.XmlPullParserException;
78import org.xmlpull.v1.XmlSerializer;
79
80import java.io.IOException;
81import java.io.PrintWriter;
John Spurlock1c923a32014-04-27 16:42:29 -040082import java.util.ArrayList;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040083import java.util.List;
John Spurlock1fc476d2015-04-14 16:05:20 -040084import java.util.Objects;
John Spurlock056c5192014-04-20 21:52:01 -040085
86/**
87 * NotificationManagerService helper for functionality related to zen mode.
88 */
John Spurlockb2278d62015-04-07 12:47:12 -040089public class ZenModeHelper {
90 static final String TAG = "ZenModeHelper";
91 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlock056c5192014-04-20 21:52:01 -040092
Julia Reynolds5a43aaa2015-12-15 13:54:41 -050093 // The amount of time rules instances can exist without their owning app being installed.
94 private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
95
John Spurlock056c5192014-04-20 21:52:01 -040096 private final Context mContext;
John Spurlock661f2cf2014-11-17 10:29:10 -050097 private final H mHandler;
John Spurlock056c5192014-04-20 21:52:01 -040098 private final SettingsObserver mSettingsObserver;
Julia Reynoldse99db5a2019-04-16 12:50:04 -040099 private final AppOpsManager mAppOps;
Beverly3bae4e52018-02-07 12:32:02 -0500100 @VisibleForTesting protected final NotificationManager mNotificationManager;
Beverly49ba9a62018-11-02 13:19:31 -0400101 @VisibleForTesting protected ZenModeConfig mDefaultConfig;
John Spurlock1c923a32014-04-27 16:42:29 -0400102 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
John Spurlockb2278d62015-04-07 12:47:12 -0400103 private final ZenModeFiltering mFiltering;
Beverlyd6964762018-02-16 14:07:03 -0500104 protected final RingerModeDelegate mRingerModeDelegate = new
105 RingerModeDelegate();
Beverly2f43b642018-08-14 09:43:11 -0400106 @VisibleForTesting protected final ZenModeConditions mConditions;
Annie Meng8b646fd2019-02-01 18:46:42 +0000107 @VisibleForTesting final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
Chris Wren98d235b2015-05-27 18:25:17 -0400108 private final Metrics mMetrics = new Metrics();
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500109 private final ConditionProviders.Config mServiceConfig;
John Spurlock056c5192014-04-20 21:52:01 -0400110
Beverly04216872017-09-28 10:55:32 -0400111 @VisibleForTesting protected int mZenMode;
Beverlyff2df9b2018-10-10 16:54:10 -0400112 @VisibleForTesting protected NotificationManager.Policy mConsolidatedPolicy;
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700113 private int mUser = UserHandle.USER_SYSTEM;
Beverly04216872017-09-28 10:55:32 -0400114 @VisibleForTesting protected ZenModeConfig mConfig;
Beverly85f52412018-02-27 10:41:13 -0500115 @VisibleForTesting protected AudioManagerInternal mAudioManager;
Beverlyd4f96492017-08-02 13:36:11 -0400116 protected PackageManager mPm;
Bryce Lee7219ada2016-04-08 10:54:23 -0700117 private long mSuppressedEffects;
118
119 public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
120 public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
121 public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
122 | SUPPRESSED_EFFECT_NOTIFICATIONS;
John Spurlock056c5192014-04-20 21:52:01 -0400123
Beverly3bae4e52018-02-07 12:32:02 -0500124 @VisibleForTesting protected boolean mIsBootComplete;
Beverlyd4f96492017-08-02 13:36:11 -0400125
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400126 private String[] mPriorityOnlyDndExemptPackages;
127
John Spurlockb2278d62015-04-07 12:47:12 -0400128 public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
John Spurlock056c5192014-04-20 21:52:01 -0400129 mContext = context;
John Spurlock661f2cf2014-11-17 10:29:10 -0500130 mHandler = new H(looper);
Chris Wren98d235b2015-05-27 18:25:17 -0400131 addCallback(mMetrics);
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400132 mAppOps = context.getSystemService(AppOpsManager.class);
Beverly3bae4e52018-02-07 12:32:02 -0500133 mNotificationManager = context.getSystemService(NotificationManager.class);
Beverlyd4f96492017-08-02 13:36:11 -0400134
Beverlyf3b92d22018-09-18 15:13:17 -0400135 mDefaultConfig = readDefaultConfig(mContext.getResources());
136 updateDefaultAutomaticRuleNames();
137 mConfig = mDefaultConfig.copy();
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700138 mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
Beverlyd4f96492017-08-02 13:36:11 -0400139
John Spurlock056c5192014-04-20 21:52:01 -0400140 mSettingsObserver = new SettingsObserver(mHandler);
141 mSettingsObserver.observe();
John Spurlockb2278d62015-04-07 12:47:12 -0400142 mFiltering = new ZenModeFiltering(mContext);
143 mConditions = new ZenModeConditions(this, conditionProviders);
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500144 mServiceConfig = conditionProviders.getConfig();
John Spurlock056c5192014-04-20 21:52:01 -0400145 }
146
John Spurlock1b8b22b2015-05-20 09:47:13 -0400147 public Looper getLooper() {
148 return mHandler.getLooper();
149 }
150
John Spurlockb2278d62015-04-07 12:47:12 -0400151 @Override
152 public String toString() {
153 return TAG;
154 }
155
156 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
157 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400158 synchronized (mConfig) {
Beverlyff2df9b2018-10-10 16:54:10 -0400159 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConsolidatedPolicy,
160 userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400161 }
John Spurlockb2278d62015-04-07 12:47:12 -0400162 }
163
164 public boolean isCall(NotificationRecord record) {
165 return mFiltering.isCall(record);
166 }
167
Julia Reynoldsc6b371b2016-06-14 08:31:03 -0400168 public void recordCaller(NotificationRecord record) {
169 mFiltering.recordCall(record);
170 }
171
John Spurlockb2278d62015-04-07 12:47:12 -0400172 public boolean shouldIntercept(NotificationRecord record) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400173 synchronized (mConfig) {
Beverlyff2df9b2018-10-10 16:54:10 -0400174 return mFiltering.shouldIntercept(mZenMode, mConsolidatedPolicy, record);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400175 }
John Spurlock056c5192014-04-20 21:52:01 -0400176 }
177
John Spurlock1c923a32014-04-27 16:42:29 -0400178 public void addCallback(Callback callback) {
179 mCallbacks.add(callback);
John Spurlock056c5192014-04-20 21:52:01 -0400180 }
181
John Spurlock530052a2014-11-30 16:26:19 -0500182 public void removeCallback(Callback callback) {
183 mCallbacks.remove(callback);
184 }
185
John Spurlockb2278d62015-04-07 12:47:12 -0400186 public void initZenMode() {
187 if (DEBUG) Log.d(TAG, "initZenMode");
188 evaluateZenMode("init", true /*setRingerMode*/);
189 }
190
John Spurlock661f2cf2014-11-17 10:29:10 -0500191 public void onSystemReady() {
John Spurlockb2278d62015-04-07 12:47:12 -0400192 if (DEBUG) Log.d(TAG, "onSystemReady");
John Spurlock661f2cf2014-11-17 10:29:10 -0500193 mAudioManager = LocalServices.getService(AudioManagerInternal.class);
194 if (mAudioManager != null) {
John Spurlockb2278d62015-04-07 12:47:12 -0400195 mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
John Spurlock661f2cf2014-11-17 10:29:10 -0500196 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500197 mPm = mContext.getPackageManager();
Chris Wren98d235b2015-05-27 18:25:17 -0400198 mHandler.postMetricsTimer();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500199 cleanUpZenRules();
Julia Reynolds8ac63032015-08-31 15:19:43 -0400200 evaluateZenMode("onSystemReady", true);
Beverly3bae4e52018-02-07 12:32:02 -0500201 mIsBootComplete = true;
202 showZenUpgradeNotification(mZenMode);
John Spurlockae641c92014-06-30 18:11:40 -0400203 }
204
John Spurlock21258a32015-05-27 18:22:55 -0400205 public void onUserSwitched(int user) {
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500206 loadConfigForUser(user, "onUserSwitched");
John Spurlock21258a32015-05-27 18:22:55 -0400207 }
208
209 public void onUserRemoved(int user) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700210 if (user < UserHandle.USER_SYSTEM) return;
John Spurlock21258a32015-05-27 18:22:55 -0400211 if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
212 mConfigs.remove(user);
213 }
214
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500215 public void onUserUnlocked(int user) {
216 loadConfigForUser(user, "onUserUnlocked");
217 }
218
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400219 void setPriorityOnlyDndExemptPackages(String[] packages) {
220 mPriorityOnlyDndExemptPackages = packages;
221 }
222
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500223 private void loadConfigForUser(int user, String reason) {
224 if (mUser == user || user < UserHandle.USER_SYSTEM) return;
225 mUser = user;
226 if (DEBUG) Log.d(TAG, reason + " u=" + user);
227 ZenModeConfig config = mConfigs.get(user);
228 if (config == null) {
229 if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user);
230 config = mDefaultConfig.copy();
231 config.user = user;
232 }
233 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400234 setConfigLocked(config, null, reason);
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500235 }
236 cleanUpZenRules();
237 }
238
Christoph Studer85a384b2014-08-27 20:16:15 +0200239 public int getZenModeListenerInterruptionFilter() {
John Spurlock80774932015-05-07 17:38:50 -0400240 return NotificationManager.zenModeToInterruptionFilter(mZenMode);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400241 }
242
John Spurlock80774932015-05-07 17:38:50 -0400243 public void requestFromListener(ComponentName name, int filter) {
244 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400245 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400246 setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
John Spurlockb2278d62015-04-07 12:47:12 -0400247 "listener:" + (name != null ? name.flattenToShortString() : null));
John Spurlockd8afe3c2014-08-01 14:04:07 -0400248 }
249 }
250
Bryce Lee7219ada2016-04-08 10:54:23 -0700251 public void setSuppressedEffects(long suppressedEffects) {
252 if (mSuppressedEffects == suppressedEffects) return;
253 mSuppressedEffects = suppressedEffects;
John Spurlock8403b752014-12-10 12:47:01 -0500254 applyRestrictions();
255 }
256
Bryce Lee7219ada2016-04-08 10:54:23 -0700257 public long getSuppressedEffects() {
258 return mSuppressedEffects;
259 }
260
John Spurlock1c923a32014-04-27 16:42:29 -0400261 public int getZenMode() {
262 return mZenMode;
263 }
264
Julia Reynolds361e82d32016-02-26 18:19:49 -0500265 public List<ZenRule> getZenRules() {
266 List<ZenRule> rules = new ArrayList<>();
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400267 synchronized (mConfig) {
268 if (mConfig == null) return rules;
269 for (ZenRule rule : mConfig.automaticRules.values()) {
270 if (canManageAutomaticZenRule(rule)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500271 rules.add(rule);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400272 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400273 }
274 }
275 return rules;
276 }
277
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400278 public AutomaticZenRule getAutomaticZenRule(String id) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400279 ZenRule rule;
280 synchronized (mConfig) {
281 if (mConfig == null) return null;
282 rule = mConfig.automaticRules.get(id);
283 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400284 if (rule == null) return null;
285 if (canManageAutomaticZenRule(rule)) {
286 return createAutomaticZenRule(rule);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400287 }
288 return null;
289 }
290
Julia Reynolds361e82d32016-02-26 18:19:49 -0500291 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500292 if (!isSystemRule(automaticZenRule)) {
Julia Reynolds68062072018-08-06 15:38:21 -0400293 PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
294 if (component == null) {
295 component = getActivityInfo(automaticZenRule.getConfigurationActivity());
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500296 }
Julia Reynolds68062072018-08-06 15:38:21 -0400297 if (component == null) {
298 throw new IllegalArgumentException("Lacking enabled CPS or config activity");
299 }
Julia Reynolds7f2f4412016-03-01 12:33:48 -0500300 int ruleInstanceLimit = -1;
Julia Reynolds68062072018-08-06 15:38:21 -0400301 if (component.metaData != null) {
302 ruleInstanceLimit = component.metaData.getInt(
Julia Reynolds7f2f4412016-03-01 12:33:48 -0500303 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
304 }
Julia Reynolds68062072018-08-06 15:38:21 -0400305 int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
306 + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
307 + 1;
308 if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500309 throw new IllegalArgumentException("Rule instance limit exceeded");
310 }
Julia Reynolds68062072018-08-06 15:38:21 -0400311
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500312 }
313
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400314 ZenModeConfig newConfig;
315 synchronized (mConfig) {
Julia Reynolds87c42772016-05-16 09:52:17 -0400316 if (mConfig == null) {
317 throw new AndroidRuntimeException("Could not create rule");
318 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400319 if (DEBUG) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500320 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400321 }
322 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500323 ZenRule rule = new ZenRule();
324 populateZenRule(automaticZenRule, rule, true);
Beverlya0d07ab2018-11-28 16:49:23 -0500325 newConfig.automaticRules.put(rule.id, rule);
Julia Reynolds8f056002018-07-13 15:12:29 -0400326 if (setConfigLocked(newConfig, reason, rule.component, true)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500327 return rule.id;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500328 } else {
Julia Reynolds87c42772016-05-16 09:52:17 -0400329 throw new AndroidRuntimeException("Could not create rule");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500330 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400331 }
332 }
333
Julia Reynolds361e82d32016-02-26 18:19:49 -0500334 public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
335 String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400336 ZenModeConfig newConfig;
337 synchronized (mConfig) {
338 if (mConfig == null) return false;
339 if (DEBUG) {
340 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule
341 + " reason=" + reason);
342 }
343 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500344 ZenModeConfig.ZenRule rule;
345 if (ruleId == null) {
346 throw new IllegalArgumentException("Rule doesn't exist");
347 } else {
348 rule = newConfig.automaticRules.get(ruleId);
349 if (rule == null || !canManageAutomaticZenRule(rule)) {
350 throw new SecurityException(
351 "Cannot update rules not owned by your condition provider");
352 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400353 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500354 populateZenRule(automaticZenRule, rule, false);
Julia Reynolds8f056002018-07-13 15:12:29 -0400355 return setConfigLocked(newConfig, reason, rule.component, true);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400356 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400357 }
358
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400359 public boolean removeAutomaticZenRule(String id, String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400360 ZenModeConfig newConfig;
361 synchronized (mConfig) {
362 if (mConfig == null) return false;
363 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500364 ZenRule rule = newConfig.automaticRules.get(id);
365 if (rule == null) return false;
366 if (canManageAutomaticZenRule(rule)) {
367 newConfig.automaticRules.remove(id);
368 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
369 } else {
370 throw new SecurityException(
371 "Cannot delete rules not owned by your condition provider");
372 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400373 return setConfigLocked(newConfig, reason, null, true);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400374 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400375 }
376
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500377 public boolean removeAutomaticZenRules(String packageName, String reason) {
378 ZenModeConfig newConfig;
379 synchronized (mConfig) {
380 if (mConfig == null) return false;
381 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500382 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
383 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
Julia Reynolds10e663b2019-01-07 10:15:12 -0500384 if (rule.pkg.equals(packageName) && canManageAutomaticZenRule(rule)) {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500385 newConfig.automaticRules.removeAt(i);
386 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500387 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400388 return setConfigLocked(newConfig, reason, null, true);
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500389 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500390 }
391
Julia Reynolds68062072018-08-06 15:38:21 -0400392 public void setAutomaticZenRuleState(String id, Condition condition) {
393 ZenModeConfig newConfig;
394 synchronized (mConfig) {
395 if (mConfig == null) return;
396
397 newConfig = mConfig.copy();
Julia Reynolds977a93e2019-04-10 16:18:13 -0400398 setAutomaticZenRuleStateLocked(newConfig, newConfig.automaticRules.get(id), condition);
Julia Reynolds68062072018-08-06 15:38:21 -0400399 }
Julia Reynolds68062072018-08-06 15:38:21 -0400400 }
401
402 public void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition) {
403 ZenModeConfig newConfig;
404 synchronized (mConfig) {
405 if (mConfig == null) return;
406 newConfig = mConfig.copy();
Julia Reynolds68062072018-08-06 15:38:21 -0400407
Julia Reynolds977a93e2019-04-10 16:18:13 -0400408 setAutomaticZenRuleStateLocked(newConfig,
409 findMatchingRule(newConfig, ruleDefinition, condition),
410 condition);
411 }
Julia Reynolds68062072018-08-06 15:38:21 -0400412 }
413
Julia Reynolds977a93e2019-04-10 16:18:13 -0400414 private void setAutomaticZenRuleStateLocked(ZenModeConfig config, ZenRule rule,
415 Condition condition) {
Julia Reynolds68062072018-08-06 15:38:21 -0400416 if (rule == null) return;
417
418 rule.condition = condition;
419 updateSnoozing(rule);
420 setConfigLocked(config, rule.component, "conditionChanged");
421 }
422
423 private ZenRule findMatchingRule(ZenModeConfig config, Uri id, Condition condition) {
424 if (ruleMatches(id, condition, config.manualRule)) {
425 return config.manualRule;
426 } else {
427 for (ZenRule automaticRule : config.automaticRules.values()) {
428 if (ruleMatches(id, condition, automaticRule)) {
429 return automaticRule;
430 }
431 }
432 }
433 return null;
434 }
435
436 private boolean ruleMatches(Uri id, Condition condition, ZenRule rule) {
437 if (id == null || rule == null || rule.conditionId == null) return false;
438 if (!rule.conditionId.equals(id)) return false;
439 if (Objects.equals(condition, rule.condition)) return false;
440 return true;
441 }
442
443 private boolean updateSnoozing(ZenRule rule) {
444 if (rule != null && rule.snoozing && !rule.isTrueOrUnknown()) {
445 rule.snoozing = false;
446 if (DEBUG) Log.d(TAG, "Snoozing reset for " + rule.conditionId);
447 return true;
448 }
449 return false;
450 }
451
452 public int getCurrentInstanceCount(ComponentName cn) {
453 if (cn == null) {
454 return 0;
455 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500456 int count = 0;
457 synchronized (mConfig) {
458 for (ZenRule rule : mConfig.automaticRules.values()) {
Julia Reynolds68062072018-08-06 15:38:21 -0400459 if (cn.equals(rule.component) || cn.equals(rule.configurationActivity)) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500460 count++;
461 }
462 }
463 }
464 return count;
465 }
466
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400467 public boolean canManageAutomaticZenRule(ZenRule rule) {
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500468 final int callingUid = Binder.getCallingUid();
469 if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
470 return true;
471 } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400472 == PackageManager.PERMISSION_GRANTED) {
473 return true;
474 } else {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500475 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400476 if (packages != null) {
477 final int packageCount = packages.length;
478 for (int i = 0; i < packageCount; i++) {
Julia Reynolds68062072018-08-06 15:38:21 -0400479 if (packages[i].equals(rule.pkg)) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400480 return true;
481 }
482 }
483 }
484 return false;
485 }
486 }
487
Beverlyd4f96492017-08-02 13:36:11 -0400488 protected void updateDefaultZenRules() {
Beverlyf3b92d22018-09-18 15:13:17 -0400489 updateDefaultAutomaticRuleNames();
490 for (ZenRule defaultRule : mDefaultConfig.automaticRules.values()) {
491 ZenRule currRule = mConfig.automaticRules.get(defaultRule.id);
Beverly49ba9a62018-11-02 13:19:31 -0400492 // if default rule wasn't user-modified nor enabled, use localized name
493 // instead of previous system name
494 if (currRule != null && !currRule.modified && !currRule.enabled
495 && !defaultRule.name.equals(currRule.name)) {
496 if (canManageAutomaticZenRule(currRule)) {
Beverlyd4f96492017-08-02 13:36:11 -0400497 if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name "
Beverlyf3b92d22018-09-18 15:13:17 -0400498 + "from " + currRule.name + " to " + defaultRule.name);
Beverlyd4f96492017-08-02 13:36:11 -0400499 // update default rule (if locale changed, name of rule will change)
Beverly49ba9a62018-11-02 13:19:31 -0400500 currRule.name = defaultRule.name;
501 updateAutomaticZenRule(defaultRule.id, createAutomaticZenRule(currRule),
Beverlyd4f96492017-08-02 13:36:11 -0400502 "locale changed");
503 }
504 }
505 }
506 }
507
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500508 private boolean isSystemRule(AutomaticZenRule rule) {
Julia Reynolds68062072018-08-06 15:38:21 -0400509 return rule.getOwner() != null
510 && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500511 }
512
513 private ServiceInfo getServiceInfo(ComponentName owner) {
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500514 Intent queryIntent = new Intent();
515 queryIntent.setComponent(owner);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500516 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500517 queryIntent,
518 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
519 UserHandle.getCallingUserId());
520 if (installedServices != null) {
521 for (int i = 0, count = installedServices.size(); i < count; i++) {
522 ResolveInfo resolveInfo = installedServices.get(i);
523 ServiceInfo info = resolveInfo.serviceInfo;
524 if (mServiceConfig.bindPermission.equals(info.permission)) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500525 return info;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500526 }
527 }
528 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500529 return null;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500530 }
531
Julia Reynolds68062072018-08-06 15:38:21 -0400532 private ActivityInfo getActivityInfo(ComponentName configActivity) {
533 Intent queryIntent = new Intent();
534 queryIntent.setComponent(configActivity);
535 List<ResolveInfo> installedComponents = mPm.queryIntentActivitiesAsUser(
536 queryIntent,
537 PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA,
538 UserHandle.getCallingUserId());
539 if (installedComponents != null) {
540 for (int i = 0, count = installedComponents.size(); i < count; i++) {
541 ResolveInfo resolveInfo = installedComponents.get(i);
542 return resolveInfo.activityInfo;
543 }
544 }
545 return null;
546 }
547
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400548 private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
549 if (isNew) {
550 rule.id = ZenModeConfig.newRuleId();
551 rule.creationTime = System.currentTimeMillis();
552 rule.component = automaticZenRule.getOwner();
Julia Reynolds68062072018-08-06 15:38:21 -0400553 rule.configurationActivity = automaticZenRule.getConfigurationActivity();
554 rule.pkg = (rule.component != null)
555 ? rule.component.getPackageName()
556 : rule.configurationActivity.getPackageName();
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400557 }
558
559 if (rule.enabled != automaticZenRule.isEnabled()) {
560 rule.snoozing = false;
561 }
562 rule.name = automaticZenRule.getName();
563 rule.condition = null;
564 rule.conditionId = automaticZenRule.getConditionId();
565 rule.enabled = automaticZenRule.isEnabled();
Beverly49ba9a62018-11-02 13:19:31 -0400566 rule.modified = automaticZenRule.isModified();
Beverly12196702018-12-12 15:05:51 -0500567 rule.zenPolicy = automaticZenRule.getZenPolicy();
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400568 rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
569 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
570 }
571
Beverlyd4f96492017-08-02 13:36:11 -0400572 protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
Julia Reynolds68062072018-08-06 15:38:21 -0400573 return new AutomaticZenRule(rule.name, rule.component, rule.configurationActivity,
574 rule.conditionId, rule.zenPolicy,
575 NotificationManager.zenModeToInterruptionFilter(rule.zenMode),
576 rule.enabled, rule.creationTime);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400577 }
578
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400579 public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
580 setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
Beverly91d0a632018-07-02 16:45:00 -0400581 Settings.Secure.putInt(mContext.getContentResolver(),
582 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0);
John Spurlocke77bb362014-04-26 10:24:59 -0400583 }
584
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400585 private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
John Spurlockb2278d62015-04-07 12:47:12 -0400586 boolean setRingerMode) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400587 ZenModeConfig newConfig;
588 synchronized (mConfig) {
589 if (mConfig == null) return;
590 if (!Global.isValidZenMode(zenMode)) return;
591 if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode)
592 + " conditionId=" + conditionId + " reason=" + reason
593 + " setRingerMode=" + setRingerMode);
594 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500595 if (zenMode == Global.ZEN_MODE_OFF) {
596 newConfig.manualRule = null;
597 for (ZenRule automaticRule : newConfig.automaticRules.values()) {
598 if (automaticRule.isAutomaticActive()) {
599 automaticRule.snoozing = true;
600 }
John Spurlockb2278d62015-04-07 12:47:12 -0400601 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500602 } else {
603 final ZenRule newRule = new ZenRule();
604 newRule.enabled = true;
605 newRule.zenMode = zenMode;
606 newRule.conditionId = conditionId;
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400607 newRule.enabler = caller;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500608 newConfig.manualRule = newRule;
John Spurlockb2278d62015-04-07 12:47:12 -0400609 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400610 setConfigLocked(newConfig, reason, null, setRingerMode);
John Spurlockb2278d62015-04-07 12:47:12 -0400611 }
John Spurlockb2278d62015-04-07 12:47:12 -0400612 }
613
Julia Reynolds520df6e2017-02-13 09:05:10 -0500614 void dump(ProtoOutputStream proto) {
Julia Reynolds520df6e2017-02-13 09:05:10 -0500615 proto.write(ZenModeProto.ZEN_MODE, mZenMode);
616 synchronized (mConfig) {
617 if (mConfig.manualRule != null) {
Kweku Adams99546332018-01-24 17:03:50 -0800618 mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500619 }
620 for (ZenRule rule : mConfig.automaticRules.values()) {
621 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
622 && !rule.snoozing) {
Kweku Adams99546332018-01-24 17:03:50 -0800623 rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500624 }
625 }
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800626 mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500627 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
628 }
629 }
630
John Spurlockb2278d62015-04-07 12:47:12 -0400631 public void dump(PrintWriter pw, String prefix) {
632 pw.print(prefix); pw.print("mZenMode=");
633 pw.println(Global.zenModeToString(mZenMode));
Beverlyff2df9b2018-10-10 16:54:10 -0400634 pw.print("mConsolidatedPolicy=" + mConsolidatedPolicy.toString());
John Spurlock21258a32015-05-27 18:22:55 -0400635 final int N = mConfigs.size();
636 for (int i = 0; i < N; i++) {
637 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
638 }
639 pw.print(prefix); pw.print("mUser="); pw.println(mUser);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400640 synchronized (mConfig) {
641 dump(pw, prefix, "mConfig", mConfig);
642 }
Bryce Lee7219ada2016-04-08 10:54:23 -0700643
644 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
John Spurlock1d7d2242015-04-10 08:10:22 -0400645 mFiltering.dump(pw, prefix);
John Spurlockb2278d62015-04-07 12:47:12 -0400646 mConditions.dump(pw, prefix);
647 }
648
649 private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) {
650 pw.print(prefix); pw.print(var); pw.print('=');
651 if (config == null) {
652 pw.println(config);
653 return;
654 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500655 pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
Julia Reynolds1f580572018-04-27 14:48:36 -0400656 + "messages=%b,messagesFrom=%s,events=%b,reminders=%b)\n",
Beverlyd6964762018-02-16 14:07:03 -0500657 config.allowAlarms, config.allowMedia, config.allowSystem,
Julia Reynolds6ee26172015-09-28 11:34:48 -0400658 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
659 config.allowRepeatCallers, config.allowMessages,
660 ZenModeConfig.sourceToString(config.allowMessagesFrom),
Julia Reynolds1f580572018-04-27 14:48:36 -0400661 config.allowEvents, config.allowReminders);
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500662 pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
John Spurlockb2278d62015-04-07 12:47:12 -0400663 pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule);
664 if (config.automaticRules.isEmpty()) return;
665 final int N = config.automaticRules.size();
666 for (int i = 0; i < N; i++) {
667 pw.print(prefix); pw.print(i == 0 ? " automaticRules=" : " ");
668 pw.println(config.automaticRules.valueAt(i));
669 }
670 }
671
Annie Meng8b646fd2019-02-01 18:46:42 +0000672 public void readXml(XmlPullParser parser, boolean forRestore, int userId)
John Spurlock35ef0a62015-05-28 11:24:10 -0400673 throws XmlPullParserException, IOException {
Beverly4e2f76c2018-03-16 15:43:49 -0400674 ZenModeConfig config = ZenModeConfig.readXml(parser);
675 String reason = "readXml";
676
John Spurlockb2278d62015-04-07 12:47:12 -0400677 if (config != null) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400678 if (forRestore) {
Annie Meng8b646fd2019-02-01 18:46:42 +0000679 config.user = userId;
John Spurlock35ef0a62015-05-28 11:24:10 -0400680 config.manualRule = null; // don't restore the manual rule
Beverly4e2f76c2018-03-16 15:43:49 -0400681 }
682
Beverlyad3841a2018-07-31 11:23:35 -0400683 // booleans to determine whether to reset the rules to the default rules
684 boolean allRulesDisabled = true;
685 boolean hasDefaultRules = config.automaticRules.containsAll(
686 ZenModeConfig.DEFAULT_RULE_IDS);
687
Beverly4e2f76c2018-03-16 15:43:49 -0400688 long time = System.currentTimeMillis();
689 if (config.automaticRules != null && config.automaticRules.size() > 0) {
690 for (ZenRule automaticRule : config.automaticRules.values()) {
691 if (forRestore) {
John Spurlock995a7492015-05-28 22:13:03 -0400692 // don't restore transient state from restored automatic rules
693 automaticRule.snoozing = false;
694 automaticRule.condition = null;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500695 automaticRule.creationTime = time;
John Spurlock995a7492015-05-28 22:13:03 -0400696 }
Beverlyad3841a2018-07-31 11:23:35 -0400697
698 allRulesDisabled &= !automaticRule.enabled;
John Spurlock995a7492015-05-28 22:13:03 -0400699 }
John Spurlock35ef0a62015-05-28 11:24:10 -0400700 }
Beverly4e2f76c2018-03-16 15:43:49 -0400701
Beverlyad3841a2018-07-31 11:23:35 -0400702 if (!hasDefaultRules && allRulesDisabled
703 && (forRestore || config.version < ZenModeConfig.XML_VERSION)) {
704 // reset zen automatic rules to default on restore or upgrade if:
705 // - doesn't already have default rules and
706 // - all previous automatic rules were disabled
707 config.automaticRules = new ArrayMap<>();
Beverlyf3b92d22018-09-18 15:13:17 -0400708 for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
709 config.automaticRules.put(rule.id, rule);
710 }
Beverlyad3841a2018-07-31 11:23:35 -0400711 reason += ", reset to default rules";
712 }
713
Annie Meng8b646fd2019-02-01 18:46:42 +0000714 // Resolve user id for settings.
715 userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
Beverlyad3841a2018-07-31 11:23:35 -0400716 if (config.version < ZenModeConfig.XML_VERSION) {
Annie Meng8b646fd2019-02-01 18:46:42 +0000717 Settings.Secure.putIntForUser(mContext.getContentResolver(),
718 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId);
Beverly301e92a2018-04-27 09:43:05 -0400719 } else {
720 // devices not restoring/upgrading already have updated zen settings
Annie Meng8b646fd2019-02-01 18:46:42 +0000721 Settings.Secure.putIntForUser(mContext.getContentResolver(),
722 Settings.Secure.ZEN_SETTINGS_UPDATED, 1, userId);
Beverly4e2f76c2018-03-16 15:43:49 -0400723 }
724 if (DEBUG) Log.d(TAG, reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500725 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400726 setConfigLocked(config, null, reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500727 }
John Spurlockb2278d62015-04-07 12:47:12 -0400728 }
729 }
730
Annie Meng8b646fd2019-02-01 18:46:42 +0000731 public void writeXml(XmlSerializer out, boolean forBackup, Integer version, int userId)
732 throws IOException {
Beverly1ef2cce2019-04-29 11:08:05 -0400733 synchronized (mConfigs) {
734 final int n = mConfigs.size();
735 for (int i = 0; i < n; i++) {
736 if (forBackup && mConfigs.keyAt(i) != userId) {
737 continue;
738 }
739 mConfigs.valueAt(i).writeXml(out, version);
John Spurlock35ef0a62015-05-28 11:24:10 -0400740 }
John Spurlock21258a32015-05-27 18:22:55 -0400741 }
John Spurlockb2278d62015-04-07 12:47:12 -0400742 }
743
Beverly174d7412018-08-22 16:34:41 -0400744 /**
745 * @return user-specified default notification policy for priority only do not disturb
746 */
John Spurlock1fc476d2015-04-14 16:05:20 -0400747 public Policy getNotificationPolicy() {
748 return getNotificationPolicy(mConfig);
749 }
750
751 private static Policy getNotificationPolicy(ZenModeConfig config) {
752 return config == null ? null : config.toNotificationPolicy();
753 }
754
Beverly174d7412018-08-22 16:34:41 -0400755 /**
756 * Sets the global notification policy used for priority only do not disturb
757 */
John Spurlock1fc476d2015-04-14 16:05:20 -0400758 public void setNotificationPolicy(Policy policy) {
759 if (policy == null || mConfig == null) return;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500760 synchronized (mConfig) {
761 final ZenModeConfig newConfig = mConfig.copy();
762 newConfig.applyNotificationPolicy(policy);
Julia Reynolds8f056002018-07-13 15:12:29 -0400763 setConfigLocked(newConfig, null, "setNotificationPolicy");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500764 }
John Spurlock1fc476d2015-04-14 16:05:20 -0400765 }
766
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500767 /**
768 * Removes old rule instances whose owner is not installed.
769 */
770 private void cleanUpZenRules() {
771 long currentTime = System.currentTimeMillis();
772 synchronized (mConfig) {
773 final ZenModeConfig newConfig = mConfig.copy();
774 if (newConfig.automaticRules != null) {
775 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
776 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
777 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
778 try {
Julia Reynolds68062072018-08-06 15:38:21 -0400779 if (rule.pkg != null) {
780 mPm.getPackageInfo(rule.pkg, PackageManager.MATCH_ANY_USER);
781 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500782 } catch (PackageManager.NameNotFoundException e) {
783 newConfig.automaticRules.removeAt(i);
784 }
785 }
786 }
787 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400788 setConfigLocked(newConfig, null, "cleanUpZenRules");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500789 }
790 }
791
792 /**
793 * @return a copy of the zen mode configuration
794 */
John Spurlockb2278d62015-04-07 12:47:12 -0400795 public ZenModeConfig getConfig() {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400796 synchronized (mConfig) {
797 return mConfig.copy();
798 }
John Spurlockb2278d62015-04-07 12:47:12 -0400799 }
800
Beverlyff2df9b2018-10-10 16:54:10 -0400801 /**
802 * @return a copy of the zen mode consolidated policy
803 */
804 public Policy getConsolidatedNotificationPolicy() {
805 if (mConsolidatedPolicy == null) {
806 return null;
807 }
808 return mConsolidatedPolicy.copy();
809 }
810
Julia Reynolds8f056002018-07-13 15:12:29 -0400811 public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
812 String reason) {
813 return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -0400814 }
815
Julia Reynolds8f056002018-07-13 15:12:29 -0400816 public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) {
Julia Reynolds89aeab02016-09-15 11:07:50 -0400817 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400818 setConfigLocked(config, triggeringComponent, reason);
Julia Reynolds89aeab02016-09-15 11:07:50 -0400819 }
Eric Laurente0ced4d2015-09-30 17:44:28 -0700820 }
821
Julia Reynolds8f056002018-07-13 15:12:29 -0400822 private boolean setConfigLocked(ZenModeConfig config, String reason,
823 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400824 final long identity = Binder.clearCallingIdentity();
825 try {
826 if (config == null || !config.isValid()) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500827 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400828 return false;
829 }
830 if (config.user != mUser) {
831 // simply store away for background users
832 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500833 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400834 return true;
835 }
Julia Reynolds68062072018-08-06 15:38:21 -0400836 // handle CPS backed conditions - danger! may modify config
Julia Reynolds8f056002018-07-13 15:12:29 -0400837 mConditions.evaluateConfig(config, null, false /*processSubscriptions*/);
Julia Reynolds68062072018-08-06 15:38:21 -0400838
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500839 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500840 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500841 ZenLog.traceConfig(reason, mConfig, config);
Julia Reynolds68062072018-08-06 15:38:21 -0400842
843 // send some broadcasts
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500844 final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
845 getNotificationPolicy(config));
Julia Reynolds9a25da12016-01-06 16:19:28 -0500846 if (!config.equals(mConfig)) {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500847 dispatchOnConfigChanged();
Beverlyff2df9b2018-10-10 16:54:10 -0400848 updateConsolidatedPolicy(reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500849 }
850 if (policyChanged) {
851 dispatchOnPolicyChanged();
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400852 }
Julia Reynolds9a25da12016-01-06 16:19:28 -0500853 mConfig = config;
Julia Reynolds8f056002018-07-13 15:12:29 -0400854 mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode);
John Spurlock21258a32015-05-27 18:22:55 -0400855 return true;
Julia Reynoldscb507b82017-09-07 13:53:40 -0400856 } catch (SecurityException e) {
857 Log.wtf(TAG, "Invalid rule in config", e);
858 return false;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400859 } finally {
860 Binder.restoreCallingIdentity(identity);
John Spurlock21258a32015-05-27 18:22:55 -0400861 }
John Spurlockb2278d62015-04-07 12:47:12 -0400862 }
863
Julia Reynolds8f056002018-07-13 15:12:29 -0400864 private void applyConfig(ZenModeConfig config, String reason,
865 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400866 final String val = Integer.toString(config.hashCode());
867 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
Beverly174d7412018-08-22 16:34:41 -0400868 evaluateZenMode(reason, setRingerMode);
Julia Reynolds8f056002018-07-13 15:12:29 -0400869 mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400870 }
871
John Spurlockb2278d62015-04-07 12:47:12 -0400872 private int getZenModeSetting() {
873 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
874 }
875
Beverly3bae4e52018-02-07 12:32:02 -0500876 @VisibleForTesting
877 protected void setZenModeSetting(int zen) {
John Spurlockb2278d62015-04-07 12:47:12 -0400878 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
Beverly3bae4e52018-02-07 12:32:02 -0500879 showZenUpgradeNotification(zen);
John Spurlockb2278d62015-04-07 12:47:12 -0400880 }
881
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400882 private int getPreviousRingerModeSetting() {
883 return Global.getInt(mContext.getContentResolver(),
884 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
885 }
886
887 private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
888 Global.putString(
889 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
890 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
891 }
892
Beverlye4ee1cc2018-03-06 17:21:08 -0500893 @VisibleForTesting
Beverly174d7412018-08-22 16:34:41 -0400894 protected void evaluateZenMode(String reason, boolean setRingerMode) {
John Spurlockb2278d62015-04-07 12:47:12 -0400895 if (DEBUG) Log.d(TAG, "evaluateZenMode");
Beverlyff2df9b2018-10-10 16:54:10 -0400896 if (mConfig == null) return;
897 final int policyHashBefore = mConsolidatedPolicy == null ? 0
898 : mConsolidatedPolicy.hashCode();
Jason Monka9927322015-12-13 16:22:37 -0500899 final int zenBefore = mZenMode;
Julia Reynolds8ac63032015-08-31 15:19:43 -0400900 final int zen = computeZenMode();
John Spurlockb2278d62015-04-07 12:47:12 -0400901 ZenLog.traceSetZenMode(zen, reason);
902 mZenMode = zen;
903 setZenModeSetting(mZenMode);
Beverlyff2df9b2018-10-10 16:54:10 -0400904 updateConsolidatedPolicy(reason);
Beverlyd6964762018-02-16 14:07:03 -0500905 updateRingerModeAffectedStreams();
Beverlyff2df9b2018-10-10 16:54:10 -0400906 if (setRingerMode && (zen != zenBefore || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
907 && policyHashBefore != mConsolidatedPolicy.hashCode()))) {
John Spurlock57627792014-12-11 11:29:54 -0500908 applyZenToRingerMode();
909 }
910 applyRestrictions();
Jason Monka9927322015-12-13 16:22:37 -0500911 if (zen != zenBefore) {
Julia Reynolds8ac63032015-08-31 15:19:43 -0400912 mHandler.postDispatchOnZenModeChanged();
913 }
John Spurlock57627792014-12-11 11:29:54 -0500914 }
915
John Spurlock50ced3f2015-05-11 16:00:09 -0400916 private void updateRingerModeAffectedStreams() {
917 if (mAudioManager != null) {
918 mAudioManager.updateRingerModeAffectedStreamsInternal();
919 }
920 }
921
Julia Reynolds8ac63032015-08-31 15:19:43 -0400922 private int computeZenMode() {
Beverlye4ee1cc2018-03-06 17:21:08 -0500923 if (mConfig == null) return Global.ZEN_MODE_OFF;
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400924 synchronized (mConfig) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400925 if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
926 int zen = Global.ZEN_MODE_OFF;
927 for (ZenRule automaticRule : mConfig.automaticRules.values()) {
928 if (automaticRule.isAutomaticActive()) {
929 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
Beverly301e92a2018-04-27 09:43:05 -0400930 // automatic rule triggered dnd and user hasn't seen update dnd dialog
Beverly91d0a632018-07-02 16:45:00 -0400931 if (Settings.Secure.getInt(mContext.getContentResolver(),
932 Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
933 Settings.Secure.putInt(mContext.getContentResolver(),
934 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
Beverly301e92a2018-04-27 09:43:05 -0400935 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400936 zen = automaticRule.zenMode;
937 }
John Spurlockb2278d62015-04-07 12:47:12 -0400938 }
939 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400940 return zen;
John Spurlockb2278d62015-04-07 12:47:12 -0400941 }
John Spurlock8403b752014-12-10 12:47:01 -0500942 }
943
Beverly1cc502f2019-04-15 11:21:25 -0400944 private void applyCustomPolicy(ZenPolicy policy, ZenRule rule) {
945 if (rule.zenMode == NotificationManager.INTERRUPTION_FILTER_NONE) {
946 policy.apply(new ZenPolicy.Builder()
947 .disallowAllSounds()
948 .build());
949 } else if (rule.zenMode
950 == NotificationManager.INTERRUPTION_FILTER_ALARMS) {
951 policy.apply(new ZenPolicy.Builder()
952 .disallowAllSounds()
953 .allowAlarms(true)
954 .allowMedia(true)
955 .build());
956 } else {
957 policy.apply(rule.zenPolicy);
958 }
959 }
960
Beverlyff2df9b2018-10-10 16:54:10 -0400961 private void updateConsolidatedPolicy(String reason) {
962 if (mConfig == null) return;
963 synchronized (mConfig) {
964 ZenPolicy policy = new ZenPolicy();
Beverly1cc502f2019-04-15 11:21:25 -0400965 if (mConfig.manualRule != null) {
966 applyCustomPolicy(policy, mConfig.manualRule);
967 }
968
Beverlyff2df9b2018-10-10 16:54:10 -0400969 for (ZenRule automaticRule : mConfig.automaticRules.values()) {
970 if (automaticRule.isAutomaticActive()) {
Beverly1cc502f2019-04-15 11:21:25 -0400971 applyCustomPolicy(policy, automaticRule);
Beverlyff2df9b2018-10-10 16:54:10 -0400972 }
973 }
974 Policy newPolicy = mConfig.toNotificationPolicy(policy);
975 if (!Objects.equals(mConsolidatedPolicy, newPolicy)) {
976 mConsolidatedPolicy = newPolicy;
977 dispatchOnConsolidatedPolicyChanged();
978 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason);
979 }
980 }
981 }
982
Beverlyf3b92d22018-09-18 15:13:17 -0400983 private void updateDefaultAutomaticRuleNames() {
984 for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
985 if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) {
986 rule.name = mContext.getResources()
987 .getString(R.string.zen_mode_default_events_name);
988 } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) {
989 rule.name = mContext.getResources()
990 .getString(R.string.zen_mode_default_every_night_name);
991 }
992 }
Beverly30bfbca2017-10-17 14:38:20 -0400993 }
994
Beverly04216872017-09-28 10:55:32 -0400995 @VisibleForTesting
996 protected void applyRestrictions() {
Beverlyd820bc22018-01-11 15:28:33 -0500997 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
Beverly925cde82018-01-23 09:31:23 -0500998 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
Beverlyd820bc22018-01-11 15:28:33 -0500999 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
Beverlyff2df9b2018-10-10 16:54:10 -04001000 final boolean allowCalls = mConsolidatedPolicy.allowCalls();
1001 final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
1002 final boolean allowSystem = mConsolidatedPolicy.allowSystem();
1003 final boolean allowMedia = mConsolidatedPolicy.allowMedia();
1004 final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();
John Spurlock8403b752014-12-10 12:47:01 -05001005
1006 // notification restrictions
Bryce Lee7219ada2016-04-08 10:54:23 -07001007 final boolean muteNotifications =
1008 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
John Spurlock056c5192014-04-20 21:52:01 -04001009 // call restrictions
Beverlyd820bc22018-01-11 15:28:33 -05001010 final boolean muteCalls = zenAlarmsOnly
Beverlyff2df9b2018-10-10 16:54:10 -04001011 || (zenPriorityOnly && !allowCalls && !allowRepeatCallers)
Bryce Lee7219ada2016-04-08 10:54:23 -07001012 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
Beverly04216872017-09-28 10:55:32 -04001013 // alarm restrictions
Beverlyff2df9b2018-10-10 16:54:10 -04001014 final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
Beverlyd6964762018-02-16 14:07:03 -05001015 // media restrictions
Beverlyff2df9b2018-10-10 16:54:10 -04001016 final boolean muteMedia = zenPriorityOnly && !allowMedia;
Beverlyd6964762018-02-16 14:07:03 -05001017 // system restrictions
Beverlyff2df9b2018-10-10 16:54:10 -04001018 final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem);
Julia Reynolds3fe81be2016-02-03 09:10:06 -05001019 // total silence restrictions
Beverlyff2df9b2018-10-10 16:54:10 -04001020 final boolean muteEverything = zenSilence || (zenPriorityOnly
1021 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
John Spurlock25d01ee2015-06-03 12:17:46 -04001022
Jean-Michel Trivie743bda2016-09-09 11:56:48 -07001023 for (int usage : AudioAttributes.SDK_USAGES) {
1024 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -07001025 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001026 applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -07001027 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001028 applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage);
Jean-Michel Trivie743bda2016-09-09 11:56:48 -07001029 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001030 applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage);
Beverly04216872017-09-28 10:55:32 -04001031 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001032 applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage);
Beverlyd6964762018-02-16 14:07:03 -05001033 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001034 applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage);
Beverlyd6964762018-02-16 14:07:03 -05001035 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
Beverly738bffd2018-03-12 10:46:17 -04001036 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
1037 // normally DND will only restrict touch sounds, not haptic feedback/vibrations
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001038 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage,
Beverly738bffd2018-03-12 10:46:17 -04001039 AppOpsManager.OP_PLAY_AUDIO);
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001040 applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE);
Beverly738bffd2018-03-12 10:46:17 -04001041 } else {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001042 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage);
Beverly738bffd2018-03-12 10:46:17 -04001043 }
Julia Reynolds3fe81be2016-02-03 09:10:06 -05001044 } else {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001045 applyRestrictions(zenPriorityOnly, muteEverything, usage);
Julia Reynolds3fe81be2016-02-03 09:10:06 -05001046 }
1047 }
John Spurlock8403b752014-12-10 12:47:01 -05001048 }
John Spurlockae641c92014-06-30 18:11:40 -04001049
Beverlye2d9a232017-11-08 18:14:59 -05001050
Beverly04216872017-09-28 10:55:32 -04001051 @VisibleForTesting
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001052 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) {
1053 final long ident = Binder.clearCallingIdentity();
1054 try {
1055 mAppOps.setRestriction(code, usage,
1056 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
1057 zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);
1058 } finally {
1059 Binder.restoreCallingIdentity(ident);
Dianne Hackbornbf1b57d2018-03-07 12:42:47 -08001060 }
John Spurlock056c5192014-04-20 21:52:01 -04001061 }
1062
Beverly85f52412018-02-27 10:41:13 -05001063 @VisibleForTesting
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001064 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) {
1065 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE);
1066 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO);
Beverly738bffd2018-03-12 10:46:17 -04001067 }
1068
1069
1070 @VisibleForTesting
Beverly85f52412018-02-27 10:41:13 -05001071 protected void applyZenToRingerMode() {
John Spurlock661f2cf2014-11-17 10:29:10 -05001072 if (mAudioManager == null) return;
John Spurlock661f2cf2014-11-17 10:29:10 -05001073 // force the ringer mode into compliance
1074 final int ringerModeInternal = mAudioManager.getRingerModeInternal();
1075 int newRingerModeInternal = ringerModeInternal;
John Spurlock57627792014-12-11 11:29:54 -05001076 switch (mZenMode) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001077 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlock4f1163c2015-04-02 17:41:21 -04001078 case Global.ZEN_MODE_ALARMS:
John Spurlock661f2cf2014-11-17 10:29:10 -05001079 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001080 setPreviousRingerModeSetting(ringerModeInternal);
John Spurlock661f2cf2014-11-17 10:29:10 -05001081 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
John Spurlock8c01d882014-07-28 13:37:13 -04001082 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001083 break;
1084 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
Beverly9e4214d2018-03-26 11:10:10 -04001085 // do not apply zen to ringer, streams zen muted in AudioService
Beverly925cde82018-01-23 09:31:23 -05001086 break;
John Spurlock661f2cf2014-11-17 10:29:10 -05001087 case Global.ZEN_MODE_OFF:
1088 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001089 newRingerModeInternal = getPreviousRingerModeSetting();
1090 setPreviousRingerModeSetting(null);
John Spurlock661f2cf2014-11-17 10:29:10 -05001091 }
1092 break;
John Spurlock8c01d882014-07-28 13:37:13 -04001093 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001094 if (newRingerModeInternal != -1) {
1095 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
1096 }
1097 }
1098
John Spurlock1c923a32014-04-27 16:42:29 -04001099 private void dispatchOnConfigChanged() {
1100 for (Callback callback : mCallbacks) {
1101 callback.onConfigChanged();
1102 }
1103 }
1104
John Spurlock1fc476d2015-04-14 16:05:20 -04001105 private void dispatchOnPolicyChanged() {
1106 for (Callback callback : mCallbacks) {
1107 callback.onPolicyChanged();
1108 }
1109 }
1110
Beverlyff2df9b2018-10-10 16:54:10 -04001111 private void dispatchOnConsolidatedPolicyChanged() {
1112 for (Callback callback : mCallbacks) {
1113 callback.onConsolidatedPolicyChanged();
1114 }
1115 }
1116
John Spurlock1c923a32014-04-27 16:42:29 -04001117 private void dispatchOnZenModeChanged() {
1118 for (Callback callback : mCallbacks) {
1119 callback.onZenModeChanged();
1120 }
1121 }
1122
John Spurlockb2278d62015-04-07 12:47:12 -04001123 private ZenModeConfig readDefaultConfig(Resources resources) {
1124 XmlResourceParser parser = null;
1125 try {
1126 parser = resources.getXml(R.xml.default_zen_mode_config);
1127 while (parser.next() != XmlPullParser.END_DOCUMENT) {
Julia Reynolds206c7e92016-09-15 10:38:03 -04001128 final ZenModeConfig config = ZenModeConfig.readXml(parser);
John Spurlockb2278d62015-04-07 12:47:12 -04001129 if (config != null) return config;
1130 }
1131 } catch (Exception e) {
1132 Log.w(TAG, "Error reading default zen mode config from resource", e);
1133 } finally {
1134 IoUtils.closeQuietly(parser);
1135 }
1136 return new ZenModeConfig();
1137 }
1138
John Spurlockb2278d62015-04-07 12:47:12 -04001139 private static int zenSeverity(int zen) {
1140 switch (zen) {
1141 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
1142 case Global.ZEN_MODE_ALARMS: return 2;
1143 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
1144 default: return 0;
1145 }
1146 }
1147
Beverly85f52412018-02-27 10:41:13 -05001148 @VisibleForTesting
1149 protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
John Spurlockb2278d62015-04-07 12:47:12 -04001150 @Override
1151 public String toString() {
1152 return TAG;
1153 }
1154
1155 @Override
1156 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
1157 int ringerModeExternal, VolumePolicy policy) {
1158 final boolean isChange = ringerModeOld != ringerModeNew;
1159
1160 int ringerModeExternalOut = ringerModeNew;
1161
Beverlye4ee1cc2018-03-06 17:21:08 -05001162 if (mZenMode == Global.ZEN_MODE_OFF
1163 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1164 && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) {
1165 // in priority only with ringer not muted, save ringer mode changes
1166 // in dnd off, save ringer mode changes
1167 setPreviousRingerModeSetting(ringerModeNew);
1168 }
John Spurlockb2278d62015-04-07 12:47:12 -04001169 int newZen = -1;
1170 switch (ringerModeNew) {
1171 case AudioManager.RINGER_MODE_SILENT:
1172 if (isChange && policy.doNotDisturbWhenSilent) {
Beverly925cde82018-01-23 09:31:23 -05001173 if (mZenMode == Global.ZEN_MODE_OFF) {
Julia Reynoldsf3252be2018-01-17 09:26:21 -05001174 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
John Spurlockb2278d62015-04-07 12:47:12 -04001175 }
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001176 setPreviousRingerModeSetting(ringerModeOld);
John Spurlockb2278d62015-04-07 12:47:12 -04001177 }
1178 break;
1179 case AudioManager.RINGER_MODE_VIBRATE:
1180 case AudioManager.RINGER_MODE_NORMAL:
1181 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
1182 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
Beverly925cde82018-01-23 09:31:23 -05001183 || mZenMode == Global.ZEN_MODE_ALARMS
1184 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1185 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
Beverlyd6964762018-02-16 14:07:03 -05001186 mConfig)))) {
John Spurlockb2278d62015-04-07 12:47:12 -04001187 newZen = Global.ZEN_MODE_OFF;
1188 } else if (mZenMode != Global.ZEN_MODE_OFF) {
1189 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
1190 }
1191 break;
1192 }
Beverly85f52412018-02-27 10:41:13 -05001193
John Spurlockb2278d62015-04-07 12:47:12 -04001194 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001195 setManualZenMode(newZen, null, "ringerModeInternal", null,
1196 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001197 }
John Spurlockb2278d62015-04-07 12:47:12 -04001198 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
1199 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
1200 ringerModeExternal, ringerModeExternalOut);
1201 }
1202 return ringerModeExternalOut;
1203 }
1204
1205 @Override
1206 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
1207 int ringerModeInternal, VolumePolicy policy) {
1208 int ringerModeInternalOut = ringerModeNew;
1209 final boolean isChange = ringerModeOld != ringerModeNew;
1210 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
1211
1212 int newZen = -1;
1213 switch (ringerModeNew) {
1214 case AudioManager.RINGER_MODE_SILENT:
1215 if (isChange) {
1216 if (mZenMode == Global.ZEN_MODE_OFF) {
Julia Reynoldsf3252be2018-01-17 09:26:21 -05001217 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
John Spurlockb2278d62015-04-07 12:47:12 -04001218 }
1219 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
John Spurlock05715ec2015-05-13 11:19:19 -04001220 : AudioManager.RINGER_MODE_SILENT;
John Spurlockb2278d62015-04-07 12:47:12 -04001221 } else {
1222 ringerModeInternalOut = ringerModeInternal;
1223 }
1224 break;
1225 case AudioManager.RINGER_MODE_VIBRATE:
1226 case AudioManager.RINGER_MODE_NORMAL:
1227 if (mZenMode != Global.ZEN_MODE_OFF) {
1228 newZen = Global.ZEN_MODE_OFF;
1229 }
1230 break;
1231 }
1232 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001233 setManualZenMode(newZen, null, "ringerModeExternal", caller,
1234 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001235 }
1236
1237 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
1238 ringerModeInternal, ringerModeInternalOut);
1239 return ringerModeInternalOut;
1240 }
John Spurlockd9c75db2015-04-28 11:19:13 -04001241
1242 @Override
1243 public boolean canVolumeDownEnterSilent() {
1244 return mZenMode == Global.ZEN_MODE_OFF;
1245 }
John Spurlock50ced3f2015-05-11 16:00:09 -04001246
1247 @Override
1248 public int getRingerModeAffectedStreams(int streams) {
Beverlyd6964762018-02-16 14:07:03 -05001249 // ringtone and notification streams are always affected by ringer mode
1250 // system stream is affected by ringer mode when not in priority-only
John Spurlock50ced3f2015-05-11 16:00:09 -04001251 streams |= (1 << AudioSystem.STREAM_RING) |
Beverlyd6964762018-02-16 14:07:03 -05001252 (1 << AudioSystem.STREAM_NOTIFICATION) |
1253 (1 << AudioSystem.STREAM_SYSTEM);
John Spurlock50ced3f2015-05-11 16:00:09 -04001254
John Spurlock50ced3f2015-05-11 16:00:09 -04001255 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
Beverly925cde82018-01-23 09:31:23 -05001256 // alarm and music streams affected by ringer mode when in total silence
John Spurlock50ced3f2015-05-11 16:00:09 -04001257 streams |= (1 << AudioSystem.STREAM_ALARM) |
Beverlyd6964762018-02-16 14:07:03 -05001258 (1 << AudioSystem.STREAM_MUSIC);
John Spurlock50ced3f2015-05-11 16:00:09 -04001259 } else {
1260 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
Beverlyd6964762018-02-16 14:07:03 -05001261 (1 << AudioSystem.STREAM_MUSIC));
1262 }
1263
1264 if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1265 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) {
1266 // system stream is not affected by ringer mode in priority only when the ringer
1267 // is zen muted (all other notification categories are muted)
1268 streams &= ~(1 << AudioSystem.STREAM_SYSTEM);
1269 } else {
1270 streams |= (1 << AudioSystem.STREAM_SYSTEM);
John Spurlock50ced3f2015-05-11 16:00:09 -04001271 }
1272 return streams;
1273 }
John Spurlockb2278d62015-04-07 12:47:12 -04001274 }
1275
1276 private final class SettingsObserver extends ContentObserver {
John Spurlock056c5192014-04-20 21:52:01 -04001277 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1278
1279 public SettingsObserver(Handler handler) {
1280 super(handler);
1281 }
1282
1283 public void observe() {
1284 final ContentResolver resolver = mContext.getContentResolver();
1285 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1286 update(null);
1287 }
1288
1289 @Override
1290 public void onChange(boolean selfChange, Uri uri) {
1291 update(uri);
1292 }
1293
1294 public void update(Uri uri) {
1295 if (ZEN_MODE.equals(uri)) {
John Spurlockb2278d62015-04-07 12:47:12 -04001296 if (mZenMode != getZenModeSetting()) {
1297 if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1298 setZenModeSetting(mZenMode);
1299 }
John Spurlock056c5192014-04-20 21:52:01 -04001300 }
1301 }
1302 }
1303
Beverly3bae4e52018-02-07 12:32:02 -05001304 private void showZenUpgradeNotification(int zen) {
Nicka485ec62018-07-03 11:32:39 -07001305 final boolean isWatch = mContext.getPackageManager().hasSystemFeature(
1306 PackageManager.FEATURE_WATCH);
Beverly3bae4e52018-02-07 12:32:02 -05001307 final boolean showNotification = mIsBootComplete
Julia Reynolds76bfa602018-04-23 09:38:47 -04001308 && zen != Global.ZEN_MODE_OFF
Nicka485ec62018-07-03 11:32:39 -07001309 && !isWatch
Beverly9087cd12018-09-21 15:30:49 -04001310 && Settings.Secure.getInt(mContext.getContentResolver(),
Beverly6c60b902018-08-17 10:10:46 -04001311 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
Beverly9087cd12018-09-21 15:30:49 -04001312 && Settings.Secure.getInt(mContext.getContentResolver(),
Beverly6c60b902018-08-17 10:10:46 -04001313 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
Beverly3bae4e52018-02-07 12:32:02 -05001314
Nicka485ec62018-07-03 11:32:39 -07001315 if (isWatch) {
Beverly9087cd12018-09-21 15:30:49 -04001316 Settings.Secure.putInt(mContext.getContentResolver(),
Beverly91d0a632018-07-02 16:45:00 -04001317 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Nicka485ec62018-07-03 11:32:39 -07001318 }
1319
Beverly3bae4e52018-02-07 12:32:02 -05001320 if (showNotification) {
1321 mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
1322 createZenUpgradeNotification());
Beverly91d0a632018-07-02 16:45:00 -04001323 Settings.Secure.putInt(mContext.getContentResolver(),
1324 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Beverly3bae4e52018-02-07 12:32:02 -05001325 }
1326 }
1327
1328 @VisibleForTesting
1329 protected Notification createZenUpgradeNotification() {
Beverly3bae4e52018-02-07 12:32:02 -05001330 final Bundle extras = new Bundle();
1331 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
1332 mContext.getResources().getString(R.string.global_action_settings));
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001333 int title = R.string.zen_upgrade_notification_title;
1334 int content = R.string.zen_upgrade_notification_content;
Julia Reynolds76bfa602018-04-23 09:38:47 -04001335 int drawable = R.drawable.ic_zen_24dp;
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001336 if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
Beverlyff2df9b2018-10-10 16:54:10 -04001337 getConsolidatedNotificationPolicy().suppressedVisualEffects)) {
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001338 title = R.string.zen_upgrade_notification_visd_title;
1339 content = R.string.zen_upgrade_notification_visd_content;
Julia Reynolds76bfa602018-04-23 09:38:47 -04001340 drawable = R.drawable.ic_dnd_block_notifications;
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001341 }
Julia Reynolds76bfa602018-04-23 09:38:47 -04001342
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001343 Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
1344 onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001345 return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001346 .setAutoCancel(true)
Beverlyd8b15ee2018-02-13 14:37:38 -05001347 .setSmallIcon(R.drawable.ic_settings_24dp)
Julia Reynolds76bfa602018-04-23 09:38:47 -04001348 .setLargeIcon(Icon.createWithResource(mContext, drawable))
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001349 .setContentTitle(mContext.getResources().getString(title))
1350 .setContentText(mContext.getResources().getString(content))
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001351 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
1352 PendingIntent.FLAG_UPDATE_CURRENT))
Beverly3bae4e52018-02-07 12:32:02 -05001353 .setAutoCancel(true)
1354 .setLocalOnly(true)
1355 .addExtras(extras)
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001356 .setStyle(new Notification.BigTextStyle())
Beverly3bae4e52018-02-07 12:32:02 -05001357 .build();
1358 }
1359
Chris Wren98d235b2015-05-27 18:25:17 -04001360 private final class Metrics extends Callback {
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001361 private static final String COUNTER_MODE_PREFIX = "dnd_mode_";
1362 private static final String COUNTER_TYPE_PREFIX = "dnd_type_";
1363 private static final int DND_OFF = 0;
1364 private static final int DND_ON_MANUAL = 1;
1365 private static final int DND_ON_AUTOMATIC = 2;
1366 private static final String COUNTER_RULE = "dnd_rule_count";
Chris Wren98d235b2015-05-27 18:25:17 -04001367 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1368
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001369 // Total silence, alarms only, priority only
Chris Wren98d235b2015-05-27 18:25:17 -04001370 private int mPreviousZenMode = -1;
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001371 private long mModeLogTimeMs = 0L;
1372
1373 private int mNumZenRules = -1;
1374 private long mRuleCountLogTime = 0L;
1375
1376 // automatic (1) vs manual (0) vs dnd off (2)
1377 private int mPreviousZenType = -1;
1378 private long mTypeLogTimeMs = 0L;
Chris Wren98d235b2015-05-27 18:25:17 -04001379
1380 @Override
1381 void onZenModeChanged() {
1382 emit();
1383 }
1384
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001385 @Override
1386 void onConfigChanged() {
1387 emit();
1388 }
1389
Chris Wren98d235b2015-05-27 18:25:17 -04001390 private void emit() {
1391 mHandler.postMetricsTimer();
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001392 emitZenMode();
1393 emitRules();
1394 emitDndType();
1395 }
1396
1397 private void emitZenMode() {
Chris Wren98d235b2015-05-27 18:25:17 -04001398 final long now = SystemClock.elapsedRealtime();
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001399 final long since = (now - mModeLogTimeMs);
Chris Wren98d235b2015-05-27 18:25:17 -04001400 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1401 if (mPreviousZenMode != -1) {
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001402 MetricsLogger.count(
1403 mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since);
Chris Wren98d235b2015-05-27 18:25:17 -04001404 }
1405 mPreviousZenMode = mZenMode;
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001406 mModeLogTimeMs = now;
1407 }
1408 }
1409
1410 private void emitRules() {
1411 final long now = SystemClock.elapsedRealtime();
1412 final long since = (now - mRuleCountLogTime);
1413 synchronized (mConfig) {
1414 int numZenRules = mConfig.automaticRules.size();
1415 if (mNumZenRules != numZenRules
1416 || since > MINIMUM_LOG_PERIOD_MS) {
1417 if (mNumZenRules != -1) {
1418 MetricsLogger.count(mContext, COUNTER_RULE,
1419 numZenRules - mNumZenRules);
1420 }
1421 mNumZenRules = numZenRules;
1422
1423 mRuleCountLogTime = since;
1424 }
1425 }
1426 }
1427
1428 private void emitDndType() {
1429 final long now = SystemClock.elapsedRealtime();
1430 final long since = (now - mTypeLogTimeMs);
1431 synchronized (mConfig) {
1432 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF;
1433 int zenType = !dndOn ? DND_OFF
1434 : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC;
1435 if (zenType != mPreviousZenType
1436 || since > MINIMUM_LOG_PERIOD_MS) {
1437 if (mPreviousZenType != -1) {
1438 MetricsLogger.count(
1439 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since);
1440 }
1441 mTypeLogTimeMs = now;
1442 mPreviousZenType = zenType;
1443 }
Chris Wren98d235b2015-05-27 18:25:17 -04001444 }
1445 }
1446 }
1447
John Spurlockb2278d62015-04-07 12:47:12 -04001448 private final class H extends Handler {
John Spurlock57627792014-12-11 11:29:54 -05001449 private static final int MSG_DISPATCH = 1;
Chris Wren98d235b2015-05-27 18:25:17 -04001450 private static final int MSG_METRICS = 2;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001451 private static final int MSG_APPLY_CONFIG = 4;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001452
1453 private final class ConfigMessageData {
1454 public final ZenModeConfig config;
Julia Reynolds8f056002018-07-13 15:12:29 -04001455 public ComponentName triggeringComponent;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001456 public final String reason;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001457 public final boolean setRingerMode;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001458
Julia Reynolds8f056002018-07-13 15:12:29 -04001459 ConfigMessageData(ZenModeConfig config, String reason,
1460 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001461 this.config = config;
1462 this.reason = reason;
1463 this.setRingerMode = setRingerMode;
Julia Reynolds8f056002018-07-13 15:12:29 -04001464 this.triggeringComponent = triggeringComponent;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001465 }
1466 }
Chris Wren98d235b2015-05-27 18:25:17 -04001467
1468 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
John Spurlock661f2cf2014-11-17 10:29:10 -05001469
1470 private H(Looper looper) {
1471 super(looper);
John Spurlock056c5192014-04-20 21:52:01 -04001472 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001473
John Spurlock57627792014-12-11 11:29:54 -05001474 private void postDispatchOnZenModeChanged() {
1475 removeMessages(MSG_DISPATCH);
1476 sendEmptyMessage(MSG_DISPATCH);
John Spurlock661f2cf2014-11-17 10:29:10 -05001477 }
1478
Chris Wren98d235b2015-05-27 18:25:17 -04001479 private void postMetricsTimer() {
1480 removeMessages(MSG_METRICS);
1481 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1482 }
1483
Julia Reynolds8f056002018-07-13 15:12:29 -04001484 private void postApplyConfig(ZenModeConfig config, String reason,
1485 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001486 sendMessage(obtainMessage(MSG_APPLY_CONFIG,
Julia Reynolds8f056002018-07-13 15:12:29 -04001487 new ConfigMessageData(config, reason, triggeringComponent, setRingerMode)));
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001488 }
1489
John Spurlock661f2cf2014-11-17 10:29:10 -05001490 @Override
1491 public void handleMessage(Message msg) {
John Spurlock57627792014-12-11 11:29:54 -05001492 switch (msg.what) {
1493 case MSG_DISPATCH:
1494 dispatchOnZenModeChanged();
John Spurlock661f2cf2014-11-17 10:29:10 -05001495 break;
Chris Wren98d235b2015-05-27 18:25:17 -04001496 case MSG_METRICS:
1497 mMetrics.emit();
1498 break;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001499 case MSG_APPLY_CONFIG:
1500 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1501 applyConfig(applyConfigData.config, applyConfigData.reason,
Julia Reynolds8f056002018-07-13 15:12:29 -04001502 applyConfigData.triggeringComponent, applyConfigData.setRingerMode);
John Spurlock661f2cf2014-11-17 10:29:10 -05001503 }
1504 }
1505 }
John Spurlock056c5192014-04-20 21:52:01 -04001506
John Spurlock1c923a32014-04-27 16:42:29 -04001507 public static class Callback {
1508 void onConfigChanged() {}
1509 void onZenModeChanged() {}
John Spurlock1fc476d2015-04-14 16:05:20 -04001510 void onPolicyChanged() {}
Beverlyff2df9b2018-10-10 16:54:10 -04001511 void onConsolidatedPolicyChanged() {}
John Spurlock056c5192014-04-20 21:52:01 -04001512 }
John Spurlock056c5192014-04-20 21:52:01 -04001513}