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

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

Merge "New APIs to let app developers manage autofill semantics when reusing views."

parents 55576285 42b9793d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -47617,6 +47617,7 @@ package android.view {
    method public void setAlpha(float);
    method public void setAnimation(android.view.animation.Animation);
    method public void setAutofillHints(java.lang.String...);
    method public void setAutofillId(android.view.autofill.AutofillId);
    method public void setBackground(android.graphics.drawable.Drawable);
    method public void setBackgroundColor(int);
    method public deprecated void setBackgroundDrawable(android.graphics.drawable.Drawable);
@@ -49780,6 +49781,7 @@ package android.view.autofill {
    method public android.content.ComponentName getAutofillServiceComponentName();
    method public java.util.List<java.lang.String> getAvailableFieldClassificationAlgorithms();
    method public java.lang.String getDefaultFieldClassificationAlgorithm();
    method public android.view.autofill.AutofillId getNextAutofillId();
    method public android.service.autofill.UserData getUserData();
    method public java.lang.String getUserDataId();
    method public boolean hasEnabledAutofillServices();
+10 −1
Original line number Diff line number Diff line
@@ -1400,6 +1400,7 @@ public class Activity extends ContextThemeWrapper
     *
     * {@hide}
     */
    @Override
    public int getNextAutofillId() {
        if (mLastAutofillId == Integer.MAX_VALUE - 1) {
            mLastAutofillId = View.LAST_APP_AUTOFILL_ID;
@@ -1410,6 +1411,14 @@ public class Activity extends ContextThemeWrapper
        return mLastAutofillId;
    }

    /**
     * @hide
     */
    @Override
    public AutofillId autofillClientGetNextAutofillId() {
        return new AutofillId(getNextAutofillId());
    }

    /**
     * Check whether this activity is running as part of a voice interaction with the user.
     * If true, it should perform its interaction with the user through the
@@ -7752,7 +7761,7 @@ public class Activity extends ContextThemeWrapper

    /** @hide */
    @Override
    public final boolean autofillIsCompatibilityModeEnabled() {
    public final boolean autofillClientIsCompatibilityModeEnabled() {
        return isAutofillCompatibilityEnabled();
    }

+61 −1
Original line number Diff line number Diff line
@@ -8144,7 +8144,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
    }
    /**
     * Gets the unique identifier of this view in the screen, for autofill purposes.
     * Gets the unique, logical identifier of this view in the activity, for autofill purposes.
     *
     * <p>The autofill id is created on demand, unless it is explicitly set by
     * {@link #setAutofillId(AutofillId)}.
     *
     * <p>See {@link #setAutofillId(AutofillId)} for more info.
     *
     * @return The View's autofill id.
     */
@@ -8157,6 +8162,61 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        return mAutofillId;
    }
    /**
     * Sets the unique, logical identifier of this view in the activity, for autofill purposes.
     *
     * <p>The autofill id is created on demand, and this method should only be called when a view is
     * reused after {@link #dispatchProvideAutofillStructure(ViewStructure, int)} is called, as
     * that method creates a snapshot of the view that is passed along to the autofill service.
     *
     * <p>This method is typically used when view subtrees are recycled to represent different
     * content* &mdash;in this case, the autofill id can be saved before the view content is swapped
     * out, and restored later when it's swapped back in. For example:
     *
     * <pre>
     * EditText reusableView = ...;
     * ViewGroup parentView = ...;
     * AutofillManager afm = ...;
     *
     * // Swap out the view and change its contents
     * AutofillId oldId = reusableView.getAutofillId();
     * CharSequence oldText = reusableView.getText();
     * parentView.removeView(reusableView);
     * AutofillId newId = afm.getNextAutofillId();
     * reusableView.setText("New I am");
     * reusableView.setAutofillId(newId);
     * parentView.addView(reusableView);
     *
     * // Later, swap the old content back in
     * parentView.removeView(reusableView);
     * reusableView.setAutofillId(oldId);
     * reusableView.setText(oldText);
     * parentView.addView(reusableView);
     * </pre>
     *
     * @param id an autofill ID that is unique in the {@link android.app.Activity} hosting the view,
     * or {@code null} to reset it. Usually it's an id previously allocated to another view (and
     * obtained through {@link #getAutofillId()}), or a new value obtained through
     * {@link AutofillManager#getNextAutofillId()}.
     *
     * @throws IllegalStateException if the view is already {@link #isAttachedToWindow() attached to
     * a window}.
     *
     * @throws IllegalArgumentException if the id is an autofill id associated with a virtual view.
     */
    public void setAutofillId(@Nullable AutofillId id) {
        if (android.view.autofill.Helper.sVerbose) {
            Log.v(VIEW_LOG_TAG, "setAutofill(): from " + mAutofillId + " to " + id);
        }
        if (isAttachedToWindow()) {
            throw new IllegalStateException("Cannot set autofill id when view is attached");
        }
        if (id.isVirtual()) {
            throw new IllegalStateException("Cannot set autofill id assigned to virtual views");
        }
        mAutofillId = id;
    }
    /**
     * Describes the autofill type of this view, so an
     * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
+40 −8
Original line number Diff line number Diff line
@@ -498,7 +498,17 @@ public final class AutofillManager {
        /**
          * @return Whether compatibility mode is enabled.
          */
        boolean autofillIsCompatibilityModeEnabled();
        boolean autofillClientIsCompatibilityModeEnabled();

        /**
         * Gets the next unique autofill ID.
         *
         * <p>Typically used to manage views whose content is recycled - see
         * {@link View#setAutofillId(AutofillId)} for more info.
         *
         * @return An ID that is unique in the activity.
         */
        @Nullable AutofillId autofillClientGetNextAutofillId();
    }

    /**
@@ -781,7 +791,7 @@ public final class AutofillManager {
    /** Returns AutofillCallback if need fire EVENT_INPUT_UNAVAILABLE */
    @GuardedBy("mLock")
    private AutofillCallback notifyViewEnteredLocked(@NonNull View view, int flags) {
        final AutofillId id = getAutofillId(view);
        final AutofillId id = view.getAutofillId();
        if (shouldIgnoreViewEnteredLocked(id, flags)) return null;

        AutofillCallback callback = null;
@@ -831,7 +841,7 @@ public final class AutofillManager {
        if (mEnabled && isActiveLocked()) {
            // dont notify exited when Activity is already in background
            if (!isClientDisablingEnterExitEvent()) {
                final AutofillId id = getAutofillId(view);
                final AutofillId id = view.getAutofillId();

                // Update focus on existing session.
                updateSessionLocked(id, null, null, ACTION_VIEW_EXITED, 0);
@@ -874,6 +884,7 @@ public final class AutofillManager {
            if (mEnabled && isActiveLocked()) {
                final AutofillId id = virtual ? getAutofillId(view, virtualId)
                        : view.getAutofillId();
                if (sVerbose) Log.v(TAG, "visibility changed for " + id + ": " + isVisible);
                if (!isVisible && mFillableIds != null) {
                    if (mFillableIds.contains(id)) {
                        if (sDebug) Log.d(TAG, "Hidding UI when view " + id + " became invisible");
@@ -882,6 +893,8 @@ public final class AutofillManager {
                }
                if (mTrackedViews != null) {
                    mTrackedViews.notifyViewVisibilityChangedLocked(id, isVisible);
                } else if (sVerbose) {
                    Log.v(TAG, "Ignoring visibility change on " + id + ": no tracked views");
                }
            }
        }
@@ -1012,7 +1025,7 @@ public final class AutofillManager {
            if (mLastAutofilledData == null) {
                view.setAutofilled(false);
            } else {
                id = getAutofillId(view);
                id = view.getAutofillId();
                if (mLastAutofilledData.containsKey(id)) {
                    value = view.getAutofillValue();
                    valueWasRead = true;
@@ -1037,7 +1050,7 @@ public final class AutofillManager {
            }

            if (id == null) {
                id = getAutofillId(view);
                id = view.getAutofillId();
            }

            if (!valueWasRead) {
@@ -1437,8 +1450,27 @@ public final class AutofillManager {
        }
    }

    private static AutofillId getAutofillId(View view) {
        return new AutofillId(view.getAutofillViewId());
    /**
     * Gets the next unique autofill ID for the activity context.
     *
     * <p>Typically used to manage views whose content is recycled - see
     * {@link View#setAutofillId(AutofillId)} for more info.
     *
     * @return An ID that is unique in the activity, or {@code null} if autofill is not supported in
     * the {@link Context} associated with this {@link AutofillManager}.
     */
    @Nullable
    public AutofillId getNextAutofillId() {
        final AutofillClient client = getClient();
        if (client == null) return null;

        final AutofillId id = client.autofillClientGetNextAutofillId();

        if (id == null && sDebug) {
            Log.d(TAG, "getNextAutofillId(): client " + client + " returned null");
        }

        return id;
    }

    private static AutofillId getAutofillId(View parent, int virtualId) {
@@ -1739,7 +1771,7 @@ public final class AutofillManager {
                if (mLastAutofilledData == null) {
                    mLastAutofilledData = new ParcelableMap(1);
                }
                mLastAutofilledData.put(getAutofillId(view), targetValue);
                mLastAutofilledData.put(view.getAutofillId(), targetValue);
            }
            view.setAutofilled(true);
        }