From 0280f3557c703beb4c14df7aab543349bfc001ea Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 6 Nov 2020 19:26:56 +0100 Subject: Android: Finish EmulationActivity from C++ This makes EmulationActivity automatically close if booting fails, and lets us get rid of s_emulation_end_event. --- Source/Android/jni/MainAndroid.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'Source/Android/jni/MainAndroid.cpp') diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 4079f947dc..f852d61590 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -77,7 +77,6 @@ ANativeWindow* s_surf; // sequentially for access. std::mutex s_host_identity_lock; Common::Event s_update_main_frame_event; -Common::Event s_emulation_end_event; bool s_have_wm_user_stop = false; bool s_game_metadata_is_valid = false; } // Anonymous namespace @@ -210,17 +209,11 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_PauseEmulati JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv*, jclass) { - { - std::lock_guard guard(s_host_identity_lock); - s_emulation_end_event.Reset(); - Core::Stop(); - - // Kick the waiting event - s_update_main_frame_event.Set(); - } + std::lock_guard guard(s_host_identity_lock); + Core::Stop(); - // Wait for shutdown, to avoid accessing the config at the same time as the shutdown code - s_emulation_end_event.Wait(); + // Kick the waiting event + s_update_main_frame_event.Set(); } JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_IsBooting(JNIEnv*, jclass) @@ -533,7 +526,8 @@ static void Run(JNIEnv* env, const std::vector& paths, s_surf = nullptr; } - s_emulation_end_event.Set(); + env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), + IDCache::GetFinishEmulationActivity()); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run___3Ljava_lang_String_2( -- cgit v1.2.3 From ee52f465b10ef8541c642522f053d273492baf8f Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 6 Nov 2020 21:22:22 +0100 Subject: 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. --- Source/Android/jni/MainAndroid.cpp | 65 ++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 21 deletions(-) (limited to 'Source/Android/jni/MainAndroid.cpp') 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(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(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(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 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 guard(s_surface_lock); + if (g_renderer) g_renderer->ChangeSurface(nullptr); @@ -480,7 +486,7 @@ static void Run(JNIEnv* env, const std::vector& paths, ASSERT(!paths.empty()); __android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Running : %s", paths[0].c_str()); - std::unique_lock guard(s_host_identity_lock); + std::unique_lock host_identity_guard(s_host_identity_lock); WiimoteReal::InitAdapterClass(); @@ -493,24 +499,41 @@ static void Run(JNIEnv* env, const std::vector& 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 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& paths, s_game_metadata_is_valid = false; Core::Shutdown(); ButtonManager::Shutdown(); - guard.unlock(); + host_identity_guard.unlock(); if (s_surf) { -- cgit v1.2.3 From 8181a7b3dd932a3035b9fc56f6def70c0cc05c59 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 6 Nov 2020 23:05:23 +0100 Subject: Android: Remove unnecessary ANativeWindow_release call This is already handled by SurfaceDestroyed. In the worst case, the extra code could even race with SurfaceDestroyed if they are triggered at the same time, but this is highly improbable. --- Source/Android/jni/MainAndroid.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'Source/Android/jni/MainAndroid.cpp') diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 9e2950b630..6fe6da3b61 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -543,12 +543,6 @@ static void Run(JNIEnv* env, const std::vector& paths, ButtonManager::Shutdown(); host_identity_guard.unlock(); - if (s_surf) - { - ANativeWindow_release(s_surf); - s_surf = nullptr; - } - env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetFinishEmulationActivity()); } -- cgit v1.2.3