• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.settings.notification;
18 
19 import android.app.ActivityManager;
20 import android.app.AlarmManager;
21 import android.app.AlarmManager.AlarmClockInfo;
22 import android.app.NotificationManager;
23 import android.content.ContentResolver;
24 import android.content.Context;
25 import android.database.ContentObserver;
26 import android.net.Uri;
27 import android.os.Handler;
28 import android.os.UserHandle;
29 import android.provider.Settings;
30 import android.service.notification.ScheduleCalendar;
31 import android.service.notification.ZenModeConfig;
32 import android.support.v7.preference.Preference;
33 import android.support.v7.preference.PreferenceScreen;
34 
35 import com.android.internal.annotations.VisibleForTesting;
36 import com.android.settings.core.PreferenceControllerMixin;
37 import com.android.settings.overlay.FeatureFactory;
38 import com.android.settingslib.core.AbstractPreferenceController;
39 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
40 import com.android.settingslib.core.lifecycle.Lifecycle;
41 import com.android.settingslib.core.lifecycle.LifecycleObserver;
42 import com.android.settingslib.core.lifecycle.events.OnPause;
43 import com.android.settingslib.core.lifecycle.events.OnResume;
44 
45 abstract public class AbstractZenModePreferenceController extends
46         AbstractPreferenceController implements PreferenceControllerMixin, LifecycleObserver,
47         OnResume, OnPause {
48 
49     @VisibleForTesting
50     protected SettingObserver mSettingObserver;
51 
52     private final String KEY;
53     final private NotificationManager mNotificationManager;
54     protected static ZenModeConfigWrapper mZenModeConfigWrapper;
55     protected MetricsFeatureProvider mMetricsFeatureProvider;
56     protected final ZenModeBackend mBackend;
57     protected PreferenceScreen mScreen;
58 
AbstractZenModePreferenceController(Context context, String key, Lifecycle lifecycle)59     public AbstractZenModePreferenceController(Context context, String key,
60             Lifecycle lifecycle) {
61         super(context);
62         mZenModeConfigWrapper = new ZenModeConfigWrapper(context);
63         if (lifecycle != null) {
64             lifecycle.addObserver(this);
65         }
66         KEY = key;
67         mNotificationManager = (NotificationManager) context.getSystemService(
68                 Context.NOTIFICATION_SERVICE);
69 
70         final FeatureFactory featureFactory = FeatureFactory.getFactory(mContext);
71         mMetricsFeatureProvider = featureFactory.getMetricsFeatureProvider();
72         mBackend = ZenModeBackend.getInstance(context);
73     }
74 
75     @Override
getPreferenceKey()76     public String getPreferenceKey() {
77         return KEY;
78     }
79 
80     @Override
displayPreference(PreferenceScreen screen)81     public void displayPreference(PreferenceScreen screen) {
82         super.displayPreference(screen);
83         mScreen = screen;
84         Preference pref = screen.findPreference(KEY);
85         if (pref != null) {
86             mSettingObserver = new SettingObserver(pref);
87         }
88     }
89 
90     @Override
onResume()91     public void onResume() {
92         if (mSettingObserver != null) {
93             mSettingObserver.register(mContext.getContentResolver());
94             mSettingObserver.onChange(false, null);
95         }
96     }
97 
98     @Override
onPause()99     public void onPause() {
100         if (mSettingObserver != null) {
101             mSettingObserver.unregister(mContext.getContentResolver());
102         }
103     }
104 
getPolicy()105     protected NotificationManager.Policy getPolicy() {
106         return mNotificationManager.getNotificationPolicy();
107     }
108 
getZenModeConfig()109     protected ZenModeConfig getZenModeConfig() {
110         return mNotificationManager.getZenModeConfig();
111     }
112 
getZenMode()113     protected int getZenMode() {
114         return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
115                 mBackend.mZenMode);
116     }
117 
getZenDuration()118     protected int getZenDuration() {
119         return Settings.Global.getInt(mContext.getContentResolver(), Settings.Global.ZEN_DURATION,
120                 0);
121     }
122 
123     class SettingObserver extends ContentObserver {
124         private final Uri ZEN_MODE_URI = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
125         private final Uri ZEN_MODE_CONFIG_ETAG_URI = Settings.Global.getUriFor(
126                 Settings.Global.ZEN_MODE_CONFIG_ETAG);
127         private final Uri ZEN_MODE_DURATION_URI = Settings.Global.getUriFor(
128                 Settings.Global.ZEN_DURATION);
129 
130         private final Preference mPreference;
131 
SettingObserver(Preference preference)132         public SettingObserver(Preference preference) {
133             super(new Handler());
134             mPreference = preference;
135         }
136 
register(ContentResolver cr)137         public void register(ContentResolver cr) {
138             cr.registerContentObserver(ZEN_MODE_URI, false, this, UserHandle.USER_ALL);
139             cr.registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false, this, UserHandle.USER_ALL);
140             cr.registerContentObserver(ZEN_MODE_DURATION_URI, false, this, UserHandle.USER_ALL);
141         }
142 
unregister(ContentResolver cr)143         public void unregister(ContentResolver cr) {
144             cr.unregisterContentObserver(this);
145         }
146 
147         @Override
onChange(boolean selfChange, Uri uri)148         public void onChange(boolean selfChange, Uri uri) {
149             super.onChange(selfChange, uri);
150             if (uri == null || ZEN_MODE_URI.equals(uri) || ZEN_MODE_CONFIG_ETAG_URI.equals(uri)
151                     || ZEN_MODE_DURATION_URI.equals(uri)) {
152                 mBackend.updatePolicy();
153                 mBackend.updateZenMode();
154                 if (mScreen != null) {
155                     displayPreference(mScreen);
156                 }
157                 updateState(mPreference);
158             }
159         }
160     }
161 
162     /**
163      * Wrapper for testing compatibility
164      */
165     @VisibleForTesting
166     static class ZenModeConfigWrapper {
167         private final Context mContext;
168 
ZenModeConfigWrapper(Context context)169         public ZenModeConfigWrapper(Context context) {
170             mContext = context;
171         }
172 
getOwnerCaption(String owner)173         protected String getOwnerCaption(String owner) {
174             return ZenModeConfig.getOwnerCaption(mContext, owner);
175         }
176 
isTimeRule(Uri id)177         protected boolean isTimeRule(Uri id) {
178             return ZenModeConfig.isValidEventConditionId(id) ||
179                     ZenModeConfig.isValidScheduleConditionId(id);
180         }
181 
getFormattedTime(long time, int userHandle)182         protected CharSequence getFormattedTime(long time, int userHandle) {
183             return ZenModeConfig.getFormattedTime(mContext, time, isToday(time), userHandle);
184         }
185 
isToday(long time)186         private boolean isToday(long time) {
187             return ZenModeConfig.isToday(time);
188         }
189 
parseManualRuleTime(Uri id)190         protected long parseManualRuleTime(Uri id) {
191             return ZenModeConfig.tryParseCountdownConditionId(id);
192         }
193 
parseAutomaticRuleEndTime(Uri id)194         protected long parseAutomaticRuleEndTime(Uri id) {
195             if (ZenModeConfig.isValidEventConditionId(id)) {
196                 // cannot look up end times for events
197                 return Long.MAX_VALUE;
198             }
199 
200             if (ZenModeConfig.isValidScheduleConditionId(id)) {
201                 ScheduleCalendar schedule = ZenModeConfig.toScheduleCalendar(id);
202                 long endTimeMs = schedule.getNextChangeTime(System.currentTimeMillis());
203 
204                 // check if automatic rule will end on next alarm
205                 if (schedule.exitAtAlarm()) {
206                     long nextAlarm = getNextAlarm(mContext);
207                     schedule.maybeSetNextAlarm(System.currentTimeMillis(), nextAlarm);
208                     if (schedule.shouldExitForAlarm(endTimeMs)) {
209                         return nextAlarm;
210                     }
211                 }
212 
213                 return endTimeMs;
214             }
215 
216             return -1;
217         }
218     }
219 
getNextAlarm(Context context)220     private static long getNextAlarm(Context context) {
221         final AlarmManager alarms = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
222         final AlarmClockInfo info = alarms.getNextAlarmClock(ActivityManager.getCurrentUser());
223         return info != null ? info.getTriggerTime() : 0;
224     }
225 }
226