Hello, I'm using the new `GraphicsLayer` API from ...
# compose-android
l
Hello, I'm using the new
GraphicsLayer
API from Compose UI 1.7.0-beta02, and on API 28, I get this crash quite often when I call
drawLayer
from a
DrawScope
provided by the
record
function of another `GraphicsLayer`:
Copy code
java.lang.IllegalArgumentException: Only add dependencies during a tracking
	at androidx.compose.ui.graphics.InlineClassHelperKt.throwIllegalArgumentException(InlineClassHelper.kt:26)
	at androidx.compose.ui.graphics.layer.ChildLayerDependenciesTracker.onDependencyAdded(ChildLayerDependenciesTracker.kt:149)
	at androidx.compose.ui.graphics.layer.GraphicsLayer.addSubLayer(AndroidGraphicsLayer.android.kt:437)
	at androidx.compose.ui.graphics.layer.GraphicsLayer.draw$ui_graphics_release(AndroidGraphicsLayer.android.kt:551)
	at androidx.compose.ui.graphics.layer.GraphicsLayerKt.drawLayer(GraphicsLayer.kt:52)
Any clue at what could be the cause?
n
Do you have a reproducible sample? And/or is there a big filed for this already?
l
I can reproduce it only in my non open-source project…
Extracting the code that reproduces it is very hard, is there another way to help on understanding what causes this issue?
n
Are there any instances of the same GraphicsLayer instances being recorded multiple times within a single record block?
l
Shouldn't be possible
What I'm doing, however, is that I'm drawing the recorded
GraphicsLayer
conditionnally, and it seems to crash just after that condition switches
I mean that there's an
if
in front of my call to
drawLayer
n
Cc @Andrey Kulikov I vaguely recall we added some tests to verify conditional tracking usages for ref counting.
Are there specific platform versions or devices that you can repro on or is it consistent for all OS versions
l
And when the condition becomes
true
, a
derivedStateOf
is accessed, which then leads to the 2 `GraphicsLayer`s being recorded if needed, with one being drawn into the other
Only on API 28 so far
I've tried only one device, I can try another if there are suspicions it would be device specific
n
Emulator would be a helpful data point as well for API 28
l
BTW, this isn't the first issue I see with API 28 when it comes to drawing layers within layers
The other one I saw might be easier to reproduce. Basically, I had some content in a non-offscreen layer being drawn into an offscreen layer. On API 28, nothing gets drawn.
Might be 2 sides of the same coin
n
If you can share repros that would be great
l
That specific issue was reproduced on 2 different API 28 devices
Still tricky to extract the code, but basically you get something like this pseudo-code:
Copy code
val firstLayer = rememberGraphicsLayerAsState { layer ->
    layer.record {
        drawCoolStuff()
    }
}
val secondLayer = rememberGraphicsLayerAsState { layer ->
    layer.compositingStrategy = CompositingStrategy.Offscreen
    val l = firstLayer.get()
    layer.record {
        drawLayer(l)
    }
}
Canvas(…) {
    drawLayer(secondLayer)
}
rememberGraphicsLayerAsState
is some custom code I wrote to get a
SizeDependentState<GraphicsLayer>
, on which I can call
get()
when I'm in another
SizeDependentState.Scope
like the lambda passed to
rememberGraphicsLayerAsState
, or a
DrawScope
. It's using
derivedStateOf
+ states for the size and density/fontScale under the hood.
There's probably a way to write the reproducer using just
rememberGraphicsLayer()
without that. If you struggle to, I can share a Kotlin file that contains all that's needed to have
rememberGraphicsLayerAsState
work.
That wouldn't be too hard for me to do, and I can write a complete reproducer along with it, in 2 Kotlin files
t
For the record with beta 2 https://issuetracker.google.com/issues/343750859 had to revert.
👀 2
z
@Tolriq Did reverting to beta01 solve that issue for you? 👀
t
I did not revert to beta 1 but to a snapshot I know works relatively well (But hve issues on some devices with missing layers....) I think beta 1 is safe if you do not use the font loader else it's ANR prone. Or maybe it was another bug for beta 1 and the ANR was introduced later don't recall, but be careful and test, 1.7 have quite some issues with each time the fix leading to something else.
z
I ended up publishing a release with beta01 again, only 600 installs thus far but no crashes (hope I dont jinx it by saying this). Ill comment if it shows up there too!
t
Beta 1 still have the ANRs https://issuetracker.google.com/issues/339670487, and maybe some missing layers too, try to move the app to background, open a few other app, return and see if there's issues.
z
No issues with that, but not even with the beta02 release.. my phone is just bad at reproducing bugs
a
hey! let’s not mix all the issues in one thread, it is hard to follow this way. and they are not related to each other in most cases. please file separate bugs for crashes with different error message
1
regarding “Only add dependencies during a tracking” the contract is that during layer.record { }. this layer is added as a “parent layer” into a draw scope object this lambda is executed with: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/ui/ui-graphics/src/commonMain/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope.kt;l=300;drc=dcaa116fbfda77e64a319e1668056ce3b032469f. then when we draw another layer during the record call of the parent layer this layer is added into its parent so we properly track which layer depend on another one: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]android.kt;l=539;drc=dcaa116fbfda77e64a319e1668056ce3b032469f
with that, I am not really sure how do you manage to make it crash, when used as intended it shouldn’t happen, and we didn’t have reports with such error message from users of compose ui. it seems like in your custom usage you do something differently. do you use
DrawScope.draw(..., graphicsLayer = ...)
somewhere directly? or do you save the DrawScope object you get from
layer.record { ... }
lamba somewhere in order to use it later?
l
The only trick I'm doing is providing my own GraphicsLayerContext with a View that is added to the WindowManager, while not drawing into that hierarchy, but drawing into another Surface backed Canvas
n
@louiscad is it possible your implementation is attempting to draw the same GraphicsLayer into different destinations on different threads?
l
AFAIK, all the drawing operations happen on the main thread, and so does the crash @Nader Jawad
213 Views