Status Update
Comments
je...@google.com <je...@google.com>
lo...@gmail.com <lo...@gmail.com> #2
1. Have you saw crash in real device or only in simulators?
2. Do you use dynamic feature for language ID?
ad...@google.com <ad...@google.com> #3
Tested on Android 12 Emulator with custom executor, but cannot repro this issue.
lo...@gmail.com <lo...@gmail.com> #4
-
Second crash in the description is from a real device. Experienced it myself on two different Xiaomi phones, plus lots of crashes from users in the Google Play console.
-
Dynamic features are not used in the application.
As a wild guess, I have downgraded build tools from 31.0.0 to 30.0.3, compileSdk from 31 to 30, and moved all work with Language ID to the service in a separate process (just to be sure that crash can kill secondary process instead of main). This combination is in beta for 2 days by now and I don't see any SIGSEGV crashes.
ap...@google.com <ap...@google.com> #5
Hmm, I feel the crash might be something related to separate/secondary process.
I also changed compileSdk and targetSDK to 31 but still cannot repro this issue.
lo...@gmail.com <lo...@gmail.com> #6
On the contrary, there was no separate process before, when crashes started.
In the new build (with the aforementioned changes) I can see SIGSEGV crash, but only one instead of dozens and it has a bit different backtrace:
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
liblanguage_id_jni.so (offset 0x11e000)
backtrace:
#00 pc 000000000003c7c0 /data/app/azagroup.reedy-mF7zTu2bv_ELlbFArwNgqA==/split_config.arm64_v8a.apk!lib/arm64-v8a/liblanguage_id_jni.so (offset 0x11e000)
#00 pc 000000000003b960 /data/app/azagroup.reedy-mF7zTu2bv_ELlbFArwNgqA==/split_config.arm64_v8a.apk!lib/arm64-v8a/liblanguage_id_jni.so (offset 0x11e000)
#00 pc 000000000003bb48 /data/app/azagroup.reedy-mF7zTu2bv_ELlbFArwNgqA==/split_config.arm64_v8a.apk!lib/arm64-v8a/liblanguage_id_jni.so (offset 0x11e000)
#00 pc 000000000003bafc /data/app/azagroup.reedy-mF7zTu2bv_ELlbFArwNgqA==/split_config.arm64_v8a.apk!lib/arm64-v8a/liblanguage_id_jni.so (offset 0x11e000)
#00 pc 0000000000036c98 /data/app/azagroup.reedy-mF7zTu2bv_ELlbFArwNgqA==/split_config.arm64_v8a.apk!lib/arm64-v8a/liblanguage_id_jni.so (offset 0x11e000)
#00 pc 0000000000032714 /data/app/azagroup.reedy-mF7zTu2bv_ELlbFArwNgqA==/split_config.arm64_v8a.apk!lib/arm64-v8a/liblanguage_id_jni.so (offset 0x11e000)
#00 pc 0000000000031cac /data/app/azagroup.reedy-mF7zTu2bv_ELlbFArwNgqA==/split_config.arm64_v8a.apk!lib/arm64-v8a/liblanguage_id_jni.so (offset 0x11e000)
#00 pc 0000000000057438 /data/app/azagroup.reedy-mF7zTu2bv_ELlbFArwNgqA==/oat/arm64/base.odex (offset 0x57000)
Description
Hello,
I found a bug that cost me one day to understand what triggers it, and I want to thank Adam Powell for helping me a bit to figure out what's going on.
TL;DR
In short, if you call
setContentView
with the same view hierarchy a second time after the initial render, the composables in the hierarchy will stop recomposing, which breaks/freezes everything in them.Jetpack Compose release version: 1.1.0-alpha02 (also reproduces with 1.0 and 1.0.1)
Android Studio Build: irrelevant
Kotlin version: irrelevant
Reproducer
I attached a self-contained Kotlin file (
MainActivity.kt
) that reproduces the issue.You can paste it in any Compose project over the existing
MainActivity
and try yourself.However, I put below reproducing steps anyway.
Steps to Reproduce:
ComposeView
that displays aState
that changes over time.setContentView
passing that instance in theonCreate
function of the hostComponentActivity
.lifecycleScope
awaitFrame()
, ordelay(1500)
setContentView
again, with the very same instance of theComposeView
created earlier.Expected outcome
The composable keeps display the updates of the
State
instance.Actual result
Once the
setContentView
is called the second time, the composable stops displaying the updates of theState
instance.The Slack thread from start to finish
If you want to see what was the process from facing the issue, to finding why it happened, you can take a look at this thread on Kotlin's Slack:
What is likely the culprit IMHO
In the Android platform, the
setContentView
method inActivity
is idempotent. Calling it a second time with the same view hierarchy while the Activity is not in the destroyed state will have no effect.However, that contract seems to have been broken by the
ComponentActivity
class from AndroidX, as it's also calling a function namedinitViewTreeOwners()
.The name of that function indicates that it's been designed for initialization, something which by definition, is supposed to happen only once. However, a setter doesn't generally have such constraints, at least, not because it's a setter (as the
setContentView
function is).I think that this
initViewTreeOwners()
function being called again is what messes upComposeView
or its underlying mechanisms, putting them in a state they should not be in.However, the issue might not be in
ComponentActivity
itself, but in the Compose runtime, or both.Thanks for reading, and have a great day!
Louis CAD