Loading core/java/android/hardware/biometrics/PromptInfo.java +11 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ public class PromptInfo implements Parcelable { private List<FallbackOption> mFallbackOptions = new ArrayList<>(); private boolean mConfirmationRequested = true; // default to true private boolean mDeviceCredentialAllowed; private boolean mIdentityCheckActive = false; private @BiometricManager.Authenticators.Types int mAuthenticators; private boolean mDisallowBiometricsIfPolicyExists; private boolean mReceiveSystemEvents; Loading Loading @@ -83,6 +84,7 @@ public class PromptInfo implements Parcelable { mNegativeButtonText = in.readCharSequence(); mConfirmationRequested = in.readBoolean(); mDeviceCredentialAllowed = in.readBoolean(); mIdentityCheckActive = in.readBoolean(); mAuthenticators = in.readInt(); mDisallowBiometricsIfPolicyExists = in.readBoolean(); mReceiveSystemEvents = in.readBoolean(); Loading Loading @@ -137,6 +139,7 @@ public class PromptInfo implements Parcelable { dest.writeCharSequence(mNegativeButtonText); dest.writeBoolean(mConfirmationRequested); dest.writeBoolean(mDeviceCredentialAllowed); dest.writeBoolean(mIdentityCheckActive); dest.writeInt(mAuthenticators); dest.writeBoolean(mDisallowBiometricsIfPolicyExists); dest.writeBoolean(mReceiveSystemEvents); Loading Loading @@ -298,6 +301,10 @@ public class PromptInfo implements Parcelable { mDeviceCredentialAllowed = deviceCredentialAllowed; } public void setIdentityCheckActive(boolean identityCheckActive) { mIdentityCheckActive = identityCheckActive; } public void setAuthenticators(int authenticators) { mAuthenticators = authenticators; } Loading Loading @@ -440,6 +447,10 @@ public class PromptInfo implements Parcelable { return mDeviceCredentialAllowed; } public boolean isIdentityCheckActive() { return mIdentityCheckActive; } public int getAuthenticators() { return mAuthenticators; } Loading core/java/android/hardware/biometrics/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,13 @@ flag { bug: "391666818" } flag { name: "bp_fallback_options" namespace: "biometrics_framework" description: "Adds fallback options UI to biometric prompt" bug: "377774089" } flag { name: "get_op_id_crypto_object" is_exported: true Loading packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +27 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.hardware.biometrics.BiometricAuthenticator import android.hardware.biometrics.BiometricConstants import android.hardware.biometrics.BiometricManager import android.hardware.biometrics.BiometricPrompt import android.hardware.biometrics.Flags import android.hardware.biometrics.PromptContentViewWithMoreOptionsButton import android.hardware.biometrics.PromptInfo import android.hardware.biometrics.PromptVerticalListContentView Loading @@ -30,6 +31,8 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.os.IBinder import android.os.UserManager import android.os.userManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper import android.testing.ViewUtils Loading @@ -46,6 +49,7 @@ import com.android.internal.widget.lockPatternUtils import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.domain.interactor.promptSelectorInteractor import com.android.systemui.biometrics.ui.viewmodel.credentialViewModel import com.android.systemui.biometrics.ui.viewmodel.fallbackViewModelFactory import com.android.systemui.biometrics.ui.viewmodel.promptViewModel import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.haptics.msdl.msdlPlayer Loading @@ -63,11 +67,11 @@ import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyLong import org.mockito.Mockito.eq import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify Loading Loading @@ -178,6 +182,7 @@ open class AuthContainerViewTest : SysuiTestCase() { } @Test @DisableFlags(Flags.FLAG_BP_FALLBACK_OPTIONS) fun testIgnoresAnimatedInWhenDialogAnimatingOut() { val container = initializeFingerprintContainer(addToView = false) container.mContainerState = 4 // STATE_ANIMATING_OUT Loading Loading @@ -265,6 +270,24 @@ open class AuthContainerViewTest : SysuiTestCase() { verify(callback).onTryAgainPressed(authContainer?.requestId ?: 0L) } @Test @EnableFlags(Flags.FLAG_BP_FALLBACK_OPTIONS) fun testActionFallbackOption_sendsFallbackOption() { val container = initializeFingerprintContainer( authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK ) container.mBiometricCallback.onFallbackOptionPressed(0) waitForIdleSync() verify(callback) .onDismissed( eq(BiometricPrompt.DISMISSED_REASON_FALLBACK_OPTION_BASE), eq<ByteArray?>(null), eq(authContainer?.requestId ?: 0L), ) } @Test fun testActionError_sendsDismissedError() { val container = initializeFingerprintContainer() Loading Loading @@ -297,6 +320,7 @@ open class AuthContainerViewTest : SysuiTestCase() { } @Test @DisableFlags(Flags.FLAG_BP_FALLBACK_OPTIONS) fun testAnimateToCredentialUI_invokesStartTransitionToCredentialUI() { val container = initializeFingerprintContainer( Loading @@ -318,6 +342,7 @@ open class AuthContainerViewTest : SysuiTestCase() { } @Test @DisableFlags(Flags.FLAG_BP_FALLBACK_OPTIONS) fun testAnimateToCredentialUI_rotateCredentialUI() { val container = initializeFingerprintContainer( Loading Loading @@ -592,6 +617,7 @@ open class AuthContainerViewTest : SysuiTestCase() { kosmos.fakeExecutor, kosmos.vibratorHelper, kosmos.msdlPlayer, kosmos.fallbackViewModelFactory, ) { override fun postOnAnimation(runnable: Runnable) { runnable.run() Loading packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java +4 −1 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.domain.interactor.LogContextInteractor; import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor; import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel; import com.android.systemui.biometrics.ui.viewmodel.PromptFallbackViewModel; import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.CommandQueue; Loading Loading @@ -133,6 +134,8 @@ public class AuthControllerTest extends SysuiTestCase { @Mock private PackageManager mPackageManager; @Mock private PromptFallbackViewModel.Factory mFallbackViewModelFactory; @Mock private IBiometricSysuiReceiver mReceiver; @Mock private IBiometricContextListener mContextListener; Loading Loading @@ -1256,7 +1259,7 @@ public class AuthControllerTest extends SysuiTestCase { () -> mLogContextInteractor, () -> mPromptSelectionInteractor, () -> mCredentialViewModel, () -> mPromptViewModel, mInteractionJankMonitor, mHandler, mBackgroundExecutor, mUdfpsUtils, mVibratorHelper, mKeyguardManager, mMSDLPlayer, mWindowManagerProvider); mMSDLPlayer, mWindowManagerProvider, mFallbackViewModelFactory); } @Override Loading packages/SystemUI/res/layout/biometric_prompt_button_bar.xml +17 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,23 @@ app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" /> <!-- Fallback Button, replaces negative button when there are several fallbacks --> <Button android:id="@+id/button_fallback" style="@style/AuthCredentialNegativeButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="24dp" android:layout_marginBottom="8dp" android:text="@string/biometric_dialog_fallback_button" android:visibility="invisible" app:layout_constrainedWidth="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@id/button_center_guideline" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" /> <!-- "Use Credential" Button, replaces if device credential is allowed --> <Button android:id="@+id/button_use_credential" Loading Loading
core/java/android/hardware/biometrics/PromptInfo.java +11 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ public class PromptInfo implements Parcelable { private List<FallbackOption> mFallbackOptions = new ArrayList<>(); private boolean mConfirmationRequested = true; // default to true private boolean mDeviceCredentialAllowed; private boolean mIdentityCheckActive = false; private @BiometricManager.Authenticators.Types int mAuthenticators; private boolean mDisallowBiometricsIfPolicyExists; private boolean mReceiveSystemEvents; Loading Loading @@ -83,6 +84,7 @@ public class PromptInfo implements Parcelable { mNegativeButtonText = in.readCharSequence(); mConfirmationRequested = in.readBoolean(); mDeviceCredentialAllowed = in.readBoolean(); mIdentityCheckActive = in.readBoolean(); mAuthenticators = in.readInt(); mDisallowBiometricsIfPolicyExists = in.readBoolean(); mReceiveSystemEvents = in.readBoolean(); Loading Loading @@ -137,6 +139,7 @@ public class PromptInfo implements Parcelable { dest.writeCharSequence(mNegativeButtonText); dest.writeBoolean(mConfirmationRequested); dest.writeBoolean(mDeviceCredentialAllowed); dest.writeBoolean(mIdentityCheckActive); dest.writeInt(mAuthenticators); dest.writeBoolean(mDisallowBiometricsIfPolicyExists); dest.writeBoolean(mReceiveSystemEvents); Loading Loading @@ -298,6 +301,10 @@ public class PromptInfo implements Parcelable { mDeviceCredentialAllowed = deviceCredentialAllowed; } public void setIdentityCheckActive(boolean identityCheckActive) { mIdentityCheckActive = identityCheckActive; } public void setAuthenticators(int authenticators) { mAuthenticators = authenticators; } Loading Loading @@ -440,6 +447,10 @@ public class PromptInfo implements Parcelable { return mDeviceCredentialAllowed; } public boolean isIdentityCheckActive() { return mIdentityCheckActive; } public int getAuthenticators() { return mAuthenticators; } Loading
core/java/android/hardware/biometrics/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,13 @@ flag { bug: "391666818" } flag { name: "bp_fallback_options" namespace: "biometrics_framework" description: "Adds fallback options UI to biometric prompt" bug: "377774089" } flag { name: "get_op_id_crypto_object" is_exported: true Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthContainerViewTest.kt +27 −1 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.hardware.biometrics.BiometricAuthenticator import android.hardware.biometrics.BiometricConstants import android.hardware.biometrics.BiometricManager import android.hardware.biometrics.BiometricPrompt import android.hardware.biometrics.Flags import android.hardware.biometrics.PromptContentViewWithMoreOptionsButton import android.hardware.biometrics.PromptInfo import android.hardware.biometrics.PromptVerticalListContentView Loading @@ -30,6 +31,8 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal import android.os.IBinder import android.os.UserManager import android.os.userManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper import android.testing.ViewUtils Loading @@ -46,6 +49,7 @@ import com.android.internal.widget.lockPatternUtils import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.domain.interactor.promptSelectorInteractor import com.android.systemui.biometrics.ui.viewmodel.credentialViewModel import com.android.systemui.biometrics.ui.viewmodel.fallbackViewModelFactory import com.android.systemui.biometrics.ui.viewmodel.promptViewModel import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.haptics.msdl.msdlPlayer Loading @@ -63,11 +67,11 @@ import org.junit.Ignore import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.anyInt import org.mockito.Mockito.anyLong import org.mockito.Mockito.eq import org.mockito.Mockito.never import org.mockito.Mockito.times import org.mockito.Mockito.verify Loading Loading @@ -178,6 +182,7 @@ open class AuthContainerViewTest : SysuiTestCase() { } @Test @DisableFlags(Flags.FLAG_BP_FALLBACK_OPTIONS) fun testIgnoresAnimatedInWhenDialogAnimatingOut() { val container = initializeFingerprintContainer(addToView = false) container.mContainerState = 4 // STATE_ANIMATING_OUT Loading Loading @@ -265,6 +270,24 @@ open class AuthContainerViewTest : SysuiTestCase() { verify(callback).onTryAgainPressed(authContainer?.requestId ?: 0L) } @Test @EnableFlags(Flags.FLAG_BP_FALLBACK_OPTIONS) fun testActionFallbackOption_sendsFallbackOption() { val container = initializeFingerprintContainer( authenticators = BiometricManager.Authenticators.BIOMETRIC_WEAK ) container.mBiometricCallback.onFallbackOptionPressed(0) waitForIdleSync() verify(callback) .onDismissed( eq(BiometricPrompt.DISMISSED_REASON_FALLBACK_OPTION_BASE), eq<ByteArray?>(null), eq(authContainer?.requestId ?: 0L), ) } @Test fun testActionError_sendsDismissedError() { val container = initializeFingerprintContainer() Loading Loading @@ -297,6 +320,7 @@ open class AuthContainerViewTest : SysuiTestCase() { } @Test @DisableFlags(Flags.FLAG_BP_FALLBACK_OPTIONS) fun testAnimateToCredentialUI_invokesStartTransitionToCredentialUI() { val container = initializeFingerprintContainer( Loading @@ -318,6 +342,7 @@ open class AuthContainerViewTest : SysuiTestCase() { } @Test @DisableFlags(Flags.FLAG_BP_FALLBACK_OPTIONS) fun testAnimateToCredentialUI_rotateCredentialUI() { val container = initializeFingerprintContainer( Loading Loading @@ -592,6 +617,7 @@ open class AuthContainerViewTest : SysuiTestCase() { kosmos.fakeExecutor, kosmos.vibratorHelper, kosmos.msdlPlayer, kosmos.fallbackViewModelFactory, ) { override fun postOnAnimation(runnable: Runnable) { runnable.run() Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/biometrics/AuthControllerTest.java +4 −1 Original line number Diff line number Diff line Loading @@ -91,6 +91,7 @@ import com.android.systemui.SysuiTestCase; import com.android.systemui.biometrics.domain.interactor.LogContextInteractor; import com.android.systemui.biometrics.domain.interactor.PromptSelectorInteractor; import com.android.systemui.biometrics.ui.viewmodel.CredentialViewModel; import com.android.systemui.biometrics.ui.viewmodel.PromptFallbackViewModel; import com.android.systemui.biometrics.ui.viewmodel.PromptViewModel; import com.android.systemui.keyguard.WakefulnessLifecycle; import com.android.systemui.statusbar.CommandQueue; Loading Loading @@ -133,6 +134,8 @@ public class AuthControllerTest extends SysuiTestCase { @Mock private PackageManager mPackageManager; @Mock private PromptFallbackViewModel.Factory mFallbackViewModelFactory; @Mock private IBiometricSysuiReceiver mReceiver; @Mock private IBiometricContextListener mContextListener; Loading Loading @@ -1256,7 +1259,7 @@ public class AuthControllerTest extends SysuiTestCase { () -> mLogContextInteractor, () -> mPromptSelectionInteractor, () -> mCredentialViewModel, () -> mPromptViewModel, mInteractionJankMonitor, mHandler, mBackgroundExecutor, mUdfpsUtils, mVibratorHelper, mKeyguardManager, mMSDLPlayer, mWindowManagerProvider); mMSDLPlayer, mWindowManagerProvider, mFallbackViewModelFactory); } @Override Loading
packages/SystemUI/res/layout/biometric_prompt_button_bar.xml +17 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,23 @@ app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" /> <!-- Fallback Button, replaces negative button when there are several fallbacks --> <Button android:id="@+id/button_fallback" style="@style/AuthCredentialNegativeButtonStyle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="24dp" android:layout_marginBottom="8dp" android:text="@string/biometric_dialog_fallback_button" android:visibility="invisible" app:layout_constrainedWidth="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@id/button_center_guideline" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" /> <!-- "Use Credential" Button, replaces if device credential is allowed --> <Button android:id="@+id/button_use_credential" Loading