Status Update
Comments
ma...@google.com <ma...@google.com>
je...@google.com <je...@google.com> #2
rocess: com.candybytes.danger, PID: 19211
10-07 07:50:27.310: E/AndroidRuntime(19211): java.lang.IndexOutOfBoundsException: offset(93) should be less than line limit(92)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.text.TextLine.measure(TextLine.java:389)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.text.Layout.getHorizontal(Layout.java:1246)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.text.Layout.getHorizontal(Layout.java:1222)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.text.Layout.getPrimaryHorizontal(Layout.java:1192)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.text.Layout.getPrimaryHorizontal(Layout.java:1181)
10-07 07:50:27.310: E/AndroidRuntime(19211): at a2.g.a(SourceFile:101)
10-07 07:50:27.310: E/AndroidRuntime(19211): at a2.u0.f(SourceFile:10)
10-07 07:50:27.310: E/AndroidRuntime(19211): at z1.a.c(SourceFile:43)
10-07 07:50:27.310: E/AndroidRuntime(19211): at z1.v.b(SourceFile:42)
10-07 07:50:27.310: E/AndroidRuntime(19211): at androidx.compose.ui.platform.s$d.addExtraDataToAccessibilityNodeInfo(SourceFile:164)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.view.AccessibilityInteractionController.populateAccessibilityNodeInfoForView(AccessibilityInteractionController.java:430)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread(AccessibilityInteractionController.java:363)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.view.AccessibilityInteractionController.-$$Nest$mfindAccessibilityNodeInfoByAccessibilityIdUiThread(Unknown Source:0)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.view.AccessibilityInteractionController$PrivateHandler.handleMessage(AccessibilityInteractionController.java:1647)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.os.Handler.dispatchMessage(Handler.java:106)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.os.Looper.loopOnce(Looper.java:201)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.os.Looper.loop(Looper.java:288)
10-07 07:50:27.310: E/AndroidRuntime(19211): at android.app.ActivityThread.main(ActivityThread.java:7898)
10-07 07:50:27.310: E/AndroidRuntime(19211): at java.lang.reflect.Method.invoke(Native Method)
10-07 07:50:27.310: E/AndroidRuntime(19211): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
10-07 07:50:27.310: E/AndroidRuntime(19211): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:936)
je...@google.com <je...@google.com> #3
Exception java.lang.IndexOutOfBoundsException: offset(7) should be less than line limit(6)
at android.text.TextLine.measure (TextLine.java:353)
at android.text.Layout.getHorizontal (Layout.java:1213)
at android.text.Layout.getHorizontal (Layout.java:1190)
at android.text.Layout.getPrimaryHorizontal (Layout.java:1160)
at android.text.Layout.getPrimaryHorizontal (Layout.java:1149)
at ckl.d (ckl.java:1)
at ckl.a (ckl.java:38)
at clb.e (clb.java:1)
at cja.r (cja.java:7)
at cka.l (cka.java:5)
at cdl.addExtraDataToAccessibilityNodeInfo (cdl.java:15)
at android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchAccessibilityNodeInfos (AccessibilityInteractionController.java:1104)
at android.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread (AccessibilityInteractionController.java:342)
at android.view.AccessibilityInteractionController.access$400 (AccessibilityInteractionController.java:75)
at android.view.AccessibilityInteractionController$PrivateHandler.handleMessage (AccessibilityInteractionController.java:1460)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loop (Looper.java:223)
at android.app.ActivityThread.main (ActivityThread.java:7664)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:947)
me...@thomaskeller.biz <me...@thomaskeller.biz> #4
Exception java.lang.IndexOutOfBoundsException: offset(261) should be less than line limit(260)
at android.text.TextLine.measure (TextLine.java:389)
at android.text.Layout.getHorizontal (Layout.java:1246)
at android.text.Layout.getHorizontal (Layout.java:1222)
at android.text.Layout.getPrimaryHorizontal (Layout.java:1192)
at android.text.Layout.getPrimaryHorizontal (Layout.java:1181)
at androidx.compose.ui.text.android.LayoutHelper.getDownstreamHorizontal (LayoutHelper.kt:353)
at androidx.compose.ui.text.android.TextLayout.getLayoutHelper (TextLayout.kt:332)
at androidx.compose.ui.text.MultiParagraph.requireIndexInRange (MultiParagraph.java:750)
at androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat$MyNodeProvider.addExtraDataToAccessibilityNodeInfo (AndroidComposeViewAccessibilityDelegateCompat.android.kt)
at android.view.AccessibilityInteractionController.populateAccessibilityNodeInfoForView (AccessibilityInteractionController.java:430)
at android.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread (AccessibilityInteractionController.java:363)
at android.view.AccessibilityInteractionController.-$$Nest$mfindAccessibilityNodeInfoByAccessibilityIdUiThread (AccessibilityInteractionController.java)
at android.view.AccessibilityInteractionController$PrivateHandler.handleMessage (AccessibilityInteractionController.java:1647)
at android.os.Handler.dispatchMessage (Handler.java:106)
at android.os.Looper.loopOnce (Looper.java:201)
at android.os.Looper.loop (Looper.java:288)
at android.app.ActivityThread.main (ActivityThread.java:7898)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:548)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:936)
je...@google.com <je...@google.com> #5
Getting the same error on a OnePlus 8 Pro running Android 11:
java.lang.IndexOutOfBoundsException: offset(7) should be less than line limit(6)
android.text.TextLine.measure(TextLine.java:353)
android.text.Layout.getHorizontal(Layout.java:1213)
android.text.Layout.getHorizontal(Layout.java:1190)
android.text.Layout.getPrimaryHorizontal(Layout.java:1160)
android.text.Layout.getPrimaryHorizontal(Layout.java:1149)
androidx.compose.ui.text.android.LayoutHelper.getDownstreamHorizontal(LayoutHelper.java:90)
androidx.compose.ui.text.android.TextLayout.getPrimaryHorizontal(TextLayout.java:10)
androidx.compose.ui.text.android.TextLayout.getBoundingBox(TextLayout.java:41)
androidx.compose.ui.text.AndroidParagraph.getBoundingBox(AndroidParagraph.java:41)
androidx.compose.ui.text.MultiParagraph.getBoundingBox(MultiParagraph.java:40)
androidx.compose.ui.text.TextLayoutResult.getBoundingBox(TextLayoutResult.java:40)
androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.addExtraDataToAccessibilityNodeInfoHelper(AndroidComposeViewAccessibilityDelegateCompat.java:162)
androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat$MyNodeProvider.addExtraDataToAccessibilityNodeInfo(AndroidComposeViewAccessibilityDelegateCompat.java:162)
android.view.AccessibilityInteractionController$AccessibilityNodePrefetcher.prefetchAccessibilityNodeInfos(AccessibilityInteractionController.java:1104)
android.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread(AccessibilityInteractionController.java:342)
android.view.AccessibilityInteractionController$PrivateHandler.handleMessage(AccessibilityInteractionController.java:1460)
android.os.Handler.dispatchMessage(Handler.java:106)
android.os.Looper.loop(Looper.java:223)
android.app.ActivityThread.main(ActivityThread.java:7701)
java.lang.reflect.Method.invoke(Method.java:0)
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
me...@thomaskeller.biz <me...@thomaskeller.biz> #6
I am getting the same issue in firebase test lab; on Pixel 7 API 33. Unable to replicate it. Happens in a compose based ModalBottomSheetLayout with a parent Column, several child Rows and a LazyColumn that holds rows with text.
android.text.TextLine.measure (TextLine.java:389)
android.text.Layout.getHorizontal (Layout.java:1246)
android.text.Layout.getHorizontal (Layout.java:1222)
android.text.Layout.getPrimaryHorizontal (Layout.java:1192)
android.text.Layout.getPrimaryHorizontal (Layout.java:1181)
androidx.compose.ui.text.android.LayoutHelper.getDownstreamHorizontal (LayoutHelper.kt:353)
androidx.compose.ui.text.android.LayoutHelper.getHorizontalPosition (LayoutHelper.kt:236)
androidx.compose.ui.text.android.TextLayout.getPrimaryHorizontal (TextLayout.kt:503)
androidx.compose.ui.text.android.TextLayout.getBoundingBox (TextLayout.java:675)
androidx.compose.ui.text.AndroidParagraph.getBoundingBox (AndroidParagraph.android.kt:312)
androidx.compose.ui.text.MultiParagraph.getBoundingBox (MultiParagraph.java:488)
androidx.compose.ui.text.TextLayoutResult.getBoundingBox (TextLayoutResult.kt:527)
androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.addExtraDataToAccessibilityNodeInfoHelper (AndroidComposeViewAccessibilityDelegateCompat.java:1439)
androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat.access$addExtraDataToAccessibilityNodeInfoHelper (AndroidComposeViewAccessibilityDelegateCompat.java:117)
androidx.compose.ui.platform.AndroidComposeViewAccessibilityDelegateCompat$MyNodeProvider.addExtraDataToAccessibilityNodeInfo (AndroidComposeViewAccessibilityDelegateCompat.android.kt:2460)
android.view.AccessibilityInteractionController.populateAccessibilityNodeInfoForView (AccessibilityInteractionController.java:430)
android.view.AccessibilityInteractionController.findAccessibilityNodeInfoByAccessibilityIdUiThread (AccessibilityInteractionController.java:363)
android.view.AccessibilityInteractionController.-$$Nest$mfindAccessibilityNodeInfoByAccessibilityIdUiThread (AccessibilityInteractionController.java)
android.view.AccessibilityInteractionController$PrivateHandler.handleMessage (AccessibilityInteractionController.java:1647)
me...@thomaskeller.biz <me...@thomaskeller.biz> #7
We also started to receive this crash on error reports, after upgrading activity-compose
to 1.6.1.
Any update on this?
je...@google.com <je...@google.com> #8
Halil I vaguely remember that you fixed a similar issue recently or mentioned about it (a 1 off error for getHorizontalPosition).
Does this sound familiar?
java.lang.IndexOutOfBoundsException: measureLimit (120) is out of start (0) and limit (119) bounds
me...@thomaskeller.biz <me...@thomaskeller.biz> #9
Yes this is the same bug that we've investigated priorly. Both originate from AccessibilityDelegateCompat and use getBoundingBox
. The underlying issue is in the platform TextLayout but we can circumvent the issue by falling back to previous implementation for the last cursor position.
je...@google.com <je...@google.com> #10
I looked at this a bit more yesterday. Some of my findings include;
- This has always been buggy unfortunately. Previous getBoundingBox implementation also had a call to
getPrimaryHorizontal(offset)
that is the culprit from platform. getPrimaryHorizontal(offset)
always fails in a situation similar to following;- Text is ellipsized.
- Ellipsis region includes an LF character '\n'
- offset points to a character after this LF
- TextLine object in text layout is set with a start and limit on given text.
- Limit does not care about ellipsis but cares about LF characters. So, a text is always guaranteed to be partitioned into multiple lines in the existence of LF.
- Querying an ellipsized offset which would have been on a different line anyway causes a crash on TextLine since TextLine thinks that the given offset is out of bounds.
There is a comment in TextLayout.kt
that references a similar problem with platform text layout
ap...@google.com <ap...@google.com> #11
Is there a recommended work around for this? Our team is seeing a rather appreciable number of reports for this crash.
Thank you!
androidx.appcompat:appcompat:1.6.1
androidx.compose:compose-bom:2023.04.00
je...@google.com <je...@google.com>
me...@thomaskeller.biz <me...@thomaskeller.biz> #12
we are also interested in a fix or workaround for this.
Best regards!
Versions used:
- androidx.activity:activity-compose:1.6.0
- androidx.compose.ui:ui:1.3.3
- androidx.compose.ui:ui-text:1.3.3
me...@thomaskeller.biz <me...@thomaskeller.biz> #13
Branch: androidx-main
commit 9e49803f6ce45ec5a3a1899101485f13036c6432
Author: Halil Ozercan <halilibo@google.com>
Date: Wed May 10 17:23:14 2023
Fix getBoundingBox crashing for some ellipsized indices
This CL fixes a bug where getBoundingBox throws an index out of bounds error when the queried offset is in the ellipsized region and comes after a LINE_FEED(\n) character.
Additionally we are converging some exception types in AndroidParagraph to use `IllegalArgumentException` via `require` function, instead of `AssertionError`.
Fix:
Relnote: "`Paragraph` methods that used to throw `AssertionError` for out of bounds offsets now throw `IllegalArgumentException` as `MultiParagraph` does."
Test: :compose:ui:ui-text:cAT
Change-Id: I549d3ec936afbd941361690d1f16fadc4998670a
A compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationBoundingBoxTest.kt
M compose/ui/ui-text/src/androidAndroidTest/kotlin/androidx/compose/ui/text/ParagraphIntegrationTest.kt
M compose/ui/ui-text/src/androidMain/kotlin/androidx/compose/ui/text/AndroidParagraph.android.kt
M text/text/src/main/java/androidx/compose/ui/text/android/LayoutHelper.kt
je...@google.com <je...@google.com> #14
We have attempted a blind fix since we couldn't reproduce the issue with the exact stacktrace. However, we still have high confidence that this fix should address the original issue.
Top of the stacktrace in all reported cases is a very isolated path that tells us that all crashes were highly likely resulted from querying a bounding box in an ellipsized region of a text layout. Attempted fix solves this particular issue.
me...@thomaskeller.biz <me...@thomaskeller.biz> #15
me...@thomaskeller.biz <me...@thomaskeller.biz> #16
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.compose.ui:ui-text:1.6.0-alpha01
androidx.compose.ui:ui-text-android:1.6.0-alpha01
me...@thomaskeller.biz <me...@thomaskeller.biz> #17
I created a follow-up DialogFragment
-related crash.
ap...@google.com <ap...@google.com> #18
Branch: androidx-main
commit 0fa0145d802d8effe0e833f0fe996dbeec3ab23e
Author: Jelle Fresen <jellefresen@google.com>
Date: Thu Feb 24 14:40:50 2022
Disallow overwriting content with test content
This adds a check in AndroidComposeTest.setContent that makes sure that
the Activity on which the content is set doesn't have content yet. If
there is content already, it is a signal that the tester is probably
unintentionally doing something wrong, so help them by throwing.
Bug: 199631334
Test: ./gradlew bOS
Relnote: "`ComposeContentTestRule.setContent` will now throw an
IllegalStateException if you try to set content when there already is
content."
Change-Id: I888a5054c27d7884110415a812d0ac748be3f869
M compose/ui/ui-viewbinding/samples/src/androidTest/java/androidx/compose/ui/samples/FragmentRemoveTest.kt
M compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/BitmapCapturingTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/AndroidAccessibilityTest.kt
M compose/ui/ui-test-junit4/src/androidAndroidTest/kotlin/androidx/compose/ui/test/junit4/CustomActivityTest.kt
M compose/ui/ui/src/androidAndroidTest/kotlin/androidx/compose/ui/accessibility/CollectionInfoTest.kt
M compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/ClickTestRuleTest.kt
M compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/IsDisplayedTest.kt
M compose/ui/ui-test/src/androidAndroidTest/kotlin/androidx/compose/ui/test/ActivityWithActionBar.kt
M compose/ui/ui-test-junit4/src/androidMain/kotlin/androidx/compose/ui/test/ComposeTest.android.kt
Description
Previously with plain XML UIs, one was able to test ViewModel and UI (Fragment/Activity + XML) in combination. With Compose and the
AndroidComposeTestRule
this is no longer possible:AndroidComposeTestRule
needs a test rule that provides anActivity
to the underlying compose infrastructure, while one can give it aFragmentScenarioRule
the fragment part of this cannot actually be re-used and the content of the whole Activity is replaced by the Compose UI.ComposeView.setContent()
of theFragment
(orActivity
, for that matter) isn't run when theAndroidComposeTestRule
'ssetContent
is used instead. Even worse, depending on the lifecycle state in which anActivity
is in (in which state it is started), a previous rendering could or could not have happened, leading to possible side effects with an actualViewModel
interfacing implementation.ComposeView
is not the root view of the controller component.I understand that a special
Recomposer
setup and a lot of other custom tooling is needed to make Jetpack Compose testable in an Robolectric / Android Instrumentation test, however I wish the test architecture would first and foremost provide an API to hook in / replace the existing functionality, e.g. by making it easy to inject a custom test composer in a running fragment / activity instance or by at least making this composer and possibly other utilities available for certain testing purposes.