1 /*
2  * Copyright (C) 2020 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 com.example.android.inlinefillservice;
18 
19 import static com.example.android.inlinefillservice.InlineFillService.TAG;
20 
21 import android.content.Context;
22 import android.content.IntentSender;
23 import android.service.autofill.Dataset;
24 import android.service.autofill.Field;
25 import android.service.autofill.InlinePresentation;
26 import android.service.autofill.Presentations;
27 import android.util.Log;
28 import android.view.autofill.AutofillId;
29 import android.view.autofill.AutofillValue;
30 import android.view.inputmethod.InlineSuggestionsRequest;
31 import android.widget.RemoteViews;
32 
33 import androidx.annotation.NonNull;
34 
35 import java.util.Map;
36 import java.util.Optional;
37 
38 class ResponseHelper {
39 
newUnlockedDataset(@onNull Context context, @NonNull Map<String, AutofillId> fields, @NonNull String packageName, int index, @NonNull Optional<InlineSuggestionsRequest> inlineRequest)40     static Dataset newUnlockedDataset(@NonNull Context context,
41             @NonNull Map<String, AutofillId> fields, @NonNull String packageName, int index,
42             @NonNull Optional<InlineSuggestionsRequest> inlineRequest) {
43 
44         Dataset.Builder dataset = new Dataset.Builder();
45         for (Map.Entry<String, AutofillId> field : fields.entrySet()) {
46             final String hint = field.getKey();
47             final AutofillId id = field.getValue();
48             final String value = hint + (index + 1);
49 
50             // We're simple - our dataset values are hardcoded as "hintN" (for example,
51             // "username1", "username2") and they're displayed as such, except if they're a
52             // password
53             Log.d(TAG, "hint: " + hint);
54             final String displayValue = hint.contains("password") ? "password for #" + (index + 1)
55                     : value;
56             // Add Inline Suggestion required info.
57             Field.Builder fieldBuilder = new Field.Builder();
58             fieldBuilder.setValue(AutofillValue.forText(value));
59             // Set presentation
60             final Presentations.Builder fieldPresentationsBuilder =
61                 new Presentations.Builder();
62             // Dropdown presentation
63             final RemoteViews presentation = newDatasetPresentation(packageName, displayValue);
64             fieldPresentationsBuilder.setMenuPresentation(presentation);
65             // Inline presentation
66             if (inlineRequest.isPresent()) {
67                 Log.d(TAG, "Found InlineSuggestionsRequest in FillRequest: " + inlineRequest);
68                 final InlinePresentation inlinePresentation =
69                     InlineRequestHelper.createInlineDataset(context, inlineRequest.get(),
70                         displayValue, index);
71                 fieldPresentationsBuilder.setInlinePresentation(inlinePresentation);
72             }
73             // Dialog presentation
74             RemoteViews dialogPresentation =
75                 newDatasetPresentation(packageName, "Dialog Presentation " + (index + 1));
76             fieldPresentationsBuilder.setDialogPresentation(dialogPresentation);
77 
78             fieldBuilder.setPresentations(fieldPresentationsBuilder.build());
79             dataset.setField(id, fieldBuilder.build());
80         }
81         return dataset.build();
82     }
83 
newLockedDataset(@onNull Context context, @NonNull Map<String, AutofillId> fields, @NonNull String packageName, int index, @NonNull Optional<InlineSuggestionsRequest> inlineRequest)84     static Dataset newLockedDataset(@NonNull Context context,
85             @NonNull Map<String, AutofillId> fields, @NonNull String packageName, int index,
86             @NonNull Optional<InlineSuggestionsRequest> inlineRequest) {
87         Dataset unlockedDataset = ResponseHelper.newUnlockedDataset(context, fields,
88                 packageName, index, inlineRequest);
89 
90         Dataset.Builder lockedDataset = new Dataset.Builder();
91         for (Map.Entry<String, AutofillId> field : fields.entrySet()) {
92             String hint = field.getKey();
93             AutofillId id = field.getValue();
94             String value = (index + 1) + "-" + hint;
95             String displayValue = "Tap to auth " + value;
96             IntentSender authentication =
97                     AuthActivity.newIntentSenderForDataset(context, unlockedDataset);
98             RemoteViews presentation = newDatasetPresentation(packageName, displayValue);
99 
100             Field.Builder fieldBuilder = new Field.Builder();
101             fieldBuilder.setValue(AutofillValue.forText(value));
102             // Dropdown presentation
103             final Presentations.Builder fieldPresentationsBuilder =
104                 new Presentations.Builder();
105             fieldPresentationsBuilder.setMenuPresentation(presentation);
106             // Inline presentation
107             if (inlineRequest.isPresent()) {
108                 final InlinePresentation inlinePresentation =
109                         InlineRequestHelper.createInlineDataset(context, inlineRequest.get(),
110                         displayValue, index);
111                 fieldPresentationsBuilder.setInlinePresentation(inlinePresentation);
112             }
113             // Dialog presentation
114             RemoteViews dialogPresentation =
115                 newDatasetPresentation(packageName, "Dialog Presentation " + (index + 1));
116             fieldPresentationsBuilder.setDialogPresentation(dialogPresentation);
117 
118             fieldBuilder.setPresentations(fieldPresentationsBuilder.build());
119             lockedDataset.setField(id, fieldBuilder.build());
120             lockedDataset.setId(null).setAuthentication(authentication);
121         }
122         return lockedDataset.build();
123     }
124 
125     /**
126      * Helper method to create a dataset presentation with the givean text.
127      */
128     @NonNull
newDatasetPresentation(@onNull String packageName, @NonNull CharSequence text)129     static RemoteViews newDatasetPresentation(@NonNull String packageName,
130             @NonNull CharSequence text) {
131         RemoteViews presentation =
132                 new RemoteViews(packageName, R.layout.list_item);
133         presentation.setTextViewText(R.id.text, text);
134         return presentation;
135     }
136 }
137