/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.example.android.inlinefillservice; import android.app.PendingIntent; import android.app.slice.Slice; import android.content.Context; import android.content.Intent; import android.graphics.drawable.Icon; import android.service.autofill.Dataset; import android.service.autofill.FillRequest; import android.service.autofill.InlinePresentation; import android.text.TextUtils; import android.util.ArrayMap; import android.view.autofill.AutofillId; import android.view.inputmethod.InlineSuggestionsRequest; import android.widget.inline.InlinePresentationSpec; import androidx.autofill.inline.v1.InlineSuggestionUi; import androidx.autofill.inline.v1.InlineSuggestionUi.Content; import java.util.Optional; public class InlineRequestHelper { static Optional getInlineSuggestionsRequest(FillRequest request) { final InlineSuggestionsRequest inlineRequest = request.getInlineSuggestionsRequest(); if (inlineRequest != null && inlineRequest.getMaxSuggestionCount() > 0 && !inlineRequest.getInlinePresentationSpecs().isEmpty()) { return Optional.of(inlineRequest); } return Optional.empty(); } static int getMaxSuggestionCount(Optional inlineRequest, int max) { if (inlineRequest.isPresent()) { return Math.min(max, inlineRequest.get().getMaxSuggestionCount()); } return max; } static InlinePresentation maybeCreateInlineAuthenticationResponse( Context context, Optional inlineRequest) { if (!inlineRequest.isPresent()) { return null; } final PendingIntent attribution = createAttribution(context, "Please tap on the chip to authenticate the Autofill response."); final Slice slice = createSlice("Tap to auth response", null, null, null, attribution); final InlinePresentationSpec spec = inlineRequest.get().getInlinePresentationSpecs().get(0); return new InlinePresentation(slice, spec, false); } static InlinePresentation createInlineDataset(Context context, InlineSuggestionsRequest inlineRequest, String value, int index) { final PendingIntent attribution = createAttribution(context, "Please tap on the chip to autofill the value:" + value); final Slice slice = createSlice(value, null, null, null, attribution); index = Math.min(inlineRequest.getInlinePresentationSpecs().size() - 1, index); final InlinePresentationSpec spec = inlineRequest.getInlinePresentationSpecs().get(index); return new InlinePresentation(slice, spec, false); } static Dataset createInlineActionDataset(Context context, ArrayMap fields, InlineSuggestionsRequest inlineRequest, int drawable) { PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(context, SettingsActivity.class), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); Dataset.Builder builder = new Dataset.Builder() .setInlinePresentation(createInlineAction(context, inlineRequest, drawable)) .setAuthentication(pendingIntent.getIntentSender()); for (AutofillId fieldId : fields.values()) { builder.setValue(fieldId, null); } return builder.build(); } private static InlinePresentation createInlineAction(Context context, InlineSuggestionsRequest inlineRequest, int drawable) { final PendingIntent attribution = createAttribution(context, "Please tap on the chip to launch the action."); final Icon icon = Icon.createWithResource(context, drawable); final Slice slice = createSlice(null, null, icon, null, attribution); // Reuse the first spec's height for the inline action size, as there isn't dedicated // value from the request for this. final InlinePresentationSpec spec = inlineRequest.getInlinePresentationSpecs().get(0); return new InlinePresentation(slice, spec, true); } private static Slice createSlice( String title, String subtitle, Icon startIcon, Icon endIcon, PendingIntent attribution) { Content.Builder builder = InlineSuggestionUi.newContentBuilder(attribution); if (!TextUtils.isEmpty(title)) { builder.setTitle(title); } if (!TextUtils.isEmpty(subtitle)) { builder.setSubtitle(subtitle); } if (startIcon != null) { builder.setStartIcon(startIcon); } if (endIcon != null) { builder.setEndIcon(endIcon); } return builder.build().getSlice(); } private static PendingIntent createAttribution(Context context, String msg) { Intent intent = new Intent(context, AttributionDialogActivity.class); intent.putExtra(AttributionDialogActivity.KEY_MSG, msg); // Should use different request code to avoid the new intent overriding the old one. PendingIntent pendingIntent = PendingIntent.getActivity(context, msg.hashCode(), intent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE); return pendingIntent; } }