blob: ee948b28e546e49c538efa5dddf732a010f95654 [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
Julia Reynolds3ec93302019-07-11 15:27:31 -040019import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED;
20import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
21import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
22
John Spurlock056c5192014-04-20 21:52:01 -040023import android.app.AppOpsManager;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040024import android.app.AutomaticZenRule;
Beverly3bae4e52018-02-07 12:32:02 -050025import android.app.Notification;
John Spurlock80774932015-05-07 17:38:50 -040026import android.app.NotificationManager;
John Spurlock1fc476d2015-04-14 16:05:20 -040027import android.app.NotificationManager.Policy;
Beverly3bae4e52018-02-07 12:32:02 -050028import android.app.PendingIntent;
John Spurlock312d1d02014-07-08 10:24:57 -040029import android.content.ComponentName;
John Spurlock056c5192014-04-20 21:52:01 -040030import android.content.ContentResolver;
31import android.content.Context;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -050032import android.content.Intent;
Julia Reynolds68062072018-08-06 15:38:21 -040033import android.content.pm.ActivityInfo;
34import android.content.pm.PackageItemInfo;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040035import android.content.pm.PackageManager;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -050036import android.content.pm.ResolveInfo;
37import android.content.pm.ServiceInfo;
John Spurlock056c5192014-04-20 21:52:01 -040038import android.content.res.Resources;
39import android.content.res.XmlResourceParser;
40import android.database.ContentObserver;
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -040041import android.graphics.drawable.Icon;
Jean-Michel Trivie743bda2016-09-09 11:56:48 -070042import android.media.AudioAttributes;
John Spurlock056c5192014-04-20 21:52:01 -040043import android.media.AudioManager;
John Spurlock661f2cf2014-11-17 10:29:10 -050044import android.media.AudioManagerInternal;
John Spurlock50ced3f2015-05-11 16:00:09 -040045import android.media.AudioSystem;
John Spurlocka48d7792015-03-03 17:35:57 -050046import android.media.VolumePolicy;
John Spurlock056c5192014-04-20 21:52:01 -040047import android.net.Uri;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040048import android.os.Binder;
John Spurlock2b122f42014-08-27 16:29:47 -040049import android.os.Bundle;
John Spurlock056c5192014-04-20 21:52:01 -040050import android.os.Handler;
John Spurlock661f2cf2014-11-17 10:29:10 -050051import android.os.Looper;
52import android.os.Message;
Julia Reynoldsc8e54e82015-11-30 16:43:05 -050053import android.os.Process;
Chris Wren98d235b2015-05-27 18:25:17 -040054import android.os.SystemClock;
John Spurlockb5e767b2014-07-27 11:53:20 -040055import android.os.UserHandle;
Beverly3bae4e52018-02-07 12:32:02 -050056import android.provider.Settings;
John Spurlock056c5192014-04-20 21:52:01 -040057import android.provider.Settings.Global;
Julia Reynolds520df6e2017-02-13 09:05:10 -050058import android.service.notification.Condition;
Julia Reynolds43b70cd2016-01-14 15:05:34 -050059import android.service.notification.ConditionProviderService;
John Spurlock056c5192014-04-20 21:52:01 -040060import android.service.notification.ZenModeConfig;
John Spurlockb2278d62015-04-07 12:47:12 -040061import android.service.notification.ZenModeConfig.ZenRule;
Julia Reynolds520df6e2017-02-13 09:05:10 -050062import android.service.notification.ZenModeProto;
Beverlyff2df9b2018-10-10 16:54:10 -040063import android.service.notification.ZenPolicy;
Julia Reynolds87c42772016-05-16 09:52:17 -040064import android.util.AndroidRuntimeException;
Beverly4e2f76c2018-03-16 15:43:49 -040065import android.util.ArrayMap;
John Spurlock4db0d982014-08-13 09:19:03 -040066import android.util.Log;
Beverlyd4f96492017-08-02 13:36:11 -040067import android.util.Slog;
John Spurlock21258a32015-05-27 18:22:55 -040068import android.util.SparseArray;
Julia Reynolds520df6e2017-02-13 09:05:10 -050069import android.util.proto.ProtoOutputStream;
John Spurlock056c5192014-04-20 21:52:01 -040070
71import com.android.internal.R;
Beverly04216872017-09-28 10:55:32 -040072import com.android.internal.annotations.VisibleForTesting;
John Spurlock25d01ee2015-06-03 12:17:46 -040073import com.android.internal.logging.MetricsLogger;
Beverly3bae4e52018-02-07 12:32:02 -050074import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
75import com.android.internal.notification.SystemNotificationChannels;
John Spurlock661f2cf2014-11-17 10:29:10 -050076import com.android.server.LocalServices;
John Spurlock056c5192014-04-20 21:52:01 -040077
78import libcore.io.IoUtils;
79
80import org.xmlpull.v1.XmlPullParser;
81import org.xmlpull.v1.XmlPullParserException;
82import org.xmlpull.v1.XmlSerializer;
83
84import java.io.IOException;
85import java.io.PrintWriter;
John Spurlock1c923a32014-04-27 16:42:29 -040086import java.util.ArrayList;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -040087import java.util.List;
John Spurlock1fc476d2015-04-14 16:05:20 -040088import java.util.Objects;
John Spurlock056c5192014-04-20 21:52:01 -040089
90/**
91 * NotificationManagerService helper for functionality related to zen mode.
92 */
John Spurlockb2278d62015-04-07 12:47:12 -040093public class ZenModeHelper {
94 static final String TAG = "ZenModeHelper";
95 static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlock056c5192014-04-20 21:52:01 -040096
Julia Reynolds5a43aaa2015-12-15 13:54:41 -050097 // The amount of time rules instances can exist without their owning app being installed.
98 private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
99
John Spurlock056c5192014-04-20 21:52:01 -0400100 private final Context mContext;
John Spurlock661f2cf2014-11-17 10:29:10 -0500101 private final H mHandler;
John Spurlock056c5192014-04-20 21:52:01 -0400102 private final SettingsObserver mSettingsObserver;
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400103 private final AppOpsManager mAppOps;
Beverly3bae4e52018-02-07 12:32:02 -0500104 @VisibleForTesting protected final NotificationManager mNotificationManager;
Beverly49ba9a62018-11-02 13:19:31 -0400105 @VisibleForTesting protected ZenModeConfig mDefaultConfig;
John Spurlock1c923a32014-04-27 16:42:29 -0400106 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
John Spurlockb2278d62015-04-07 12:47:12 -0400107 private final ZenModeFiltering mFiltering;
Beverlyd6964762018-02-16 14:07:03 -0500108 protected final RingerModeDelegate mRingerModeDelegate = new
109 RingerModeDelegate();
Beverly2f43b642018-08-14 09:43:11 -0400110 @VisibleForTesting protected final ZenModeConditions mConditions;
Annie Meng8b646fd2019-02-01 18:46:42 +0000111 @VisibleForTesting final SparseArray<ZenModeConfig> mConfigs = new SparseArray<>();
Chris Wren98d235b2015-05-27 18:25:17 -0400112 private final Metrics mMetrics = new Metrics();
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500113 private final ConditionProviders.Config mServiceConfig;
John Spurlock056c5192014-04-20 21:52:01 -0400114
Beverly04216872017-09-28 10:55:32 -0400115 @VisibleForTesting protected int mZenMode;
Beverlyff2df9b2018-10-10 16:54:10 -0400116 @VisibleForTesting protected NotificationManager.Policy mConsolidatedPolicy;
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700117 private int mUser = UserHandle.USER_SYSTEM;
Beverly04216872017-09-28 10:55:32 -0400118 @VisibleForTesting protected ZenModeConfig mConfig;
Beverly85f52412018-02-27 10:41:13 -0500119 @VisibleForTesting protected AudioManagerInternal mAudioManager;
Beverlyd4f96492017-08-02 13:36:11 -0400120 protected PackageManager mPm;
Bryce Lee7219ada2016-04-08 10:54:23 -0700121 private long mSuppressedEffects;
122
123 public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
124 public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
125 public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
126 | SUPPRESSED_EFFECT_NOTIFICATIONS;
John Spurlock056c5192014-04-20 21:52:01 -0400127
Beverly3bae4e52018-02-07 12:32:02 -0500128 @VisibleForTesting protected boolean mIsBootComplete;
Beverlyd4f96492017-08-02 13:36:11 -0400129
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400130 private String[] mPriorityOnlyDndExemptPackages;
131
John Spurlockb2278d62015-04-07 12:47:12 -0400132 public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
John Spurlock056c5192014-04-20 21:52:01 -0400133 mContext = context;
John Spurlock661f2cf2014-11-17 10:29:10 -0500134 mHandler = new H(looper);
Chris Wren98d235b2015-05-27 18:25:17 -0400135 addCallback(mMetrics);
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400136 mAppOps = context.getSystemService(AppOpsManager.class);
Beverly3bae4e52018-02-07 12:32:02 -0500137 mNotificationManager = context.getSystemService(NotificationManager.class);
Beverlyd4f96492017-08-02 13:36:11 -0400138
Beverlyf3b92d22018-09-18 15:13:17 -0400139 mDefaultConfig = readDefaultConfig(mContext.getResources());
140 updateDefaultAutomaticRuleNames();
141 mConfig = mDefaultConfig.copy();
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700142 mConfigs.put(UserHandle.USER_SYSTEM, mConfig);
Beverlyd4f96492017-08-02 13:36:11 -0400143
John Spurlock056c5192014-04-20 21:52:01 -0400144 mSettingsObserver = new SettingsObserver(mHandler);
145 mSettingsObserver.observe();
John Spurlockb2278d62015-04-07 12:47:12 -0400146 mFiltering = new ZenModeFiltering(mContext);
147 mConditions = new ZenModeConditions(this, conditionProviders);
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500148 mServiceConfig = conditionProviders.getConfig();
John Spurlock056c5192014-04-20 21:52:01 -0400149 }
150
John Spurlock1b8b22b2015-05-20 09:47:13 -0400151 public Looper getLooper() {
152 return mHandler.getLooper();
153 }
154
John Spurlockb2278d62015-04-07 12:47:12 -0400155 @Override
156 public String toString() {
157 return TAG;
158 }
159
160 public boolean matchesCallFilter(UserHandle userHandle, Bundle extras,
161 ValidateNotificationPeople validator, int contactsTimeoutMs, float timeoutAffinity) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400162 synchronized (mConfig) {
Beverlyff2df9b2018-10-10 16:54:10 -0400163 return ZenModeFiltering.matchesCallFilter(mContext, mZenMode, mConsolidatedPolicy,
164 userHandle, extras, validator, contactsTimeoutMs, timeoutAffinity);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400165 }
John Spurlockb2278d62015-04-07 12:47:12 -0400166 }
167
168 public boolean isCall(NotificationRecord record) {
169 return mFiltering.isCall(record);
170 }
171
Julia Reynoldsc6b371b2016-06-14 08:31:03 -0400172 public void recordCaller(NotificationRecord record) {
173 mFiltering.recordCall(record);
174 }
175
John Spurlockb2278d62015-04-07 12:47:12 -0400176 public boolean shouldIntercept(NotificationRecord record) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400177 synchronized (mConfig) {
Beverlyff2df9b2018-10-10 16:54:10 -0400178 return mFiltering.shouldIntercept(mZenMode, mConsolidatedPolicy, record);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400179 }
John Spurlock056c5192014-04-20 21:52:01 -0400180 }
181
John Spurlock1c923a32014-04-27 16:42:29 -0400182 public void addCallback(Callback callback) {
183 mCallbacks.add(callback);
John Spurlock056c5192014-04-20 21:52:01 -0400184 }
185
John Spurlock530052a2014-11-30 16:26:19 -0500186 public void removeCallback(Callback callback) {
187 mCallbacks.remove(callback);
188 }
189
John Spurlockb2278d62015-04-07 12:47:12 -0400190 public void initZenMode() {
191 if (DEBUG) Log.d(TAG, "initZenMode");
192 evaluateZenMode("init", true /*setRingerMode*/);
193 }
194
John Spurlock661f2cf2014-11-17 10:29:10 -0500195 public void onSystemReady() {
John Spurlockb2278d62015-04-07 12:47:12 -0400196 if (DEBUG) Log.d(TAG, "onSystemReady");
John Spurlock661f2cf2014-11-17 10:29:10 -0500197 mAudioManager = LocalServices.getService(AudioManagerInternal.class);
198 if (mAudioManager != null) {
John Spurlockb2278d62015-04-07 12:47:12 -0400199 mAudioManager.setRingerModeDelegate(mRingerModeDelegate);
John Spurlock661f2cf2014-11-17 10:29:10 -0500200 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500201 mPm = mContext.getPackageManager();
Chris Wren98d235b2015-05-27 18:25:17 -0400202 mHandler.postMetricsTimer();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500203 cleanUpZenRules();
Julia Reynolds8ac63032015-08-31 15:19:43 -0400204 evaluateZenMode("onSystemReady", true);
Beverly3bae4e52018-02-07 12:32:02 -0500205 mIsBootComplete = true;
206 showZenUpgradeNotification(mZenMode);
John Spurlockae641c92014-06-30 18:11:40 -0400207 }
208
John Spurlock21258a32015-05-27 18:22:55 -0400209 public void onUserSwitched(int user) {
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500210 loadConfigForUser(user, "onUserSwitched");
John Spurlock21258a32015-05-27 18:22:55 -0400211 }
212
213 public void onUserRemoved(int user) {
Xiaohui Chenddbe4ca2015-08-13 16:20:56 -0700214 if (user < UserHandle.USER_SYSTEM) return;
John Spurlock21258a32015-05-27 18:22:55 -0400215 if (DEBUG) Log.d(TAG, "onUserRemoved u=" + user);
216 mConfigs.remove(user);
217 }
218
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500219 public void onUserUnlocked(int user) {
220 loadConfigForUser(user, "onUserUnlocked");
221 }
222
Julia Reynoldse99db5a2019-04-16 12:50:04 -0400223 void setPriorityOnlyDndExemptPackages(String[] packages) {
224 mPriorityOnlyDndExemptPackages = packages;
225 }
226
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500227 private void loadConfigForUser(int user, String reason) {
228 if (mUser == user || user < UserHandle.USER_SYSTEM) return;
229 mUser = user;
230 if (DEBUG) Log.d(TAG, reason + " u=" + user);
231 ZenModeConfig config = mConfigs.get(user);
232 if (config == null) {
233 if (DEBUG) Log.d(TAG, reason + " generating default config for user " + user);
234 config = mDefaultConfig.copy();
235 config.user = user;
236 }
237 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400238 setConfigLocked(config, null, reason);
Julia Reynoldsa3dcaff2016-02-03 15:04:05 -0500239 }
240 cleanUpZenRules();
241 }
242
Christoph Studer85a384b2014-08-27 20:16:15 +0200243 public int getZenModeListenerInterruptionFilter() {
John Spurlock80774932015-05-07 17:38:50 -0400244 return NotificationManager.zenModeToInterruptionFilter(mZenMode);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400245 }
246
John Spurlock80774932015-05-07 17:38:50 -0400247 public void requestFromListener(ComponentName name, int filter) {
248 final int newZen = NotificationManager.zenModeFromInterruptionFilter(filter, -1);
John Spurlockd8afe3c2014-08-01 14:04:07 -0400249 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400250 setManualZenMode(newZen, null, name != null ? name.getPackageName() : null,
John Spurlockb2278d62015-04-07 12:47:12 -0400251 "listener:" + (name != null ? name.flattenToShortString() : null));
John Spurlockd8afe3c2014-08-01 14:04:07 -0400252 }
253 }
254
Bryce Lee7219ada2016-04-08 10:54:23 -0700255 public void setSuppressedEffects(long suppressedEffects) {
256 if (mSuppressedEffects == suppressedEffects) return;
257 mSuppressedEffects = suppressedEffects;
John Spurlock8403b752014-12-10 12:47:01 -0500258 applyRestrictions();
259 }
260
Bryce Lee7219ada2016-04-08 10:54:23 -0700261 public long getSuppressedEffects() {
262 return mSuppressedEffects;
263 }
264
John Spurlock1c923a32014-04-27 16:42:29 -0400265 public int getZenMode() {
266 return mZenMode;
267 }
268
Julia Reynolds361e82d32016-02-26 18:19:49 -0500269 public List<ZenRule> getZenRules() {
270 List<ZenRule> rules = new ArrayList<>();
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400271 synchronized (mConfig) {
272 if (mConfig == null) return rules;
273 for (ZenRule rule : mConfig.automaticRules.values()) {
274 if (canManageAutomaticZenRule(rule)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500275 rules.add(rule);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400276 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400277 }
278 }
279 return rules;
280 }
281
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400282 public AutomaticZenRule getAutomaticZenRule(String id) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400283 ZenRule rule;
284 synchronized (mConfig) {
285 if (mConfig == null) return null;
286 rule = mConfig.automaticRules.get(id);
287 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400288 if (rule == null) return null;
289 if (canManageAutomaticZenRule(rule)) {
290 return createAutomaticZenRule(rule);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400291 }
292 return null;
293 }
294
Julia Reynolds361e82d32016-02-26 18:19:49 -0500295 public String addAutomaticZenRule(AutomaticZenRule automaticZenRule, String reason) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500296 if (!isSystemRule(automaticZenRule)) {
Julia Reynolds68062072018-08-06 15:38:21 -0400297 PackageItemInfo component = getServiceInfo(automaticZenRule.getOwner());
298 if (component == null) {
299 component = getActivityInfo(automaticZenRule.getConfigurationActivity());
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500300 }
Julia Reynolds68062072018-08-06 15:38:21 -0400301 if (component == null) {
302 throw new IllegalArgumentException("Lacking enabled CPS or config activity");
303 }
Julia Reynolds7f2f4412016-03-01 12:33:48 -0500304 int ruleInstanceLimit = -1;
Julia Reynolds68062072018-08-06 15:38:21 -0400305 if (component.metaData != null) {
306 ruleInstanceLimit = component.metaData.getInt(
Julia Reynolds7f2f4412016-03-01 12:33:48 -0500307 ConditionProviderService.META_DATA_RULE_INSTANCE_LIMIT, -1);
308 }
Julia Reynolds68062072018-08-06 15:38:21 -0400309 int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
310 + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
311 + 1;
312 if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500313 throw new IllegalArgumentException("Rule instance limit exceeded");
314 }
Julia Reynolds68062072018-08-06 15:38:21 -0400315
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500316 }
317
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400318 ZenModeConfig newConfig;
319 synchronized (mConfig) {
Julia Reynolds87c42772016-05-16 09:52:17 -0400320 if (mConfig == null) {
321 throw new AndroidRuntimeException("Could not create rule");
322 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400323 if (DEBUG) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500324 Log.d(TAG, "addAutomaticZenRule rule= " + automaticZenRule + " reason=" + reason);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400325 }
326 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500327 ZenRule rule = new ZenRule();
328 populateZenRule(automaticZenRule, rule, true);
Beverlya0d07ab2018-11-28 16:49:23 -0500329 newConfig.automaticRules.put(rule.id, rule);
Julia Reynolds8f056002018-07-13 15:12:29 -0400330 if (setConfigLocked(newConfig, reason, rule.component, true)) {
Julia Reynolds361e82d32016-02-26 18:19:49 -0500331 return rule.id;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500332 } else {
Julia Reynolds87c42772016-05-16 09:52:17 -0400333 throw new AndroidRuntimeException("Could not create rule");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500334 }
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400335 }
336 }
337
Julia Reynolds361e82d32016-02-26 18:19:49 -0500338 public boolean updateAutomaticZenRule(String ruleId, AutomaticZenRule automaticZenRule,
339 String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400340 ZenModeConfig newConfig;
341 synchronized (mConfig) {
342 if (mConfig == null) return false;
343 if (DEBUG) {
344 Log.d(TAG, "updateAutomaticZenRule zenRule=" + automaticZenRule
345 + " reason=" + reason);
346 }
347 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500348 ZenModeConfig.ZenRule rule;
349 if (ruleId == null) {
350 throw new IllegalArgumentException("Rule doesn't exist");
351 } else {
352 rule = newConfig.automaticRules.get(ruleId);
353 if (rule == null || !canManageAutomaticZenRule(rule)) {
354 throw new SecurityException(
355 "Cannot update rules not owned by your condition provider");
356 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400357 }
Julia Reynolds3ec93302019-07-11 15:27:31 -0400358 if (rule.enabled != automaticZenRule.isEnabled()) {
359 dispatchOnAutomaticRuleStatusChanged(mConfig.user, rule.pkg, ruleId,
360 automaticZenRule.isEnabled()
361 ? AUTOMATIC_RULE_STATUS_ENABLED : AUTOMATIC_RULE_STATUS_DISABLED);
362 }
363
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500364 populateZenRule(automaticZenRule, rule, false);
Julia Reynolds8f056002018-07-13 15:12:29 -0400365 return setConfigLocked(newConfig, reason, rule.component, true);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400366 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400367 }
368
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400369 public boolean removeAutomaticZenRule(String id, String reason) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400370 ZenModeConfig newConfig;
371 synchronized (mConfig) {
372 if (mConfig == null) return false;
373 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500374 ZenRule rule = newConfig.automaticRules.get(id);
375 if (rule == null) return false;
376 if (canManageAutomaticZenRule(rule)) {
377 newConfig.automaticRules.remove(id);
378 if (DEBUG) Log.d(TAG, "removeZenRule zenRule=" + id + " reason=" + reason);
379 } else {
380 throw new SecurityException(
381 "Cannot delete rules not owned by your condition provider");
382 }
Julia Reynolds3ec93302019-07-11 15:27:31 -0400383 dispatchOnAutomaticRuleStatusChanged(
384 mConfig.user, rule.pkg, id, AUTOMATIC_RULE_STATUS_REMOVED);
Julia Reynolds8f056002018-07-13 15:12:29 -0400385 return setConfigLocked(newConfig, reason, null, true);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400386 }
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400387 }
388
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500389 public boolean removeAutomaticZenRules(String packageName, String reason) {
390 ZenModeConfig newConfig;
391 synchronized (mConfig) {
392 if (mConfig == null) return false;
393 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500394 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
395 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
Julia Reynolds10e663b2019-01-07 10:15:12 -0500396 if (rule.pkg.equals(packageName) && canManageAutomaticZenRule(rule)) {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500397 newConfig.automaticRules.removeAt(i);
398 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500399 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400400 return setConfigLocked(newConfig, reason, null, true);
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500401 }
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500402 }
403
Julia Reynolds68062072018-08-06 15:38:21 -0400404 public void setAutomaticZenRuleState(String id, Condition condition) {
405 ZenModeConfig newConfig;
406 synchronized (mConfig) {
407 if (mConfig == null) return;
408
409 newConfig = mConfig.copy();
Julia Reynolds977a93e2019-04-10 16:18:13 -0400410 setAutomaticZenRuleStateLocked(newConfig, newConfig.automaticRules.get(id), condition);
Julia Reynolds68062072018-08-06 15:38:21 -0400411 }
Julia Reynolds68062072018-08-06 15:38:21 -0400412 }
413
414 public void setAutomaticZenRuleState(Uri ruleDefinition, Condition condition) {
415 ZenModeConfig newConfig;
416 synchronized (mConfig) {
417 if (mConfig == null) return;
418 newConfig = mConfig.copy();
Julia Reynolds68062072018-08-06 15:38:21 -0400419
Julia Reynolds977a93e2019-04-10 16:18:13 -0400420 setAutomaticZenRuleStateLocked(newConfig,
421 findMatchingRule(newConfig, ruleDefinition, condition),
422 condition);
423 }
Julia Reynolds68062072018-08-06 15:38:21 -0400424 }
425
Julia Reynolds977a93e2019-04-10 16:18:13 -0400426 private void setAutomaticZenRuleStateLocked(ZenModeConfig config, ZenRule rule,
427 Condition condition) {
Julia Reynolds68062072018-08-06 15:38:21 -0400428 if (rule == null) return;
429
430 rule.condition = condition;
431 updateSnoozing(rule);
432 setConfigLocked(config, rule.component, "conditionChanged");
433 }
434
435 private ZenRule findMatchingRule(ZenModeConfig config, Uri id, Condition condition) {
436 if (ruleMatches(id, condition, config.manualRule)) {
437 return config.manualRule;
438 } else {
439 for (ZenRule automaticRule : config.automaticRules.values()) {
440 if (ruleMatches(id, condition, automaticRule)) {
441 return automaticRule;
442 }
443 }
444 }
445 return null;
446 }
447
448 private boolean ruleMatches(Uri id, Condition condition, ZenRule rule) {
449 if (id == null || rule == null || rule.conditionId == null) return false;
450 if (!rule.conditionId.equals(id)) return false;
451 if (Objects.equals(condition, rule.condition)) return false;
452 return true;
453 }
454
455 private boolean updateSnoozing(ZenRule rule) {
456 if (rule != null && rule.snoozing && !rule.isTrueOrUnknown()) {
457 rule.snoozing = false;
458 if (DEBUG) Log.d(TAG, "Snoozing reset for " + rule.conditionId);
459 return true;
460 }
461 return false;
462 }
463
464 public int getCurrentInstanceCount(ComponentName cn) {
465 if (cn == null) {
466 return 0;
467 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500468 int count = 0;
469 synchronized (mConfig) {
470 for (ZenRule rule : mConfig.automaticRules.values()) {
Julia Reynolds68062072018-08-06 15:38:21 -0400471 if (cn.equals(rule.component) || cn.equals(rule.configurationActivity)) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500472 count++;
473 }
474 }
475 }
476 return count;
477 }
478
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400479 public boolean canManageAutomaticZenRule(ZenRule rule) {
Julia Reynoldsc8e54e82015-11-30 16:43:05 -0500480 final int callingUid = Binder.getCallingUid();
481 if (callingUid == 0 || callingUid == Process.SYSTEM_UID) {
482 return true;
483 } else if (mContext.checkCallingPermission(android.Manifest.permission.MANAGE_NOTIFICATIONS)
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400484 == PackageManager.PERMISSION_GRANTED) {
485 return true;
486 } else {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500487 String[] packages = mPm.getPackagesForUid(Binder.getCallingUid());
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400488 if (packages != null) {
489 final int packageCount = packages.length;
490 for (int i = 0; i < packageCount; i++) {
Julia Reynolds68062072018-08-06 15:38:21 -0400491 if (packages[i].equals(rule.pkg)) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400492 return true;
493 }
494 }
495 }
496 return false;
497 }
498 }
499
Beverlyd4f96492017-08-02 13:36:11 -0400500 protected void updateDefaultZenRules() {
Beverlyf3b92d22018-09-18 15:13:17 -0400501 updateDefaultAutomaticRuleNames();
502 for (ZenRule defaultRule : mDefaultConfig.automaticRules.values()) {
503 ZenRule currRule = mConfig.automaticRules.get(defaultRule.id);
Beverly49ba9a62018-11-02 13:19:31 -0400504 // if default rule wasn't user-modified nor enabled, use localized name
505 // instead of previous system name
506 if (currRule != null && !currRule.modified && !currRule.enabled
507 && !defaultRule.name.equals(currRule.name)) {
508 if (canManageAutomaticZenRule(currRule)) {
Beverlyd4f96492017-08-02 13:36:11 -0400509 if (DEBUG) Slog.d(TAG, "Locale change - updating default zen rule name "
Beverlyf3b92d22018-09-18 15:13:17 -0400510 + "from " + currRule.name + " to " + defaultRule.name);
Beverlyd4f96492017-08-02 13:36:11 -0400511 // update default rule (if locale changed, name of rule will change)
Beverly49ba9a62018-11-02 13:19:31 -0400512 currRule.name = defaultRule.name;
513 updateAutomaticZenRule(defaultRule.id, createAutomaticZenRule(currRule),
Beverlyd4f96492017-08-02 13:36:11 -0400514 "locale changed");
515 }
516 }
517 }
518 }
519
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500520 private boolean isSystemRule(AutomaticZenRule rule) {
Julia Reynolds68062072018-08-06 15:38:21 -0400521 return rule.getOwner() != null
522 && ZenModeConfig.SYSTEM_AUTHORITY.equals(rule.getOwner().getPackageName());
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500523 }
524
525 private ServiceInfo getServiceInfo(ComponentName owner) {
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500526 Intent queryIntent = new Intent();
527 queryIntent.setComponent(owner);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500528 List<ResolveInfo> installedServices = mPm.queryIntentServicesAsUser(
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500529 queryIntent,
530 PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
531 UserHandle.getCallingUserId());
532 if (installedServices != null) {
533 for (int i = 0, count = installedServices.size(); i < count; i++) {
534 ResolveInfo resolveInfo = installedServices.get(i);
535 ServiceInfo info = resolveInfo.serviceInfo;
536 if (mServiceConfig.bindPermission.equals(info.permission)) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500537 return info;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500538 }
539 }
540 }
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500541 return null;
Julia Reynolds0ae2b0b2016-01-14 09:58:03 -0500542 }
543
Julia Reynolds68062072018-08-06 15:38:21 -0400544 private ActivityInfo getActivityInfo(ComponentName configActivity) {
545 Intent queryIntent = new Intent();
546 queryIntent.setComponent(configActivity);
547 List<ResolveInfo> installedComponents = mPm.queryIntentActivitiesAsUser(
548 queryIntent,
549 PackageManager.GET_ACTIVITIES | PackageManager.GET_META_DATA,
550 UserHandle.getCallingUserId());
551 if (installedComponents != null) {
552 for (int i = 0, count = installedComponents.size(); i < count; i++) {
553 ResolveInfo resolveInfo = installedComponents.get(i);
554 return resolveInfo.activityInfo;
555 }
556 }
557 return null;
558 }
559
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400560 private void populateZenRule(AutomaticZenRule automaticZenRule, ZenRule rule, boolean isNew) {
561 if (isNew) {
562 rule.id = ZenModeConfig.newRuleId();
563 rule.creationTime = System.currentTimeMillis();
564 rule.component = automaticZenRule.getOwner();
Julia Reynolds68062072018-08-06 15:38:21 -0400565 rule.configurationActivity = automaticZenRule.getConfigurationActivity();
566 rule.pkg = (rule.component != null)
567 ? rule.component.getPackageName()
568 : rule.configurationActivity.getPackageName();
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400569 }
570
571 if (rule.enabled != automaticZenRule.isEnabled()) {
572 rule.snoozing = false;
573 }
574 rule.name = automaticZenRule.getName();
575 rule.condition = null;
576 rule.conditionId = automaticZenRule.getConditionId();
577 rule.enabled = automaticZenRule.isEnabled();
Beverly49ba9a62018-11-02 13:19:31 -0400578 rule.modified = automaticZenRule.isModified();
Beverly12196702018-12-12 15:05:51 -0500579 rule.zenPolicy = automaticZenRule.getZenPolicy();
Julia Reynolds4fe98d62015-10-06 16:23:41 -0400580 rule.zenMode = NotificationManager.zenModeFromInterruptionFilter(
581 automaticZenRule.getInterruptionFilter(), Global.ZEN_MODE_OFF);
582 }
583
Beverlyd4f96492017-08-02 13:36:11 -0400584 protected AutomaticZenRule createAutomaticZenRule(ZenRule rule) {
Julia Reynolds68062072018-08-06 15:38:21 -0400585 return new AutomaticZenRule(rule.name, rule.component, rule.configurationActivity,
586 rule.conditionId, rule.zenPolicy,
587 NotificationManager.zenModeToInterruptionFilter(rule.zenMode),
588 rule.enabled, rule.creationTime);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400589 }
590
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400591 public void setManualZenMode(int zenMode, Uri conditionId, String caller, String reason) {
592 setManualZenMode(zenMode, conditionId, reason, caller, true /*setRingerMode*/);
Beverly91d0a632018-07-02 16:45:00 -0400593 Settings.Secure.putInt(mContext.getContentResolver(),
594 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 0);
John Spurlocke77bb362014-04-26 10:24:59 -0400595 }
596
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400597 private void setManualZenMode(int zenMode, Uri conditionId, String reason, String caller,
John Spurlockb2278d62015-04-07 12:47:12 -0400598 boolean setRingerMode) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400599 ZenModeConfig newConfig;
600 synchronized (mConfig) {
601 if (mConfig == null) return;
602 if (!Global.isValidZenMode(zenMode)) return;
603 if (DEBUG) Log.d(TAG, "setManualZenMode " + Global.zenModeToString(zenMode)
604 + " conditionId=" + conditionId + " reason=" + reason
605 + " setRingerMode=" + setRingerMode);
606 newConfig = mConfig.copy();
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500607 if (zenMode == Global.ZEN_MODE_OFF) {
608 newConfig.manualRule = null;
609 for (ZenRule automaticRule : newConfig.automaticRules.values()) {
610 if (automaticRule.isAutomaticActive()) {
611 automaticRule.snoozing = true;
612 }
John Spurlockb2278d62015-04-07 12:47:12 -0400613 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500614 } else {
615 final ZenRule newRule = new ZenRule();
616 newRule.enabled = true;
617 newRule.zenMode = zenMode;
618 newRule.conditionId = conditionId;
Julia Reynolds44ad6ff2016-07-06 09:47:45 -0400619 newRule.enabler = caller;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500620 newConfig.manualRule = newRule;
John Spurlockb2278d62015-04-07 12:47:12 -0400621 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400622 setConfigLocked(newConfig, reason, null, setRingerMode);
John Spurlockb2278d62015-04-07 12:47:12 -0400623 }
John Spurlockb2278d62015-04-07 12:47:12 -0400624 }
625
Julia Reynolds520df6e2017-02-13 09:05:10 -0500626 void dump(ProtoOutputStream proto) {
Julia Reynolds520df6e2017-02-13 09:05:10 -0500627 proto.write(ZenModeProto.ZEN_MODE, mZenMode);
628 synchronized (mConfig) {
629 if (mConfig.manualRule != null) {
Kweku Adams99546332018-01-24 17:03:50 -0800630 mConfig.manualRule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500631 }
632 for (ZenRule rule : mConfig.automaticRules.values()) {
633 if (rule.enabled && rule.condition.state == Condition.STATE_TRUE
634 && !rule.snoozing) {
Kweku Adams99546332018-01-24 17:03:50 -0800635 rule.writeToProto(proto, ZenModeProto.ENABLED_ACTIVE_CONDITIONS);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500636 }
637 }
Kweku Adamsbc84aec2018-01-23 13:33:12 -0800638 mConfig.toNotificationPolicy().writeToProto(proto, ZenModeProto.POLICY);
Julia Reynolds520df6e2017-02-13 09:05:10 -0500639 proto.write(ZenModeProto.SUPPRESSED_EFFECTS, mSuppressedEffects);
640 }
641 }
642
John Spurlockb2278d62015-04-07 12:47:12 -0400643 public void dump(PrintWriter pw, String prefix) {
644 pw.print(prefix); pw.print("mZenMode=");
645 pw.println(Global.zenModeToString(mZenMode));
Beverlyff2df9b2018-10-10 16:54:10 -0400646 pw.print("mConsolidatedPolicy=" + mConsolidatedPolicy.toString());
John Spurlock21258a32015-05-27 18:22:55 -0400647 final int N = mConfigs.size();
648 for (int i = 0; i < N; i++) {
649 dump(pw, prefix, "mConfigs[u=" + mConfigs.keyAt(i) + "]", mConfigs.valueAt(i));
650 }
651 pw.print(prefix); pw.print("mUser="); pw.println(mUser);
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400652 synchronized (mConfig) {
653 dump(pw, prefix, "mConfig", mConfig);
654 }
Bryce Lee7219ada2016-04-08 10:54:23 -0700655
656 pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
John Spurlock1d7d2242015-04-10 08:10:22 -0400657 mFiltering.dump(pw, prefix);
John Spurlockb2278d62015-04-07 12:47:12 -0400658 mConditions.dump(pw, prefix);
659 }
660
661 private static void dump(PrintWriter pw, String prefix, String var, ZenModeConfig config) {
662 pw.print(prefix); pw.print(var); pw.print('=');
663 if (config == null) {
664 pw.println(config);
665 return;
666 }
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500667 pw.printf("allow(alarms=%b,media=%b,system=%b,calls=%b,callsFrom=%s,repeatCallers=%b,"
Julia Reynolds1f580572018-04-27 14:48:36 -0400668 + "messages=%b,messagesFrom=%s,events=%b,reminders=%b)\n",
Beverlyd6964762018-02-16 14:07:03 -0500669 config.allowAlarms, config.allowMedia, config.allowSystem,
Julia Reynolds6ee26172015-09-28 11:34:48 -0400670 config.allowCalls, ZenModeConfig.sourceToString(config.allowCallsFrom),
671 config.allowRepeatCallers, config.allowMessages,
672 ZenModeConfig.sourceToString(config.allowMessagesFrom),
Julia Reynolds1f580572018-04-27 14:48:36 -0400673 config.allowEvents, config.allowReminders);
Julia Reynoldsccc6ae62018-03-01 16:24:49 -0500674 pw.printf(" disallow(visualEffects=%s)\n", config.suppressedVisualEffects);
John Spurlockb2278d62015-04-07 12:47:12 -0400675 pw.print(prefix); pw.print(" manualRule="); pw.println(config.manualRule);
676 if (config.automaticRules.isEmpty()) return;
677 final int N = config.automaticRules.size();
678 for (int i = 0; i < N; i++) {
679 pw.print(prefix); pw.print(i == 0 ? " automaticRules=" : " ");
680 pw.println(config.automaticRules.valueAt(i));
681 }
682 }
683
Annie Meng8b646fd2019-02-01 18:46:42 +0000684 public void readXml(XmlPullParser parser, boolean forRestore, int userId)
John Spurlock35ef0a62015-05-28 11:24:10 -0400685 throws XmlPullParserException, IOException {
Beverly4e2f76c2018-03-16 15:43:49 -0400686 ZenModeConfig config = ZenModeConfig.readXml(parser);
687 String reason = "readXml";
688
John Spurlockb2278d62015-04-07 12:47:12 -0400689 if (config != null) {
John Spurlock35ef0a62015-05-28 11:24:10 -0400690 if (forRestore) {
Annie Meng8b646fd2019-02-01 18:46:42 +0000691 config.user = userId;
John Spurlock35ef0a62015-05-28 11:24:10 -0400692 config.manualRule = null; // don't restore the manual rule
Beverly4e2f76c2018-03-16 15:43:49 -0400693 }
694
Beverlyad3841a2018-07-31 11:23:35 -0400695 // booleans to determine whether to reset the rules to the default rules
696 boolean allRulesDisabled = true;
697 boolean hasDefaultRules = config.automaticRules.containsAll(
698 ZenModeConfig.DEFAULT_RULE_IDS);
699
Beverly4e2f76c2018-03-16 15:43:49 -0400700 long time = System.currentTimeMillis();
701 if (config.automaticRules != null && config.automaticRules.size() > 0) {
702 for (ZenRule automaticRule : config.automaticRules.values()) {
703 if (forRestore) {
John Spurlock995a7492015-05-28 22:13:03 -0400704 // don't restore transient state from restored automatic rules
705 automaticRule.snoozing = false;
706 automaticRule.condition = null;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500707 automaticRule.creationTime = time;
John Spurlock995a7492015-05-28 22:13:03 -0400708 }
Beverlyad3841a2018-07-31 11:23:35 -0400709
710 allRulesDisabled &= !automaticRule.enabled;
John Spurlock995a7492015-05-28 22:13:03 -0400711 }
John Spurlock35ef0a62015-05-28 11:24:10 -0400712 }
Beverly4e2f76c2018-03-16 15:43:49 -0400713
Beverlyad3841a2018-07-31 11:23:35 -0400714 if (!hasDefaultRules && allRulesDisabled
715 && (forRestore || config.version < ZenModeConfig.XML_VERSION)) {
716 // reset zen automatic rules to default on restore or upgrade if:
717 // - doesn't already have default rules and
718 // - all previous automatic rules were disabled
719 config.automaticRules = new ArrayMap<>();
Beverlyf3b92d22018-09-18 15:13:17 -0400720 for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
721 config.automaticRules.put(rule.id, rule);
722 }
Beverlyad3841a2018-07-31 11:23:35 -0400723 reason += ", reset to default rules";
724 }
725
Annie Meng8b646fd2019-02-01 18:46:42 +0000726 // Resolve user id for settings.
727 userId = userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId;
Beverlyad3841a2018-07-31 11:23:35 -0400728 if (config.version < ZenModeConfig.XML_VERSION) {
Annie Meng8b646fd2019-02-01 18:46:42 +0000729 Settings.Secure.putIntForUser(mContext.getContentResolver(),
730 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 1, userId);
Beverly301e92a2018-04-27 09:43:05 -0400731 } else {
732 // devices not restoring/upgrading already have updated zen settings
Annie Meng8b646fd2019-02-01 18:46:42 +0000733 Settings.Secure.putIntForUser(mContext.getContentResolver(),
734 Settings.Secure.ZEN_SETTINGS_UPDATED, 1, userId);
Beverly4e2f76c2018-03-16 15:43:49 -0400735 }
736 if (DEBUG) Log.d(TAG, reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500737 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400738 setConfigLocked(config, null, reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500739 }
John Spurlockb2278d62015-04-07 12:47:12 -0400740 }
741 }
742
Annie Meng8b646fd2019-02-01 18:46:42 +0000743 public void writeXml(XmlSerializer out, boolean forBackup, Integer version, int userId)
744 throws IOException {
Beverly1ef2cce2019-04-29 11:08:05 -0400745 synchronized (mConfigs) {
746 final int n = mConfigs.size();
747 for (int i = 0; i < n; i++) {
748 if (forBackup && mConfigs.keyAt(i) != userId) {
749 continue;
750 }
751 mConfigs.valueAt(i).writeXml(out, version);
John Spurlock35ef0a62015-05-28 11:24:10 -0400752 }
John Spurlock21258a32015-05-27 18:22:55 -0400753 }
John Spurlockb2278d62015-04-07 12:47:12 -0400754 }
755
Beverly174d7412018-08-22 16:34:41 -0400756 /**
757 * @return user-specified default notification policy for priority only do not disturb
758 */
John Spurlock1fc476d2015-04-14 16:05:20 -0400759 public Policy getNotificationPolicy() {
760 return getNotificationPolicy(mConfig);
761 }
762
763 private static Policy getNotificationPolicy(ZenModeConfig config) {
764 return config == null ? null : config.toNotificationPolicy();
765 }
766
Beverly174d7412018-08-22 16:34:41 -0400767 /**
768 * Sets the global notification policy used for priority only do not disturb
769 */
John Spurlock1fc476d2015-04-14 16:05:20 -0400770 public void setNotificationPolicy(Policy policy) {
771 if (policy == null || mConfig == null) return;
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500772 synchronized (mConfig) {
773 final ZenModeConfig newConfig = mConfig.copy();
774 newConfig.applyNotificationPolicy(policy);
Julia Reynolds8f056002018-07-13 15:12:29 -0400775 setConfigLocked(newConfig, null, "setNotificationPolicy");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500776 }
John Spurlock1fc476d2015-04-14 16:05:20 -0400777 }
778
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500779 /**
780 * Removes old rule instances whose owner is not installed.
781 */
782 private void cleanUpZenRules() {
783 long currentTime = System.currentTimeMillis();
784 synchronized (mConfig) {
785 final ZenModeConfig newConfig = mConfig.copy();
786 if (newConfig.automaticRules != null) {
787 for (int i = newConfig.automaticRules.size() - 1; i >= 0; i--) {
788 ZenRule rule = newConfig.automaticRules.get(newConfig.automaticRules.keyAt(i));
789 if (RULE_INSTANCE_GRACE_PERIOD < (currentTime - rule.creationTime)) {
790 try {
Julia Reynolds68062072018-08-06 15:38:21 -0400791 if (rule.pkg != null) {
792 mPm.getPackageInfo(rule.pkg, PackageManager.MATCH_ANY_USER);
793 }
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500794 } catch (PackageManager.NameNotFoundException e) {
795 newConfig.automaticRules.removeAt(i);
796 }
797 }
798 }
799 }
Julia Reynolds8f056002018-07-13 15:12:29 -0400800 setConfigLocked(newConfig, null, "cleanUpZenRules");
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500801 }
802 }
803
804 /**
805 * @return a copy of the zen mode configuration
806 */
John Spurlockb2278d62015-04-07 12:47:12 -0400807 public ZenModeConfig getConfig() {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400808 synchronized (mConfig) {
809 return mConfig.copy();
810 }
John Spurlockb2278d62015-04-07 12:47:12 -0400811 }
812
Beverlyff2df9b2018-10-10 16:54:10 -0400813 /**
814 * @return a copy of the zen mode consolidated policy
815 */
816 public Policy getConsolidatedNotificationPolicy() {
817 if (mConsolidatedPolicy == null) {
818 return null;
819 }
820 return mConsolidatedPolicy.copy();
821 }
822
Julia Reynolds8f056002018-07-13 15:12:29 -0400823 public boolean setConfigLocked(ZenModeConfig config, ComponentName triggeringComponent,
824 String reason) {
825 return setConfigLocked(config, reason, triggeringComponent, true /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -0400826 }
827
Julia Reynolds8f056002018-07-13 15:12:29 -0400828 public void setConfig(ZenModeConfig config, ComponentName triggeringComponent, String reason) {
Julia Reynolds89aeab02016-09-15 11:07:50 -0400829 synchronized (mConfig) {
Julia Reynolds8f056002018-07-13 15:12:29 -0400830 setConfigLocked(config, triggeringComponent, reason);
Julia Reynolds89aeab02016-09-15 11:07:50 -0400831 }
Eric Laurente0ced4d2015-09-30 17:44:28 -0700832 }
833
Julia Reynolds8f056002018-07-13 15:12:29 -0400834 private boolean setConfigLocked(ZenModeConfig config, String reason,
835 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400836 final long identity = Binder.clearCallingIdentity();
837 try {
838 if (config == null || !config.isValid()) {
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500839 Log.w(TAG, "Invalid config in setConfigLocked; " + config);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400840 return false;
841 }
842 if (config.user != mUser) {
843 // simply store away for background users
844 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500845 if (DEBUG) Log.d(TAG, "setConfigLocked: store config for user " + config.user);
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400846 return true;
847 }
Julia Reynolds68062072018-08-06 15:38:21 -0400848 // handle CPS backed conditions - danger! may modify config
Julia Reynolds8f056002018-07-13 15:12:29 -0400849 mConditions.evaluateConfig(config, null, false /*processSubscriptions*/);
Julia Reynolds68062072018-08-06 15:38:21 -0400850
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500851 mConfigs.put(config.user, config);
Julia Reynolds43b70cd2016-01-14 15:05:34 -0500852 if (DEBUG) Log.d(TAG, "setConfigLocked reason=" + reason, new Throwable());
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500853 ZenLog.traceConfig(reason, mConfig, config);
Julia Reynolds68062072018-08-06 15:38:21 -0400854
855 // send some broadcasts
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500856 final boolean policyChanged = !Objects.equals(getNotificationPolicy(mConfig),
857 getNotificationPolicy(config));
Julia Reynolds9a25da12016-01-06 16:19:28 -0500858 if (!config.equals(mConfig)) {
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500859 dispatchOnConfigChanged();
Beverlyff2df9b2018-10-10 16:54:10 -0400860 updateConsolidatedPolicy(reason);
Julia Reynolds5a43aaa2015-12-15 13:54:41 -0500861 }
862 if (policyChanged) {
863 dispatchOnPolicyChanged();
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400864 }
Julia Reynolds9a25da12016-01-06 16:19:28 -0500865 mConfig = config;
Julia Reynolds8f056002018-07-13 15:12:29 -0400866 mHandler.postApplyConfig(config, reason, triggeringComponent, setRingerMode);
John Spurlock21258a32015-05-27 18:22:55 -0400867 return true;
Julia Reynoldscb507b82017-09-07 13:53:40 -0400868 } catch (SecurityException e) {
869 Log.wtf(TAG, "Invalid rule in config", e);
870 return false;
Julia Reynoldsa47a27f2015-08-24 08:31:47 -0400871 } finally {
872 Binder.restoreCallingIdentity(identity);
John Spurlock21258a32015-05-27 18:22:55 -0400873 }
John Spurlockb2278d62015-04-07 12:47:12 -0400874 }
875
Julia Reynolds8f056002018-07-13 15:12:29 -0400876 private void applyConfig(ZenModeConfig config, String reason,
877 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400878 final String val = Integer.toString(config.hashCode());
879 Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
Beverly174d7412018-08-22 16:34:41 -0400880 evaluateZenMode(reason, setRingerMode);
Julia Reynolds8f056002018-07-13 15:12:29 -0400881 mConditions.evaluateConfig(config, triggeringComponent, true /*processSubscriptions*/);
Julia Reynoldsd82e9812016-04-19 13:27:41 -0400882 }
883
John Spurlockb2278d62015-04-07 12:47:12 -0400884 private int getZenModeSetting() {
885 return Global.getInt(mContext.getContentResolver(), Global.ZEN_MODE, Global.ZEN_MODE_OFF);
886 }
887
Beverly3bae4e52018-02-07 12:32:02 -0500888 @VisibleForTesting
889 protected void setZenModeSetting(int zen) {
John Spurlockb2278d62015-04-07 12:47:12 -0400890 Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zen);
Beverly3bae4e52018-02-07 12:32:02 -0500891 showZenUpgradeNotification(zen);
John Spurlockb2278d62015-04-07 12:47:12 -0400892 }
893
Julia Reynolds9b11fdb2015-07-31 09:49:55 -0400894 private int getPreviousRingerModeSetting() {
895 return Global.getInt(mContext.getContentResolver(),
896 Global.ZEN_MODE_RINGER_LEVEL, AudioManager.RINGER_MODE_NORMAL);
897 }
898
899 private void setPreviousRingerModeSetting(Integer previousRingerLevel) {
900 Global.putString(
901 mContext.getContentResolver(), Global.ZEN_MODE_RINGER_LEVEL,
902 previousRingerLevel == null ? null : Integer.toString(previousRingerLevel));
903 }
904
Beverlye4ee1cc2018-03-06 17:21:08 -0500905 @VisibleForTesting
Beverly174d7412018-08-22 16:34:41 -0400906 protected void evaluateZenMode(String reason, boolean setRingerMode) {
John Spurlockb2278d62015-04-07 12:47:12 -0400907 if (DEBUG) Log.d(TAG, "evaluateZenMode");
Beverlyff2df9b2018-10-10 16:54:10 -0400908 if (mConfig == null) return;
909 final int policyHashBefore = mConsolidatedPolicy == null ? 0
910 : mConsolidatedPolicy.hashCode();
Jason Monka9927322015-12-13 16:22:37 -0500911 final int zenBefore = mZenMode;
Julia Reynolds8ac63032015-08-31 15:19:43 -0400912 final int zen = computeZenMode();
John Spurlockb2278d62015-04-07 12:47:12 -0400913 ZenLog.traceSetZenMode(zen, reason);
914 mZenMode = zen;
915 setZenModeSetting(mZenMode);
Beverlyff2df9b2018-10-10 16:54:10 -0400916 updateConsolidatedPolicy(reason);
Beverlyd6964762018-02-16 14:07:03 -0500917 updateRingerModeAffectedStreams();
Beverlyff2df9b2018-10-10 16:54:10 -0400918 if (setRingerMode && (zen != zenBefore || (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
919 && policyHashBefore != mConsolidatedPolicy.hashCode()))) {
John Spurlock57627792014-12-11 11:29:54 -0500920 applyZenToRingerMode();
921 }
922 applyRestrictions();
Jason Monka9927322015-12-13 16:22:37 -0500923 if (zen != zenBefore) {
Julia Reynolds8ac63032015-08-31 15:19:43 -0400924 mHandler.postDispatchOnZenModeChanged();
925 }
John Spurlock57627792014-12-11 11:29:54 -0500926 }
927
John Spurlock50ced3f2015-05-11 16:00:09 -0400928 private void updateRingerModeAffectedStreams() {
929 if (mAudioManager != null) {
930 mAudioManager.updateRingerModeAffectedStreamsInternal();
931 }
932 }
933
Julia Reynolds8ac63032015-08-31 15:19:43 -0400934 private int computeZenMode() {
Beverlye4ee1cc2018-03-06 17:21:08 -0500935 if (mConfig == null) return Global.ZEN_MODE_OFF;
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400936 synchronized (mConfig) {
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400937 if (mConfig.manualRule != null) return mConfig.manualRule.zenMode;
938 int zen = Global.ZEN_MODE_OFF;
939 for (ZenRule automaticRule : mConfig.automaticRules.values()) {
940 if (automaticRule.isAutomaticActive()) {
941 if (zenSeverity(automaticRule.zenMode) > zenSeverity(zen)) {
Beverly301e92a2018-04-27 09:43:05 -0400942 // automatic rule triggered dnd and user hasn't seen update dnd dialog
Beverly91d0a632018-07-02 16:45:00 -0400943 if (Settings.Secure.getInt(mContext.getContentResolver(),
944 Settings.Secure.ZEN_SETTINGS_SUGGESTION_VIEWED, 1) == 0) {
945 Settings.Secure.putInt(mContext.getContentResolver(),
946 Settings.Secure.SHOW_ZEN_SETTINGS_SUGGESTION, 1);
Beverly301e92a2018-04-27 09:43:05 -0400947 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400948 zen = automaticRule.zenMode;
949 }
John Spurlockb2278d62015-04-07 12:47:12 -0400950 }
951 }
Julia Reynoldsaaf191c2015-10-26 15:53:28 -0400952 return zen;
John Spurlockb2278d62015-04-07 12:47:12 -0400953 }
John Spurlock8403b752014-12-10 12:47:01 -0500954 }
955
Beverly1cc502f2019-04-15 11:21:25 -0400956 private void applyCustomPolicy(ZenPolicy policy, ZenRule rule) {
957 if (rule.zenMode == NotificationManager.INTERRUPTION_FILTER_NONE) {
958 policy.apply(new ZenPolicy.Builder()
959 .disallowAllSounds()
960 .build());
961 } else if (rule.zenMode
962 == NotificationManager.INTERRUPTION_FILTER_ALARMS) {
963 policy.apply(new ZenPolicy.Builder()
964 .disallowAllSounds()
965 .allowAlarms(true)
966 .allowMedia(true)
967 .build());
968 } else {
969 policy.apply(rule.zenPolicy);
970 }
971 }
972
Beverlyff2df9b2018-10-10 16:54:10 -0400973 private void updateConsolidatedPolicy(String reason) {
974 if (mConfig == null) return;
975 synchronized (mConfig) {
976 ZenPolicy policy = new ZenPolicy();
Beverly1cc502f2019-04-15 11:21:25 -0400977 if (mConfig.manualRule != null) {
978 applyCustomPolicy(policy, mConfig.manualRule);
979 }
980
Beverlyff2df9b2018-10-10 16:54:10 -0400981 for (ZenRule automaticRule : mConfig.automaticRules.values()) {
982 if (automaticRule.isAutomaticActive()) {
Beverly1cc502f2019-04-15 11:21:25 -0400983 applyCustomPolicy(policy, automaticRule);
Beverlyff2df9b2018-10-10 16:54:10 -0400984 }
985 }
986 Policy newPolicy = mConfig.toNotificationPolicy(policy);
987 if (!Objects.equals(mConsolidatedPolicy, newPolicy)) {
988 mConsolidatedPolicy = newPolicy;
989 dispatchOnConsolidatedPolicyChanged();
990 ZenLog.traceSetConsolidatedZenPolicy(mConsolidatedPolicy, reason);
991 }
992 }
993 }
994
Beverlyf3b92d22018-09-18 15:13:17 -0400995 private void updateDefaultAutomaticRuleNames() {
996 for (ZenRule rule : mDefaultConfig.automaticRules.values()) {
997 if (ZenModeConfig.EVENTS_DEFAULT_RULE_ID.equals(rule.id)) {
998 rule.name = mContext.getResources()
999 .getString(R.string.zen_mode_default_events_name);
1000 } else if (ZenModeConfig.EVERY_NIGHT_DEFAULT_RULE_ID.equals(rule.id)) {
1001 rule.name = mContext.getResources()
1002 .getString(R.string.zen_mode_default_every_night_name);
1003 }
1004 }
Beverly30bfbca2017-10-17 14:38:20 -04001005 }
1006
Beverly04216872017-09-28 10:55:32 -04001007 @VisibleForTesting
1008 protected void applyRestrictions() {
Beverlyd820bc22018-01-11 15:28:33 -05001009 final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
Beverly925cde82018-01-23 09:31:23 -05001010 final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
Beverlyd820bc22018-01-11 15:28:33 -05001011 final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
Beverlyff2df9b2018-10-10 16:54:10 -04001012 final boolean allowCalls = mConsolidatedPolicy.allowCalls();
1013 final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
1014 final boolean allowSystem = mConsolidatedPolicy.allowSystem();
1015 final boolean allowMedia = mConsolidatedPolicy.allowMedia();
1016 final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();
John Spurlock8403b752014-12-10 12:47:01 -05001017
1018 // notification restrictions
Bryce Lee7219ada2016-04-08 10:54:23 -07001019 final boolean muteNotifications =
1020 (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
John Spurlock056c5192014-04-20 21:52:01 -04001021 // call restrictions
Beverlyd820bc22018-01-11 15:28:33 -05001022 final boolean muteCalls = zenAlarmsOnly
Beverlyff2df9b2018-10-10 16:54:10 -04001023 || (zenPriorityOnly && !allowCalls && !allowRepeatCallers)
Bryce Lee7219ada2016-04-08 10:54:23 -07001024 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
Beverly04216872017-09-28 10:55:32 -04001025 // alarm restrictions
Beverlyff2df9b2018-10-10 16:54:10 -04001026 final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
Beverlyd6964762018-02-16 14:07:03 -05001027 // media restrictions
Beverlyff2df9b2018-10-10 16:54:10 -04001028 final boolean muteMedia = zenPriorityOnly && !allowMedia;
Beverlyd6964762018-02-16 14:07:03 -05001029 // system restrictions
Beverlyff2df9b2018-10-10 16:54:10 -04001030 final boolean muteSystem = zenAlarmsOnly || (zenPriorityOnly && !allowSystem);
Julia Reynolds3fe81be2016-02-03 09:10:06 -05001031 // total silence restrictions
Beverlyff2df9b2018-10-10 16:54:10 -04001032 final boolean muteEverything = zenSilence || (zenPriorityOnly
1033 && ZenModeConfig.areAllZenBehaviorSoundsMuted(mConsolidatedPolicy));
John Spurlock25d01ee2015-06-03 12:17:46 -04001034
Jean-Michel Trivie743bda2016-09-09 11:56:48 -07001035 for (int usage : AudioAttributes.SDK_USAGES) {
1036 final int suppressionBehavior = AudioAttributes.SUPPRESSIBLE_USAGES.get(usage);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -07001037 if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NEVER) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001038 applyRestrictions(zenPriorityOnly, false /*mute*/, usage);
Jean-Michel Trivi7a84eae2017-06-20 14:58:18 -07001039 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_NOTIFICATION) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001040 applyRestrictions(zenPriorityOnly, muteNotifications || muteEverything, usage);
Jean-Michel Trivie743bda2016-09-09 11:56:48 -07001041 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_CALL) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001042 applyRestrictions(zenPriorityOnly, muteCalls || muteEverything, usage);
Beverly04216872017-09-28 10:55:32 -04001043 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_ALARM) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001044 applyRestrictions(zenPriorityOnly, muteAlarms || muteEverything, usage);
Beverlyd6964762018-02-16 14:07:03 -05001045 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_MEDIA) {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001046 applyRestrictions(zenPriorityOnly, muteMedia || muteEverything, usage);
Beverlyd6964762018-02-16 14:07:03 -05001047 } else if (suppressionBehavior == AudioAttributes.SUPPRESSIBLE_SYSTEM) {
Beverly738bffd2018-03-12 10:46:17 -04001048 if (usage == AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) {
1049 // normally DND will only restrict touch sounds, not haptic feedback/vibrations
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001050 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage,
Beverly738bffd2018-03-12 10:46:17 -04001051 AppOpsManager.OP_PLAY_AUDIO);
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001052 applyRestrictions(zenPriorityOnly, false, usage, AppOpsManager.OP_VIBRATE);
Beverly738bffd2018-03-12 10:46:17 -04001053 } else {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001054 applyRestrictions(zenPriorityOnly, muteSystem || muteEverything, usage);
Beverly738bffd2018-03-12 10:46:17 -04001055 }
Julia Reynolds3fe81be2016-02-03 09:10:06 -05001056 } else {
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001057 applyRestrictions(zenPriorityOnly, muteEverything, usage);
Julia Reynolds3fe81be2016-02-03 09:10:06 -05001058 }
1059 }
John Spurlock8403b752014-12-10 12:47:01 -05001060 }
John Spurlockae641c92014-06-30 18:11:40 -04001061
Beverlye2d9a232017-11-08 18:14:59 -05001062
Beverly04216872017-09-28 10:55:32 -04001063 @VisibleForTesting
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001064 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage, int code) {
1065 final long ident = Binder.clearCallingIdentity();
1066 try {
1067 mAppOps.setRestriction(code, usage,
1068 mute ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
1069 zenPriorityOnly ? mPriorityOnlyDndExemptPackages : null);
1070 } finally {
1071 Binder.restoreCallingIdentity(ident);
Dianne Hackbornbf1b57d2018-03-07 12:42:47 -08001072 }
John Spurlock056c5192014-04-20 21:52:01 -04001073 }
1074
Beverly85f52412018-02-27 10:41:13 -05001075 @VisibleForTesting
Julia Reynoldse99db5a2019-04-16 12:50:04 -04001076 protected void applyRestrictions(boolean zenPriorityOnly, boolean mute, int usage) {
1077 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_VIBRATE);
1078 applyRestrictions(zenPriorityOnly, mute, usage, AppOpsManager.OP_PLAY_AUDIO);
Beverly738bffd2018-03-12 10:46:17 -04001079 }
1080
1081
1082 @VisibleForTesting
Beverly85f52412018-02-27 10:41:13 -05001083 protected void applyZenToRingerMode() {
John Spurlock661f2cf2014-11-17 10:29:10 -05001084 if (mAudioManager == null) return;
John Spurlock661f2cf2014-11-17 10:29:10 -05001085 // force the ringer mode into compliance
1086 final int ringerModeInternal = mAudioManager.getRingerModeInternal();
1087 int newRingerModeInternal = ringerModeInternal;
John Spurlock57627792014-12-11 11:29:54 -05001088 switch (mZenMode) {
John Spurlock661f2cf2014-11-17 10:29:10 -05001089 case Global.ZEN_MODE_NO_INTERRUPTIONS:
John Spurlock4f1163c2015-04-02 17:41:21 -04001090 case Global.ZEN_MODE_ALARMS:
John Spurlock661f2cf2014-11-17 10:29:10 -05001091 if (ringerModeInternal != AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001092 setPreviousRingerModeSetting(ringerModeInternal);
John Spurlock661f2cf2014-11-17 10:29:10 -05001093 newRingerModeInternal = AudioManager.RINGER_MODE_SILENT;
John Spurlock8c01d882014-07-28 13:37:13 -04001094 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001095 break;
1096 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
Beverly9e4214d2018-03-26 11:10:10 -04001097 // do not apply zen to ringer, streams zen muted in AudioService
Beverly925cde82018-01-23 09:31:23 -05001098 break;
John Spurlock661f2cf2014-11-17 10:29:10 -05001099 case Global.ZEN_MODE_OFF:
1100 if (ringerModeInternal == AudioManager.RINGER_MODE_SILENT) {
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001101 newRingerModeInternal = getPreviousRingerModeSetting();
1102 setPreviousRingerModeSetting(null);
John Spurlock661f2cf2014-11-17 10:29:10 -05001103 }
1104 break;
John Spurlock8c01d882014-07-28 13:37:13 -04001105 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001106 if (newRingerModeInternal != -1) {
1107 mAudioManager.setRingerModeInternal(newRingerModeInternal, TAG);
1108 }
1109 }
1110
John Spurlock1c923a32014-04-27 16:42:29 -04001111 private void dispatchOnConfigChanged() {
1112 for (Callback callback : mCallbacks) {
1113 callback.onConfigChanged();
1114 }
1115 }
1116
John Spurlock1fc476d2015-04-14 16:05:20 -04001117 private void dispatchOnPolicyChanged() {
1118 for (Callback callback : mCallbacks) {
1119 callback.onPolicyChanged();
1120 }
1121 }
1122
Beverlyff2df9b2018-10-10 16:54:10 -04001123 private void dispatchOnConsolidatedPolicyChanged() {
1124 for (Callback callback : mCallbacks) {
1125 callback.onConsolidatedPolicyChanged();
1126 }
1127 }
1128
John Spurlock1c923a32014-04-27 16:42:29 -04001129 private void dispatchOnZenModeChanged() {
1130 for (Callback callback : mCallbacks) {
1131 callback.onZenModeChanged();
1132 }
1133 }
1134
Julia Reynolds3ec93302019-07-11 15:27:31 -04001135 private void dispatchOnAutomaticRuleStatusChanged(int userId, String pkg, String id,
1136 int status) {
1137 for (Callback callback : mCallbacks) {
1138 callback.onAutomaticRuleStatusChanged(userId, pkg, id, status);
1139 }
1140 }
1141
John Spurlockb2278d62015-04-07 12:47:12 -04001142 private ZenModeConfig readDefaultConfig(Resources resources) {
1143 XmlResourceParser parser = null;
1144 try {
1145 parser = resources.getXml(R.xml.default_zen_mode_config);
1146 while (parser.next() != XmlPullParser.END_DOCUMENT) {
Julia Reynolds206c7e92016-09-15 10:38:03 -04001147 final ZenModeConfig config = ZenModeConfig.readXml(parser);
John Spurlockb2278d62015-04-07 12:47:12 -04001148 if (config != null) return config;
1149 }
1150 } catch (Exception e) {
1151 Log.w(TAG, "Error reading default zen mode config from resource", e);
1152 } finally {
1153 IoUtils.closeQuietly(parser);
1154 }
1155 return new ZenModeConfig();
1156 }
1157
John Spurlockb2278d62015-04-07 12:47:12 -04001158 private static int zenSeverity(int zen) {
1159 switch (zen) {
1160 case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: return 1;
1161 case Global.ZEN_MODE_ALARMS: return 2;
1162 case Global.ZEN_MODE_NO_INTERRUPTIONS: return 3;
1163 default: return 0;
1164 }
1165 }
1166
Beverly85f52412018-02-27 10:41:13 -05001167 @VisibleForTesting
1168 protected final class RingerModeDelegate implements AudioManagerInternal.RingerModeDelegate {
John Spurlockb2278d62015-04-07 12:47:12 -04001169 @Override
1170 public String toString() {
1171 return TAG;
1172 }
1173
1174 @Override
1175 public int onSetRingerModeInternal(int ringerModeOld, int ringerModeNew, String caller,
1176 int ringerModeExternal, VolumePolicy policy) {
1177 final boolean isChange = ringerModeOld != ringerModeNew;
1178
1179 int ringerModeExternalOut = ringerModeNew;
1180
Beverlye4ee1cc2018-03-06 17:21:08 -05001181 if (mZenMode == Global.ZEN_MODE_OFF
1182 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1183 && !ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig))) {
1184 // in priority only with ringer not muted, save ringer mode changes
1185 // in dnd off, save ringer mode changes
1186 setPreviousRingerModeSetting(ringerModeNew);
1187 }
John Spurlockb2278d62015-04-07 12:47:12 -04001188 int newZen = -1;
1189 switch (ringerModeNew) {
1190 case AudioManager.RINGER_MODE_SILENT:
1191 if (isChange && policy.doNotDisturbWhenSilent) {
Beverly925cde82018-01-23 09:31:23 -05001192 if (mZenMode == Global.ZEN_MODE_OFF) {
Julia Reynoldsf3252be2018-01-17 09:26:21 -05001193 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
John Spurlockb2278d62015-04-07 12:47:12 -04001194 }
Julia Reynolds9b11fdb2015-07-31 09:49:55 -04001195 setPreviousRingerModeSetting(ringerModeOld);
John Spurlockb2278d62015-04-07 12:47:12 -04001196 }
1197 break;
1198 case AudioManager.RINGER_MODE_VIBRATE:
1199 case AudioManager.RINGER_MODE_NORMAL:
1200 if (isChange && ringerModeOld == AudioManager.RINGER_MODE_SILENT
1201 && (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS
Beverly925cde82018-01-23 09:31:23 -05001202 || mZenMode == Global.ZEN_MODE_ALARMS
1203 || (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1204 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(
Beverlyd6964762018-02-16 14:07:03 -05001205 mConfig)))) {
John Spurlockb2278d62015-04-07 12:47:12 -04001206 newZen = Global.ZEN_MODE_OFF;
1207 } else if (mZenMode != Global.ZEN_MODE_OFF) {
1208 ringerModeExternalOut = AudioManager.RINGER_MODE_SILENT;
1209 }
1210 break;
1211 }
Beverly85f52412018-02-27 10:41:13 -05001212
John Spurlockb2278d62015-04-07 12:47:12 -04001213 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001214 setManualZenMode(newZen, null, "ringerModeInternal", null,
1215 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001216 }
John Spurlockb2278d62015-04-07 12:47:12 -04001217 if (isChange || newZen != -1 || ringerModeExternal != ringerModeExternalOut) {
1218 ZenLog.traceSetRingerModeInternal(ringerModeOld, ringerModeNew, caller,
1219 ringerModeExternal, ringerModeExternalOut);
1220 }
1221 return ringerModeExternalOut;
1222 }
1223
1224 @Override
1225 public int onSetRingerModeExternal(int ringerModeOld, int ringerModeNew, String caller,
1226 int ringerModeInternal, VolumePolicy policy) {
1227 int ringerModeInternalOut = ringerModeNew;
1228 final boolean isChange = ringerModeOld != ringerModeNew;
1229 final boolean isVibrate = ringerModeInternal == AudioManager.RINGER_MODE_VIBRATE;
1230
1231 int newZen = -1;
1232 switch (ringerModeNew) {
1233 case AudioManager.RINGER_MODE_SILENT:
1234 if (isChange) {
1235 if (mZenMode == Global.ZEN_MODE_OFF) {
Julia Reynoldsf3252be2018-01-17 09:26:21 -05001236 newZen = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
John Spurlockb2278d62015-04-07 12:47:12 -04001237 }
1238 ringerModeInternalOut = isVibrate ? AudioManager.RINGER_MODE_VIBRATE
John Spurlock05715ec2015-05-13 11:19:19 -04001239 : AudioManager.RINGER_MODE_SILENT;
John Spurlockb2278d62015-04-07 12:47:12 -04001240 } else {
1241 ringerModeInternalOut = ringerModeInternal;
1242 }
1243 break;
1244 case AudioManager.RINGER_MODE_VIBRATE:
1245 case AudioManager.RINGER_MODE_NORMAL:
1246 if (mZenMode != Global.ZEN_MODE_OFF) {
1247 newZen = Global.ZEN_MODE_OFF;
1248 }
1249 break;
1250 }
1251 if (newZen != -1) {
Julia Reynolds44ad6ff2016-07-06 09:47:45 -04001252 setManualZenMode(newZen, null, "ringerModeExternal", caller,
1253 false /*setRingerMode*/);
John Spurlockb2278d62015-04-07 12:47:12 -04001254 }
1255
1256 ZenLog.traceSetRingerModeExternal(ringerModeOld, ringerModeNew, caller,
1257 ringerModeInternal, ringerModeInternalOut);
1258 return ringerModeInternalOut;
1259 }
John Spurlockd9c75db2015-04-28 11:19:13 -04001260
1261 @Override
1262 public boolean canVolumeDownEnterSilent() {
1263 return mZenMode == Global.ZEN_MODE_OFF;
1264 }
John Spurlock50ced3f2015-05-11 16:00:09 -04001265
1266 @Override
1267 public int getRingerModeAffectedStreams(int streams) {
Beverlyd6964762018-02-16 14:07:03 -05001268 // ringtone and notification streams are always affected by ringer mode
1269 // system stream is affected by ringer mode when not in priority-only
John Spurlock50ced3f2015-05-11 16:00:09 -04001270 streams |= (1 << AudioSystem.STREAM_RING) |
Beverlyd6964762018-02-16 14:07:03 -05001271 (1 << AudioSystem.STREAM_NOTIFICATION) |
1272 (1 << AudioSystem.STREAM_SYSTEM);
John Spurlock50ced3f2015-05-11 16:00:09 -04001273
John Spurlock50ced3f2015-05-11 16:00:09 -04001274 if (mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS) {
Beverly925cde82018-01-23 09:31:23 -05001275 // alarm and music streams affected by ringer mode when in total silence
John Spurlock50ced3f2015-05-11 16:00:09 -04001276 streams |= (1 << AudioSystem.STREAM_ALARM) |
Beverlyd6964762018-02-16 14:07:03 -05001277 (1 << AudioSystem.STREAM_MUSIC);
John Spurlock50ced3f2015-05-11 16:00:09 -04001278 } else {
1279 streams &= ~((1 << AudioSystem.STREAM_ALARM) |
Beverlyd6964762018-02-16 14:07:03 -05001280 (1 << AudioSystem.STREAM_MUSIC));
1281 }
1282
1283 if (mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS
1284 && ZenModeConfig.areAllPriorityOnlyNotificationZenSoundsMuted(mConfig)) {
1285 // system stream is not affected by ringer mode in priority only when the ringer
1286 // is zen muted (all other notification categories are muted)
1287 streams &= ~(1 << AudioSystem.STREAM_SYSTEM);
1288 } else {
1289 streams |= (1 << AudioSystem.STREAM_SYSTEM);
John Spurlock50ced3f2015-05-11 16:00:09 -04001290 }
1291 return streams;
1292 }
John Spurlockb2278d62015-04-07 12:47:12 -04001293 }
1294
1295 private final class SettingsObserver extends ContentObserver {
John Spurlock056c5192014-04-20 21:52:01 -04001296 private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
1297
1298 public SettingsObserver(Handler handler) {
1299 super(handler);
1300 }
1301
1302 public void observe() {
1303 final ContentResolver resolver = mContext.getContentResolver();
1304 resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
1305 update(null);
1306 }
1307
1308 @Override
1309 public void onChange(boolean selfChange, Uri uri) {
1310 update(uri);
1311 }
1312
1313 public void update(Uri uri) {
1314 if (ZEN_MODE.equals(uri)) {
John Spurlockb2278d62015-04-07 12:47:12 -04001315 if (mZenMode != getZenModeSetting()) {
1316 if (DEBUG) Log.d(TAG, "Fixing zen mode setting");
1317 setZenModeSetting(mZenMode);
1318 }
John Spurlock056c5192014-04-20 21:52:01 -04001319 }
1320 }
1321 }
1322
Beverly3bae4e52018-02-07 12:32:02 -05001323 private void showZenUpgradeNotification(int zen) {
Nicka485ec62018-07-03 11:32:39 -07001324 final boolean isWatch = mContext.getPackageManager().hasSystemFeature(
1325 PackageManager.FEATURE_WATCH);
Beverly3bae4e52018-02-07 12:32:02 -05001326 final boolean showNotification = mIsBootComplete
Julia Reynolds76bfa602018-04-23 09:38:47 -04001327 && zen != Global.ZEN_MODE_OFF
Nicka485ec62018-07-03 11:32:39 -07001328 && !isWatch
Beverly9087cd12018-09-21 15:30:49 -04001329 && Settings.Secure.getInt(mContext.getContentResolver(),
Beverly6c60b902018-08-17 10:10:46 -04001330 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0) != 0
Beverly9087cd12018-09-21 15:30:49 -04001331 && Settings.Secure.getInt(mContext.getContentResolver(),
Beverly6c60b902018-08-17 10:10:46 -04001332 Settings.Secure.ZEN_SETTINGS_UPDATED, 0) != 1;
Beverly3bae4e52018-02-07 12:32:02 -05001333
Nicka485ec62018-07-03 11:32:39 -07001334 if (isWatch) {
Beverly9087cd12018-09-21 15:30:49 -04001335 Settings.Secure.putInt(mContext.getContentResolver(),
Beverly91d0a632018-07-02 16:45:00 -04001336 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Nicka485ec62018-07-03 11:32:39 -07001337 }
1338
Beverly3bae4e52018-02-07 12:32:02 -05001339 if (showNotification) {
1340 mNotificationManager.notify(TAG, SystemMessage.NOTE_ZEN_UPGRADE,
1341 createZenUpgradeNotification());
Beverly91d0a632018-07-02 16:45:00 -04001342 Settings.Secure.putInt(mContext.getContentResolver(),
1343 Settings.Secure.SHOW_ZEN_UPGRADE_NOTIFICATION, 0);
Beverly3bae4e52018-02-07 12:32:02 -05001344 }
1345 }
1346
1347 @VisibleForTesting
1348 protected Notification createZenUpgradeNotification() {
Beverly3bae4e52018-02-07 12:32:02 -05001349 final Bundle extras = new Bundle();
1350 extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
1351 mContext.getResources().getString(R.string.global_action_settings));
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001352 int title = R.string.zen_upgrade_notification_title;
1353 int content = R.string.zen_upgrade_notification_content;
Julia Reynolds76bfa602018-04-23 09:38:47 -04001354 int drawable = R.drawable.ic_zen_24dp;
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001355 if (NotificationManager.Policy.areAllVisualEffectsSuppressed(
Beverlyff2df9b2018-10-10 16:54:10 -04001356 getConsolidatedNotificationPolicy().suppressedVisualEffects)) {
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001357 title = R.string.zen_upgrade_notification_visd_title;
1358 content = R.string.zen_upgrade_notification_visd_content;
Julia Reynolds76bfa602018-04-23 09:38:47 -04001359 drawable = R.drawable.ic_dnd_block_notifications;
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001360 }
Julia Reynolds76bfa602018-04-23 09:38:47 -04001361
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001362 Intent onboardingIntent = new Intent(Settings.ZEN_MODE_ONBOARDING);
1363 onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001364 return new Notification.Builder(mContext, SystemNotificationChannels.DO_NOT_DISTURB)
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001365 .setAutoCancel(true)
Beverlyd8b15ee2018-02-13 14:37:38 -05001366 .setSmallIcon(R.drawable.ic_settings_24dp)
Julia Reynolds76bfa602018-04-23 09:38:47 -04001367 .setLargeIcon(Icon.createWithResource(mContext, drawable))
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001368 .setContentTitle(mContext.getResources().getString(title))
1369 .setContentText(mContext.getResources().getString(content))
Julia Reynolds9aa1c9e2018-04-09 11:31:15 -04001370 .setContentIntent(PendingIntent.getActivity(mContext, 0, onboardingIntent,
1371 PendingIntent.FLAG_UPDATE_CURRENT))
Beverly3bae4e52018-02-07 12:32:02 -05001372 .setAutoCancel(true)
1373 .setLocalOnly(true)
1374 .addExtras(extras)
Julia Reynolds0b8455d2018-03-14 11:38:44 -04001375 .setStyle(new Notification.BigTextStyle())
Beverly3bae4e52018-02-07 12:32:02 -05001376 .build();
1377 }
1378
Chris Wren98d235b2015-05-27 18:25:17 -04001379 private final class Metrics extends Callback {
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001380 private static final String COUNTER_MODE_PREFIX = "dnd_mode_";
1381 private static final String COUNTER_TYPE_PREFIX = "dnd_type_";
1382 private static final int DND_OFF = 0;
1383 private static final int DND_ON_MANUAL = 1;
1384 private static final int DND_ON_AUTOMATIC = 2;
1385 private static final String COUNTER_RULE = "dnd_rule_count";
Chris Wren98d235b2015-05-27 18:25:17 -04001386 private static final long MINIMUM_LOG_PERIOD_MS = 60 * 1000;
1387
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001388 // Total silence, alarms only, priority only
Chris Wren98d235b2015-05-27 18:25:17 -04001389 private int mPreviousZenMode = -1;
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001390 private long mModeLogTimeMs = 0L;
1391
1392 private int mNumZenRules = -1;
1393 private long mRuleCountLogTime = 0L;
1394
1395 // automatic (1) vs manual (0) vs dnd off (2)
1396 private int mPreviousZenType = -1;
1397 private long mTypeLogTimeMs = 0L;
Chris Wren98d235b2015-05-27 18:25:17 -04001398
1399 @Override
1400 void onZenModeChanged() {
1401 emit();
1402 }
1403
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001404 @Override
1405 void onConfigChanged() {
1406 emit();
1407 }
1408
Chris Wren98d235b2015-05-27 18:25:17 -04001409 private void emit() {
1410 mHandler.postMetricsTimer();
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001411 emitZenMode();
1412 emitRules();
1413 emitDndType();
1414 }
1415
1416 private void emitZenMode() {
Chris Wren98d235b2015-05-27 18:25:17 -04001417 final long now = SystemClock.elapsedRealtime();
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001418 final long since = (now - mModeLogTimeMs);
Chris Wren98d235b2015-05-27 18:25:17 -04001419 if (mPreviousZenMode != mZenMode || since > MINIMUM_LOG_PERIOD_MS) {
1420 if (mPreviousZenMode != -1) {
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001421 MetricsLogger.count(
1422 mContext, COUNTER_MODE_PREFIX + mPreviousZenMode, (int) since);
Chris Wren98d235b2015-05-27 18:25:17 -04001423 }
1424 mPreviousZenMode = mZenMode;
Julia Reynolds3dfdde02018-10-08 09:17:56 -04001425 mModeLogTimeMs = now;
1426 }
1427 }
1428
1429 private void emitRules() {
1430 final long now = SystemClock.elapsedRealtime();
1431 final long since = (now - mRuleCountLogTime);
1432 synchronized (mConfig) {
1433 int numZenRules = mConfig.automaticRules.size();
1434 if (mNumZenRules != numZenRules
1435 || since > MINIMUM_LOG_PERIOD_MS) {
1436 if (mNumZenRules != -1) {
1437 MetricsLogger.count(mContext, COUNTER_RULE,
1438 numZenRules - mNumZenRules);
1439 }
1440 mNumZenRules = numZenRules;
1441
1442 mRuleCountLogTime = since;
1443 }
1444 }
1445 }
1446
1447 private void emitDndType() {
1448 final long now = SystemClock.elapsedRealtime();
1449 final long since = (now - mTypeLogTimeMs);
1450 synchronized (mConfig) {
1451 boolean dndOn = mZenMode != Global.ZEN_MODE_OFF;
1452 int zenType = !dndOn ? DND_OFF
1453 : (mConfig.manualRule != null) ? DND_ON_MANUAL : DND_ON_AUTOMATIC;
1454 if (zenType != mPreviousZenType
1455 || since > MINIMUM_LOG_PERIOD_MS) {
1456 if (mPreviousZenType != -1) {
1457 MetricsLogger.count(
1458 mContext, COUNTER_TYPE_PREFIX + mPreviousZenType, (int) since);
1459 }
1460 mTypeLogTimeMs = now;
1461 mPreviousZenType = zenType;
1462 }
Chris Wren98d235b2015-05-27 18:25:17 -04001463 }
1464 }
1465 }
1466
John Spurlockb2278d62015-04-07 12:47:12 -04001467 private final class H extends Handler {
John Spurlock57627792014-12-11 11:29:54 -05001468 private static final int MSG_DISPATCH = 1;
Chris Wren98d235b2015-05-27 18:25:17 -04001469 private static final int MSG_METRICS = 2;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001470 private static final int MSG_APPLY_CONFIG = 4;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001471
1472 private final class ConfigMessageData {
1473 public final ZenModeConfig config;
Julia Reynolds8f056002018-07-13 15:12:29 -04001474 public ComponentName triggeringComponent;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001475 public final String reason;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001476 public final boolean setRingerMode;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001477
Julia Reynolds8f056002018-07-13 15:12:29 -04001478 ConfigMessageData(ZenModeConfig config, String reason,
1479 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001480 this.config = config;
1481 this.reason = reason;
1482 this.setRingerMode = setRingerMode;
Julia Reynolds8f056002018-07-13 15:12:29 -04001483 this.triggeringComponent = triggeringComponent;
Eric Laurente0ced4d2015-09-30 17:44:28 -07001484 }
1485 }
Chris Wren98d235b2015-05-27 18:25:17 -04001486
1487 private static final long METRICS_PERIOD_MS = 6 * 60 * 60 * 1000;
John Spurlock661f2cf2014-11-17 10:29:10 -05001488
1489 private H(Looper looper) {
1490 super(looper);
John Spurlock056c5192014-04-20 21:52:01 -04001491 }
John Spurlock661f2cf2014-11-17 10:29:10 -05001492
John Spurlock57627792014-12-11 11:29:54 -05001493 private void postDispatchOnZenModeChanged() {
1494 removeMessages(MSG_DISPATCH);
1495 sendEmptyMessage(MSG_DISPATCH);
John Spurlock661f2cf2014-11-17 10:29:10 -05001496 }
1497
Chris Wren98d235b2015-05-27 18:25:17 -04001498 private void postMetricsTimer() {
1499 removeMessages(MSG_METRICS);
1500 sendEmptyMessageDelayed(MSG_METRICS, METRICS_PERIOD_MS);
1501 }
1502
Julia Reynolds8f056002018-07-13 15:12:29 -04001503 private void postApplyConfig(ZenModeConfig config, String reason,
1504 ComponentName triggeringComponent, boolean setRingerMode) {
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001505 sendMessage(obtainMessage(MSG_APPLY_CONFIG,
Julia Reynolds8f056002018-07-13 15:12:29 -04001506 new ConfigMessageData(config, reason, triggeringComponent, setRingerMode)));
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001507 }
1508
John Spurlock661f2cf2014-11-17 10:29:10 -05001509 @Override
1510 public void handleMessage(Message msg) {
John Spurlock57627792014-12-11 11:29:54 -05001511 switch (msg.what) {
1512 case MSG_DISPATCH:
1513 dispatchOnZenModeChanged();
John Spurlock661f2cf2014-11-17 10:29:10 -05001514 break;
Chris Wren98d235b2015-05-27 18:25:17 -04001515 case MSG_METRICS:
1516 mMetrics.emit();
1517 break;
Julia Reynoldsd82e9812016-04-19 13:27:41 -04001518 case MSG_APPLY_CONFIG:
1519 ConfigMessageData applyConfigData = (ConfigMessageData) msg.obj;
1520 applyConfig(applyConfigData.config, applyConfigData.reason,
Julia Reynolds8f056002018-07-13 15:12:29 -04001521 applyConfigData.triggeringComponent, applyConfigData.setRingerMode);
John Spurlock661f2cf2014-11-17 10:29:10 -05001522 }
1523 }
1524 }
John Spurlock056c5192014-04-20 21:52:01 -04001525
John Spurlock1c923a32014-04-27 16:42:29 -04001526 public static class Callback {
1527 void onConfigChanged() {}
1528 void onZenModeChanged() {}
John Spurlock1fc476d2015-04-14 16:05:20 -04001529 void onPolicyChanged() {}
Beverlyff2df9b2018-10-10 16:54:10 -04001530 void onConsolidatedPolicyChanged() {}
Julia Reynolds3ec93302019-07-11 15:27:31 -04001531 void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {}
John Spurlock056c5192014-04-20 21:52:01 -04001532 }
John Spurlock056c5192014-04-20 21:52:01 -04001533}