diff --git a/osu.Android.props b/osu.Android.props index b5e3114266ac..797ba69f0b49 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -46,11 +46,20 @@ managed paths (the JIT no longer needs to tier them up at runtime, and Mono's profiled AOT covers framework/game hot loops including draw-thread Schedulers, bindable propagation, and the texture upload path). - * PublishTrimmed stays OFF — re-enabling it requires explicitly rooting every - reflection-using assembly (osu.Game, rulesets, Realm, Newtonsoft.Json, - AutoMapper, Sentry, OsuTK, Microsoft.CSharp, ppy.Veldrid.SPIRV …) and running - with SuppressTrimAnalysisWarnings=false to surface gaps before shipping. That - is a separate, larger PR. + * PublishTrimmed stays OFF — the .NET ILLink trimmer is driven exclusively + through AndroidLinkMode=Full + osu.Android/Linker.xml (see below). + Setting PublishTrimmed=true in addition would double-run ILLink with + automatic root discovery, re-introducing the risk of silent reflection + gaps this approach was designed to eliminate. + * AndroidLinkMode=Full (replacing the previous SdkOnly). Full enables + ILLink across all assemblies, not just Mono.Android.dll. Compared to + SdkOnly this additionally strips unused BCL types, ~80% of NUnit bulk, + and unreachable types in pure-algorithmic utility libs. + osu.Android/Linker.xml supplies a curated preserve="all" list for every + assembly that uses runtime reflection — implementing "manual trim": we + review and own the preserve list rather than letting the trimmer auto- + discover reflection roots. See Linker.xml for per-assembly rationale. + When a new reflection-using package is added, add it to Linker.xml. * AndroidEnableMarshalMethods stays OFF (see PropertyGroup above) — silent SIGSEGV with current interop on .NET 10 Android. * Server GC is enabled for Release: workstation GC's STW pauses on the Update/ @@ -60,11 +69,7 @@ the cost of ~20-30% extra resident memory. Mono Android has supported this since .NET 8; ppy/osu desktop already uses it. Concurrent GC is the .NET default but we set it explicitly so Server GC runs in the background mode - rather than blocking foreground. - - To re-enable trimming in the future, reintroduce it on its own, root every - reflection-using assembly explicitly, and run with SuppressTrimAnalysisWarnings=false - to surface the gaps before shipping. --> + rather than blocking foreground. --> @@ -74,32 +79,30 @@ none false + profiles. Methods outside the profile remain JIT-compiled at runtime. Preserved + assemblies (see Linker.xml) are fully present, so a profile-miss falls back to JIT + instead of throwing MissingMethodException. --> true true true - - SdkOnly - + + Full + false - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher.png b/osu.Android/Resources/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a1f717cf6c41..000000000000 Binary files a/osu.Android/Resources/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png deleted file mode 100644 index 36651206e8c7..000000000000 Binary files a/osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.webp b/osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.webp new file mode 100644 index 000000000000..72f467eb46ec Binary files /dev/null and b/osu.Android/Resources/mipmap-hdpi/ic_launcher_foreground.webp differ diff --git a/osu.Android/Resources/mipmap-mdpi/ic_launcher.png b/osu.Android/Resources/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index c68ed7a2d558..000000000000 Binary files a/osu.Android/Resources/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png deleted file mode 100644 index 85f308442952..000000000000 Binary files a/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.webp b/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.webp new file mode 100644 index 000000000000..c656c1622684 Binary files /dev/null and b/osu.Android/Resources/mipmap-mdpi/ic_launcher_foreground.webp differ diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png b/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 28be07512ad6..000000000000 Binary files a/osu.Android/Resources/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png deleted file mode 100644 index 613b817f0a54..000000000000 Binary files a/osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.webp b/osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.webp new file mode 100644 index 000000000000..8f50e77e2103 Binary files /dev/null and b/osu.Android/Resources/mipmap-xhdpi/ic_launcher_foreground.webp differ diff --git a/osu.Android/Resources/mipmap-xxhdpi/ic_launcher.png b/osu.Android/Resources/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index 4330a939d9f1..000000000000 Binary files a/osu.Android/Resources/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png deleted file mode 100644 index ec7d60283808..000000000000 Binary files a/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.webp b/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.webp new file mode 100644 index 000000000000..d319fcbe4fe0 Binary files /dev/null and b/osu.Android/Resources/mipmap-xxhdpi/ic_launcher_foreground.webp differ diff --git a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher.png b/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 2e722ee884f6..000000000000 Binary files a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png b/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png deleted file mode 100644 index f22db0c61680..000000000000 Binary files a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.png and /dev/null differ diff --git a/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.webp b/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.webp new file mode 100644 index 000000000000..dd80d8c76a88 Binary files /dev/null and b/osu.Android/Resources/mipmap-xxxhdpi/ic_launcher_foreground.webp differ diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 27f27ff0359e..26f147124053 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -40,4 +40,12 @@ + + + + diff --git a/osu.Game/Resources/README.md b/osu.Game/Resources/README.md index 4f42b7512b61..eba34a20087d 100644 --- a/osu.Game/Resources/README.md +++ b/osu.Game/Resources/README.md @@ -24,7 +24,9 @@ That means you can keep call sites unchanged and still serve a compressed local **AVIF vs WebP**: AVIF is tried first because it offers better compression than WebP at equal quality (attractive for large backgrounds/splash art). WebP is the safe fallback because it is supported everywhere. The framework's `TextureLoaderStore` applies the same AVIF-first order with ImageSharp capability checking, so AVIF will be silently skipped on any platform where ImageSharp cannot decode it. -**⚠️ Do NOT generate AVIF for PNG files with alpha channels (e.g. font atlases, UI sprites)**: `libsvtav1` encodes only yuv420p and silently strips the alpha channel, producing a tiny (~350 byte) but completely blank/solid output. `libaom-av1` would preserve alpha via yuva420p but is extremely slow and AVIF alpha support is inconsistent on Android. Use WebP for all PNG assets — WebP lossless perfectly preserves alpha. AVIF is only safe for JPEG-sourced images (no alpha channel) and even then savings over WebP are marginal. +**⚠️ Do NOT generate AVIF for PNG files with alpha channels (e.g. font atlases, UI sprites)**: `libsvtav1` encodes only yuv420p and silently strips the alpha channel, producing a tiny (~350 byte) but completely blank/solid output. Use WebP for all PNG assets that carry transparency — WebP lossless perfectly preserves alpha. + +For PNG files **without** an alpha channel, AVIF is safe and is tried alongside WebP; the smaller of the two (that passes the SSIM threshold) is kept. The optimizer uses `ffprobe` to detect whether a PNG has an alpha channel before attempting AVIF. Example: diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index 08412032bd54..1cd55ef7e46e 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -38,7 +38,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - +