Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86e20959 authored by Hao Dong's avatar Hao Dong
Browse files

Log the warning if logo description exceeds char limit.

1. Remove the exception for logo description char limit and log a
   warning instead.
2. Truncate if the logo description exceeds 30 characters
3. Set title's top constraint on both logo icon and logo description for
   non-icon or non-description cases.

Flag: android.hardware.biometrics.custom_biometric_prompt
Bug: 355677518
Test: manual test on test app
Test: atest BiometricPromptTest
Test: atest BiometricPromptScreenshotTest

Change-Id: Icb07acd88138a7519f73d3df9ab323220d99dfe7
parent 421f3f05
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -240,18 +240,19 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
         *
         * @param logoDescription The logo description text that will be shown on the prompt.
         * @return This builder.
         * @throws IllegalArgumentException If logo description is null or exceeds certain character
         *                                  limit.
         * @throws IllegalArgumentException If logo description is null.
         */
        @FlaggedApi(FLAG_CUSTOM_BIOMETRIC_PROMPT)
        @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
        @NonNull
        public BiometricPrompt.Builder setLogoDescription(@NonNull String logoDescription) {
            if (logoDescription == null
                    || logoDescription.length() > MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER) {
                throw new IllegalArgumentException(
                        "Logo description passed in can not be null or exceed "
                                + MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER + " character number.");
            if (logoDescription == null || logoDescription.isEmpty()) {
                throw new IllegalArgumentException("Logo description passed in can not be null");
            }
            if (logoDescription.length() > MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER) {
                Log.w(TAG,
                        "Logo description passed in exceeds" + MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER
                                + " character number and may be truncated.");
            }
            mPromptInfo.setLogoDescription(logoDescription);
            return this;
+1 −14
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

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;
@@ -117,19 +116,7 @@ public class BiometricPromptTest {
                () -> 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");
        assertThat(e).hasMessageThat().isEqualTo("Logo description passed in can not be null");
    }

    @Test
+16 −6
Original line number Diff line number Diff line
@@ -87,20 +87,21 @@ android:layout_height="match_parent">
                android:id="@+id/logo_description"
                style="@style/TextAppearance.AuthCredential.LogoDescription"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_height="@dimen/biometric_prompt_logo_size"
                android:gravity="start|center_vertical"
                android:textAlignment="viewStart"
                android:paddingStart="16dp"
                app:layout_constraintBottom_toBottomOf="@+id/logo"
                android:layout_marginStart="16dp"
                app:layout_goneMarginStart="0dp"
                app:layout_constraintBottom_toTopOf="@+id/title"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toEndOf="@+id/logo"
                app:layout_constraintTop_toTopOf="@+id/logo" />
                app:layout_constraintTop_toTopOf="parent" />

            <TextView
                android:id="@+id/title"
                style="@style/TextAppearance.AuthCredential.Title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="12dp"
                android:gravity="@integer/biometric_dialog_text_gravity"
                android:paddingHorizontal="0dp"
                android:textAlignment="viewStart"
@@ -108,7 +109,7 @@ android:layout_height="match_parent">
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintHorizontal_bias="0.0"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/logo"
                app:layout_constraintTop_toBottomOf="@+id/logoBarrier"
                app:layout_constraintVertical_bias="0.0"
                app:layout_constraintVertical_chainStyle="packed" />

@@ -158,6 +159,15 @@ android:layout_height="match_parent">
                app:layout_constraintTop_toBottomOf="@+id/subtitle"
                app:layout_constraintVertical_bias="0.0" />

            <androidx.constraintlayout.widget.Barrier
                android:id="@+id/logoBarrier"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                app:barrierMargin="12dp"
                app:barrierAllowsGoneWidgets="false"
                app:barrierDirection="bottom"
                app:constraint_referenced_ids="logo_description, logo" />

            <androidx.constraintlayout.widget.Barrier
                android:id="@+id/contentBarrier"
                android:layout_width="wrap_content"
+2 −3
Original line number Diff line number Diff line
@@ -192,11 +192,10 @@

    <style name="TextAppearance.AuthCredential.LogoDescription" parent="TextAppearance.Material3.LabelLarge" >
        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
        <item name="android:ellipsize">marquee</item>
        <item name="android:gravity">@integer/biometric_dialog_text_gravity</item>
        <item name="android:marqueeRepeatLimit">1</item>
        <item name="android:singleLine">true</item>
        <item name="android:maxLines">1</item>
        <item name="android:textColor">?androidprv:attr/materialColorOnSurfaceVariant</item>
        <item name="android:ellipsize">end</item>
    </style>

    <style name="TextAppearance.AuthCredential.Title" parent="TextAppearance.Material3.HeadlineSmall" >
+8 −1
Original line number Diff line number Diff line
@@ -63,6 +63,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

private const val TAG = "BiometricViewBinder"
private const val MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER = 30

/** Top-most view binder for BiometricPrompt views. */
object BiometricViewBinder {
@@ -173,7 +174,10 @@ object BiometricViewBinder {
            }

            logoView.setImageDrawable(viewModel.logo.first())
            logoDescriptionView.text = viewModel.logoDescription.first()
            // The ellipsize effect on xml happens only when the TextView does not have any free
            // space on the screen to show the text. So we need to manually truncate.
            logoDescriptionView.text =
                viewModel.logoDescription.first().ellipsize(MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER)
            titleView.text = viewModel.title.first()
            subtitleView.text = viewModel.subtitle.first()
            descriptionView.text = viewModel.description.first()
@@ -694,6 +698,9 @@ private fun BiometricModalities.asDefaultHelpMessage(context: Context): String =
        else -> ""
    }

private fun String.ellipsize(cutOffLength: Int) =
    if (length <= cutOffLength) this else replaceRange(cutOffLength, length, "...")

private fun Boolean.asVisibleOrGone(): Int = if (this) View.VISIBLE else View.GONE

private fun Boolean.asVisibleOrHidden(): Int = if (this) View.VISIBLE else View.INVISIBLE