FillResponse.java revision 640f30a7763b0a4b80c767acb84c740aac04768b
126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen/*
226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Copyright (C) 2016 The Android Open Source Project
326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *
426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Licensed under the Apache License, Version 2.0 (the "License");
526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * you may not use this file except in compliance with the License.
626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * You may obtain a copy of the License at
726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *
826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *      http://www.apache.org/licenses/LICENSE-2.0
926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *
1026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * Unless required by applicable law or agreed to in writing, software
1126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * distributed under the License is distributed on an "AS IS" BASIS,
1226a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * See the License for the specific language governing permissions and
1426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen * limitations under the License.
1526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen */
1626a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenpackage android.service.autofill;
1726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen
1826a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenimport static android.view.autofill.Helper.DEBUG;
1926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen
2026a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenimport android.annotation.NonNull;
2126a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenimport android.annotation.Nullable;
228a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemonimport android.content.IntentSender;
2326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenimport android.os.Bundle;
2426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenimport android.os.Parcel;
2526a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssenimport android.os.Parcelable;
26b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkeimport android.view.autofill.AutofillManager;
27e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemonimport android.widget.RemoteViews;
28b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penke
29b63ebad49dc0ff3456c787f9b689144f6e8860c7Chandra Penkeimport java.util.ArrayList;
308a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon
318a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon/**
328a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon * Response for a {@link
338a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon * AutofillService#onFillRequest(android.app.assist.AssistStructure,
348a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon * Bundle, android.os.CancellationSignal, FillCallback)}.
358a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon *
368a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon * <p>The response typically contains one or more {@link Dataset}s, each representing a set of
3738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * fields that can be autofilled together, and the Android system displays a dataset picker UI
3838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * affordance that the user must use before the {@link android.app.Activity} is filled with
3938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * the dataset.
408e1aae0fd69c2bf4eb0ff5ed7af44983d04de9dflakedaemon *
418e1aae0fd69c2bf4eb0ff5ed7af44983d04de9dflakedaemon * <p>For example, for a login page with username/password where the user only has one account in
4238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * the response could be:
4338597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
448a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon * <pre class="prettyprint">
458a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon *  new FillResponse.Builder()
464a8801da34b0edd03277b26b6fd280658c585ca6Lakedaemon *      .add(new Dataset.Builder(createPresentation())
4738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .setTextFieldValue(id1, "homer")
4838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .setTextFieldValue(id2, "D'OH!")
49cd1493b0829b48407887844921ef0e040c0f485alakedaemon *          .build())
5038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *      .build();
5138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * </pre>
5238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
5338597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * <p>If the user had 2 accounts, each with its own user-provided names, the response could be:
5438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
5538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * <pre class="prettyprint">
5638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *  new FillResponse.Builder()
5738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *      .add(new Dataset.Builder(createFirstPresentation())
5838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .setTextFieldValue(id1, "homer")
5938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .setTextFieldValue(id2, "D'OH!")
6038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .build())
6138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *      .add(new Dataset.Builder(createSecondPresentation())
6238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .setTextFieldValue(id1, "elbarto")
6338597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .setTextFieldValue(id2, "cowabonga")
6438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .build())
6538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *      .build();
6638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * </pre>
6738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
6838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * <p>If the user does not have any data associated with this {@link android.app.Activity} but
6938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * the service wants to offer the user the option to save the data that was entered, then the
7038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * service could populate the response with a {@link SaveInfo} instead of {@link Dataset}s:
7138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
7238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * <pre class="prettyprint">
7338597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *  new FillResponse.Builder()
7438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *      .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_CREDENTIALS)
7538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *                   .addSavableFields(id1, id2))
7638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *      .build();
7738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * </pre>
7838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
7938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * <p>Similarly, there might be cases where the user data on the service is enough to populate some
8038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * fields but not all, and the service would still be interested on saving the other fields. In this
8138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * scenario, the service could populate the response with both {@link Dataset}s and
8238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * {@link SaveInfo}:
8338597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
8420c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen * <pre class="prettyprint">
8538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *   new FillResponse.Builder()
8620c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen *       .add(new Dataset.Builder(createPresentation())
8726a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *          .setTextFieldValue(id1, "Homer")                  // first name
88a3a2bf890f9e02f3f0f5f28f2e07edb630419707lakedaemon *          .setTextFieldValue(id2, "Simpson")                // last name
8920c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen *          .setTextFieldValue(id3, "742 Evergreen Terrace")  // street
9038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .setTextFieldValue(id4, "Springfield")            // city
9138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .build())
92a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon *       .setSaveInfo(new SaveInfo.Builder(SaveInfo.SAVE_INFO_TYPE_ADDRESS)
93a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon *                   .addSavableFields(id5, id6)) // state and zipcode
9438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *       .build();
9538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
9615863c34a0733929069da177aab2861ddb719e80lakedaemon * </pre>
973101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *
983101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen * <p>Notice that the ids that are part of a dataset (ids 1 to 4, in this example) are automatically
993101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen * added to the {@code savableIds} list.
1003101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *
1013101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen * <p>If the service has multiple {@link Dataset}s for different sections of the activity,
10238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * for example, a user section for which there are two datasets followed by an address
103e597ad8f0f63bd0e5b9571e7c6c9d22d3e1acdc5Wouter van Oortmerssen * section for which there are two datasets for each user user, then it should "partition"
10420c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen * the activity in sections and populate the response with just a subset of the data that would
10538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * fulfill the first section (the name in our example); then once the user fills the first
10638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * section and taps a field from the next section (the address in our example), the Android
10738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * system would issue another request for that section, and so on. Note that if the user
10838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * chooses to populate the first section with a service provided dataset, the subsequent request
10938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * would contain the populated values so you don't try to provide suggestions for the first
11015863c34a0733929069da177aab2861ddb719e80lakedaemon * section but ony for the second one based on the context of what was already filled. For
111a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon * example, the first response could be:
11238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
11320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen * <pre class="prettyprint">
11426a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen *  new FillResponse.Builder()
11538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *      .add(new Dataset.Builder(createFirstPresentation())
116a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon *          .setTextFieldValue(id1, "Homer")
117a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon *          .setTextFieldValue(id2, "Simpson")
11838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .build())
11938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *      .add(new Dataset.Builder(createSecondPresentation())
12015863c34a0733929069da177aab2861ddb719e80lakedaemon *          .setTextFieldValue(id1, "Bart")
121a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon *          .setTextFieldValue(id2, "Simpson")
12238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *          .build())
12320c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen *      .build();
124a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon * </pre>
125a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon *
12638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * <p>Then after the user picks the second dataset and taps the street field to
12738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * trigger another autofill request, the second response could be:
12815863c34a0733929069da177aab2861ddb719e80lakedaemon *
129a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon * <pre class="prettyprint">
13038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *  new FillResponse.Builder()
13130642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssen *      .add(new Dataset.Builder(createThirdPresentation())
1323101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *          .setTextFieldValue(id3, "742 Evergreen Terrace")
1333101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *          .setTextFieldValue(id4, "Springfield")
1343101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *          .build())
1353101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *      .add(new Dataset.Builder(createFourthPresentation())
1363101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *          .setTextFieldValue(id3, "Springfield Power Plant")
1373101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *          .setTextFieldValue(id4, "Springfield")
1383101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *          .build())
1393101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen *      .build();
14030642c5a6f0fe2728d5b05cd272880d325c18cf6Wouter van Oortmerssen * </pre>
14138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon *
14238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * <p>The service could require user authentication at the {@link FillResponse} or the
14338597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * {@link Dataset} level, prior to autofilling an activity - see
14438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * {@link FillResponse.Builder#setAuthentication(IntentSender, RemoteViews)} and
14538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * {@link Dataset.Builder#setAuthentication(IntentSender)}.
14615863c34a0733929069da177aab2861ddb719e80lakedaemon *
1473101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen * <p>It is recommended that you encrypt only the sensitive data but leave the labels unencrypted
14838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * which would allow you to provide a dataset presentation views with labels and if the user
14920c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen * chooses one of them challenge the user to authenticate. For example, if the user has a
150249f71a12bb950eefa9768d461db9bf084432d55Brett Cooley * home and a work address the Home and Work labels could be stored unencrypted as they don't
15138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * have any sensitive data while the address data is in an encrypted storage. If the user
15238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * chooses Home, then the platform will start your authentication flow. If you encrypt all
15315863c34a0733929069da177aab2861ddb719e80lakedaemon * data and require auth at the response level the user will have to interact with the fill
15438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * UI to trigger a request for the datasets (as they don't see the presentation views for the
15538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * possible options) which will start your auth flow and after successfully authenticating
15638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * the user will be presented with the Home and Work options to pick one. Hence, you have
15738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon * flexibility how to implement your auth while storing labels non-encrypted and data
158354fd906a54d5a241785b57286d4aa58a2c91e86Lars Magnusson * encrypted provides a better user experience.</p>
15938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon */
16038597160f2b79a9620d70c43754248c41a5fdfebLakedaemonpublic final class FillResponse implements Parcelable {
161352b743c710367e496113ab1d8d76984f181a3ebWouter van Oortmerssen
16238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    private final ArrayList<Dataset> mDatasets;
16338597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    private final SaveInfo mSaveInfo;
16438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    private final Bundle mExtras;
16538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    private final RemoteViews mPresentation;
16638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    private final IntentSender mAuthentication;
16738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon
16838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    private FillResponse(@NonNull Builder builder) {
16938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        mDatasets = builder.mDatasets;
17037e6efe1f97b0788bd457d61e52ed40e12d2e69aWouter van Oortmerssen
17138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        mSaveInfo = builder.mSaveInfo;
17238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        if (mSaveInfo != null) {
17338597160f2b79a9620d70c43754248c41a5fdfebLakedaemon            mSaveInfo.addSavableIds(mDatasets);
17438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon            if (mSaveInfo.getSavableIds() == null) {
17538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon                throw new IllegalArgumentException(
17638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon                        "need to provide at least one savable id on SaveInfo");
17738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon            }
17838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        }
17938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon
18038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        mExtras = builder.mExtras;
18138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        mPresentation = builder.mPresentation;
18238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        mAuthentication = builder.mAuthentication;
18359043114ac2931e4b77c3c5b2c2022cda809c6d4Wouter van Oortmerssen    }
1843a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra
1853a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra    /** @hide */
1863a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra    public @Nullable Bundle getExtras() {
1873a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra        return mExtras;
1883a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra    }
1893a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra
1903a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra    /** @hide */
1913a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra    public @Nullable ArrayList<Dataset> getDatasets() {
1923a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra        return mDatasets;
1933a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra    }
1943a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra
1953a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra    /** @hide */
1963a1f776132cf9377e3a85a888e6ff2bc12c7248cBogDan Vatra    public @Nullable SaveInfo getSaveInfo() {
19738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        return mSaveInfo;
19838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    }
19938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon
20038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    /** @hide */
20138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    public @Nullable RemoteViews getPresentation() {
20238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        return mPresentation;
20326a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen    }
20438597160f2b79a9620d70c43754248c41a5fdfebLakedaemon
20538597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    /** @hide */
20638597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    public @Nullable IntentSender getAuthentication() {
20738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        return mAuthentication;
20838597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    }
20938597160f2b79a9620d70c43754248c41a5fdfebLakedaemon
21038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon    /**
21138597160f2b79a9620d70c43754248c41a5fdfebLakedaemon     * Builder for {@link FillResponse} objects. You must to provide at least
21238597160f2b79a9620d70c43754248c41a5fdfebLakedaemon     * one dataset or set an authentication intent with a presentation view.
21359043114ac2931e4b77c3c5b2c2022cda809c6d4Wouter van Oortmerssen     */
214a3a2bf890f9e02f3f0f5f28f2e07edb630419707lakedaemon    public static final class Builder {
21515863c34a0733929069da177aab2861ddb719e80lakedaemon        private ArrayList<Dataset> mDatasets;
21620c0082ee5bfeeecaa443c001a89934e9448ffa4Wouter van Oortmerssen        private SaveInfo mSaveInfo;
21738597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        private Bundle mExtras;
218a3a2bf890f9e02f3f0f5f28f2e07edb630419707lakedaemon        private RemoteViews mPresentation;
21926a30738a4fa4e92300821fd761764ec8df2dcf2Wouter van Oortmerssen        private IntentSender mAuthentication;
22038597160f2b79a9620d70c43754248c41a5fdfebLakedaemon        private boolean mDestroyed;
2218a64afabfd3c3f7f4602efbc6dac3f3cd067dd1dLakedaemon
222a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        /**
223a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * Requires a fill response authentication before autofilling the activity with
224a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * any data set in this response.
225084e5dbc4b170a828add67e81601f3c2c80cc481lakedaemon         *
226a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * <p>This is typically useful when a user interaction is required to unlock their
227f794f97d883d1ce2702f086a8f88be693b834415lakedaemon         * data vault if you encrypt the data set labels and data set data. It is recommended
228a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * to encrypt only the sensitive data and not the data set labels which would allow
229a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * auth on the data set level leading to a better user experience. Note that if you
230a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * use sensitive data as a label, for example an email address, then it should also
231a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * be encrypted. The provided {@link android.app.PendingIntent intent} must be an
232a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * activity which implements your authentication flow. Also if you provide an auth
233a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * intent you also need to specify the presentation view to be shown in the fill UI
234a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * for the user to trigger your authentication flow.</p>
235a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         *
236a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * <p>When a user triggers autofill, the system launches the provided intent
237a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * whose extras will have the {@link AutofillManager#EXTRA_ASSIST_STRUCTURE screen
238a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * content}. Once you complete your authentication flow you should set the activity
239a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * result to {@link android.app.Activity#RESULT_OK} and provide the fully populated
240a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * {@link FillResponse response} by setting it to the {@link
241a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * AutofillManager#EXTRA_AUTHENTICATION_RESULT} extra.
242a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * For example, if you provided an empty {@link FillResponse resppnse} because the
243a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * user's data was locked and marked that the response needs an authentication then
2443101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * in the response returned if authentication succeeds you need to provide all
2453101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * available data sets some of which may need to be further authenticated, for
246a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * example a credit card whose CVV needs to be entered.</p>
2473101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         *
248a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * <p>If you provide an authentication intent you must also provide a presentation
249a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * which is used to visualize visualize the response for triggering the authentication
250a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * flow.</p>
251a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         *
252a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * <p></><strong>Note:</strong> Do not make the provided pending intent
253a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * immutable by using {@link android.app.PendingIntent#FLAG_IMMUTABLE} as the
254a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * platform needs to fill in the authentication arguments.</p>
255a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         *
256a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * @param authentication Intent to an activity with your authentication flow.
257a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * @param presentation The presentation to visualize the response.
258a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * @return This builder.
259a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         *
260a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * @see android.app.PendingIntent#getIntentSender()
261a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         */
262a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        public @NonNull Builder setAuthentication(@Nullable IntentSender authentication,
263a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                @Nullable RemoteViews presentation) {
264a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            throwIfDestroyed();
2653101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            if (authentication == null ^ presentation == null) {
266a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                throw new IllegalArgumentException("authentication and presentation"
267a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                        + " must be both non-null or null");
268a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            }
269a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            mAuthentication = authentication;
270a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            mPresentation = presentation;
271a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            return this;
272a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        }
273a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon
274a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        /**
275a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * Adds a new {@link Dataset} to this response.
276e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon         *
277e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon         * @return This builder.
278a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         */
279a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        public@NonNull Builder addDataset(@Nullable Dataset dataset) {
280e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon            throwIfDestroyed();
281e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon            if (dataset == null) {
282e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon                return this;
283a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            }
284a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            if (mDatasets == null) {
285a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                mDatasets = new ArrayList<>();
286a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            }
287a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            if (!mDatasets.add(dataset)) {
288e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon                return this;
289e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon            }
290e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon            return this;
291a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        }
292a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon
2933101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        /**
2943101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * Sets the {@link SaveInfo} associated with this response.
2953101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         *
2963101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * <p>See {@link FillResponse} for more info.
2973101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         *
2983101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * @return This builder.
2993101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         */
3003101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        public @NonNull Builder setSaveInfo(@NonNull SaveInfo saveInfo) {
3013101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            throwIfDestroyed();
3023101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            mSaveInfo = saveInfo;
3033101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            return this;
3043101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        }
3053101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen
3063101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        /**
3073101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * Sets a {@link Bundle} that will be passed to subsequent APIs that
3083101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * manipulate this response. For example, they are passed to subsequent
3093101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * calls to {@link AutofillService#onFillRequest(
3103101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * android.app.assist.AssistStructure, Bundle, android.os.CancellationSignal,
3113101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * FillCallback)} and {@link AutofillService#onSaveRequest(
3123101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * android.app.assist.AssistStructure, Bundle, SaveCallback)}.
3133101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         *
3143101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * @param extras The response extras.
3153101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         * @return This builder.
3163101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen         */
3173101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        public Builder setExtras(Bundle extras) {
3183101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            throwIfDestroyed();
3193101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            mExtras = extras;
3203101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            return this;
321a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        }
322a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon
323e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon        /**
324e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon         * Builds a new {@link FillResponse} instance. You must provide at least
325e750268f0cb3386ab8c6324cf18de4f8d95e6bf3lakedaemon         * one dataset or some savable ids or an authentication with a presentation
326a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * view.
327a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         *
328a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         * @return A built response.
329a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon         */
330a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        public FillResponse build() {
331a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            throwIfDestroyed();
332a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon
333a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            if (mAuthentication == null && mDatasets == null && mSaveInfo == null) {
334a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                throw new IllegalArgumentException("need to provide at least one DataSet or a "
335a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                        + "SaveInfo or an authentication with a presentation");
336b04e21db16fbf732d6b48359ba1a444c1eed0a74Wouter van Oortmerssen            }
337b04e21db16fbf732d6b48359ba1a444c1eed0a74Wouter van Oortmerssen            mDestroyed = true;
338b04e21db16fbf732d6b48359ba1a444c1eed0a74Wouter van Oortmerssen            return new FillResponse(this);
339a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        }
340a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon
341a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        private void throwIfDestroyed() {
342b04e21db16fbf732d6b48359ba1a444c1eed0a74Wouter van Oortmerssen            if (mDestroyed) {
343b04e21db16fbf732d6b48359ba1a444c1eed0a74Wouter van Oortmerssen                throw new IllegalStateException("Already called #build()");
344b04e21db16fbf732d6b48359ba1a444c1eed0a74Wouter van Oortmerssen            }
345a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        }
346a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon    }
347a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon
348a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon    /////////////////////////////////////
349a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon    //  Object "contract" methods. //
350a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon    /////////////////////////////////////
351a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon    @Override
352a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon    public String toString() {
353a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        if (!DEBUG) return super.toString();
3543101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen
355a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        return new StringBuilder(
3563101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen                "FillResponse: [datasets=").append(mDatasets)
357a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                .append(", saveInfo=").append(mSaveInfo)
358a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                .append(", hasExtras=").append(mExtras != null)
359a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                .append(", hasPresentation=").append(mPresentation != null)
3603101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen                .append(", hasAuthentication=").append(mAuthentication != null)
3613101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen                .toString();
3623101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen    }
3633101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen
364dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen    /////////////////////////////////////
365dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen    //  Parcelable "contract" methods. //
3663101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen    /////////////////////////////////////
3673101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen
3683101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen    @Override
3693101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen    public int describeContents() {
3703101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        return 0;
371dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen    }
372dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen
373dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen    @Override
3743101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen    public void writeToParcel(Parcel parcel, int flags) {
3753101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        parcel.writeTypedArrayList(mDatasets, flags);
376dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen        parcel.writeParcelable(mSaveInfo, flags);
3773101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        parcel.writeParcelable(mExtras, flags);
3783101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        parcel.writeParcelable(mAuthentication, flags);
3793101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        parcel.writeParcelable(mPresentation, flags);
380dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen    }
381dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen
382dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen    public static final Parcelable.Creator<FillResponse> CREATOR =
3833101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            new Parcelable.Creator<FillResponse>() {
3843101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        @Override
3853101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen        public FillResponse createFromParcel(Parcel parcel) {
3863101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            // Always go through the builder to ensure the data ingested by
387dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen            // the system obeys the contract of the builder to avoid attacks
388dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen            // using specially crafted parcels.
389dc2fa215b854b31aa9a7f8c959ce08297ec79e23Wouter van Oortmerssen            final Builder builder = new Builder();
3903101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            final ArrayList<Dataset> datasets = parcel.readTypedArrayList(null);
3913101e327c04f14f9345f60fd184aa3034e2faadfWouter van Oortmerssen            final int datasetCount = (datasets != null) ? datasets.size() : 0;
392a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            for (int i = 0; i < datasetCount; i++) {
393a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                builder.addDataset(datasets.get(i));
394a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            }
395a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            builder.setSaveInfo(parcel.readParcelable(null));
396a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            builder.setExtras(parcel.readParcelable(null));
397a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            builder.setAuthentication(parcel.readParcelable(null),
398a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon                    parcel.readParcelable(null));
399a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            return builder.build();
400a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        }
401a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon
402a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        @Override
403a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        public FillResponse[] newArray(int size) {
404a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon            return new FillResponse[size];
405a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon        }
406b04e21db16fbf732d6b48359ba1a444c1eed0a74Wouter van Oortmerssen    };
407a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon}
408a9194c4c686ace7455b1ae5b146544d788feaafdlakedaemon