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

Commit b6db54ac authored by Haoyu Zhang's avatar Haoyu Zhang Committed by Android (Google) Code Review
Browse files

Merge "Fix: insert mode crash when delete" into main

parents a8d0e2bd 97edc8f2
Loading
Loading
Loading
Loading
+31 −4
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import android.util.Pools.SynchronizedPool;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
import com.android.text.flags.Flags;

import java.lang.ref.WeakReference;

@@ -1276,9 +1277,22 @@ public class DynamicLayout extends Layout {
        }

        public void onSpanRemoved(Spannable s, Object o, int start, int end) {
            if (o instanceof UpdateLayout)
            if (o instanceof UpdateLayout) {
                if (Flags.insertModeCrashWhenDelete()) {
                    final DynamicLayout dynamicLayout = mLayout.get();
                    if (dynamicLayout != null && dynamicLayout.mDisplay instanceof OffsetMapping) {
                        // It's possible that a Span is removed when the text covering it is
                        // deleted, in this case, the original start and end of the span might be
                        // OOB. So it'll reflow the entire string instead.
                        reflow(s, 0, 0, s.length());
                    } else {
                        reflow(s, start, end - start, end - start);
                    }
                } else {
                    transformAndReflow(s, start, end);
                }
            }
        }

        public void onSpanChanged(Spannable s, Object o, int start, int end, int nstart, int nend) {
            if (o instanceof UpdateLayout) {
@@ -1287,10 +1301,23 @@ public class DynamicLayout extends Layout {
                    // instead of causing an exception
                    start = 0;
                }
                if (Flags.insertModeCrashWhenDelete()) {
                    final DynamicLayout dynamicLayout = mLayout.get();
                    if (dynamicLayout != null && dynamicLayout.mDisplay instanceof OffsetMapping) {
                        // When text is changed, it'll also trigger onSpanChanged. In this case we
                        // can't determine the updated range in the transformed text. So it'll
                        // reflow the entire range instead.
                        reflow(s, 0, 0, s.length());
                    } else {
                        reflow(s, start, end - start, end - start);
                        reflow(s, nstart, nend - nstart, nend - nstart);
                    }
                } else {
                    transformAndReflow(s, start, end);
                    transformAndReflow(s, nstart, nend);
                }
            }
        }

        private WeakReference<DynamicLayout> mLayout;
        private OffsetMapping.TextUpdate mTransformedTextUpdate;
+7 −0
Original line number Diff line number Diff line
@@ -89,3 +89,10 @@ flag {
  description: "Feature flag for clearing focus when the escape key is pressed."
  bug: "312921137"
}

flag {
  name: "insert_mode_crash_when_delete"
  namespace: "text"
  description: "A feature flag for fixing the crash while delete text in insert mode."
  bug: "314254153"
}
+8 −0
Original line number Diff line number Diff line
@@ -148,6 +148,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.internal.view.FloatingActionMode;
import com.android.text.flags.Flags;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -2343,6 +2344,13 @@ public class Editor {
     */
    void invalidateTextDisplayList(Layout layout, int start, int end) {
        if (mTextRenderNodes != null && layout instanceof DynamicLayout) {
            if (Flags.insertModeCrashWhenDelete()
                    && mTextView.isOffsetMappingAvailable()) {
                // Text is transformed with an OffsetMapping, and we can't know the changed range
                // on the transformed text. Invalidate the all display lists instead.
                invalidateTextDisplayList();
                return;
            }
            final int startTransformed =
                    mTextView.originalToTransformed(start, OffsetMapping.MAP_STRATEGY_CHARACTER);
            final int endTransformed =