Android: Fix crash when loading input profile ingame

This commit is contained in:
Connor McLaughlin 2021-01-27 01:10:25 +10:00
parent 0b4363679c
commit b96136a9ec
4 changed files with 36 additions and 20 deletions

View File

@ -34,10 +34,11 @@ static jclass s_String_class;
static jclass s_AndroidHostInterface_class; static jclass s_AndroidHostInterface_class;
static jmethodID s_AndroidHostInterface_constructor; static jmethodID s_AndroidHostInterface_constructor;
static jfieldID s_AndroidHostInterface_field_mNativePointer; static jfieldID s_AndroidHostInterface_field_mNativePointer;
static jmethodID s_AndroidHostInterface_method_reportError;
static jmethodID s_AndroidHostInterface_method_reportMessage;
static jmethodID s_AndroidHostInterface_method_openAssetStream; static jmethodID s_AndroidHostInterface_method_openAssetStream;
static jclass s_EmulationActivity_class; static jclass s_EmulationActivity_class;
static jmethodID s_EmulationActivity_method_reportError; static jmethodID s_EmulationActivity_method_reportError;
static jmethodID s_EmulationActivity_method_reportMessage;
static jmethodID s_EmulationActivity_method_onEmulationStarted; static jmethodID s_EmulationActivity_method_onEmulationStarted;
static jmethodID s_EmulationActivity_method_onEmulationStopped; static jmethodID s_EmulationActivity_method_onEmulationStopped;
static jmethodID s_EmulationActivity_method_onGameTitleChanged; static jmethodID s_EmulationActivity_method_onGameTitleChanged;
@ -161,25 +162,29 @@ void AndroidHostInterface::ReportError(const char* message)
{ {
CommonHostInterface::ReportError(message); CommonHostInterface::ReportError(message);
if (m_emulation_activity_object)
{
JNIEnv* env = AndroidHelpers::GetJNIEnv(); JNIEnv* env = AndroidHelpers::GetJNIEnv();
jstring message_jstr = env->NewStringUTF(message); jstring message_jstr = env->NewStringUTF(message);
if (m_emulation_activity_object)
env->CallVoidMethod(m_emulation_activity_object, s_EmulationActivity_method_reportError, message_jstr); env->CallVoidMethod(m_emulation_activity_object, s_EmulationActivity_method_reportError, message_jstr);
else
env->CallVoidMethod(m_java_object, s_AndroidHostInterface_method_reportError, message_jstr);
env->DeleteLocalRef(message_jstr); env->DeleteLocalRef(message_jstr);
} }
}
void AndroidHostInterface::ReportMessage(const char* message) void AndroidHostInterface::ReportMessage(const char* message)
{ {
CommonHostInterface::ReportMessage(message); CommonHostInterface::ReportMessage(message);
JNIEnv* env = AndroidHelpers::GetJNIEnv(); if (IsOnEmulationThread())
if (m_emulation_activity_object)
{ {
jstring message_jstr = env->NewStringUTF(message); // The toasts are not visible when the emulation activity is running anyway.
env->CallVoidMethod(m_emulation_activity_object, s_EmulationActivity_method_reportMessage, message_jstr); AddOSDMessage(message, 5.0f);
env->DeleteLocalRef(message_jstr); }
else
{
JNIEnv* env = AndroidHelpers::GetJNIEnv();
LocalRefHolder<jstring> message_jstr(env, env->NewStringUTF(message));
env->CallVoidMethod(m_java_object, s_AndroidHostInterface_method_reportMessage, message_jstr.Get());
} }
} }
@ -309,6 +314,11 @@ void AndroidHostInterface::StopEmulationThreadLoop()
m_sleep_cv.notify_one(); m_sleep_cv.notify_one();
} }
bool AndroidHostInterface::IsOnEmulationThread() const
{
return std::this_thread::get_id() == m_emulation_thread_id;
}
void AndroidHostInterface::RunOnEmulationThread(std::function<void()> function, bool blocking) void AndroidHostInterface::RunOnEmulationThread(std::function<void()> function, bool blocking)
{ {
if (!IsEmulationThreadRunning()) if (!IsEmulationThreadRunning())
@ -350,6 +360,7 @@ void AndroidHostInterface::EmulationThreadEntryPoint(JNIEnv* env, jobject emulat
CreateImGuiContext(); CreateImGuiContext();
m_emulation_activity_object = emulation_activity; m_emulation_activity_object = emulation_activity;
m_emulation_thread_id = std::this_thread::get_id();
ApplySettings(true); ApplySettings(true);
// Boot system. // Boot system.
@ -887,14 +898,16 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
env->GetMethodID(s_AndroidHostInterface_class, "<init>", "(Landroid/content/Context;)V")) == nullptr || env->GetMethodID(s_AndroidHostInterface_class, "<init>", "(Landroid/content/Context;)V")) == nullptr ||
(s_AndroidHostInterface_field_mNativePointer = (s_AndroidHostInterface_field_mNativePointer =
env->GetFieldID(s_AndroidHostInterface_class, "mNativePointer", "J")) == nullptr || env->GetFieldID(s_AndroidHostInterface_class, "mNativePointer", "J")) == nullptr ||
(s_AndroidHostInterface_method_reportError =
env->GetMethodID(s_AndroidHostInterface_class, "reportError", "(Ljava/lang/String;)V")) == nullptr ||
(s_AndroidHostInterface_method_reportMessage =
env->GetMethodID(s_AndroidHostInterface_class, "reportMessage", "(Ljava/lang/String;)V")) == nullptr ||
(s_AndroidHostInterface_method_openAssetStream = env->GetMethodID( (s_AndroidHostInterface_method_openAssetStream = env->GetMethodID(
s_AndroidHostInterface_class, "openAssetStream", "(Ljava/lang/String;)Ljava/io/InputStream;")) == nullptr || s_AndroidHostInterface_class, "openAssetStream", "(Ljava/lang/String;)Ljava/io/InputStream;")) == nullptr ||
(emulation_activity_class = env->FindClass("com/github/stenzek/duckstation/EmulationActivity")) == nullptr || (emulation_activity_class = env->FindClass("com/github/stenzek/duckstation/EmulationActivity")) == nullptr ||
(s_EmulationActivity_class = static_cast<jclass>(env->NewGlobalRef(emulation_activity_class))) == nullptr || (s_EmulationActivity_class = static_cast<jclass>(env->NewGlobalRef(emulation_activity_class))) == nullptr ||
(s_EmulationActivity_method_reportError = (s_EmulationActivity_method_reportError =
env->GetMethodID(s_EmulationActivity_class, "reportError", "(Ljava/lang/String;)V")) == nullptr || env->GetMethodID(s_EmulationActivity_class, "reportError", "(Ljava/lang/String;)V")) == nullptr ||
(s_EmulationActivity_method_reportMessage =
env->GetMethodID(s_EmulationActivity_class, "reportMessage", "(Ljava/lang/String;)V")) == nullptr ||
(s_EmulationActivity_method_onEmulationStarted = (s_EmulationActivity_method_onEmulationStarted =
env->GetMethodID(s_EmulationActivity_class, "onEmulationStarted", "()V")) == nullptr || env->GetMethodID(s_EmulationActivity_class, "onEmulationStarted", "()V")) == nullptr ||
(s_EmulationActivity_method_onEmulationStopped = (s_EmulationActivity_method_onEmulationStopped =

View File

@ -44,6 +44,7 @@ public:
bool IsEmulationThreadRunning() const { return m_emulation_thread_running.load(); } bool IsEmulationThreadRunning() const { return m_emulation_thread_running.load(); }
bool IsEmulationThreadPaused() const; bool IsEmulationThreadPaused() const;
bool IsOnEmulationThread() const;
void RunOnEmulationThread(std::function<void()> function, bool blocking = false); void RunOnEmulationThread(std::function<void()> function, bool blocking = false);
void PauseEmulationThread(bool paused); void PauseEmulationThread(bool paused);
void StopEmulationThreadLoop(); void StopEmulationThreadLoop();
@ -109,6 +110,7 @@ private:
std::atomic_bool m_emulation_thread_stop_request{false}; std::atomic_bool m_emulation_thread_stop_request{false};
std::atomic_bool m_emulation_thread_running{false}; std::atomic_bool m_emulation_thread_running{false};
std::thread::id m_emulation_thread_id{};
HostDisplay::Alignment m_display_alignment = HostDisplay::Alignment::Center; HostDisplay::Alignment m_display_alignment = HostDisplay::Alignment::Center;

View File

@ -25,6 +25,14 @@ public class AndroidHostInterface {
this.mContext = context; this.mContext = context;
} }
public void reportError(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_LONG).show();
}
public void reportMessage(String message) {
Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show();
}
public InputStream openAssetStream(String path) { public InputStream openAssetStream(String path) {
try { try {
return mContext.getAssets().open(path, AssetManager.ACCESS_STREAMING); return mContext.getAssets().open(path, AssetManager.ACCESS_STREAMING);

View File

@ -104,13 +104,6 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
} }
} }
public void reportMessage(String message) {
Log.i("EmulationActivity", message);
runOnUiThread(() -> {
Toast.makeText(this, message, Toast.LENGTH_SHORT);
});
}
private EmulationThread mEmulationThread; private EmulationThread mEmulationThread;
private void stopEmulationThread() { private void stopEmulationThread() {