blob: afc0b7230e276b39e40808a32f17f813fc4fca6c [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;
Beverly04216872017-09-28 10:55:32 -040099 @VisibleForTesting protected 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;
John Spurlock21258a32015-05-27 18:22:55 -0400107 private 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
John Spurlockb2278d62015-04-07 12:47:12 -0400126 public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
John Spurlock056c5192014-04-20 21:52:01 -0400127 mContext = context;
John Spurlock661f2cf2014-11-17 10:29:10 -0500128 mHandler = new H(looper);
Chris Wren98d235b2015-05-27 18:25:17 -0400129 addCallback(mMetrics);
John Spurlock056c5192014-04-20 21:52:01 -0400130 mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
Beverly3bae4e52018-02-07 12:32:02 -0500131 mNotificationManager = context.getSystemService(NotificationManager.class);
Beverlyd4f96492017-08-02 13:36:11 -0400132
Beverlyf3b92d22018-09-18 15:13:17 -0400133 mDefaultConfig = readDefaultConfig(mContext.getResources());
134 updateDefaultAutomaticRuleNames();
135 mConfig = mDefaultConfig.copy();
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700136 mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
Beverlyd4f96492017-08-02 13:36:11 -0400137
John Spurlock056c5192014-04-20 21:52:01 -0400138 mSettingsObserver = new SettingsObserver(mHandler);
139 mSettingsObserver.observe();
John Spurlockb2278d62015-04-07 12:47:12 -0400140 mFiltering = new ZenModeFiltering(mContext);
141 mConditions = new ZenModeConditions(this, conditionProviders);
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500142 mServiceConfig = conditionProviders.getConfig();
John Spurlock056c5192014-04-20 21:52:01 -0400143 }
144
John Spurlock1b8b22b2015-05-20 09:47:13 -0400145 public Looper getLooper() {
146 return mHandler.getLooper();
147 }
148
John Spurlockb2278d62015-04-07 12:47:12 -0400149 @Override
150 public String toString() {
151 return TAG;
152 }
153
154 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
155 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400156 synchronized (mConfig) {
Beverlyff2df9b2018-10-10 16:54:10 -0400157 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConsolidatedPolicy,
158 userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400159 }
John Spurlockb2278d62015-04-07 12:47:12 -0400160 }
161
162 public boolean isCall(NotificationRecord record) {
163 return mFiltering.isCall(record);
164 }
165
Julia Reynoldsc6b371b2016-06-14 08:31:03 -0400166 public void recordCaller(NotificationRecord record) {
167 mFiltering.recordCall(record);
168 }
169
John Spurlockb2278d62015-04-07 12:47:12 -0400170 public boolean shouldIntercept(NotificationRecord record) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400171 synchronized (mConfig) {
Beverlyff2df9b2018-10-10 16:54:10 -0400172 return mFiltering.shouldIntercept(mZenMode, mConsolidatedPolicy, record);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400173 }
John Spurlock056c5192014-04-20 21:52:01 -0400174 }
175
John Spurlock1c923a32014-04-27 16:42:29 -0400176 public void addCallback(Callback callback) {
177 mCallbacks.add(callback);
John Spurlock056c5192014-04-20 21:52:01 -0400178 }
179
John Spurlock530052a2014-11-30 16:26:19 -0500180 public void removeCallback(Callback callback) {
181 mCallbacks.remove(callback);
182 }
183
John Spurlockb2278d62015-04-07 12:47:12 -0400184 public void initZenMode() {
185 if (DEBUG) Log.d(TAG, "initZenMode");
186 evaluateZenMode("init", true /*setRingerMode*/);
187 }
188
John Spurlock661f2cf2014-11-17 10:29:10 -0500189 public void onSystemReady() {
John Spurlockb2278d62015-04-07 12:47:12 -0400190 if (DEBUG) Log.d(TAG, "onSystemReady");
John Spurlock661f2cf2014-11-17 10:29:10 -0500191 mAudioManager = LocalServices.getService(AudioManagerInternal.class);
192 if (mAudioManager != null) {
John Spurlockb2278d62015-04-07 12:47:12 -0400193 mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
John Spurlock661f2cf2014-11-17 10:29:10 -0500194 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500195 mPm = mContext.getPackageManager();
Chris Wren98d235b2015-05-27 18:25:17 -0400196 mHandler.postMetricsTimer();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500197 cleanUpZenRules();
Julia Reynolds8ac63032015-08-31 15:19:43 -0400198 evaluateZenMode("onSystemReady", true);
Beverly3bae4e52018-02-07 12:32:02 -0500199 mIsBootComplete = true;
200 showZenUpgradeNotification(mZenMode);
John Spurlockae641c92014-06-30 18:11:40 -0400201 }
202
John Spurlock21258a32015-05-27 18:22:55 -0400203 public void onUserSwitched(int user) {
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500204 loadConfigForUser(user, "onUserSwitched");
John Spurlock21258a32015-05-27 18:22:55 -0400205 }
206
207 public void onUserRemoved(int user) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700208 if (user < UserHandle.USER_SYSTEM) return;
John Spurlock21258a32015-05-27 18:22:55 -0400209 if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
210 mConfigs.remove(user);
211 }
212
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500213 public void onUserUnlocked(int user) {
214 loadConfigForUser(user, "onUserUnlocked");
215 }
216
217 private void loadConfigForUser(int user, String reason) {
218 if (mUser == user || user < UserHandle.USER_SYSTEM) return;
219 mUser = user;
220 if (DEBUG) Log.d(TAG, reason + " u=" + user);
221 ZenModeConfig config = mConfigs.get(user);
222 if (config == null) {
223 if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user);
224 config = mDefaultConfig.copy();
225 config.user = user;
226 }
227 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400228 setConfigLocked(config, null, reason);
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500229 }
230 cleanUpZenRules();
231 }
232
Christoph Studer85a384b2014-08-27 20:16:15 +0200233 public int getZenModeListenerInterruptionFilter() {
John Spurlock80774932015-05-07 17:38:50 -0400234 return NotificationManager.zenModeToInterruptionFilter(mZenMode);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400235 }
236
John Spurlock80774932015-05-07 17:38:50 -0400237 public void requestFromListener(ComponentName name, int filter) {
238 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400239 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400240 setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
John Spurlockb2278d62015-04-07 12:47:12 -0400241 "listener:" + (name != null ? name.flattenToShortString() : null));
John Spurlockd8afe3c2014-08-01 14:04:07 -0400242 }
243 }
244
Bryce Lee7219ada2016-04-08 10:54:23 -0700245 public void setSuppressedEffects(long suppressedEffects) {
246 if (mSuppressedEffects == suppressedEffects) return;
247 mSuppressedEffects = suppressedEffects;
John Spurlock8403b752014-12-10 12:47:01 -0500248 applyRestrictions();
249 }
250
Bryce Lee7219ada2016-04-08 10:54:23 -0700251 public long getSuppressedEffects() {
252 return mSuppressedEffects;
253 }
254
John Spurlock1c923a32014-04-27 16:42:29 -0400255 public int getZenMode() {
256 return mZenMode;
257 }
258
Julia Reynolds361e82d32016-02-26 18:19:49 -0500259 public List<ZenRule> getZenRules() {
260 List<ZenRule> rules = new ArrayList<>();
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400261 synchronized (mConfig) {
262 if (mConfig == null) return rules;
263 for (ZenRule rule : mConfig.automaticRules.values()) {
264 if (canManageAutomaticZenRule(rule)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500265 rules.add(rule);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400266 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400267 }
268 }
269 return rules;
270 }
271
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400272 public AutomaticZenRule getAutomaticZenRule(String id) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400273 ZenRule rule;
274 synchronized (mConfig) {
275 if (mConfig == null) return null;
276 rule = mConfig.automaticRules.get(id);
277 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400278 if (rule == null) return null;
279 if (canManageAutomaticZenRule(rule)) {
280 return createAutomaticZenRule(rule);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400281 }
282 return null;
283 }
284
Julia Reynolds361e82d32016-02-26 18:19:49 -0500285 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500286 if (!isSystemRule(automaticZenRule)) {
Julia Reynolds68062072018-08-06 15:38:21 -0400287 PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
288 if (component == null) {
289 component = getActivityInfo(automaticZenRule.getConfigurationActivity());
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500290 }
Julia Reynolds68062072018-08-06 15:38:21 -0400291 if (component == null) {
292 throw new IllegalArgumentException("Lacking enabled CPS or config activity");
293 }
Julia Reynolds7f2f4412016-03-01 12:33:48 -0500294 int ruleInstanceLimit = -1;
Julia Reynolds68062072018-08-06 15:38:21 -0400295 if (component.metaData != null) {
296 ruleInstanceLimit = component.metaData.getInt(
Julia Reynolds7f2f4412016-03-01 12:33:48 -0500297 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
298 }
Julia Reynolds68062072018-08-06 15:38:21 -0400299 int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
300 + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
301 + 1;
302 if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500303 throw new IllegalArgumentException("Rule instance limit exceeded");
304 }
Julia Reynolds68062072018-08-06 15:38:21 -0400305
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500306 }
307
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400308 ZenModeConfig newConfig;
309 synchronized (mConfig) {
Julia Reynolds87c42772016-05-16 09:52:17 -0400310 if (mConfig == null) {
311 throw new AndroidRuntimeException("Could not create rule");
312 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400313 if (DEBUG) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500314 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400315 }
316 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500317 ZenRule rule = new ZenRule();
318 populateZenRule(automaticZenRule, rule, true);
Beverlya0d07ab2018-11-28 16:49:23 -0500319 newConfig.automaticRules.put(rule.id, rule);
Julia Reynolds8f056002018-07-13 15:12:29 -0400320 if (setConfigLocked(newConfig, reason, rule.component, true)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500321 return rule.id;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500322 } else {
Julia Reynolds87c42772016-05-16 09:52:17 -0400323 throw new AndroidRuntimeException("Could not create rule");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500324 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400325 }
326 }
327
Julia Reynolds361e82d32016-02-26 18:19:49 -0500328 public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
329 String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400330 ZenModeConfig newConfig;
331 synchronized (mConfig) {
332 if (mConfig == null) return false;
333 if (DEBUG) {
334 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule
335 + " reason=" + reason);
336 }
337 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500338 ZenModeConfig.ZenRule rule;
339 if (ruleId == null) {
340 throw new IllegalArgumentException("Rule doesn't exist");
341 } else {
342 rule = newConfig.automaticRules.get(ruleId);
343 if (rule == null || !canManageAutomaticZenRule(rule)) {
344 throw new SecurityException(
345 "Cannot update rules not owned by your condition provider");
346 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400347 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500348 populateZenRule(automaticZenRule, rule, false);
Julia Reynolds8f056002018-07-13 15:12:29 -0400349 return setConfigLocked(newConfig, reason, rule.component, true);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400350 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400351 }
352
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400353 public boolean removeAutomaticZenRule(String id, String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400354 ZenModeConfig newConfig;
355 synchronized (mConfig) {
356 if (mConfig == null) return false;
357 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500358 ZenRule rule = newConfig.automaticRules.get(id);
359 if (rule == null) return false;
360 if (canManageAutomaticZenRule(rule)) {
361 newConfig.automaticRules.remove(id);
362 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
363 } else {
364 throw new SecurityException(
365 "Cannot delete rules not owned by your condition provider");
366 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400367 return setConfigLocked(newConfig, reason, null, true);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400368 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400369 }
370
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500371 public boolean removeAutomaticZenRules(String packageName, String reason) {
372 ZenModeConfig newConfig;
373 synchronized (mConfig) {
374 if (mConfig == null) return false;
375 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500376 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
377 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
Julia Reynolds10e663b2019-01-07 10:15:12 -0500378 if (rule.pkg.equals(packageName) && canManageAutomaticZenRule(rule)) {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500379 newConfig.automaticRules.removeAt(i);
380 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500381 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400382 return setConfigLocked(newConfig, reason, null, true);
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500383 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500384 }
385
Julia Reynolds68062072018-08-06 15:38:21 -0400386 public void setAutomaticZenRuleState(String id, Condition condition) {
387 ZenModeConfig newConfig;
388 synchronized (mConfig) {
389 if (mConfig == null) return;
390
391 newConfig = mConfig.copy();
392 }
393 setAutomaticZenRuleState(newConfig, newConfig.automaticRules.get(id), condition);
394 }
395
396 public void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition) {
397 ZenModeConfig newConfig;
398 synchronized (mConfig) {
399 if (mConfig == null) return;
400 newConfig = mConfig.copy();
401 }
402
403 setAutomaticZenRuleState(newConfig,
404 findMatchingRule(newConfig, ruleDefinition, condition),
405 condition);
406 }
407
408 private void setAutomaticZenRuleState(ZenModeConfig config, ZenRule rule, Condition condition) {
409 if (rule == null) return;
410
411 rule.condition = condition;
412 updateSnoozing(rule);
413 setConfigLocked(config, rule.component, "conditionChanged");
414 }
415
416 private ZenRule findMatchingRule(ZenModeConfig config, Uri id, Condition condition) {
417 if (ruleMatches(id, condition, config.manualRule)) {
418 return config.manualRule;
419 } else {
420 for (ZenRule automaticRule : config.automaticRules.values()) {
421 if (ruleMatches(id, condition, automaticRule)) {
422 return automaticRule;
423 }
424 }
425 }
426 return null;
427 }
428
429 private boolean ruleMatches(Uri id, Condition condition, ZenRule rule) {
430 if (id == null || rule == null || rule.conditionId == null) return false;
431 if (!rule.conditionId.equals(id)) return false;
432 if (Objects.equals(condition, rule.condition)) return false;
433 return true;
434 }
435
436 private boolean updateSnoozing(ZenRule rule) {
437 if (rule != null && rule.snoozing && !rule.isTrueOrUnknown()) {
438 rule.snoozing = false;
439 if (DEBUG) Log.d(TAG, "Snoozing reset for " + rule.conditionId);
440 return true;
441 }
442 return false;
443 }
444
445 public int getCurrentInstanceCount(ComponentName cn) {
446 if (cn == null) {
447 return 0;
448 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500449 int count = 0;
450 synchronized (mConfig) {
451 for (ZenRule rule : mConfig.automaticRules.values()) {
Julia Reynolds68062072018-08-06 15:38:21 -0400452 if (cn.equals(rule.component) || cn.equals(rule.configurationActivity)) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500453 count++;
454 }
455 }
456 }
457 return count;
458 }
459
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400460 public boolean canManageAutomaticZenRule(ZenRule rule) {
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500461 final int callingUid = Binder.getCallingUid();
462 if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
463 return true;
464 } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400465 == PackageManager.PERMISSION_GRANTED) {
466 return true;
467 } else {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500468 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400469 if (packages != null) {
470 final int packageCount = packages.length;
471 for (int i = 0; i < packageCount; i++) {
Julia Reynolds68062072018-08-06 15:38:21 -0400472 if (packages[i].equals(rule.pkg)) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400473 return true;
474 }
475 }
476 }
477 return false;
478 }
479 }
480
Beverlyd4f96492017-08-02 13:36:11 -0400481 protected void updateDefaultZenRules() {
Beverlyf3b92d22018-09-18 15:13:17 -0400482 updateDefaultAutomaticRuleNames();
483 for (ZenRule defaultRule : mDefaultConfig.automaticRules.values()) {
484 ZenRule currRule = mConfig.automaticRules.get(defaultRule.id);
Beverly49ba9a62018-11-02 13:19:31 -0400485 // if default rule wasn't user-modified nor enabled, use localized name
486 // instead of previous system name
487 if (currRule != null && !currRule.modified && !currRule.enabled
488 && !defaultRule.name.equals(currRule.name)) {
489 if (canManageAutomaticZenRule(currRule)) {
Beverlyd4f96492017-08-02 13:36:11 -0400490 if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name "
Beverlyf3b92d22018-09-18 15:13:17 -0400491 + "from " + currRule.name + " to " + defaultRule.name);
Beverlyd4f96492017-08-02 13:36:11 -0400492 // update default rule (if locale changed, name of rule will change)
Beverly49ba9a62018-11-02 13:19:31 -0400493 currRule.name = defaultRule.name;
494 updateAutomaticZenRule(defaultRule.id, createAutomaticZenRule(currRule),
Beverlyd4f96492017-08-02 13:36:11 -0400495 "locale changed");
496 }
497 }
498 }
499 }
500
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500501 private boolean isSystemRule(AutomaticZenRule rule) {
Julia Reynolds68062072018-08-06 15:38:21 -0400502 return rule.getOwner() != null
503 && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500504 }
505
506 private ServiceInfo getServiceInfo(ComponentName owner) {
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500507 Intent queryIntent = new Intent();
508 queryIntent.setComponent(owner);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500509 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500510 queryIntent,
511 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
512 UserHandle.getCallingUserId());
513 if (installedServices != null) {
514 for (int i = 0, count = installedServices.size(); i < count; i++) {
515 ResolveInfo resolveInfo = installedServices.get(i);
516 ServiceInfo info = resolveInfo.serviceInfo;
517 if (mServiceConfig.bindPermission.equals(info.permission)) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500518 return info;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500519 }
520 }
521 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500522 return null;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500523 }
524
Julia Reynolds68062072018-08-06 15:38:21 -0400525 private ActivityInfo getActivityInfo(ComponentName configActivity) {
526 Intent queryIntent = new Intent();
527 queryIntent.setComponent(configActivity);
528 List<ResolveInfo> installedComponents = mPm.queryIntentActivitiesAsUser(
529 queryIntent,
530 PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA,
531 UserHandle.getCallingUserId());
532 if (installedComponents != null) {
533 for (int i = 0, count = installedComponents.size(); i < count; i++) {
534 ResolveInfo resolveInfo = installedComponents.get(i);
535 return resolveInfo.activityInfo;
536 }
537 }
538 return null;
539 }
540
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400541 private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
542 if (isNew) {
543 rule.id = ZenModeConfig.newRuleId();
544 rule.creationTime = System.currentTimeMillis();
545 rule.component = automaticZenRule.getOwner();
Julia Reynolds68062072018-08-06 15:38:21 -0400546 rule.configurationActivity = automaticZenRule.getConfigurationActivity();
547 rule.pkg = (rule.component != null)
548 ? rule.component.getPackageName()
549 : rule.configurationActivity.getPackageName();
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400550 }
551
552 if (rule.enabled != automaticZenRule.isEnabled()) {
553 rule.snoozing = false;
554 }
555 rule.name = automaticZenRule.getName();
556 rule.condition = null;
557 rule.conditionId = automaticZenRule.getConditionId();
558 rule.enabled = automaticZenRule.isEnabled();
Beverly49ba9a62018-11-02 13:19:31 -0400559 rule.modified = automaticZenRule.isModified();
Beverly12196702018-12-12 15:05:51 -0500560 rule.zenPolicy = automaticZenRule.getZenPolicy();
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400561 rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
562 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
563 }
564
Beverlyd4f96492017-08-02 13:36:11 -0400565 protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
Julia Reynolds68062072018-08-06 15:38:21 -0400566 return new AutomaticZenRule(rule.name, rule.component, rule.configurationActivity,
567 rule.conditionId, rule.zenPolicy,
568 NotificationManager.zenModeToInterruptionFilter(rule.zenMode),
569 rule.enabled, rule.creationTime);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400570 }
571
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400572 public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
573 setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
Beverly91d0a632018-07-02 16:45:00 -0400574 Settings.Secure.putInt(mContext.getContentResolver(),
575 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0);
John Spurlocke77bb362014-04-26 10:24:59 -0400576 }
577
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400578 private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
John Spurlockb2278d62015-04-07 12:47:12 -0400579 boolean setRingerMode) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400580 ZenModeConfig newConfig;
581 synchronized (mConfig) {
582 if (mConfig == null) return;
583 if (!Global.isValidZenMode(zenMode)) return;
584 if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode)
585 + " conditionId=" + conditionId + " reason=" + reason
586 + " setRingerMode=" + setRingerMode);
587 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500588 if (zenMode == Global.ZEN_MODE_OFF) {
589 newConfig.manualRule = null;
590 for (ZenRule automaticRule : newConfig.automaticRules.values()) {
591 if (automaticRule.isAutomaticActive()) {
592 automaticRule.snoozing = true;
593 }
John Spurlockb2278d62015-04-07 12:47:12 -0400594 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500595 } else {
596 final ZenRule newRule = new ZenRule();
597 newRule.enabled = true;
598 newRule.zenMode = zenMode;
599 newRule.conditionId = conditionId;
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400600 newRule.enabler = caller;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500601 newConfig.manualRule = newRule;
John Spurlockb2278d62015-04-07 12:47:12 -0400602 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400603 setConfigLocked(newConfig, reason, null, setRingerMode);
John Spurlockb2278d62015-04-07 12:47:12 -0400604 }
John Spurlockb2278d62015-04-07 12:47:12 -0400605 }
606
Julia Reynolds520df6e2017-02-13 09:05:10 -0500607 void dump(ProtoOutputStream proto) {
Julia Reynolds520df6e2017-02-13 09:05:10 -0500608 proto.write(ZenModeProto.ZEN_MODE, mZenMode);
609 synchronized (mConfig) {
610 if (mConfig.manualRule != null) {
Kweku Adams99546332018-01-24 17:03:50 -0800611 mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500612 }
613 for (ZenRule rule : mConfig.automaticRules.values()) {
614 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
615 && !rule.snoozing) {
Kweku Adams99546332018-01-24 17:03:50 -0800616 rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500617 }
618 }
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800619 mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500620 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
621 }
622 }
623
John Spurlockb2278d62015-04-07 12:47:12 -0400624 public void dump(PrintWriter pw, String prefix) {
625 pw.print(prefix); pw.print("mZenMode=");
626 pw.println(Global.zenModeToString(mZenMode));
Beverlyff2df9b2018-10-10 16:54:10 -0400627 pw.print("mConsolidatedPolicy=" + mConsolidatedPolicy.toString());
John Spurlock21258a32015-05-27 18:22:55 -0400628 final int N = mConfigs.size();
629 for (int i = 0; i < N; i++) {
630 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
631 }
632 pw.print(prefix); pw.print("mUser="); pw.println(mUser);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400633 synchronized (mConfig) {
634 dump(pw, prefix, "mConfig", mConfig);
635 }
Bryce Lee7219ada2016-04-08 10:54:23 -0700636
637 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
John Spurlock1d7d2242015-04-10 08:10:22 -0400638 mFiltering.dump(pw, prefix);
John Spurlockb2278d62015-04-07 12:47:12 -0400639 mConditions.dump(pw, prefix);
640 }
641
642 private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) {
643 pw.print(prefix); pw.print(var); pw.print('=');
644 if (config == null) {
645 pw.println(config);
646 return;
647 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500648 pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
Julia Reynolds1f580572018-04-27 14:48:36 -0400649 + "messages=%b,messagesFrom=%s,events=%b,reminders=%b)\n",
Beverlyd6964762018-02-16 14:07:03 -0500650 config.allowAlarms, config.allowMedia, config.allowSystem,
Julia Reynolds6ee26172015-09-28 11:34:48 -0400651 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
652 config.allowRepeatCallers, config.allowMessages,
653 ZenModeConfig.sourceToString(config.allowMessagesFrom),
Julia Reynolds1f580572018-04-27 14:48:36 -0400654 config.allowEvents, config.allowReminders);
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500655 pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
John Spurlockb2278d62015-04-07 12:47:12 -0400656 pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule);
657 if (config.automaticRules.isEmpty()) return;
658 final int N = config.automaticRules.size();
659 for (int i = 0; i < N; i++) {
660 pw.print(prefix); pw.print(i == 0 ? " automaticRules=" : " ");
661 pw.println(config.automaticRules.valueAt(i));
662 }
663 }
664
John Spurlock35ef0a62015-05-28 11:24:10 -0400665 public void readXml(XmlPullParser parser, boolean forRestore)
666 throws XmlPullParserException, IOException {
Beverly4e2f76c2018-03-16 15:43:49 -0400667 ZenModeConfig config = ZenModeConfig.readXml(parser);
668 String reason = "readXml";
669
John Spurlockb2278d62015-04-07 12:47:12 -0400670 if (config != null) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400671 if (forRestore) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700672 //TODO: http://b/22388012
673 if (config.user != UserHandle.USER_SYSTEM) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400674 return;
675 }
676 config.manualRule = null; // don't restore the manual rule
Beverly4e2f76c2018-03-16 15:43:49 -0400677 }
678
Beverlyad3841a2018-07-31 11:23:35 -0400679 // booleans to determine whether to reset the rules to the default rules
680 boolean allRulesDisabled = true;
681 boolean hasDefaultRules = config.automaticRules.containsAll(
682 ZenModeConfig.DEFAULT_RULE_IDS);
683
Beverly4e2f76c2018-03-16 15:43:49 -0400684 long time = System.currentTimeMillis();
685 if (config.automaticRules != null && config.automaticRules.size() > 0) {
686 for (ZenRule automaticRule : config.automaticRules.values()) {
687 if (forRestore) {
John Spurlock995a7492015-05-28 22:13:03 -0400688 // don't restore transient state from restored automatic rules
689 automaticRule.snoozing = false;
690 automaticRule.condition = null;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500691 automaticRule.creationTime = time;
John Spurlock995a7492015-05-28 22:13:03 -0400692 }
Beverlyad3841a2018-07-31 11:23:35 -0400693
694 allRulesDisabled &= !automaticRule.enabled;
John Spurlock995a7492015-05-28 22:13:03 -0400695 }
John Spurlock35ef0a62015-05-28 11:24:10 -0400696 }
Beverly4e2f76c2018-03-16 15:43:49 -0400697
Beverlyad3841a2018-07-31 11:23:35 -0400698 if (!hasDefaultRules && allRulesDisabled
699 && (forRestore || config.version < ZenModeConfig.XML_VERSION)) {
700 // reset zen automatic rules to default on restore or upgrade if:
701 // - doesn't already have default rules and
702 // - all previous automatic rules were disabled
703 config.automaticRules = new ArrayMap<>();
Beverlyf3b92d22018-09-18 15:13:17 -0400704 for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
705 config.automaticRules.put(rule.id, rule);
706 }
Beverlyad3841a2018-07-31 11:23:35 -0400707 reason += ", reset to default rules";
708 }
709
710 if (config.version < ZenModeConfig.XML_VERSION) {
Beverly91d0a632018-07-02 16:45:00 -0400711 Settings.Secure.putInt(mContext.getContentResolver(),
712 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1);
Beverly301e92a2018-04-27 09:43:05 -0400713 } else {
714 // devices not restoring/upgrading already have updated zen settings
Beverly91d0a632018-07-02 16:45:00 -0400715 Settings.Secure.putInt(mContext.getContentResolver(),
716 Settings.Secure.ZEN_SETTINGS_UPDATED, 1);
Beverly4e2f76c2018-03-16 15:43:49 -0400717 }
718 if (DEBUG) Log.d(TAG, reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500719 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400720 setConfigLocked(config, null, reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500721 }
John Spurlockb2278d62015-04-07 12:47:12 -0400722 }
723 }
724
Beverly4e2f76c2018-03-16 15:43:49 -0400725 public void writeXml(XmlSerializer out, boolean forBackup, Integer version) throws IOException {
John Spurlock21258a32015-05-27 18:22:55 -0400726 final int N = mConfigs.size();
727 for (int i = 0; i < N; i++) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700728 //TODO: http://b/22388012
729 if (forBackup && mConfigs.keyAt(i) != UserHandle.USER_SYSTEM) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400730 continue;
731 }
Beverly4e2f76c2018-03-16 15:43:49 -0400732 mConfigs.valueAt(i).writeXml(out, version);
John Spurlock21258a32015-05-27 18:22:55 -0400733 }
John Spurlockb2278d62015-04-07 12:47:12 -0400734 }
735
Beverly174d7412018-08-22 16:34:41 -0400736 /**
737 * @return user-specified default notification policy for priority only do not disturb
738 */
John Spurlock1fc476d2015-04-14 16:05:20 -0400739 public Policy getNotificationPolicy() {
740 return getNotificationPolicy(mConfig);
741 }
742
743 private static Policy getNotificationPolicy(ZenModeConfig config) {
744 return config == null ? null : config.toNotificationPolicy();
745 }
746
Beverly174d7412018-08-22 16:34:41 -0400747 /**
748 * Sets the global notification policy used for priority only do not disturb
749 */
John Spurlock1fc476d2015-04-14 16:05:20 -0400750 public void setNotificationPolicy(Policy policy) {
751 if (policy == null || mConfig == null) return;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500752 synchronized (mConfig) {
753 final ZenModeConfig newConfig = mConfig.copy();
754 newConfig.applyNotificationPolicy(policy);
Julia Reynolds8f056002018-07-13 15:12:29 -0400755 setConfigLocked(newConfig, null, "setNotificationPolicy");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500756 }
John Spurlock1fc476d2015-04-14 16:05:20 -0400757 }
758
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500759 /**
760 * Removes old rule instances whose owner is not installed.
761 */
762 private void cleanUpZenRules() {
763 long currentTime = System.currentTimeMillis();
764 synchronized (mConfig) {
765 final ZenModeConfig newConfig = mConfig.copy();
766 if (newConfig.automaticRules != null) {
767 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
768 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
769 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
770 try {
Julia Reynolds68062072018-08-06 15:38:21 -0400771 if (rule.pkg != null) {
772 mPm.getPackageInfo(rule.pkg, PackageManager.MATCH_ANY_USER);
773 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500774 } catch (PackageManager.NameNotFoundException e) {
775 newConfig.automaticRules.removeAt(i);
776 }
777 }
778 }
779 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400780 setConfigLocked(newConfig, null, "cleanUpZenRules");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500781 }
782 }
783
784 /**
785 * @return a copy of the zen mode configuration
786 */
John Spurlockb2278d62015-04-07 12:47:12 -0400787 public ZenModeConfig getConfig() {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400788 synchronized (mConfig) {
789 return mConfig.copy();
790 }
John Spurlockb2278d62015-04-07 12:47:12 -0400791 }
792
Beverlyff2df9b2018-10-10 16:54:10 -0400793 /**
794 * @return a copy of the zen mode consolidated policy
795 */
796 public Policy getConsolidatedNotificationPolicy() {
797 if (mConsolidatedPolicy == null) {
798 return null;
799 }
800 return mConsolidatedPolicy.copy();
801 }
802
Julia Reynolds8f056002018-07-13 15:12:29 -0400803 public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
804 String reason) {
805 return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -0400806 }
807
Julia Reynolds8f056002018-07-13 15:12:29 -0400808 public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) {
Julia Reynolds89aeab02016-09-15 11:07:50 -0400809 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400810 setConfigLocked(config, triggeringComponent, reason);
Julia Reynolds89aeab02016-09-15 11:07:50 -0400811 }
Eric Laurente0ced4d2015-09-30 17:44:28 -0700812 }
813
Julia Reynolds8f056002018-07-13 15:12:29 -0400814 private boolean setConfigLocked(ZenModeConfig config, String reason,
815 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400816 final long identity = Binder.clearCallingIdentity();
817 try {
818 if (config == null || !config.isValid()) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500819 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400820 return false;
821 }
822 if (config.user != mUser) {
823 // simply store away for background users
824 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500825 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400826 return true;
827 }
Julia Reynolds68062072018-08-06 15:38:21 -0400828 // handle CPS backed conditions - danger! may modify config
Julia Reynolds8f056002018-07-13 15:12:29 -0400829 mConditions.evaluateConfig(config, null, false /*processSubscriptions*/);
Julia Reynolds68062072018-08-06 15:38:21 -0400830
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500831 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500832 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500833 ZenLog.traceConfig(reason, mConfig, config);
Julia Reynolds68062072018-08-06 15:38:21 -0400834
835 // send some broadcasts
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500836 final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
837 getNotificationPolicy(config));
Julia Reynolds9a25da12016-01-06 16:19:28 -0500838 if (!config.equals(mConfig)) {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500839 dispatchOnConfigChanged();
Beverlyff2df9b2018-10-10 16:54:10 -0400840 updateConsolidatedPolicy(reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500841 }
842 if (policyChanged) {
843 dispatchOnPolicyChanged();
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400844 }
Julia Reynolds9a25da12016-01-06 16:19:28 -0500845 mConfig = config;
Julia Reynolds8f056002018-07-13 15:12:29 -0400846 mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode);
John Spurlock21258a32015-05-27 18:22:55 -0400847 return true;
Julia Reynoldscb507b82017-09-07 13:53:40 -0400848 } catch (SecurityException e) {
849 Log.wtf(TAG, "Invalid rule in config", e);
850 return false;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400851 } finally {
852 Binder.restoreCallingIdentity(identity);
John Spurlock21258a32015-05-27 18:22:55 -0400853 }
John Spurlockb2278d62015-04-07 12:47:12 -0400854 }
855
Julia Reynolds8f056002018-07-13 15:12:29 -0400856 private void applyConfig(ZenModeConfig config, String reason,
857 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400858 final String val = Integer.toString(config.hashCode());
859 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
Beverly174d7412018-08-22 16:34:41 -0400860 evaluateZenMode(reason, setRingerMode);
Julia Reynolds8f056002018-07-13 15:12:29 -0400861 mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400862 }
863
John Spurlockb2278d62015-04-07 12:47:12 -0400864 private int getZenModeSetting() {
865 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
866 }
867
Beverly3bae4e52018-02-07 12:32:02 -0500868 @VisibleForTesting
869 protected void setZenModeSetting(int zen) {
John Spurlockb2278d62015-04-07 12:47:12 -0400870 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
Beverly3bae4e52018-02-07 12:32:02 -0500871 showZenUpgradeNotification(zen);
John Spurlockb2278d62015-04-07 12:47:12 -0400872 }
873
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400874 private int getPreviousRingerModeSetting() {
875 return Global.getInt(mContext.getContentResolver(),
876 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
877 }
878
879 private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
880 Global.putString(
881 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
882 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
883 }
884
Beverlye4ee1cc2018-03-06 17:21:08 -0500885 @VisibleForTesting
Beverly174d7412018-08-22 16:34:41 -0400886 protected void evaluateZenMode(String reason, boolean setRingerMode) {
John Spurlockb2278d62015-04-07 12:47:12 -0400887 if (DEBUG) Log.d(TAG, "evaluateZenMode");
Beverlyff2df9b2018-10-10 16:54:10 -0400888 if (mConfig == null) return;
889 final int policyHashBefore = mConsolidatedPolicy == null ? 0
890 : mConsolidatedPolicy.hashCode();
Jason Monka9927322015-12-13 16:22:37 -0500891 final int zenBefore = mZenMode;
Julia Reynolds8ac63032015-08-31 15:19:43 -0400892 final int zen = computeZenMode();
John Spurlockb2278d62015-04-07 12:47:12 -0400893 ZenLog.traceSetZenMode(zen, reason);
894 mZenMode = zen;
895 setZenModeSetting(mZenMode);
Beverlyff2df9b2018-10-10 16:54:10 -0400896 updateConsolidatedPolicy(reason);
Beverlyd6964762018-02-16 14:07:03 -0500897 updateRingerModeAffectedStreams();
Beverlyff2df9b2018-10-10 16:54:10 -0400898 if (setRingerMode && (zen != zenBefore || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
899 && policyHashBefore != mConsolidatedPolicy.hashCode()))) {
John Spurlock57627792014-12-11 11:29:54 -0500900 applyZenToRingerMode();
901 }
902 applyRestrictions();
Jason Monka9927322015-12-13 16:22:37 -0500903 if (zen != zenBefore) {
Julia Reynolds8ac63032015-08-31 15:19:43 -0400904 mHandler.postDispatchOnZenModeChanged();
905 }
John Spurlock57627792014-12-11 11:29:54 -0500906 }
907
John Spurlock50ced3f2015-05-11 16:00:09 -0400908 private void updateRingerModeAffectedStreams() {
909 if (mAudioManager != null) {
910 mAudioManager.updateRingerModeAffectedStreamsInternal();
911 }
912 }
913
Julia Reynolds8ac63032015-08-31 15:19:43 -0400914 private int computeZenMode() {
Beverlye4ee1cc2018-03-06 17:21:08 -0500915 if (mConfig == null) return Global.ZEN_MODE_OFF;
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400916 synchronized (mConfig) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400917 if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
918 int zen = Global.ZEN_MODE_OFF;
919 for (ZenRule automaticRule : mConfig.automaticRules.values()) {
920 if (automaticRule.isAutomaticActive()) {
921 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
Beverly301e92a2018-04-27 09:43:05 -0400922 // automatic rule triggered dnd and user hasn't seen update dnd dialog
Beverly91d0a632018-07-02 16:45:00 -0400923 if (Settings.Secure.getInt(mContext.getContentResolver(),
924 Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
925 Settings.Secure.putInt(mContext.getContentResolver(),
926 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
Beverly301e92a2018-04-27 09:43:05 -0400927 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400928 zen = automaticRule.zenMode;
929 }
John Spurlockb2278d62015-04-07 12:47:12 -0400930 }
931 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400932 return zen;
John Spurlockb2278d62015-04-07 12:47:12 -0400933 }
John Spurlock8403b752014-12-10 12:47:01 -0500934 }
935
Beverlyff2df9b2018-10-10 16:54:10 -0400936 private void updateConsolidatedPolicy(String reason) {
937 if (mConfig == null) return;
938 synchronized (mConfig) {
939 ZenPolicy policy = new ZenPolicy();
940 for (ZenRule automaticRule : mConfig.automaticRules.values()) {
941 if (automaticRule.isAutomaticActive()) {
942 policy.apply(automaticRule.zenPolicy);
943 }
944 }
945 Policy newPolicy = mConfig.toNotificationPolicy(policy);
946 if (!Objects.equals(mConsolidatedPolicy, newPolicy)) {
947 mConsolidatedPolicy = newPolicy;
948 dispatchOnConsolidatedPolicyChanged();
949 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason);
950 }
951 }
952 }
953
Beverlyf3b92d22018-09-18 15:13:17 -0400954 private void updateDefaultAutomaticRuleNames() {
955 for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
956 if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) {
957 rule.name = mContext.getResources()
958 .getString(R.string.zen_mode_default_events_name);
959 } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) {
960 rule.name = mContext.getResources()
961 .getString(R.string.zen_mode_default_every_night_name);
962 }
963 }
Beverly30bfbca2017-10-17 14:38:20 -0400964 }
965
Beverly04216872017-09-28 10:55:32 -0400966 @VisibleForTesting
967 protected void applyRestrictions() {
Beverlyd820bc22018-01-11 15:28:33 -0500968 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
Beverly925cde82018-01-23 09:31:23 -0500969 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
Beverlyd820bc22018-01-11 15:28:33 -0500970 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
Beverlyff2df9b2018-10-10 16:54:10 -0400971 final boolean allowCalls = mConsolidatedPolicy.allowCalls();
972 final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
973 final boolean allowSystem = mConsolidatedPolicy.allowSystem();
974 final boolean allowMedia = mConsolidatedPolicy.allowMedia();
975 final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();
John Spurlock8403b752014-12-10 12:47:01 -0500976
977 // notification restrictions
Bryce Lee7219ada2016-04-08 10:54:23 -0700978 final boolean muteNotifications =
979 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
John Spurlock056c5192014-04-20 21:52:01 -0400980 // call restrictions
Beverlyd820bc22018-01-11 15:28:33 -0500981 final boolean muteCalls = zenAlarmsOnly
Beverlyff2df9b2018-10-10 16:54:10 -0400982 || (zenPriorityOnly && !allowCalls && !allowRepeatCallers)
Bryce Lee7219ada2016-04-08 10:54:23 -0700983 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
Beverly04216872017-09-28 10:55:32 -0400984 // alarm restrictions
Beverlyff2df9b2018-10-10 16:54:10 -0400985 final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
Beverlyd6964762018-02-16 14:07:03 -0500986 // media restrictions
Beverlyff2df9b2018-10-10 16:54:10 -0400987 final boolean muteMedia = zenPriorityOnly && !allowMedia;
Beverlyd6964762018-02-16 14:07:03 -0500988 // system restrictions
Beverlyff2df9b2018-10-10 16:54:10 -0400989 final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem);
Julia Reynolds3fe81be2016-02-03 09:10:06 -0500990 // total silence restrictions
Beverlyff2df9b2018-10-10 16:54:10 -0400991 final boolean muteEverything = zenSilence || (zenPriorityOnly
992 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
John Spurlock25d01ee2015-06-03 12:17:46 -0400993
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700994 for (int usage : AudioAttributes.SDK_USAGES) {
995 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -0700996 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
997 applyRestrictions(false /*mute*/, usage);
998 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
Jean-Michel Trivie743bda2016-09-09 11:56:48 -0700999 applyRestrictions(muteNotifications || muteEverything, usage);
1000 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
1001 applyRestrictions(muteCalls || muteEverything, usage);
Beverly04216872017-09-28 10:55:32 -04001002 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
1003 applyRestrictions(muteAlarms || muteEverything, usage);
Beverlyd6964762018-02-16 14:07:03 -05001004 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
1005 applyRestrictions(muteMedia || muteEverything, usage);
1006 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
Beverly738bffd2018-03-12 10:46:17 -04001007 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
1008 // normally DND will only restrict touch sounds, not haptic feedback/vibrations
1009 applyRestrictions(muteSystem || muteEverything, usage,
1010 AppOpsManager.OP_PLAY_AUDIO);
1011 applyRestrictions(false, usage, AppOpsManager.OP_VIBRATE);
1012 } else {
1013 applyRestrictions(muteSystem || muteEverything, usage);
1014 }
Julia Reynolds3fe81be2016-02-03 09:10:06 -05001015 } else {
Jean-Michel Trivie743bda2016-09-09 11:56:48 -07001016 applyRestrictions(muteEverything, usage);
Julia Reynolds3fe81be2016-02-03 09:10:06 -05001017 }
1018 }
John Spurlock8403b752014-12-10 12:47:01 -05001019 }
John Spurlockae641c92014-06-30 18:11:40 -04001020
Beverlye2d9a232017-11-08 18:14:59 -05001021
Beverly04216872017-09-28 10:55:32 -04001022 @VisibleForTesting
Beverly738bffd2018-03-12 10:46:17 -04001023 protected void applyRestrictions(boolean mute, int usage, int code) {
John Spurlock8403b752014-12-10 12:47:01 -05001024 final String[] exceptionPackages = null; // none (for now)
Beverlye2d9a232017-11-08 18:14:59 -05001025
Dianne Hackbornbf1b57d2018-03-07 12:42:47 -08001026 // Only do this if we are executing within the system process... otherwise
1027 // we are running as test code, so don't have access to the protected call.
1028 if (Process.myUid() == Process.SYSTEM_UID) {
1029 final long ident = Binder.clearCallingIdentity();
1030 try {
1031 mAppOps.setRestriction(code, usage,
1032 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
1033 exceptionPackages);
1034 } finally {
1035 Binder.restoreCallingIdentity(ident);
1036 }
1037 }
John Spurlock056c5192014-04-20 21:52:01 -04001038 }
1039
Beverly85f52412018-02-27 10:41:13 -05001040 @VisibleForTesting
Beverly738bffd2018-03-12 10:46:17 -04001041 protected void applyRestrictions(boolean mute, int usage) {
1042 applyRestrictions(mute, usage, AppOpsManager.OP_VIBRATE);
1043 applyRestrictions(mute, usage, AppOpsManager.OP_PLAY_AUDIO);
1044 }
1045
1046
1047 @VisibleForTesting
Beverly85f52412018-02-27 10:41:13 -05001048 protected void applyZenToRingerMode() {
John Spurlock661f2cf2014-11-17 10:29:10 -05001049 if (mAudioManager == null) return;
John Spurlock661f2cf2014-11-17 10:29:10 -05001050 // force the ringer mode into compliance
1051 final int ringerModeInternal = mAudioManager.getRingerModeInternal();
1052 int newRingerModeInternal = ringerModeInternal;
John Spurlock57627792014-12-11 11:29:54 -05001053 switch (mZenMode) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001054 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlock4f1163c2015-04-02 17:41:21 -04001055 case Global.ZEN_MODE_ALARMS:
John Spurlock661f2cf2014-11-17 10:29:10 -05001056 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001057 setPreviousRingerModeSetting(ringerModeInternal);
John Spurlock661f2cf2014-11-17 10:29:10 -05001058 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
John Spurlock8c01d882014-07-28 13:37:13 -04001059 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001060 break;
1061 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
Beverly9e4214d2018-03-26 11:10:10 -04001062 // do not apply zen to ringer, streams zen muted in AudioService
Beverly925cde82018-01-23 09:31:23 -05001063 break;
John Spurlock661f2cf2014-11-17 10:29:10 -05001064 case Global.ZEN_MODE_OFF:
1065 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001066 newRingerModeInternal = getPreviousRingerModeSetting();
1067 setPreviousRingerModeSetting(null);
John Spurlock661f2cf2014-11-17 10:29:10 -05001068 }
1069 break;
John Spurlock8c01d882014-07-28 13:37:13 -04001070 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001071 if (newRingerModeInternal != -1) {
1072 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
1073 }
1074 }
1075
John Spurlock1c923a32014-04-27 16:42:29 -04001076 private void dispatchOnConfigChanged() {
1077 for (Callback callback : mCallbacks) {
1078 callback.onConfigChanged();
1079 }
1080 }
1081
John Spurlock1fc476d2015-04-14 16:05:20 -04001082 private void dispatchOnPolicyChanged() {
1083 for (Callback callback : mCallbacks) {
1084 callback.onPolicyChanged();
1085 }
1086 }
1087
Beverlyff2df9b2018-10-10 16:54:10 -04001088 private void dispatchOnConsolidatedPolicyChanged() {
1089 for (Callback callback : mCallbacks) {
1090 callback.onConsolidatedPolicyChanged();
1091 }
1092 }
1093
John Spurlock1c923a32014-04-27 16:42:29 -04001094 private void dispatchOnZenModeChanged() {
1095 for (Callback callback : mCallbacks) {
1096 callback.onZenModeChanged();
1097 }
1098 }
1099
John Spurlockb2278d62015-04-07 12:47:12 -04001100 private ZenModeConfig readDefaultConfig(Resources resources) {
1101 XmlResourceParser parser = null;
1102 try {
1103 parser = resources.getXml(R.xml.default_zen_mode_config);
1104 while (parser.next() != XmlPullParser.END_DOCUMENT) {
Julia Reynolds206c7e92016-09-15 10:38:03 -04001105 final ZenModeConfig config = ZenModeConfig.readXml(parser);
John Spurlockb2278d62015-04-07 12:47:12 -04001106 if (config != null) return config;
1107 }
1108 } catch (Exception e) {
1109 Log.w(TAG, "Error reading default zen mode config from resource", e);
1110 } finally {
1111 IoUtils.closeQuietly(parser);
1112 }
1113 return new ZenModeConfig();
1114 }
1115
John Spurlockb2278d62015-04-07 12:47:12 -04001116 private static int zenSeverity(int zen) {
1117 switch (zen) {
1118 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
1119 case Global.ZEN_MODE_ALARMS: return 2;
1120 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
1121 default: return 0;
1122 }
1123 }
1124
Beverly85f52412018-02-27 10:41:13 -05001125 @VisibleForTesting
1126 protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
John Spurlockb2278d62015-04-07 12:47:12 -04001127 @Override
1128 public String toString() {
1129 return TAG;
1130 }
1131
1132 @Override
1133 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
1134 int ringerModeExternal, VolumePolicy policy) {
1135 final boolean isChange = ringerModeOld != ringerModeNew;
1136
1137 int ringerModeExternalOut = ringerModeNew;
1138
Beverlye4ee1cc2018-03-06 17:21:08 -05001139 if (mZenMode == Global.ZEN_MODE_OFF
1140 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1141 && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) {
1142 // in priority only with ringer not muted, save ringer mode changes
1143 // in dnd off, save ringer mode changes
1144 setPreviousRingerModeSetting(ringerModeNew);
1145 }
John Spurlockb2278d62015-04-07 12:47:12 -04001146 int newZen = -1;
1147 switch (ringerModeNew) {
1148 case AudioManager.RINGER_MODE_SILENT:
1149 if (isChange && policy.doNotDisturbWhenSilent) {
Beverly925cde82018-01-23 09:31:23 -05001150 if (mZenMode == Global.ZEN_MODE_OFF) {
Julia Reynoldsf3252be2018-01-17 09:26:21 -05001151 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
John Spurlockb2278d62015-04-07 12:47:12 -04001152 }
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001153 setPreviousRingerModeSetting(ringerModeOld);
John Spurlockb2278d62015-04-07 12:47:12 -04001154 }
1155 break;
1156 case AudioManager.RINGER_MODE_VIBRATE:
1157 case AudioManager.RINGER_MODE_NORMAL:
1158 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
1159 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
Beverly925cde82018-01-23 09:31:23 -05001160 || mZenMode == Global.ZEN_MODE_ALARMS
1161 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1162 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
Beverlyd6964762018-02-16 14:07:03 -05001163 mConfig)))) {
John Spurlockb2278d62015-04-07 12:47:12 -04001164 newZen = Global.ZEN_MODE_OFF;
1165 } else if (mZenMode != Global.ZEN_MODE_OFF) {
1166 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
1167 }
1168 break;
1169 }
Beverly85f52412018-02-27 10:41:13 -05001170
John Spurlockb2278d62015-04-07 12:47:12 -04001171 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001172 setManualZenMode(newZen, null, "ringerModeInternal", null,
1173 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001174 }
John Spurlockb2278d62015-04-07 12:47:12 -04001175 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
1176 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
1177 ringerModeExternal, ringerModeExternalOut);
1178 }
1179 return ringerModeExternalOut;
1180 }
1181
1182 @Override
1183 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
1184 int ringerModeInternal, VolumePolicy policy) {
1185 int ringerModeInternalOut = ringerModeNew;
1186 final boolean isChange = ringerModeOld != ringerModeNew;
1187 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
1188
1189 int newZen = -1;
1190 switch (ringerModeNew) {
1191 case AudioManager.RINGER_MODE_SILENT:
1192 if (isChange) {
1193 if (mZenMode == Global.ZEN_MODE_OFF) {
Julia Reynoldsf3252be2018-01-17 09:26:21 -05001194 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
John Spurlockb2278d62015-04-07 12:47:12 -04001195 }
1196 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
John Spurlock05715ec2015-05-13 11:19:19 -04001197 : AudioManager.RINGER_MODE_SILENT;
John Spurlockb2278d62015-04-07 12:47:12 -04001198 } else {
1199 ringerModeInternalOut = ringerModeInternal;
1200 }
1201 break;
1202 case AudioManager.RINGER_MODE_VIBRATE:
1203 case AudioManager.RINGER_MODE_NORMAL:
1204 if (mZenMode != Global.ZEN_MODE_OFF) {
1205 newZen = Global.ZEN_MODE_OFF;
1206 }
1207 break;
1208 }
1209 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001210 setManualZenMode(newZen, null, "ringerModeExternal", caller,
1211 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001212 }
1213
1214 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
1215 ringerModeInternal, ringerModeInternalOut);
1216 return ringerModeInternalOut;
1217 }
John Spurlockd9c75db2015-04-28 11:19:13 -04001218
1219 @Override
1220 public boolean canVolumeDownEnterSilent() {
1221 return mZenMode == Global.ZEN_MODE_OFF;
1222 }
John Spurlock50ced3f2015-05-11 16:00:09 -04001223
1224 @Override
1225 public int getRingerModeAffectedStreams(int streams) {
Beverlyd6964762018-02-16 14:07:03 -05001226 // ringtone and notification streams are always affected by ringer mode
1227 // system stream is affected by ringer mode when not in priority-only
John Spurlock50ced3f2015-05-11 16:00:09 -04001228 streams |= (1 << AudioSystem.STREAM_RING) |
Beverlyd6964762018-02-16 14:07:03 -05001229 (1 << AudioSystem.STREAM_NOTIFICATION) |
1230 (1 << AudioSystem.STREAM_SYSTEM);
John Spurlock50ced3f2015-05-11 16:00:09 -04001231
John Spurlock50ced3f2015-05-11 16:00:09 -04001232 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
Beverly925cde82018-01-23 09:31:23 -05001233 // alarm and music streams affected by ringer mode when in total silence
John Spurlock50ced3f2015-05-11 16:00:09 -04001234 streams |= (1 << AudioSystem.STREAM_ALARM) |
Beverlyd6964762018-02-16 14:07:03 -05001235 (1 << AudioSystem.STREAM_MUSIC);
John Spurlock50ced3f2015-05-11 16:00:09 -04001236 } else {
1237 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
Beverlyd6964762018-02-16 14:07:03 -05001238 (1 << AudioSystem.STREAM_MUSIC));
1239 }
1240
1241 if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1242 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) {
1243 // system stream is not affected by ringer mode in priority only when the ringer
1244 // is zen muted (all other notification categories are muted)
1245 streams &= ~(1 << AudioSystem.STREAM_SYSTEM);
1246 } else {
1247 streams |= (1 << AudioSystem.STREAM_SYSTEM);
John Spurlock50ced3f2015-05-11 16:00:09 -04001248 }
1249 return streams;
1250 }
John Spurlockb2278d62015-04-07 12:47:12 -04001251 }
1252
1253 private final class SettingsObserver extends ContentObserver {
John Spurlock056c5192014-04-20 21:52:01 -04001254 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1255
1256 public SettingsObserver(Handler handler) {
1257 super(handler);
1258 }
1259
1260 public void observe() {
1261 final ContentResolver resolver = mContext.getContentResolver();
1262 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1263 update(null);
1264 }
1265
1266 @Override
1267 public void onChange(boolean selfChange, Uri uri) {
1268 update(uri);
1269 }
1270
1271 public void update(Uri uri) {
1272 if (ZEN_MODE.equals(uri)) {
John Spurlockb2278d62015-04-07 12:47:12 -04001273 if (mZenMode != getZenModeSetting()) {
1274 if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1275 setZenModeSetting(mZenMode);
1276 }
John Spurlock056c5192014-04-20 21:52:01 -04001277 }
1278 }
1279 }
1280
Beverly3bae4e52018-02-07 12:32:02 -05001281 private void showZenUpgradeNotification(int zen) {
Nicka485ec62018-07-03 11:32:39 -07001282 final boolean isWatch = mContext.getPackageManager().hasSystemFeature(
1283 PackageManager.FEATURE_WATCH);
Beverly3bae4e52018-02-07 12:32:02 -05001284 final boolean showNotification = mIsBootComplete
Julia Reynolds76bfa602018-04-23 09:38:47 -04001285 && zen != Global.ZEN_MODE_OFF
Nicka485ec62018-07-03 11:32:39 -07001286 && !isWatch
Beverly9087cd12018-09-21 15:30:49 -04001287 && Settings.Secure.getInt(mContext.getContentResolver(),
Beverly6c60b902018-08-17 10:10:46 -04001288 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
Beverly9087cd12018-09-21 15:30:49 -04001289 && Settings.Secure.getInt(mContext.getContentResolver(),
Beverly6c60b902018-08-17 10:10:46 -04001290 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
Beverly3bae4e52018-02-07 12:32:02 -05001291
Nicka485ec62018-07-03 11:32:39 -07001292 if (isWatch) {
Beverly9087cd12018-09-21 15:30:49 -04001293 Settings.Secure.putInt(mContext.getContentResolver(),
Beverly91d0a632018-07-02 16:45:00 -04001294 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Nicka485ec62018-07-03 11:32:39 -07001295 }
1296
Beverly3bae4e52018-02-07 12:32:02 -05001297 if (showNotification) {
1298 mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
1299 createZenUpgradeNotification());
Beverly91d0a632018-07-02 16:45:00 -04001300 Settings.Secure.putInt(mContext.getContentResolver(),
1301 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Beverly3bae4e52018-02-07 12:32:02 -05001302 }
1303 }
1304
1305 @VisibleForTesting
1306 protected Notification createZenUpgradeNotification() {
Beverly3bae4e52018-02-07 12:32:02 -05001307 final Bundle extras = new Bundle();
1308 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
1309 mContext.getResources().getString(R.string.global_action_settings));
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001310 int title = R.string.zen_upgrade_notification_title;
1311 int content = R.string.zen_upgrade_notification_content;
Julia Reynolds76bfa602018-04-23 09:38:47 -04001312 int drawable = R.drawable.ic_zen_24dp;
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001313 if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
Beverlyff2df9b2018-10-10 16:54:10 -04001314 getConsolidatedNotificationPolicy().suppressedVisualEffects)) {
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001315 title = R.string.zen_upgrade_notification_visd_title;
1316 content = R.string.zen_upgrade_notification_visd_content;
Julia Reynolds76bfa602018-04-23 09:38:47 -04001317 drawable = R.drawable.ic_dnd_block_notifications;
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001318 }
Julia Reynolds76bfa602018-04-23 09:38:47 -04001319
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001320 Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
1321 onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001322 return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001323 .setAutoCancel(true)
Beverlyd8b15ee2018-02-13 14:37:38 -05001324 .setSmallIcon(R.drawable.ic_settings_24dp)
Julia Reynolds76bfa602018-04-23 09:38:47 -04001325 .setLargeIcon(Icon.createWithResource(mContext, drawable))
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001326 .setContentTitle(mContext.getResources().getString(title))
1327 .setContentText(mContext.getResources().getString(content))
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001328 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
1329 PendingIntent.FLAG_UPDATE_CURRENT))
Beverly3bae4e52018-02-07 12:32:02 -05001330 .setAutoCancel(true)
1331 .setLocalOnly(true)
1332 .addExtras(extras)
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001333 .setStyle(new Notification.BigTextStyle())
Beverly3bae4e52018-02-07 12:32:02 -05001334 .build();
1335 }
1336
Chris Wren98d235b2015-05-27 18:25:17 -04001337 private final class Metrics extends Callback {
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001338 private static final String COUNTER_MODE_PREFIX = "dnd_mode_";
1339 private static final String COUNTER_TYPE_PREFIX = "dnd_type_";
1340 private static final int DND_OFF = 0;
1341 private static final int DND_ON_MANUAL = 1;
1342 private static final int DND_ON_AUTOMATIC = 2;
1343 private static final String COUNTER_RULE = "dnd_rule_count";
Chris Wren98d235b2015-05-27 18:25:17 -04001344 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1345
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001346 // Total silence, alarms only, priority only
Chris Wren98d235b2015-05-27 18:25:17 -04001347 private int mPreviousZenMode = -1;
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001348 private long mModeLogTimeMs = 0L;
1349
1350 private int mNumZenRules = -1;
1351 private long mRuleCountLogTime = 0L;
1352
1353 // automatic (1) vs manual (0) vs dnd off (2)
1354 private int mPreviousZenType = -1;
1355 private long mTypeLogTimeMs = 0L;
Chris Wren98d235b2015-05-27 18:25:17 -04001356
1357 @Override
1358 void onZenModeChanged() {
1359 emit();
1360 }
1361
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001362 @Override
1363 void onConfigChanged() {
1364 emit();
1365 }
1366
Chris Wren98d235b2015-05-27 18:25:17 -04001367 private void emit() {
1368 mHandler.postMetricsTimer();
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001369 emitZenMode();
1370 emitRules();
1371 emitDndType();
1372 }
1373
1374 private void emitZenMode() {
Chris Wren98d235b2015-05-27 18:25:17 -04001375 final long now = SystemClock.elapsedRealtime();
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001376 final long since = (now - mModeLogTimeMs);
Chris Wren98d235b2015-05-27 18:25:17 -04001377 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1378 if (mPreviousZenMode != -1) {
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001379 MetricsLogger.count(
1380 mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since);
Chris Wren98d235b2015-05-27 18:25:17 -04001381 }
1382 mPreviousZenMode = mZenMode;
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001383 mModeLogTimeMs = now;
1384 }
1385 }
1386
1387 private void emitRules() {
1388 final long now = SystemClock.elapsedRealtime();
1389 final long since = (now - mRuleCountLogTime);
1390 synchronized (mConfig) {
1391 int numZenRules = mConfig.automaticRules.size();
1392 if (mNumZenRules != numZenRules
1393 || since > MINIMUM_LOG_PERIOD_MS) {
1394 if (mNumZenRules != -1) {
1395 MetricsLogger.count(mContext, COUNTER_RULE,
1396 numZenRules - mNumZenRules);
1397 }
1398 mNumZenRules = numZenRules;
1399
1400 mRuleCountLogTime = since;
1401 }
1402 }
1403 }
1404
1405 private void emitDndType() {
1406 final long now = SystemClock.elapsedRealtime();
1407 final long since = (now - mTypeLogTimeMs);
1408 synchronized (mConfig) {
1409 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF;
1410 int zenType = !dndOn ? DND_OFF
1411 : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC;
1412 if (zenType != mPreviousZenType
1413 || since > MINIMUM_LOG_PERIOD_MS) {
1414 if (mPreviousZenType != -1) {
1415 MetricsLogger.count(
1416 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since);
1417 }
1418 mTypeLogTimeMs = now;
1419 mPreviousZenType = zenType;
1420 }
Chris Wren98d235b2015-05-27 18:25:17 -04001421 }
1422 }
1423 }
1424
John Spurlockb2278d62015-04-07 12:47:12 -04001425 private final class H extends Handler {
John Spurlock57627792014-12-11 11:29:54 -05001426 private static final int MSG_DISPATCH = 1;
Chris Wren98d235b2015-05-27 18:25:17 -04001427 private static final int MSG_METRICS = 2;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001428 private static final int MSG_APPLY_CONFIG = 4;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001429
1430 private final class ConfigMessageData {
1431 public final ZenModeConfig config;
Julia Reynolds8f056002018-07-13 15:12:29 -04001432 public ComponentName triggeringComponent;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001433 public final String reason;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001434 public final boolean setRingerMode;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001435
Julia Reynolds8f056002018-07-13 15:12:29 -04001436 ConfigMessageData(ZenModeConfig config, String reason,
1437 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001438 this.config = config;
1439 this.reason = reason;
1440 this.setRingerMode = setRingerMode;
Julia Reynolds8f056002018-07-13 15:12:29 -04001441 this.triggeringComponent = triggeringComponent;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001442 }
1443 }
Chris Wren98d235b2015-05-27 18:25:17 -04001444
1445 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
John Spurlock661f2cf2014-11-17 10:29:10 -05001446
1447 private H(Looper looper) {
1448 super(looper);
John Spurlock056c5192014-04-20 21:52:01 -04001449 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001450
John Spurlock57627792014-12-11 11:29:54 -05001451 private void postDispatchOnZenModeChanged() {
1452 removeMessages(MSG_DISPATCH);
1453 sendEmptyMessage(MSG_DISPATCH);
John Spurlock661f2cf2014-11-17 10:29:10 -05001454 }
1455
Chris Wren98d235b2015-05-27 18:25:17 -04001456 private void postMetricsTimer() {
1457 removeMessages(MSG_METRICS);
1458 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1459 }
1460
Julia Reynolds8f056002018-07-13 15:12:29 -04001461 private void postApplyConfig(ZenModeConfig config, String reason,
1462 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001463 sendMessage(obtainMessage(MSG_APPLY_CONFIG,
Julia Reynolds8f056002018-07-13 15:12:29 -04001464 new ConfigMessageData(config, reason, triggeringComponent, setRingerMode)));
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001465 }
1466
John Spurlock661f2cf2014-11-17 10:29:10 -05001467 @Override
1468 public void handleMessage(Message msg) {
John Spurlock57627792014-12-11 11:29:54 -05001469 switch (msg.what) {
1470 case MSG_DISPATCH:
1471 dispatchOnZenModeChanged();
John Spurlock661f2cf2014-11-17 10:29:10 -05001472 break;
Chris Wren98d235b2015-05-27 18:25:17 -04001473 case MSG_METRICS:
1474 mMetrics.emit();
1475 break;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001476 case MSG_APPLY_CONFIG:
1477 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1478 applyConfig(applyConfigData.config, applyConfigData.reason,
Julia Reynolds8f056002018-07-13 15:12:29 -04001479 applyConfigData.triggeringComponent, applyConfigData.setRingerMode);
John Spurlock661f2cf2014-11-17 10:29:10 -05001480 }
1481 }
1482 }
John Spurlock056c5192014-04-20 21:52:01 -04001483
John Spurlock1c923a32014-04-27 16:42:29 -04001484 public static class Callback {
1485 void onConfigChanged() {}
1486 void onZenModeChanged() {}
John Spurlock1fc476d2015-04-14 16:05:20 -04001487 void onPolicyChanged() {}
Beverlyff2df9b2018-10-10 16:54:10 -04001488 void onConsolidatedPolicyChanged() {}
John Spurlock056c5192014-04-20 21:52:01 -04001489 }
John Spurlock056c5192014-04-20 21:52:01 -04001490}