From 7840072317e0436b5b50e33d6f7d25f0349a297d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 9 May 2026 09:44:13 +0000 Subject: [PATCH 1/6] fix: add SDL3-CS to Linker.xml + AndroidLinkSkip to stop OsuGameActivity JNI activation crash Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/3e3e344a-127e-4c51-b475-cfaa53791766 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com> --- osu.Android.props | 13 +++++++ osu.Android/Linker.xml | 63 ++++++++++++++++------------------ osu.Android/OsuGameActivity.cs | 16 ++++++--- 3 files changed, 54 insertions(+), 38 deletions(-) diff --git a/osu.Android.props b/osu.Android.props index 5c20ca86fc6b..db49b3d40316 100644 --- a/osu.Android.props +++ b/osu.Android.props @@ -112,6 +112,19 @@ we make it explicit so a future SDK bump cannot silently start stripping IL and reproduce the trim-then-AOT crash class we removed above. --> false + + $(AndroidLinkSkip);osu.Framework.Android;SDL3-CS diff --git a/osu.Android/Linker.xml b/osu.Android/Linker.xml index 3325da1c3c4f..5618e5b60223 100644 --- a/osu.Android/Linker.xml +++ b/osu.Android/Linker.xml @@ -67,13 +67,24 @@ Shader attribute scanning, TextureLoaderStore fallback chain, bindable system, resource store extension routing — all reflection-dependent. osu.Framework.Android: Android-specific host, input handling, surface wrappers. - AndroidGameActivity carries the (IntPtr, JniHandleOwnership) JNI-activation - constructor and RegisterAttribute-driven type-binding needed for all derived - Activity/Fragment types. Without preserve="all", ILLink will trim these - constructors (they are only reachable via JNI, not through any managed call - graph), causing TypeManager.Activate to throw NotSupportedException: + AndroidGameActivity is the abstract base of OsuGameActivity but does NOT declare + its own (IntPtr, JniHandleOwnership) JNI-activation constructor — that constructor + lives on its SDLActivity grandparent (in the SDL3-CS assembly, listed below). + Without preserve="all", ILLink trims reflection-only members such as + RegisterAttribute-driven type-binding and generated JNI glue — none of which have + a managed call-graph path. + SDL3-CS (ppy.SDL3-CS): Contains Org.Libsdl.App.SDLActivity, the Java-binding class + from which AndroidGameActivity (and transitively OsuGameActivity) inherits. + SDLActivity's JNI-activation constructors — in particular the + (IntPtr, JniHandleOwnership) overload used by TypeManager.Activate to wrap the + freshly-created Android Activity Java object in a managed peer — are never called + from managed code, so ILLink has no static call-graph path to them and strips them + under AndroidLinkMode=Full. The resulting crash is exactly the "Could not activate JNI Handle ... as managed type 'osu.Android.OsuGameActivity'" - at startup. + NotSupportedException seen in the v2026.508.226 and v2026.508.228 field logs. + (The v2026.508.228 fix added osu.Framework.Android to Linker.xml and a + [DynamicDependency] on OsuGameActivity() but missed SDL3-CS entirely, because the + assumption was that AndroidGameActivity carried the JNI ctor — it does not.) ppy.Veldrid.SPIRV: SPIR-V cross-compiler; dynamically loads shader reflector types. (NuGet package ID and assembly name are both ppy.Veldrid.SPIRV — no mismatch.) @@ -84,38 +95,24 @@ NuGet package ID → CLR assembly name (AssemblyName in csproj) ppy.osu.Framework → osu.Framework ppy.osu.Framework.Android → osu.Framework.Android + ppy.SDL3-CS → SDL3-CS ppy.Veldrid.SPIRV → ppy.Veldrid.SPIRV (same — no ppy. mismatch here) - Using the NuGet package ID instead of the assembly name causes the preserve rule - to be stored but never matched: ILLink looks for an assembly named - "ppy.osu.Framework.Android" in the link set, finds only "osu.Framework.Android", - skips preservation, and freely trims the JNI-activation constructor from - AndroidGameActivity. The resulting startup crash ("Could not activate JNI Handle - ... as managed type 'osu.Android.OsuGameActivity'") is exactly what was reported - in the v2026.508.225 field log. + Using the NuGet package ID instead of the CLR assembly name causes the preserve rule + to be stored but never matched. - NOTE: osu.Framework and osu.Framework.Android originate from net10.0 NuGet + NOTE: osu.Framework, osu.Framework.Android, and SDL3-CS originate from NuGet packages and are not visible in ILLink's assembly search path at descriptor- - processing time. ILLink therefore emits warning IL2007 ("Could not resolve - assembly") for each entry. This warning is BENIGN and EXPECTED: ILLink stores - the preserve="all" rule in its internal table even when it cannot resolve the - assembly immediately. When the assembly is later encountered during the trimming - pass (where the .NET Android SDK does include it in the link set), ILLink finds - the stored rule and preserves the assembly in full. Removing these entries - "to silence the warnings" allows ILLink to freely trim JNI-only constructors - from AndroidGameActivity, crashing the app on launch. - - ADDITIONAL DEFENCE (v2026.508.228+): OsuGameActivity carries a [DynamicDependency] - attribute that explicitly roots AndroidGameActivity's constructors from the - osu.Android assembly. Because osu.Android is unambiguously preserve="all" and is - always resolvable at descriptor-processing time, ILLink processes this root - reference before it can trim the JNI-activation constructor, regardless of whether - the IL2007-deferred rule for osu.Framework.Android is honoured. This supersedes - the v2026.508.227 approach (explicit OsuGameActivity(IntPtr, JniHandleOwnership) - constructor) which did not compile because AndroidGameActivity does not expose an - explicit (IntPtr, JniHandleOwnership) constructor — only its SDLActivity grandparent - does, and C# base() invocations resolve only against the direct parent class. --> + processing time, causing IL2007 ("Could not resolve assembly") for each entry. + In theory ILLink stores the rule for later application; in practice the deferred + mechanism has proven unreliable with ILLink 10.0.x + NuGet-resolved assemblies + (evidenced by the v2026.508.228 field crash being identical to v2026.508.226 despite + these entries being present). The primary protection is therefore AndroidLinkSkip + in osu.Android.props, which bypasses ILLink entirely for these assemblies; these + Linker.xml entries and the [DynamicDependency] attributes on OsuGameActivity serve + as secondary and tertiary backstops respectively. --> + - + + + NU1902 + From bc3c98ede5f903a2f2dd6e9adf297c2642e841b0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 9 May 2026 10:04:40 +0000 Subject: [PATCH 3/6] =?UTF-8?q?chore:=20update=20SharpCompress=200.47.3=20?= =?UTF-8?q?=E2=86=92=200.48.0,=20remove=20obsolete=20NU1902=20suppression?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/29c65f29-ab61-4fc1-8533-85179a4caf15 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com> --- osu.Game/osu.Game.csproj | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index b1d79ef0a450..15eea8db21b1 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -51,13 +51,7 @@ - - - - NU1902 - + From 2fcc72e68695fe5470d57739d6a5cc730c066586 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 9 May 2026 10:12:19 +0000 Subject: [PATCH 4/6] chore: update all dependencies across codebase and workflows Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/d5f7d66b-e601-4c64-8929-91a628166bc5 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- Directory.Build.props | 2 +- .../osu.Game.Rulesets.EmptyFreeform.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 4 ++-- ...osu.Game.Rulesets.EmptyScrolling.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Pippidon.Tests.csproj | 4 ++-- osu.Android/osu.Android.csproj | 2 +- osu.Desktop/osu.Desktop.csproj | 4 ++-- osu.Game.Benchmarks/osu.Game.Benchmarks.csproj | 2 +- .../osu.Game.Rulesets.Catch.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Mania.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Osu.Tests.iOS.csproj | 2 +- .../osu.Game.Rulesets.Osu.Tests.csproj | 4 ++-- .../osu.Game.Rulesets.Taiko.Tests.csproj | 4 ++-- .../osu.Game.Tests.Android.csproj | 2 +- osu.Game.Tests.iOS/osu.Game.Tests.iOS.csproj | 2 +- osu.Game.Tests/osu.Game.Tests.csproj | 4 ++-- .../osu.Game.Tournament.Tests.csproj | 4 ++-- osu.Game/osu.Game.csproj | 16 ++++++++-------- osu.iOS/osu.iOS.csproj | 2 +- 20 files changed, 38 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 556441b4b48a..cc787db7a51d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -106,7 +106,7 @@ jobs: exit $exit_code - name: InspectCode - uses: JetBrains/ReSharper-InspectCode@v0.12 + uses: JetBrains/ReSharper-InspectCode@v0.13 with: tool-version: 2026.1.0.1 # this is WTF tier but if you don't specify *both* of these the defaults assume `build: true` diff --git a/Directory.Build.props b/Directory.Build.props index 607ee1ed9e33..587085384613 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -20,7 +20,7 @@ - + diff --git a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj index b671686c89aa..a9bb1e73643a 100644 --- a/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj +++ b/Templates/Rulesets/ruleset-empty/osu.Game.Rulesets.EmptyFreeform.Tests/osu.Game.Rulesets.EmptyFreeform.Tests.csproj @@ -9,8 +9,8 @@ false - - + + diff --git a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 796f182a2561..e9529b4328c2 100644 --- a/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -9,8 +9,8 @@ false - - + + diff --git a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj index 2ff812335eac..dd2186a7eaad 100644 --- a/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-empty/osu.Game.Rulesets.EmptyScrolling.Tests/osu.Game.Rulesets.EmptyScrolling.Tests.csproj @@ -9,8 +9,8 @@ false - - + + diff --git a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj index 796f182a2561..e9529b4328c2 100644 --- a/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj +++ b/Templates/Rulesets/ruleset-scrolling-example/osu.Game.Rulesets.Pippidon.Tests/osu.Game.Rulesets.Pippidon.Tests.csproj @@ -9,8 +9,8 @@ false - - + + diff --git a/osu.Android/osu.Android.csproj b/osu.Android/osu.Android.csproj index 26f147124053..66bb1a80a764 100644 --- a/osu.Android/osu.Android.csproj +++ b/osu.Android/osu.Android.csproj @@ -18,7 +18,7 @@ - + - + diff --git a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj index b2170ee51027..fe4ca4c79233 100644 --- a/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj +++ b/osu.Game.Benchmarks/osu.Game.Benchmarks.csproj @@ -8,7 +8,7 @@ - + diff --git a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj index 388802aaaa22..016868d2742d 100644 --- a/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj +++ b/osu.Game.Rulesets.Catch.Tests/osu.Game.Rulesets.Catch.Tests.csproj @@ -1,8 +1,8 @@  - - + + diff --git a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj index 315c1662b4e9..e9e5d0a18375 100644 --- a/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj +++ b/osu.Game.Rulesets.Mania.Tests/osu.Game.Rulesets.Mania.Tests.csproj @@ -1,8 +1,8 @@  - - + + diff --git a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj index c2f34683a4bd..6aa9e6fa9b17 100644 --- a/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj +++ b/osu.Game.Rulesets.Osu.Tests.iOS/osu.Game.Rulesets.Osu.Tests.iOS.csproj @@ -18,7 +18,7 @@ - + diff --git a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj index e259e9847f9e..c3515c87754e 100644 --- a/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj +++ b/osu.Game.Rulesets.Osu.Tests/osu.Game.Rulesets.Osu.Tests.csproj @@ -1,9 +1,9 @@  - + - + diff --git a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj index ae742a661343..f5f7c0e6c182 100644 --- a/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj +++ b/osu.Game.Rulesets.Taiko.Tests/osu.Game.Rulesets.Taiko.Tests.csproj @@ -1,8 +1,8 @@  - - + + diff --git a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj index fe55f652bfc5..c453b14b3b3f 100644 --- a/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj +++ b/osu.Game.Tests.Android/osu.Game.Tests.Android.csproj @@ -29,7 +29,7 @@ - + - + - - + + diff --git a/osu.iOS/osu.iOS.csproj b/osu.iOS/osu.iOS.csproj index 3d897f0ef0f7..2b81c0e7b554 100644 --- a/osu.iOS/osu.iOS.csproj +++ b/osu.iOS/osu.iOS.csproj @@ -20,7 +20,7 @@ - + From b7decbe4a87f8a22e91c92cedb3330ca9c858550 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 9 May 2026 10:13:33 +0000 Subject: [PATCH 5/6] chore: fix stale framework version comment in osu.Game.csproj Agent-Logs-Url: https://github.com/winnerspiros/osu/sessions/d5f7d66b-e601-4c64-8929-91a628166bc5 Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com> --- osu.Game/osu.Game.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/osu.Game.csproj b/osu.Game/osu.Game.csproj index a64cf62aa0d6..7fb0ae1ff102 100644 --- a/osu.Game/osu.Game.csproj +++ b/osu.Game/osu.Game.csproj @@ -41,7 +41,7 @@ - +