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