Loading core/java/android/hardware/biometrics/BiometricPrompt.java +6 −5 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; import java.lang.annotation.Retention; Loading @@ -70,7 +71,8 @@ import javax.crypto.Mac; public class BiometricPrompt implements BiometricAuthenticator, BiometricConstants { private static final String TAG = "BiometricPrompt"; private static final int MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER = 30; @VisibleForTesting static final int MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER = 30; /** * Error/help message will show for this amount of time. Loading Loading @@ -223,7 +225,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * * @param logoDescription The logo description text that will be shown on the prompt. * @return This builder. * @throws IllegalStateException If logo description is null or exceeds certain character * @throws IllegalArgumentException If logo description is null or exceeds certain character * limit. */ @FlaggedApi(FLAG_CUSTOM_BIOMETRIC_PROMPT) Loading @@ -232,7 +234,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan public BiometricPrompt.Builder setLogoDescription(@NonNull String logoDescription) { if (logoDescription == null || logoDescription.length() > MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER) { throw new IllegalStateException( throw new IllegalArgumentException( "Logo description passed in can not be null or exceed " + MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER + " character number."); } Loading @@ -240,7 +242,6 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } /** * Required: Sets the title that will be shown on the prompt. * @param title The title to display. Loading core/java/android/hardware/biometrics/PromptContentViewWithMoreOptionsButton.java +18 −12 Original line number Diff line number Diff line Loading @@ -29,19 +29,22 @@ import android.hardware.biometrics.BiometricPrompt.ButtonInfo; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; import java.util.concurrent.Executor; /** * Contains the information of the template of content view with a more options button for Biometric * Prompt. * Contains the information of the template of content view with a more options button for * Biometric Prompt. * <p> * This button should be used to provide more options for sign in or other purposes, such as when a * user needs to select between multiple app-specific accounts or profiles that are available for * sign in. This is not common and apps should avoid using it if there is only one choice available * or if the user has already selected the appropriate account to use before invoking * BiometricPrompt because it will create additional steps that the user must navigate through. * Clicking the more options button will dismiss the prompt, provide the app an opportunity to ask * the user for the correct account, and finally allow the app to decide how to proceed once * selected. * sign in. * <p> * Apps should avoid using this when possible because it will create additional steps that the user * must navigate through - clicking the more options button will dismiss the prompt, provide the app * an opportunity to ask the user for the correct option, and finally allow the app to decide how to * proceed once selected. * * <p> * Here's how you'd set a <code>PromptContentViewWithMoreOptionsButton</code> on a Biometric Loading @@ -59,7 +62,8 @@ import java.util.concurrent.Executor; */ @FlaggedApi(FLAG_CUSTOM_BIOMETRIC_PROMPT) public final class PromptContentViewWithMoreOptionsButton implements PromptContentViewParcelable { private static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225; @VisibleForTesting static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225; private final String mDescription; private DialogInterface.OnClickListener mListener; Loading Loading @@ -132,14 +136,16 @@ public final class PromptContentViewWithMoreOptionsButton implements PromptConte } }; /** * A builder that collects arguments to be shown on the content view with more options button. */ public static final class Builder { private String mDescription; private Executor mExecutor; private DialogInterface.OnClickListener mListener; /** * Optional: Sets a description that will be shown on the content view. Note that there are * limits on the number of characters allowed for description. * Optional: Sets a description that will be shown on the content view. * * @param description The description to display. * @return This builder. Loading @@ -149,7 +155,7 @@ public final class PromptContentViewWithMoreOptionsButton implements PromptConte @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED) public Builder setDescription(@NonNull String description) { if (description.length() > MAX_DESCRIPTION_CHARACTER_NUMBER) { throw new IllegalStateException("The character number of description exceeds " throw new IllegalArgumentException("The character number of description exceeds " + MAX_DESCRIPTION_CHARACTER_NUMBER); } mDescription = description; Loading core/java/android/hardware/biometrics/PromptVerticalListContentView.java +11 −6 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; Loading @@ -47,9 +49,12 @@ import java.util.List; */ @FlaggedApi(FLAG_CUSTOM_BIOMETRIC_PROMPT) public final class PromptVerticalListContentView implements PromptContentViewParcelable { private static final int MAX_ITEM_NUMBER = 20; private static final int MAX_EACH_ITEM_CHARACTER_NUMBER = 640; private static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225; @VisibleForTesting static final int MAX_ITEM_NUMBER = 20; @VisibleForTesting static final int MAX_EACH_ITEM_CHARACTER_NUMBER = 640; @VisibleForTesting static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225; private final List<PromptContentItemParcelable> mContentList; private final String mDescription; Loading Loading @@ -155,7 +160,7 @@ public final class PromptVerticalListContentView implements PromptContentViewPar @NonNull public Builder setDescription(@NonNull String description) { if (description.length() > MAX_DESCRIPTION_CHARACTER_NUMBER) { throw new IllegalStateException("The character number of description exceeds " throw new IllegalArgumentException("The character number of description exceeds " + MAX_DESCRIPTION_CHARACTER_NUMBER); } mDescription = description; Loading Loading @@ -195,12 +200,12 @@ public final class PromptVerticalListContentView implements PromptContentViewPar private void checkItemLimits(@NonNull PromptContentItem listItem) { if (doesListItemExceedsCharLimit(listItem)) { throw new IllegalStateException( throw new IllegalArgumentException( "The character number of list item exceeds " + MAX_EACH_ITEM_CHARACTER_NUMBER); } if (mContentList.size() > MAX_ITEM_NUMBER) { throw new IllegalStateException( throw new IllegalArgumentException( "The number of list items exceeds " + MAX_ITEM_NUMBER); } } Loading core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java +122 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,14 @@ package android.hardware.biometrics; import static android.hardware.biometrics.BiometricPrompt.MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER; import static android.hardware.biometrics.PromptContentViewWithMoreOptionsButton.MAX_DESCRIPTION_CHARACTER_NUMBER; import static android.hardware.biometrics.PromptVerticalListContentView.MAX_EACH_ITEM_CHARACTER_NUMBER; import static android.hardware.biometrics.PromptVerticalListContentView.MAX_ITEM_NUMBER; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; Loading @@ -40,6 +48,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoRule; import java.util.Random; import java.util.concurrent.Executor; Loading Loading @@ -86,7 +95,8 @@ public class BiometricPromptTest { @Override public void onAuthenticationError(int errorCode, CharSequence errString) { super.onAuthenticationError(errorCode, errString); }}; } }; mBiometricPrompt.authenticate(mCancellationSignal, mExecutor, callback); mLooper.dispatchAll(); Loading @@ -99,4 +109,112 @@ public class BiometricPromptTest { verify(mService).cancelAuthentication(any(), anyString(), anyLong()); } @Test public void testLogoDescription_null() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new BiometricPrompt.Builder(mContext).setLogoDescription(null) ); assertThat(e).hasMessageThat().contains( "Logo description passed in can not be null or exceed"); } @Test public void testLogoDescription_charLimit() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new BiometricPrompt.Builder(mContext).setLogoDescription( generateRandomString(MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER + 1)) ); assertThat(e).hasMessageThat().contains( "Logo description passed in can not be null or exceed"); } @Test public void testMoreOptionsButton_descriptionCharLimit() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new PromptContentViewWithMoreOptionsButton.Builder().setDescription( generateRandomString(MAX_DESCRIPTION_CHARACTER_NUMBER + 1)) ); assertThat(e).hasMessageThat().contains( "The character number of description exceeds "); } @Test public void testMoreOptionsButton_ExecutorNull() { PromptContentViewWithMoreOptionsButton.Builder builder = new PromptContentViewWithMoreOptionsButton.Builder().setMoreOptionsButtonListener( null, null); IllegalArgumentException e = assertThrows(IllegalArgumentException.class, builder::build ); assertThat(e).hasMessageThat().contains( "The executor for the listener of more options button on prompt content must be " + "set"); } @Test public void testMoreOptionsButton_ListenerNull() { PromptContentViewWithMoreOptionsButton.Builder builder = new PromptContentViewWithMoreOptionsButton.Builder().setMoreOptionsButtonListener( mExecutor, null); IllegalArgumentException e = assertThrows(IllegalArgumentException.class, builder::build ); assertThat(e).hasMessageThat().contains( "The listener of more options button on prompt content must be set"); } @Test public void testVerticalList_descriptionCharLimit() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new PromptVerticalListContentView.Builder().setDescription( generateRandomString(MAX_DESCRIPTION_CHARACTER_NUMBER + 1)) ); assertThat(e).hasMessageThat().contains( "The character number of description exceeds "); } @Test public void testVerticalList_itemCharLimit() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new PromptVerticalListContentView.Builder().addListItem( new PromptContentItemBulletedText( generateRandomString(MAX_EACH_ITEM_CHARACTER_NUMBER + 1))) ); assertThat(e).hasMessageThat().contains( "The character number of list item exceeds "); } @Test public void testVerticalList_itemNumLimit() { PromptVerticalListContentView.Builder builder = new PromptVerticalListContentView.Builder(); for (int i = 0; i < MAX_ITEM_NUMBER; i++) { builder.addListItem(new PromptContentItemBulletedText(generateRandomString(10))); } IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> builder.addListItem( new PromptContentItemBulletedText(generateRandomString(10))) ); assertThat(e).hasMessageThat().contains( "The number of list items exceeds "); } private String generateRandomString(int charNum) { final Random random = new Random(); final StringBuilder longString = new StringBuilder(charNum); for (int j = 0; j < charNum; j++) { longString.append(random.nextInt(10)); } return longString.toString(); } } packages/SystemUI/res/values/styles.xml +1 −0 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ <style name="TextAppearance.AuthCredential.ContentViewListItem" parent="TextAppearance.Material3.BodySmall"> <item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item> <item name="android:paddingTop">@dimen/biometric_prompt_content_list_item_padding_top</item> <item name="android:breakStrategy">high_quality</item> </style> <style name="TextAppearance.AuthCredential.Indicator" parent="TextAppearance.Material3.BodyMedium"> Loading Loading
core/java/android/hardware/biometrics/BiometricPrompt.java +6 −5 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; import java.lang.annotation.Retention; Loading @@ -70,7 +71,8 @@ import javax.crypto.Mac; public class BiometricPrompt implements BiometricAuthenticator, BiometricConstants { private static final String TAG = "BiometricPrompt"; private static final int MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER = 30; @VisibleForTesting static final int MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER = 30; /** * Error/help message will show for this amount of time. Loading Loading @@ -223,7 +225,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan * * @param logoDescription The logo description text that will be shown on the prompt. * @return This builder. * @throws IllegalStateException If logo description is null or exceeds certain character * @throws IllegalArgumentException If logo description is null or exceeds certain character * limit. */ @FlaggedApi(FLAG_CUSTOM_BIOMETRIC_PROMPT) Loading @@ -232,7 +234,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan public BiometricPrompt.Builder setLogoDescription(@NonNull String logoDescription) { if (logoDescription == null || logoDescription.length() > MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER) { throw new IllegalStateException( throw new IllegalArgumentException( "Logo description passed in can not be null or exceed " + MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER + " character number."); } Loading @@ -240,7 +242,6 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } /** * Required: Sets the title that will be shown on the prompt. * @param title The title to display. Loading
core/java/android/hardware/biometrics/PromptContentViewWithMoreOptionsButton.java +18 −12 Original line number Diff line number Diff line Loading @@ -29,19 +29,22 @@ import android.hardware.biometrics.BiometricPrompt.ButtonInfo; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; import java.util.concurrent.Executor; /** * Contains the information of the template of content view with a more options button for Biometric * Prompt. * Contains the information of the template of content view with a more options button for * Biometric Prompt. * <p> * This button should be used to provide more options for sign in or other purposes, such as when a * user needs to select between multiple app-specific accounts or profiles that are available for * sign in. This is not common and apps should avoid using it if there is only one choice available * or if the user has already selected the appropriate account to use before invoking * BiometricPrompt because it will create additional steps that the user must navigate through. * Clicking the more options button will dismiss the prompt, provide the app an opportunity to ask * the user for the correct account, and finally allow the app to decide how to proceed once * selected. * sign in. * <p> * Apps should avoid using this when possible because it will create additional steps that the user * must navigate through - clicking the more options button will dismiss the prompt, provide the app * an opportunity to ask the user for the correct option, and finally allow the app to decide how to * proceed once selected. * * <p> * Here's how you'd set a <code>PromptContentViewWithMoreOptionsButton</code> on a Biometric Loading @@ -59,7 +62,8 @@ import java.util.concurrent.Executor; */ @FlaggedApi(FLAG_CUSTOM_BIOMETRIC_PROMPT) public final class PromptContentViewWithMoreOptionsButton implements PromptContentViewParcelable { private static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225; @VisibleForTesting static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225; private final String mDescription; private DialogInterface.OnClickListener mListener; Loading Loading @@ -132,14 +136,16 @@ public final class PromptContentViewWithMoreOptionsButton implements PromptConte } }; /** * A builder that collects arguments to be shown on the content view with more options button. */ public static final class Builder { private String mDescription; private Executor mExecutor; private DialogInterface.OnClickListener mListener; /** * Optional: Sets a description that will be shown on the content view. Note that there are * limits on the number of characters allowed for description. * Optional: Sets a description that will be shown on the content view. * * @param description The description to display. * @return This builder. Loading @@ -149,7 +155,7 @@ public final class PromptContentViewWithMoreOptionsButton implements PromptConte @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED) public Builder setDescription(@NonNull String description) { if (description.length() > MAX_DESCRIPTION_CHARACTER_NUMBER) { throw new IllegalStateException("The character number of description exceeds " throw new IllegalArgumentException("The character number of description exceeds " + MAX_DESCRIPTION_CHARACTER_NUMBER); } mDescription = description; Loading
core/java/android/hardware/biometrics/PromptVerticalListContentView.java +11 −6 Original line number Diff line number Diff line Loading @@ -24,6 +24,8 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.List; Loading @@ -47,9 +49,12 @@ import java.util.List; */ @FlaggedApi(FLAG_CUSTOM_BIOMETRIC_PROMPT) public final class PromptVerticalListContentView implements PromptContentViewParcelable { private static final int MAX_ITEM_NUMBER = 20; private static final int MAX_EACH_ITEM_CHARACTER_NUMBER = 640; private static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225; @VisibleForTesting static final int MAX_ITEM_NUMBER = 20; @VisibleForTesting static final int MAX_EACH_ITEM_CHARACTER_NUMBER = 640; @VisibleForTesting static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225; private final List<PromptContentItemParcelable> mContentList; private final String mDescription; Loading Loading @@ -155,7 +160,7 @@ public final class PromptVerticalListContentView implements PromptContentViewPar @NonNull public Builder setDescription(@NonNull String description) { if (description.length() > MAX_DESCRIPTION_CHARACTER_NUMBER) { throw new IllegalStateException("The character number of description exceeds " throw new IllegalArgumentException("The character number of description exceeds " + MAX_DESCRIPTION_CHARACTER_NUMBER); } mDescription = description; Loading Loading @@ -195,12 +200,12 @@ public final class PromptVerticalListContentView implements PromptContentViewPar private void checkItemLimits(@NonNull PromptContentItem listItem) { if (doesListItemExceedsCharLimit(listItem)) { throw new IllegalStateException( throw new IllegalArgumentException( "The character number of list item exceeds " + MAX_EACH_ITEM_CHARACTER_NUMBER); } if (mContentList.size() > MAX_ITEM_NUMBER) { throw new IllegalStateException( throw new IllegalArgumentException( "The number of list items exceeds " + MAX_ITEM_NUMBER); } } Loading
core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java +122 −4 Original line number Diff line number Diff line Loading @@ -16,6 +16,14 @@ package android.hardware.biometrics; import static android.hardware.biometrics.BiometricPrompt.MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER; import static android.hardware.biometrics.PromptContentViewWithMoreOptionsButton.MAX_DESCRIPTION_CHARACTER_NUMBER; import static android.hardware.biometrics.PromptVerticalListContentView.MAX_EACH_ITEM_CHARACTER_NUMBER; import static android.hardware.biometrics.PromptVerticalListContentView.MAX_ITEM_NUMBER; import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; Loading @@ -40,6 +48,7 @@ import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoJUnitRunner; import org.mockito.junit.MockitoRule; import java.util.Random; import java.util.concurrent.Executor; Loading Loading @@ -86,7 +95,8 @@ public class BiometricPromptTest { @Override public void onAuthenticationError(int errorCode, CharSequence errString) { super.onAuthenticationError(errorCode, errString); }}; } }; mBiometricPrompt.authenticate(mCancellationSignal, mExecutor, callback); mLooper.dispatchAll(); Loading @@ -99,4 +109,112 @@ public class BiometricPromptTest { verify(mService).cancelAuthentication(any(), anyString(), anyLong()); } @Test public void testLogoDescription_null() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new BiometricPrompt.Builder(mContext).setLogoDescription(null) ); assertThat(e).hasMessageThat().contains( "Logo description passed in can not be null or exceed"); } @Test public void testLogoDescription_charLimit() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new BiometricPrompt.Builder(mContext).setLogoDescription( generateRandomString(MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER + 1)) ); assertThat(e).hasMessageThat().contains( "Logo description passed in can not be null or exceed"); } @Test public void testMoreOptionsButton_descriptionCharLimit() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new PromptContentViewWithMoreOptionsButton.Builder().setDescription( generateRandomString(MAX_DESCRIPTION_CHARACTER_NUMBER + 1)) ); assertThat(e).hasMessageThat().contains( "The character number of description exceeds "); } @Test public void testMoreOptionsButton_ExecutorNull() { PromptContentViewWithMoreOptionsButton.Builder builder = new PromptContentViewWithMoreOptionsButton.Builder().setMoreOptionsButtonListener( null, null); IllegalArgumentException e = assertThrows(IllegalArgumentException.class, builder::build ); assertThat(e).hasMessageThat().contains( "The executor for the listener of more options button on prompt content must be " + "set"); } @Test public void testMoreOptionsButton_ListenerNull() { PromptContentViewWithMoreOptionsButton.Builder builder = new PromptContentViewWithMoreOptionsButton.Builder().setMoreOptionsButtonListener( mExecutor, null); IllegalArgumentException e = assertThrows(IllegalArgumentException.class, builder::build ); assertThat(e).hasMessageThat().contains( "The listener of more options button on prompt content must be set"); } @Test public void testVerticalList_descriptionCharLimit() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new PromptVerticalListContentView.Builder().setDescription( generateRandomString(MAX_DESCRIPTION_CHARACTER_NUMBER + 1)) ); assertThat(e).hasMessageThat().contains( "The character number of description exceeds "); } @Test public void testVerticalList_itemCharLimit() { IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> new PromptVerticalListContentView.Builder().addListItem( new PromptContentItemBulletedText( generateRandomString(MAX_EACH_ITEM_CHARACTER_NUMBER + 1))) ); assertThat(e).hasMessageThat().contains( "The character number of list item exceeds "); } @Test public void testVerticalList_itemNumLimit() { PromptVerticalListContentView.Builder builder = new PromptVerticalListContentView.Builder(); for (int i = 0; i < MAX_ITEM_NUMBER; i++) { builder.addListItem(new PromptContentItemBulletedText(generateRandomString(10))); } IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> builder.addListItem( new PromptContentItemBulletedText(generateRandomString(10))) ); assertThat(e).hasMessageThat().contains( "The number of list items exceeds "); } private String generateRandomString(int charNum) { final Random random = new Random(); final StringBuilder longString = new StringBuilder(charNum); for (int j = 0; j < charNum; j++) { longString.append(random.nextInt(10)); } return longString.toString(); } }
packages/SystemUI/res/values/styles.xml +1 −0 Original line number Diff line number Diff line Loading @@ -224,6 +224,7 @@ <style name="TextAppearance.AuthCredential.ContentViewListItem" parent="TextAppearance.Material3.BodySmall"> <item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item> <item name="android:paddingTop">@dimen/biometric_prompt_content_list_item_padding_top</item> <item name="android:breakStrategy">high_quality</item> </style> <style name="TextAppearance.AuthCredential.Indicator" parent="TextAppearance.Material3.BodyMedium"> Loading