ADFA-4327: Stop mem-usage chart LegendRenderer crash (disable legend)#1417
ADFA-4327: Stop mem-usage chart LegendRenderer crash (disable legend)#1417fryanpan wants to merge 1 commit into
Conversation
c4a99e7 to
464fdea
Compare
On-device verification — Samsung A56 (Android 16)Built CoGo v8 debug with this fix (
Result: across all three daemon-connect cycles —
This is the runtime counterpart to the green |
|
MPAndroidChart's LegendRenderer threw IndexOutOfBoundsException when its auto-computed legend desynced from the dataset count as that count changed at runtime (Gradle daemons connecting -> resetMemUsageChart rebuilds the datasets with a new count). Keep the legend visible (no UI removal; replaces the earlier legend.isEnabled = false approach) and set its entries EXPLICITLY via legend.setCustom(...) in both resetMemUsageChart and the live-update listener, so the renderer never lazily recomputes a stale entry list against a changed count. The entry builder is a top-level internal fun (buildMemUsageLegendEntries) so it is unit-testable without an Activity. Test: MemUsageLegendEntriesTest (Robolectric) pins the anti-desync invariant - one entry per dataset, label/color carried through, and the entry count tracking the dataset count across a count change. The literal draw-time IndexOutOfBoundsException is a race inside the third-party renderer, verified on-device (recording on the PR). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
464fdea to
dbffc52
Compare
Jira Ticket: https://appdevforall.atlassian.net/browse/ADFA-4327
Sentry Issue: https://appdevforall-inc-9p.sentry.io/issues/APPDEVFORALL-31
Reproduction Details
The editor's live memory-usage chart (MPAndroidChart) crashes in
LegendRenderer.renderLegendwith anIndexOutOfBoundsExceptionwhen the chart's dataset count changes at runtime — a Gradle daemon/tooling process connects,resetMemUsageChartrebuilds theLineDatawith a new dataset count, and the auto-computed legend then renders against a stale/desynced entry array.Stack Trace
(repro device: moto g56, device.class: high, Android 16 — not limited to low-end)
User Steps
User steps leading up to crash, based on Sentry breadcrumbs:
MainActivity→EditorActivityKt). As the editor loads and the mem-usage chart updates (Gradle daemon connecting → dataset count grows), the legend renders out of bounds during a draw pass.Was able to reproduce in a unit test?
Yes — the fix's invariant is unit-tested.
MemUsageLegendEntriesTest(Robolectric, 3/3 green) asserts the legend entries always match the datasets: one entry per dataset, label/color carried through, and the entry count tracking the dataset count across a 1→3 change (the exact condition that desynced the renderer). The literal draw-timeIndexOutOfBoundsExceptionis a race inside the third-party renderer that is not deterministically reproducible on the JVM, so it is verified on-device (see Testing).What Was Fixed
Keep the legend visible and set its entries explicitly so MPAndroidChart never lazily re-computes a stale entry list when the dataset count changes — this handles dataset item-length changes without disabling the legend:
buildMemUsageLegendEntries(datasets)builds oneLegendEntryper dataset (label + line color).legend.setCustom(...)is called with those entries inresetMemUsageChart(when the dataset count changes) and in the live-update listener (so the"<name> - <MB>"labels stay current) — keeping the legend's entry list always consistent with the datasets.The legend remains fully functional; nothing is hidden from the user.
Testing
MemUsageLegendEntriesTest(Robolectric) — 3/3 green (:app:testV8DebugUnitTest).:app:assembleDebug— each connects the Gradle daemon (the dataset-count change that crashed pre-fix). NoLegendRenderer/IndexOutOfBoundsException/ FATAL in logcat, app stayed alive, and the chart's legend renders correctly (screenshot + recording on the PR).Fixes APPDEVFORALL-31