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

Commit cf7d9a50 authored by Hao Dong's avatar Hao Dong
Browse files

Add char limits and permission enforcement for custom bp.

Flag: ACONFIG android.hardware.biometrics.custom_biometric_prompt DEVELOPMENT
Bug: 302735104
Test: atest BiometricPromptLogoTests
Test: atest BiometricPromptContentViewTest
Change-Id: Id159cde0df2520b4474c216f8d6503558262fc67
parent fa4bde6d
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -70,6 +70,7 @@ 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;

    /**
     * Error/help message will show for this amount of time.
@@ -222,11 +223,19 @@ 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
         *                               limit.
         */
        @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 IllegalStateException(
                        "Logo description passed in can not be null or exceed "
                                + MAX_LOGO_DESCRIPTION_CHARACTER_NUMBER + " character number.");
            }
            mPromptInfo.setLogoDescription(logoDescription);
            return this;
        }
@@ -814,7 +823,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan

    /**
     * Gets the logo description for the prompt, as set by
     * {@link Builder#setDescription(CharSequence)}.
     * {@link Builder#setLogoDescription(String)}.
     * Currently for system applications use only.
     *
     * @return The logo description of the prompt, or null if the prompt has no logo description
+21 −18
Original line number Diff line number Diff line
@@ -40,9 +40,12 @@ import java.util.concurrent.Executor;
 * 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, &finally allow the app to decide how to proceed once selected.
 * the user for the correct account, 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 Prompt:
 * Here's how you'd set a <code>PromptContentViewWithMoreOptionsButton</code> on a Biometric
 * Prompt:
 * <pre class="prettyprint">
 * BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(...)
 *     .setTitle(...)
@@ -56,6 +59,7 @@ 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;

    private final String mDescription;
    private DialogInterface.OnClickListener mListener;
@@ -139,10 +143,15 @@ public final class PromptContentViewWithMoreOptionsButton implements PromptConte
         *
         * @param description The description to display.
         * @return This builder.
         * @throws IllegalArgumentException If description exceeds certain character limit.
         */
        @NonNull
        @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 "
                        + MAX_DESCRIPTION_CHARACTER_NUMBER);
            }
            mDescription = description;
            return this;
        }
@@ -150,14 +159,6 @@ public final class PromptContentViewWithMoreOptionsButton implements PromptConte
        /**
         * Required: Sets the executor and click listener for the more options button on the
         * prompt content.
         * 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, &finally
         * allow the app to decide how to proceed once selected.
         *
         * @param executor Executor that will be used to run the on click callback.
         * @param listener Listener containing a callback to be run when the button is pressed.
@@ -167,12 +168,6 @@ public final class PromptContentViewWithMoreOptionsButton implements PromptConte
        @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
        public Builder setMoreOptionsButtonListener(@NonNull @CallbackExecutor Executor executor,
                @NonNull DialogInterface.OnClickListener listener) {
            if (executor == null) {
                throw new IllegalArgumentException("Executor must not be null");
            }
            if (listener == null) {
                throw new IllegalArgumentException("Listener must not be null");
            }
            mExecutor = executor;
            mListener = listener;
            return this;
@@ -183,15 +178,23 @@ public final class PromptContentViewWithMoreOptionsButton implements PromptConte
         * Creates a {@link PromptContentViewWithMoreOptionsButton}.
         *
         * @return An instance of {@link PromptContentViewWithMoreOptionsButton}.
         * @throws IllegalArgumentException If the executor of more options button is null, or the
         *                                  listener of more options button is null.
         */
        @NonNull
        @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
        public PromptContentViewWithMoreOptionsButton build() {
            if (mListener == null) {
            if (mExecutor == null) {
                throw new IllegalArgumentException(
                        "The listener of more options button on prompt content must be set if "
                        "The executor for the listener of more options button on prompt content "
                                + "must be set and non-null if "
                                + "PromptContentViewWithMoreOptionsButton is used.");
            }
            if (mListener == null) {
                throw new IllegalArgumentException(
                        "The listener of more options button on prompt content must be set and "
                                + "non-null if PromptContentViewWithMoreOptionsButton is used.");
            }
            return new PromptContentViewWithMoreOptionsButton(mDescription, mExecutor, mListener);
        }
    }
+6 −1
Original line number Diff line number Diff line
@@ -173,14 +173,19 @@ public class PromptInfo implements Parcelable {

    /**
     * Returns whether SET_BIOMETRIC_DIALOG_ADVANCED is contained.
     *
     * Currently, logo res, logo bitmap, logo description, PromptContentViewWithMoreOptions needs
     * this permission.
     */
    public boolean containsSetLogoApiConfigurations() {
    public boolean containsAdvancedApiConfigurations() {
        if (mLogoRes != -1) {
            return true;
        } else if (mLogoBitmap != null) {
            return true;
        } else if (mLogoDescription != null) {
            return true;
        } else if (mContentView != null && isContentViewMoreOptionsButtonUsed()) {
            return true;
        }
        return false;
    }
+26 −22
Original line number Diff line number Diff line
@@ -29,9 +29,7 @@ import java.util.List;


/**
 * Contains the information of the template of vertical list content view for Biometric Prompt. Note
 * that there are limits on the item count and the number of characters allowed for each item's
 * text.
 * Contains the information of the template of vertical list content view for Biometric Prompt.
 * <p>
 * Here's how you'd set a <code>PromptVerticalListContentView</code> on a Biometric Prompt:
 * <pre class="prettyprint">
@@ -51,6 +49,8 @@ import java.util.List;
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;

    private final List<PromptContentItemParcelable> mContentList;
    private final String mDescription;

@@ -150,51 +150,59 @@ public final class PromptVerticalListContentView implements PromptContentViewPar
         *
         * @param description The description to display.
         * @return This builder.
         * @throws IllegalArgumentException If description exceeds certain character limit.
         */
        @NonNull
        public Builder setDescription(@NonNull String description) {
            if (description.length() > MAX_DESCRIPTION_CHARACTER_NUMBER) {
                throw new IllegalStateException("The character number of description exceeds "
                        + MAX_DESCRIPTION_CHARACTER_NUMBER);
            }
            mDescription = description;
            return this;
        }

        /**
         * Optional: Adds a list item in the current row. Maximum {@value MAX_ITEM_NUMBER} items in
         * total. The maximum length for each item is {@value MAX_EACH_ITEM_CHARACTER_NUMBER}
         * characters.
         * Optional: Adds a list item in the current row.
         *
         * @param listItem The list item view to display
         * @return This builder.
         * @throws IllegalArgumentException If this list item exceeds certain character limits or
         *                                  the number of list items exceeds certain limit.
         */
        @NonNull
        public Builder addListItem(@NonNull PromptContentItem listItem) {
            if (doesListItemExceedsCharLimit(listItem)) {
                throw new IllegalStateException(
                        "The character number of list item exceeds "
                                + MAX_EACH_ITEM_CHARACTER_NUMBER);
            }
            mContentList.add((PromptContentItemParcelable) listItem);
            checkItemLimits(listItem);
            return this;
        }


        /**
         * Optional: Adds a list item in the current row. Maximum {@value MAX_ITEM_NUMBER} items in
         * total. The maximum length for each item is {@value MAX_EACH_ITEM_CHARACTER_NUMBER}
         * characters.
         * Optional: Adds a list item in the current row.
         *
         * @param listItem The list item view to display
         * @param index    The position at which to add the item
         * @return This builder.
         * @throws IllegalArgumentException If this list item exceeds certain character limits or
         *                                  the number of list items exceeds certain limit.
         */
        @NonNull
        public Builder addListItem(@NonNull PromptContentItem listItem, int index) {
            mContentList.add(index, (PromptContentItemParcelable) listItem);
            checkItemLimits(listItem);
            return this;
        }

        private void checkItemLimits(@NonNull PromptContentItem listItem) {
            if (doesListItemExceedsCharLimit(listItem)) {
                throw new IllegalStateException(
                        "The character number of list item exceeds "
                                + MAX_EACH_ITEM_CHARACTER_NUMBER);
            }
            mContentList.add(index, (PromptContentItemParcelable) listItem);
            return this;
            if (mContentList.size() > MAX_ITEM_NUMBER) {
                throw new IllegalStateException(
                        "The number of list items exceeds " + MAX_ITEM_NUMBER);
            }
        }

        private boolean doesListItemExceedsCharLimit(PromptContentItem listItem) {
@@ -217,10 +225,6 @@ public final class PromptVerticalListContentView implements PromptContentViewPar
         */
        @NonNull
        public PromptVerticalListContentView build() {
            if (mContentList.size() > MAX_ITEM_NUMBER) {
                throw new IllegalStateException(
                        "The number of list items exceeds " + MAX_ITEM_NUMBER);
            }
            return new PromptVerticalListContentView(mContentList, mDescription);
        }
    }
+1 −1
Original line number Diff line number Diff line
@@ -6778,7 +6778,7 @@
                android:protectionLevel="signature" />

    <!-- Allows an application to set the advanced features on BiometricDialog (SystemUI), including
         logo, logo description.
         logo, logo description, and content view with more options button.
         <p>Not for use by third-party applications.
         @FlaggedApi("android.hardware.biometrics.custom_biometric_prompt")
    -->
Loading