1 /* 2 * Copyright (C) 2019 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.provider.Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS; 22 23 import android.app.KeyguardManager; 24 import android.app.admin.DevicePolicyManager; 25 import android.content.Context; 26 import android.database.ContentObserver; 27 import android.os.Handler; 28 import android.os.Looper; 29 import android.os.UserHandle; 30 import android.os.UserManager; 31 import android.provider.Settings; 32 33 import androidx.preference.Preference; 34 import androidx.preference.PreferenceScreen; 35 36 import com.android.internal.widget.LockPatternUtils; 37 import com.android.settings.Utils; 38 import com.android.settings.core.TogglePreferenceController; 39 import com.android.settings.overlay.FeatureFactory; 40 import com.android.settingslib.core.lifecycle.LifecycleObserver; 41 import com.android.settingslib.core.lifecycle.events.OnStart; 42 import com.android.settingslib.core.lifecycle.events.OnStop; 43 44 /** 45 * The controller of the sensitive notifications. 46 */ 47 public class RedactNotificationPreferenceController extends TogglePreferenceController implements 48 LifecycleObserver, OnStart, OnStop { 49 private static final String TAG = "LockScreenNotifPref"; 50 51 static final String KEY_LOCKSCREEN_REDACT = "lock_screen_redact"; 52 static final String KEY_LOCKSCREEN_WORK_PROFILE_REDACT = "lock_screen_work_redact"; 53 54 private DevicePolicyManager mDpm; 55 private UserManager mUm; 56 private KeyguardManager mKm; 57 private final int mProfileUserId; 58 private Preference mPreference; 59 private ContentObserver mContentObserver = 60 new ContentObserver(new Handler(Looper.getMainLooper())) { 61 @Override 62 public void onChange(boolean selfChange) { 63 if (mPreference != null) { 64 mPreference.setEnabled( 65 getAvailabilityStatus() != DISABLED_DEPENDENT_SETTING); 66 } 67 } 68 }; 69 RedactNotificationPreferenceController(Context context, String settingKey)70 public RedactNotificationPreferenceController(Context context, String settingKey) { 71 super(context, settingKey); 72 73 mUm = context.getSystemService(UserManager.class); 74 mDpm = context.getSystemService(DevicePolicyManager.class); 75 mKm = context.getSystemService(KeyguardManager.class); 76 77 mProfileUserId = Utils.getManagedProfileId(mUm, UserHandle.myUserId()); 78 } 79 80 @Override displayPreference(PreferenceScreen screen)81 public void displayPreference(PreferenceScreen screen) { 82 super.displayPreference(screen); 83 mPreference = screen.findPreference(getPreferenceKey()); 84 } 85 86 @Override isChecked()87 public boolean isChecked() { 88 int userId = KEY_LOCKSCREEN_REDACT.equals(getPreferenceKey()) 89 ? UserHandle.myUserId() : mProfileUserId; 90 91 return getAllowPrivateNotifications(userId); 92 } 93 94 @Override setChecked(boolean isChecked)95 public boolean setChecked(boolean isChecked) { 96 int userId = KEY_LOCKSCREEN_REDACT.equals(getPreferenceKey()) 97 ? UserHandle.myUserId() : mProfileUserId; 98 99 Settings.Secure.putIntForUser(mContext.getContentResolver(), 100 Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, isChecked ? 1 : 0, userId); 101 return true; 102 } 103 104 @Override getAvailabilityStatus()105 public int getAvailabilityStatus() { 106 // hide work profile setting if no work profile 107 if (KEY_LOCKSCREEN_WORK_PROFILE_REDACT.equals(getPreferenceKey()) 108 && mProfileUserId == UserHandle.USER_NULL) { 109 return CONDITIONALLY_UNAVAILABLE; 110 } 111 112 int userId = KEY_LOCKSCREEN_REDACT.equals(getPreferenceKey()) 113 ? UserHandle.myUserId() : mProfileUserId; 114 115 // hide if lockscreen isn't secure for this user 116 final LockPatternUtils utils = FeatureFactory.getFactory(mContext) 117 .getSecurityFeatureProvider() 118 .getLockPatternUtils(mContext); 119 if (!utils.isSecure(userId)) { 120 return CONDITIONALLY_UNAVAILABLE; 121 } 122 123 // all notifs hidden? admin doesn't allow notifs or redacted notifs? disabled 124 if (!getLockscreenNotificationsEnabled(userId) 125 || !adminAllowsNotifications(userId) 126 || !adminAllowsUnredactedNotifications(userId)) { 127 return DISABLED_DEPENDENT_SETTING; 128 } 129 130 // specifically the work profile setting requires the work profile to be unlocked 131 if (KEY_LOCKSCREEN_WORK_PROFILE_REDACT.equals(getPreferenceKey())) { 132 if (mKm.isDeviceLocked(mProfileUserId)) { 133 return DISABLED_DEPENDENT_SETTING; 134 } 135 } 136 137 return AVAILABLE; 138 } 139 140 @Override onStart()141 public void onStart() { 142 mContext.getContentResolver().registerContentObserver( 143 Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS), 144 false /* notifyForDescendants */, mContentObserver); 145 } 146 147 @Override onStop()148 public void onStop() { 149 mContext.getContentResolver().unregisterContentObserver(mContentObserver); 150 } 151 adminAllowsNotifications(int userId)152 private boolean adminAllowsNotifications(int userId) { 153 final int dpmFlags = mDpm.getKeyguardDisabledFeatures(null/* admin */, userId); 154 return (dpmFlags & KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) == 0; 155 } 156 adminAllowsUnredactedNotifications(int userId)157 private boolean adminAllowsUnredactedNotifications(int userId) { 158 final int dpmFlags = mDpm.getKeyguardDisabledFeatures(null/* admin */, userId); 159 return (dpmFlags & KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) == 0; 160 } 161 getAllowPrivateNotifications(int userId)162 private boolean getAllowPrivateNotifications(int userId) { 163 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 164 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1, userId) != 0; 165 } 166 getLockscreenNotificationsEnabled(int userId)167 private boolean getLockscreenNotificationsEnabled(int userId) { 168 return Settings.Secure.getIntForUser(mContext.getContentResolver(), 169 Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 1, userId) != 0; 170 } 171 } 172