Android: Defer rotation request until after start

Fixes messed-up state when orientation is set.
This commit is contained in:
Connor McLaughlin 2021-01-21 01:23:07 +10:00
parent 5b4aff5edf
commit a0ca20a821
5 changed files with 29 additions and 34 deletions

View file

@ -227,13 +227,14 @@ std::unique_ptr<ByteStream> AndroidHostInterface::OpenPackageFile(const char* pa
void AndroidHostInterface::RegisterHotkeys() void AndroidHostInterface::RegisterHotkeys()
{ {
RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "General")), StaticString("OpenPauseMenu"), RegisterHotkey(StaticString(TRANSLATABLE("Hotkeys", "General")), StaticString("OpenPauseMenu"),
StaticString(TRANSLATABLE("Hotkeys", "Open Pause Menu")), [this](bool pressed) { StaticString(TRANSLATABLE("Hotkeys", "Open Pause Menu")), [this](bool pressed) {
if (pressed) { if (pressed)
AndroidHelpers::GetJNIEnv()->CallVoidMethod(m_emulation_activity_object, {
s_EmulationActivity_method_openPauseMenu); AndroidHelpers::GetJNIEnv()->CallVoidMethod(m_emulation_activity_object,
} s_EmulationActivity_method_openPauseMenu);
}); }
});
CommonHostInterface::RegisterHotkeys(); CommonHostInterface::RegisterHotkeys();
} }
@ -339,19 +340,17 @@ void AndroidHostInterface::RunOnEmulationThread(std::function<void()> function,
m_mutex.unlock(); m_mutex.unlock();
} }
void AndroidHostInterface::EmulationThreadEntryPoint(JNIEnv* env, jobject emulation_activity, jobject surface, void AndroidHostInterface::EmulationThreadEntryPoint(JNIEnv* env, jobject emulation_activity,
SystemBootParameters boot_params, bool resume_state) SystemBootParameters boot_params, bool resume_state)
{ {
ANativeWindow* native_surface = ANativeWindow_fromSurface(env, surface); if (!m_surface)
if (!native_surface)
{ {
Log_ErrorPrint("ANativeWindow_fromSurface() returned null"); Log_ErrorPrint("Emulation thread started without surface set.");
env->CallVoidMethod(m_emulation_activity_object, s_EmulationActivity_method_onEmulationStopped); env->CallVoidMethod(m_emulation_activity_object, s_EmulationActivity_method_onEmulationStopped);
return; return;
} }
CreateImGuiContext(); CreateImGuiContext();
m_surface = native_surface;
m_emulation_activity_object = emulation_activity; m_emulation_activity_object = emulation_activity;
ApplySettings(true); ApplySettings(true);
@ -912,8 +911,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
nullptr || nullptr ||
(s_EmulationActivity_method_getRefreshRate = (s_EmulationActivity_method_getRefreshRate =
env->GetMethodID(emulation_activity_class, "getRefreshRate", "()F")) == nullptr || env->GetMethodID(emulation_activity_class, "getRefreshRate", "()F")) == nullptr ||
(s_EmulationActivity_method_openPauseMenu = (s_EmulationActivity_method_openPauseMenu = env->GetMethodID(emulation_activity_class, "openPauseMenu", "()V")) ==
env->GetMethodID(emulation_activity_class, "openPauseMenu", "()V")) == nullptr || nullptr ||
(s_PatchCode_constructor = env->GetMethodID(s_PatchCode_class, "<init>", "(ILjava/lang/String;Z)V")) == nullptr || (s_PatchCode_constructor = env->GetMethodID(s_PatchCode_class, "<init>", "(ILjava/lang/String;Z)V")) == nullptr ||
(s_GameListEntry_constructor = env->GetMethodID( (s_GameListEntry_constructor = env->GetMethodID(
s_GameListEntry_class, "<init>", s_GameListEntry_class, "<init>",
@ -985,15 +984,15 @@ DEFINE_JNI_ARGS_METHOD(jboolean, AndroidHostInterface_isEmulationThreadRunning,
} }
DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_runEmulationThread, jobject obj, jobject emulationActivity, DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_runEmulationThread, jobject obj, jobject emulationActivity,
jobject surface, jstring filename, jboolean resume_state, jstring state_filename) jstring filename, jboolean resume_state, jstring state_filename)
{ {
std::string state_filename_str = AndroidHelpers::JStringToString(env, state_filename); std::string state_filename_str = AndroidHelpers::JStringToString(env, state_filename);
SystemBootParameters boot_params; SystemBootParameters boot_params;
boot_params.filename = AndroidHelpers::JStringToString(env, filename); boot_params.filename = AndroidHelpers::JStringToString(env, filename);
AndroidHelpers::GetNativeClass(env, obj)->EmulationThreadEntryPoint(env, emulationActivity, surface, AndroidHelpers::GetNativeClass(env, obj)->EmulationThreadEntryPoint(env, emulationActivity, std::move(boot_params),
std::move(boot_params), resume_state); resume_state);
} }
DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_stopEmulationThreadLoop, jobject obj) DEFINE_JNI_ARGS_METHOD(void, AndroidHostInterface_stopEmulationThreadLoop, jobject obj)

View file

@ -46,8 +46,8 @@ public:
void PauseEmulationThread(bool paused); void PauseEmulationThread(bool paused);
void StopEmulationThreadLoop(); void StopEmulationThreadLoop();
void EmulationThreadEntryPoint(JNIEnv* env, jobject emulation_activity, jobject initial_surface, void EmulationThreadEntryPoint(JNIEnv* env, jobject emulation_activity, SystemBootParameters boot_params,
SystemBootParameters boot_params, bool resume_state); bool resume_state);
void SurfaceChanged(ANativeWindow* surface, int format, int width, int height); void SurfaceChanged(ANativeWindow* surface, int format, int width, int height);
void SetDisplayAlignment(HostDisplay::Alignment alignment); void SetDisplayAlignment(HostDisplay::Alignment alignment);

View file

@ -49,7 +49,7 @@ public class AndroidHostInterface {
public native boolean isEmulationThreadRunning(); public native boolean isEmulationThreadRunning();
public native boolean runEmulationThread(EmulationActivity emulationActivity, Surface surface, String filename, boolean resumeState, String state_filename); public native boolean runEmulationThread(EmulationActivity emulationActivity, String filename, boolean resumeState, String state_filename);
public native boolean isEmulationThreadPaused(); public native boolean isEmulationThreadPaused();

View file

@ -123,6 +123,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
public void onEmulationStarted() { public void onEmulationStarted() {
runOnUiThread(() -> { runOnUiThread(() -> {
updateRequestedOrientation();
updateOrientation(); updateOrientation();
}); });
} }
@ -196,8 +197,9 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
@Override @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// Once we get a surface, we can boot. // Once we get a surface, we can boot.
AndroidHostInterface.getInstance().surfaceChanged(holder.getSurface(), format, width, height);
if (mEmulationThread != null) { if (mEmulationThread != null) {
AndroidHostInterface.getInstance().surfaceChanged(holder.getSurface(), format, width, height);
updateOrientation(); updateOrientation();
if (mApplySettingsOnSurfaceRestored) { if (mApplySettingsOnSurfaceRestored) {
@ -212,18 +214,15 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
final boolean resumeState = getIntent().getBooleanExtra("resumeState", false); final boolean resumeState = getIntent().getBooleanExtra("resumeState", false);
final String bootSaveStatePath = getIntent().getStringExtra("saveStatePath"); final String bootSaveStatePath = getIntent().getStringExtra("saveStatePath");
mEmulationThread = EmulationThread.create(this, holder.getSurface(), bootPath, resumeState, bootSaveStatePath); mEmulationThread = EmulationThread.create(this, bootPath, resumeState, bootSaveStatePath);
} }
@Override @Override
public void surfaceDestroyed(SurfaceHolder holder) { public void surfaceDestroyed(SurfaceHolder holder) {
if (!AndroidHostInterface.getInstance().isEmulationThreadRunning())
return;
Log.i("EmulationActivity", "Surface destroyed"); Log.i("EmulationActivity", "Surface destroyed");
// Save the resume state in case we never get back again... // Save the resume state in case we never get back again...
if (!mStopRequested) if (AndroidHostInterface.getInstance().isEmulationThreadRunning() && !mStopRequested)
AndroidHostInterface.getInstance().saveResumeState(true); AndroidHostInterface.getInstance().saveResumeState(true);
AndroidHostInterface.getInstance().surfaceChanged(null, 0, 0, 0); AndroidHostInterface.getInstance().surfaceChanged(null, 0, 0, 0);
@ -231,9 +230,9 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
Log.i("EmulationActivity", "OnCreate"); Log.i("EmulationActivity", "OnCreate");
// we might be coming from a third-party launcher if the host interface isn't setup // we might be coming from a third-party launcher if the host interface isn't setup
@ -255,7 +254,6 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
mContentView.requestFocus(); mContentView.requestFocus();
// Sort out rotation. // Sort out rotation.
updateRequestedOrientation();
updateOrientation(); updateOrientation();
updateSustainedPerformanceMode(); updateSustainedPerformanceMode();

View file

@ -8,24 +8,22 @@ import androidx.annotation.NonNull;
public class EmulationThread extends Thread { public class EmulationThread extends Thread {
private EmulationActivity emulationActivity; private EmulationActivity emulationActivity;
private Surface surface;
private String filename; private String filename;
private boolean resumeState; private boolean resumeState;
private String stateFilename; private String stateFilename;
private EmulationThread(EmulationActivity emulationActivity, Surface surface, String filename, boolean resumeState, String stateFilename) { private EmulationThread(EmulationActivity emulationActivity, String filename, boolean resumeState, String stateFilename) {
super("EmulationThread"); super("EmulationThread");
this.emulationActivity = emulationActivity; this.emulationActivity = emulationActivity;
this.surface = surface;
this.filename = filename; this.filename = filename;
this.resumeState = resumeState; this.resumeState = resumeState;
this.stateFilename = stateFilename; this.stateFilename = stateFilename;
} }
public static EmulationThread create(EmulationActivity emulationActivity, Surface surface, String filename, boolean resumeState, String stateFilename) { public static EmulationThread create(EmulationActivity emulationActivity, String filename, boolean resumeState, String stateFilename) {
Log.i("EmulationThread", String.format("Starting emulation thread (%s)...", filename)); Log.i("EmulationThread", String.format("Starting emulation thread (%s)...", filename));
EmulationThread thread = new EmulationThread(emulationActivity, surface, filename, resumeState, stateFilename); EmulationThread thread = new EmulationThread(emulationActivity, filename, resumeState, stateFilename);
thread.start(); thread.start();
return thread; return thread;
} }
@ -38,7 +36,7 @@ public class EmulationThread extends Thread {
Log.i("EmulationThread", "Failed to set priority for emulation thread: " + e.getMessage()); Log.i("EmulationThread", "Failed to set priority for emulation thread: " + e.getMessage());
} }
AndroidHostInterface.getInstance().runEmulationThread(emulationActivity, surface, filename, resumeState, stateFilename); AndroidHostInterface.getInstance().runEmulationThread(emulationActivity, filename, resumeState, stateFilename);
Log.i("EmulationThread", "Emulation thread exiting."); Log.i("EmulationThread", "Emulation thread exiting.");
} }