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