Android: Wait for surface in Run

When we boot the core, it needs to have a valid surface to draw graphics
to. Our Kotlin code does wait for a valid surface to exist before it
calls NativeLibrary.Run, but there's a chance for the surface to be
deleted before Run locks s_surface_lock. If that happens, the core boots
without a valid surface, which presumably would cause a crash. (I
haven't been able to reproduce the problem myself.)
This commit is contained in:
JosJuice 2024-08-21 20:36:46 +02:00
parent 93617e96c3
commit dcf8ab0189

View File

@ -1,13 +1,9 @@
// Copyright 2003 Dolphin Emulator Project // Copyright 2003 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <EGL/egl.h> #include <condition_variable>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <fmt/format.h>
#include <jni.h>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
@ -15,6 +11,12 @@
#include <thread> #include <thread>
#include <utility> #include <utility>
#include <EGL/egl.h>
#include <android/log.h>
#include <android/native_window_jni.h>
#include <fmt/format.h>
#include <jni.h>
#include "Common/AndroidAnalytics.h" #include "Common/AndroidAnalytics.h"
#include "Common/Assert.h" #include "Common/Assert.h"
#include "Common/CPUDetect.h" #include "Common/CPUDetect.h"
@ -77,6 +79,8 @@ Common::Event s_update_main_frame_event;
// This exists to prevent surfaces from being destroyed during the boot process, // This exists to prevent surfaces from being destroyed during the boot process,
// as that can lead to the boot process dereferencing nullptr. // as that can lead to the boot process dereferencing nullptr.
std::mutex s_surface_lock; std::mutex s_surface_lock;
std::condition_variable s_surface_cv;
bool s_need_nonblocking_alert_msg; bool s_need_nonblocking_alert_msg;
Common::Flag s_is_booting; Common::Flag s_is_booting;
@ -454,6 +458,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChang
if (g_presenter) if (g_presenter)
g_presenter->ChangeSurface(s_surf); g_presenter->ChangeSurface(s_surf);
s_surface_cv.notify_all();
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv*, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv*,
@ -487,6 +493,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestr
ANativeWindow_release(s_surf); ANativeWindow_release(s_surf);
s_surf = nullptr; s_surf = nullptr;
} }
s_surface_cv.notify_all();
} }
JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_HasSurface(JNIEnv*, jclass) JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_HasSurface(JNIEnv*, jclass)
@ -578,12 +586,14 @@ static void Run(JNIEnv* env, std::unique_ptr<BootParameters>&& boot, bool riivol
volume.GetDiscNumber())); volume.GetDiscNumber()));
} }
WindowSystemInfo wsi(WindowSystemType::Android, nullptr, s_surf, s_surf);
wsi.render_surface_scale = GetRenderSurfaceScale(env);
s_need_nonblocking_alert_msg = true; s_need_nonblocking_alert_msg = true;
std::unique_lock<std::mutex> surface_guard(s_surface_lock); std::unique_lock<std::mutex> surface_guard(s_surface_lock);
s_surface_cv.wait(surface_guard, []() { return s_surf != nullptr; });
WindowSystemInfo wsi(WindowSystemType::Android, nullptr, s_surf, s_surf);
wsi.render_surface_scale = GetRenderSurfaceScale(env);
if (BootManager::BootCore(Core::System::GetInstance(), std::move(boot), wsi)) if (BootManager::BootCore(Core::System::GetInstance(), std::move(boot), wsi))
{ {
static constexpr int WAIT_STEP = 25; static constexpr int WAIT_STEP = 25;