/* * 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.annotation.SuppressLint; import android.annotation.TestApi; import android.content.ClipData; import android.content.ClipDescription; import android.net.Uri; import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.util.Pair; import android.view.inputmethod.InputContentInfo; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; 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 implements Parcelable { /** * 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; @Nullable private final InputContentInfo mInputContentInfo; @Nullable private final DragAndDropPermissions mDragAndDropPermissions; 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; this.mInputContentInfo = b.mInputContentInfo; this.mDragAndDropPermissions = b.mDragAndDropPermissions; } /** * If the content came from a source that supports proactive release of URI permissions * (e.g. IME), releases permissions; otherwise a no-op. * * @hide */ @TestApi public void releasePermissions() { if (mInputContentInfo != null) { mInputContentInfo.releasePermission(); } if (mDragAndDropPermissions != null) { mDragAndDropPermissions.release(); } } @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 @SuppressLint("NullableCollection") public Bundle getExtras() { return mExtras; } /** * Partitions this content based on the given predicate. * *
This function classifies the content and organizes it into a pair, grouping the items * that matched vs didn't match the predicate. * *
Except for the {@link ClipData} items, the returned objects will contain all the same
* metadata as this {@link ContentInfo}.
*
* @param itemPredicate The predicate to test each {@link ClipData.Item} to determine which
* partition to place it into.
* @return A pair containing the partitioned content. The pair's first object will have the
* content that matched the predicate, or null if none of the items matched. The pair's
* second object will have the content that didn't match the predicate, or null if all of
* the items matched.
*
* @hide
*/
@TestApi
@NonNull
public Pair