Fixed
Status Update
Comments
jb...@google.com <jb...@google.com>
lo...@gmail.com <lo...@gmail.com> #2
Looking into this. It's not clear from looking at the code how this can happen. There are two IDs used as tags:
<item type="id" name="metricsStateHolder"/>
<item type="id" name="metricsDelegator"/>
These are assigned unique values at build time. As long as they are only ever used to assign objects of the correct type with those tags, there shouldn't be the kind of classCast exception seen above, and the assignments look correct, eg:
metricsStateHolder = Holder()
rootView.setTag(R.id.metricsStateHolder, metricsStateHolder)
and
delegator = DelegatingFrameMetricsListener(delegates)
decorView.setTag(R.id.metricsDelegator, delegator)
Logging shows ids are indeed unique and off by one, eg:
2131230959, 2131230958
Still investigating
<item type="id" name="metricsStateHolder"/>
<item type="id" name="metricsDelegator"/>
These are assigned unique values at build time. As long as they are only ever used to assign objects of the correct type with those tags, there shouldn't be the kind of classCast exception seen above, and the assignments look correct, eg:
metricsStateHolder = Holder()
rootView.setTag(R.id.metricsStateHolder, metricsStateHolder)
and
delegator = DelegatingFrameMetricsListener(delegates)
decorView.setTag(R.id.metricsDelegator, delegator)
Logging shows ids are indeed unique and off by one, eg:
2131230959, 2131230958
Still investigating
ap...@google.com <ap...@google.com> #3
Looks like a race condition. The two keys can be used from different threads: the main thread and the FrameMetricsAggregator thread. SparseArray (used by View tags) is not thread safe, so it is theoretically possible for some of the same items in the array to be used by different threads. The API doesn't make that obvious, since different tags should be sorted with different keys, but since it's not thread safe, the same item may be manipulated by two threads in parallel, thus resulting in ill-defined results like what we're seeing here. I'm not able to repro the issue directly in JankStats, but I am able to create such a situation using SparseArray directly, so it seems like this is probably the root cause.
We synchronize access to some structures in JankStats already for other potential race conditions; we should be able to similarly protect access to the tags array for use between threads.
We synchronize access to some structures in JankStats already for other potential race conditions; we should be able to similarly protect access to the tags array for use between threads.
cl...@google.com <cl...@google.com> #4
The main culprit (called out in that stack trace) was the call to get the state holder from the FrameMetricsAggregator thread. This is only done to remove SingleFrameStates after processing a frame, but there's a simpler way to do that during frame processing code directly, without needing to access the tags from a non-UI thread.
There are various other calls to getTag/setTag that have been modified to ensure they are called from the UI thread, so things should be more solid (in an upcoming fix).
There are various other calls to getTag/setTag that have been modified to ensure they are called from the UI thread, so things should be more solid (in an upcoming fix).
lo...@gmail.com <lo...@gmail.com> #5
Happened to me as well.
According to datadog a user clicked a deeplink that navigates into our app.
java.lang.ClassCastException: com.xxx.ui.main.MainActivity cannot be cast to androidx.metrics.performance.PerformanceMetricsState$Holder
at androidx.metrics.performance.PerformanceMetricsState$Companion.getHolderForHierarchy(Unknown Source:27)
at androidx.metrics.performance.a.onFrameMetricsAvailable(Unknown Source:162)
at android.view.FrameMetricsObserver.onFrameMetricsAvailable(FrameMetricsObserver.java:59)
at android.graphics.HardwareRendererObserver.lambda$notifyDataAvailable$0$HardwareRendererObserver(HardwareRendererObserver.java:93)
at android.graphics.HardwareRendererObserver$$ExternalSyntheticLambda0.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:980)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loopOnce(Looper.java:238)
at android.os.Looper.loop(Looper.java:357)
at android.os.HandlerThread.run(HandlerThread.java:85)
According to datadog a user clicked a deeplink that navigates into our app.
java.lang.ClassCastException: com.xxx.ui.main.MainActivity cannot be cast to androidx.metrics.performance.PerformanceMetricsState$Holder
at androidx.metrics.performance.PerformanceMetricsState$Companion.getHolderForHierarchy(Unknown Source:27)
at androidx.metrics.performance.a.onFrameMetricsAvailable(Unknown Source:162)
at android.view.FrameMetricsObserver.onFrameMetricsAvailable(FrameMetricsObserver.java:59)
at android.graphics.HardwareRendererObserver.lambda$notifyDataAvailable$0$HardwareRendererObserver(HardwareRendererObserver.java:93)
at android.graphics.HardwareRendererObserver$$ExternalSyntheticLambda0.run(Unknown Source:2)
at android.os.Handler.handleCallback(Handler.java:980)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loopOnce(Looper.java:238)
at android.os.Looper.loop(Looper.java:357)
at android.os.HandlerThread.run(HandlerThread.java:85)
cl...@google.com <cl...@google.com> #6
Is there any update on this issue? I can see pending code changes linked to this bug, but they are not yet merged (seems like CR is hanging without any action for a few months already).
Description
Component used: Navigation Version used: 2.7.7 - success 2.8.0 - failed 2.8.5 - failed 2.9.0-alpha04 - failed
Devices/Android versions reproduced on: tested API 30, 33. i think any affected
Sample project to trigger the issue. in the attachments
A screenrecord or screenshots showing the issue (if UI related). in the attachments
Issue: wildcard segment in deep link stopped work as expected since 2.8.0 and till latest 2.9.0-alpha04
spent ~2 days to understand the reason!!! when examples from internet work, but my app - not.