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