Status Update
Comments
kl...@google.com <kl...@google.com> #2
Also doesn't work in AS 2024.3.2 Canary 4 and Compose 1.8.0-beta01
as...@google.com <as...@google.com> #3
Andrei: Is this the same as
zo...@gmail.com <zo...@gmail.com> #4
Triage notes: Needs investigation. Assigning for later.
as...@google.com <as...@google.com> #5
Could you share the AppScaffoldTopBar
function that fails here? This seems different from
es...@weversecompany.com <es...@weversecompany.com> #6
bu...@gmail.com <bu...@gmail.com> #7
sure i can paste more source. let me see what I can give you. do you need internals or externals?
as...@google.com <as...@google.com> #8
The bug with Xiaomi devices should be fixed in 2023.09.02 (see
er...@gmail.com <er...@gmail.com> #9
I experienced this crash on Android TV, when calling requestFocus() on a FocusRequester in a callback from a library, which internally uses Handler(Looper.getMainLooper()) to call the callback. I cannot reproduce this, it happened to me only once.
[Deleted User] <[Deleted User]> #10
The thing is that SnapshotStateObserver calls in tests are usually wrapped in runOnUiThread, for example here ui-test-android-1.6.8-sources.jar!/commonMain/androidx/compose/ui/test/TestOwner.kt:81
But in some cases the test framework does not switch to mainThread.
I patched the SnapshotStateObserver bytecode to save the stacks of both threads that entered it.
Based on the resulting stacks, I see that the test framework calls SnapshotStateObserver from the test thread, while laout was requested on the main thread, which also provokes a call to SnapshotStateObserver
Stacks:
```
Caused by: java.lang.Exception: Multithreaded access caught!!!
at company.package.ComposeInterceptorsKt.checkObserveReadsBefore(ComposeInterceptors.kt:33) <--- my bytecode pach to save stacktrace
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:262) <--- reads on main thread
<...>
at androidx.compose.ui.platform.AndroidComposeView.forceMeasureTheSubtree(AndroidComposeView.android.kt:993)
<...>
at androidx.compose.ui.platform.AndroidComposeView.onMeasure(AndroidComposeView.android.kt:1058)
<...>
at android.view.View.layout(View.java:22844) <--- relayout request
<...>
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.app.ActivityThread.main(ActivityThread.java:7656) <--- main thread
<...>
```
```
Caused by: java.lang.Exception: First access thread stack trace
at dalvik.system.VMStack.getThreadStackTrace(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:1736)
at company.package.ComposeInterceptorsKt.checkObserveReadsBefore(ComposeInterceptors.kt:36) <--- my bytecode pach to save stacktrace
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:262) <--- reads on test thread
<...>
at androidx.compose.ui.semantics.SemanticsNodeKt.SemanticsNode(SemanticsNode.kt:48)
at androidx.compose.ui.semantics.SemanticsNode.getParent(SemanticsNode.kt:354) <--- maybe problem here, no switch to main thread
<...>
at androidx.compose.ui.test.SemanticsSelector.map(SemanticsSelector.kt:54)
<...>
at io.github.kakaocup.compose.node.core.BaseNode.assertIsDisplayed(BaseNode.kt:15)
<...>
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2205) <--- test thread
<...>
```
as...@google.com <as...@google.com> #11
Thanks for investigating this!
The observation above is valid, it seems like we only call getAllSemanticsNodes
on the UI thread but selectors can also result in a remeasure request and similar failure. I think we need to make sure that fetchSemanticsNodes
is also executed on the UI thread for this to work correctly.
ap...@google.com <ap...@google.com> #12
Project: platform/frameworks/support
Branch: androidx-main
Author: Ralston Da Silva <
Link:
Revert "Semantics Listener Interface"
Expand for full commit details
Revert "Semantics Listener Interface"
This reverts commit b17c30917d12d1dd8729a980c5662ee839fd08b1.
Reason for revert: Reverting due to b/374823219 and possibly b/319395743
Change-Id: Id412218da77b7b9fe76da9427732861cc087ad1d
Files:
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/HitPathTrackerTest.kt
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/input/pointer/PointerInputEventProcessorTest.kt
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/layout/Helpers.kt
- M
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/node/NodeChainTester.kt
- D
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/semantics/SemanticsInfoTest.kt
- D
compose/ui/ui/src/androidInstrumentedTest/kotlin/androidx/compose/ui/semantics/SemanticsListenerTest.kt
- M
compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/autofill/AndroidAutofillManager.android.kt
- M
compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeView.android.kt
- M
compose/ui/ui/src/androidMain/kotlin/androidx/compose/ui/platform/AndroidComposeViewAccessibilityDelegateCompat.android.kt
- M
compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/LayoutNodeTest.kt
- M
compose/ui/ui/src/androidUnitTest/kotlin/androidx/compose/ui/node/ModifierLocalConsumerEntityTest.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/LayoutNode.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeChain.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/NodeCoordinator.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/Owner.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/node/SemanticsModifierNode.kt
- D
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsInfo.kt
- D
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsListener.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsNode.kt
- M
compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/semantics/SemanticsOwner.kt
Hash: 8fc9d69a618b8eca966c1d887b2c854c0a9d274a
Date: Wed Oct 23 18:37:39 2024
ap...@google.com <ap...@google.com> #13
Project: platform/frameworks/support
Branch: androidx-main
Author: Andrei Shikov <
Link:
Force SemanticsSelector#map to be always called on the main thread
Expand for full commit details
Force SemanticsSelector#map to be always called on the main thread
Some actions such as SemanticsNode#parent might cause synchronous remeasure on bg thread which should not happen.
Bug: 319395743
Change-Id: Ice1cd463088e4fbf024d0cf6f120de760f28ccd3
Files:
- M
compose/ui/ui-test/src/commonMain/kotlin/androidx/compose/ui/test/SemanticsNodeInteraction.kt
Hash: 11efee13094ad33f5d64c4dd273381d775cc0608
Date: Tue Oct 22 18:15:23 2024
je...@google.com <je...@google.com> #14
SemanticsNode.parent()
is also called from a few other places, with the same problem. I'll file another bug for those.
Are there any more properties of SemanticsNode
that are thread unsafe?
je...@google.com <je...@google.com> #15
I'm just rereading the description and as observed before in
Of course that doesn't make the analysis in
za...@squareup.com <za...@squareup.com> #16
We are seeing what looks like this issue cause flakes in a bunch of our tests. Would it be possible to release the test fixes above in a 1.7 dot release?
Description
Jetpack Compose component used: ?
Android Studio Build: Jellyfish Canary 3
Kotlin version: 1.9.21
This showed up in crashlytics the other day. Its happened 2 times, for 2 unique user, out of ~17 000 users with the same release. My application is 100% jetpack compose, including using it in an overlay (windowManager.addView).
Related slack discussion ->
Stack trace (if applicable):
Fatal Exception: java.lang.IllegalArgumentException: Detected multithreaded access to SnapshotStateObserver: previousThreadId=167), currentThread={id=2, name=main}. Note that observation on multiple threads in layout/draw is not supported. Make sure your measure/layout/draw for each Owner (AndroidComposeView) is executed on the same thread.
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:241)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.java:1613)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.java:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release(LayoutNode.java:1144)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release$default(LayoutNode.java:1135)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:509)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.onlyRemeasureIfScheduled(MeasureAndLayoutDelegate.kt:593)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtreeInternal(MeasureAndLayoutDelegate.kt:619)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.forceMeasureTheSubtree(MeasureAndLayoutDelegate.kt:582)
at androidx.compose.ui.platform.AndroidComposeView.forceMeasureTheSubtree(AndroidComposeView.android.kt:993)
at androidx.compose.ui.node.Owner.forceMeasureTheSubtree$default(Owner.java:239)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:632)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release(LayoutNode.java:1144)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:354)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureOnly(MeasureAndLayoutDelegate.kt:557)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureOnly(MeasureAndLayoutDelegate.kt:407)
at androidx.compose.ui.platform.AndroidComposeView.onMeasure(AndroidComposeView.android.kt:1058)
at android.view.View.measure(View.java:26207)
at androidx.compose.ui.platform.AbstractComposeView.internalOnMeasure$ui_release(ComposeView.android.kt:302)
at androidx.compose.ui.platform.AbstractComposeView.onMeasure(ComposeView.android.kt:289)
at android.view.View.measure(View.java:26207)
at androidx.compose.ui.viewinterop.AndroidViewHolder.onMeasure(AndroidViewHolder.android.kt:242)
at android.view.View.measure(View.java:26207)
at androidx.compose.ui.viewinterop.AndroidViewHolder$layoutNode$1$5.measure-3p2s80s(AndroidViewHolder.android.kt:397)
at androidx.compose.ui.node.InnerNodeCoordinator.measure-BRTryo0(InnerNodeCoordinator.kt:126)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.java:252)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$performMeasureBlock$1.invoke(LayoutNodeLayoutDelegate.java:251)
at androidx.compose.runtime.snapshots.Snapshot$Companion.observe(Snapshot.java:2303)
at androidx.compose.runtime.snapshots.SnapshotStateObserver$ObservedScopeMap.observe(SnapshotStateObserver.kt:500)
at androidx.compose.runtime.snapshots.SnapshotStateObserver.observeReads(SnapshotStateObserver.kt:256)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeReads$ui_release(OwnerSnapshotObserver.kt:133)
at androidx.compose.ui.node.OwnerSnapshotObserver.observeMeasureSnapshotReads$ui_release(OwnerSnapshotObserver.kt:113)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.performMeasure-BRTryo0(LayoutNodeLayoutDelegate.java:1613)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate.access$performMeasure-BRTryo0(LayoutNodeLayoutDelegate.java:36)
at androidx.compose.ui.node.LayoutNodeLayoutDelegate$MeasurePassDelegate.remeasure-BRTryo0(LayoutNodeLayoutDelegate.kt:620)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release(LayoutNode.java:1144)
at androidx.compose.ui.node.LayoutNode.remeasure-_Sx5XlM$ui_release$default(LayoutNode.java:1135)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.doRemeasure-sdFAvZA(MeasureAndLayoutDelegate.kt:356)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded(MeasureAndLayoutDelegate.kt:509)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.remeasureAndRelayoutIfNeeded$default(MeasureAndLayoutDelegate.kt:486)
at androidx.compose.ui.node.MeasureAndLayoutDelegate.measureAndLayout(MeasureAndLayoutDelegate.kt:377)
at androidx.compose.ui.platform.AndroidComposeView.measureAndLayout(AndroidComposeView.android.kt:971)
at androidx.compose.ui.node.Owner.measureAndLayout$default(Owner.java:228)
at androidx.compose.ui.platform.AndroidComposeView.dispatchDraw(AndroidComposeView.android.kt:1224)
at android.view.View.draw(View.java:23016)
at android.view.View.updateDisplayListIfDirty(View.java:21880)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4526)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4499)
at android.view.View.updateDisplayListIfDirty(View.java:21833)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4526)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4499)
at android.view.View.updateDisplayListIfDirty(View.java:21833)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4526)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4499)
at android.view.View.updateDisplayListIfDirty(View.java:21833)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4526)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4499)
at android.view.View.updateDisplayListIfDirty(View.java:21833)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:534)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:542)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:625)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:4645)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4363)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3474)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2265)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9009)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1142)
at android.view.Choreographer.doCallbacks(Choreographer.java:946)
at android.view.Choreographer.doFrame(Choreographer.java:875)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1127)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:210)
at android.os.Looper.loop(Looper.java:299)
at android.app.ActivityThread.main(ActivityThread.java:8250)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:556)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1045)