android: jni: Fix management of core emulation state and various cleanups.

- Fixes a shutdown crash.
This commit is contained in:
bunnei 2019-07-23 17:37:13 -04:00
parent 70c0f60d38
commit 87dd8888a3

View File

@ -40,18 +40,20 @@
JavaVM* g_java_vm; JavaVM* g_java_vm;
namespace { namespace {
ANativeWindow* s_surf; ANativeWindow* s_surf;
jclass s_jni_class; jclass s_jni_class;
jmethodID s_jni_method_alert; jmethodID s_jni_method_alert;
EmuWindow_Android* emu; std::unique_ptr<EmuWindow_Android> window;
std::atomic<bool> is_running{false}; std::atomic<bool> is_running{false};
std::atomic<bool> pause_emulation{false}; std::atomic<bool> pause_emulation{false};
std::mutex running_mutex; std::mutex running_mutex;
std::condition_variable running_cv; std::condition_variable running_cv;
} // Anonymous namespace } // Anonymous namespace
/** /**
@ -78,8 +80,6 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
static int RunCitra(const std::string& filepath) { static int RunCitra(const std::string& filepath) {
LOG_INFO(Frontend, "Citra is Starting"); LOG_INFO(Frontend, "Citra is Starting");
Config config;
MicroProfileOnThreadCreate("EmuThread"); MicroProfileOnThreadCreate("EmuThread");
SCOPE_EXIT({ MicroProfileShutdown(); }); SCOPE_EXIT({ MicroProfileShutdown(); });
@ -91,19 +91,19 @@ static int RunCitra(const std::string& filepath) {
// Register frontend applets // Register frontend applets
Frontend::RegisterDefaultApplets(); Frontend::RegisterDefaultApplets();
Settings::Apply();
InputManager::Init();
emu = new EmuWindow_Android(s_surf);
Core::System& system{Core::System::GetInstance()}; Core::System& system{Core::System::GetInstance()};
SCOPE_EXIT({ // If we have a window from last session, clean up old state
if (window) {
system.Shutdown(); system.Shutdown();
InputManager::Shutdown(); InputManager::Shutdown();
emu->~EmuWindow_Android(); }
});
const Core::System::ResultStatus load_result{system.Load(*emu, filepath)}; Settings::Apply();
InputManager::Init();
window = std::make_unique<EmuWindow_Android>(s_surf);
const Core::System::ResultStatus load_result{system.Load(*window, filepath)};
switch (load_result) { switch (load_result) {
case Core::System::ResultStatus::ErrorGetLoader: case Core::System::ResultStatus::ErrorGetLoader:
LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filepath); LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filepath);
@ -121,7 +121,7 @@ static int RunCitra(const std::string& filepath) {
LOG_CRITICAL(Frontend, "Error while loading ROM: The ROM format is not supported."); LOG_CRITICAL(Frontend, "Error while loading ROM: The ROM format is not supported.");
return -1; return -1;
case Core::System::ResultStatus::ErrorNotInitialized: case Core::System::ResultStatus::ErrorNotInitialized:
LOG_CRITICAL(Frontend, "CPUCore not initialized"); LOG_CRITICAL(Frontend, "Core not initialized");
return -1; return -1;
case Core::System::ResultStatus::ErrorSystemMode: case Core::System::ResultStatus::ErrorSystemMode:
LOG_CRITICAL(Frontend, "Failed to determine system mode!"); LOG_CRITICAL(Frontend, "Failed to determine system mode!");
@ -148,16 +148,16 @@ static int RunCitra(const std::string& filepath) {
} }
} }
return 0; return {};
} }
static std::string GetJString(JNIEnv* env, jstring jstr) { static std::string GetJString(JNIEnv* env, jstring jstr) {
std::string result = ""; if (!jstr) {
if (!jstr) return {};
return result; }
const char* s = env->GetStringUTFChars(jstr, nullptr); const char* s = env->GetStringUTFChars(jstr, nullptr);
result = s; std::string result = s;
env->ReleaseStringUTFChars(jstr, s); env->ReleaseStringUTFChars(jstr, s);
return result; return result;
} }
@ -167,7 +167,7 @@ void Java_org_citra_citra_1android_NativeLibrary_SurfaceChanged(JNIEnv* env, job
s_surf = ANativeWindow_fromSurface(env, surf); s_surf = ANativeWindow_fromSurface(env, surf);
if (is_running) { if (is_running) {
emu->OnSurfaceChanged(s_surf); window->OnSurfaceChanged(s_surf);
} }
LOG_INFO(Frontend, "Surface changed"); LOG_INFO(Frontend, "Surface changed");
@ -182,10 +182,6 @@ void Java_org_citra_citra_1android_NativeLibrary_CacheClassesAndMethods(JNIEnv*
// This reference, however, is valid until we delete it. // This reference, however, is valid until we delete it.
s_jni_class = reinterpret_cast<jclass>(env->NewGlobalRef(localClass)); s_jni_class = reinterpret_cast<jclass>(env->NewGlobalRef(localClass));
// TODO Find a place for this.
// So we don't leak a reference to NativeLibrary.class.
// env->DeleteGlobalRef(s_jni_class);
// Method signature taken from javap -s // Method signature taken from javap -s
// Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class // Source/Android/app/build/intermediates/classes/arm/debug/org/dolphinemu/dolphinemu/NativeLibrary.class
s_jni_method_alert = env->GetStaticMethodID(s_jni_class, "displayAlertMsg", s_jni_method_alert = env->GetStaticMethodID(s_jni_class, "displayAlertMsg",
@ -231,7 +227,7 @@ jboolean Java_org_citra_citra_1android_NativeLibrary_IsRunning(JNIEnv* env, jobj
jboolean Java_org_citra_citra_1android_NativeLibrary_onGamePadEvent(JNIEnv* env, jobject obj, jboolean Java_org_citra_citra_1android_NativeLibrary_onGamePadEvent(JNIEnv* env, jobject obj,
jstring jDevice, jint button, jstring jDevice, jint button,
jint pressed) { jint pressed) {
bool consumed; bool consumed{};
if (pressed) { if (pressed) {
consumed = InputManager::ButtonHandler()->PressKey(button); consumed = InputManager::ButtonHandler()->PressKey(button);
} else { } else {
@ -263,13 +259,13 @@ jboolean Java_org_citra_citra_1android_NativeLibrary_onGamePadAxisEvent(JNIEnv*
void Java_org_citra_citra_1android_NativeLibrary_onTouchEvent(JNIEnv* env, jobject obj, jfloat x, void Java_org_citra_citra_1android_NativeLibrary_onTouchEvent(JNIEnv* env, jobject obj, jfloat x,
jfloat y, jboolean pressed) { jfloat y, jboolean pressed) {
LOG_DEBUG(Frontend, "Touch at x: %d y: %d", (int)x, (int)y); LOG_DEBUG(Frontend, "Touch at x: %d y: %d", (int)x, (int)y);
emu->OnTouchEvent((int)x, (int)y, (bool)pressed); window->OnTouchEvent((int)x, (int)y, (bool)pressed);
} }
void Java_org_citra_citra_1android_NativeLibrary_onTouchMoved(JNIEnv* env, jobject obj, jfloat x, void Java_org_citra_citra_1android_NativeLibrary_onTouchMoved(JNIEnv* env, jobject obj, jfloat x,
jfloat y) { jfloat y) {
LOG_DEBUG(Frontend, "Touch at x: %d y: %d", (int)x, (int)y); LOG_DEBUG(Frontend, "Touch at x: %d y: %d", (int)x, (int)y);
emu->OnTouchMoved((int)x, (int)y); window->OnTouchMoved((int)x, (int)y);
} }
jintArray Java_org_citra_citra_1android_NativeLibrary_GetBanner(JNIEnv* env, jobject obj, jintArray Java_org_citra_citra_1android_NativeLibrary_GetBanner(JNIEnv* env, jobject obj,