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 import static android.provider.Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS;
23 
24 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
25 import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
26 import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
27 
28 import static com.google.common.truth.Truth.assertThat;
29 
30 import static org.mockito.ArgumentMatchers.anyInt;
31 import static org.mockito.ArgumentMatchers.eq;
32 import static org.mockito.Mockito.when;
33 
34 import android.app.KeyguardManager;
35 import android.app.admin.DevicePolicyManager;
36 import android.content.Context;
37 import android.content.pm.UserInfo;
38 import android.os.UserHandle;
39 import android.os.UserManager;
40 import android.provider.Settings;
41 
42 import androidx.preference.PreferenceScreen;
43 
44 import com.android.internal.widget.LockPatternUtils;
45 import com.android.settings.testutils.FakeFeatureFactory;
46 import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
47 import com.android.settings.testutils.shadow.ShadowUtils;
48 import com.android.settingslib.RestrictedSwitchPreference;
49 
50 import org.junit.After;
51 import org.junit.Before;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 import org.mockito.Mock;
55 import org.mockito.MockitoAnnotations;
56 import org.robolectric.RobolectricTestRunner;
57 import org.robolectric.RuntimeEnvironment;
58 import org.robolectric.annotation.Config;
59 
60 import java.util.Arrays;
61 
62 @RunWith(RobolectricTestRunner.class)
63 @Config(shadows = {
64         ShadowUtils.class,
65         ShadowRestrictedLockUtilsInternal.class,
66 })
67 public class RedactNotificationPreferenceControllerTest {
68 
69     @Mock
70     private DevicePolicyManager mDpm;
71     @Mock
72     UserManager mUm;
73     @Mock
74     KeyguardManager mKm;
75     @Mock
76     private PreferenceScreen mScreen;
77     @Mock
78     private LockPatternUtils mLockPatternUtils;
79     @Mock
80     private Context mMockContext;
81 
82     private Context mContext;
83     private RedactNotificationPreferenceController mController;
84     private RedactNotificationPreferenceController mWorkController;
85     private RestrictedSwitchPreference mPreference;
86     private RestrictedSwitchPreference mWorkPreference;
87 
88     @Before
setUp()89     public void setUp() {
90         MockitoAnnotations.initMocks(this);
91         mContext = RuntimeEnvironment.application;
92 
93         FakeFeatureFactory featureFactory = FakeFeatureFactory.setupForTest();
94         when(featureFactory.securityFeatureProvider.getLockPatternUtils(mMockContext))
95                 .thenReturn(mLockPatternUtils);
96         when(mMockContext.getContentResolver()).thenReturn(mContext.getContentResolver());
97         when(mMockContext.getSystemService(UserManager.class)).thenReturn(mUm);
98         when(mMockContext.getSystemService(DevicePolicyManager.class)).thenReturn(mDpm);
99         when(mMockContext.getSystemService(KeyguardManager.class)).thenReturn(mKm);
100         when(mUm.getProfiles(anyInt())).thenReturn(Arrays.asList(new UserInfo(0, "", 0)));
101 
102         mController = new RedactNotificationPreferenceController(
103                 mMockContext, RedactNotificationPreferenceController.KEY_LOCKSCREEN_REDACT);
104         mPreference = new RestrictedSwitchPreference(mContext);
105         mPreference.setKey(mController.getPreferenceKey());
106         when(mScreen.findPreference(
107                 mController.getPreferenceKey())).thenReturn(mPreference);
108         assertThat(mController.mProfileUserId).isEqualTo(0);
109 
110         when(mUm.getProfiles(anyInt())).thenReturn(Arrays.asList(
111                 new UserInfo(5, "", 0),
112                 new UserInfo(10, "", UserInfo.FLAG_MANAGED_PROFILE | UserInfo.FLAG_PROFILE)));
113         mWorkController = new RedactNotificationPreferenceController(mMockContext,
114                 RedactNotificationPreferenceController.KEY_LOCKSCREEN_WORK_PROFILE_REDACT);
115         mWorkPreference = new RestrictedSwitchPreference(mContext);
116         mWorkPreference.setKey(mWorkController.getPreferenceKey());
117         when(mScreen.findPreference(
118                 mWorkController.getPreferenceKey())).thenReturn(mWorkPreference);
119         assertThat(mWorkController.mProfileUserId).isEqualTo(10);
120     }
121 
122     @After
tearDown()123     public void tearDown() {
124         ShadowRestrictedLockUtilsInternal.reset();
125     }
126 
127     @Test
getAvailabilityStatus_noSecureLockscreen()128     public void getAvailabilityStatus_noSecureLockscreen() {
129         when(mLockPatternUtils.isSecure(anyInt())).thenReturn(false);
130         Settings.Secure.putIntForUser(mContext.getContentResolver(),
131                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
132                 1, 0);
133         Settings.Secure.putIntForUser(mContext.getContentResolver(),
134                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
135                 1, 10);
136 
137         assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
138         assertThat(mWorkController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
139     }
140 
141     @Test
getAvailabilityStatus_noWorkProfile()142     public void getAvailabilityStatus_noWorkProfile() {
143         // reset controllers with no work profile
144         when(mUm.getProfiles(anyInt())).thenReturn(Arrays.asList(
145                 new UserInfo(UserHandle.myUserId(), "", 0)));
146         mWorkController = new RedactNotificationPreferenceController(mMockContext,
147                 RedactNotificationPreferenceController.KEY_LOCKSCREEN_WORK_PROFILE_REDACT);
148         mController = new RedactNotificationPreferenceController(mMockContext,
149                 RedactNotificationPreferenceController.KEY_LOCKSCREEN_REDACT);
150 
151         // should otherwise show
152         when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
153         Settings.Secure.putIntForUser(mContext.getContentResolver(),
154                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
155                 1, 0);
156 
157         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
158         assertThat(mWorkController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
159     }
160 
161     @Test
displayPreference_adminSaysNoRedaction()162     public void displayPreference_adminSaysNoRedaction() {
163         ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(
164                 KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS);
165 
166         mController.displayPreference(mScreen);
167         RestrictedSwitchPreference primaryPref =
168                 mScreen.findPreference(mController.getPreferenceKey());
169         assertThat(primaryPref.isDisabledByAdmin()).isTrue();
170         mWorkController.displayPreference(mScreen);
171         RestrictedSwitchPreference workPref =
172                 mScreen.findPreference(mWorkController.getPreferenceKey());
173         assertThat(workPref.isDisabledByAdmin()).isTrue();
174     }
175 
176     @Test
displayPreference_adminSaysNoSecure()177     public void displayPreference_adminSaysNoSecure() {
178         ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(
179                 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
180 
181         mController.displayPreference(mScreen);
182         RestrictedSwitchPreference primaryPref =
183                 mScreen.findPreference(mController.getPreferenceKey());
184         assertThat(primaryPref.isDisabledByAdmin()).isTrue();
185         mWorkController.displayPreference(mScreen);
186         RestrictedSwitchPreference workPref =
187                 mScreen.findPreference(mWorkController.getPreferenceKey());
188         assertThat(workPref.isDisabledByAdmin()).isTrue();
189     }
190 
191     @Test
displayPreference()192     public void displayPreference() {
193         ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(0);
194 
195         mController.displayPreference(mScreen);
196         RestrictedSwitchPreference primaryPref =
197                 mScreen.findPreference(mController.getPreferenceKey());
198         assertThat(primaryPref.isDisabledByAdmin()).isFalse();
199         mWorkController.displayPreference(mScreen);
200         RestrictedSwitchPreference workPref =
201                 mScreen.findPreference(mWorkController.getPreferenceKey());
202         assertThat(workPref.isDisabledByAdmin()).isFalse();
203     }
204 
205     @Test
getAvailabilityStatus_adminSaysNoNotifications()206     public void getAvailabilityStatus_adminSaysNoNotifications() {
207         when(mDpm.getKeyguardDisabledFeatures(eq(null), anyInt())).thenReturn(
208                 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
209 
210         // should otherwise show
211         when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
212         Settings.Secure.putIntForUser(mContext.getContentResolver(),
213                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
214                 1, 0);
215         Settings.Secure.putIntForUser(mContext.getContentResolver(),
216                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
217                 1, 10);
218 
219         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
220         assertThat(mWorkController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
221     }
222 
223     @Test
getAvailabilityStatus_noNotifications()224     public void getAvailabilityStatus_noNotifications() {
225         when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
226 
227         Settings.Secure.putIntForUser(mContext.getContentResolver(),
228                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
229                 0, 0);
230         Settings.Secure.putIntForUser(mContext.getContentResolver(),
231                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
232                 0, 10);
233 
234         assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
235         assertThat(mWorkController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
236     }
237 
238     @Test
getAvailabilityStatus_workProfileLocked()239     public void getAvailabilityStatus_workProfileLocked() {
240         // should otherwise show
241         when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
242         Settings.Secure.putIntForUser(mContext.getContentResolver(),
243                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
244                 1, 0);
245         Settings.Secure.putIntForUser(mContext.getContentResolver(),
246                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
247                 1, 10);
248 
249         when(mKm.isDeviceLocked(10)).thenReturn(true);
250 
251         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
252         assertThat(mWorkController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
253     }
254 
255     @Test
getAvailabilityStatus_show()256     public void getAvailabilityStatus_show() {
257         // should otherwise show
258         when(mLockPatternUtils.isSecure(anyInt())).thenReturn(true);
259         Settings.Secure.putIntForUser(mContext.getContentResolver(),
260                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
261                 1, 0);
262         Settings.Secure.putIntForUser(mContext.getContentResolver(),
263                 LOCK_SCREEN_SHOW_NOTIFICATIONS,
264                 1, 10);
265 
266         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
267         assertThat(mWorkController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
268     }
269 
270     @Test
isChecked()271     public void isChecked() {
272         Settings.Secure.putIntForUser(mContext.getContentResolver(),
273                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
274                 1, 0);
275 
276         assertThat(mController.isChecked()).isTrue();
277 
278         Settings.Secure.putIntForUser(mContext.getContentResolver(),
279                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
280                 0, 0);
281 
282         assertThat(mController.isChecked()).isFalse();
283     }
284 
285     @Test
isChecked_work()286     public void isChecked_work() {
287         Settings.Secure.putIntForUser(mContext.getContentResolver(),
288                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
289                 1, 10);
290 
291         assertThat(mWorkController.isChecked()).isTrue();
292 
293         Settings.Secure.putIntForUser(mContext.getContentResolver(),
294                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
295                 0, 10);
296 
297         assertThat(mWorkController.isChecked()).isFalse();
298     }
299 
300     @Test
isChecked_admin()301     public void isChecked_admin() {
302         Settings.Secure.putIntForUser(mContext.getContentResolver(),
303                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
304                 1, 0);
305 
306         ShadowRestrictedLockUtilsInternal.setKeyguardDisabledFeatures(
307                 KEYGUARD_DISABLE_SECURE_NOTIFICATIONS);
308 
309         assertThat(mController.isChecked()).isFalse();
310     }
311 
312     @Test
setChecked_false()313     public void setChecked_false() throws Exception {
314         Settings.Secure.putIntForUser(mContext.getContentResolver(),
315                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
316                 1, 0);
317 
318         mController.setChecked(false);
319         assertThat(Settings.Secure.getIntForUser(
320                 mContext.getContentResolver(), LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0))
321                 .isEqualTo(0);
322     }
323 
324     @Test
setChecked_workProfile_false()325     public void setChecked_workProfile_false() throws Exception {
326         Settings.Secure.putIntForUser(mContext.getContentResolver(),
327                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
328                 1, 10);
329 
330         mWorkController.setChecked(false);
331         assertThat(Settings.Secure.getIntForUser(
332                 mContext.getContentResolver(), LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 10))
333                 .isEqualTo(0);
334     }
335 
336     @Test
setChecked_true()337     public void setChecked_true() throws Exception {
338         Settings.Secure.putIntForUser(mContext.getContentResolver(),
339                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
340                 0, 0);
341         Settings.Secure.putIntForUser(mContext.getContentResolver(),
342                 LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS,
343                 0, 10);
344 
345         mController.setChecked(true);
346         mWorkController.setChecked(true);
347         assertThat(Settings.Secure.getIntForUser(
348                 mContext.getContentResolver(), LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 10))
349                 .isEqualTo(1);
350         assertThat(Settings.Secure.getIntForUser(
351                 mContext.getContentResolver(), LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0))
352                 .isEqualTo(1);
353     }
354 }
355 
356