blob: b5d284494d20e1b882dfbfdb92b0f21f4ef3edb9 [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;
John Spurlock80774932015-05-07 17:38:50 -040021import android.app.NotificationManager;
John Spurlock1fc476d2015-04-14 16:05:20 -040022import android.app.NotificationManager.Policy;
John Spurlock312d1d02014-07-08 10:24:57 -040023import android.content.ComponentName;
John Spurlock056c5192014-04-20 21:52:01 -040024import android.content.ContentResolver;
25import android.content.Context;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -050026import android.content.Intent;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040027import android.content.pm.PackageManager;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -050028import android.content.pm.ResolveInfo;
29import android.content.pm.ServiceInfo;
John Spurlock056c5192014-04-20 21:52:01 -040030import android.content.res.Resources;
31import android.content.res.XmlResourceParser;
32import android.database.ContentObserver;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -070033import android.media.AudioAttributes;
John Spurlock056c5192014-04-20 21:52:01 -040034import android.media.AudioManager;
John Spurlock661f2cf2014-11-17 10:29:10 -050035import android.media.AudioManagerInternal;
John Spurlock50ced3f2015-05-11 16:00:09 -040036import android.media.AudioSystem;
John Spurlocka48d7792015-03-03 17:35:57 -050037import android.media.VolumePolicy;
John Spurlock056c5192014-04-20 21:52:01 -040038import android.net.Uri;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040039import android.os.Binder;
John Spurlock2b122f42014-08-27 16:29:47 -040040import android.os.Bundle;
John Spurlock056c5192014-04-20 21:52:01 -040041import android.os.Handler;
John Spurlock661f2cf2014-11-17 10:29:10 -050042import android.os.Looper;
43import android.os.Message;
Julia Reynoldsc8e54e82015-11-30 16:43:05 -050044import android.os.Process;
Chris Wren98d235b2015-05-27 18:25:17 -040045import android.os.SystemClock;
John Spurlockb5e767b2014-07-27 11:53:20 -040046import android.os.UserHandle;
John Spurlock056c5192014-04-20 21:52:01 -040047import android.provider.Settings.Global;
Julia Reynolds520df6e2017-02-13 09:05:10 -050048import android.service.notification.Condition;
Julia Reynolds43b70cd2016-01-14 15:05:34 -050049import android.service.notification.ConditionProviderService;
John Spurlock056c5192014-04-20 21:52:01 -040050import android.service.notification.ZenModeConfig;
John Spurlockcb9aa202015-05-08 17:35:22 -040051import android.service.notification.ZenModeConfig.EventInfo;
John Spurlockb2278d62015-04-07 12:47:12 -040052import android.service.notification.ZenModeConfig.ScheduleInfo;
53import android.service.notification.ZenModeConfig.ZenRule;
Julia Reynolds520df6e2017-02-13 09:05:10 -050054import android.service.notification.ZenModeProto;
Julia Reynolds87c42772016-05-16 09:52:17 -040055import android.util.AndroidRuntimeException;
John Spurlock4db0d982014-08-13 09:19:03 -040056import android.util.Log;
Beverlyd4f96492017-08-02 13:36:11 -040057import android.util.Slog;
John Spurlock21258a32015-05-27 18:22:55 -040058import android.util.SparseArray;
Julia Reynolds520df6e2017-02-13 09:05:10 -050059import android.util.proto.ProtoOutputStream;
John Spurlock056c5192014-04-20 21:52:01 -040060
61import com.android.internal.R;
Beverly04216872017-09-28 10:55:32 -040062import com.android.internal.annotations.VisibleForTesting;
John Spurlock25d01ee2015-06-03 12:17:46 -040063import com.android.internal.logging.MetricsLogger;
John Spurlock661f2cf2014-11-17 10:29:10 -050064import com.android.server.LocalServices;
John Spurlock056c5192014-04-20 21:52:01 -040065
66import libcore.io.IoUtils;
67
68import org.xmlpull.v1.XmlPullParser;
69import org.xmlpull.v1.XmlPullParserException;
70import org.xmlpull.v1.XmlSerializer;
71
72import java.io.IOException;
73import java.io.PrintWriter;
John Spurlock1c923a32014-04-27 16:42:29 -040074import java.util.ArrayList;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040075import java.util.List;
John Spurlock1fc476d2015-04-14 16:05:20 -040076import java.util.Objects;
John Spurlock056c5192014-04-20 21:52:01 -040077
78/**
79 * NotificationManagerService helper for functionality related to zen mode.
80 */
John Spurlockb2278d62015-04-07 12:47:12 -040081public class ZenModeHelper {
82 static final String TAG = "ZenModeHelper";
83 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlock056c5192014-04-20 21:52:01 -040084
Julia Reynolds5a43aaa2015-12-15 13:54:41 -050085 // The amount of time rules instances can exist without their owning app being installed.
86 private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
87
John Spurlock056c5192014-04-20 21:52:01 -040088 private final Context mContext;
John Spurlock661f2cf2014-11-17 10:29:10 -050089 private final H mHandler;
John Spurlock056c5192014-04-20 21:52:01 -040090 private final SettingsObserver mSettingsObserver;
Beverly04216872017-09-28 10:55:32 -040091 @VisibleForTesting protected final AppOpsManager mAppOps;
Beverlyd4f96492017-08-02 13:36:11 -040092 protected ZenModeConfig mDefaultConfig;
John Spurlock1c923a32014-04-27 16:42:29 -040093 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
John Spurlockb2278d62015-04-07 12:47:12 -040094 private final ZenModeFiltering mFiltering;
95 private final RingerModeDelegate mRingerModeDelegate = new RingerModeDelegate();
96 private final ZenModeConditions mConditions;
John Spurlock21258a32015-05-27 18:22:55 -040097 private final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
Chris Wren98d235b2015-05-27 18:25:17 -040098 private final Metrics mMetrics = new Metrics();
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -050099 private final ConditionProviders.Config mServiceConfig;
John Spurlock056c5192014-04-20 21:52:01 -0400100
Beverly04216872017-09-28 10:55:32 -0400101 @VisibleForTesting protected int mZenMode;
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700102 private int mUser = UserHandle.USER_SYSTEM;
Beverly04216872017-09-28 10:55:32 -0400103 @VisibleForTesting protected ZenModeConfig mConfig;
John Spurlock661f2cf2014-11-17 10:29:10 -0500104 private AudioManagerInternal mAudioManager;
Beverlyd4f96492017-08-02 13:36:11 -0400105 protected PackageManager mPm;
Bryce Lee7219ada2016-04-08 10:54:23 -0700106 private long mSuppressedEffects;
107
108 public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
109 public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
110 public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
111 | SUPPRESSED_EFFECT_NOTIFICATIONS;
John Spurlock056c5192014-04-20 21:52:01 -0400112
Beverly26eba872017-12-04 16:30:11 -0500113 protected String mDefaultRuleEveryNightName;
Beverlyd4f96492017-08-02 13:36:11 -0400114 protected String mDefaultRuleEventsName;
Beverlyd4f96492017-08-02 13:36:11 -0400115
John Spurlockb2278d62015-04-07 12:47:12 -0400116 public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
John Spurlock056c5192014-04-20 21:52:01 -0400117 mContext = context;
John Spurlock661f2cf2014-11-17 10:29:10 -0500118 mHandler = new H(looper);
Chris Wren98d235b2015-05-27 18:25:17 -0400119 addCallback(mMetrics);
John Spurlock056c5192014-04-20 21:52:01 -0400120 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Beverlyd4f96492017-08-02 13:36:11 -0400121
122 mDefaultConfig = new ZenModeConfig();
Beverlyd4f96492017-08-02 13:36:11 -0400123 setDefaultZenRules(mContext);
John Spurlock056c5192014-04-20 21:52:01 -0400124 mConfig = mDefaultConfig;
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700125 mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
Beverlyd4f96492017-08-02 13:36:11 -0400126
John Spurlock056c5192014-04-20 21:52:01 -0400127 mSettingsObserver = new SettingsObserver(mHandler);
128 mSettingsObserver.observe();
John Spurlockb2278d62015-04-07 12:47:12 -0400129 mFiltering = new ZenModeFiltering(mContext);
130 mConditions = new ZenModeConditions(this, conditionProviders);
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500131 mServiceConfig = conditionProviders.getConfig();
Beverlyd4f96492017-08-02 13:36:11 -0400132
John Spurlock056c5192014-04-20 21:52:01 -0400133 }
134
John Spurlock1b8b22b2015-05-20 09:47:13 -0400135 public Looper getLooper() {
136 return mHandler.getLooper();
137 }
138
John Spurlockb2278d62015-04-07 12:47:12 -0400139 @Override
140 public String toString() {
141 return TAG;
142 }
143
144 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
145 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400146 synchronized (mConfig) {
147 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConfig, userHandle,
Julia Reynoldsc6b371b2016-06-14 08:31:03 -0400148 extras, validator, contactsTimeoutMs, timeoutAffinity);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400149 }
John Spurlockb2278d62015-04-07 12:47:12 -0400150 }
151
152 public boolean isCall(NotificationRecord record) {
153 return mFiltering.isCall(record);
154 }
155
Julia Reynoldsc6b371b2016-06-14 08:31:03 -0400156 public void recordCaller(NotificationRecord record) {
157 mFiltering.recordCall(record);
158 }
159
John Spurlockb2278d62015-04-07 12:47:12 -0400160 public boolean shouldIntercept(NotificationRecord record) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400161 synchronized (mConfig) {
162 return mFiltering.shouldIntercept(mZenMode, mConfig, record);
163 }
John Spurlock056c5192014-04-20 21:52:01 -0400164 }
165
Julia Reynoldsd5607292016-02-05 15:25:58 -0500166 public boolean shouldSuppressWhenScreenOff() {
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500167 synchronized (mConfig) {
Julia Reynoldsd5607292016-02-05 15:25:58 -0500168 return !mConfig.allowWhenScreenOff;
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500169 }
170 }
171
Julia Reynoldsd5607292016-02-05 15:25:58 -0500172 public boolean shouldSuppressWhenScreenOn() {
Julia Reynoldsf612869ae2015-11-05 16:48:55 -0500173 synchronized (mConfig) {
Julia Reynoldsd5607292016-02-05 15:25:58 -0500174 return !mConfig.allowWhenScreenOn;
Julia Reynolds61721582016-01-05 08:35:25 -0500175 }
176 }
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);
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 }
Beverly26eba872017-12-04 16:30:11 -0500227 enforceDefaultRulesExist(config);
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500228 synchronized (mConfig) {
229 setConfigLocked(config, reason);
230 }
231 cleanUpZenRules();
232 }
233
Beverly26eba872017-12-04 16:30:11 -0500234 private void enforceDefaultRulesExist(ZenModeConfig config) {
235 for (String id : ZenModeConfig.DEFAULT_RULE_IDS) {
236 if (!config.automaticRules.containsKey(id)) {
237 if (id.equals(ZenModeConfig.EVENTS_DEFAULT_RULE_ID)) {
238 appendDefaultEventRules(config);
239 } else if (id.equals(ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID)) {
240 appendDefaultEveryNightRule(config);
241 }
242 }
243 }
244 }
245
Christoph Studer85a384b2014-08-27 20:16:15 +0200246 public int getZenModeListenerInterruptionFilter() {
John Spurlock80774932015-05-07 17:38:50 -0400247 return NotificationManager.zenModeToInterruptionFilter(mZenMode);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400248 }
249
John Spurlock80774932015-05-07 17:38:50 -0400250 public void requestFromListener(ComponentName name, int filter) {
251 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400252 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400253 setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
John Spurlockb2278d62015-04-07 12:47:12 -0400254 "listener:" + (name != null ? name.flattenToShortString() : null));
John Spurlockd8afe3c2014-08-01 14:04:07 -0400255 }
256 }
257
Bryce Lee7219ada2016-04-08 10:54:23 -0700258 public void setSuppressedEffects(long suppressedEffects) {
259 if (mSuppressedEffects == suppressedEffects) return;
260 mSuppressedEffects = suppressedEffects;
John Spurlock8403b752014-12-10 12:47:01 -0500261 applyRestrictions();
262 }
263
Bryce Lee7219ada2016-04-08 10:54:23 -0700264 public long getSuppressedEffects() {
265 return mSuppressedEffects;
266 }
267
John Spurlock1c923a32014-04-27 16:42:29 -0400268 public int getZenMode() {
269 return mZenMode;
270 }
271
Julia Reynolds361e82d32016-02-26 18:19:49 -0500272 public List<ZenRule> getZenRules() {
273 List<ZenRule> rules = new ArrayList<>();
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400274 synchronized (mConfig) {
275 if (mConfig == null) return rules;
276 for (ZenRule rule : mConfig.automaticRules.values()) {
277 if (canManageAutomaticZenRule(rule)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500278 rules.add(rule);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400279 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400280 }
281 }
282 return rules;
283 }
284
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400285 public AutomaticZenRule getAutomaticZenRule(String id) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400286 ZenRule rule;
287 synchronized (mConfig) {
288 if (mConfig == null) return null;
289 rule = mConfig.automaticRules.get(id);
290 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400291 if (rule == null) return null;
292 if (canManageAutomaticZenRule(rule)) {
293 return createAutomaticZenRule(rule);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400294 }
295 return null;
296 }
297
Julia Reynolds361e82d32016-02-26 18:19:49 -0500298 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500299 if (!isSystemRule(automaticZenRule)) {
300 ServiceInfo owner = getServiceInfo(automaticZenRule.getOwner());
301 if (owner == null) {
302 throw new IllegalArgumentException("Owner is not a condition provider service");
303 }
304
Julia Reynolds7f2f4412016-03-01 12:33:48 -0500305 int ruleInstanceLimit = -1;
306 if (owner.metaData != null) {
307 ruleInstanceLimit = owner.metaData.getInt(
308 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
309 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500310 if (ruleInstanceLimit > 0 && ruleInstanceLimit
311 < (getCurrentInstanceCount(automaticZenRule.getOwner()) + 1)) {
312 throw new IllegalArgumentException("Rule instance limit exceeded");
313 }
314 }
315
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400316 ZenModeConfig newConfig;
317 synchronized (mConfig) {
Julia Reynolds87c42772016-05-16 09:52:17 -0400318 if (mConfig == null) {
319 throw new AndroidRuntimeException("Could not create rule");
320 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400321 if (DEBUG) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500322 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400323 }
324 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500325 ZenRule rule = new ZenRule();
326 populateZenRule(automaticZenRule, rule, true);
327 newConfig.automaticRules.put(rule.id, rule);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500328 if (setConfigLocked(newConfig, reason, true)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500329 return rule.id;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500330 } else {
Julia Reynolds87c42772016-05-16 09:52:17 -0400331 throw new AndroidRuntimeException("Could not create rule");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500332 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400333 }
334 }
335
Julia Reynolds361e82d32016-02-26 18:19:49 -0500336 public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
337 String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400338 ZenModeConfig newConfig;
339 synchronized (mConfig) {
340 if (mConfig == null) return false;
341 if (DEBUG) {
342 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule
343 + " reason=" + reason);
344 }
345 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500346 ZenModeConfig.ZenRule rule;
347 if (ruleId == null) {
348 throw new IllegalArgumentException("Rule doesn't exist");
349 } else {
350 rule = newConfig.automaticRules.get(ruleId);
351 if (rule == null || !canManageAutomaticZenRule(rule)) {
352 throw new SecurityException(
353 "Cannot update rules not owned by your condition provider");
354 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400355 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500356 populateZenRule(automaticZenRule, rule, false);
357 newConfig.automaticRules.put(ruleId, rule);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500358 return setConfigLocked(newConfig, reason, true);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400359 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400360 }
361
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400362 public boolean removeAutomaticZenRule(String id, String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400363 ZenModeConfig newConfig;
364 synchronized (mConfig) {
365 if (mConfig == null) return false;
366 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500367 ZenRule rule = newConfig.automaticRules.get(id);
368 if (rule == null) return false;
369 if (canManageAutomaticZenRule(rule)) {
370 newConfig.automaticRules.remove(id);
371 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
372 } else {
373 throw new SecurityException(
374 "Cannot delete rules not owned by your condition provider");
375 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500376 return setConfigLocked(newConfig, reason, true);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400377 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400378 }
379
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500380 public boolean removeAutomaticZenRules(String packageName, String reason) {
381 ZenModeConfig newConfig;
382 synchronized (mConfig) {
383 if (mConfig == null) return false;
384 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500385 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
386 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
387 if (rule.component.getPackageName().equals(packageName)
388 && canManageAutomaticZenRule(rule)) {
389 newConfig.automaticRules.removeAt(i);
390 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500391 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500392 return setConfigLocked(newConfig, reason, true);
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500393 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500394 }
395
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500396 public int getCurrentInstanceCount(ComponentName owner) {
397 int count = 0;
398 synchronized (mConfig) {
399 for (ZenRule rule : mConfig.automaticRules.values()) {
400 if (rule.component != null && rule.component.equals(owner)) {
401 count++;
402 }
403 }
404 }
405 return count;
406 }
407
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400408 public boolean canManageAutomaticZenRule(ZenRule rule) {
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500409 final int callingUid = Binder.getCallingUid();
410 if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
411 return true;
412 } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400413 == PackageManager.PERMISSION_GRANTED) {
414 return true;
415 } else {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500416 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400417 if (packages != null) {
418 final int packageCount = packages.length;
419 for (int i = 0; i < packageCount; i++) {
420 if (packages[i].equals(rule.component.getPackageName())) {
421 return true;
422 }
423 }
424 }
425 return false;
426 }
427 }
428
Beverlyd4f96492017-08-02 13:36:11 -0400429 public void setDefaultZenRules(Context context) {
430 mDefaultConfig = readDefaultConfig(context.getResources());
Beverlyd4f96492017-08-02 13:36:11 -0400431 appendDefaultRules(mDefaultConfig);
432 }
433
434 private void appendDefaultRules (ZenModeConfig config) {
Beverly30bfbca2017-10-17 14:38:20 -0400435 getDefaultRuleNames();
Beverly26eba872017-12-04 16:30:11 -0500436 appendDefaultEveryNightRule(config);
Beverlyd4f96492017-08-02 13:36:11 -0400437 appendDefaultEventRules(config);
438 }
439
440 // Checks zen rule properties are the same (doesn't check creation time, name nor enabled)
441 // used to check if default rules were customized or not
442 private boolean ruleValuesEqual(AutomaticZenRule rule, ZenRule defaultRule) {
443 if (rule == null || defaultRule == null) {
444 return false;
445 }
446 return rule.getInterruptionFilter() ==
447 NotificationManager.zenModeToInterruptionFilter(defaultRule.zenMode)
448 && rule.getConditionId().equals(defaultRule.conditionId)
449 && rule.getOwner().equals(defaultRule.component);
450 }
451
452 protected void updateDefaultZenRules() {
453 ZenModeConfig configDefaultRules = new ZenModeConfig();
454 appendDefaultRules(configDefaultRules); // "new" localized default rules
Beverly26eba872017-12-04 16:30:11 -0500455 for (String ruleId : ZenModeConfig.DEFAULT_RULE_IDS) {
Beverlyd4f96492017-08-02 13:36:11 -0400456 AutomaticZenRule currRule = getAutomaticZenRule(ruleId);
457 ZenRule defaultRule = configDefaultRules.automaticRules.get(ruleId);
458 // if default rule wasn't customized, use localized name instead of previous
459 if (ruleValuesEqual(currRule, defaultRule) &&
460 !defaultRule.name.equals(currRule.getName())) {
461 if (canManageAutomaticZenRule(defaultRule)) {
462 if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name "
463 + "from " + currRule.getName() + " to " + defaultRule.name);
464 // update default rule (if locale changed, name of rule will change)
465 AutomaticZenRule defaultAutoRule = createAutomaticZenRule(defaultRule);
Beverly83639442017-09-06 10:36:04 -0400466 // ensure enabled state is carried over from current rule
467 defaultAutoRule.setEnabled(currRule.isEnabled());
Beverlyd4f96492017-08-02 13:36:11 -0400468 updateAutomaticZenRule(ruleId, defaultAutoRule,
469 "locale changed");
470 }
471 }
472 }
473 }
474
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500475 private boolean isSystemRule(AutomaticZenRule rule) {
476 return ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
477 }
478
479 private ServiceInfo getServiceInfo(ComponentName owner) {
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500480 Intent queryIntent = new Intent();
481 queryIntent.setComponent(owner);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500482 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500483 queryIntent,
484 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
485 UserHandle.getCallingUserId());
486 if (installedServices != null) {
487 for (int i = 0, count = installedServices.size(); i < count; i++) {
488 ResolveInfo resolveInfo = installedServices.get(i);
489 ServiceInfo info = resolveInfo.serviceInfo;
490 if (mServiceConfig.bindPermission.equals(info.permission)) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500491 return info;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500492 }
493 }
494 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500495 return null;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500496 }
497
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400498 private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
499 if (isNew) {
500 rule.id = ZenModeConfig.newRuleId();
501 rule.creationTime = System.currentTimeMillis();
502 rule.component = automaticZenRule.getOwner();
503 }
504
505 if (rule.enabled != automaticZenRule.isEnabled()) {
506 rule.snoozing = false;
507 }
508 rule.name = automaticZenRule.getName();
509 rule.condition = null;
510 rule.conditionId = automaticZenRule.getConditionId();
511 rule.enabled = automaticZenRule.isEnabled();
512 rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
513 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
514 }
515
Beverlyd4f96492017-08-02 13:36:11 -0400516 protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400517 return new AutomaticZenRule(rule.name, rule.component, rule.conditionId,
Julia Reynolds56106ff2015-09-30 14:42:53 -0400518 NotificationManager.zenModeToInterruptionFilter(rule.zenMode), rule.enabled,
Julia Reynolds361e82d32016-02-26 18:19:49 -0500519 rule.creationTime);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400520 }
521
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400522 public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
523 setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
John Spurlocke77bb362014-04-26 10:24:59 -0400524 }
525
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400526 private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
John Spurlockb2278d62015-04-07 12:47:12 -0400527 boolean setRingerMode) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400528 ZenModeConfig newConfig;
529 synchronized (mConfig) {
530 if (mConfig == null) return;
531 if (!Global.isValidZenMode(zenMode)) return;
532 if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode)
533 + " conditionId=" + conditionId + " reason=" + reason
534 + " setRingerMode=" + setRingerMode);
535 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500536 if (zenMode == Global.ZEN_MODE_OFF) {
537 newConfig.manualRule = null;
538 for (ZenRule automaticRule : newConfig.automaticRules.values()) {
539 if (automaticRule.isAutomaticActive()) {
540 automaticRule.snoozing = true;
541 }
John Spurlockb2278d62015-04-07 12:47:12 -0400542 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500543 } else {
544 final ZenRule newRule = new ZenRule();
545 newRule.enabled = true;
546 newRule.zenMode = zenMode;
547 newRule.conditionId = conditionId;
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400548 newRule.enabler = caller;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500549 newConfig.manualRule = newRule;
John Spurlockb2278d62015-04-07 12:47:12 -0400550 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500551 setConfigLocked(newConfig, reason, setRingerMode);
John Spurlockb2278d62015-04-07 12:47:12 -0400552 }
John Spurlockb2278d62015-04-07 12:47:12 -0400553 }
554
Julia Reynolds520df6e2017-02-13 09:05:10 -0500555 void dump(ProtoOutputStream proto) {
556
557 proto.write(ZenModeProto.ZEN_MODE, mZenMode);
558 synchronized (mConfig) {
559 if (mConfig.manualRule != null) {
560 proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, mConfig.manualRule.toString());
561 }
562 for (ZenRule rule : mConfig.automaticRules.values()) {
563 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
564 && !rule.snoozing) {
565 proto.write(ZenModeProto.ENABLED_ACTIVE_CONDITIONS, rule.toString());
566 }
567 }
Kweku Adams5ec78cd2017-09-25 16:29:54 -0700568 mConfig.toNotificationPolicy().toProto(proto, ZenModeProto.POLICY);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500569 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
570 }
571 }
572
John Spurlockb2278d62015-04-07 12:47:12 -0400573 public void dump(PrintWriter pw, String prefix) {
574 pw.print(prefix); pw.print("mZenMode=");
575 pw.println(Global.zenModeToString(mZenMode));
John Spurlock21258a32015-05-27 18:22:55 -0400576 final int N = mConfigs.size();
577 for (int i = 0; i < N; i++) {
578 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
579 }
580 pw.print(prefix); pw.print("mUser="); pw.println(mUser);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400581 synchronized (mConfig) {
582 dump(pw, prefix, "mConfig", mConfig);
583 }
Bryce Lee7219ada2016-04-08 10:54:23 -0700584
585 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
John Spurlock1d7d2242015-04-10 08:10:22 -0400586 mFiltering.dump(pw, prefix);
John Spurlockb2278d62015-04-07 12:47:12 -0400587 mConditions.dump(pw, prefix);
588 }
589
590 private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) {
591 pw.print(prefix); pw.print(var); pw.print('=');
592 if (config == null) {
593 pw.println(config);
594 return;
595 }
Beverly04216872017-09-28 10:55:32 -0400596 pw.printf("allow(alarms=%b,media=%bcalls=%b,callsFrom=%s,repeatCallers=%b,messages=%b,messagesFrom=%s,"
Ian Rogersb0b995b2016-06-06 23:43:59 -0700597 + "events=%b,reminders=%b,whenScreenOff=%b,whenScreenOn=%b)\n",
Beverly04216872017-09-28 10:55:32 -0400598 config.allowAlarms, config.allowMediaSystemOther,
Julia Reynolds6ee26172015-09-28 11:34:48 -0400599 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
600 config.allowRepeatCallers, config.allowMessages,
601 ZenModeConfig.sourceToString(config.allowMessagesFrom),
Julia Reynoldsd5607292016-02-05 15:25:58 -0500602 config.allowEvents, config.allowReminders, config.allowWhenScreenOff,
603 config.allowWhenScreenOn);
John Spurlockb2278d62015-04-07 12:47:12 -0400604 pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule);
605 if (config.automaticRules.isEmpty()) return;
606 final int N = config.automaticRules.size();
607 for (int i = 0; i < N; i++) {
608 pw.print(prefix); pw.print(i == 0 ? " automaticRules=" : " ");
609 pw.println(config.automaticRules.valueAt(i));
610 }
611 }
612
John Spurlock35ef0a62015-05-28 11:24:10 -0400613 public void readXml(XmlPullParser parser, boolean forRestore)
614 throws XmlPullParserException, IOException {
Julia Reynolds206c7e92016-09-15 10:38:03 -0400615 final ZenModeConfig config = ZenModeConfig.readXml(parser);
John Spurlockb2278d62015-04-07 12:47:12 -0400616 if (config != null) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400617 if (forRestore) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700618 //TODO: http://b/22388012
619 if (config.user != UserHandle.USER_SYSTEM) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400620 return;
621 }
622 config.manualRule = null; // don't restore the manual rule
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500623 long time = System.currentTimeMillis();
John Spurlock995a7492015-05-28 22:13:03 -0400624 if (config.automaticRules != null) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400625 for (ZenRule automaticRule : config.automaticRules.values()) {
John Spurlock995a7492015-05-28 22:13:03 -0400626 // don't restore transient state from restored automatic rules
627 automaticRule.snoozing = false;
628 automaticRule.condition = null;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500629 automaticRule.creationTime = time;
John Spurlock995a7492015-05-28 22:13:03 -0400630 }
631 }
John Spurlock35ef0a62015-05-28 11:24:10 -0400632 }
John Spurlockb2278d62015-04-07 12:47:12 -0400633 if (DEBUG) Log.d(TAG, "readXml");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500634 synchronized (mConfig) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500635 setConfigLocked(config, "readXml");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500636 }
John Spurlockb2278d62015-04-07 12:47:12 -0400637 }
638 }
639
John Spurlock35ef0a62015-05-28 11:24:10 -0400640 public void writeXml(XmlSerializer out, boolean forBackup) throws IOException {
John Spurlock21258a32015-05-27 18:22:55 -0400641 final int N = mConfigs.size();
642 for (int i = 0; i < N; i++) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700643 //TODO: http://b/22388012
644 if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400645 continue;
646 }
John Spurlock21258a32015-05-27 18:22:55 -0400647 mConfigs.valueAt(i).writeXml(out);
648 }
John Spurlockb2278d62015-04-07 12:47:12 -0400649 }
650
John Spurlock1fc476d2015-04-14 16:05:20 -0400651 public Policy getNotificationPolicy() {
652 return getNotificationPolicy(mConfig);
653 }
654
655 private static Policy getNotificationPolicy(ZenModeConfig config) {
656 return config == null ? null : config.toNotificationPolicy();
657 }
658
659 public void setNotificationPolicy(Policy policy) {
660 if (policy == null || mConfig == null) return;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500661 synchronized (mConfig) {
662 final ZenModeConfig newConfig = mConfig.copy();
663 newConfig.applyNotificationPolicy(policy);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500664 setConfigLocked(newConfig, "setNotificationPolicy");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500665 }
John Spurlock1fc476d2015-04-14 16:05:20 -0400666 }
667
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500668 /**
669 * Removes old rule instances whose owner is not installed.
670 */
671 private void cleanUpZenRules() {
672 long currentTime = System.currentTimeMillis();
673 synchronized (mConfig) {
674 final ZenModeConfig newConfig = mConfig.copy();
675 if (newConfig.automaticRules != null) {
676 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
677 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
678 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
679 try {
Jeff Sharkeyc7bacab2016-02-09 15:56:11 -0700680 mPm.getPackageInfo(rule.component.getPackageName(),
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -0700681 PackageManager.MATCH_ANY_USER);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500682 } catch (PackageManager.NameNotFoundException e) {
683 newConfig.automaticRules.removeAt(i);
684 }
685 }
686 }
687 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500688 setConfigLocked(newConfig, "cleanUpZenRules");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500689 }
690 }
691
692 /**
693 * @return a copy of the zen mode configuration
694 */
John Spurlockb2278d62015-04-07 12:47:12 -0400695 public ZenModeConfig getConfig() {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400696 synchronized (mConfig) {
697 return mConfig.copy();
698 }
John Spurlockb2278d62015-04-07 12:47:12 -0400699 }
700
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500701 public boolean setConfigLocked(ZenModeConfig config, String reason) {
702 return setConfigLocked(config, reason, true /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -0400703 }
704
Julia Reynolds89aeab02016-09-15 11:07:50 -0400705 public void setConfig(ZenModeConfig config, String reason) {
706 synchronized (mConfig) {
707 setConfigLocked(config, reason);
708 }
Eric Laurente0ced4d2015-09-30 17:44:28 -0700709 }
710
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500711 private boolean setConfigLocked(ZenModeConfig config, String reason, boolean setRingerMode) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400712 final long identity = Binder.clearCallingIdentity();
713 try {
714 if (config == null || !config.isValid()) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500715 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400716 return false;
717 }
718 if (config.user != mUser) {
719 // simply store away for background users
720 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500721 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400722 return true;
723 }
724 mConditions.evaluateConfig(config, false /*processSubscriptions*/); // may modify config
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500725 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500726 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500727 ZenLog.traceConfig(reason, mConfig, config);
728 final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
729 getNotificationPolicy(config));
Julia Reynolds9a25da12016-01-06 16:19:28 -0500730 if (!config.equals(mConfig)) {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500731 dispatchOnConfigChanged();
732 }
733 if (policyChanged) {
734 dispatchOnPolicyChanged();
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400735 }
Julia Reynolds9a25da12016-01-06 16:19:28 -0500736 mConfig = config;
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400737 mHandler.postApplyConfig(config, reason, setRingerMode);
John Spurlock21258a32015-05-27 18:22:55 -0400738 return true;
Julia Reynoldscb507b82017-09-07 13:53:40 -0400739 } catch (SecurityException e) {
740 Log.wtf(TAG, "Invalid rule in config", e);
741 return false;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400742 } finally {
743 Binder.restoreCallingIdentity(identity);
John Spurlock21258a32015-05-27 18:22:55 -0400744 }
John Spurlockb2278d62015-04-07 12:47:12 -0400745 }
746
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400747 private void applyConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
748 final String val = Integer.toString(config.hashCode());
749 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
750 if (!evaluateZenMode(reason, setRingerMode)) {
751 applyRestrictions(); // evaluateZenMode will also apply restrictions if changed
752 }
753 mConditions.evaluateConfig(config, true /*processSubscriptions*/);
754 }
755
John Spurlockb2278d62015-04-07 12:47:12 -0400756 private int getZenModeSetting() {
757 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
758 }
759
760 private void setZenModeSetting(int zen) {
761 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
762 }
763
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400764 private int getPreviousRingerModeSetting() {
765 return Global.getInt(mContext.getContentResolver(),
766 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
767 }
768
769 private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
770 Global.putString(
771 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
772 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
773 }
774
John Spurlockb2278d62015-04-07 12:47:12 -0400775 private boolean evaluateZenMode(String reason, boolean setRingerMode) {
776 if (DEBUG) Log.d(TAG, "evaluateZenMode");
Jason Monka9927322015-12-13 16:22:37 -0500777 final int zenBefore = mZenMode;
Julia Reynolds8ac63032015-08-31 15:19:43 -0400778 final int zen = computeZenMode();
John Spurlockb2278d62015-04-07 12:47:12 -0400779 ZenLog.traceSetZenMode(zen, reason);
780 mZenMode = zen;
John Spurlock50ced3f2015-05-11 16:00:09 -0400781 updateRingerModeAffectedStreams();
John Spurlockb2278d62015-04-07 12:47:12 -0400782 setZenModeSetting(mZenMode);
John Spurlock57627792014-12-11 11:29:54 -0500783 if (setRingerMode) {
784 applyZenToRingerMode();
785 }
786 applyRestrictions();
Jason Monka9927322015-12-13 16:22:37 -0500787 if (zen != zenBefore) {
Julia Reynolds8ac63032015-08-31 15:19:43 -0400788 mHandler.postDispatchOnZenModeChanged();
789 }
John Spurlockb2278d62015-04-07 12:47:12 -0400790 return true;
John Spurlock57627792014-12-11 11:29:54 -0500791 }
792
John Spurlock50ced3f2015-05-11 16:00:09 -0400793 private void updateRingerModeAffectedStreams() {
794 if (mAudioManager != null) {
795 mAudioManager.updateRingerModeAffectedStreamsInternal();
796 }
797 }
798
Julia Reynolds8ac63032015-08-31 15:19:43 -0400799 private int computeZenMode() {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400800 synchronized (mConfig) {
801 if (mConfig == null) return Global.ZEN_MODE_OFF;
802 if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
803 int zen = Global.ZEN_MODE_OFF;
804 for (ZenRule automaticRule : mConfig.automaticRules.values()) {
805 if (automaticRule.isAutomaticActive()) {
806 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
807 zen = automaticRule.zenMode;
808 }
John Spurlockb2278d62015-04-07 12:47:12 -0400809 }
810 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400811 return zen;
John Spurlockb2278d62015-04-07 12:47:12 -0400812 }
John Spurlock8403b752014-12-10 12:47:01 -0500813 }
814
Beverly30bfbca2017-10-17 14:38:20 -0400815 private void getDefaultRuleNames() {
816 // on locale-change, these values differ
Beverly26eba872017-12-04 16:30:11 -0500817 mDefaultRuleEveryNightName = mContext.getResources()
818 .getString(R.string.zen_mode_default_every_night_name);
Beverly30bfbca2017-10-17 14:38:20 -0400819 mDefaultRuleEventsName = mContext.getResources()
820 .getString(R.string.zen_mode_default_events_name);
821 }
822
Beverly04216872017-09-28 10:55:32 -0400823 @VisibleForTesting
824 protected void applyRestrictions() {
Beverlyd820bc22018-01-11 15:28:33 -0500825 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
826 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
827 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
John Spurlock8403b752014-12-10 12:47:01 -0500828
829 // notification restrictions
Bryce Lee7219ada2016-04-08 10:54:23 -0700830 final boolean muteNotifications =
831 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
John Spurlock056c5192014-04-20 21:52:01 -0400832 // call restrictions
Beverlyd820bc22018-01-11 15:28:33 -0500833 final boolean muteCalls = zenAlarmsOnly
834 || (zenPriorityOnly && !mConfig.allowCalls && !mConfig.allowRepeatCallers)
Bryce Lee7219ada2016-04-08 10:54:23 -0700835 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
Beverly04216872017-09-28 10:55:32 -0400836 // alarm restrictions
Beverlyd820bc22018-01-11 15:28:33 -0500837 final boolean muteAlarms = zenPriorityOnly && !mConfig.allowAlarms;
Beverly04216872017-09-28 10:55:32 -0400838 // alarm restrictions
Beverlyd820bc22018-01-11 15:28:33 -0500839 final boolean muteMediaAndSystemSounds = zenPriorityOnly && !mConfig.allowMediaSystemOther;
Julia Reynolds3fe81be2016-02-03 09:10:06 -0500840 // total silence restrictions
Beverlyd820bc22018-01-11 15:28:33 -0500841 final boolean muteEverything = zenSilence
842 || (zenPriorityOnly && areAllBehaviorSoundsMuted());
John Spurlock25d01ee2015-06-03 12:17:46 -0400843
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700844 for (int usage : AudioAttributes.SDK_USAGES) {
845 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700846 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
847 applyRestrictions(false /*mute*/, usage);
848 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700849 applyRestrictions(muteNotifications || muteEverything, usage);
850 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
851 applyRestrictions(muteCalls || muteEverything, usage);
Beverly04216872017-09-28 10:55:32 -0400852 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
853 applyRestrictions(muteAlarms || muteEverything, usage);
854 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA_SYSTEM_OTHER) {
855 applyRestrictions(muteMediaAndSystemSounds || muteEverything, usage);
Julia Reynolds3fe81be2016-02-03 09:10:06 -0500856 } else {
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700857 applyRestrictions(muteEverything, usage);
Julia Reynolds3fe81be2016-02-03 09:10:06 -0500858 }
859 }
John Spurlock8403b752014-12-10 12:47:01 -0500860 }
John Spurlockae641c92014-06-30 18:11:40 -0400861
Beverlye2d9a232017-11-08 18:14:59 -0500862
Beverly04216872017-09-28 10:55:32 -0400863 @VisibleForTesting
864 protected void applyRestrictions(boolean mute, int usage) {
John Spurlock8403b752014-12-10 12:47:01 -0500865 final String[] exceptionPackages = null; // none (for now)
Beverlye2d9a232017-11-08 18:14:59 -0500866
John Spurlock8403b752014-12-10 12:47:01 -0500867 mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, usage,
868 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
869 exceptionPackages);
870 mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, usage,
871 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
872 exceptionPackages);
John Spurlock056c5192014-04-20 21:52:01 -0400873 }
874
Beverlye2d9a232017-11-08 18:14:59 -0500875 private boolean areAllBehaviorSoundsMuted() {
876 return !mConfig.allowAlarms && !mConfig.allowMediaSystemOther && !mConfig.allowReminders
877 && !mConfig.allowCalls && !mConfig.allowMessages && !mConfig.allowEvents
878 && !mConfig.allowRepeatCallers;
879 }
880
John Spurlock57627792014-12-11 11:29:54 -0500881 private void applyZenToRingerMode() {
John Spurlock661f2cf2014-11-17 10:29:10 -0500882 if (mAudioManager == null) return;
John Spurlock661f2cf2014-11-17 10:29:10 -0500883 // force the ringer mode into compliance
884 final int ringerModeInternal = mAudioManager.getRingerModeInternal();
885 int newRingerModeInternal = ringerModeInternal;
John Spurlock57627792014-12-11 11:29:54 -0500886 switch (mZenMode) {
John Spurlock661f2cf2014-11-17 10:29:10 -0500887 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlock4f1163c2015-04-02 17:41:21 -0400888 case Global.ZEN_MODE_ALARMS:
John Spurlock661f2cf2014-11-17 10:29:10 -0500889 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400890 setPreviousRingerModeSetting(ringerModeInternal);
John Spurlock661f2cf2014-11-17 10:29:10 -0500891 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
John Spurlock8c01d882014-07-28 13:37:13 -0400892 }
John Spurlock661f2cf2014-11-17 10:29:10 -0500893 break;
894 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
895 case Global.ZEN_MODE_OFF:
896 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400897 newRingerModeInternal = getPreviousRingerModeSetting();
898 setPreviousRingerModeSetting(null);
John Spurlock661f2cf2014-11-17 10:29:10 -0500899 }
900 break;
John Spurlock8c01d882014-07-28 13:37:13 -0400901 }
John Spurlock661f2cf2014-11-17 10:29:10 -0500902 if (newRingerModeInternal != -1) {
903 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
904 }
905 }
906
John Spurlock1c923a32014-04-27 16:42:29 -0400907 private void dispatchOnConfigChanged() {
908 for (Callback callback : mCallbacks) {
909 callback.onConfigChanged();
910 }
911 }
912
John Spurlock1fc476d2015-04-14 16:05:20 -0400913 private void dispatchOnPolicyChanged() {
914 for (Callback callback : mCallbacks) {
915 callback.onPolicyChanged();
916 }
917 }
918
John Spurlock1c923a32014-04-27 16:42:29 -0400919 private void dispatchOnZenModeChanged() {
920 for (Callback callback : mCallbacks) {
921 callback.onZenModeChanged();
922 }
923 }
924
John Spurlockb2278d62015-04-07 12:47:12 -0400925 private ZenModeConfig readDefaultConfig(Resources resources) {
926 XmlResourceParser parser = null;
927 try {
928 parser = resources.getXml(R.xml.default_zen_mode_config);
929 while (parser.next() != XmlPullParser.END_DOCUMENT) {
Julia Reynolds206c7e92016-09-15 10:38:03 -0400930 final ZenModeConfig config = ZenModeConfig.readXml(parser);
John Spurlockb2278d62015-04-07 12:47:12 -0400931 if (config != null) return config;
932 }
933 } catch (Exception e) {
934 Log.w(TAG, "Error reading default zen mode config from resource", e);
935 } finally {
936 IoUtils.closeQuietly(parser);
937 }
938 return new ZenModeConfig();
939 }
940
Beverly26eba872017-12-04 16:30:11 -0500941 private void appendDefaultEveryNightRule(ZenModeConfig config) {
John Spurlockb2278d62015-04-07 12:47:12 -0400942 if (config == null) return;
943
944 final ScheduleInfo weeknights = new ScheduleInfo();
Beverly26eba872017-12-04 16:30:11 -0500945 weeknights.days = ZenModeConfig.ALL_DAYS;
John Spurlockb2278d62015-04-07 12:47:12 -0400946 weeknights.startHour = 22;
947 weeknights.endHour = 7;
Beverly30bfbca2017-10-17 14:38:20 -0400948 weeknights.exitAtAlarm = true;
Beverly26eba872017-12-04 16:30:11 -0500949 final ZenRule rule = new ZenRule();
950 rule.enabled = false;
951 rule.name = mDefaultRuleEveryNightName;
952 rule.conditionId = ZenModeConfig.toScheduleConditionId(weeknights);
953 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
954 rule.component = ScheduleConditionProvider.COMPONENT;
955 rule.id = ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID;
956 rule.creationTime = System.currentTimeMillis();
957 config.automaticRules.put(rule.id, rule);
John Spurlockb2278d62015-04-07 12:47:12 -0400958 }
959
John Spurlockcb9aa202015-05-08 17:35:22 -0400960 private void appendDefaultEventRules(ZenModeConfig config) {
961 if (config == null) return;
962
963 final EventInfo events = new EventInfo();
John Spurlock995a7492015-05-28 22:13:03 -0400964 events.calendar = null; // any calendar
John Spurlockcb9aa202015-05-08 17:35:22 -0400965 events.reply = EventInfo.REPLY_YES_OR_MAYBE;
966 final ZenRule rule = new ZenRule();
967 rule.enabled = false;
Beverlyd4f96492017-08-02 13:36:11 -0400968 rule.name = mDefaultRuleEventsName;
John Spurlockcb9aa202015-05-08 17:35:22 -0400969 rule.conditionId = ZenModeConfig.toEventConditionId(events);
Beverlybf16c142017-11-27 16:21:34 -0500970 rule.zenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400971 rule.component = EventConditionProvider.COMPONENT;
Beverly26eba872017-12-04 16:30:11 -0500972 rule.id = ZenModeConfig.EVENTS_DEFAULT_RULE_ID;
Julia Reynolds56106ff2015-09-30 14:42:53 -0400973 rule.creationTime = System.currentTimeMillis();
974 config.automaticRules.put(rule.id, rule);
John Spurlockcb9aa202015-05-08 17:35:22 -0400975 }
976
John Spurlockb2278d62015-04-07 12:47:12 -0400977 private static int zenSeverity(int zen) {
978 switch (zen) {
979 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
980 case Global.ZEN_MODE_ALARMS: return 2;
981 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
982 default: return 0;
983 }
984 }
985
John Spurlockb2278d62015-04-07 12:47:12 -0400986 private final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
987 @Override
988 public String toString() {
989 return TAG;
990 }
991
992 @Override
993 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
994 int ringerModeExternal, VolumePolicy policy) {
995 final boolean isChange = ringerModeOld != ringerModeNew;
996
997 int ringerModeExternalOut = ringerModeNew;
998
999 int newZen = -1;
1000 switch (ringerModeNew) {
1001 case AudioManager.RINGER_MODE_SILENT:
1002 if (isChange && policy.doNotDisturbWhenSilent) {
1003 if (mZenMode != Global.ZEN_MODE_NO_INTERRUPTIONS
1004 && mZenMode != Global.ZEN_MODE_ALARMS) {
John Spurlockb02c7442015-04-14 09:32:25 -04001005 newZen = Global.ZEN_MODE_ALARMS;
John Spurlockb2278d62015-04-07 12:47:12 -04001006 }
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001007 setPreviousRingerModeSetting(ringerModeOld);
John Spurlockb2278d62015-04-07 12:47:12 -04001008 }
1009 break;
1010 case AudioManager.RINGER_MODE_VIBRATE:
1011 case AudioManager.RINGER_MODE_NORMAL:
1012 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
1013 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
1014 || mZenMode == Global.ZEN_MODE_ALARMS)) {
1015 newZen = Global.ZEN_MODE_OFF;
1016 } else if (mZenMode != Global.ZEN_MODE_OFF) {
1017 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
1018 }
1019 break;
1020 }
1021 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001022 setManualZenMode(newZen, null, "ringerModeInternal", null,
1023 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001024 }
1025
1026 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
1027 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
1028 ringerModeExternal, ringerModeExternalOut);
1029 }
1030 return ringerModeExternalOut;
1031 }
1032
1033 @Override
1034 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
1035 int ringerModeInternal, VolumePolicy policy) {
1036 int ringerModeInternalOut = ringerModeNew;
1037 final boolean isChange = ringerModeOld != ringerModeNew;
1038 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
1039
1040 int newZen = -1;
1041 switch (ringerModeNew) {
1042 case AudioManager.RINGER_MODE_SILENT:
1043 if (isChange) {
1044 if (mZenMode == Global.ZEN_MODE_OFF) {
John Spurlock05715ec2015-05-13 11:19:19 -04001045 newZen = Global.ZEN_MODE_ALARMS;
John Spurlockb2278d62015-04-07 12:47:12 -04001046 }
1047 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
John Spurlock05715ec2015-05-13 11:19:19 -04001048 : AudioManager.RINGER_MODE_SILENT;
John Spurlockb2278d62015-04-07 12:47:12 -04001049 } else {
1050 ringerModeInternalOut = ringerModeInternal;
1051 }
1052 break;
1053 case AudioManager.RINGER_MODE_VIBRATE:
1054 case AudioManager.RINGER_MODE_NORMAL:
1055 if (mZenMode != Global.ZEN_MODE_OFF) {
1056 newZen = Global.ZEN_MODE_OFF;
1057 }
1058 break;
1059 }
1060 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001061 setManualZenMode(newZen, null, "ringerModeExternal", caller,
1062 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001063 }
1064
1065 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
1066 ringerModeInternal, ringerModeInternalOut);
1067 return ringerModeInternalOut;
1068 }
John Spurlockd9c75db2015-04-28 11:19:13 -04001069
1070 @Override
1071 public boolean canVolumeDownEnterSilent() {
1072 return mZenMode == Global.ZEN_MODE_OFF;
1073 }
John Spurlock50ced3f2015-05-11 16:00:09 -04001074
1075 @Override
1076 public int getRingerModeAffectedStreams(int streams) {
1077 // ringtone, notification and system streams are always affected by ringer mode
1078 streams |= (1 << AudioSystem.STREAM_RING) |
1079 (1 << AudioSystem.STREAM_NOTIFICATION) |
1080 (1 << AudioSystem.STREAM_SYSTEM);
1081
1082 // alarm and music streams are only affected by ringer mode when in total silence
1083 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
1084 streams |= (1 << AudioSystem.STREAM_ALARM) |
1085 (1 << AudioSystem.STREAM_MUSIC);
1086 } else {
1087 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
1088 (1 << AudioSystem.STREAM_MUSIC));
1089 }
1090 return streams;
1091 }
John Spurlockb2278d62015-04-07 12:47:12 -04001092 }
1093
1094 private final class SettingsObserver extends ContentObserver {
John Spurlock056c5192014-04-20 21:52:01 -04001095 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1096
1097 public SettingsObserver(Handler handler) {
1098 super(handler);
1099 }
1100
1101 public void observe() {
1102 final ContentResolver resolver = mContext.getContentResolver();
1103 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1104 update(null);
1105 }
1106
1107 @Override
1108 public void onChange(boolean selfChange, Uri uri) {
1109 update(uri);
1110 }
1111
1112 public void update(Uri uri) {
1113 if (ZEN_MODE.equals(uri)) {
John Spurlockb2278d62015-04-07 12:47:12 -04001114 if (mZenMode != getZenModeSetting()) {
1115 if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1116 setZenModeSetting(mZenMode);
1117 }
John Spurlock056c5192014-04-20 21:52:01 -04001118 }
1119 }
1120 }
1121
Chris Wren98d235b2015-05-27 18:25:17 -04001122 private final class Metrics extends Callback {
1123 private static final String COUNTER_PREFIX = "dnd_mode_";
1124 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1125
1126 private int mPreviousZenMode = -1;
1127 private long mBeginningMs = 0L;
1128
1129 @Override
1130 void onZenModeChanged() {
1131 emit();
1132 }
1133
1134 private void emit() {
1135 mHandler.postMetricsTimer();
1136 final long now = SystemClock.elapsedRealtime();
1137 final long since = (now - mBeginningMs);
1138 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1139 if (mPreviousZenMode != -1) {
1140 MetricsLogger.count(mContext, COUNTER_PREFIX + mPreviousZenMode, (int) since);
1141 }
1142 mPreviousZenMode = mZenMode;
1143 mBeginningMs = now;
1144 }
1145 }
1146 }
1147
John Spurlockb2278d62015-04-07 12:47:12 -04001148 private final class H extends Handler {
John Spurlock57627792014-12-11 11:29:54 -05001149 private static final int MSG_DISPATCH = 1;
Chris Wren98d235b2015-05-27 18:25:17 -04001150 private static final int MSG_METRICS = 2;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001151 private static final int MSG_APPLY_CONFIG = 4;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001152
1153 private final class ConfigMessageData {
1154 public final ZenModeConfig config;
1155 public final String reason;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001156 public final boolean setRingerMode;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001157
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001158 ConfigMessageData(ZenModeConfig config, String reason, boolean setRingerMode) {
1159 this.config = config;
1160 this.reason = reason;
1161 this.setRingerMode = setRingerMode;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001162 }
1163 }
Chris Wren98d235b2015-05-27 18:25:17 -04001164
1165 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
John Spurlock661f2cf2014-11-17 10:29:10 -05001166
1167 private H(Looper looper) {
1168 super(looper);
John Spurlock056c5192014-04-20 21:52:01 -04001169 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001170
John Spurlock57627792014-12-11 11:29:54 -05001171 private void postDispatchOnZenModeChanged() {
1172 removeMessages(MSG_DISPATCH);
1173 sendEmptyMessage(MSG_DISPATCH);
John Spurlock661f2cf2014-11-17 10:29:10 -05001174 }
1175
Chris Wren98d235b2015-05-27 18:25:17 -04001176 private void postMetricsTimer() {
1177 removeMessages(MSG_METRICS);
1178 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1179 }
1180
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001181 private void postApplyConfig(ZenModeConfig config, String reason, boolean setRingerMode) {
1182 sendMessage(obtainMessage(MSG_APPLY_CONFIG,
1183 new ConfigMessageData(config, reason, setRingerMode)));
1184 }
1185
John Spurlock661f2cf2014-11-17 10:29:10 -05001186 @Override
1187 public void handleMessage(Message msg) {
John Spurlock57627792014-12-11 11:29:54 -05001188 switch (msg.what) {
1189 case MSG_DISPATCH:
1190 dispatchOnZenModeChanged();
John Spurlock661f2cf2014-11-17 10:29:10 -05001191 break;
Chris Wren98d235b2015-05-27 18:25:17 -04001192 case MSG_METRICS:
1193 mMetrics.emit();
1194 break;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001195 case MSG_APPLY_CONFIG:
1196 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1197 applyConfig(applyConfigData.config, applyConfigData.reason,
1198 applyConfigData.setRingerMode);
John Spurlock661f2cf2014-11-17 10:29:10 -05001199 }
1200 }
1201 }
John Spurlock056c5192014-04-20 21:52:01 -04001202
John Spurlock1c923a32014-04-27 16:42:29 -04001203 public static class Callback {
1204 void onConfigChanged() {}
1205 void onZenModeChanged() {}
John Spurlock1fc476d2015-04-14 16:05:20 -04001206 void onPolicyChanged() {}
John Spurlock056c5192014-04-20 21:52:01 -04001207 }
John Spurlockb2278d62015-04-07 12:47:12 -04001208
John Spurlock056c5192014-04-20 21:52:01 -04001209}