blob: 59b376f311fb30d80f872a9155069485493433c7 [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) {
116 mCallbacks.add(callback);
117 }
118
119 @Override
120 public void removeCallback(Callback callback) {
121 mCallbacks.remove(callback);
122 }
123
124 @Override
John Spurlockae641c92014-06-30 18:11:40 -0400125 public int getZen() {
Lucas Dupin8b77a3b2018-05-01 13:23:03 -0700126 return mZenMode;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400127 }
128
129 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400130 public void setZen(int zen, Uri conditionId, String reason) {
131 mNoMan.setZenMode(zen, conditionId, reason);
John Spurlockaf8d6c42014-05-07 17:49:08 -0400132 }
133
134 @Override
John Spurlock45601d62014-08-07 17:40:50 -0400135 public boolean isZenAvailable() {
136 return mSetupObserver.isDeviceProvisioned() && mSetupObserver.isUserSetup();
137 }
138
139 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400140 public ZenRule getManualRule() {
141 return mConfig == null ? null : mConfig.manualRule;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400142 }
143
John Spurlock856edeb2014-06-01 20:36:47 -0400144 @Override
John Spurlockb2278d62015-04-07 12:47:12 -0400145 public ZenModeConfig getConfig() {
146 return mConfig;
John Spurlock856edeb2014-06-01 20:36:47 -0400147 }
148
John Spurlockae641c92014-06-30 18:11:40 -0400149 @Override
John Spurlock89f060a2014-07-16 21:03:15 -0400150 public long getNextAlarm() {
Jose Lima235510e2014-08-13 12:50:01 -0700151 final AlarmManager.AlarmClockInfo info = mAlarmManager.getNextAlarmClock(mUserId);
John Spurlock89f060a2014-07-16 21:03:15 -0400152 return info != null ? info.getTriggerTime() : 0;
153 }
154
155 @Override
Jason Monk9c7844c2017-01-18 15:21:53 -0500156 public void onUserSwitched(int userId) {
John Spurlock89f060a2014-07-16 21:03:15 -0400157 mUserId = userId;
John Spurlock8b0249d2014-07-17 15:53:32 -0400158 if (mRegistered) {
159 mContext.unregisterReceiver(mReceiver);
160 }
John Spurlock661f2cf2014-11-17 10:29:10 -0500161 final IntentFilter filter = new IntentFilter(AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED);
162 filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
163 mContext.registerReceiverAsUser(mReceiver, new UserHandle(mUserId), filter, null, null);
John Spurlock8b0249d2014-07-17 15:53:32 -0400164 mRegistered = true;
John Spurlock45601d62014-08-07 17:40:50 -0400165 mSetupObserver.register();
John Spurlock89f060a2014-07-16 21:03:15 -0400166 }
167
John Spurlockb4782522014-08-22 14:54:46 -0400168 @Override
169 public ComponentName getEffectsSuppressor() {
170 return NotificationManager.from(mContext).getEffectsSuppressor();
171 }
172
John Spurlockad680d42015-01-30 15:48:15 -0500173 @Override
174 public boolean isCountdownConditionSupported() {
175 return NotificationManager.from(mContext)
176 .isSystemConditionProviderEnabled(ZenModeConfig.COUNTDOWN_PATH);
177 }
178
John Spurlockd9c75db2015-04-28 11:19:13 -0400179 @Override
180 public int getCurrentUser() {
181 return ActivityManager.getCurrentUser();
182 }
183
John Spurlock89f060a2014-07-16 21:03:15 -0400184 private void fireNextAlarmChanged() {
Jason Monkf66d3772017-05-30 14:31:51 -0400185 Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged());
John Spurlockae641c92014-06-30 18:11:40 -0400186 }
187
John Spurlockb4782522014-08-22 14:54:46 -0400188 private void fireEffectsSuppressorChanged() {
Jason Monkf66d3772017-05-30 14:31:51 -0400189 Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged());
John Spurlockb4782522014-08-22 14:54:46 -0400190 }
191
John Spurlockae641c92014-06-30 18:11:40 -0400192 private void fireZenChanged(int zen) {
Jason Monkf66d3772017-05-30 14:31:51 -0400193 Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen));
John Spurlockaf8d6c42014-05-07 17:49:08 -0400194 }
195
John Spurlock45601d62014-08-07 17:40:50 -0400196 private void fireZenAvailableChanged(boolean available) {
Jason Monkf66d3772017-05-30 14:31:51 -0400197 Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available));
John Spurlock45601d62014-08-07 17:40:50 -0400198 }
199
John Spurlockb2278d62015-04-07 12:47:12 -0400200 private void fireManualRuleChanged(ZenRule rule) {
Jason Monkf66d3772017-05-30 14:31:51 -0400201 Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule));
John Spurlockb2278d62015-04-07 12:47:12 -0400202 }
203
Jason Monkf66d3772017-05-30 14:31:51 -0400204 @VisibleForTesting
205 protected void fireConfigChanged(ZenModeConfig config) {
206 Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config));
John Spurlock856edeb2014-06-01 20:36:47 -0400207 }
208
Julia Reynolds9cf17562018-03-14 09:49:35 -0400209 @VisibleForTesting
210 protected void updateZenMode(int mode) {
211 mZenMode = mode;
John Spurlockaf8d6c42014-05-07 17:49:08 -0400212 }
213
Julia Reynolds9cf17562018-03-14 09:49:35 -0400214 @VisibleForTesting
215 protected void updateZenModeConfig() {
John Spurlockb2278d62015-04-07 12:47:12 -0400216 final ZenModeConfig config = mNoMan.getZenModeConfig();
217 if (Objects.equals(config, mConfig)) return;
218 final ZenRule oldRule = mConfig != null ? mConfig.manualRule : null;
219 mConfig = config;
220 fireConfigChanged(config);
221 final ZenRule newRule = config != null ? config.manualRule : null;
222 if (Objects.equals(oldRule, newRule)) return;
223 fireManualRuleChanged(newRule);
224 }
225
John Spurlock89f060a2014-07-16 21:03:15 -0400226 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
227 @Override
228 public void onReceive(Context context, Intent intent) {
229 if (AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED.equals(intent.getAction())) {
230 fireNextAlarmChanged();
231 }
John Spurlockb4782522014-08-22 14:54:46 -0400232 if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(intent.getAction())) {
233 fireEffectsSuppressorChanged();
234 }
John Spurlock89f060a2014-07-16 21:03:15 -0400235 }
236 };
John Spurlock45601d62014-08-07 17:40:50 -0400237
238 private final class SetupObserver extends ContentObserver {
239 private final ContentResolver mResolver;
240
241 private boolean mRegistered;
242
243 public SetupObserver(Handler handler) {
244 super(handler);
245 mResolver = mContext.getContentResolver();
246 }
247
248 public boolean isUserSetup() {
249 return Secure.getIntForUser(mResolver, Secure.USER_SETUP_COMPLETE, 0, mUserId) != 0;
250 }
251
252 public boolean isDeviceProvisioned() {
253 return Global.getInt(mResolver, Global.DEVICE_PROVISIONED, 0) != 0;
254 }
255
256 public void register() {
257 if (mRegistered) {
258 mResolver.unregisterContentObserver(this);
259 }
260 mResolver.registerContentObserver(
261 Global.getUriFor(Global.DEVICE_PROVISIONED), false, this);
262 mResolver.registerContentObserver(
263 Secure.getUriFor(Secure.USER_SETUP_COMPLETE), false, this, mUserId);
264 fireZenAvailableChanged(isZenAvailable());
265 }
266
267 @Override
268 public void onChange(boolean selfChange, Uri uri) {
269 if (Global.getUriFor(Global.DEVICE_PROVISIONED).equals(uri)
270 || Secure.getUriFor(Secure.USER_SETUP_COMPLETE).equals(uri)) {
271 fireZenAvailableChanged(isZenAvailable());
272 }
273 }
274 }
John Spurlockaf8d6c42014-05-07 17:49:08 -0400275}