From b8fc7436995c79effd478c19dd5434626d64735f Mon Sep 17 00:00:00 2001 From: TYM Tsai Date: Thu, 3 Jun 2021 21:19:39 +0800 Subject: [PATCH] Make ContentCapture event contains parcelable span The spans were removed by ag/13819626. Adds them back into the ContentCaptureEvent. And removes unnecessary Map data because we can get it via travel events. The total of events is not large. Bug: 190035037 Bug: 184311217 Test: atest CtsContentCaptureServiceTestCases Test: atest FrameworksCoreTests:ContentCaptureEventTest Change-Id: I5fa1f7a6b51fd050a63731543cca98972c294b22 --- .../MainContentCaptureSession.java | 73 +++++++++---------- 1 file changed, 35 insertions(+), 38 deletions(-) diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java index ad4ba76a17cb1..aee540f466bfb 100644 --- a/core/java/android/view/contentcapture/MainContentCaptureSession.java +++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java @@ -44,8 +44,9 @@ import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.RemoteException; import android.text.Spannable; +import android.text.SpannableString; +import android.text.Spanned; import android.text.TextUtils; -import android.util.ArrayMap; import android.util.LocalLog; import android.util.Log; import android.util.TimeUtils; @@ -60,7 +61,6 @@ import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -150,12 +150,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession { @Nullable private final LocalLog mFlushHistory; - /** - * If the event in the buffer is of type {@link TYPE_VIEW_TEXT_CHANGED}, this value - * indicates whether the event has composing span or not. - */ - private final Map mLastComposingSpan = new ArrayMap<>(); - /** * Binder object used to update the session state. */ @@ -352,40 +346,34 @@ public final class MainContentCaptureSession extends ContentCaptureSession { // 2.1 either last or current text is empty: add. // 2.2 last event doesn't have composing span: add. // Otherwise, merge. - final CharSequence text = event.getText(); final boolean textHasComposingSpan = event.getTextHasComposingSpan(); - - if (textHasComposingSpan && !mLastComposingSpan.isEmpty()) { - final Boolean lastEventHasComposingSpan = mLastComposingSpan.get(event.getId()); - if (lastEventHasComposingSpan != null && lastEventHasComposingSpan.booleanValue()) { - ContentCaptureEvent lastEvent = null; - for (int index = mEvents.size() - 1; index >= 0; index--) { - final ContentCaptureEvent tmpEvent = mEvents.get(index); - if (event.getId().equals(tmpEvent.getId())) { - lastEvent = tmpEvent; - break; - } + if (textHasComposingSpan) { + ContentCaptureEvent lastEvent = null; + for (int index = mEvents.size() - 1; index >= 0; index--) { + final ContentCaptureEvent tmpEvent = mEvents.get(index); + if (event.getId().equals(tmpEvent.getId())) { + lastEvent = tmpEvent; + break; } - if (lastEvent != null) { - final CharSequence lastText = lastEvent.getText(); - final boolean bothNonEmpty = !TextUtils.isEmpty(lastText) - && !TextUtils.isEmpty(text); - boolean equalContent = TextUtils.equals(lastText, text); - if (equalContent) { - addEvent = false; - } else if (bothNonEmpty && lastEventHasComposingSpan) { - lastEvent.mergeEvent(event); - addEvent = false; - } - if (!addEvent && sVerbose) { - Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text=" - + getSanitizedString(text)); - } + } + if (lastEvent != null && lastEvent.getTextHasComposingSpan()) { + final CharSequence lastText = lastEvent.getText(); + final boolean bothNonEmpty = !TextUtils.isEmpty(lastText) + && !TextUtils.isEmpty(text); + boolean equalContent = TextUtils.equals(lastText, text); + if (equalContent) { + addEvent = false; + } else if (bothNonEmpty) { + lastEvent.mergeEvent(event); + addEvent = false; + } + if (!addEvent && sVerbose) { + Log.v(TAG, "Buffering VIEW_TEXT_CHANGED event, updated text=" + + getSanitizedString(text)); } } } - mLastComposingSpan.put(event.getId(), textHasComposingSpan); } if (!mEvents.isEmpty() && eventType == TYPE_VIEW_DISAPPEARED) { @@ -586,7 +574,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession { ? Collections.EMPTY_LIST : new ArrayList<>(mEvents); mEvents.clear(); - mLastComposingSpan.clear(); return new ParceledListSlice<>(events); } @@ -717,7 +704,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession { // Since the same CharSequence instance may be reused in the TextView, we need to make // a copy of its content so that its value will not be changed by subsequent updates // in the TextView. - final String eventText = text == null ? null : text.toString(); + final CharSequence eventText = stringOrSpannedStringWithoutNoCopySpans(text); final boolean textHasComposingSpan = text instanceof Spannable && BaseInputConnection.getComposingSpanStart( (Spannable) text) >= 0; @@ -726,6 +713,16 @@ public final class MainContentCaptureSession extends ContentCaptureSession { .setAutofillId(id).setText(eventText, textHasComposingSpan))); } + private CharSequence stringOrSpannedStringWithoutNoCopySpans(CharSequence source) { + if (source == null) { + return null; + } else if (source instanceof Spanned) { + return new SpannableString(source, /* ignoreNoCopySpan= */ true); + } else { + return source.toString(); + } + } + /** Public because is also used by ViewRootImpl */ public void notifyViewInsetsChanged(int sessionId, @NonNull Insets viewInsets) { mHandler.post(() -> sendEvent(new ContentCaptureEvent(sessionId, TYPE_VIEW_INSETS_CHANGED)