• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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 android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.os.Parcel;
22 import android.os.Parcelable;
23 import android.util.Log;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 
27 import java.util.ArrayList;
28 import java.util.List;
29 
30 
31 /**
32  * Contains the information of the template of vertical list content view for Biometric Prompt.
33  * <p>
34  * Here's how you'd set a <code>PromptVerticalListContentView</code> on a Biometric Prompt:
35  * <pre class="prettyprint">
36  * BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(...)
37  *     .setTitle(...)
38  *     .setSubTitle(...)
39  *     .setContentView(new PromptVerticalListContentView.Builder()
40  *         .setDescription("test description")
41  *         .addListItem(new PromptContentItemPlainText("test item 1"))
42  *         .addListItem(new PromptContentItemPlainText("test item 2"))
43  *         .addListItem(new PromptContentItemBulletedText("test item 3"))
44  *         .build())
45  *     .build();
46  * </pre>
47  */
48 public final class PromptVerticalListContentView implements PromptContentViewParcelable {
49     private static final String TAG = "PromptVerticalListContentView";
50     @VisibleForTesting
51     static final int MAX_ITEM_NUMBER = 20;
52     @VisibleForTesting
53     static final int MAX_EACH_ITEM_CHARACTER_NUMBER = 640;
54     @VisibleForTesting
55     static final int MAX_DESCRIPTION_CHARACTER_NUMBER = 225;
56 
57     private final List<PromptContentItemParcelable> mContentList;
58     private final String mDescription;
59 
PromptVerticalListContentView( @onNull List<PromptContentItemParcelable> contentList, @NonNull String description)60     private PromptVerticalListContentView(
61             @NonNull List<PromptContentItemParcelable> contentList,
62             @NonNull String description) {
63         mContentList = contentList;
64         mDescription = description;
65     }
66 
PromptVerticalListContentView(Parcel in)67     private PromptVerticalListContentView(Parcel in) {
68         mContentList = in.readArrayList(
69                 PromptContentItemParcelable.class.getClassLoader(),
70                 PromptContentItemParcelable.class);
71         mDescription = in.readString();
72     }
73 
74     /**
75      * Returns the maximum count of the list items.
76      */
getMaxItemCount()77     public static int getMaxItemCount() {
78         return MAX_ITEM_NUMBER;
79     }
80 
81     /**
82      * Returns the maximum number of characters allowed for each item's text.
83      */
getMaxEachItemCharacterNumber()84     public static int getMaxEachItemCharacterNumber() {
85         return MAX_EACH_ITEM_CHARACTER_NUMBER;
86     }
87 
88     /**
89      * Gets the description for the content view, as set by
90      * {@link PromptVerticalListContentView.Builder#setDescription(String)}.
91      *
92      * @return The description for the content view, or null if the content view has no description.
93      */
94     @Nullable
getDescription()95     public String getDescription() {
96         return mDescription;
97     }
98 
99     /**
100      * Gets the list of items on the content view, as set by
101      * {@link PromptVerticalListContentView.Builder#addListItem(PromptContentItem)}.
102      *
103      * @return The item list on the content view.
104      */
105     @NonNull
getListItems()106     public List<PromptContentItem> getListItems() {
107         return new ArrayList<>(mContentList);
108     }
109 
110     /**
111      * {@inheritDoc}
112      */
113     @Override
describeContents()114     public int describeContents() {
115         return 0;
116     }
117 
118     /**
119      * {@inheritDoc}
120      */
121     @Override
writeToParcel(@ndroidx.annotation.NonNull Parcel dest, int flags)122     public void writeToParcel(@androidx.annotation.NonNull Parcel dest, int flags) {
123         dest.writeList(mContentList);
124         dest.writeString(mDescription);
125     }
126 
127     /**
128      * @see Parcelable.Creator
129      */
130     @NonNull
131     public static final Creator<PromptVerticalListContentView> CREATOR = new Creator<>() {
132         @Override
133         public PromptVerticalListContentView createFromParcel(Parcel in) {
134             return new PromptVerticalListContentView(in);
135         }
136 
137         @Override
138         public PromptVerticalListContentView[] newArray(int size) {
139             return new PromptVerticalListContentView[size];
140         }
141     };
142 
143 
144     /**
145      * A builder that collects arguments to be shown on the vertical list view.
146      */
147     public static final class Builder {
148         private final List<PromptContentItemParcelable> mContentList = new ArrayList<>();
149         private String mDescription;
150 
151         /**
152          * Optional: Sets a description that will be shown on the content view.
153          *
154          * @param description The description to display.
155          * @return This builder.
156          */
157         @NonNull
setDescription(@onNull String description)158         public Builder setDescription(@NonNull String description) {
159             if (description.length() > MAX_DESCRIPTION_CHARACTER_NUMBER) {
160                 Log.w(TAG, "The character number of description exceeds "
161                         + MAX_DESCRIPTION_CHARACTER_NUMBER);
162             }
163             mDescription = description;
164             return this;
165         }
166 
167         /**
168          * Optional: Adds a list item in the current row.
169          *
170          * @param listItem The list item view to display
171          * @return This builder.
172          * @throws IllegalArgumentException If the number of list items exceeds certain limit.
173          */
174         @NonNull
addListItem(@onNull PromptContentItem listItem)175         public Builder addListItem(@NonNull PromptContentItem listItem) {
176             mContentList.add((PromptContentItemParcelable) listItem);
177             checkItemLimits(listItem);
178             return this;
179         }
180 
181         /**
182          * Optional: Adds a list item in the current row.
183          *
184          * @param listItem The list item view to display
185          * @param index    The position at which to add the item
186          * @return This builder.
187          * @throws IllegalArgumentException If the number of list items exceeds certain limit.
188          */
189         @NonNull
addListItem(@onNull PromptContentItem listItem, int index)190         public Builder addListItem(@NonNull PromptContentItem listItem, int index) {
191             mContentList.add(index, (PromptContentItemParcelable) listItem);
192             checkItemLimits(listItem);
193             return this;
194         }
195 
checkItemLimits(@onNull PromptContentItem listItem)196         private void checkItemLimits(@NonNull PromptContentItem listItem) {
197             if (doesListItemExceedsCharLimit(listItem)) {
198                 Log.w(TAG, "The character number of list item exceeds "
199                         + MAX_EACH_ITEM_CHARACTER_NUMBER);
200             }
201             if (mContentList.size() > MAX_ITEM_NUMBER) {
202                 throw new IllegalArgumentException(
203                         "The number of list items exceeds " + MAX_ITEM_NUMBER);
204             }
205         }
206 
doesListItemExceedsCharLimit(PromptContentItem listItem)207         private boolean doesListItemExceedsCharLimit(PromptContentItem listItem) {
208             if (listItem instanceof PromptContentItemPlainText) {
209                 return ((PromptContentItemPlainText) listItem).getText().length()
210                         > MAX_EACH_ITEM_CHARACTER_NUMBER;
211             } else if (listItem instanceof PromptContentItemBulletedText) {
212                 return ((PromptContentItemBulletedText) listItem).getText().length()
213                         > MAX_EACH_ITEM_CHARACTER_NUMBER;
214             } else {
215                 return false;
216             }
217         }
218 
219 
220         /**
221          * Creates a {@link PromptVerticalListContentView}.
222          *
223          * @return An instance of {@link PromptVerticalListContentView}.
224          */
225         @NonNull
build()226         public PromptVerticalListContentView build() {
227             return new PromptVerticalListContentView(mContentList, mDescription);
228         }
229     }
230 }
231