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