blob: 9180791fd555d8fc89ac25490bf4bc56e25ef7cc [file] [log] [blame]
Beverlya58e52a2017-10-27 14:44:23 -04001/*
2 * Copyright (C) 2017 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.settings.notification;
18
Beverlyb7b74222017-11-17 16:29:30 -050019import android.app.ActivityManager;
20import android.app.AlarmManager;
21import android.app.AlarmManager.AlarmClockInfo;
Beverlya58e52a2017-10-27 14:44:23 -040022import android.app.NotificationManager;
23import android.content.ContentResolver;
24import android.content.Context;
25import android.database.ContentObserver;
26import android.net.Uri;
27import android.os.Handler;
Beverly71a191c2017-12-01 12:57:13 -050028import android.os.UserHandle;
Beverlya58e52a2017-10-27 14:44:23 -040029import android.provider.Settings;
Beverlyb7b74222017-11-17 16:29:30 -050030import android.service.notification.ScheduleCalendar;
31import android.service.notification.ZenModeConfig;
Beverlya58e52a2017-10-27 14:44:23 -040032import android.support.v7.preference.Preference;
33import android.support.v7.preference.PreferenceScreen;
34
Beverly71a191c2017-12-01 12:57:13 -050035import com.android.internal.annotations.VisibleForTesting;
Beverlya58e52a2017-10-27 14:44:23 -040036import com.android.settings.core.PreferenceControllerMixin;
Beverly32352212017-11-20 17:33:01 -050037import com.android.settings.overlay.FeatureFactory;
Beverlya58e52a2017-10-27 14:44:23 -040038import com.android.settingslib.core.AbstractPreferenceController;
Leif Hendrik Wilden1546cca2018-01-11 10:15:36 -080039import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
Beverlya58e52a2017-10-27 14:44:23 -040040import com.android.settingslib.core.lifecycle.Lifecycle;
41import com.android.settingslib.core.lifecycle.LifecycleObserver;
42import com.android.settingslib.core.lifecycle.events.OnPause;
43import com.android.settingslib.core.lifecycle.events.OnResume;
44
45abstract public class AbstractZenModePreferenceController extends
46 AbstractPreferenceController implements PreferenceControllerMixin, LifecycleObserver,
47 OnResume, OnPause {
48
Beverly71a191c2017-12-01 12:57:13 -050049 @VisibleForTesting
50 protected SettingObserver mSettingObserver;
Beverlyb7b74222017-11-17 16:29:30 -050051
Beverlya58e52a2017-10-27 14:44:23 -040052 private final String KEY;
53 final private NotificationManager mNotificationManager;
Beverlyb7b74222017-11-17 16:29:30 -050054 protected static ZenModeConfigWrapper mZenModeConfigWrapper;
Beverly32352212017-11-20 17:33:01 -050055 protected MetricsFeatureProvider mMetricsFeatureProvider;
Beverlybd775d92017-12-14 09:37:01 -050056 protected final ZenModeBackend mBackend;
Beverlya58e52a2017-10-27 14:44:23 -040057
58 public AbstractZenModePreferenceController(Context context, String key,
59 Lifecycle lifecycle) {
60 super(context);
Beverlyb7b74222017-11-17 16:29:30 -050061 mZenModeConfigWrapper = new ZenModeConfigWrapper(context);
Beverlya58e52a2017-10-27 14:44:23 -040062 if (lifecycle != null) {
63 lifecycle.addObserver(this);
64 }
65 KEY = key;
66 mNotificationManager = (NotificationManager) context.getSystemService(
67 Context.NOTIFICATION_SERVICE);
Beverly32352212017-11-20 17:33:01 -050068
69 final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext);
70 mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
Beverlybd775d92017-12-14 09:37:01 -050071 mBackend = ZenModeBackend.getInstance(context);
Beverlya58e52a2017-10-27 14:44:23 -040072 }
73
74 @Override
75 public void displayPreference(PreferenceScreen screen) {
76 super.displayPreference(screen);
77 mSettingObserver = new SettingObserver(screen.findPreference(KEY));
78 }
79
80 @Override
81 public void onResume() {
82 if (mSettingObserver != null) {
83 mSettingObserver.register(mContext.getContentResolver());
84 }
85 }
86
87 @Override
88 public void onPause() {
89 if (mSettingObserver != null) {
90 mSettingObserver.unregister(mContext.getContentResolver());
91 }
92 }
93
Beverlybd775d92017-12-14 09:37:01 -050094 @Override
95 public void updateState(Preference preference) {
96 super.updateState(preference);
97
98 mBackend.updatePolicy();
99 mBackend.updateZenMode();
100 }
101
Beverlya58e52a2017-10-27 14:44:23 -0400102 protected NotificationManager.Policy getPolicy() {
103 return mNotificationManager.getNotificationPolicy();
104 }
105
Beverlyb7b74222017-11-17 16:29:30 -0500106 protected ZenModeConfig getZenModeConfig() {
107 return mNotificationManager.getZenModeConfig();
108 }
109
Beverlya58e52a2017-10-27 14:44:23 -0400110 protected int getZenMode() {
Beverlybd775d92017-12-14 09:37:01 -0500111 return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
112 mBackend.mZenMode);
Beverlya58e52a2017-10-27 14:44:23 -0400113 }
114
115 class SettingObserver extends ContentObserver {
116 private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
117 private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
118 Settings.Global.ZEN_MODE_CONFIG_ETAG);
119
120 private final Preference mPreference;
121
122 public SettingObserver(Preference preference) {
123 super(new Handler());
124 mPreference = preference;
125 }
126
127 public void register(ContentResolver cr) {
Beverly71a191c2017-12-01 12:57:13 -0500128 cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL);
129 cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL);
Beverlya58e52a2017-10-27 14:44:23 -0400130 }
131
132 public void unregister(ContentResolver cr) {
133 cr.unregisterContentObserver(this);
134 }
135
136 @Override
137 public void onChange(boolean selfChange, Uri uri) {
138 super.onChange(selfChange, uri);
139 if (ZEN_MODE_URI.equals(uri)) {
140 updateState(mPreference);
141 }
142
143 if (ZEN_MODE_CONFIG_ETAG_URI.equals(uri)) {
144 updateState(mPreference);
145 }
146 }
147 }
Beverlyb7b74222017-11-17 16:29:30 -0500148
149 /**
150 * Wrapper for testing compatibility
151 */
152 @VisibleForTesting
153 static class ZenModeConfigWrapper {
154 private final Context mContext;
155
156 public ZenModeConfigWrapper(Context context) {
157 mContext = context;
158 }
159
160 protected String getOwnerCaption(String owner) {
161 return ZenModeConfig.getOwnerCaption(mContext, owner);
162 }
163
164 protected boolean isTimeRule(Uri id) {
165 return ZenModeConfig.isValidEventConditionId(id) ||
166 ZenModeConfig.isValidScheduleConditionId(id);
167 }
168
169 protected CharSequence getFormattedTime(long time, int userHandle) {
170 return ZenModeConfig.getFormattedTime(mContext, time, isToday(time), userHandle);
171 }
172
173 private boolean isToday(long time) {
174 return ZenModeConfig.isToday(time);
175 }
176
177 protected long parseManualRuleTime(Uri id) {
178 return ZenModeConfig.tryParseCountdownConditionId(id);
179 }
180
181 protected long parseAutomaticRuleEndTime(Uri id) {
182 if (ZenModeConfig.isValidEventConditionId(id)) {
183 // cannot look up end times for events
184 return Long.MAX_VALUE;
185 }
186
187 if (ZenModeConfig.isValidScheduleConditionId(id)) {
188 ScheduleCalendar schedule = ZenModeConfig.toScheduleCalendar(id);
189 long endTimeMs = schedule.getNextChangeTime(System.currentTimeMillis());
190
191 // check if automatic rule will end on next alarm
192 if (schedule.exitAtAlarm()) {
193 long nextAlarm = getNextAlarm(mContext);
194 schedule.maybeSetNextAlarm(System.currentTimeMillis(), nextAlarm);
195 if (schedule.shouldExitForAlarm(endTimeMs)) {
196 return nextAlarm;
197 }
198 }
199
Beverlyb7b74222017-11-17 16:29:30 -0500200 return endTimeMs;
201 }
202
203 return -1;
204 }
205 }
206
207 private static long getNextAlarm(Context context) {
208 final AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
209 final AlarmClockInfo info = alarms.getNextAlarmClock(ActivityManager.getCurrentUser());
210 return info != null ? info.getTriggerTime() : 0;
211 }
Beverlya58e52a2017-10-27 14:44:23 -0400212}