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