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
-
+