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

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

Merge "Fixed Augmented Autofill workflow so the UI is closed when another field is focused."

parents 7e9af61c 481db7cc
Loading
Loading
Loading
Loading
+0 −1
Original line number Original line Diff line number Diff line
@@ -405,7 +405,6 @@ public abstract class AugmentedAutofillService extends Service {
        private void update(@NonNull AutofillId focusedId, @NonNull AutofillValue focusedValue,
        private void update(@NonNull AutofillId focusedId, @NonNull AutofillValue focusedValue,
                @NonNull IFillCallback callback) {
                @NonNull IFillCallback callback) {
            synchronized (mLock) {
            synchronized (mLock) {
                // TODO(b/123099468): should we close the popupwindow if the focused id changed?
                mFocusedId = focusedId;
                mFocusedId = focusedId;
                mFocusedValue = focusedValue;
                mFocusedValue = focusedValue;
                if (mCallback != null) {
                if (mCallback != null) {
+1 −4
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.service.autofill.FillRequest.FLAG_AUGMENTED_AUTOFILL_REQUE
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.view.autofill.Helper.sDebug;
import static android.view.autofill.Helper.sDebug;
import static android.view.autofill.Helper.sVerbose;
import static android.view.autofill.Helper.sVerbose;
import static android.view.autofill.Helper.toList;


import android.accessibilityservice.AccessibilityServiceInfo;
import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.IntDef;
import android.annotation.IntDef;
@@ -1872,10 +1873,6 @@ public final class AutofillManager {
        }
        }
    }
    }


    private <T> ArrayList<T> toList(@Nullable Set<T> set) {
        return set == null ? null : new ArrayList<T>(set);
    }

    /**
    /**
     * Notifies that a non-autofillable view was entered because the activity is whitelisted for
     * Notifies that a non-autofillable view was entered because the activity is whitelisted for
     * augmented autofill.
     * augmented autofill.
+12 −1
Original line number Original line Diff line number Diff line
@@ -19,7 +19,9 @@ package android.view.autofill;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;


import java.util.ArrayList;
import java.util.Collection;
import java.util.Collection;
import java.util.Set;


/** @hide */
/** @hide */
public final class Helper {
public final class Helper {
@@ -62,7 +64,8 @@ public final class Helper {
    }
    }


    /**
    /**
     * Convers a collaction of {@link AutofillId AutofillIds} to an array.
     * Converts a collaction of {@link AutofillId AutofillIds} to an array.
     *
     * @param collection The collection.
     * @param collection The collection.
     * @return The array.
     * @return The array.
     */
     */
@@ -75,6 +78,14 @@ public final class Helper {
        return array;
        return array;
    }
    }


    /**
     * Converts a Set to a List.
     */
    @Nullable
    public static <T> ArrayList<T> toList(@Nullable Set<T> set) {
        return set == null ? null : new ArrayList<T>(set);
    }

    private Helper() {
    private Helper() {
        throw new UnsupportedOperationException("contains static members only");
        throw new UnsupportedOperationException("contains static members only");
    }
    }
+3 −3
Original line number Original line Diff line number Diff line
@@ -211,8 +211,8 @@ public final class Helper {
     * Gets the {@link AutofillId} of the autofillable nodes in the {@code structure}.
     * Gets the {@link AutofillId} of the autofillable nodes in the {@code structure}.
     */
     */
    @NonNull
    @NonNull
    static ArrayList<AutofillId> getAutofillableIds(@NonNull AssistStructure structure) {
    static ArraySet<AutofillId> getAutofillableIds(@NonNull AssistStructure structure) {
        final ArrayList<AutofillId> ids = new ArrayList<>();
        final ArraySet<AutofillId> ids = new ArraySet<>();
        final int size = structure.getWindowNodeCount();
        final int size = structure.getWindowNodeCount();
        for (int i = 0; i < size; i++) {
        for (int i = 0; i < size; i++) {
            final WindowNode node = structure.getWindowNodeAt(i);
            final WindowNode node = structure.getWindowNodeAt(i);
@@ -222,7 +222,7 @@ public final class Helper {
    }
    }


    private static void addAutofillableIds(@NonNull ViewNode node,
    private static void addAutofillableIds(@NonNull ViewNode node,
            @NonNull ArrayList<AutofillId> ids) {
            @NonNull ArraySet<AutofillId> ids) {
        if (node.getAutofillType() != View.AUTOFILL_TYPE_NONE) {
        if (node.getAutofillType() != View.AUTOFILL_TYPE_NONE) {
            ids.add(node.getAutofillId());
            ids.add(node.getAutofillId());
        }
        }
+60 −10
Original line number Original line Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.view.autofill.AutofillManager.ACTION_VIEW_ENTERED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
import static android.view.autofill.AutofillManager.ACTION_VIEW_EXITED;
import static android.view.autofill.AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM;
import static android.view.autofill.AutofillManager.FLAG_SMART_SUGGESTION_SYSTEM;
import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
import static android.view.autofill.AutofillManager.getSmartSuggestionModeToString;
import static android.view.autofill.Helper.toList;


import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
import static com.android.server.autofill.Helper.getNumericValue;
import static com.android.server.autofill.Helper.getNumericValue;
@@ -266,6 +267,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private ArrayList<LogMaker> mAugmentedRequestsLogs;
    private ArrayList<LogMaker> mAugmentedRequestsLogs;



    /**
     * List of autofill ids of autofillable fields present in the AssistStructure that can be used
     * to trigger new augmented autofill requests (because the "standard" service was not interested
     * on autofilling the app.
     */
    @GuardedBy("mLock")
    private ArraySet<AutofillId> mAugmentedAutofillableIds;

    /**
    /**
     * Receiver of assist data from the app's {@link Activity}.
     * Receiver of assist data from the app's {@link Activity}.
     */
     */
@@ -2327,12 +2337,28 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                    return;
                    return;
                }
                }


                if (mAugmentedAutofillableIds != null && mAugmentedAutofillableIds.contains(id)) {
                    // View was already reported when server could not handle a response, but it
                    // triggered augmented autofill

                    if (sDebug) Slog.d(TAG, "updateLocked(" + id + "): augmented-autofillable");

                    // Update the view states first...
                    mCurrentViewId = viewState.id;
                    viewState.setCurrentValue(value);

                    // ...then trigger the augmented autofill UI
                    triggerAugmentedAutofillLocked();
                    return;
                }

                requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags);
                requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags);


                // Remove the UI if the ViewState has changed.
                // Remove the UI if the ViewState has changed.
                if (!Objects.equals(mCurrentViewId, viewState.id)) {
                if (!Objects.equals(mCurrentViewId, viewState.id)) {
                    mUi.hideFillUi(this);
                    mUi.hideFillUi(this);
                    mCurrentViewId = viewState.id;
                    mCurrentViewId = viewState.id;
                    hideAugmentedAutofillLocked(viewState);
                }
                }


                // If the ViewState is ready to be displayed, onReady() will be called.
                // If the ViewState is ready to be displayed, onReady() will be called.
@@ -2340,8 +2366,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                break;
                break;
            case ACTION_VIEW_EXITED:
            case ACTION_VIEW_EXITED:
                if (Objects.equals(mCurrentViewId, viewState.id)) {
                if (Objects.equals(mCurrentViewId, viewState.id)) {
                    if (sVerbose) Slog.d(TAG, "Exiting view " + id);
                    if (sVerbose) Slog.v(TAG, "Exiting view " + id);
                    mUi.hideFillUi(this);
                    mUi.hideFillUi(this);
                    hideAugmentedAutofillLocked(viewState);
                    mCurrentViewId = null;
                    mCurrentViewId = null;
                }
                }
                break;
                break;
@@ -2350,6 +2377,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        }
        }
    }
    }


    @GuardedBy("mLock")
    private void hideAugmentedAutofillLocked(@NonNull ViewState viewState) {
        if ((viewState.getState()
                & ViewState.STATE_TRIGGERED_AUGMENTED_AUTOFILL) != 0) {
            viewState.resetState(ViewState.STATE_TRIGGERED_AUGMENTED_AUTOFILL);
            cancelAugmentedAutofillLocked();
        }
    }

    /**
    /**
     * Checks whether a view should be ignored.
     * Checks whether a view should be ignored.
     */
     */
@@ -2430,14 +2466,14 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
    }
    }


    private void notifyUnavailableToClient(int sessionFinishedState,
    private void notifyUnavailableToClient(int sessionFinishedState,
            @Nullable ArrayList<AutofillId> autofillableIds) {
            @Nullable ArraySet<AutofillId> autofillableIds) {
        synchronized (mLock) {
        synchronized (mLock) {
            if (mCurrentViewId == null) return;
            if (mCurrentViewId == null) return;
            try {
            try {
                if (mHasCallback) {
                if (mHasCallback) {
                    mClient.notifyNoFillUi(id, mCurrentViewId, sessionFinishedState);
                    mClient.notifyNoFillUi(id, mCurrentViewId, sessionFinishedState);
                } else if (sessionFinishedState != 0) {
                } else if (sessionFinishedState != 0) {
                    mClient.setSessionFinished(sessionFinishedState, autofillableIds);
                    mClient.setSessionFinished(sessionFinishedState, toList(autofillableIds));
                }
                }
            } catch (RemoteException e) {
            } catch (RemoteException e) {
                Slog.e(TAG, "Error notifying client no fill UI: id=" + mCurrentViewId, e);
                Slog.e(TAG, "Error notifying client no fill UI: id=" + mCurrentViewId, e);
@@ -2560,7 +2596,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState


        final FillContext context = getFillContextByRequestIdLocked(requestId);
        final FillContext context = getFillContextByRequestIdLocked(requestId);


        final ArrayList<AutofillId> autofillableIds;
        final ArraySet<AutofillId> autofillableIds;
        if (context != null) {
        if (context != null) {
            final AssistStructure structure = context.getStructure();
            final AssistStructure structure = context.getStructure();
            autofillableIds = Helper.getAutofillableIds(structure);
            autofillableIds = Helper.getAutofillableIds(structure);
@@ -2583,16 +2619,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
            notifyUnavailableToClient(AutofillManager.STATE_FINISHED, autofillableIds);
            notifyUnavailableToClient(AutofillManager.STATE_FINISHED, autofillableIds);
            removeSelf();
            removeSelf();
        } else {
        } else {
            // TODO(b/123099468, b/119638958): must set internal state so when user focus other
            // fields it does not generate a new call to the standard autofill service (right now
            // it does). In other words, must also pass the autofillableIds - we'll be handled in
            // a separate change (with new CTS tests to exercise this scenario).

            if (sVerbose) {
            if (sVerbose) {
                Slog.v(TAG, "keeping session " + id + " when server returned null but "
                Slog.v(TAG, "keeping session " + id + " when server returned null but "
                        + "there is an AugmentedAutofill for user. AutofillableIds: "
                        + "there is an AugmentedAutofill for user. AutofillableIds: "
                        + autofillableIds);
                        + autofillableIds);
            }
            }
            mAugmentedAutofillableIds = autofillableIds;
        }
        }
    }
    }


@@ -2660,7 +2692,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
            return null;
            return null;
        }
        }


        final AutofillValue currentValue = mViewStates.get(mCurrentViewId).getCurrentValue();
        final ViewState viewState = mViewStates.get(mCurrentViewId);
        viewState.setState(ViewState.STATE_TRIGGERED_AUGMENTED_AUTOFILL);
        final AutofillValue currentValue = viewState.getCurrentValue();


        // TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
        // TODO(b/111330312): we might need to add a new state in the AutofillManager to optimize
        // further AFM -> AFMS calls.
        // further AFM -> AFMS calls.
@@ -2681,6 +2715,18 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
        return mAugmentedAutofillDestroyer;
        return mAugmentedAutofillDestroyer;
    }
    }


    @GuardedBy("mLock")
    private void cancelAugmentedAutofillLocked() {
        final RemoteAugmentedAutofillService remoteService = mService
                .getRemoteAugmentedAutofillServiceLocked();
        if (remoteService == null) {
            Slog.w(TAG, "cancelAugmentedAutofillLocked(): no service for user");
            return;
        }
        if (sVerbose) Slog.v(TAG, "cancelAugmentedAutofillLocked() on " + mCurrentViewId);
        remoteService.onDestroyAutofillWindowsRequest();
    }

    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private void processResponseLocked(@NonNull FillResponse newResponse,
    private void processResponseLocked(@NonNull FillResponse newResponse,
            @Nullable Bundle newClientState, int flags) {
            @Nullable Bundle newClientState, int flags) {
@@ -2967,6 +3013,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
            pw.println(mAugmentedRequestsLogs.size());
            pw.println(mAugmentedRequestsLogs.size());
        }
        }


        if (mAugmentedAutofillableIds != null) {
            pw.print(prefix); pw.print("mAugmentedAutofillableIds: ");
            pw.println(mAugmentedAutofillableIds);
        }
        mRemoteFillService.dump(prefix, pw);
        mRemoteFillService.dump(prefix, pw);
    }
    }


Loading