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