diff --git a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java index 978fb0d1534..50eb43d6545 100644 --- a/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java +++ b/src/com/android/settings/biometrics/combination/CombinedBiometricStatusPreferenceController.java @@ -35,7 +35,7 @@ import com.android.settingslib.RestrictedPreference; */ public class CombinedBiometricStatusPreferenceController extends BiometricStatusPreferenceController implements LifecycleObserver { - private static final String KEY_BIOMETRIC_SETTINGS = "biometric_settings"; + public static final String KEY_BIOMETRIC_SETTINGS = "biometric_settings"; @VisibleForTesting RestrictedPreference mPreference; @@ -122,4 +122,8 @@ public class CombinedBiometricStatusPreferenceController extends protected String getSettingsClassName() { return mCombinedBiometricStatusUtils.getSettingsClassName(); } + + public void setPreferenceScreen(PreferenceScreen preferenceScreen) { + mPreferenceScreen = preferenceScreen; + } } diff --git a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java index 7c419579c83..f18a74fa190 100644 --- a/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceStatusPreferenceController.java @@ -38,6 +38,7 @@ public class FaceStatusPreferenceController extends BiometricStatusPreferenceCon public static final String KEY_FACE_SETTINGS = "face_settings"; protected final FaceManager mFaceManager; + @VisibleForTesting RestrictedPreference mPreference; private PreferenceScreen mPreferenceScreen; @@ -111,4 +112,8 @@ public class FaceStatusPreferenceController extends BiometricStatusPreferenceCon protected String getSettingsClassName() { return mFaceStatusUtils.getSettingsClassName(); } + + public void setPreferenceScreen(PreferenceScreen preferenceScreen) { + mPreferenceScreen = preferenceScreen; + } } diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java index 1ed06880ac8..347fec72870 100644 --- a/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java +++ b/src/com/android/settings/biometrics/fingerprint/FingerprintStatusPreferenceController.java @@ -35,7 +35,7 @@ import com.android.settingslib.RestrictedPreference; public class FingerprintStatusPreferenceController extends BiometricStatusPreferenceController implements LifecycleObserver { - private static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings"; + public static final String KEY_FINGERPRINT_SETTINGS = "fingerprint_settings"; protected final FingerprintManager mFingerprintManager; @VisibleForTesting @@ -112,4 +112,8 @@ public class FingerprintStatusPreferenceController extends BiometricStatusPrefer mPreference.setDisabledByAdmin(enforcedAdmin); } } + + public void setPreferenceScreen(PreferenceScreen preferenceScreen) { + mPreferenceScreen = preferenceScreen; + } } diff --git a/src/com/android/settings/security/SecuritySettings.java b/src/com/android/settings/security/SecuritySettings.java index 6aadee6aad5..b30b54d4d4c 100644 --- a/src/com/android/settings/security/SecuritySettings.java +++ b/src/com/android/settings/security/SecuritySettings.java @@ -40,7 +40,7 @@ import java.util.List; public class SecuritySettings extends DashboardFragment { private static final String TAG = "SecuritySettings"; - private static final String SECURITY_CATEGORY = "security_category"; + protected static final String SECURITY_CATEGORY = "security_category"; public static final int CHANGE_TRUST_AGENT_SETTINGS = 126; public static final int UNIFY_LOCK_CONFIRM_PROFILE_REQUEST = 129; @@ -132,4 +132,9 @@ public class SecuritySettings extends DashboardFragment { && !SafetyCenterManagerWrapper.get().isEnabled(context); } }; + + @Override + public Lifecycle getSettingsLifecycle() { + return super.getSettingsLifecycle(); + } } diff --git a/tests/unit/src/com/android/settings/security/SecuritySettingsTest.java b/tests/unit/src/com/android/settings/security/SecuritySettingsTest.java index 272c8408698..c51788472c1 100644 --- a/tests/unit/src/com/android/settings/security/SecuritySettingsTest.java +++ b/tests/unit/src/com/android/settings/security/SecuritySettingsTest.java @@ -40,6 +40,10 @@ import android.os.Bundle; import android.os.Looper; import android.provider.SearchIndexableResource; +import androidx.lifecycle.Lifecycle; +import androidx.preference.Preference; +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; import androidx.test.annotation.UiThreadTest; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -51,6 +55,7 @@ import com.android.settings.core.PreferenceXmlParserUtils; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.security.trustagent.TrustAgentManager; import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settingslib.RestrictedPreference; import com.android.settingslib.core.AbstractPreferenceController; import org.junit.Before; @@ -62,13 +67,15 @@ import org.mockito.MockitoAnnotations; import java.util.ArrayList; import java.util.List; - @RunWith(AndroidJUnit4.class) public class SecuritySettingsTest { - private Context mContext; private SecuritySettingsFeatureProvider mSecuritySettingsFeatureProvider; private SecuritySettings mSecuritySettings; + private Preference mPreference; + private RestrictedPreference mPreferenceFace; + private RestrictedPreference mPreferenceFingerprint; + private RestrictedPreference mPreferenceCombined; @Mock private TrustAgentManager mTrustAgentManager; @@ -79,6 +86,8 @@ public class SecuritySettingsTest { @Mock private PackageManager mPackageManager; + private PreferenceScreen mScreen; + @Before @UiThreadTest public void setup() { @@ -96,10 +105,30 @@ public class SecuritySettingsTest { FakeFeatureFactory mFeatureFactory = FakeFeatureFactory.setupForTest(); SecurityFeatureProvider mSecurityFeatureProvider = mFeatureFactory.getSecurityFeatureProvider(); - when(mSecurityFeatureProvider.getTrustAgentManager()).thenReturn(mTrustAgentManager); mSecuritySettingsFeatureProvider = mFeatureFactory.getSecuritySettingsFeatureProvider(); mSecuritySettings = new SecuritySettings(); + + PreferenceManager preferenceManager = new PreferenceManager(mContext); + mScreen = preferenceManager.createPreferenceScreen(mContext); + mPreference = new Preference(mContext); + mPreference.setKey(SecuritySettings.SECURITY_CATEGORY); + + mPreferenceFace = new RestrictedPreference(mContext); + mPreferenceFingerprint = new RestrictedPreference(mContext); + mPreferenceCombined = new RestrictedPreference(mContext); + + mPreferenceFace.setKey(FaceStatusPreferenceController + .KEY_FACE_SETTINGS); + mPreferenceFingerprint.setKey(FingerprintStatusPreferenceController + .KEY_FINGERPRINT_SETTINGS); + mPreferenceCombined.setKey(CombinedBiometricStatusPreferenceController + .KEY_BIOMETRIC_SETTINGS); + + mScreen.addPreference(mPreference); + mScreen.addPreference(mPreferenceFace); + mScreen.addPreference(mPreferenceFingerprint); + mScreen.addPreference(mPreferenceCombined); } @Test @@ -167,6 +196,150 @@ public class SecuritySettingsTest { assertThat(isCombinedPrefAvailable(controllers)).isTrue(); } + @Test + @UiThreadTest + public void preferenceLifecycle_faceShowsThenCombined() { + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(false); + final List controllers = + mSecuritySettings.createPreferenceControllers(mContext); + + FaceStatusPreferenceController mFaceStatusPreferenceController = + getFaceStatusPreferenceController(controllers); + + FingerprintStatusPreferenceController mFingerprintStatusPreferenceController = + getFingerprintStatusPreferenceController(controllers); + + CombinedBiometricStatusPreferenceController mCombinedStatusPreferenceController = + getCombinedBiometricStatusPreferenceController(controllers); + + mFaceStatusPreferenceController.setPreferenceScreen(mScreen); + mFingerprintStatusPreferenceController.setPreferenceScreen(mScreen); + mCombinedStatusPreferenceController.setPreferenceScreen(mScreen); + + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME); + + assertThat(mPreferenceFace.isVisible()).isTrue(); + assertThat(mPreferenceFingerprint.isVisible()).isFalse(); + assertThat(mPreferenceCombined.isVisible()).isFalse(); + + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_PAUSE); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME); + + assertThat(mPreferenceFace.isVisible()).isFalse(); + assertThat(mPreferenceFingerprint.isVisible()).isFalse(); + assertThat(mPreferenceCombined.isVisible()).isTrue(); + } + + @Test + @UiThreadTest + public void preferenceLifecycle_fingerprintShowsThenCombined() { + when(mFaceManager.isHardwareDetected()).thenReturn(false); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + final List controllers = + mSecuritySettings.createPreferenceControllers(mContext); + + FaceStatusPreferenceController mFaceStatusPreferenceController = + getFaceStatusPreferenceController(controllers); + + FingerprintStatusPreferenceController mFingerprintStatusPreferenceController = + getFingerprintStatusPreferenceController(controllers); + + CombinedBiometricStatusPreferenceController mCombinedStatusPreferenceController = + getCombinedBiometricStatusPreferenceController(controllers); + + mFaceStatusPreferenceController.setPreferenceScreen(mScreen); + mFingerprintStatusPreferenceController.setPreferenceScreen(mScreen); + mCombinedStatusPreferenceController.setPreferenceScreen(mScreen); + + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME); + + assertThat(mPreferenceFace.isVisible()).isFalse(); + assertThat(mPreferenceFingerprint.isVisible()).isTrue(); + assertThat(mPreferenceCombined.isVisible()).isFalse(); + + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_PAUSE); + when(mFaceManager.isHardwareDetected()).thenReturn(true); + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME); + + assertThat(mPreferenceFace.isVisible()).isFalse(); + assertThat(mPreferenceFingerprint.isVisible()).isFalse(); + assertThat(mPreferenceCombined.isVisible()).isTrue(); + } + + @Test + @UiThreadTest + public void preferenceLifecycle_combinedShowsThenFace() { + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + final List controllers = + mSecuritySettings.createPreferenceControllers(mContext); + + FaceStatusPreferenceController mFaceStatusPreferenceController = + getFaceStatusPreferenceController(controllers); + + FingerprintStatusPreferenceController mFingerprintStatusPreferenceController = + getFingerprintStatusPreferenceController(controllers); + + CombinedBiometricStatusPreferenceController mCombinedStatusPreferenceController = + getCombinedBiometricStatusPreferenceController(controllers); + + mFaceStatusPreferenceController.setPreferenceScreen(mScreen); + mFingerprintStatusPreferenceController.setPreferenceScreen(mScreen); + mCombinedStatusPreferenceController.setPreferenceScreen(mScreen); + + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME); + + assertThat(mPreferenceFace.isVisible()).isFalse(); + assertThat(mPreferenceFingerprint.isVisible()).isFalse(); + assertThat(mPreferenceCombined.isVisible()).isTrue(); + + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_PAUSE); + when(mFingerprintManager.isHardwareDetected()).thenReturn(false); + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME); + + assertThat(mPreferenceFace.isVisible()).isTrue(); + assertThat(mPreferenceFingerprint.isVisible()).isFalse(); + assertThat(mPreferenceCombined.isVisible()).isFalse(); + } + + @Test + @UiThreadTest + public void preferenceLifecycle_combinedShowsThenFingerprint() { + when(mFaceManager.isHardwareDetected()).thenReturn(true); + when(mFingerprintManager.isHardwareDetected()).thenReturn(true); + final List controllers = + mSecuritySettings.createPreferenceControllers(mContext); + + FaceStatusPreferenceController mFaceStatusPreferenceController = + getFaceStatusPreferenceController(controllers); + + FingerprintStatusPreferenceController mFingerprintStatusPreferenceController = + getFingerprintStatusPreferenceController(controllers); + + CombinedBiometricStatusPreferenceController mCombinedStatusPreferenceController = + getCombinedBiometricStatusPreferenceController(controllers); + + mFaceStatusPreferenceController.setPreferenceScreen(mScreen); + mFingerprintStatusPreferenceController.setPreferenceScreen(mScreen); + mCombinedStatusPreferenceController.setPreferenceScreen(mScreen); + + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME); + + assertThat(mPreferenceFace.isVisible()).isFalse(); + assertThat(mPreferenceFingerprint.isVisible()).isFalse(); + assertThat(mPreferenceCombined.isVisible()).isTrue(); + + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_PAUSE); + when(mFaceManager.isHardwareDetected()).thenReturn(false); + mSecuritySettings.getSettingsLifecycle().handleLifecycleEvent(Lifecycle.Event.ON_RESUME); + + assertThat(mPreferenceFace.isVisible()).isFalse(); + assertThat(mPreferenceFingerprint.isVisible()).isTrue(); + assertThat(mPreferenceCombined.isVisible()).isFalse(); + } + private List getAllXmlKeys(BaseSearchIndexProvider indexProvider) throws Exception { final List resources = indexProvider.getXmlResourcesToIndex( mContext, true /* not used*/); @@ -207,4 +380,35 @@ public class SecuritySettingsTest { controller -> controller instanceof CombinedBiometricStatusPreferenceController && controller.isAvailable()).count() == 1; } + + FaceStatusPreferenceController getFaceStatusPreferenceController( + List controllers) { + for (AbstractPreferenceController abstractPreferenceController: controllers) { + if (abstractPreferenceController instanceof FaceStatusPreferenceController) { + return (FaceStatusPreferenceController) abstractPreferenceController; + } + } + return null; + } + + FingerprintStatusPreferenceController getFingerprintStatusPreferenceController( + List controllers) { + for (AbstractPreferenceController abstractPreferenceController: controllers) { + if (abstractPreferenceController instanceof FingerprintStatusPreferenceController) { + return (FingerprintStatusPreferenceController) abstractPreferenceController; + } + } + return null; + } + + CombinedBiometricStatusPreferenceController getCombinedBiometricStatusPreferenceController( + List controllers) { + for (AbstractPreferenceController abstractPreferenceController: controllers) { + if (abstractPreferenceController + instanceof CombinedBiometricStatusPreferenceController) { + return (CombinedBiometricStatusPreferenceController) abstractPreferenceController; + } + } + return null; + } }