diff --git a/Android.bp b/Android.bp
index 087030b37cf..e81ef9e2f06 100644
--- a/Android.bp
+++ b/Android.bp
@@ -79,6 +79,7 @@ android_library {
"BiometricsSharedLib",
"SystemUIUnfoldLib",
"WifiTrackerLib",
+ "android.hardware.biometrics.flags-aconfig-java",
"android.hardware.dumpstate-V1-java",
"android.hardware.dumpstate-V1.0-java",
"android.hardware.dumpstate-V1.1-java",
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a58702a0a2b..e986ce08663 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1234,6 +1234,16 @@
Can\u2019t use fingerprint sensor
Visit a repair provider.
+
+
+ security_settings_screen_off_unlock_udfps
+
+ Screen-off Fingerprint Unlock
+
+ Use Fingerprint Unlock even when the screen is off
+
+ Screen-off, Unlock
+
More security settings
diff --git a/res/xml/security_settings_fingerprint.xml b/res/xml/security_settings_fingerprint.xml
index 9c8b0a3f9ea..32f09244f97 100644
--- a/res/xml/security_settings_fingerprint.xml
+++ b/res/xml/security_settings_fingerprint.xml
@@ -40,7 +40,16 @@
android:title="@string/security_settings_require_screen_on_to_auth_title"
android:summary="@string/security_settings_require_screen_on_to_auth_description"
settings:keywords="@string/security_settings_require_screen_on_to_auth_keywords"
- settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsRequireScreenOnToAuthPreferenceController" />
+ settings:controller="com.android.settings.biometrics.fingerprint.FingerprintSettingsRequireScreenOnToAuthPreferenceController"
+ settings:isPreferenceVisible="false"/>
+
+
{
+ final boolean isChecked = ((TwoStatePreference) preference).isChecked();
+ mScreenOffUnlockUdfpsPreferenceController.setChecked(!isChecked);
+ return true;
+ });
+ }
+
private void updatePreferencesAfterFingerprintRemoved() {
updateAddPreference();
- if (isSfps()) {
+ if (isSfps() || screenOffUnlockUdfps()) {
updateFingerprintUnlockCategoryVisibility();
}
updatePreferences();
@@ -954,6 +997,18 @@ public class FingerprintSettings extends SubSettings {
controller;
}
+ }
+ } else if (screenOffUnlockUdfps()) {
+ for (AbstractPreferenceController controller : controllers) {
+ if (controller.getPreferenceKey() == KEY_FINGERPRINT_UNLOCK_CATEGORY) {
+ mFingerprintUnlockCategoryPreferenceController =
+ (FingerprintUnlockCategoryController) controller;
+ } else if (controller.getPreferenceKey() == KEY_SCREEN_OFF_FINGERPRINT_UNLOCK) {
+ mScreenOffUnlockUdfpsPreferenceController =
+ (FingerprintSettingsScreenOffUnlockUdfpsPreferenceController)
+ controller;
+ }
+
}
}
return controllers;
@@ -1070,7 +1125,8 @@ public class FingerprintSettings extends SubSettings {
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false;
if (resultCode != RESULT_OK) {
- if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ if (resultCode
+ == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
IdentityCheckBiometricErrorDialog
.showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
Utils.BiometricStatus.LOCKOUT);
@@ -1408,7 +1464,7 @@ public class FingerprintSettings extends SubSettings {
getContext().getSystemService(DevicePolicyManager.class);
String messageId =
isProfileChallengeUser ? WORK_PROFILE_FINGERPRINT_LAST_DELETE_MESSAGE
- : UNDEFINED;
+ : UNDEFINED;
int defaultMessageId = isProfileChallengeUser
? R.string.fingerprint_last_delete_message_profile_challenge
: R.string.fingerprint_last_delete_message;
@@ -1417,7 +1473,7 @@ public class FingerprintSettings extends SubSettings {
.setTitle(title)
.setMessage(devicePolicyManager.getResources().getString(
messageId,
- () -> message + "\n\n" + getContext().getString(defaultMessageId)))
+ () -> message + "\n\n" + getContext().getString(defaultMessageId)))
.setPositiveButton(
R.string.security_settings_fingerprint_enroll_dialog_delete,
new DialogInterface.OnClickListener() {
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsScreenOffUnlockUdfpsPreferenceController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsScreenOffUnlockUdfpsPreferenceController.java
new file mode 100644
index 00000000000..5c32d90ba7e
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsScreenOffUnlockUdfpsPreferenceController.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint;
+
+import static android.hardware.biometrics.Flags.screenOffUnlockUdfps;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+import androidx.preference.Preference;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.Utils;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+/**
+ * Preference controller that controls whether show screen off UDFPS unlock toggle for users to
+ * turn this feature ON or OFF
+ */
+@SearchIndexable
+public class FingerprintSettingsScreenOffUnlockUdfpsPreferenceController
+ extends FingerprintSettingsPreferenceController {
+ private static final String TAG =
+ "FingerprintSettingsScreenOffUnlockUdfpsPreferenceController";
+
+ @VisibleForTesting
+ protected FingerprintManager mFingerprintManager;
+
+ public FingerprintSettingsScreenOffUnlockUdfpsPreferenceController(
+ @NonNull Context context, @NonNull String prefKey) {
+ super(context, prefKey);
+ mFingerprintManager = Utils.getFingerprintManagerOrNull(context);
+ }
+
+ @Override
+ public boolean isChecked() {
+ if (!FingerprintSettings.isFingerprintHardwareDetected(mContext)) {
+ return false;
+ } else if (getRestrictingAdmin() != null) {
+ return false;
+ }
+ final boolean defEnabled = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_screen_off_udfps_enabled);
+ final int value = Settings.Secure.getIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED,
+ defEnabled ? 1 : 0 /* config_screen_off_udfps_enabled */,
+ getUserHandle());
+ return value == 1;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ Settings.Secure.putIntForUser(
+ mContext.getContentResolver(),
+ Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED,
+ isChecked ? 1 : 0,
+ getUserHandle());
+ return true;
+ }
+
+ @Override
+ public void updateState(@NonNull Preference preference) {
+ super.updateState(preference);
+ if (!FingerprintSettings.isFingerprintHardwareDetected(mContext)) {
+ preference.setEnabled(false);
+ } else if (!mFingerprintManager.hasEnrolledTemplates(getUserId())) {
+ preference.setEnabled(false);
+ } else if (getRestrictingAdmin() != null) {
+ preference.setEnabled(false);
+ } else {
+ preference.setEnabled(true);
+ }
+ }
+
+ @SuppressLint("MissingPermission")
+ @Override
+ public int getAvailabilityStatus() {
+ if (mFingerprintManager != null
+ && mFingerprintManager.isHardwareDetected()
+ && screenOffUnlockUdfps()
+ && !mFingerprintManager.isPowerbuttonFps()) {
+ return mFingerprintManager.hasEnrolledTemplates(getUserId())
+ ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
+ } else {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ }
+
+ private int getUserHandle() {
+ return UserHandle.of(getUserId()).getIdentifier();
+ }
+
+ /**
+ * This feature is not directly searchable.
+ */
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {};
+
+}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java b/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java
index 674a0dfa758..c949d3da4d8 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintUnlockCategoryController.java
@@ -16,6 +16,8 @@
package com.android.settings.biometrics.fingerprint;
+import static android.hardware.biometrics.Flags.screenOffUnlockUdfps;
+
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
@@ -42,7 +44,7 @@ public class FingerprintUnlockCategoryController extends BasePreferenceControlle
public int getAvailabilityStatus() {
if (mFingerprintManager != null
&& mFingerprintManager.isHardwareDetected()
- && mFingerprintManager.isPowerbuttonFps()) {
+ && (mFingerprintManager.isPowerbuttonFps() || screenOffUnlockUdfps())) {
return mFingerprintManager.hasEnrolledTemplates(getUserId())
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
} else {
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsScreenOffUnlockUdfpsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsScreenOffUnlockUdfpsPreferenceControllerTest.java
new file mode 100644
index 00000000000..7660e889db3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsScreenOffUnlockUdfpsPreferenceControllerTest.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
+import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.provider.Settings;
+
+import com.android.settings.testutils.shadow.ShadowUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowUtils.class})
+public class FingerprintSettingsScreenOffUnlockUdfpsPreferenceControllerTest {
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ @Mock
+ private FingerprintManager mFingerprintManager;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private RestrictedSwitchPreference mPreference;
+
+ private Context mContext;
+ private FingerprintSettingsScreenOffUnlockUdfpsPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(RuntimeEnvironment.application);
+ when(mContext.getSystemService(eq(Context.FINGERPRINT_SERVICE))).thenReturn(
+ mFingerprintManager);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+
+ mController = spy(new FingerprintSettingsScreenOffUnlockUdfpsPreferenceController(mContext,
+ "test_key"));
+ ReflectionHelpers.setField(mController, "mFingerprintManager", mFingerprintManager);
+ }
+
+ @After
+ public void tearDown() {
+ ShadowUtils.reset();
+ }
+
+ @Test
+ public void onPreferenceChange_settingIsUpdated() {
+ boolean state = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED, 1) != 0;
+
+ assertThat(mController.isChecked()).isFalse();
+ assertThat(mController.onPreferenceChange(mPreference, !state)).isTrue();
+ boolean newState = Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SCREEN_OFF_UNLOCK_UDFPS_ENABLED, 1) != 0;
+ assertThat(newState).isEqualTo(!state);
+ }
+
+ @Test
+ @EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
+ public void isAvailable_isEnabled_whenUdfpsHardwareDetected_AndHasEnrolledFingerprints() {
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ false /* isPowerbuttonFps false implies udfps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isEqualTo(true);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ @EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
+ public void isUnavailable_isDisabled_whenUdfpsHardwareDetected_AndNoEnrolledFingerprints() {
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ false /* isPowerbuttonFps false implies udfps */,
+ false /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ @EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
+ public void isUnavailable_whenHardwareNotDetected() {
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
+ false /* isHardwareDetected */,
+ false /* isPowerbuttonFps false implies udfps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isEqualTo(false);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ @EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
+ public void isUnavailable_onNonUdfpsDevice() {
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ true /* isPowerbuttonFps false implies udfps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mController.isAvailable()).isFalse();
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
+ }
+
+ private void configure_hardwareDetected_isUdfps_hasEnrolledTemplates(
+ boolean isHardwareDetected, boolean isPowerbuttonFps, boolean hasEnrolledTemplates) {
+ when(mFingerprintManager.isHardwareDetected()).thenReturn(isHardwareDetected);
+ when(mFingerprintManager.isPowerbuttonFps()).thenReturn(isPowerbuttonFps);
+ when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(hasEnrolledTemplates);
+ }
+
+}
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsUnlockCategoryControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsUnlockCategoryControllerTest.java
index 7b6a70ed7ef..59af9346a29 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsUnlockCategoryControllerTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintSettingsUnlockCategoryControllerTest.java
@@ -30,12 +30,15 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.pm.PackageManager;
import android.hardware.fingerprint.FingerprintManager;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -49,6 +52,8 @@ import org.robolectric.util.ReflectionHelpers;
@Config(shadows = {ShadowUtils.class})
public class FingerprintSettingsUnlockCategoryControllerTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Mock
private FingerprintManager mFingerprintManager;
@Mock
@@ -59,6 +64,8 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
private Context mContext;
private FingerprintSettingsRequireScreenOnToAuthPreferenceController mController;
+ private FingerprintSettingsScreenOffUnlockUdfpsPreferenceController mScreenOffUnlockController;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
@@ -69,7 +76,12 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
mController = spy(new FingerprintSettingsRequireScreenOnToAuthPreferenceController(mContext,
"test_key"));
+ mScreenOffUnlockController = spy(
+ new FingerprintSettingsScreenOffUnlockUdfpsPreferenceController(mContext,
+ "screen_off_unlock_test_key"));
ReflectionHelpers.setField(mController, "mFingerprintManager", mFingerprintManager);
+ ReflectionHelpers.setField(mScreenOffUnlockController, "mFingerprintManager",
+ mFingerprintManager);
}
@After
@@ -89,6 +101,20 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
}
+ @Test
+ @EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
+ public void isAvailable_isEnabled_whenUdfpsHardwareDetected_AndHasEnrolledFingerprints() {
+ assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(false);
+ assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
+ UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ false /* isPowerbuttonFps false implies udfps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(true);
+ assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
@Test
public void isUnavailable_isDisabled_whenSfpsHardwareDetected_AndNoEnrolledFingerprints() {
assertThat(mController.isAvailable()).isEqualTo(false);
@@ -102,7 +128,22 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
}
@Test
- public void isUnavailable_whenHardwareNotDetected() {
+ @EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
+ public void isUnavailable_isDisabled_whenUdfpsHardwareDetected_AndNoEnrolledFingerprints() {
+ assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(false);
+ assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
+ UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ true /* isHardwareDetected */,
+ false /* isPowerbuttonFps false implies udfps */,
+ false /* hasEnrolledTemplates */);
+ assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(false);
+ assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
+ CONDITIONALLY_UNAVAILABLE);
+ }
+
+ @Test
+ public void isUnavailable_whenHardwareNotDetected_onSfpsDevice() {
assertThat(mController.isAvailable()).isFalse();
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
configure_hardwareDetected_isSfps_hasEnrolledTemplates(
@@ -113,6 +154,21 @@ public class FingerprintSettingsUnlockCategoryControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
+ @Test
+ @EnableFlags(android.hardware.biometrics.Flags.FLAG_SCREEN_OFF_UNLOCK_UDFPS)
+ public void isUnavailable_whenHardwareNotDetected_onUdfpsDevice() {
+ assertThat(mScreenOffUnlockController.isAvailable()).isFalse();
+ assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
+ UNSUPPORTED_ON_DEVICE);
+ configure_hardwareDetected_isSfps_hasEnrolledTemplates(
+ false /* isHardwareDetected */,
+ false /* isPowerbuttonFps false implies udfps */,
+ true /* hasEnrolledTemplates */);
+ assertThat(mScreenOffUnlockController.isAvailable()).isEqualTo(false);
+ assertThat(mScreenOffUnlockController.getAvailabilityStatus()).isEqualTo(
+ UNSUPPORTED_ON_DEVICE);
+ }
+
@Test
public void isUnavailable_onNonSfpsDevice() {
assertThat(mController.isAvailable()).isFalse();