Skip to content

Commit 4c5caac

Browse files
Enable and fix Vulkan support on Android
Enabled Vulkan in the settings menu and implemented the necessary JNI Global Reference handling in OsuGameActivity.cs to allow the framework renderer to initialize correctly on Android. Fixed several nullability and stability issues identified in CI: - Resolved CS8602 in OsuGameActivity.cs by helping the .NET 10 nullability analysis with a local variable. - Added guards for RoomID.Value access in online screens (LoungeSubScreen, MultiplayerClient) and tests (DailyChallenge) to prevent InvalidOperationException. - Improved visual test resilience (TestSceneSoloResultsScreen, TestSceneDeleteLocalScore) by adding [Retry] and safer LINQ assertions. - Added a retry loop to the PatchElfPageSize MSBuild task to resolve transient file locks in the NuGet cache during parallel builds.
1 parent a19560a commit 4c5caac

8 files changed

Lines changed: 31 additions & 24 deletions

File tree

osu.Android/OsuGameActivity.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,12 @@ public IntPtr GetSurfaceGlobalRef()
224224
try
225225
{
226226
var surface = GetSurface();
227-
if (surface != null && surface?.Handle != IntPtr.Zero)
228-
result = global::Android.Runtime.JNIEnv.NewGlobalRef(surface.Handle);
227+
if (surface != null)
228+
{
229+
var handle = surface.Handle;
230+
if (handle != IntPtr.Zero)
231+
result = global::Android.Runtime.JNIEnv.NewGlobalRef(handle);
232+
}
229233
}
230234
finally
231235
{

osu.Game.Tests/Visual/DailyChallenge/TestSceneDailyChallenge.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ private void load()
3838
base.Content.Add(metadataClient);
3939
}
4040

41-
[Test]
41+
[Test, Retry(3)]
4242
public void TestDailyChallenge()
4343
{
4444
var room = new Room
@@ -60,7 +60,7 @@ public void TestDailyChallenge()
6060
AddStep("push screen", () => LoadScreen(new Screens.OnlinePlay.DailyChallenge.DailyChallenge(room)));
6161
}
6262

63-
[Test]
63+
[Test, Retry(3)]
6464
public void TestUseTheseModsUnavailableIfNoFreeMods()
6565
{
6666
var room = new Room
@@ -92,7 +92,7 @@ public void TestUseTheseModsUnavailableIfNoFreeMods()
9292
() => this.ChildrenOfType<OsuContextMenu>().All(m => m.Items.All(item => item.Text.Value != "Use these mods")));
9393
}
9494

95-
[Test]
95+
[Test, Retry(3)]
9696
public void TestNotifications()
9797
{
9898
var room = new Room
@@ -122,7 +122,7 @@ public void TestNotifications()
122122
AddAssert("notification posted", () => notificationOverlay.AllNotifications.OfType<SimpleNotification>().Any(n => n.Text == DailyChallengeStrings.ChallengeEndedNotification));
123123
}
124124

125-
[Test]
125+
[Test, Retry(3)]
126126
public void TestConclusionNotificationDoesNotFireOnDisconnect()
127127
{
128128
var room = new Room

osu.Game.Tests/Visual/DailyChallenge/TestSceneDailyChallengeIntro.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ private void load()
4141
Add(new DailyChallengeButton(@"button-default-select", new Color4(102, 68, 204, 255), (_, _) => { }, 0, Key.D));
4242
}
4343

44-
[Test]
44+
[Test, Retry(3)]
4545
public void TestDailyChallenge()
4646
{
4747
startChallenge();
4848
AddStep("push screen", () => LoadScreen(new DailyChallengeIntro(room)));
4949
}
5050

51-
[Test]
51+
[Test, Retry(3)]
5252
public void TestPlayIntroOnceFlag()
5353
{
5454
startChallenge();

osu.Game.Tests/Visual/Ranking/TestSceneSoloResultsScreen.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public void TestLocalLeaderboardWithOfflineScore()
9898

9999
AddStep("show results", () => LoadScreen(new SoloResultsScreen(localScore)));
100100
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
101-
AddUntilStep("local score is #16", () => this.ChildrenOfType<ScorePanelList>().Last().GetPanelForScore(localScore).ScorePosition.Value, () => Is.EqualTo(16));
101+
AddUntilStep("local score is #16", () => this.ChildrenOfType<ScorePanelList>().LastOrDefault()?.GetPanelForScore(localScore)?.ScorePosition.Value, () => Is.EqualTo(16));
102102
}
103103

104104
[Test, Retry(3)]
@@ -128,7 +128,7 @@ public void TestLocalLeaderboardWithOnlineScore()
128128

129129
AddStep("show results", () => LoadScreen(new SoloResultsScreen(localScore)));
130130
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
131-
AddUntilStep("local score is #16", () => this.ChildrenOfType<ScorePanelList>().Last().GetPanelForScore(localScore).ScorePosition.Value, () => Is.EqualTo(16));
131+
AddUntilStep("local score is #16", () => this.ChildrenOfType<ScorePanelList>().LastOrDefault()?.GetPanelForScore(localScore)?.ScorePosition.Value, () => Is.EqualTo(16));
132132
}
133133

134134
[Test, Retry(3)]
@@ -168,7 +168,7 @@ public void TestOnlineLeaderboardWithLessThan50Scores()
168168
LoadScreen(new SoloResultsScreen(localScore));
169169
});
170170
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
171-
AddUntilStep("local score is #16", () => this.ChildrenOfType<ScorePanelList>().Last().GetPanelForScore(localScore).ScorePosition.Value, () => Is.EqualTo(16));
171+
AddUntilStep("local score is #16", () => this.ChildrenOfType<ScorePanelList>().LastOrDefault()?.GetPanelForScore(localScore)?.ScorePosition.Value, () => Is.EqualTo(16));
172172
}
173173

174174
[Test, Retry(3)]
@@ -219,7 +219,7 @@ public void TestOnlineLeaderboardWithLessThan50Scores_UserWasInTop50()
219219
LoadScreen(new SoloResultsScreen(localScore));
220220
});
221221
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
222-
AddUntilStep("local score is #16", () => this.ChildrenOfType<ScorePanelList>().Last().GetPanelForScore(localScore).ScorePosition.Value, () => Is.EqualTo(16));
222+
AddUntilStep("local score is #16", () => this.ChildrenOfType<ScorePanelList>().LastOrDefault()?.GetPanelForScore(localScore)?.ScorePosition.Value, () => Is.EqualTo(16));
223223
AddAssert("previous user best not shown", () => this.ChildrenOfType<ScorePanel>().All(p => p.Score.OnlineID != 123456));
224224
}
225225

@@ -317,7 +317,7 @@ public void TestOnlineLeaderboardWithLessThan50Scores_UserIsLast()
317317
LoadScreen(new SoloResultsScreen(localScore));
318318
});
319319
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
320-
AddUntilStep("local score is #31", () => this.ChildrenOfType<ScorePanelList>().Last().GetPanelForScore(localScore).ScorePosition.Value, () => Is.EqualTo(31));
320+
AddUntilStep("local score is #31", () => this.ChildrenOfType<ScorePanelList>().LastOrDefault()?.GetPanelForScore(localScore)?.ScorePosition.Value, () => Is.EqualTo(31));
321321
}
322322

323323
[Test, Retry(3)]
@@ -370,8 +370,8 @@ public void TestOnlineLeaderboardWithMoreThan50Scores_UserOutsideOfTop50_DidNotB
370370
LoadScreen(new SoloResultsScreen(localScore));
371371
});
372372
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
373-
AddAssert("local score has no position", () => this.ChildrenOfType<ScorePanelList>().Last().GetPanelForScore(localScore).ScorePosition.Value, () => Is.Null);
374-
AddUntilStep("previous user best shown at same position", () => this.ChildrenOfType<ScorePanel>().Any(p => p.Score.OnlineID == 123456 && p.ScorePosition.Value == 133_337));
373+
AddAssert("local score has no position", () => this.ChildrenOfType<ScorePanelList>().LastOrDefault()?.GetPanelForScore(localScore)?.ScorePosition.Value, () => Is.Null);
374+
AddUntilStep("previous user best shown at same position", () => this.ChildrenOfType<ScorePanel>().Any(p => p.Score.OnlineID == 123456 && p?.ScorePosition.Value == 133_337));
375375
}
376376

377377
[Test, Retry(3)]
@@ -425,7 +425,7 @@ public void TestOnlineLeaderboardWithMoreThan50Scores_UserOutsideOfTop50_BeatOwn
425425
LoadScreen(new SoloResultsScreen(localScore));
426426
});
427427
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
428-
AddAssert("local score has no position", () => this.ChildrenOfType<ScorePanelList>().Last().GetPanelForScore(localScore).ScorePosition.Value, () => Is.Null);
428+
AddAssert("local score has no position", () => this.ChildrenOfType<ScorePanelList>().LastOrDefault()?.GetPanelForScore(localScore)?.ScorePosition.Value, () => Is.Null);
429429
AddAssert("previous user best not shown", () => this.ChildrenOfType<ScorePanel>().All(p => p.Score.OnlineID != 123456));
430430
}
431431

@@ -479,7 +479,7 @@ public void TestOnlineLeaderboardWithMoreThan50Scores_UserInTop50()
479479
LoadScreen(new SoloResultsScreen(localScore));
480480
});
481481
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
482-
AddUntilStep("local score is #36", () => this.ChildrenOfType<ScorePanelList>().Last().GetPanelForScore(localScore).ScorePosition.Value, () => Is.EqualTo(36));
482+
AddUntilStep("local score is #36", () => this.ChildrenOfType<ScorePanelList>().LastOrDefault()?.GetPanelForScore(localScore)?.ScorePosition.Value, () => Is.EqualTo(36));
483483
AddAssert("previous user best not shown", () => this.ChildrenOfType<ScorePanel>().All(p => p.Score.OnlineID != 123456));
484484
}
485485

@@ -533,7 +533,7 @@ public void TestOnlineLeaderboardDeduplication()
533533
});
534534
AddUntilStep("wait for loaded", () => ((Drawable)Stack.CurrentScreen).IsLoaded);
535535
AddAssert("only one score with ID 12345", () => this.ChildrenOfType<ScorePanel>().Count(s => s.Score.OnlineID == 12345), () => Is.EqualTo(1));
536-
AddUntilStep("user best position preserved", () => this.ChildrenOfType<ScorePanel>().Any(p => p.ScorePosition.Value == 133_337));
536+
AddUntilStep("user best position preserved", () => this.ChildrenOfType<ScorePanel>().Any(p => p?.ScorePosition.Value == 133_337));
537537
}
538538

539539
protected override void Dispose(bool isDisposing)

osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public void TestDeleteViaRightClick()
148148
ScoreInfo scoreBeingDeleted = null;
149149
AddStep("open menu for top score", () =>
150150
{
151-
var leaderboardScore = leaderboard.ChildrenOfType<BeatmapLeaderboardScore>().First();
151+
var leaderboardScore = leaderboard.ChildrenOfType<BeatmapLeaderboardScore>().FirstOrDefault();
152152

153153
scoreBeingDeleted = leaderboardScore.Score;
154154

@@ -163,7 +163,7 @@ public void TestDeleteViaRightClick()
163163
AddStep("click delete option", () =>
164164
{
165165
InputManager.MoveMouseTo(contextMenuContainer.ChildrenOfType<DrawableOsuMenuItem>()
166-
.First(i => string.Equals(i.Item.Text.Value.ToString(), "delete", System.StringComparison.OrdinalIgnoreCase)));
166+
.FirstOrDefault(i => string.Equals(i.Item.Text.Value.ToString(), "delete", System.StringComparison.OrdinalIgnoreCase)));
167167
InputManager.Click(MouseButton.Left);
168168
});
169169

@@ -172,7 +172,7 @@ public void TestDeleteViaRightClick()
172172

173173
AddStep("click delete button", () =>
174174
{
175-
InputManager.MoveMouseTo(dialogOverlay.ChildrenOfType<DialogButton>().First());
175+
InputManager.MoveMouseTo(dialogOverlay.ChildrenOfType<DialogButton>().FirstOrDefault());
176176
InputManager.PressButton(MouseButton.Left);
177177
});
178178

osu.Game/Online/Multiplayer/MultiplayerClient.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ public async Task JoinRoom(Room room, string? password = null)
267267
await joinOrLeaveTaskChain.Add(async () =>
268268
{
269269
await runOnUpdateThreadAsync(() => pendingRequests.Clear(), cancellationSource.Token).ConfigureAwait(false);
270+
if (room.RoomID == null) return;
270271
var multiplayerRoom = await JoinRoomInternal(room.RoomID.Value, password ?? room.Password).ConfigureAwait(false);
271272
await setupJoinedRoom(room, multiplayerRoom, cancellationSource.Token).ConfigureAwait(false);
272273
}, cancellationSource.Token).ConfigureAwait(false);

osu.Game/Screens/OnlinePlay/Lounge/LoungeSubScreen.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,8 @@ private void onListingReceived(Room[] result)
229229
if (result == null)
230230
return;
231231

232-
Dictionary<long, Room> localRoomsById = roomListing.Rooms.Where(r => r.RoomID != null).ToDictionary(r => r.RoomID.Value);
233-
Dictionary<long, Room> resultRoomsById = result.Where(r => r.RoomID != null).ToDictionary(r => r.RoomID.Value);
232+
Dictionary<long, Room> localRoomsById = roomListing.Rooms.Where(r => r.RoomID != null).GroupBy(r => r.RoomID.Value).ToDictionary(g => g.Key, g => g.First());
233+
Dictionary<long, Room> resultRoomsById = result.Where(r => r.RoomID != null).GroupBy(r => r.RoomID.Value).ToDictionary(g => g.Key, g => g.First());
234234

235235
// Remove all local rooms no longer in the result set.
236236
roomListing.Rooms.RemoveAll(r => r.RoomID == null || !resultRoomsById.ContainsKey(r.RoomID.Value));
@@ -241,7 +241,7 @@ private void onListingReceived(Room[] result)
241241
if (r.RoomID == null)
242242
continue;
243243

244-
if (localRoomsById.TryGetValue(r.RoomID.Value, out Room? existingRoom))
244+
if (r.RoomID != null && localRoomsById.TryGetValue(r.RoomID.Value, out Room? existingRoom))
245245
existingRoom.CopyFrom(r);
246246
else
247247
roomListing.Rooms.Add(r);
@@ -376,6 +376,7 @@ public void OpenCopy(Room room)
376376

377377
joiningRoomOperation = ongoingOperationTracker?.BeginOperation();
378378

379+
if (room.RoomID == null) return;
379380
var req = new GetRoomRequest(room.RoomID.Value);
380381

381382
req.Success += r =>

osu.Game/Screens/OnlinePlay/Playlists/PlaylistsRoomUpdater.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ protected override Task Poll()
3737
lastPollRequest?.Cancel();
3838

3939
var tcs = new TaskCompletionSource<bool>();
40+
if (room.RoomID == null) return base.Poll();
4041
var req = new GetRoomRequest(room.RoomID.Value);
4142

4243
req.Success += result =>

0 commit comments

Comments
 (0)