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

Commit 83de85f7 authored by Nikita Dubrovsky's avatar Nikita Dubrovsky Committed by Android (Google) Code Review
Browse files

Merge "Move/rename OnReceiveContentListener.Payload to android.view.ContentInfo"

parents 0a993aac 10f027f6
Loading
Loading
Loading
Loading
+30 −30
Original line number Diff line number Diff line
@@ -50849,6 +50849,33 @@ package android.view {
    method public void onActionViewExpanded();
  }
  public final class ContentInfo {
    method @NonNull public android.content.ClipData getClip();
    method @Nullable public android.os.Bundle getExtras();
    method public int getFlags();
    method @Nullable public android.net.Uri getLinkUri();
    method public int getSource();
    method @NonNull public java.util.Map<java.lang.Boolean,android.view.ContentInfo> partition(@NonNull java.util.function.Predicate<android.content.ClipData.Item>);
    field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
    field public static final int SOURCE_APP = 0; // 0x0
    field public static final int SOURCE_AUTOFILL = 4; // 0x4
    field public static final int SOURCE_CLIPBOARD = 1; // 0x1
    field public static final int SOURCE_DRAG_AND_DROP = 3; // 0x3
    field public static final int SOURCE_INPUT_METHOD = 2; // 0x2
    field public static final int SOURCE_PROCESS_TEXT = 5; // 0x5
  }
  public static final class ContentInfo.Builder {
    ctor public ContentInfo.Builder(@NonNull android.view.ContentInfo);
    ctor public ContentInfo.Builder(@NonNull android.content.ClipData, int);
    method @NonNull public android.view.ContentInfo build();
    method @NonNull public android.view.ContentInfo.Builder setClip(@NonNull android.content.ClipData);
    method @NonNull public android.view.ContentInfo.Builder setExtras(@Nullable android.os.Bundle);
    method @NonNull public android.view.ContentInfo.Builder setFlags(int);
    method @NonNull public android.view.ContentInfo.Builder setLinkUri(@Nullable android.net.Uri);
    method @NonNull public android.view.ContentInfo.Builder setSource(int);
  }
  public interface ContextMenu extends android.view.Menu {
    method public void clearHeader();
    method public android.view.ContextMenu setHeaderIcon(@DrawableRes int);
@@ -52064,34 +52091,7 @@ package android.view {
  }
  public interface OnReceiveContentListener {
    method @Nullable public android.view.OnReceiveContentListener.Payload onReceiveContent(@NonNull android.view.View, @NonNull android.view.OnReceiveContentListener.Payload);
  }
  public static final class OnReceiveContentListener.Payload {
    method @NonNull public android.content.ClipData getClip();
    method @Nullable public android.os.Bundle getExtras();
    method public int getFlags();
    method @Nullable public android.net.Uri getLinkUri();
    method public int getSource();
    method @NonNull public java.util.Map<java.lang.Boolean,android.view.OnReceiveContentListener.Payload> partition(@NonNull java.util.function.Predicate<android.content.ClipData.Item>);
    field public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1; // 0x1
    field public static final int SOURCE_APP = 0; // 0x0
    field public static final int SOURCE_AUTOFILL = 4; // 0x4
    field public static final int SOURCE_CLIPBOARD = 1; // 0x1
    field public static final int SOURCE_DRAG_AND_DROP = 3; // 0x3
    field public static final int SOURCE_INPUT_METHOD = 2; // 0x2
    field public static final int SOURCE_PROCESS_TEXT = 5; // 0x5
  }
  public static final class OnReceiveContentListener.Payload.Builder {
    ctor public OnReceiveContentListener.Payload.Builder(@NonNull android.view.OnReceiveContentListener.Payload);
    ctor public OnReceiveContentListener.Payload.Builder(@NonNull android.content.ClipData, int);
    method @NonNull public android.view.OnReceiveContentListener.Payload build();
    method @NonNull public android.view.OnReceiveContentListener.Payload.Builder setClip(@NonNull android.content.ClipData);
    method @NonNull public android.view.OnReceiveContentListener.Payload.Builder setExtras(@Nullable android.os.Bundle);
    method @NonNull public android.view.OnReceiveContentListener.Payload.Builder setFlags(int);
    method @NonNull public android.view.OnReceiveContentListener.Payload.Builder setLinkUri(@Nullable android.net.Uri);
    method @NonNull public android.view.OnReceiveContentListener.Payload.Builder setSource(int);
    method @Nullable public android.view.ContentInfo onReceiveContent(@NonNull android.view.View, @NonNull android.view.ContentInfo);
  }
  public abstract class OrientationEventListener {
@@ -52842,7 +52842,7 @@ package android.view {
    method public void onProvideContentCaptureStructure(@NonNull android.view.ViewStructure, int);
    method public void onProvideStructure(android.view.ViewStructure);
    method public void onProvideVirtualStructure(android.view.ViewStructure);
    method @Nullable public android.view.OnReceiveContentListener.Payload onReceiveContent(@NonNull android.view.OnReceiveContentListener.Payload);
    method @Nullable public android.view.ContentInfo onReceiveContent(@NonNull android.view.ContentInfo);
    method public android.view.PointerIcon onResolvePointerIcon(android.view.MotionEvent, int);
    method @CallSuper protected void onRestoreInstanceState(android.os.Parcelable);
    method public void onRtlPropertiesChanged(int);
@@ -52868,7 +52868,7 @@ package android.view {
    method public boolean performHapticFeedback(int, int);
    method public boolean performLongClick();
    method public boolean performLongClick(float, float);
    method @Nullable public android.view.OnReceiveContentListener.Payload performReceiveContent(@NonNull android.view.OnReceiveContentListener.Payload);
    method @Nullable public android.view.ContentInfo performReceiveContent(@NonNull android.view.ContentInfo);
    method public void playSoundEffect(int);
    method public boolean post(Runnable);
    method public boolean postDelayed(Runnable, long);
+358 −0
Original line number 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 android.view;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ClipData;
import android.net.Uri;
import android.os.Bundle;
import android.util.ArrayMap;

import com.android.internal.util.Preconditions;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;
import java.util.function.Predicate;

/**
 * Holds all the relevant data for a request to {@link View#performReceiveContent}.
 */
public final class ContentInfo {

    /**
     * Specifies the UI through which content is being inserted. Future versions of Android may
     * support additional values.
     *
     * @hide
     */
    @IntDef(prefix = {"SOURCE_"}, value = {SOURCE_APP, SOURCE_CLIPBOARD, SOURCE_INPUT_METHOD,
            SOURCE_DRAG_AND_DROP, SOURCE_AUTOFILL, SOURCE_PROCESS_TEXT})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Source {}

    /**
     * Specifies that the operation was triggered by the app that contains the target view.
     */
    public static final int SOURCE_APP = 0;

    /**
     * Specifies that the operation was triggered by a paste from the clipboard (e.g. "Paste" or
     * "Paste as plain text" action in the insertion/selection menu).
     */
    public static final int SOURCE_CLIPBOARD = 1;

    /**
     * Specifies that the operation was triggered from the soft keyboard (also known as input
     * method editor or IME). See https://developer.android.com/guide/topics/text/image-keyboard
     * for more info.
     */
    public static final int SOURCE_INPUT_METHOD = 2;

    /**
     * Specifies that the operation was triggered by the drag/drop framework. See
     * https://developer.android.com/guide/topics/ui/drag-drop for more info.
     */
    public static final int SOURCE_DRAG_AND_DROP = 3;

    /**
     * Specifies that the operation was triggered by the autofill framework. See
     * https://developer.android.com/guide/topics/text/autofill for more info.
     */
    public static final int SOURCE_AUTOFILL = 4;

    /**
     * Specifies that the operation was triggered by a result from a
     * {@link android.content.Intent#ACTION_PROCESS_TEXT PROCESS_TEXT} action in the selection
     * menu.
     */
    public static final int SOURCE_PROCESS_TEXT = 5;

    /**
     * Returns the symbolic name of the given source.
     *
     * @hide
     */
    static String sourceToString(@Source int source) {
        switch (source) {
            case SOURCE_APP: return "SOURCE_APP";
            case SOURCE_CLIPBOARD: return "SOURCE_CLIPBOARD";
            case SOURCE_INPUT_METHOD: return "SOURCE_INPUT_METHOD";
            case SOURCE_DRAG_AND_DROP: return "SOURCE_DRAG_AND_DROP";
            case SOURCE_AUTOFILL: return "SOURCE_AUTOFILL";
            case SOURCE_PROCESS_TEXT: return "SOURCE_PROCESS_TEXT";
        }
        return String.valueOf(source);
    }

    /**
     * Flags to configure the insertion behavior.
     *
     * @hide
     */
    @IntDef(flag = true, prefix = {"FLAG_"}, value = {FLAG_CONVERT_TO_PLAIN_TEXT})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Flags {}

    /**
     * Flag requesting that the content should be converted to plain text prior to inserting.
     */
    public static final int FLAG_CONVERT_TO_PLAIN_TEXT = 1 << 0;

    /**
     * Returns the symbolic names of the set flags or {@code "0"} if no flags are set.
     *
     * @hide
     */
    static String flagsToString(@Flags int flags) {
        if ((flags & FLAG_CONVERT_TO_PLAIN_TEXT) != 0) {
            return "FLAG_CONVERT_TO_PLAIN_TEXT";
        }
        return String.valueOf(flags);
    }

    @NonNull
    private final ClipData mClip;
    @Source
    private final int mSource;
    @Flags
    private final int mFlags;
    @Nullable
    private final Uri mLinkUri;
    @Nullable
    private final Bundle mExtras;

    private ContentInfo(Builder b) {
        this.mClip = Objects.requireNonNull(b.mClip);
        this.mSource = Preconditions.checkArgumentInRange(b.mSource, 0, SOURCE_PROCESS_TEXT,
                "source");
        this.mFlags = Preconditions.checkFlagsArgument(b.mFlags, FLAG_CONVERT_TO_PLAIN_TEXT);
        this.mLinkUri = b.mLinkUri;
        this.mExtras = b.mExtras;
    }

    @NonNull
    @Override
    public String toString() {
        return "ContentInfo{"
                + "clip=" + mClip
                + ", source=" + sourceToString(mSource)
                + ", flags=" + flagsToString(mFlags)
                + ", linkUri=" + mLinkUri
                + ", extras=" + mExtras
                + "}";
    }

    /**
     * The data to be inserted.
     */
    @NonNull
    public ClipData getClip() {
        return mClip;
    }

    /**
     * The source of the operation. See {@code SOURCE_} constants. Future versions of Android
     * may pass additional values.
     */
    @Source
    public int getSource() {
        return mSource;
    }

    /**
     * Optional flags that control the insertion behavior. See {@code FLAG_} constants.
     */
    @Flags
    public int getFlags() {
        return mFlags;
    }

    /**
     * Optional http/https URI for the content that may be provided by the IME. This is only
     * populated if the source is {@link #SOURCE_INPUT_METHOD} and if a non-empty
     * {@link android.view.inputmethod.InputContentInfo#getLinkUri linkUri} was passed by the
     * IME.
     */
    @Nullable
    public Uri getLinkUri() {
        return mLinkUri;
    }

    /**
     * Optional additional metadata. If the source is {@link #SOURCE_INPUT_METHOD}, this will
     * include the {@link android.view.inputmethod.InputConnection#commitContent opts} passed by
     * the IME.
     */
    @Nullable
    public Bundle getExtras() {
        return mExtras;
    }

    /**
     * Partitions the content based on the given predicate.
     *
     * <p>Similar to a
     * {@link java.util.stream.Collectors#partitioningBy(Predicate) partitioning collector},
     * this function classifies the content and organizes it into a map, grouping the items that
     * matched vs didn't match the predicate.
     *
     * <p>Except for the {@link ClipData} items, the returned objects will contain all the same
     * metadata as the original.
     *
     * @param itemPredicate The predicate to test each {@link ClipData.Item} to determine which
     * partition to place it into.
     * @return A map containing the partitioned content. The map will contain a single entry if
     * all items were classified into the same partition (all matched or all didn't match the
     * predicate) or two entries (if there's at least one item that matched the predicate and at
     * least one item that didn't match the predicate).
     */
    @NonNull
    public Map<Boolean, ContentInfo> partition(@NonNull Predicate<ClipData.Item> itemPredicate) {
        if (mClip.getItemCount() == 1) {
            Map<Boolean, ContentInfo> result = new ArrayMap<>(1);
            result.put(itemPredicate.test(mClip.getItemAt(0)), this);
            return result;
        }
        ArrayList<ClipData.Item> accepted = new ArrayList<>();
        ArrayList<ClipData.Item> remaining = new ArrayList<>();
        for (int i = 0; i < mClip.getItemCount(); i++) {
            ClipData.Item item = mClip.getItemAt(i);
            if (itemPredicate.test(item)) {
                accepted.add(item);
            } else {
                remaining.add(item);
            }
        }
        Map<Boolean, ContentInfo> result = new ArrayMap<>(2);
        if (!accepted.isEmpty()) {
            ClipData acceptedClip = new ClipData(mClip.getDescription(), accepted);
            result.put(true, new Builder(this).setClip(acceptedClip).build());
        }
        if (!remaining.isEmpty()) {
            ClipData remainingClip = new ClipData(mClip.getDescription(), remaining);
            result.put(false, new Builder(this).setClip(remainingClip).build());
        }
        return result;
    }

    /**
     * Builder for {@link ContentInfo}.
     */
    public static final class Builder {
        @NonNull
        private ClipData mClip;
        @Source
        private int mSource;
        @Flags
        private  int mFlags;
        @Nullable
        private Uri mLinkUri;
        @Nullable
        private Bundle mExtras;

        /**
         * Creates a new builder initialized with the data from the given builder.
         */
        public Builder(@NonNull ContentInfo other) {
            mClip = other.mClip;
            mSource = other.mSource;
            mFlags = other.mFlags;
            mLinkUri = other.mLinkUri;
            mExtras = other.mExtras;
        }

        /**
         * Creates a new builder.
         * @param clip   The data to insert.
         * @param source The source of the operation. See {@code SOURCE_} constants.
         */
        public Builder(@NonNull ClipData clip, @Source int source) {
            mClip = clip;
            mSource = source;
        }

        /**
         * Sets the data to be inserted.
         * @param clip The data to insert.
         * @return this builder
         */
        @NonNull
        public Builder setClip(@NonNull ClipData clip) {
            mClip = clip;
            return this;
        }

        /**
         * Sets the source of the operation.
         * @param source The source of the operation. See {@code SOURCE_} constants.
         * @return this builder
         */
        @NonNull
        public Builder setSource(@Source int source) {
            mSource = source;
            return this;
        }

        /**
         * Sets flags that control content insertion behavior.
         * @param flags Optional flags to configure the insertion behavior. Use 0 for default
         *              behavior. See {@code FLAG_} constants.
         * @return this builder
         */
        @NonNull
        public Builder setFlags(@Flags int flags) {
            mFlags = flags;
            return this;
        }

        /**
         * Sets the http/https URI for the content. See
         * {@link android.view.inputmethod.InputContentInfo#getLinkUri} for more info.
         * @param linkUri Optional http/https URI for the content.
         * @return this builder
         */
        @NonNull
        public Builder setLinkUri(@Nullable Uri linkUri) {
            mLinkUri = linkUri;
            return this;
        }

        /**
         * Sets additional metadata.
         * @param extras Optional bundle with additional metadata.
         * @return this builder
         */
        @NonNull
        public Builder setExtras(@Nullable Bundle extras) {
            mExtras = extras;
            return this;
        }

        /**
         * @return A new {@link ContentInfo} instance with the data from this builder.
         */
        @NonNull
        public ContentInfo build() {
            return new ContentInfo(this);
        }
    }
}
+12 −331

File changed.

Preview size limit exceeded, changes collapsed.

+7 −5
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@ import android.view.AccessibilityIterators.TextSegmentIterator;
import android.view.AccessibilityIterators.WordTextSegmentIterator;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.InputDevice.InputSourceClass;
import android.view.OnReceiveContentListener.Payload;
import android.view.Window.OnContentApplyWindowInsetsListener;
import android.view.WindowInsets.Type;
import android.view.WindowInsetsAnimation.Bounds;
@@ -9063,11 +9062,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return The portion of the passed-in content that was not accepted (may be all, some, or none
     * of the passed-in content).
     */
    public @Nullable Payload performReceiveContent(@NonNull Payload payload) {
    @Nullable
    public ContentInfo performReceiveContent(@NonNull ContentInfo payload) {
        final OnReceiveContentListener listener = (mListenerInfo == null) ? null
                : getListenerInfo().mOnReceiveContentListener;
        if (listener != null) {
            final Payload remaining = listener.onReceiveContent(this, payload);
            final ContentInfo remaining = listener.onReceiveContent(this, payload);
            return (remaining == null) ? null : onReceiveContent(remaining);
        }
        return onReceiveContent(payload);
@@ -9088,7 +9088,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return The portion of the passed-in content that was not handled (may be all, some, or none
     * of the passed-in content).
     */
    public @Nullable Payload onReceiveContent(@NonNull Payload payload) {
    @Nullable
    public ContentInfo onReceiveContent(@NonNull ContentInfo payload) {
        return payload;
    }
@@ -9113,7 +9114,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     * @return The MIME types accepted by {@link #performReceiveContent} for this view (may
     * include patterns such as "image/*").
     */
    public @Nullable String[] getOnReceiveContentMimeTypes() {
    @Nullable
    public String[] getOnReceiveContentMimeTypes() {
        return mOnReceiveContentMimeTypes;
    }
+4 −4
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@ package android.view.autofill;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
import static android.service.autofill.FillRequest.FLAG_VIEW_NOT_FOCUSED;
import static android.view.OnReceiveContentListener.Payload.SOURCE_AUTOFILL;
import static android.view.ContentInfo.SOURCE_AUTOFILL;
import static android.view.autofill.Helper.sDebug;
import static android.view.autofill.Helper.sVerbose;
import static android.view.autofill.Helper.toList;
@@ -61,8 +61,8 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Choreographer;
import android.view.ContentInfo;
import android.view.KeyEvent;
import android.view.OnReceiveContentListener.Payload;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -2371,8 +2371,8 @@ public final class AutofillManager {
                reportAutofillContentFailure(id);
                return;
            }
            Payload payload = new Payload.Builder(clip, SOURCE_AUTOFILL).build();
            Payload result = view.performReceiveContent(payload);
            ContentInfo payload = new ContentInfo.Builder(clip, SOURCE_AUTOFILL).build();
            ContentInfo result = view.performReceiveContent(payload);
            if (result != null) {
                Log.w(TAG, "autofillContent(): receiver could not insert content: id=" + id
                        + ", view=" + view + ", clip=" + clip);
Loading