blob: a2028e6c0c33ae160b1d9c3a99b854901dd2172d [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 Spurlock856edeb2014-06-01 20:36:47 -040035import android.service.notification.ZenModeConfig;
John Spurlockb2278d62015-04-07 12:47:12 -040036import android.service.notification.ZenModeConfig.ZenRule;
Amin Shaikh25ae2b72018-06-25 13:53:35 -040037import android.text.format.DateFormat;
John Spurlock89f060a2014-07-16 21:03:15 -040038import android.util.Log;
John Spurlockaf8d6c42014-05-07 17:49:08 -040039
Julia Reynolds9cf17562018-03-14 09:49:35 -040040import com.android.internal.annotations.VisibleForTesting;
Amin Shaikh25ae2b72018-06-25 13:53:35 -040041import com.android.systemui.Dumpable;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000042import com.android.systemui.broadcast.BroadcastDispatcher;
Dave Mankofff4736812019-10-18 17:25:50 -040043import com.android.systemui.dagger.qualifiers.MainHandler;
John Spurlockaf8d6c42014-05-07 17:49:08 -040044import com.android.systemui.qs.GlobalSetting;
Jason Monk9c7844c2017-01-18 15:21:53 -050045import com.android.systemui.settings.CurrentUserTracker;
Jason Monkf66d3772017-05-30 14:31:51 -040046import com.android.systemui.util.Utils;
John Spurlockaf8d6c42014-05-07 17:49:08 -040047
Amin Shaikh25ae2b72018-06-25 13:53:35 -040048import java.io.FileDescriptor;
49import java.io.PrintWriter;
John Spurlockaf8d6c42014-05-07 17:49:08 -040050import java.util.ArrayList;
John Spurlockb2278d62015-04-07 12:47:12 -040051import java.util.Objects;
John Spurlockaf8d6c42014-05-07 17:49:08 -040052
Jason Monk196d6392018-12-20 13:25:34 -050053import javax.inject.Inject;
Jason Monk196d6392018-12-20 13:25:34 -050054import javax.inject.Singleton;
55
John Spurlockaf8d6c42014-05-07 17:49:08 -040056/** Platform implementation of the zen mode controller. **/
Jason Monk196d6392018-12-20 13:25:34 -050057@Singleton
Amin Shaikh25ae2b72018-06-25 13:53:35 -040058public class ZenModeControllerImpl extends CurrentUserTracker
59 implements ZenModeController, Dumpable {
John Spurlock89f060a2014-07-16 21:03:15 -040060 private static final String TAG = "ZenModeController";
61 private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
John Spurlockaf8d6c42014-05-07 17:49:08 -040062
Amin Shaikh25ae2b72018-06-25 13:53:35 -040063 private final ArrayList<Callback> mCallbacks = new ArrayList<>();
Beverly3f74c5d2018-10-02 09:22:56 -040064 private final Object mCallbacksLock = new Object();
John Spurlockaf8d6c42014-05-07 17:49:08 -040065 private final Context mContext;
John Spurlock856edeb2014-06-01 20:36:47 -040066 private final GlobalSetting mModeSetting;
67 private final GlobalSetting mConfigSetting;
John Spurlockcdb57ae2015-02-11 19:04:11 -050068 private final NotificationManager mNoMan;
John Spurlock89f060a2014-07-16 21:03:15 -040069 private final AlarmManager mAlarmManager;
John Spurlock45601d62014-08-07 17:40:50 -040070 private final SetupObserver mSetupObserver;
Jason Monkf0a60dd2015-06-30 10:54:48 -040071 private final UserManager mUserManager;
John Spurlockaf8d6c42014-05-07 17:49:08 -040072
John Spurlock89f060a2014-07-16 21:03:15 -040073 private int mUserId;
John Spurlock8b0249d2014-07-17 15:53:32 -040074 private boolean mRegistered;
John Spurlockb2278d62015-04-07 12:47:12 -040075 private ZenModeConfig mConfig;
Julia Reynolds9cf17562018-03-14 09:49:35 -040076 private int mZenMode;
Amin Shaikh25ae2b72018-06-25 13:53:35 -040077 private long mZenUpdateTime;
Beverlyff2df9b2018-10-10 16:54:10 -040078 private NotificationManager.Policy mConsolidatedNotificationPolicy;
John Spurlockaf8d6c42014-05-07 17:49:08 -040079
Jason Monk196d6392018-12-20 13:25:34 -050080 @Inject
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000081 public ZenModeControllerImpl(Context context, @MainHandler Handler handler,
82 BroadcastDispatcher broadcastDispatcher) {
83 super(broadcastDispatcher);
John Spurlockaf8d6c42014-05-07 17:49:08 -040084 mContext = context;
John Spurlock856edeb2014-06-01 20:36:47 -040085 mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
John Spurlockaf8d6c42014-05-07 17:49:08 -040086 @Override
87 protected void handleValueChanged(int value) {
Julia Reynolds9cf17562018-03-14 09:49:35 -040088 updateZenMode(value);
John Spurlockae641c92014-06-30 18:11:40 -040089 fireZenChanged(value);
John Spurlockaf8d6c42014-05-07 17:49:08 -040090 }
91 };
John Spurlock856edeb2014-06-01 20:36:47 -040092 mConfigSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE_CONFIG_ETAG) {
93 @Override
94 protected void handleValueChanged(int value) {
John Spurlockb2278d62015-04-07 12:47:12 -040095 updateZenModeConfig();
John Spurlock856edeb2014-06-01 20:36:47 -040096 }
97 };
John Spurlockb2278d62015-04-07 12:47:12 -040098 mNoMan = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
John Spurlock856edeb2014-06-01 20:36:47 -040099 mModeSetting.setListening(true);
Julia Reynolds9cf17562018-03-14 09:49:35 -0400100 updateZenMode(mModeSetting.getValue());
John Spurlock856edeb2014-06-01 20:36:47 -0400101 mConfigSetting.setListening(true);
Julia Reynolds9cf17562018-03-14 09:49:35 -0400102 updateZenModeConfig();
Beverlyff2df9b2018-10-10 16:54:10 -0400103 updateConsolidatedNotificationPolicy();
John Spurlock89f060a2014-07-16 21:03:15 -0400104 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
John Spurlock45601d62014-08-07 17:40:50 -0400105 mSetupObserver = new SetupObserver(handler);
106 mSetupObserver.register();
Jason Monkf0a60dd2015-06-30 10:54:48 -0400107 mUserManager = context.getSystemService(UserManager.class);
Jason Monk9c7844c2017-01-18 15:21:53 -0500108 startTracking();
Jason Monkf0a60dd2015-06-30 10:54:48 -0400109 }
110
111 @Override
112 public boolean isVolumeRestricted() {
113 return mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME,
114 new UserHandle(mUserId));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400115 }
116
117 @Override
Julia Reynolds9cf17562018-03-14 09:49:35 -0400118 public boolean areNotificationsHiddenInShade() {
119 if (mZenMode != Global.ZEN_MODE_OFF) {
Beverly12196702018-12-12 15:05:51 -0500120 return (mConsolidatedNotificationPolicy.suppressedVisualEffects
121 & NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST) != 0;
Julia Reynolds9cf17562018-03-14 09:49:35 -0400122 }
123 return false;
124 }
125
126 @Override
John Spurlockaf8d6c42014-05-07 17:49:08 -0400127 public void addCallback(Callback callback) {
Beverly3f74c5d2018-10-02 09:22:56 -0400128 synchronized (mCallbacksLock) {
129 mCallbacks.add(callback);
130 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400131 }
132
133 @Override
134 public void removeCallback(Callback callback) {
Beverly3f74c5d2018-10-02 09:22:56 -0400135 synchronized (mCallbacksLock) {
136 mCallbacks.remove(callback);
137 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400138 }
139
140 @Override
John Spurlockae641c92014-06-30 18:11:40 -0400141 public int getZen() {
Lucas Dupin8b77a3b2018-05-01 13:23:03 -0700142 return mZenMode;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400143 }
144
145 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400146 public void setZen(int zen, Uri conditionId, String reason) {
147 mNoMan.setZenMode(zen, conditionId, reason);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400148 }
149
150 @Override
John Spurlock45601d62014-08-07 17:40:50 -0400151 public boolean isZenAvailable() {
152 return mSetupObserver.isDeviceProvisioned() && mSetupObserver.isUserSetup();
153 }
154
155 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400156 public ZenRule getManualRule() {
157 return mConfig == null ? null : mConfig.manualRule;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400158 }
159
John Spurlock856edeb2014-06-01 20:36:47 -0400160 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400161 public ZenModeConfig getConfig() {
162 return mConfig;
John Spurlock856edeb2014-06-01 20:36:47 -0400163 }
164
John Spurlockae641c92014-06-30 18:11:40 -0400165 @Override
Beverlyff2df9b2018-10-10 16:54:10 -0400166 public NotificationManager.Policy getConsolidatedPolicy() {
167 return mConsolidatedNotificationPolicy;
168 }
169
170 @Override
John Spurlock89f060a2014-07-16 21:03:15 -0400171 public long getNextAlarm() {
Jose Lima235510e2014-08-13 12:50:01 -0700172 final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
John Spurlock89f060a2014-07-16 21:03:15 -0400173 return info != null ? info.getTriggerTime() : 0;
174 }
175
176 @Override
Jason Monk9c7844c2017-01-18 15:21:53 -0500177 public void onUserSwitched(int userId) {
John Spurlock89f060a2014-07-16 21:03:15 -0400178 mUserId = userId;
John Spurlock8b0249d2014-07-17 15:53:32 -0400179 if (mRegistered) {
180 mContext.unregisterReceiver(mReceiver);
181 }
John Spurlock661f2cf2014-11-17 10:29:10 -0500182 final IntentFilter filter = new IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
183 filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
184 mContext.registerReceiverAsUser(mReceiver, new UserHandle(mUserId), filter, null, null);
John Spurlock8b0249d2014-07-17 15:53:32 -0400185 mRegistered = true;
John Spurlock45601d62014-08-07 17:40:50 -0400186 mSetupObserver.register();
John Spurlock89f060a2014-07-16 21:03:15 -0400187 }
188
John Spurlockb4782522014-08-22 14:54:46 -0400189 @Override
190 public ComponentName getEffectsSuppressor() {
191 return NotificationManager.from(mContext).getEffectsSuppressor();
192 }
193
John Spurlockad680d42015-01-30 15:48:15 -0500194 @Override
195 public boolean isCountdownConditionSupported() {
196 return NotificationManager.from(mContext)
197 .isSystemConditionProviderEnabled(ZenModeConfig.COUNTDOWN_PATH);
198 }
199
John Spurlockd9c75db2015-04-28 11:19:13 -0400200 @Override
201 public int getCurrentUser() {
202 return ActivityManager.getCurrentUser();
203 }
204
John Spurlock89f060a2014-07-16 21:03:15 -0400205 private void fireNextAlarmChanged() {
Beverly3f74c5d2018-10-02 09:22:56 -0400206 synchronized (mCallbacksLock) {
207 Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged());
208 }
John Spurlockae641c92014-06-30 18:11:40 -0400209 }
210
John Spurlockb4782522014-08-22 14:54:46 -0400211 private void fireEffectsSuppressorChanged() {
Beverly3f74c5d2018-10-02 09:22:56 -0400212 synchronized (mCallbacksLock) {
213 Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged());
214 }
John Spurlockb4782522014-08-22 14:54:46 -0400215 }
216
John Spurlockae641c92014-06-30 18:11:40 -0400217 private void fireZenChanged(int zen) {
Beverly3f74c5d2018-10-02 09:22:56 -0400218 synchronized (mCallbacksLock) {
219 Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen));
220 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400221 }
222
John Spurlock45601d62014-08-07 17:40:50 -0400223 private void fireZenAvailableChanged(boolean available) {
Beverly3f74c5d2018-10-02 09:22:56 -0400224 synchronized (mCallbacksLock) {
225 Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available));
226 }
John Spurlock45601d62014-08-07 17:40:50 -0400227 }
228
John Spurlockb2278d62015-04-07 12:47:12 -0400229 private void fireManualRuleChanged(ZenRule rule) {
Beverly3f74c5d2018-10-02 09:22:56 -0400230 synchronized (mCallbacksLock) {
231 Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule));
232 }
John Spurlockb2278d62015-04-07 12:47:12 -0400233 }
234
Beverlyff2df9b2018-10-10 16:54:10 -0400235 private void fireConsolidatedPolicyChanged(NotificationManager.Policy policy) {
236 synchronized (mCallbacksLock) {
237 Utils.safeForeach(mCallbacks, c -> c.onConsolidatedPolicyChanged(policy));
238 }
239 }
240
Jason Monkf66d3772017-05-30 14:31:51 -0400241 @VisibleForTesting
242 protected void fireConfigChanged(ZenModeConfig config) {
Beverly3f74c5d2018-10-02 09:22:56 -0400243 synchronized (mCallbacksLock) {
244 Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config));
245 }
John Spurlock856edeb2014-06-01 20:36:47 -0400246 }
247
Julia Reynolds9cf17562018-03-14 09:49:35 -0400248 @VisibleForTesting
249 protected void updateZenMode(int mode) {
250 mZenMode = mode;
Amin Shaikh25ae2b72018-06-25 13:53:35 -0400251 mZenUpdateTime = System.currentTimeMillis();
John Spurlockaf8d6c42014-05-07 17:49:08 -0400252 }
253
Julia Reynolds9cf17562018-03-14 09:49:35 -0400254 @VisibleForTesting
Beverlyff2df9b2018-10-10 16:54:10 -0400255 protected void updateConsolidatedNotificationPolicy() {
256 final NotificationManager.Policy policy = mNoMan.getConsolidatedNotificationPolicy();
257 if (!Objects.equals(policy, mConsolidatedNotificationPolicy)) {
258 mConsolidatedNotificationPolicy = policy;
259 fireConsolidatedPolicyChanged(policy);
260 }
261 }
262
Beverlyff2df9b2018-10-10 16:54:10 -0400263 @VisibleForTesting
Julia Reynolds9cf17562018-03-14 09:49:35 -0400264 protected void updateZenModeConfig() {
John Spurlockb2278d62015-04-07 12:47:12 -0400265 final ZenModeConfig config = mNoMan.getZenModeConfig();
266 if (Objects.equals(config, mConfig)) return;
267 final ZenRule oldRule = mConfig != null ? mConfig.manualRule : null;
268 mConfig = config;
Amin Shaikh25ae2b72018-06-25 13:53:35 -0400269 mZenUpdateTime = System.currentTimeMillis();
John Spurlockb2278d62015-04-07 12:47:12 -0400270 fireConfigChanged(config);
Beverlyff2df9b2018-10-10 16:54:10 -0400271
John Spurlockb2278d62015-04-07 12:47:12 -0400272 final ZenRule newRule = config != null ? config.manualRule : null;
Beverlyff2df9b2018-10-10 16:54:10 -0400273 if (!Objects.equals(oldRule, newRule)) {
274 fireManualRuleChanged(newRule);
275 }
276
277 final NotificationManager.Policy consolidatedPolicy =
278 mNoMan.getConsolidatedNotificationPolicy();
279 if (!Objects.equals(consolidatedPolicy, mConsolidatedNotificationPolicy)) {
280 mConsolidatedNotificationPolicy = consolidatedPolicy;
281 fireConsolidatedPolicyChanged(consolidatedPolicy);
282 }
283
John Spurlockb2278d62015-04-07 12:47:12 -0400284 }
285
John Spurlock89f060a2014-07-16 21:03:15 -0400286 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
287 @Override
288 public void onReceive(Context context, Intent intent) {
289 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) {
290 fireNextAlarmChanged();
291 }
John Spurlockb4782522014-08-22 14:54:46 -0400292 if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) {
293 fireEffectsSuppressorChanged();
294 }
John Spurlock89f060a2014-07-16 21:03:15 -0400295 }
296 };
John Spurlock45601d62014-08-07 17:40:50 -0400297
Amin Shaikh25ae2b72018-06-25 13:53:35 -0400298 @Override
299 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
300 pw.println("ZenModeControllerImpl:");
301 pw.println(" mZenMode=" + mZenMode);
302 pw.println(" mConfig=" + mConfig);
Beverlyff2df9b2018-10-10 16:54:10 -0400303 pw.println(" mConsolidatedNotificationPolicy=" + mConsolidatedNotificationPolicy);
Amin Shaikh25ae2b72018-06-25 13:53:35 -0400304 pw.println(" mZenUpdateTime=" + DateFormat.format("MM-dd HH:mm:ss", mZenUpdateTime));
305 }
306
John Spurlock45601d62014-08-07 17:40:50 -0400307 private final class SetupObserver extends ContentObserver {
308 private final ContentResolver mResolver;
309
310 private boolean mRegistered;
311
312 public SetupObserver(Handler handler) {
313 super(handler);
314 mResolver = mContext.getContentResolver();
315 }
316
317 public boolean isUserSetup() {
318 return Secure.getIntForUser(mResolver, Secure.USER_SETUP_COMPLETE, 0, mUserId) != 0;
319 }
320
321 public boolean isDeviceProvisioned() {
322 return Global.getInt(mResolver, Global.DEVICE_PROVISIONED, 0) != 0;
323 }
324
325 public void register() {
326 if (mRegistered) {
327 mResolver.unregisterContentObserver(this);
328 }
329 mResolver.registerContentObserver(
330 Global.getUriFor(Global.DEVICE_PROVISIONED), false, this);
331 mResolver.registerContentObserver(
332 Secure.getUriFor(Secure.USER_SETUP_COMPLETE), false, this, mUserId);
Amin Shaikh25ae2b72018-06-25 13:53:35 -0400333 mRegistered = true;
John Spurlock45601d62014-08-07 17:40:50 -0400334 fireZenAvailableChanged(isZenAvailable());
335 }
336
337 @Override
338 public void onChange(boolean selfChange, Uri uri) {
339 if (Global.getUriFor(Global.DEVICE_PROVISIONED).equals(uri)
340 || Secure.getUriFor(Secure.USER_SETUP_COMPLETE).equals(uri)) {
341 fireZenAvailableChanged(isZenAvailable());
342 }
343 }
344 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400345}