Illustrations are decoded at 4× — ship them in density buckets #41
Labels
No Label
P0
P1
P2
release-blocker
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: null/Privacy-Period-Tracker#41
Loading…
Reference in New Issue
No description provided.
Delete Branch "%!s(<nil>)"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
A live memory defect, present before any artwork change and made much worse by one.
What is true now
core/designsystem/src/main/res/has exactly two folders —drawable/anddrawable-night/— with no density qualifier on either. Android therefore treats every illustration as mdpi and pre-scales it at decode time by the device's density bucket.On an xxxhdpi device that is a 4× upscale:
art_forecast.webpat 552 × 480 decodes to roughly 2208 × 1920, which is about 17 MB for a single ARGB_8888 bitmap. The app declares noandroid:largeHeap, and a non-large heap can be as low as 96–192 MB.The contrast is instructive: the launcher icon is correctly bucketed across
mipmap-mdpithroughmipmap-xxxhdpi. The illustrations are not bucketed at all.What it costs
Today it is survivable because each screen shows one illustration and the sources are small. It stops being survivable the moment the artwork ships at the higher source resolution a full-bleed hero needs — and
OnboardingPreviews.ktalready stacks all eight in one preview.This is also the error-handling story. There is no
try/catch, no fallback, no image-loading library and no error boundary anywhere in the app:painterResourcedecodes inside composition, so an OOM or a decode failure throws on the onboarding screen — on first launch, before the user has seen anything. ArunCatchingaround a resource compiled into the APK would hide the failure rather than remove it; sizing the bitmaps correctly removes it.What to do
drawable-hdpi,-xhdpi,-xxhdpi,-xxxhdpiand their-nighttwins from the masters, and delete the density-less copies.Traps
drawable/still resolves as the mdpi fallback and will be picked on any device whose bucket you missed.isShrinkResources = trueon release will drop unreferenced density variants, so check the release APK rather than only the debug one.Why filed separately
It is a defect that exists today and is worth fixing whether or not the artwork is ever redrawn.
Verify:
core/designsystem/src/main/res/contains no density-lessdrawable/illustration,dumpsys meminfoonPeriodMinSdk26shows no growth beyond the stated budget while stepping through onboarding, and the whole flow completes on the API 26 device without a crash.Shipped in
ae27ef6. Four density buckets per theme (617/822/1233/1644 px) and the density-less drawable/ folders are gone, so nothing is decoded at the mdpi assumption any more — that was ~17 MB of heap for one bitmap on an xxxhdpi device. 2.3 MB across every bucket; the release is an AAB and Play splits by density, so a device downloads 130-500 KB. Also the error-handling fix: painterResource decodes inside composition with no boundary anywhere, so correct sizing removes the OOM rather than hiding it. Driven on PeriodMinSdk26 with no crash or OOM.