blob: 2031b27c93f297c6abecf44c4c1c0ab69380957a [file] [log] [blame]
John Spurlockaf8d6c42014-05-07 17:49:08 -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.systemui.statusbar.policy;
18
John Spurlockd9c75db2015-04-28 11:19:13 -040019import android.app.ActivityManager;
John Spurlock89f060a2014-07-16 21:03:15 -040020import android.app.AlarmManager;
John Spurlockb4782522014-08-22 14:54:46 -040021import android.app.NotificationManager;
John Spurlock89f060a2014-07-16 21:03:15 -040022import android.content.BroadcastReceiver;
John Spurlockb4782522014-08-22 14:54:46 -040023import android.content.ComponentName;
John Spurlock45601d62014-08-07 17:40:50 -040024import android.content.ContentResolver;
John Spurlockaf8d6c42014-05-07 17:49:08 -040025import android.content.Context;
John Spurlock89f060a2014-07-16 21:03:15 -040026import android.content.Intent;
27import android.content.IntentFilter;
John Spurlock45601d62014-08-07 17:40:50 -040028import android.database.ContentObserver;
John Spurlockaf8d6c42014-05-07 17:49:08 -040029import android.net.Uri;
30import android.os.Handler;
John Spurlock89f060a2014-07-16 21:03:15 -040031import android.os.UserHandle;
Jason Monkf0a60dd2015-06-30 10:54:48 -040032import android.os.UserManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040033import android.provider.Settings.Global;
John Spurlock45601d62014-08-07 17:40:50 -040034import android.provider.Settings.Secure;
John Spurlockaf8d6c42014-05-07 17:49:08 -040035import android.service.notification.Condition;
John Spurlock856edeb2014-06-01 20:36:47 -040036import android.service.notification.ZenModeConfig;
John Spurlockb2278d62015-04-07 12:47:12 -040037import android.service.notification.ZenModeConfig.ZenRule;
John Spurlock89f060a2014-07-16 21:03:15 -040038import android.util.Log;
Beverly80313ca2018-05-10 16:43:52 -040039import android.util.Slog;
John Spurlockaf8d6c42014-05-07 17:49:08 -040040
Julia Reynolds9cf17562018-03-14 09:49:35 -040041import com.android.internal.annotations.VisibleForTesting;
John Spurlockaf8d6c42014-05-07 17:49:08 -040042import com.android.systemui.qs.GlobalSetting;
Jason Monk9c7844c2017-01-18 15:21:53 -050043import com.android.systemui.settings.CurrentUserTracker;
Jason Monkf66d3772017-05-30 14:31:51 -040044import com.android.systemui.util.Utils;
John Spurlockaf8d6c42014-05-07 17:49:08 -040045
46import java.util.ArrayList;
47import java.util.LinkedHashMap;
John Spurlockb2278d62015-04-07 12:47:12 -040048import java.util.Objects;
John Spurlockaf8d6c42014-05-07 17:49:08 -040049
50/** Platform implementation of the zen mode controller. **/
Jason Monk9c7844c2017-01-18 15:21:53 -050051public class ZenModeControllerImpl extends CurrentUserTracker implements ZenModeController {
John Spurlock89f060a2014-07-16 21:03:15 -040052 private static final String TAG = "ZenModeController";
53 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlockaf8d6c42014-05-07 17:49:08 -040054
55 private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
56 private final Context mContext;
John Spurlock856edeb2014-06-01 20:36:47 -040057 private final GlobalSetting mModeSetting;
58 private final GlobalSetting mConfigSetting;
John Spurlockcdb57ae2015-02-11 19:04:11 -050059 private final NotificationManager mNoMan;
John Spurlockaf8d6c42014-05-07 17:49:08 -040060 private final LinkedHashMap<Uri, Condition> mConditions = new LinkedHashMap<Uri, Condition>();
John Spurlock89f060a2014-07-16 21:03:15 -040061 private final AlarmManager mAlarmManager;
John Spurlock45601d62014-08-07 17:40:50 -040062 private final SetupObserver mSetupObserver;
Jason Monkf0a60dd2015-06-30 10:54:48 -040063 private final UserManager mUserManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040064
John Spurlock89f060a2014-07-16 21:03:15 -040065 private int mUserId;
John Spurlock8b0249d2014-07-17 15:53:32 -040066 private boolean mRegistered;
John Spurlockb2278d62015-04-07 12:47:12 -040067 private ZenModeConfig mConfig;
Julia Reynolds9cf17562018-03-14 09:49:35 -040068 private int mZenMode;
John Spurlockaf8d6c42014-05-07 17:49:08 -040069
70 public ZenModeControllerImpl(Context context, Handler handler) {
Jason Monk9c7844c2017-01-18 15:21:53 -050071 super(context);
John Spurlockaf8d6c42014-05-07 17:49:08 -040072 mContext = context;
John Spurlock856edeb2014-06-01 20:36:47 -040073 mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
John Spurlockaf8d6c42014-05-07 17:49:08 -040074 @Override
75 protected void handleValueChanged(int value) {
Julia Reynolds9cf17562018-03-14 09:49:35 -040076 updateZenMode(value);
John Spurlockae641c92014-06-30 18:11:40 -040077 fireZenChanged(value);
John Spurlockaf8d6c42014-05-07 17:49:08 -040078 }
79 };
John Spurlock856edeb2014-06-01 20:36:47 -040080 mConfigSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE_CONFIG_ETAG) {
81 @Override
82 protected void handleValueChanged(int value) {
John Spurlockb2278d62015-04-07 12:47:12 -040083 updateZenModeConfig();
John Spurlock856edeb2014-06-01 20:36:47 -040084 }
85 };
John Spurlockb2278d62015-04-07 12:47:12 -040086 mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
87 mConfig = mNoMan.getZenModeConfig();
John Spurlock856edeb2014-06-01 20:36:47 -040088 mModeSetting.setListening(true);
Julia Reynolds9cf17562018-03-14 09:49:35 -040089 updateZenMode(mModeSetting.getValue());
John Spurlock856edeb2014-06-01 20:36:47 -040090 mConfigSetting.setListening(true);
Julia Reynolds9cf17562018-03-14 09:49:35 -040091 updateZenModeConfig();
John Spurlock89f060a2014-07-16 21:03:15 -040092 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
John Spurlock45601d62014-08-07 17:40:50 -040093 mSetupObserver = new SetupObserver(handler);
94 mSetupObserver.register();
Jason Monkf0a60dd2015-06-30 10:54:48 -040095 mUserManager = context.getSystemService(UserManager.class);
Jason Monk9c7844c2017-01-18 15:21:53 -050096 startTracking();
Jason Monkf0a60dd2015-06-30 10:54:48 -040097 }
98
99 @Override
100 public boolean isVolumeRestricted() {
101 return mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME,
102 new UserHandle(mUserId));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400103 }
104
105 @Override
Julia Reynolds9cf17562018-03-14 09:49:35 -0400106 public boolean areNotificationsHiddenInShade() {
107 if (mZenMode != Global.ZEN_MODE_OFF) {
108 return (mConfig.suppressedVisualEffects & NotificationManager.Policy
109 .SUPPRESSED_EFFECT_NOTIFICATION_LIST) != 0;
110 }
111 return false;
112 }
113
114 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400115 public void addCallback(Callback callback) {
Beverly80313ca2018-05-10 16:43:52 -0400116 if (callback == null) {
117 Slog.e(TAG, "Attempted to add a null callback.");
118 return;
119 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400120 mCallbacks.add(callback);
121 }
122
123 @Override
124 public void removeCallback(Callback callback) {
125 mCallbacks.remove(callback);
126 }
127
128 @Override
John Spurlockae641c92014-06-30 18:11:40 -0400129 public int getZen() {
Lucas Dupin8b77a3b2018-05-01 13:23:03 -0700130 return mZenMode;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400131 }
132
133 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400134 public void setZen(int zen, Uri conditionId, String reason) {
135 mNoMan.setZenMode(zen, conditionId, reason);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400136 }
137
138 @Override
John Spurlock45601d62014-08-07 17:40:50 -0400139 public boolean isZenAvailable() {
140 return mSetupObserver.isDeviceProvisioned() && mSetupObserver.isUserSetup();
141 }
142
143 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400144 public ZenRule getManualRule() {
145 return mConfig == null ? null : mConfig.manualRule;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400146 }
147
John Spurlock856edeb2014-06-01 20:36:47 -0400148 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400149 public ZenModeConfig getConfig() {
150 return mConfig;
John Spurlock856edeb2014-06-01 20:36:47 -0400151 }
152
John Spurlockae641c92014-06-30 18:11:40 -0400153 @Override
John Spurlock89f060a2014-07-16 21:03:15 -0400154 public long getNextAlarm() {
Jose Lima235510e2014-08-13 12:50:01 -0700155 final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
John Spurlock89f060a2014-07-16 21:03:15 -0400156 return info != null ? info.getTriggerTime() : 0;
157 }
158
159 @Override
Jason Monk9c7844c2017-01-18 15:21:53 -0500160 public void onUserSwitched(int userId) {
John Spurlock89f060a2014-07-16 21:03:15 -0400161 mUserId = userId;
John Spurlock8b0249d2014-07-17 15:53:32 -0400162 if (mRegistered) {
163 mContext.unregisterReceiver(mReceiver);
164 }
John Spurlock661f2cf2014-11-17 10:29:10 -0500165 final IntentFilter filter = new IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
166 filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
167 mContext.registerReceiverAsUser(mReceiver, new UserHandle(mUserId), filter, null, null);
John Spurlock8b0249d2014-07-17 15:53:32 -0400168 mRegistered = true;
John Spurlock45601d62014-08-07 17:40:50 -0400169 mSetupObserver.register();
John Spurlock89f060a2014-07-16 21:03:15 -0400170 }
171
John Spurlockb4782522014-08-22 14:54:46 -0400172 @Override
173 public ComponentName getEffectsSuppressor() {
174 return NotificationManager.from(mContext).getEffectsSuppressor();
175 }
176
John Spurlockad680d42015-01-30 15:48:15 -0500177 @Override
178 public boolean isCountdownConditionSupported() {
179 return NotificationManager.from(mContext)
180 .isSystemConditionProviderEnabled(ZenModeConfig.COUNTDOWN_PATH);
181 }
182
John Spurlockd9c75db2015-04-28 11:19:13 -0400183 @Override
184 public int getCurrentUser() {
185 return ActivityManager.getCurrentUser();
186 }
187
John Spurlock89f060a2014-07-16 21:03:15 -0400188 private void fireNextAlarmChanged() {
Jason Monkf66d3772017-05-30 14:31:51 -0400189 Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged());
John Spurlockae641c92014-06-30 18:11:40 -0400190 }
191
John Spurlockb4782522014-08-22 14:54:46 -0400192 private void fireEffectsSuppressorChanged() {
Jason Monkf66d3772017-05-30 14:31:51 -0400193 Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged());
John Spurlockb4782522014-08-22 14:54:46 -0400194 }
195
John Spurlockae641c92014-06-30 18:11:40 -0400196 private void fireZenChanged(int zen) {
Jason Monkf66d3772017-05-30 14:31:51 -0400197 Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400198 }
199
John Spurlock45601d62014-08-07 17:40:50 -0400200 private void fireZenAvailableChanged(boolean available) {
Jason Monkf66d3772017-05-30 14:31:51 -0400201 Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available));
John Spurlock45601d62014-08-07 17:40:50 -0400202 }
203
John Spurlockb2278d62015-04-07 12:47:12 -0400204 private void fireManualRuleChanged(ZenRule rule) {
Jason Monkf66d3772017-05-30 14:31:51 -0400205 Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule));
John Spurlockb2278d62015-04-07 12:47:12 -0400206 }
207
Jason Monkf66d3772017-05-30 14:31:51 -0400208 @VisibleForTesting
209 protected void fireConfigChanged(ZenModeConfig config) {
210 Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config));
John Spurlock856edeb2014-06-01 20:36:47 -0400211 }
212
Julia Reynolds9cf17562018-03-14 09:49:35 -0400213 @VisibleForTesting
214 protected void updateZenMode(int mode) {
215 mZenMode = mode;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400216 }
217
Julia Reynolds9cf17562018-03-14 09:49:35 -0400218 @VisibleForTesting
219 protected void updateZenModeConfig() {
John Spurlockb2278d62015-04-07 12:47:12 -0400220 final ZenModeConfig config = mNoMan.getZenModeConfig();
221 if (Objects.equals(config, mConfig)) return;
222 final ZenRule oldRule = mConfig != null ? mConfig.manualRule : null;
223 mConfig = config;
224 fireConfigChanged(config);
225 final ZenRule newRule = config != null ? config.manualRule : null;
226 if (Objects.equals(oldRule, newRule)) return;
227 fireManualRuleChanged(newRule);
228 }
229
John Spurlock89f060a2014-07-16 21:03:15 -0400230 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
231 @Override
232 public void onReceive(Context context, Intent intent) {
233 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) {
234 fireNextAlarmChanged();
235 }
John Spurlockb4782522014-08-22 14:54:46 -0400236 if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) {
237 fireEffectsSuppressorChanged();
238 }
John Spurlock89f060a2014-07-16 21:03:15 -0400239 }
240 };
John Spurlock45601d62014-08-07 17:40:50 -0400241
242 private final class SetupObserver extends ContentObserver {
243 private final ContentResolver mResolver;
244
245 private boolean mRegistered;
246
247 public SetupObserver(Handler handler) {
248 super(handler);
249 mResolver = mContext.getContentResolver();
250 }
251
252 public boolean isUserSetup() {
253 return Secure.getIntForUser(mResolver, Secure.USER_SETUP_COMPLETE, 0, mUserId) != 0;
254 }
255
256 public boolean isDeviceProvisioned() {
257 return Global.getInt(mResolver, Global.DEVICE_PROVISIONED, 0) != 0;
258 }
259
260 public void register() {
261 if (mRegistered) {
262 mResolver.unregisterContentObserver(this);
263 }
264 mResolver.registerContentObserver(
265 Global.getUriFor(Global.DEVICE_PROVISIONED), false, this);
266 mResolver.registerContentObserver(
267 Secure.getUriFor(Secure.USER_SETUP_COMPLETE), false, this, mUserId);
268 fireZenAvailableChanged(isZenAvailable());
269 }
270
271 @Override
272 public void onChange(boolean selfChange, Uri uri) {
273 if (Global.getUriFor(Global.DEVICE_PROVISIONED).equals(uri)
274 || Secure.getUriFor(Secure.USER_SETUP_COMPLETE).equals(uri)) {
275 fireZenAvailableChanged(isZenAvailable());
276 }
277 }
278 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400279}