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

Commit 48f363c5 authored by Felipe Leme's avatar Felipe Leme
Browse files

ContentCapture: add new API to notify views deletion on batch.

Test: atest CtsContentCaptureServiceTestCases
Bug: 121050915

Change-Id: I325cfb2954c7c990c8916fe9b17a2642dcaa1c79
parent b53afba8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -8266,6 +8266,7 @@ package android.view.contentcapture {
    method public long getEventTime();
    method public int getFlags();
    method public android.view.autofill.AutofillId getId();
    method public java.util.List<android.view.autofill.AutofillId> getIds();
    method public java.lang.CharSequence getText();
    method public int getType();
    method public android.view.contentcapture.ViewNode getViewNode();
+56 −3
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
import android.view.autofill.AutofillId;

import com.android.internal.util.Preconditions;
@@ -28,11 +29,15 @@ import com.android.internal.util.Preconditions;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;

/** @hide */
@SystemApi
public final class ContentCaptureEvent implements Parcelable {

    private static final String TAG = ContentCaptureEvent.class.getSimpleName();

    /** @hide */
    public static final int TYPE_SESSION_FINISHED = -2;
    /** @hide */
@@ -46,9 +51,11 @@ public final class ContentCaptureEvent implements Parcelable {
    public static final int TYPE_VIEW_APPEARED = 1;

    /**
     * Called when a node has been removed from the screen and is not visible to the user anymore.
     * Called when one or more nodes have been removed from the screen and is not visible to the
     * user anymore.
     *
     * <p>The id of the node is available through {@link #getId()}.
     * <p>To get the id(s), first call {@link #getIds()} - if it returns {@code null}, then call
     * {@link #getId()}.
     */
    public static final int TYPE_VIEW_DISAPPEARED = 2;

@@ -76,6 +83,7 @@ public final class ContentCaptureEvent implements Parcelable {
    private final long mEventTime;
    private final int mFlags;
    private @Nullable AutofillId mId;
    private @Nullable ArrayList<AutofillId> mIds;
    private @Nullable ViewNode mNode;
    private @Nullable CharSequence mText;
    private @Nullable String mParentSessionId;
@@ -105,6 +113,27 @@ public final class ContentCaptureEvent implements Parcelable {
        return this;
    }

    private void setAutofillIds(@NonNull ArrayList<AutofillId> ids) {
        mIds = Preconditions.checkNotNull(ids);
    }

    /**
     * Adds an autofill id to the this event, merging the single id into a list if necessary.
     * @hide */
    public ContentCaptureEvent addAutofillId(@NonNull AutofillId id) {
        if (mIds == null) {
            mIds = new ArrayList<>();
            if (mId == null) {
                Log.w(TAG, "addAutofillId(" + id + ") called without an initial id");
            } else {
                mIds.add(mId);
                mId = null;
            }
        }
        mIds.add(id);
        return this;
    }

    /**
     * Used by {@link #TYPE_SESSION_STARTED} and {@link #TYPE_SESSION_FINISHED}.
     *
@@ -205,13 +234,26 @@ public final class ContentCaptureEvent implements Parcelable {
    /**
     * Gets the {@link AutofillId} of the node associated with the event.
     *
     * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED} and {@link #TYPE_VIEW_TEXT_CHANGED} events.
     * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED} (when the event contains just one node - if
     * it contains more than one, this method returns {@code null} and the actual ids should be
     * retrived by {@link #getIds()}) and {@link #TYPE_VIEW_TEXT_CHANGED} events.
     */
    @Nullable
    public AutofillId getId() {
        return mId;
    }

    /**
     * Gets the {@link AutofillId AutofillIds} of the nodes associated with the event.
     *
     * <p>Only set on {@link #TYPE_VIEW_DISAPPEARED}, when the event contains more than one node
     * (if it contains just one node, it's returned by {@link #getId()} instead.
     */
    @Nullable
    public List<AutofillId> getIds() {
        return mIds;
    }

    /**
     * Gets the current text of the node associated with the event.
     *
@@ -232,6 +274,9 @@ public final class ContentCaptureEvent implements Parcelable {
        if (mId != null) {
            pw.print(", id="); pw.print(mId);
        }
        if (mIds != null) {
            pw.print(", ids="); pw.print(mIds);
        }
        if (mNode != null) {
            pw.print(", mNode.id="); pw.print(mNode.getAutofillId());
        }
@@ -261,6 +306,9 @@ public final class ContentCaptureEvent implements Parcelable {
        if (mId != null) {
            string.append(", id=").append(mId);
        }
        if (mIds != null) {
            string.append(", ids=").append(mIds);
        }
        if (mNode != null) {
            final String className = mNode.getClassName();
            if (mNode != null) {
@@ -283,6 +331,7 @@ public final class ContentCaptureEvent implements Parcelable {
        parcel.writeLong(mEventTime);
        parcel.writeInt(mFlags);
        parcel.writeParcelable(mId, flags);
        parcel.writeTypedList(mIds);
        ViewNode.writeToParcel(parcel, mNode, flags);
        parcel.writeCharSequence(mText);
        if (mType == TYPE_SESSION_STARTED || mType == TYPE_SESSION_FINISHED) {
@@ -308,6 +357,10 @@ public final class ContentCaptureEvent implements Parcelable {
            if (id != null) {
                event.setAutofillId(id);
            }
            final ArrayList<AutofillId> ids = parcel.createTypedArrayList(AutofillId.CREATOR);
            if (ids != null) {
                event.setAutofillIds(ids);
            }
            final ViewNode node = ViewNode.readFromParcel(parcel);
            if (node != null) {
                event.setViewNode(node);
+2 −2
Original line number Diff line number Diff line
@@ -363,8 +363,8 @@ public abstract class ContentCaptureSession implements AutoCloseable {
        Preconditions.checkArgument(!ArrayUtils.isEmpty(virtualIds), "virtual ids cannot be empty");
        if (!isContentCaptureEnabled()) return;

        // TODO(b/121050915): create a new VIEWS_DISAPPEARED event type, which could also be used
        // to batch delete non-virtual views
        // TODO(b/123036895): use a internalNotifyViewsDisappeared that optimizes how the event is
        // parcelized
        for (int id : virtualIds) {
            internalNotifyViewDisappeared(new AutofillId(hostId, id, getIdAsInt()));
        }
+20 −3
Original line number Diff line number Diff line
@@ -286,6 +286,9 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
            mEvents = new ArrayList<>(MAX_BUFFER_SIZE);
        }

        // Some type of events can be merged together
        boolean addEvent = true;

        if (!mEvents.isEmpty() && eventType == TYPE_VIEW_TEXT_CHANGED) {
            final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1);

@@ -297,10 +300,24 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
                            + event.getText());
                }
                lastEvent.setText(event.getText());
            } else {
                mEvents.add(event);
                addEvent = false;
            }
        } else {
        }

        if (!mEvents.isEmpty() && eventType == TYPE_VIEW_DISAPPEARED) {
            final ContentCaptureEvent lastEvent = mEvents.get(mEvents.size() - 1);
            if (lastEvent.getType() == TYPE_VIEW_DISAPPEARED
                    && event.getSessionId().equals(lastEvent.getSessionId())) {
                if (VERBOSE) {
                    Log.v(TAG, "Buffering TYPE_VIEW_DISAPPEARED events for session "
                            + lastEvent.getSessionId());
                }
                lastEvent.addAutofillId(event.getId());
                addEvent = false;
            }
        }

        if (addEvent) {
            mEvents.add(event);
        }