• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.hardware.biometrics;
18 
19 import static android.Manifest.permission.SET_BIOMETRIC_DIALOG_ADVANCED;
20 
21 import android.annotation.CallbackExecutor;
22 import android.annotation.NonNull;
23 import android.annotation.Nullable;
24 import android.annotation.RequiresPermission;
25 import android.content.DialogInterface;
26 import android.hardware.biometrics.BiometricPrompt.ButtonInfo;
27 import android.os.Parcel;
28 import android.os.Parcelable;
29 import android.util.Log;
30 
31 import com.android.internal.annotations.VisibleForTesting;
32 
33 import java.util.concurrent.Executor;
34 
35 /**
36  * Contains the information of the template of content view with a more options button for
37  * Biometric Prompt.
38  * <p>
39  * This button should be used to provide more options for sign in or other purposes, such as when a
40  * user needs to select between multiple app-specific accounts or profiles that are available for
41  * sign in.
42  * <p>
43  * Apps should avoid using this when possible because it will create additional steps that the user
44  * must navigate through - clicking the more options button will dismiss the prompt, provide the app
45  * an opportunity to ask the user for the correct option, and finally allow the app to decide how to
46  * proceed once selected.
47  *
48  * <p>
49  * Here's how you'd set a <code>PromptContentViewWithMoreOptionsButton</code> on a Biometric
50  * Prompt:
51  * <pre class="prettyprint">
52  * BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(...)
53  *     .setTitle(...)
54  *     .setSubTitle(...)
55  *     .setContentView(new PromptContentViewWithMoreOptionsButton.Builder()
56  *         .setDescription("test description")
57  *         .setMoreOptionsButtonListener(executor, listener)
58  *         .build())
59  *     .build();
60  * </pre>
61  */
62 public final class PromptContentViewWithMoreOptionsButton implements PromptContentViewParcelable {
63     private static final String TAG = "PromptContentViewWithMoreOptionsButton";
64     @VisibleForTesting
65     static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225;
66 
67     private final String mDescription;
68     private DialogInterface.OnClickListener mListener;
69     private ButtonInfo mButtonInfo;
70 
PromptContentViewWithMoreOptionsButton( @onNull String description, @NonNull @CallbackExecutor Executor executor, @NonNull DialogInterface.OnClickListener listener)71     private PromptContentViewWithMoreOptionsButton(
72             @NonNull String description, @NonNull @CallbackExecutor Executor executor,
73             @NonNull DialogInterface.OnClickListener listener) {
74         mDescription = description;
75         mListener = listener;
76         mButtonInfo = new ButtonInfo(executor, listener);
77     }
78 
PromptContentViewWithMoreOptionsButton(Parcel in)79     private PromptContentViewWithMoreOptionsButton(Parcel in) {
80         mDescription = in.readString();
81     }
82 
83     /**
84      * Gets the description for the content view, as set by
85      * {@link PromptContentViewWithMoreOptionsButton.Builder#setDescription(String)}.
86      *
87      * @return The description for the content view, or null if the content view has no description.
88      */
89     @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
90     @Nullable
getDescription()91     public String getDescription() {
92         return mDescription;
93     }
94 
95     /**
96      * Gets the click listener for the more options button on the content view, as set by
97      * {@link PromptContentViewWithMoreOptionsButton.Builder#setMoreOptionsButtonListener(Executor,
98      * DialogInterface.OnClickListener)}.
99      *
100      * @return The click listener for the more options button on the content view.
101      */
102     @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
103     @NonNull
getMoreOptionsButtonListener()104     public DialogInterface.OnClickListener getMoreOptionsButtonListener() {
105         return mListener;
106     }
107 
getButtonInfo()108     ButtonInfo getButtonInfo() {
109         return mButtonInfo;
110     }
111 
112     @Override
describeContents()113     public int describeContents() {
114         return 0;
115     }
116 
117     @Override
writeToParcel(@onNull Parcel dest, int flags)118     public void writeToParcel(@NonNull Parcel dest, int flags) {
119         dest.writeString(mDescription);
120     }
121 
122     /**
123      * @see Parcelable.Creator
124      */
125     @NonNull
126     public static final Creator<PromptContentViewWithMoreOptionsButton> CREATOR = new Creator<>() {
127         @Override
128         public PromptContentViewWithMoreOptionsButton createFromParcel(Parcel in) {
129             return new PromptContentViewWithMoreOptionsButton(in);
130         }
131 
132         @Override
133         public PromptContentViewWithMoreOptionsButton[] newArray(int size) {
134             return new PromptContentViewWithMoreOptionsButton[size];
135         }
136     };
137 
138     /**
139      * A builder that collects arguments to be shown on the content view with more options button.
140      */
141     public static final class Builder {
142         private String mDescription;
143         private Executor mExecutor;
144         private DialogInterface.OnClickListener mListener;
145 
146         /**
147          * Optional: Sets a description that will be shown on the content view.
148          *
149          * @param description The description to display.
150          * @return This builder.
151          */
152         @NonNull
153         @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
setDescription(@onNull String description)154         public Builder setDescription(@NonNull String description) {
155             if (description.length() > MAX_DESCRIPTION_CHARACTER_NUMBER) {
156                 Log.w(TAG, "The character number of description exceeds "
157                         + MAX_DESCRIPTION_CHARACTER_NUMBER);
158             }
159             mDescription = description;
160             return this;
161         }
162 
163         /**
164          * Required: Sets the executor and click listener for the more options button on the
165          * prompt content.
166          *
167          * @param executor Executor that will be used to run the on click callback.
168          * @param listener Listener containing a callback to be run when the button is pressed.
169          * @return This builder.
170          */
171         @NonNull
172         @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
setMoreOptionsButtonListener(@onNull @allbackExecutor Executor executor, @NonNull DialogInterface.OnClickListener listener)173         public Builder setMoreOptionsButtonListener(@NonNull @CallbackExecutor Executor executor,
174                 @NonNull DialogInterface.OnClickListener listener) {
175             mExecutor = executor;
176             mListener = listener;
177             return this;
178         }
179 
180 
181         /**
182          * Creates a {@link PromptContentViewWithMoreOptionsButton}.
183          *
184          * @return An instance of {@link PromptContentViewWithMoreOptionsButton}.
185          * @throws IllegalArgumentException If the executor of more options button is null, or the
186          *                                  listener of more options button is null.
187          */
188         @NonNull
189         @RequiresPermission(SET_BIOMETRIC_DIALOG_ADVANCED)
build()190         public PromptContentViewWithMoreOptionsButton build() {
191             if (mExecutor == null) {
192                 throw new IllegalArgumentException(
193                         "The executor for the listener of more options button on prompt content "
194                                 + "must be set and non-null if "
195                                 + "PromptContentViewWithMoreOptionsButton is used.");
196             }
197             if (mListener == null) {
198                 throw new IllegalArgumentException(
199                         "The listener of more options button on prompt content must be set and "
200                                 + "non-null if PromptContentViewWithMoreOptionsButton is used.");
201             }
202             return new PromptContentViewWithMoreOptionsButton(mDescription, mExecutor, mListener);
203         }
204     }
205 }
206