diff options
| author | JosJuice <josjuice@gmail.com> | 2020-11-06 21:22:22 +0100 |
|---|---|---|
| committer | JosJuice <josjuice@gmail.com> | 2020-11-09 10:38:49 +0100 |
| commit | ee52f465b10ef8541c642522f053d273492baf8f (patch) | |
| tree | 9d966a763e75de6ad8a2a80606b4a828f1c5d3d1 /Source/Android/jni/MainAndroid.cpp | |
| parent | d06830b27457fef2afc9f2e848a5291eae30a6b1 (diff) | |
Android: Fix rotating EmulationActivity after boot fails
Time for yet another new iteration of working around the
"surface destruction during boot" problem...
This time, the strategy is to use a mutex in MainAndroid.cpp.
Diffstat (limited to 'Source/Android/jni/MainAndroid.cpp')
| -rw-r--r-- | Source/Android/jni/MainAndroid.cpp | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index f852d61590..9e2950b630 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -77,6 +77,12 @@ ANativeWindow* s_surf; // sequentially for access. std::mutex s_host_identity_lock; Common::Event s_update_main_frame_event; + +// This exists to prevent surfaces from being destroyed during the boot process, +// as that can lead to the boot process dereferencing nullptr. +std::mutex s_surface_lock; +bool s_need_nonblocking_alert_msg; + bool s_have_wm_user_stop = false; bool s_game_metadata_is_valid = false; } // Anonymous namespace @@ -159,9 +165,10 @@ static bool MsgAlert(const char* caption, const char* text, bool yes_no, Common: JNIEnv* env = IDCache::GetEnvForThread(); // Execute the Java method. - jboolean result = env->CallStaticBooleanMethod( - IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), ToJString(env, caption), - ToJString(env, text), yes_no ? JNI_TRUE : JNI_FALSE, style == Common::MsgType::Warning); + jboolean result = + env->CallStaticBooleanMethod(IDCache::GetNativeLibraryClass(), IDCache::GetDisplayAlertMsg(), + ToJString(env, caption), ToJString(env, text), yes_no, + style == Common::MsgType::Warning, s_need_nonblocking_alert_msg); return result != JNI_FALSE; } @@ -216,20 +223,15 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulatio s_update_main_frame_event.Set(); } -JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsBooting(JNIEnv*, jclass) -{ - return static_cast<jboolean>(Core::IsBooting()); -} - -JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_WaitUntilDoneBooting(JNIEnv*, - jclass) +JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsRunning(JNIEnv*, jclass) { - Core::WaitUntilDoneBooting(); + return static_cast<jboolean>(Core::IsRunning()); } -JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsRunning(JNIEnv*, jclass) +JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsRunningAndStarted(JNIEnv*, + jclass) { - return Core::IsRunning(); + return static_cast<jboolean>(Core::IsRunningAndStarted()); } JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onGamePadEvent( @@ -391,6 +393,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChang jclass, jobject surf) { + std::lock_guard<std::mutex> guard(s_surface_lock); + s_surf = ANativeWindow_fromSurface(env, surf); if (s_surf == nullptr) __android_log_print(ANDROID_LOG_ERROR, DOLPHIN_TAG, "Error: Surface is null."); @@ -402,6 +406,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceChang JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SurfaceDestroyed(JNIEnv*, jclass) { + std::lock_guard<std::mutex> guard(s_surface_lock); + if (g_renderer) g_renderer->ChangeSurface(nullptr); @@ -480,7 +486,7 @@ static void Run(JNIEnv* env, const std::vector<std::string>& paths, ASSERT(!paths.empty()); __android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Running : %s", paths[0].c_str()); - std::unique_lock<std::mutex> guard(s_host_identity_lock); + std::unique_lock<std::mutex> host_identity_guard(s_host_identity_lock); WiimoteReal::InitAdapterClass(); @@ -493,24 +499,41 @@ static void Run(JNIEnv* env, const std::vector<std::string>& paths, WindowSystemInfo wsi(WindowSystemType::Android, nullptr, s_surf, s_surf); wsi.render_surface_scale = GetRenderSurfaceScale(env); - // No use running the loop when booting fails - if (BootManager::BootCore(std::move(boot), wsi)) + s_need_nonblocking_alert_msg = true; + std::unique_lock<std::mutex> surface_guard(s_surface_lock); + + bool successful_boot = BootManager::BootCore(std::move(boot), wsi); + if (successful_boot) { ButtonManager::Init(SConfig::GetInstance().GetGameID()); + static constexpr int TIMEOUT = 10000; static constexpr int WAIT_STEP = 25; int time_waited = 0; // A Core::CORE_ERROR state would be helpful here. - while (!Core::IsRunning() && time_waited < TIMEOUT && !s_have_wm_user_stop) + while (!Core::IsRunningAndStarted()) { + if (time_waited >= TIMEOUT || s_have_wm_user_stop) + { + successful_boot = false; + break; + } + std::this_thread::sleep_for(std::chrono::milliseconds(WAIT_STEP)); time_waited += WAIT_STEP; } - while (Core::IsRunning()) + } + + s_need_nonblocking_alert_msg = false; + surface_guard.unlock(); + + if (successful_boot) + { + while (Core::IsRunningAndStarted()) { - guard.unlock(); + host_identity_guard.unlock(); s_update_main_frame_event.Wait(); - guard.lock(); + host_identity_guard.lock(); Core::HostDispatchJobs(); } } @@ -518,7 +541,7 @@ static void Run(JNIEnv* env, const std::vector<std::string>& paths, s_game_metadata_is_valid = false; Core::Shutdown(); ButtonManager::Shutdown(); - guard.unlock(); + host_identity_guard.unlock(); if (s_surf) { |
