Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 950e55d4 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add server side implementation for inline augmented autofill request."

parents de12cc1a 5bf0d2bc
Loading
Loading
Loading
Loading
+16 −5
Original line number Original line Diff line number Diff line
@@ -38,6 +38,7 @@ import android.os.ICancellationSignal;
import android.os.Looper;
import android.os.Looper;
import android.os.RemoteException;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemClock;
import android.service.autofill.Dataset;
import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
import android.service.autofill.augmented.PresentationParams.SystemPopupPresentationParams;
import android.util.Log;
import android.util.Log;
import android.util.Pair;
import android.util.Pair;
@@ -47,6 +48,7 @@ import android.view.autofill.AutofillManager;
import android.view.autofill.AutofillValue;
import android.view.autofill.AutofillValue;
import android.view.autofill.IAugmentedAutofillManagerClient;
import android.view.autofill.IAugmentedAutofillManagerClient;
import android.view.autofill.IAutofillWindowPresenter;
import android.view.autofill.IAutofillWindowPresenter;
import android.view.inputmethod.InlineSuggestionsRequest;


import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -106,10 +108,11 @@ public abstract class AugmentedAutofillService extends Service {
        @Override
        @Override
        public void onFillRequest(int sessionId, IBinder client, int taskId,
        public void onFillRequest(int sessionId, IBinder client, int taskId,
                ComponentName componentName, AutofillId focusedId, AutofillValue focusedValue,
                ComponentName componentName, AutofillId focusedId, AutofillValue focusedValue,
                long requestTime, IFillCallback callback) {
                long requestTime, @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
                IFillCallback callback) {
            mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnFillRequest,
            mHandler.sendMessage(obtainMessage(AugmentedAutofillService::handleOnFillRequest,
                    AugmentedAutofillService.this, sessionId, client, taskId, componentName,
                    AugmentedAutofillService.this, sessionId, client, taskId, componentName,
                    focusedId, focusedValue, requestTime, callback));
                    focusedId, focusedValue, requestTime, inlineSuggestionsRequest, callback));
        }
        }


        @Override
        @Override
@@ -212,6 +215,7 @@ public abstract class AugmentedAutofillService extends Service {
    private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
    private void handleOnFillRequest(int sessionId, @NonNull IBinder client, int taskId,
            @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
            @NonNull ComponentName componentName, @NonNull AutofillId focusedId,
            @Nullable AutofillValue focusedValue, long requestTime,
            @Nullable AutofillValue focusedValue, long requestTime,
            @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
            @NonNull IFillCallback callback) {
            @NonNull IFillCallback callback) {
        if (mAutofillProxies == null) {
        if (mAutofillProxies == null) {
            mAutofillProxies = new SparseArray<>();
            mAutofillProxies = new SparseArray<>();
@@ -236,9 +240,8 @@ public abstract class AugmentedAutofillService extends Service {
        } catch (RemoteException e) {
        } catch (RemoteException e) {
            e.rethrowFromSystemServer();
            e.rethrowFromSystemServer();
        }
        }
        // TODO(b/146453195): pass the inline suggestion request over.
        onFillRequest(new FillRequest(proxy, inlineSuggestionsRequest), cancellationSignal,
        onFillRequest(new FillRequest(proxy, /* inlineSuggestionsRequest= */null),
                new FillController(proxy), new FillCallback(proxy));
                cancellationSignal, new FillController(proxy), new FillCallback(proxy));
    }
    }


    private void handleOnDestroyAllFillWindowsRequest() {
    private void handleOnDestroyAllFillWindowsRequest() {
@@ -484,6 +487,14 @@ public abstract class AugmentedAutofillService extends Service {
            }
            }
        }
        }


        public void onInlineSuggestionsDataReady(@NonNull List<Dataset> inlineSuggestionsData) {
            try {
                mCallback.onSuccess(inlineSuggestionsData.toArray(new Dataset[]{}));
            } catch (RemoteException e) {
                Log.e(TAG, "Error calling back with the inline suggestions data: " + e);
            }
        }

        // Used (mostly) for metrics.
        // Used (mostly) for metrics.
        public void report(@ReportEvent int event) {
        public void report(@ReportEvent int event) {
            if (sVerbose) Log.v(TAG, "report(): " + event);
            if (sVerbose) Log.v(TAG, "report(): " + event);
+10 −1
Original line number Original line Diff line number Diff line
@@ -21,9 +21,12 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.TestApi;
import android.service.autofill.Dataset;
import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.service.autofill.augmented.AugmentedAutofillService.AutofillProxy;
import android.util.Log;
import android.util.Log;


import java.util.List;

/**
/**
 * Callback used to indicate at {@link FillRequest} has been fulfilled.
 * Callback used to indicate at {@link FillRequest} has been fulfilled.
 *
 *
@@ -55,6 +58,12 @@ public final class FillCallback {
            return;
            return;
        }
        }


        List<Dataset> inlineSuggestions = response.getInlineSuggestions();
        if (inlineSuggestions != null && !inlineSuggestions.isEmpty()) {
            mProxy.onInlineSuggestionsDataReady(inlineSuggestions);
            return;
        }

        final FillWindow fillWindow = response.getFillWindow();
        final FillWindow fillWindow = response.getFillWindow();
        if (fillWindow != null) {
        if (fillWindow != null) {
            fillWindow.show();
            fillWindow.show();
+4 −1
Original line number Original line Diff line number Diff line
@@ -22,6 +22,7 @@ import android.os.IBinder;
import android.service.autofill.augmented.IFillCallback;
import android.service.autofill.augmented.IFillCallback;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import android.view.autofill.AutofillValue;
import android.view.inputmethod.InlineSuggestionsRequest;


import java.util.List;
import java.util.List;


@@ -35,7 +36,9 @@ oneway interface IAugmentedAutofillService {
    void onDisconnected();
    void onDisconnected();
    void onFillRequest(int sessionId, in IBinder autofillManagerClient, int taskId,
    void onFillRequest(int sessionId, in IBinder autofillManagerClient, int taskId,
                       in ComponentName activityComponent, in AutofillId focusedId,
                       in ComponentName activityComponent, in AutofillId focusedId,
                       in AutofillValue focusedValue, long requestTime, in IFillCallback callback);
                       in AutofillValue focusedValue, long requestTime,
                       in InlineSuggestionsRequest inlineSuggestionsRequest,
                       in IFillCallback callback);


    void onDestroyAllFillWindowsRequest();
    void onDestroyAllFillWindowsRequest();
}
}
+1 −1
Original line number Original line Diff line number Diff line
@@ -223,7 +223,7 @@ public interface ServiceConnector<I extends IInterface> {
        private final @NonNull ServiceConnection mServiceConnection = this;
        private final @NonNull ServiceConnection mServiceConnection = this;
        private final @NonNull Runnable mTimeoutDisconnect = this;
        private final @NonNull Runnable mTimeoutDisconnect = this;


        private final @NonNull Context mContext;
        protected final @NonNull Context mContext;
        private final @NonNull Intent mIntent;
        private final @NonNull Intent mIntent;
        private final int mBindingFlags;
        private final int mBindingFlags;
        private final int mUserId;
        private final int mUserId;
+135 −0
Original line number Original line Diff line number Diff line
/*
 * 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.android.server.autofill;

import static com.android.server.autofill.Helper.sDebug;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.os.Handler;
import android.os.RemoteException;
import android.service.autofill.Dataset;
import android.util.Slog;
import android.view.SurfaceControl;
import android.view.View;
import android.view.autofill.AutofillId;
import android.view.autofill.IAutoFillManagerClient;
import android.view.inline.InlinePresentationSpec;
import android.view.inputmethod.InlineSuggestion;
import android.view.inputmethod.InlineSuggestionInfo;
import android.view.inputmethod.InlineSuggestionsRequest;
import android.view.inputmethod.InlineSuggestionsResponse;

import com.android.internal.view.inline.IInlineContentCallback;
import com.android.internal.view.inline.IInlineContentProvider;
import com.android.server.autofill.ui.InlineSuggestionUi;

import java.util.ArrayList;


/**
 * @hide
 */
public final class InlineSuggestionFactory {
    private static final String TAG = "InlineSuggestionFactory";

    /**
     * Creates an {@link InlineSuggestionsResponse} with the {@code datasets} provided by
     * augmented autofill service.
     */
    public static InlineSuggestionsResponse createAugmentedInlineSuggestionsResponse(
            int sessionId,
            @NonNull Dataset[] datasets,
            @NonNull AutofillId autofillId,
            @NonNull InlineSuggestionsRequest request,
            @NonNull Handler uiHandler,
            @NonNull Context context,
            @NonNull IAutoFillManagerClient client) {
        if (sDebug) Slog.d(TAG, "createInlineSuggestionsResponse called");

        final ArrayList<InlineSuggestion> inlineSuggestions = new ArrayList<>();
        final InlineSuggestionUi inlineSuggestionUi = new InlineSuggestionUi(context);
        for (Dataset dataset : datasets) {
            // TODO(b/146453195): use the spec in the dataset.
            InlinePresentationSpec spec = request.getPresentationSpecs().get(0);
            if (spec == null) {
                Slog.w(TAG, "InlinePresentationSpec is not provided in the response data set");
                continue;
            }
            InlineSuggestion inlineSuggestion = createAugmentedInlineSuggestion(sessionId, dataset,
                    autofillId, spec, uiHandler, inlineSuggestionUi, client);
            inlineSuggestions.add(inlineSuggestion);
        }
        return new InlineSuggestionsResponse(inlineSuggestions);
    }

    private static InlineSuggestion createAugmentedInlineSuggestion(int sessionId,
            @NonNull Dataset dataset,
            @NonNull AutofillId autofillId,
            @NonNull InlinePresentationSpec spec,
            @NonNull Handler uiHandler,
            @NonNull InlineSuggestionUi inlineSuggestionUi,
            @NonNull IAutoFillManagerClient client) {
        // TODO(b/146453195): fill in the autofill hint properly.
        final InlineSuggestionInfo inlineSuggestionInfo = new InlineSuggestionInfo(
                spec, InlineSuggestionInfo.SOURCE_PLATFORM, new String[]{""});
        final View.OnClickListener onClickListener = createOnClickListener(sessionId, dataset,
                client);
        final InlineSuggestion inlineSuggestion = new InlineSuggestion(inlineSuggestionInfo,
                createInlineContentProvider(autofillId, dataset, uiHandler, inlineSuggestionUi,
                        onClickListener));
        return inlineSuggestion;
    }

    private static IInlineContentProvider.Stub createInlineContentProvider(
            @NonNull AutofillId autofillId, @NonNull Dataset dataset, @NonNull Handler uiHandler,
            @NonNull InlineSuggestionUi inlineSuggestionUi,
            @Nullable View.OnClickListener onClickListener) {
        return new IInlineContentProvider.Stub() {
            @Override
            public void provideContent(int width, int height,
                    IInlineContentCallback callback) {
                uiHandler.post(() -> {
                    SurfaceControl sc = inlineSuggestionUi.inflate(dataset, autofillId,
                            width, height, onClickListener);
                    try {
                        callback.onContent(sc);
                    } catch (RemoteException e) {
                        Slog.w(TAG, "Encounter exception calling back with inline content.");
                    }
                });
            }
        };
    }

    private static View.OnClickListener createOnClickListener(int sessionId,
            @NonNull Dataset dataset,
            @NonNull IAutoFillManagerClient client) {
        return v -> {
            if (sDebug) Slog.d(TAG, "Inline suggestion clicked");
            try {
                client.autofill(sessionId, dataset.getFieldIds(), dataset.getFieldValues());
            } catch (RemoteException e) {
                Slog.w(TAG, "Encounter exception autofilling the values");
            }
        };
    }

    private InlineSuggestionFactory() {
    }
}
Loading