diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
index 2753735200..8e59d07cca 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
@@ -42,6 +42,7 @@ import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.utils.Animations;
import org.dolphinemu.dolphinemu.utils.Java_GCAdapter;
import org.dolphinemu.dolphinemu.utils.Java_WiimoteAdapter;
+import org.dolphinemu.dolphinemu.utils.Log;
import java.lang.annotation.Retention;
import java.util.List;
@@ -226,8 +227,17 @@ public final class EmulationActivity extends AppCompatActivity
setContentView(R.layout.activity_emulation);
mImageView = (ImageView) findViewById(R.id.image_screenshot);
+
+ // Find or create the EmulationFragment
mEmulationFragment = (EmulationFragment) getSupportFragmentManager()
- .findFragmentById(R.id.fragment_emulation);
+ .findFragmentById(R.id.frame_emulation_fragment);
+ if (mEmulationFragment == null)
+ {
+ mEmulationFragment = EmulationFragment.newInstance(path);
+ getSupportFragmentManager().beginTransaction()
+ .add(R.id.frame_emulation_fragment, mEmulationFragment)
+ .commit();
+ }
if (savedInstanceState == null)
{
@@ -265,9 +275,6 @@ public final class EmulationActivity extends AppCompatActivity
mImageView.setVisibility(View.GONE);
}
});
-
- mEmulationFragment.setGamePath(path);
- mEmulationFragment.startEmulation();
}
else
{
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java
index 0572d048f4..263cd597c1 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java
@@ -21,16 +21,24 @@ import org.dolphinemu.dolphinemu.utils.Log;
public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback
{
- private SharedPreferences mPreferences;
+ private static final String KEY_GAMEPATH = "gamepath";
- private Surface mSurface;
+ private SharedPreferences mPreferences;
private InputOverlay mInputOverlay;
- private Thread mEmulationThread;
+ private EmulationState mEmulationState;
- private String mGamePath;
- private final EmulationState mEmulationState = new EmulationState();
+ public static EmulationFragment newInstance(String gamePath)
+ {
+
+ Bundle args = new Bundle();
+ args.putString(KEY_GAMEPATH, gamePath);
+
+ EmulationFragment fragment = new EmulationFragment();
+ fragment.setArguments(args);
+ return fragment;
+ }
@Override
public void onAttach(Context context)
@@ -59,6 +67,9 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
setRetainInstance(true);
mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
+
+ String gamePath = getArguments().getString(KEY_GAMEPATH);
+ mEmulationState = new EmulationState(gamePath);
}
/**
@@ -101,10 +112,17 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
}
@Override
- public void onStop()
+ public void onResume()
{
- pauseEmulation();
- super.onStop();
+ super.onResume();
+ mEmulationState.run();
+ }
+
+ @Override
+ public void onPause()
+ {
+ mEmulationState.pause();
+ super.onPause();
}
@Override
@@ -114,11 +132,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
super.onDetach();
}
- public void setGamePath(String gamePath)
- {
- mGamePath = gamePath;
- }
-
public void toggleInputOverlayVisibility()
{
SharedPreferences.Editor editor = mPreferences.edit();
@@ -148,101 +161,28 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
@Override
public void surfaceCreated(SurfaceHolder holder)
{
- Log.debug("[EmulationFragment] Surface created.");
+ // We purposely don't do anything here.
+ // All work is done in surfaceChanged, which we are guaranteed to get even for surface creation.
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Log.debug("[EmulationFragment] Surface changed. Resolution: " + width + "x" + height);
-
- if (mEmulationState.isPaused())
- {
- NativeLibrary.UnPauseEmulation();
- }
-
- mSurface = holder.getSurface();
- NativeLibrary.SurfaceChanged(mSurface);
+ mEmulationState.newSurface(holder.getSurface());
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
- Log.debug("[EmulationFragment] Surface destroyed.");
- NativeLibrary.SurfaceDestroyed();
-
- if (mEmulationState.isRunning())
- {
- pauseEmulation();
- }
+ mEmulationState.clearSurface();
}
- public void startEmulation()
+ public void stopEmulation()
{
- synchronized (mEmulationState)
- {
- if (mEmulationState.isStopped())
- {
- Log.debug("[EmulationFragment] Starting emulation thread.");
-
- mEmulationThread = new Thread(mEmulationRunner, "NativeEmulation");
- mEmulationThread.start();
- // The thread will call mEmulationState.run()
- }
- else if (mEmulationState.isPaused())
- {
- Log.debug("[EmulationFragment] Resuming emulation.");
- NativeLibrary.UnPauseEmulation();
- mEmulationState.run();
- }
- else
- {
- Log.debug("[EmulationFragment] Bug, startEmulation called while running.");
- }
- }
+ mEmulationState.stop();
}
- public void stopEmulation() {
- synchronized (mEmulationState)
- {
- if (!mEmulationState.isStopped())
- {
- NativeLibrary.StopEmulation();
- mEmulationState.stop();
- }
- }
- }
-
- private void pauseEmulation()
- {
- synchronized (mEmulationState)
- {
- Log.debug("[EmulationFragment] Pausing emulation.");
-
- NativeLibrary.PauseEmulation();
- mEmulationState.pause();
- }
- }
-
- private Runnable mEmulationRunner = new Runnable()
- {
- @Override
- public void run()
- {
- // Busy-wait for surface to be set
- while (mSurface == null) {}
-
- synchronized (mEmulationState)
- {
- Log.info("[EmulationFragment] Starting emulation: " + mSurface);
-
- mEmulationState.run();
- }
- // Start emulation using the provided Surface.
- NativeLibrary.Run(mGamePath);
- }
- };
-
public void startConfiguringControls()
{
getView().findViewById(R.id.done_control_config).setVisibility(View.VISIBLE);
@@ -267,42 +207,149 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
STOPPED, RUNNING, PAUSED
}
+ private final String mGamePath;
+ private Thread mEmulationThread;
private State state;
+ private Surface mSurface;
+ private boolean mRunWhenSurfaceIsValid;
- EmulationState()
+ EmulationState(String gamePath)
{
+ mGamePath = gamePath;
// Starting state is stopped.
state = State.STOPPED;
}
- public boolean isStopped()
+ // Getters for the current state
+
+ public synchronized boolean isStopped()
{
return state == State.STOPPED;
}
- public boolean isRunning()
- {
- return state == State.RUNNING;
- }
-
- public boolean isPaused()
+ public synchronized boolean isPaused()
{
return state == State.PAUSED;
}
- public void run()
+ public synchronized boolean isRunning()
{
+ return state == State.RUNNING;
+ }
+
+ // State changing methods
+
+ public synchronized void stop()
+ {
+ if (state != State.STOPPED)
+ {
+ state = State.STOPPED;
+ NativeLibrary.StopEmulation();
+ }
+ else
+ {
+ Log.warning("[EmulationFragment] Stop called while already stopped.");
+ }
+ }
+
+ public synchronized void pause()
+ {
+ if (state != State.PAUSED)
+ {
+ state = State.PAUSED;
+ Log.debug("[EmulationFragment] Pausing emulation.");
+
+ // Release the surface before pausing, since emulation has to be running for that.
+ mSurface = null;
+ NativeLibrary.SurfaceDestroyed();
+ NativeLibrary.PauseEmulation();
+ }
+ else
+ {
+ Log.warning("[EmulationFragment] Pause called while already paused.");
+ }
+ }
+
+ public synchronized void run()
+ {
+ // If the surface is set, run now. Otherwise, wait for it to get set.
+ if (mSurface != null)
+ {
+ runWithValidSurface();
+ }
+ else
+ {
+ mRunWhenSurfaceIsValid = true;
+ }
+ }
+
+ // Surface callbacks
+ public synchronized void newSurface(Surface surface)
+ {
+ mSurface = surface;
+ if (mRunWhenSurfaceIsValid)
+ {
+ runWithValidSurface();
+ }
+ }
+
+ public synchronized void clearSurface()
+ {
+ if (mSurface == null)
+ {
+ Log.warning("[EmulationFragment] clearSurface called, but surface already null.");
+ }
+ else
+ {
+ mSurface = null;
+ Log.debug("[EmulationFragment] Surface destroyed.");
+
+ if (state == State.RUNNING)
+ {
+ NativeLibrary.SurfaceDestroyed();
+ state = State.PAUSED;
+ }
+ else if (state == State.PAUSED)
+ {
+ Log.warning("[EmulationFragment] Surface cleared while emulation paused.");
+ }
+ else
+ {
+ Log.warning("[EmulationFragment] Surface cleared while emulation stopped.");
+ }
+ }
+ }
+
+ private void runWithValidSurface()
+ {
+ mRunWhenSurfaceIsValid = false;
+ if (state == State.STOPPED)
+ {
+ Log.debug("[EmulationFragment] Starting emulation thread.");
+
+ mEmulationThread = new Thread(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ NativeLibrary.SurfaceChanged(mSurface);
+ NativeLibrary.Run(mGamePath);
+ }},
+ "NativeEmulation");
+ mEmulationThread.start();
+
+ }
+ else if (state == State.PAUSED)
+ {
+ Log.debug("[EmulationFragment] Resuming emulation.");
+ NativeLibrary.UnPauseEmulation();
+ NativeLibrary.SurfaceChanged(mSurface);
+ }
+ else
+ {
+ Log.debug("[EmulationFragment] Bug, run called while already running.");
+ }
state = State.RUNNING;
}
-
- public void pause()
- {
- state = State.PAUSED;
- }
-
- public void stop()
- {
- state = State.STOPPED;
- }
}
}
diff --git a/Source/Android/app/src/main/res/layout-television/activity_emulation.xml b/Source/Android/app/src/main/res/layout-television/activity_emulation.xml
index 3009f40e84..835af1b39b 100644
--- a/Source/Android/app/src/main/res/layout-television/activity_emulation.xml
+++ b/Source/Android/app/src/main/res/layout-television/activity_emulation.xml
@@ -5,9 +5,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frame_content">
-
diff --git a/Source/Android/app/src/main/res/layout/activity_emulation.xml b/Source/Android/app/src/main/res/layout/activity_emulation.xml
index 2562d5a44b..7ebaceee22 100644
--- a/Source/Android/app/src/main/res/layout/activity_emulation.xml
+++ b/Source/Android/app/src/main/res/layout/activity_emulation.xml
@@ -3,9 +3,8 @@
android:layout_height="match_parent"
android:id="@+id/frame_content">
-