1 /* 2 * Copyright (C) 2016 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 static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS; 20 import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS; 21 22 import android.app.admin.DevicePolicyManager; 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.os.UserManager; 30 import android.provider.Settings; 31 import android.support.v7.preference.Preference; 32 import android.support.v7.preference.PreferenceScreen; 33 import android.text.TextUtils; 34 import android.util.Log; 35 36 import com.android.internal.widget.LockPatternUtils; 37 import com.android.settings.R; 38 import com.android.settings.RestrictedListPreference; 39 import com.android.settings.Utils; 40 import com.android.settings.core.PreferenceControllerMixin; 41 import com.android.settings.overlay.FeatureFactory; 42 import com.android.settingslib.RestrictedLockUtils; 43 import com.android.settingslib.core.AbstractPreferenceController; 44 import com.android.settingslib.core.lifecycle.LifecycleObserver; 45 import com.android.settingslib.core.lifecycle.events.OnPause; 46 import com.android.settingslib.core.lifecycle.events.OnResume; 47 48 import java.util.ArrayList; 49 50 public class LockScreenNotificationPreferenceController extends AbstractPreferenceController 51 implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener, 52 LifecycleObserver, OnResume, OnPause { 53 54 private static final String TAG = "LockScreenNotifPref"; 55 56 private final String mSettingKey; 57 private final String mWorkSettingCategoryKey; 58 private final String mWorkSettingKey; 59 60 private RestrictedListPreference mLockscreen; 61 private RestrictedListPreference mLockscreenProfile; 62 63 private final int mProfileUserId; 64 private final boolean mSecure; 65 private final boolean mSecureProfile; 66 67 private SettingObserver mSettingObserver; 68 private int mLockscreenSelectedValue; 69 private int mLockscreenSelectedValueProfile; 70 71 public LockScreenNotificationPreferenceController(Context context) { 72 this(context, null, null, null); 73 } 74 75 public LockScreenNotificationPreferenceController(Context context, 76 String settingKey, String workSettingCategoryKey, String workSettingKey) { 77 super(context); 78 mSettingKey = settingKey; 79 mWorkSettingCategoryKey = workSettingCategoryKey; 80 mWorkSettingKey = workSettingKey; 81 82 mProfileUserId = Utils.getManagedProfileId(UserManager.get(context), UserHandle.myUserId()); 83 final LockPatternUtils utils = FeatureFactory.getFactory(context) 84 .getSecurityFeatureProvider() 85 .getLockPatternUtils(context); 86 mSecure = utils.isSecure(UserHandle.myUserId()); 87 mSecureProfile = (mProfileUserId != UserHandle.USER_NULL) && utils.isSecure(mProfileUserId); 88 } 89 90 @Override 91 public void displayPreference(PreferenceScreen screen) { 92 super.displayPreference(screen); 93 mLockscreen = (RestrictedListPreference) screen.findPreference(mSettingKey); 94 if (mLockscreen == null) { 95 Log.i(TAG, "Preference not found: " + mSettingKey); 96 return; 97 } 98 if (mProfileUserId != UserHandle.USER_NULL) { 99 mLockscreenProfile = (RestrictedListPreference) screen.findPreference(mWorkSettingKey); 100 mLockscreenProfile.setRequiresActiveUnlockedProfile(true); 101 mLockscreenProfile.setProfileUserId(mProfileUserId); 102 } else { 103 setVisible(screen, mWorkSettingKey, false /* visible */); 104 setVisible(screen, mWorkSettingCategoryKey, false /* visible */); 105 } 106 mSettingObserver = new SettingObserver(); 107 initLockScreenNotificationPrefDisplay(); 108 initLockscreenNotificationPrefForProfile(); 109 } 110 111 private void initLockScreenNotificationPrefDisplay() { 112 ArrayList<CharSequence> entries = new ArrayList<>(); 113 ArrayList<CharSequence> values = new ArrayList<>(); 114 115 String summaryShowEntry = 116 mContext.getString(R.string.lock_screen_notifications_summary_show); 117 String summaryShowEntryValue = 118 Integer.toString(R.string.lock_screen_notifications_summary_show); 119 entries.add(summaryShowEntry); 120 values.add(summaryShowEntryValue); 121 setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue, 122 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS); 123 124 if (mSecure) { 125 String summaryHideEntry = 126 mContext.getString(R.string.lock_screen_notifications_summary_hide); 127 String summaryHideEntryValue = 128 Integer.toString(R.string.lock_screen_notifications_summary_hide); 129 entries.add(summaryHideEntry); 130 values.add(summaryHideEntryValue); 131 setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue, 132 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS); 133 } 134 135 entries.add(mContext.getString(R.string.lock_screen_notifications_summary_disable)); 136 values.add(Integer.toString(R.string.lock_screen_notifications_summary_disable)); 137 138 139 mLockscreen.setEntries(entries.toArray(new CharSequence[entries.size()])); 140 mLockscreen.setEntryValues(values.toArray(new CharSequence[values.size()])); 141 updateLockscreenNotifications(); 142 143 if (mLockscreen.getEntries().length > 1) { 144 mLockscreen.setOnPreferenceChangeListener(this); 145 } else { 146 // There is one or less option for the user, disable the drop down. 147 mLockscreen.setEnabled(false); 148 } 149 } 150 151 private void initLockscreenNotificationPrefForProfile() { 152 if (mLockscreenProfile == null) { 153 Log.i(TAG, "Preference not found: " + mWorkSettingKey); 154 return; 155 } 156 ArrayList<CharSequence> entries = new ArrayList<>(); 157 ArrayList<CharSequence> values = new ArrayList<>(); 158 159 String summaryShowEntry = mContext.getString( 160 R.string.lock_screen_notifications_summary_show_profile); 161 String summaryShowEntryValue = Integer.toString( 162 R.string.lock_screen_notifications_summary_show_profile); 163 entries.add(summaryShowEntry); 164 values.add(summaryShowEntryValue); 165 setRestrictedIfNotificationFeaturesDisabled(summaryShowEntry, summaryShowEntryValue, 166 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS | KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS); 167 168 if (mSecureProfile) { 169 String summaryHideEntry = mContext.getString( 170 R.string.lock_screen_notifications_summary_hide_profile); 171 String summaryHideEntryValue = Integer.toString( 172 R.string.lock_screen_notifications_summary_hide_profile); 173 entries.add(summaryHideEntry); 174 values.add(summaryHideEntryValue); 175 setRestrictedIfNotificationFeaturesDisabled(summaryHideEntry, summaryHideEntryValue, 176 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS); 177 } 178 179 mLockscreenProfile.setEntries(entries.toArray(new CharSequence[entries.size()])); 180 mLockscreenProfile.setEntryValues(values.toArray(new CharSequence[values.size()])); 181 updateLockscreenNotificationsForProfile(); 182 if (mLockscreenProfile.getEntries().length > 1) { 183 mLockscreenProfile.setOnPreferenceChangeListener(this); 184 } else { 185 // There is one or less option for the user, disable the drop down. 186 mLockscreenProfile.setEnabled(false); 187 } 188 } 189 190 @Override 191 public String getPreferenceKey() { 192 return null; 193 } 194 195 @Override 196 public boolean isAvailable() { 197 return false; 198 } 199 200 @Override 201 public void onResume() { 202 if (mSettingObserver != null) { 203 mSettingObserver.register(mContext.getContentResolver(), true /* register */); 204 } 205 } 206 207 @Override 208 public void onPause() { 209 if (mSettingObserver != null) { 210 mSettingObserver.register(mContext.getContentResolver(), false /* register */); 211 } 212 } 213 214 @Override 215 public boolean onPreferenceChange(Preference preference, Object newValue) { 216 final String key = preference.getKey(); 217 if (TextUtils.equals(mWorkSettingKey, key)) { 218 final int val = Integer.parseInt((String) newValue); 219 if (val == mLockscreenSelectedValueProfile) { 220 return false; 221 } 222 final boolean show = val == R.string.lock_screen_notifications_summary_show_profile; 223 Settings.Secure.putIntForUser(mContext.getContentResolver(), 224 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 225 show ? 1 : 0, mProfileUserId); 226 mLockscreenSelectedValueProfile = val; 227 return true; 228 } else if (TextUtils.equals(mSettingKey, key)) { 229 final int val = Integer.parseInt((String) newValue); 230 if (val == mLockscreenSelectedValue) { 231 return false; 232 } 233 final boolean enabled = val != R.string.lock_screen_notifications_summary_disable; 234 final boolean show = val == R.string.lock_screen_notifications_summary_show; 235 Settings.Secure.putInt(mContext.getContentResolver(), 236 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0); 237 Settings.Secure.putInt(mContext.getContentResolver(), 238 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0); 239 mLockscreenSelectedValue = val; 240 return true; 241 } 242 return false; 243 } 244 245 private void setRestrictedIfNotificationFeaturesDisabled(CharSequence entry, 246 CharSequence entryValue, int keyguardNotificationFeatures) { 247 RestrictedLockUtils.EnforcedAdmin admin = 248 RestrictedLockUtils.checkIfKeyguardFeaturesDisabled( 249 mContext, keyguardNotificationFeatures, UserHandle.myUserId()); 250 if (admin != null && mLockscreen != null) { 251 RestrictedListPreference.RestrictedItem item = 252 new RestrictedListPreference.RestrictedItem(entry, entryValue, admin); 253 mLockscreen.addRestrictedItem(item); 254 } 255 if (mProfileUserId != UserHandle.USER_NULL) { 256 RestrictedLockUtils.EnforcedAdmin profileAdmin = 257 RestrictedLockUtils.checkIfKeyguardFeaturesDisabled( 258 mContext, keyguardNotificationFeatures, mProfileUserId); 259 if (profileAdmin != null && mLockscreenProfile != null) { 260 RestrictedListPreference.RestrictedItem item = 261 new RestrictedListPreference.RestrictedItem( 262 entry, entryValue, profileAdmin); 263 mLockscreenProfile.addRestrictedItem(item); 264 } 265 } 266 } 267 268 public static int getSummaryResource(Context context) { 269 final boolean enabled = getLockscreenNotificationsEnabled(context); 270 final boolean secure = FeatureFactory.getFactory(context) 271 .getSecurityFeatureProvider() 272 .getLockPatternUtils(context) 273 .isSecure(UserHandle.myUserId()); 274 final boolean allowPrivate = !secure 275 || getAllowPrivateNotifications(context, UserHandle.myUserId()); 276 return !enabled ? R.string.lock_screen_notifications_summary_disable : 277 allowPrivate ? R.string.lock_screen_notifications_summary_show : 278 R.string.lock_screen_notifications_summary_hide; 279 } 280 281 private void updateLockscreenNotifications() { 282 if (mLockscreen == null) { 283 return; 284 } 285 mLockscreenSelectedValue = getSummaryResource(mContext); 286 mLockscreen.setSummary("%s"); 287 mLockscreen.setValue(Integer.toString(mLockscreenSelectedValue)); 288 } 289 290 private boolean adminAllowsUnredactedNotifications(int userId) { 291 final int dpmFlags = mContext.getSystemService(DevicePolicyManager.class) 292 .getKeyguardDisabledFeatures(null/* admin */, userId); 293 return (dpmFlags & KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0; 294 } 295 296 private void updateLockscreenNotificationsForProfile() { 297 if (mProfileUserId == UserHandle.USER_NULL) { 298 return; 299 } 300 if (mLockscreenProfile == null) { 301 return; 302 } 303 final boolean allowPrivate = adminAllowsUnredactedNotifications(mProfileUserId) && 304 (!mSecureProfile || getAllowPrivateNotifications(mContext, mProfileUserId)); 305 mLockscreenProfile.setSummary("%s"); 306 mLockscreenSelectedValueProfile = allowPrivate 307 ? R.string.lock_screen_notifications_summary_show_profile 308 : R.string.lock_screen_notifications_summary_hide_profile; 309 mLockscreenProfile.setValue(Integer.toString(mLockscreenSelectedValueProfile)); 310 } 311 312 private static boolean getLockscreenNotificationsEnabled(Context context) { 313 return Settings.Secure.getInt(context.getContentResolver(), 314 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0; 315 } 316 317 private static boolean getAllowPrivateNotifications(Context context, int userId) { 318 return Settings.Secure.getIntForUser(context.getContentResolver(), 319 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0, userId) != 0; 320 } 321 322 class SettingObserver extends ContentObserver { 323 324 private final Uri LOCK_SCREEN_PRIVATE_URI = 325 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); 326 private final Uri LOCK_SCREEN_SHOW_URI = 327 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS); 328 329 public SettingObserver() { 330 super(new Handler()); 331 } 332 333 public void register(ContentResolver cr, boolean register) { 334 if (register) { 335 cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this); 336 cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this); 337 } else { 338 cr.unregisterContentObserver(this); 339 } 340 } 341 342 @Override 343 public void onChange(boolean selfChange, Uri uri) { 344 super.onChange(selfChange, uri); 345 if (LOCK_SCREEN_PRIVATE_URI.equals(uri) || LOCK_SCREEN_SHOW_URI.equals(uri)) { 346 updateLockscreenNotifications(); 347 if (mProfileUserId != UserHandle.USER_NULL) { 348 updateLockscreenNotificationsForProfile(); 349 } 350 } 351 } 352 } 353 } 354