1 /*
2  * Copyright (C) 2021 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.security;
18 
19 import static android.content.Context.FACE_SERVICE;
20 import static android.content.Context.FINGERPRINT_SERVICE;
21 import static android.content.pm.PackageManager.FEATURE_FACE;
22 import static android.content.pm.PackageManager.FEATURE_FINGERPRINT;
23 
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.Mockito.doReturn;
28 import static org.mockito.Mockito.spy;
29 import static org.mockito.Mockito.when;
30 
31 import android.content.Context;
32 import android.content.pm.PackageManager;
33 import android.hardware.face.FaceManager;
34 import android.hardware.fingerprint.FingerprintManager;
35 import android.os.Looper;
36 
37 import androidx.lifecycle.Lifecycle;
38 import androidx.preference.Preference;
39 import androidx.preference.PreferenceManager;
40 import androidx.preference.PreferenceScreen;
41 import androidx.test.annotation.UiThreadTest;
42 import androidx.test.core.app.ApplicationProvider;
43 import androidx.test.ext.junit.runners.AndroidJUnit4;
44 
45 import com.android.settings.TestUtils;
46 import com.android.settings.biometrics.combination.CombinedBiometricStatusPreferenceController;
47 import com.android.settings.biometrics.face.FaceStatusPreferenceController;
48 import com.android.settings.biometrics.fingerprint.FingerprintStatusPreferenceController;
49 import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
50 import com.android.settings.search.BaseSearchIndexProvider;
51 import com.android.settings.security.trustagent.TrustAgentManager;
52 import com.android.settings.testutils.FakeFeatureFactory;
53 import com.android.settingslib.RestrictedPreference;
54 import com.android.settingslib.core.AbstractPreferenceController;
55 
56 import org.junit.Before;
57 import org.junit.Test;
58 import org.junit.runner.RunWith;
59 import org.mockito.Mock;
60 import org.mockito.MockitoAnnotations;
61 
62 import java.util.List;
63 
64 @RunWith(AndroidJUnit4.class)
65 public class SecuritySettingsTest {
66     private Context mContext;
67     private SecuritySettingsFeatureProvider mSecuritySettingsFeatureProvider;
68     private SecuritySettings mSecuritySettings;
69     private Preference mPreference;
70     private RestrictedPreference mPreferenceFace;
71     private RestrictedPreference mPreferenceFingerprint;
72     private RestrictedPreference mPreferenceCombined;
73 
74     @Mock
75     private TrustAgentManager mTrustAgentManager;
76     @Mock
77     private FaceManager mFaceManager;
78     @Mock
79     private FingerprintManager mFingerprintManager;
80     @Mock
81     private PackageManager mPackageManager;
82     @Mock
83     private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
84 
85     private PreferenceScreen mScreen;
86 
87     @Before
88     @UiThreadTest
setup()89     public void setup() {
90         if (Looper.myLooper() == null) {
91             Looper.prepare();
92         }
93 
94         MockitoAnnotations.initMocks(this);
95         SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
96         mContext = spy(ApplicationProvider.getApplicationContext());
97         when(mContext.getPackageManager()).thenReturn(mPackageManager);
98         when(mPackageManager.hasSystemFeature(FEATURE_FACE)).thenReturn(true);
99         when(mPackageManager.hasSystemFeature(FEATURE_FINGERPRINT)).thenReturn(true);
100         doReturn(mFaceManager).when(mContext).getSystemService(FACE_SERVICE);
101         doReturn(mFingerprintManager).when(mContext).getSystemService(FINGERPRINT_SERVICE);
102         FakeFeatureFactory mFeatureFactory = FakeFeatureFactory.setupForTest();
103         SecurityFeatureProvider mSecurityFeatureProvider =
104                 mFeatureFactory.getSecurityFeatureProvider();
105         when(mSecurityFeatureProvider.getTrustAgentManager()).thenReturn(mTrustAgentManager);
106         mSecuritySettingsFeatureProvider = mFeatureFactory.getSecuritySettingsFeatureProvider();
107         mSecuritySettings = new SecuritySettings();
108 
109         PreferenceManager preferenceManager = new PreferenceManager(mContext);
110         mScreen = preferenceManager.createPreferenceScreen(mContext);
111         mPreference = new Preference(mContext);
112         mPreference.setKey(SecuritySettings.SECURITY_CATEGORY);
113 
114         mPreferenceFace = new RestrictedPreference(mContext);
115         mPreferenceFingerprint = new RestrictedPreference(mContext);
116         mPreferenceCombined = new RestrictedPreference(mContext);
117 
118         mPreferenceFace.setKey(FaceStatusPreferenceController
119                 .KEY_FACE_SETTINGS);
120         mPreferenceFingerprint.setKey(FingerprintStatusPreferenceController
121                 .KEY_FINGERPRINT_SETTINGS);
122         mPreferenceCombined.setKey(CombinedBiometricStatusPreferenceController
123                 .KEY_BIOMETRIC_SETTINGS);
124 
125         mScreen.addPreference(mPreference);
126         mScreen.addPreference(mPreferenceFace);
127         mScreen.addPreference(mPreferenceFingerprint);
128         mScreen.addPreference(mPreferenceCombined);
129     }
130 
131     @Test
noAlternativeFragmentAvailableAndSafetyCenterIsDisabled_pageIndexIncluded()132     public void noAlternativeFragmentAvailableAndSafetyCenterIsDisabled_pageIndexIncluded()
133             throws Exception {
134         when(mSecuritySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment()).thenReturn(
135                 false);
136         when(mSafetyCenterManagerWrapper.isEnabled(any())).thenReturn(false);
137         BaseSearchIndexProvider indexProvider = SecuritySettings.SEARCH_INDEX_DATA_PROVIDER;
138 
139         List<String> allXmlKeys = TestUtils.getAllXmlKeys(mContext, indexProvider);
140         List<String> nonIndexableKeys = indexProvider.getNonIndexableKeys(mContext);
141         allXmlKeys.removeAll(nonIndexableKeys);
142 
143         assertThat(allXmlKeys).isNotEmpty();
144     }
145 
146     @Test
alternativeFragmentAvailable_pageIndexExcluded()147     public void alternativeFragmentAvailable_pageIndexExcluded() throws Exception {
148         when(mSecuritySettingsFeatureProvider.hasAlternativeSecuritySettingsFragment()).thenReturn(
149                 true);
150         BaseSearchIndexProvider indexProvider = SecuritySettings.SEARCH_INDEX_DATA_PROVIDER;
151 
152         List<String> allXmlKeys = TestUtils.getAllXmlKeys(mContext, indexProvider);
153         List<String> nonIndexableKeys = indexProvider.getNonIndexableKeys(mContext);
154         allXmlKeys.removeAll(nonIndexableKeys);
155 
156         assertThat(allXmlKeys).isEmpty();
157     }
158 
159     @Test
160     @UiThreadTest
preferenceController_containsFaceWhenAvailable()161     public void preferenceController_containsFaceWhenAvailable() {
162         when(mFaceManager.isHardwareDetected()).thenReturn(true);
163         when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
164         final List<AbstractPreferenceController> controllers =
165                 mSecuritySettings.createPreferenceControllers(mContext);
166 
167         assertThat(isFacePrefAvailable(controllers)).isTrue();
168         assertThat(isFingerprintPrefAvailable(controllers)).isFalse();
169         assertThat(isCombinedPrefAvailable(controllers)).isFalse();
170     }
171 
172     @Test
173     @UiThreadTest
preferenceController_containsFingerprintWhenAvailable()174     public void preferenceController_containsFingerprintWhenAvailable() {
175         when(mFaceManager.isHardwareDetected()).thenReturn(false);
176         when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
177         final List<AbstractPreferenceController> controllers =
178                 mSecuritySettings.createPreferenceControllers(mContext);
179 
180         assertThat(isFacePrefAvailable(controllers)).isFalse();
181         assertThat(isFingerprintPrefAvailable(controllers)).isTrue();
182         assertThat(isCombinedPrefAvailable(controllers)).isFalse();
183     }
184 
185     @Test
186     @UiThreadTest
preferenceController_containsCombinedBiometricWhenAvailable()187     public void preferenceController_containsCombinedBiometricWhenAvailable() {
188         when(mFaceManager.isHardwareDetected()).thenReturn(true);
189         when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
190         final List<AbstractPreferenceController> controllers =
191                 mSecuritySettings.createPreferenceControllers(mContext);
192 
193         assertThat(isFacePrefAvailable(controllers)).isFalse();
194         assertThat(isFingerprintPrefAvailable(controllers)).isFalse();
195         assertThat(isCombinedPrefAvailable(controllers)).isTrue();
196     }
197 
198     @Test
199     @UiThreadTest
preferenceLifecycle_faceShowsThenCombined()200     public void preferenceLifecycle_faceShowsThenCombined() {
201         when(mFaceManager.isHardwareDetected()).thenReturn(true);
202         when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
203         final List<AbstractPreferenceController> controllers =
204                 mSecuritySettings.createPreferenceControllers(mContext);
205 
206         FaceStatusPreferenceController mFaceStatusPreferenceController =
207                 getFaceStatusPreferenceController(controllers);
208 
209         FingerprintStatusPreferenceController mFingerprintStatusPreferenceController =
210                 getFingerprintStatusPreferenceController(controllers);
211 
212         CombinedBiometricStatusPreferenceController mCombinedStatusPreferenceController =
213                 getCombinedBiometricStatusPreferenceController(controllers);
214 
215         mFaceStatusPreferenceController.setPreferenceScreen(mScreen);
216         mFingerprintStatusPreferenceController.setPreferenceScreen(mScreen);
217         mCombinedStatusPreferenceController.setPreferenceScreen(mScreen);
218 
219         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
220 
221         assertThat(mPreferenceFace.isVisible()).isTrue();
222         assertThat(mPreferenceFingerprint.isVisible()).isFalse();
223         assertThat(mPreferenceCombined.isVisible()).isFalse();
224 
225         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
226         when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
227         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
228 
229         assertThat(mPreferenceFace.isVisible()).isFalse();
230         assertThat(mPreferenceFingerprint.isVisible()).isFalse();
231         assertThat(mPreferenceCombined.isVisible()).isTrue();
232     }
233 
234     @Test
235     @UiThreadTest
preferenceLifecycle_fingerprintShowsThenCombined()236     public void preferenceLifecycle_fingerprintShowsThenCombined() {
237         when(mFaceManager.isHardwareDetected()).thenReturn(false);
238         when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
239         final List<AbstractPreferenceController> controllers =
240                 mSecuritySettings.createPreferenceControllers(mContext);
241 
242         FaceStatusPreferenceController mFaceStatusPreferenceController =
243                 getFaceStatusPreferenceController(controllers);
244 
245         FingerprintStatusPreferenceController mFingerprintStatusPreferenceController =
246                 getFingerprintStatusPreferenceController(controllers);
247 
248         CombinedBiometricStatusPreferenceController mCombinedStatusPreferenceController =
249                 getCombinedBiometricStatusPreferenceController(controllers);
250 
251         mFaceStatusPreferenceController.setPreferenceScreen(mScreen);
252         mFingerprintStatusPreferenceController.setPreferenceScreen(mScreen);
253         mCombinedStatusPreferenceController.setPreferenceScreen(mScreen);
254 
255         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
256 
257         assertThat(mPreferenceFace.isVisible()).isFalse();
258         assertThat(mPreferenceFingerprint.isVisible()).isTrue();
259         assertThat(mPreferenceCombined.isVisible()).isFalse();
260 
261         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
262         when(mFaceManager.isHardwareDetected()).thenReturn(true);
263         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
264 
265         assertThat(mPreferenceFace.isVisible()).isFalse();
266         assertThat(mPreferenceFingerprint.isVisible()).isFalse();
267         assertThat(mPreferenceCombined.isVisible()).isTrue();
268     }
269 
270     @Test
271     @UiThreadTest
preferenceLifecycle_combinedShowsThenFace()272     public void preferenceLifecycle_combinedShowsThenFace() {
273         when(mFaceManager.isHardwareDetected()).thenReturn(true);
274         when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
275         final List<AbstractPreferenceController> controllers =
276                 mSecuritySettings.createPreferenceControllers(mContext);
277 
278         FaceStatusPreferenceController mFaceStatusPreferenceController =
279                 getFaceStatusPreferenceController(controllers);
280 
281         FingerprintStatusPreferenceController mFingerprintStatusPreferenceController =
282                 getFingerprintStatusPreferenceController(controllers);
283 
284         CombinedBiometricStatusPreferenceController mCombinedStatusPreferenceController =
285                 getCombinedBiometricStatusPreferenceController(controllers);
286 
287         mFaceStatusPreferenceController.setPreferenceScreen(mScreen);
288         mFingerprintStatusPreferenceController.setPreferenceScreen(mScreen);
289         mCombinedStatusPreferenceController.setPreferenceScreen(mScreen);
290 
291         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
292 
293         assertThat(mPreferenceFace.isVisible()).isFalse();
294         assertThat(mPreferenceFingerprint.isVisible()).isFalse();
295         assertThat(mPreferenceCombined.isVisible()).isTrue();
296 
297         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
298         when(mFingerprintManager.isHardwareDetected()).thenReturn(false);
299         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
300 
301         assertThat(mPreferenceFace.isVisible()).isTrue();
302         assertThat(mPreferenceFingerprint.isVisible()).isFalse();
303         assertThat(mPreferenceCombined.isVisible()).isFalse();
304     }
305 
306     @Test
307     @UiThreadTest
preferenceLifecycle_combinedShowsThenFingerprint()308     public void preferenceLifecycle_combinedShowsThenFingerprint() {
309         when(mFaceManager.isHardwareDetected()).thenReturn(true);
310         when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
311         final List<AbstractPreferenceController> controllers =
312                 mSecuritySettings.createPreferenceControllers(mContext);
313 
314         FaceStatusPreferenceController mFaceStatusPreferenceController =
315                 getFaceStatusPreferenceController(controllers);
316 
317         FingerprintStatusPreferenceController mFingerprintStatusPreferenceController =
318                 getFingerprintStatusPreferenceController(controllers);
319 
320         CombinedBiometricStatusPreferenceController mCombinedStatusPreferenceController =
321                 getCombinedBiometricStatusPreferenceController(controllers);
322 
323         mFaceStatusPreferenceController.setPreferenceScreen(mScreen);
324         mFingerprintStatusPreferenceController.setPreferenceScreen(mScreen);
325         mCombinedStatusPreferenceController.setPreferenceScreen(mScreen);
326 
327         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
328 
329         assertThat(mPreferenceFace.isVisible()).isFalse();
330         assertThat(mPreferenceFingerprint.isVisible()).isFalse();
331         assertThat(mPreferenceCombined.isVisible()).isTrue();
332 
333         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
334         when(mFaceManager.isHardwareDetected()).thenReturn(false);
335         mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
336 
337         assertThat(mPreferenceFace.isVisible()).isFalse();
338         assertThat(mPreferenceFingerprint.isVisible()).isTrue();
339         assertThat(mPreferenceCombined.isVisible()).isFalse();
340     }
341 
isFacePrefAvailable(List<AbstractPreferenceController> controllers)342     boolean isFacePrefAvailable(List<AbstractPreferenceController> controllers) {
343         return controllers.stream().filter(
344                 controller -> controller instanceof FaceStatusPreferenceController
345                         && controller.isAvailable()).count() == 1;
346     }
347 
isFingerprintPrefAvailable(List<AbstractPreferenceController> controllers)348     boolean isFingerprintPrefAvailable(List<AbstractPreferenceController> controllers) {
349         return controllers.stream().filter(
350                 controller -> controller instanceof FingerprintStatusPreferenceController
351                         && controller.isAvailable()).count() == 1;
352     }
353 
isCombinedPrefAvailable(List<AbstractPreferenceController> controllers)354     boolean isCombinedPrefAvailable(List<AbstractPreferenceController> controllers) {
355         return controllers.stream().filter(
356                 controller -> controller instanceof CombinedBiometricStatusPreferenceController
357                         && controller.isAvailable()).count() == 1;
358     }
359 
getFaceStatusPreferenceController( List<AbstractPreferenceController> controllers)360     FaceStatusPreferenceController getFaceStatusPreferenceController(
361             List<AbstractPreferenceController> controllers) {
362         for (AbstractPreferenceController abstractPreferenceController: controllers) {
363             if (abstractPreferenceController instanceof FaceStatusPreferenceController) {
364                 return (FaceStatusPreferenceController) abstractPreferenceController;
365             }
366         }
367         return null;
368     }
369 
getFingerprintStatusPreferenceController( List<AbstractPreferenceController> controllers)370     FingerprintStatusPreferenceController getFingerprintStatusPreferenceController(
371             List<AbstractPreferenceController> controllers) {
372         for (AbstractPreferenceController abstractPreferenceController: controllers) {
373             if (abstractPreferenceController instanceof FingerprintStatusPreferenceController) {
374                 return (FingerprintStatusPreferenceController) abstractPreferenceController;
375             }
376         }
377         return null;
378     }
379 
getCombinedBiometricStatusPreferenceController( List<AbstractPreferenceController> controllers)380     CombinedBiometricStatusPreferenceController getCombinedBiometricStatusPreferenceController(
381             List<AbstractPreferenceController> controllers) {
382         for (AbstractPreferenceController abstractPreferenceController: controllers) {
383             if (abstractPreferenceController
384                     instanceof CombinedBiometricStatusPreferenceController) {
385                 return (CombinedBiometricStatusPreferenceController) abstractPreferenceController;
386             }
387         }
388         return null;
389     }
390 }
391