1 /**
2  * Copyright (C) 2015 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.admin.DevicePolicyManager;
20 import android.content.ContentResolver;
21 import android.content.Context;
22 import android.database.ContentObserver;
23 import android.net.Uri;
24 import android.os.Bundle;
25 import android.os.Handler;
26 import android.os.UserHandle;
27 import android.os.UserManager;
28 import android.provider.Settings;
29 import android.support.v7.preference.Preference;
30 import android.support.v7.preference.Preference.OnPreferenceChangeListener;
31 import android.support.v7.preference.TwoStatePreference;
32 import android.util.Log;
33 import com.android.internal.logging.MetricsProto.MetricsEvent;
34 import com.android.internal.widget.LockPatternUtils;
35 import com.android.settings.R;
36 import com.android.settings.RestrictedListPreference.RestrictedItem;
37 import com.android.settings.SettingsPreferenceFragment;
38 import com.android.settings.Utils;
39 import com.android.settingslib.RestrictedLockUtils;
40 
41 import java.util.ArrayList;
42 
43 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS;
44 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS;
45 import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
46 
47 public class ConfigureNotificationSettings extends SettingsPreferenceFragment {
48     private static final String TAG = "ConfigNotiSettings";
49 
50     private static final String KEY_NOTIFICATION_PULSE = "notification_pulse";
51     private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "lock_screen_notifications";
52     private static final String KEY_LOCK_SCREEN_PROFILE_NOTIFICATIONS =
53             "lock_screen_notifications_profile";
54 
55     private final SettingsObserver mSettingsObserver = new SettingsObserver();
56 
57     private Context mContext;
58 
59     private TwoStatePreference mNotificationPulse;
60     private RestrictedDropDownPreference mLockscreen;
61     private RestrictedDropDownPreference mLockscreenProfile;
62     private boolean mSecure;
63     private boolean mSecureProfile;
64     private int mLockscreenSelectedValue;
65     private int mLockscreenSelectedValueProfile;
66     private int mProfileChallengeUserId;
67 
68     @Override
getMetricsCategory()69     protected int getMetricsCategory() {
70         return MetricsEvent.CONFIGURE_NOTIFICATION;
71     }
72 
73     @Override
onCreate(Bundle savedInstanceState)74     public void onCreate(Bundle savedInstanceState) {
75         super.onCreate(savedInstanceState);
76         mContext = getActivity();
77         mProfileChallengeUserId = Utils.getManagedProfileId(
78                 UserManager.get(mContext), UserHandle.myUserId());
79 
80         final LockPatternUtils utils = new LockPatternUtils(getActivity());
81         final boolean isUnified =
82                 !utils.isSeparateProfileChallengeEnabled(mProfileChallengeUserId);
83 
84         mSecure = utils.isSecure(UserHandle.myUserId());
85         mSecureProfile = (mProfileChallengeUserId != UserHandle.USER_NULL)
86                 && (utils.isSecure(mProfileChallengeUserId) || (isUnified && mSecure));
87 
88         addPreferencesFromResource(R.xml.configure_notification_settings);
89 
90         initPulse();
91         initLockscreenNotifications();
92 
93         if (mProfileChallengeUserId != UserHandle.USER_NULL) {
94             addPreferencesFromResource(R.xml.configure_notification_settings_profile);
95             initLockscreenNotificationsForProfile();
96         }
97 
98     }
99 
100     @Override
onResume()101     public void onResume() {
102         super.onResume();
103         mSettingsObserver.register(true);
104     }
105 
106     @Override
onPause()107     public void onPause() {
108         super.onPause();
109         mSettingsObserver.register(false);
110     }
111 
112     // === Pulse notification light ===
113 
initPulse()114     private void initPulse() {
115         mNotificationPulse =
116                 (TwoStatePreference) getPreferenceScreen().findPreference(KEY_NOTIFICATION_PULSE);
117         if (mNotificationPulse == null) {
118             Log.i(TAG, "Preference not found: " + KEY_NOTIFICATION_PULSE);
119             return;
120         }
121         if (!getResources()
122                 .getBoolean(com.android.internal.R.bool.config_intrusiveNotificationLed)) {
123             getPreferenceScreen().removePreference(mNotificationPulse);
124         } else {
125             updatePulse();
126             mNotificationPulse.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
127                 @Override
128                 public boolean onPreferenceChange(Preference preference, Object newValue) {
129                     final boolean val = (Boolean)newValue;
130                     return Settings.System.putInt(getContentResolver(),
131                             Settings.System.NOTIFICATION_LIGHT_PULSE,
132                             val ? 1 : 0);
133                 }
134             });
135         }
136     }
137 
updatePulse()138     private void updatePulse() {
139         if (mNotificationPulse == null) {
140             return;
141         }
142         try {
143             mNotificationPulse.setChecked(Settings.System.getInt(getContentResolver(),
144                     Settings.System.NOTIFICATION_LIGHT_PULSE) == 1);
145         } catch (Settings.SettingNotFoundException snfe) {
146             Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found");
147         }
148     }
149 
initLockscreenNotifications()150     private void initLockscreenNotifications() {
151         mLockscreen = (RestrictedDropDownPreference) getPreferenceScreen().findPreference(
152                 KEY_LOCK_SCREEN_NOTIFICATIONS);
153         if (mLockscreen == null) {
154             Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS);
155             return;
156         }
157 
158         ArrayList<CharSequence> entries = new ArrayList<>();
159         ArrayList<CharSequence> values = new ArrayList<>();
160         entries.add(getString(R.string.lock_screen_notifications_summary_disable));
161         values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable));
162 
163         String summaryShowEntry = getString(R.string.lock_screen_notifications_summary_show);
164         String summaryShowEntryValue = Integer.toString(
165                 R.string.lock_screen_notifications_summary_show);
166         entries.add(summaryShowEntry);
167         values.add(summaryShowEntryValue);
168         setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
169                 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
170 
171         if (mSecure) {
172             String summaryHideEntry = getString(R.string.lock_screen_notifications_summary_hide);
173             String summaryHideEntryValue = Integer.toString(
174                     R.string.lock_screen_notifications_summary_hide);
175             entries.add(summaryHideEntry);
176             values.add(summaryHideEntryValue);
177             setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
178                     KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
179         }
180 
181         mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()]));
182         mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()]));
183         updateLockscreenNotifications();
184         if (mLockscreen.getEntries().length > 1) {
185             mLockscreen.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
186                 @Override
187                 public boolean onPreferenceChange(Preference preference, Object newValue) {
188                     final int val = Integer.parseInt((String) newValue);
189                     if (val == mLockscreenSelectedValue) {
190                         return false;
191                     }
192                     final boolean enabled =
193                             val != R.string.lock_screen_notifications_summary_disable;
194                     final boolean show = val == R.string.lock_screen_notifications_summary_show;
195                     Settings.Secure.putInt(getContentResolver(),
196                             Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0);
197                     Settings.Secure.putInt(getContentResolver(),
198                             Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0);
199                     mLockscreenSelectedValue = val;
200                     return true;
201                 }
202             });
203         } else {
204             // There is one or less option for the user, disable the drop down.
205             mLockscreen.setEnabled(false);
206         }
207     }
208 
209     // === Lockscreen (public / private) notifications ===
initLockscreenNotificationsForProfile()210     private void initLockscreenNotificationsForProfile() {
211         mLockscreenProfile = (RestrictedDropDownPreference) getPreferenceScreen()
212                 .findPreference(KEY_LOCK_SCREEN_PROFILE_NOTIFICATIONS);
213         if (mLockscreenProfile == null) {
214             Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_PROFILE_NOTIFICATIONS);
215             return;
216         }
217         ArrayList<CharSequence> entries = new ArrayList<>();
218         ArrayList<CharSequence> values = new ArrayList<>();
219         entries.add(getString(R.string.lock_screen_notifications_summary_disable_profile));
220         values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable_profile));
221 
222         String summaryShowEntry = getString(
223                 R.string.lock_screen_notifications_summary_show_profile);
224         String summaryShowEntryValue = Integer.toString(
225                 R.string.lock_screen_notifications_summary_show_profile);
226         entries.add(summaryShowEntry);
227         values.add(summaryShowEntryValue);
228         setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue,
229                 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
230 
231         if (mSecureProfile) {
232             String summaryHideEntry = getString(
233                     R.string.lock_screen_notifications_summary_hide_profile);
234             String summaryHideEntryValue = Integer.toString(
235                     R.string.lock_screen_notifications_summary_hide_profile);
236             entries.add(summaryHideEntry);
237             values.add(summaryHideEntryValue);
238             setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue,
239                     KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
240         }
241 
242         mLockscreenProfile.setOnPreClickListener(
243                 (Preference p) -> Utils.startQuietModeDialogIfNecessary(mContext,
244                         UserManager.get(mContext),
245                         mProfileChallengeUserId)
246         );
247 
248         mLockscreenProfile.setEntries(entries.toArray(new CharSequence[entries.size()]));
249         mLockscreenProfile.setEntryValues(values.toArray(new CharSequence[values.size()]));
250         updateLockscreenNotificationsForProfile();
251         if (mLockscreenProfile.getEntries().length > 1) {
252             mLockscreenProfile.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
253                 @Override
254                 public boolean onPreferenceChange(Preference preference, Object newValue) {
255                     final int val = Integer.parseInt((String) newValue);
256                     if (val == mLockscreenSelectedValueProfile) {
257                         return false;
258                     }
259                     final boolean enabled =
260                             val != R.string.lock_screen_notifications_summary_disable_profile;
261                     final boolean show =
262                             val == R.string.lock_screen_notifications_summary_show_profile;
263                     Settings.Secure.putIntForUser(getContentResolver(),
264                             Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
265                             show ? 1 : 0, mProfileChallengeUserId);
266                     Settings.Secure.putIntForUser(getContentResolver(),
267                             Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS,
268                             enabled ? 1 : 0, mProfileChallengeUserId);
269                     mLockscreenSelectedValueProfile = val;
270                     return true;
271                 }
272             });
273         } else {
274             // There is one or less option for the user, disable the drop down.
275             mLockscreenProfile.setEnabled(false);
276         }
277     }
278 
setRestrictedIfNotificationFeaturesDisabled(CharSequence entry, CharSequence entryValue, int keyguardNotificationFeatures)279     private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry,
280             CharSequence entryValue, int keyguardNotificationFeatures) {
281         EnforcedAdmin admin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
282                 mContext, keyguardNotificationFeatures, UserHandle.myUserId());
283         if (admin != null && mLockscreen != null) {
284             RestrictedDropDownPreference.RestrictedItem item =
285                     new RestrictedDropDownPreference.RestrictedItem(entry, entryValue, admin);
286             mLockscreen.addRestrictedItem(item);
287         }
288         if (mProfileChallengeUserId != UserHandle.USER_NULL) {
289             EnforcedAdmin profileAdmin = RestrictedLockUtils.checkIfKeyguardFeaturesDisabled(
290                     mContext, keyguardNotificationFeatures, mProfileChallengeUserId);
291             if (profileAdmin != null && mLockscreenProfile != null) {
292                 RestrictedDropDownPreference.RestrictedItem item =
293                         new RestrictedDropDownPreference.RestrictedItem(
294                                 entry, entryValue, profileAdmin);
295                 mLockscreenProfile.addRestrictedItem(item);
296             }
297         }
298     }
299 
updateLockscreenNotifications()300     private void updateLockscreenNotifications() {
301         if (mLockscreen == null) {
302             return;
303         }
304         final boolean enabled = getLockscreenNotificationsEnabled(UserHandle.myUserId());
305         final boolean allowPrivate = !mSecure
306                 || getLockscreenAllowPrivateNotifications(UserHandle.myUserId());
307         mLockscreenSelectedValue = !enabled ? R.string.lock_screen_notifications_summary_disable :
308                 allowPrivate ? R.string.lock_screen_notifications_summary_show :
309                 R.string.lock_screen_notifications_summary_hide;
310         mLockscreen.setValue(Integer.toString(mLockscreenSelectedValue));
311     }
312 
updateLockscreenNotificationsForProfile()313     private void updateLockscreenNotificationsForProfile() {
314         if (mProfileChallengeUserId == UserHandle.USER_NULL) {
315             return;
316         }
317         if (mLockscreenProfile == null) {
318             return;
319         }
320         final boolean enabled = getLockscreenNotificationsEnabled(mProfileChallengeUserId);
321         final boolean allowPrivate = !mSecureProfile
322                 || getLockscreenAllowPrivateNotifications(mProfileChallengeUserId);
323         mLockscreenSelectedValueProfile = !enabled
324                 ? R.string.lock_screen_notifications_summary_disable_profile
325                         : (allowPrivate ? R.string.lock_screen_notifications_summary_show_profile
326                                 : R.string.lock_screen_notifications_summary_hide_profile);
327         mLockscreenProfile.setValue(Integer.toString(mLockscreenSelectedValueProfile));
328     }
329 
getLockscreenNotificationsEnabled(int userId)330     private boolean getLockscreenNotificationsEnabled(int userId) {
331         return Settings.Secure.getIntForUser(getContentResolver(),
332                 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0, userId) != 0;
333     }
334 
getLockscreenAllowPrivateNotifications(int userId)335     private boolean getLockscreenAllowPrivateNotifications(int userId) {
336         return Settings.Secure.getIntForUser(getContentResolver(),
337                 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userId) != 0;
338     }
339 
340 
341     // === Callbacks ===
342 
343     private final class SettingsObserver extends ContentObserver {
344         private final Uri NOTIFICATION_LIGHT_PULSE_URI =
345                 Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
346         private final Uri LOCK_SCREEN_PRIVATE_URI =
347                 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
348         private final Uri LOCK_SCREEN_SHOW_URI =
349                 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS);
350 
SettingsObserver()351         public SettingsObserver() {
352             super(new Handler());
353         }
354 
register(boolean register)355         public void register(boolean register) {
356             final ContentResolver cr = getContentResolver();
357             if (register) {
358                 cr.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this);
359                 cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this);
360                 cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this);
361             } else {
362                 cr.unregisterContentObserver(this);
363             }
364         }
365 
366         @Override
onChange(boolean selfChange, Uri uri)367         public void onChange(boolean selfChange, Uri uri) {
368             super.onChange(selfChange, uri);
369             if (NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) {
370                 updatePulse();
371             }
372             if (LOCK_SCREEN_PRIVATE_URI.equals(uri) || LOCK_SCREEN_SHOW_URI.equals(uri)) {
373                 updateLockscreenNotifications();
374                 if (mProfileChallengeUserId != UserHandle.USER_NULL) {
375                     updateLockscreenNotificationsForProfile();
376                 }
377             }
378         }
379     }
380 }
381