diff options
| -rw-r--r-- | core/java/android/text/DynamicLayout.java | 35 | ||||
| -rw-r--r-- | core/java/android/text/flags/flags.aconfig | 7 | ||||
| -rw-r--r-- | core/java/android/widget/Editor.java | 8 |
3 files changed, 46 insertions, 4 deletions
diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index 7b9cb6afd6a0..928604983b70 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -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,8 +1277,21 @@ public class DynamicLayout extends Layout { } public void onSpanRemoved(Spannable s, Object o, int start, int end) { - if (o instanceof UpdateLayout) - transformAndReflow(s, start, end); + 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) { @@ -1287,8 +1301,21 @@ public class DynamicLayout extends Layout { // instead of causing an exception start = 0; } - transformAndReflow(s, start, end); - transformAndReflow(s, nstart, nend); + 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); + } } } diff --git a/core/java/android/text/flags/flags.aconfig b/core/java/android/text/flags/flags.aconfig index bf1a59625c93..6e45fea930d2 100644 --- a/core/java/android/text/flags/flags.aconfig +++ b/core/java/android/text/flags/flags.aconfig @@ -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" +} diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index ddcfb40e00ce..57d268ced6f4 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -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 = |