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