Android: Use Java thread for emulation thread

This commit is contained in:
Connor McLaughlin
2021-01-11 01:03:17 +10:00
parent a5f9aa11e1
commit 5996945b37
5 changed files with 145 additions and 87 deletions

View File

@ -4,6 +4,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.AssetManager;
import android.os.Environment;
import android.os.Process;
import android.util.Log;
import android.view.Surface;
import android.widget.Toast;
@ -20,12 +21,6 @@ public class AndroidHostInterface {
private long mNativePointer;
private Context mContext;
static public native String getScmVersion();
static public native String getFullScmVersion();
static public native AndroidHostInterface create(Context context, String userDirectory);
public AndroidHostInterface(Context context) {
this.mContext = context;
}
@ -46,15 +41,21 @@ public class AndroidHostInterface {
}
}
static public native String getScmVersion();
static public native String getFullScmVersion();
static public native AndroidHostInterface create(Context context, String userDirectory);
public native boolean isEmulationThreadRunning();
public native boolean startEmulationThread(EmulationActivity emulationActivity, Surface surface, String filename, boolean resumeState, String state_filename);
public native boolean runEmulationThread(EmulationActivity emulationActivity, Surface surface, String filename, boolean resumeState, String state_filename);
public native boolean isEmulationThreadPaused();
public native void pauseEmulationThread(boolean paused);
public native void stopEmulationThread();
public native void stopEmulationThreadLoop();
public native boolean hasSurface();

View File

@ -108,12 +108,24 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
});
}
private EmulationThread mEmulationThread;
private void stopEmulationThread() {
if (mEmulationThread == null)
return;
mEmulationThread.stopAndJoin();
mEmulationThread = null;
}
public void onEmulationStarted() {
runOnUiThread(() -> {
updateOrientation();
});
}
public void onEmulationStopped() {
runOnUiThread(() -> {
AndroidHostInterface.getInstance().stopEmulationThread();
if (!mWasDestroyed && !mStopRequested)
finish();
});
@ -159,7 +171,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// Once we get a surface, we can boot.
if (AndroidHostInterface.getInstance().isEmulationThreadRunning()) {
if (mEmulationThread != null) {
AndroidHostInterface.getInstance().surfaceChanged(holder.getSurface(), format, width, height);
updateOrientation();
@ -175,9 +187,7 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
final boolean resumeState = getIntent().getBooleanExtra("resumeState", false);
final String bootSaveStatePath = getIntent().getStringExtra("saveStatePath");
AndroidHostInterface.getInstance().startEmulationThread(this, holder.getSurface(), bootPath, resumeState, bootSaveStatePath);
updateRequestedOrientation();
updateOrientation();
mEmulationThread = EmulationThread.create(this, holder.getSurface(), bootPath, resumeState, bootSaveStatePath);
}
@Override
@ -219,6 +229,10 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
}
mContentView.requestFocus();
// Sort out rotation.
updateRequestedOrientation();
updateOrientation();
// Hook up controller input.
updateControllers();
registerInputDeviceListener();
@ -240,9 +254,9 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
protected void onDestroy() {
super.onDestroy();
Log.i("EmulationActivity", "OnStop");
if (AndroidHostInterface.getInstance().isEmulationThreadRunning()) {
if (mEmulationThread != null) {
mWasDestroyed = true;
AndroidHostInterface.getInstance().stopEmulationThread();
stopEmulationThread();
}
unregisterInputDeviceListener();
@ -317,9 +331,6 @@ public class EmulationActivity extends AppCompatActivity implements SurfaceHolde
}
private void updateOrientation(int newOrientation) {
if (!AndroidHostInterface.getInstance().isEmulationThreadRunning())
return;
if (newOrientation == Configuration.ORIENTATION_PORTRAIT)
AndroidHostInterface.getInstance().setDisplayAlignment(AndroidHostInterface.DISPLAY_ALIGNMENT_TOP_OR_LEFT);
else

View File

@ -0,0 +1,53 @@
package com.github.stenzek.duckstation;
import android.os.Process;
import android.util.Log;
import android.view.Surface;
import androidx.annotation.NonNull;
public class EmulationThread extends Thread {
private EmulationActivity emulationActivity;
private Surface surface;
private String filename;
private boolean resumeState;
private String stateFilename;
private EmulationThread(EmulationActivity emulationActivity, Surface surface, String filename, boolean resumeState, String stateFilename) {
super("EmulationThread");
this.emulationActivity = emulationActivity;
this.surface = surface;
this.filename = filename;
this.resumeState = resumeState;
this.stateFilename = stateFilename;
}
public static EmulationThread create(EmulationActivity emulationActivity, Surface surface, String filename, boolean resumeState, String stateFilename) {
Log.i("EmulationThread", String.format("Starting emulation thread (%s)...", filename));
EmulationThread thread = new EmulationThread(emulationActivity, surface, filename, resumeState, stateFilename);
thread.start();
return thread;
}
@Override
public void run() {
try {
Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);
} catch (Exception e) {
Log.i("EmulationThread", "Failed to set priority for emulation thread: " + e.getMessage());
}
AndroidHostInterface.getInstance().runEmulationThread(emulationActivity, surface, filename, resumeState, stateFilename);
Log.i("EmulationThread", "Emulation thread exiting.");
}
public void stopAndJoin() {
AndroidHostInterface.getInstance().stopEmulationThreadLoop();
try {
join();
} catch (InterruptedException e) {
Log.i("EmulationThread", "join() interrupted: " + e.getMessage());
}
}
}