Skip to content

Commit

Permalink
[Android] Support restore emulator state after the emulation screen i…
Browse files Browse the repository at this point in the history
…s killed
  • Loading branch information
mahdihijazi committed Dec 27, 2017
1 parent d854a77 commit f41c782
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.usb.UsbManager;
Expand Down Expand Up @@ -42,7 +41,6 @@
import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper;
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;
Expand All @@ -68,8 +66,16 @@ public final class EmulationActivity extends AppCompatActivity

private static boolean sIsGameCubeGame;

private boolean isManualExit;
private boolean activityRecreated;
private String mScreenPath;
private String mSelectedTitle;
private String mPath;

public static final String EXTRA_SELECTED_GAME = "SelectedGame";
public static final String EXTRA_SELECTED_TITLE = "SelectedTitle";
public static final String EXTRA_SCREEN_PATH = "ScreenPath";
public static final String EXTRA_GRID_POSITION = "GridPosition";

@Retention(SOURCE)
@IntDef({MENU_ACTION_EDIT_CONTROLS_PLACEMENT, MENU_ACTION_TOGGLE_CONTROLS, MENU_ACTION_ADJUST_SCALE,
Expand Down Expand Up @@ -138,10 +144,10 @@ public static void launch(FragmentActivity activity, String path, String title,
{
Intent launcher = new Intent(activity, EmulationActivity.class);

launcher.putExtra("SelectedGame", path);
launcher.putExtra("SelectedTitle", title);
launcher.putExtra("ScreenPath", screenshotPath);
launcher.putExtra("GridPosition", position);
launcher.putExtra(EXTRA_SELECTED_GAME, path);
launcher.putExtra(EXTRA_SELECTED_TITLE, title);
launcher.putExtra(EXTRA_SCREEN_PATH, screenshotPath);
launcher.putExtra(EXTRA_GRID_POSITION, position);

ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(
activity,
Expand All @@ -158,13 +164,23 @@ protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);

// Get params we were passed
Intent gameToEmulate = getIntent();
String path = gameToEmulate.getStringExtra("SelectedGame");
sIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(path)) == Platform.GAMECUBE;
mSelectedTitle = gameToEmulate.getStringExtra("SelectedTitle");
mScreenPath = gameToEmulate.getStringExtra("ScreenPath");
mPosition = gameToEmulate.getIntExtra("GridPosition", -1);
if (savedInstanceState == null)
{
// Get params we were passed
Intent gameToEmulate = getIntent();
mPath = gameToEmulate.getStringExtra(EXTRA_SELECTED_GAME);
mSelectedTitle = gameToEmulate.getStringExtra(EXTRA_SELECTED_TITLE);
mScreenPath = gameToEmulate.getStringExtra(EXTRA_SCREEN_PATH);
mPosition = gameToEmulate.getIntExtra(EXTRA_GRID_POSITION, -1);
activityRecreated = false;
}
else
{
activityRecreated = true;
restoreState(savedInstanceState);
}

sIsGameCubeGame = Platform.fromNativeInt(NativeLibrary.GetPlatform(mPath)) == Platform.GAMECUBE;
mDeviceHasTouchScreen = getPackageManager().hasSystemFeature("android.hardware.touchscreen");
mControllerMappingHelper = new ControllerMappingHelper();

Expand Down Expand Up @@ -206,7 +222,7 @@ protected void onCreate(Bundle savedInstanceState)
.findFragmentById(R.id.frame_emulation_fragment);
if (mEmulationFragment == null)
{
mEmulationFragment = EmulationFragment.newInstance(path);
mEmulationFragment = EmulationFragment.newInstance(mPath);
getSupportFragmentManager().beginTransaction()
.add(R.id.frame_emulation_fragment, mEmulationFragment)
.commit();
Expand Down Expand Up @@ -256,6 +272,34 @@ public void onError()

}

@Override
protected void onPause()
{
if (!isManualExit)
{
mEmulationFragment.saveTemporaryState();
}
super.onPause();
}

@Override
protected void onSaveInstanceState(Bundle outState)
{
outState.putString(EXTRA_SELECTED_GAME, mPath);
outState.putString(EXTRA_SELECTED_TITLE, mSelectedTitle);
outState.putString(EXTRA_SCREEN_PATH, mScreenPath);
outState.putInt(EXTRA_GRID_POSITION, mPosition);
super.onSaveInstanceState(outState);
}

protected void restoreState(Bundle savedInstanceState)
{
mPath = savedInstanceState.getString(EXTRA_SELECTED_GAME);
mSelectedTitle = savedInstanceState.getString(EXTRA_SELECTED_TITLE);
mScreenPath = savedInstanceState.getString(EXTRA_SCREEN_PATH);
mPosition = savedInstanceState.getInt(EXTRA_GRID_POSITION);
}

@Override
public void onBackPressed()
{
Expand All @@ -270,6 +314,7 @@ public void onBackPressed()
}
else
{
isManualExit = true;
mEmulationFragment.stopEmulation();
exitWithAnimation();
}
Expand Down Expand Up @@ -485,6 +530,7 @@ public void handleMenuAction(@MenuAction int menuAction)
return;

case MENU_ACTION_EXIT:
isManualExit = true;
toggleMenu(); // Hide the menu (it will be showing since we just clicked it)
mEmulationFragment.stopEmulation();
exitWithAnimation();
Expand Down Expand Up @@ -716,4 +762,9 @@ public static boolean isGameCubeGame()
{
return sIsGameCubeGame;
}

public boolean isActivityRecreated()
{
return activityRecreated;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
import org.dolphinemu.dolphinemu.utils.Log;

import java.io.File;

import rx.functions.Action1;

public final class EmulationFragment extends Fragment implements SurfaceHolder.Callback
Expand All @@ -39,6 +41,8 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C

private DirectoryStateReceiver directoryStateReceiver;

private EmulationActivity activity;

public static EmulationFragment newInstance(String gamePath)
{

Expand All @@ -57,6 +61,7 @@ public void onAttach(Context context)

if (context instanceof EmulationActivity)
{
activity = (EmulationActivity)context;
NativeLibrary.setEmulationActivity((EmulationActivity) context);
}
else
Expand All @@ -79,7 +84,7 @@ public void onCreate(Bundle savedInstanceState)
mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());

String gamePath = getArguments().getString(KEY_GAMEPATH);
mEmulationState = new EmulationState(gamePath);
mEmulationState = new EmulationState(gamePath, getTemporaryStateFilePath());
}

/**
Expand Down Expand Up @@ -120,7 +125,7 @@ public void onResume()
super.onResume();
if (DirectoryInitializationService.areDolphinDirectoriesReady())
{
mEmulationState.run();
mEmulationState.run(activity.isActivityRecreated());
}
else
{
Expand Down Expand Up @@ -155,7 +160,7 @@ private void setupDolphinDirectoriesThenStartEmulation() {
directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState -> {
if (directoryInitializationState == DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) {
mEmulationState.run();
mEmulationState.run(activity.isActivityRecreated());
} else if (directoryInitializationState == DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) {
Toast.makeText(getContext(), R.string.write_permission_needed, Toast.LENGTH_SHORT)
.show();
Expand Down Expand Up @@ -249,10 +254,13 @@ private enum State
private State state;
private Surface mSurface;
private boolean mRunWhenSurfaceIsValid;
private boolean loadPreviousTemporaryState;
private final String temporaryStatePath;

EmulationState(String gamePath)
EmulationState(String gamePath, String temporaryStatePath)
{
mGamePath = gamePath;
this.temporaryStatePath = temporaryStatePath;
// Starting state is stopped.
state = State.STOPPED;
}
Expand Down Expand Up @@ -280,6 +288,7 @@ public synchronized void stop()
{
if (state != State.STOPPED)
{
Log.debug("[EmulationFragment] Stopping emulation.");
state = State.STOPPED;
NativeLibrary.StopEmulation();
}
Expand Down Expand Up @@ -307,8 +316,28 @@ public synchronized void pause()
}
}

public synchronized void run()
public synchronized void run(boolean isActivityRecreated)
{
if (isActivityRecreated)
{
if (NativeLibrary.IsRunning())
{
loadPreviousTemporaryState = false;
state = State.PAUSED;
deleteFile(temporaryStatePath);
}
else
{
loadPreviousTemporaryState = true;
}
}
else
{
Log.debug("[EmulationFragment] activity resumed or fresh start");
// activity resumed without being killed or this is the first run
deleteFile(temporaryStatePath);
}

// If the surface is set, run now. Otherwise, wait for it to get set.
if (mSurface != null)
{
Expand Down Expand Up @@ -362,12 +391,19 @@ private void runWithValidSurface()
mRunWhenSurfaceIsValid = false;
if (state == State.STOPPED)
{
Log.debug("[EmulationFragment] Starting emulation thread.");

mEmulationThread = new Thread(() ->
{
NativeLibrary.SurfaceChanged(mSurface);
NativeLibrary.Run(mGamePath);
if (loadPreviousTemporaryState)
{
Log.debug("[EmulationFragment] Starting emulation thread from previous state.");
NativeLibrary.Run(mGamePath, temporaryStatePath);
}
else
{
Log.debug("[EmulationFragment] Starting emulation thread.");
NativeLibrary.Run(mGamePath);
}
}, "NativeEmulation");
mEmulationThread.start();

Expand All @@ -385,4 +421,27 @@ else if (state == State.PAUSED)
state = State.RUNNING;
}
}

public void saveTemporaryState()
{
NativeLibrary.SaveStateAs(getTemporaryStateFilePath(), true);
}

private String getTemporaryStateFilePath()
{
return getContext().getCacheDir() + File.separator + "temp.sav";
}

private static void deleteFile(String path)
{
try
{
File file = new File(path);
file.delete();
}
catch (Exception ex)
{
// fail safely
}
}
}

0 comments on commit f41c782

Please sign in to comment.