Android: Call UICommon::Init at app start instead of emulation start

Much of our native code assumes that UICommon::Init has been called
(for reasons such as wanting to access the user's settings),
so not calling it until emulation start heavily limits what native
code we can use in the Android GUI (except during emulation).
This commit is contained in:
JosJuice 2019-06-16 14:41:58 +02:00
parent 47e1108d57
commit 9f3f45aa5f
6 changed files with 67 additions and 39 deletions

View File

@ -349,10 +349,29 @@ public final class NativeLibrary
public static native int DefaultCPUCore(); public static native int DefaultCPUCore();
public static native void ReloadConfig();
/**
* Initializes the native parts of the app.
*
* Should be called at app start before running any other native code
* (other than the native methods in DirectoryInitialization).
*/
public static native void Initialize();
/**
* Tells analytics that Dolphin has been started.
*
* Since users typically don't explicitly close Android apps, it's appropriate to
* call this not only when the app starts but also when the user returns to the app
* after not using it for a significant amount of time.
*/
public static native void ReportStartToAnalytics();
/** /**
* Begins emulation. * Begins emulation.
*/ */
public static native void Run(String[] path, boolean firstOpen); public static native void Run(String[] path);
/** /**
* Begins emulation from the specified savestate. * Begins emulation from the specified savestate.

View File

@ -2,6 +2,7 @@ package org.dolphinemu.dolphinemu.features.settings.model;
import android.text.TextUtils; import android.text.TextUtils;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivityView; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivityView;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile; import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
@ -175,6 +176,9 @@ public class Settings
SettingsFile.saveFile(fileName, iniSections, view); SettingsFile.saveFile(fileName, iniSections, view);
} }
// Notify the native code of the changes
NativeLibrary.ReloadConfig();
} }
else else
{ {

View File

@ -82,12 +82,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity());
String[] gamePaths = getArguments().getStringArray(KEY_GAMEPATHS); String[] gamePaths = getArguments().getStringArray(KEY_GAMEPATHS);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); mEmulationState = new EmulationState(gamePaths, getTemporaryStateFilePath());
boolean firstOpen = preferences.getBoolean(StartupHandler.NEW_SESSION, true);
SharedPreferences.Editor sPrefsEditor = preferences.edit();
sPrefsEditor.putBoolean(StartupHandler.NEW_SESSION, false);
sPrefsEditor.apply();
mEmulationState = new EmulationState(gamePaths, getTemporaryStateFilePath(), firstOpen);
} }
/** /**
@ -271,12 +266,10 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
private Surface mSurface; private Surface mSurface;
private boolean mRunWhenSurfaceIsValid; private boolean mRunWhenSurfaceIsValid;
private boolean loadPreviousTemporaryState; private boolean loadPreviousTemporaryState;
private boolean firstOpen;
private final String temporaryStatePath; private final String temporaryStatePath;
EmulationState(String[] gamePaths, String temporaryStatePath, boolean firstOpen) EmulationState(String[] gamePaths, String temporaryStatePath)
{ {
this.firstOpen = firstOpen;
mGamePaths = gamePaths; mGamePaths = gamePaths;
this.temporaryStatePath = temporaryStatePath; this.temporaryStatePath = temporaryStatePath;
// Starting state is stopped. // Starting state is stopped.
@ -420,7 +413,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
else else
{ {
Log.debug("[EmulationFragment] Starting emulation thread."); Log.debug("[EmulationFragment] Starting emulation thread.");
NativeLibrary.Run(mGamePaths, firstOpen); NativeLibrary.Run(mGamePaths);
} }
}, "NativeEmulation"); }, "NativeEmulation");
mEmulationThread.start(); mEmulationThread.start();

View File

@ -67,6 +67,8 @@ public final class DirectoryInitialization
{ {
initializeInternalStorage(context); initializeInternalStorage(context);
initializeExternalStorage(context); initializeExternalStorage(context);
NativeLibrary.Initialize();
NativeLibrary.ReportStartToAnalytics();
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
} }

View File

@ -8,15 +8,15 @@ import android.preference.PreferenceManager;
import android.support.v4.app.FragmentActivity; import android.support.v4.app.FragmentActivity;
import android.text.TextUtils; import android.text.TextUtils;
import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import java.util.Date; import java.util.Date;
public final class StartupHandler public final class StartupHandler
{ {
public static final String NEW_SESSION = "NEW_SESSION";
public static final String LAST_CLOSED = "LAST_CLOSED"; public static final String LAST_CLOSED = "LAST_CLOSED";
public static final Long SESSION_TIMEOUT = 21600000L; // 6 hours in milliseconds public static final long SESSION_TIMEOUT = 21600000L; // 6 hours in milliseconds
public static void HandleInit(FragmentActivity parent) public static void HandleInit(FragmentActivity parent)
{ {
@ -66,15 +66,13 @@ public final class StartupHandler
*/ */
public static void checkSessionReset(Context context) public static void checkSessionReset(Context context)
{ {
Long currentTime = new Date(System.currentTimeMillis()).getTime(); long currentTime = new Date(System.currentTimeMillis()).getTime();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
Long lastOpen = preferences.getLong(LAST_CLOSED, 0); long lastOpen = preferences.getLong(LAST_CLOSED, 0);
if (currentTime > (lastOpen + SESSION_TIMEOUT)) if (currentTime > (lastOpen + SESSION_TIMEOUT))
{ {
// Passed at emulation start to trigger first open event. new AfterDirectoryInitializationRunner().run(context,
SharedPreferences.Editor sPrefsEditor = preferences.edit(); () -> NativeLibrary.ReportStartToAnalytics());
sPrefsEditor.putBoolean(NEW_SESSION, true);
sPrefsEditor.apply();
} }
} }
} }

View File

@ -245,12 +245,14 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_DefaultCPUCo
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfiling(JNIEnv* env, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetProfiling(JNIEnv* env,
jobject obj, jobject obj,
jboolean enable); jboolean enable);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Initialize(JNIEnv* env,
jobject obj);
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_ReportStartToAnalytics(JNIEnv* env, jobject obj);
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_WriteProfileResults(JNIEnv* env, jobject obj); Java_org_dolphinemu_dolphinemu_NativeLibrary_WriteProfileResults(JNIEnv* env, jobject obj);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run__Ljava_lang_String_2(
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run__Ljava_lang_String_2Z( JNIEnv* env, jobject obj, jstring jFile);
JNIEnv* env, jobject obj, jstring jFile, jboolean jfirstOpen);
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z( Java_org_dolphinemu_dolphinemu_NativeLibrary_Run__Ljava_lang_String_2Ljava_lang_String_2Z(
JNIEnv* env, jobject obj, jstring jFile, jstring jSavestate, jboolean jDeleteSavestate); JNIEnv* env, jobject obj, jstring jFile, jstring jSavestate, jboolean jDeleteSavestate);
@ -585,6 +587,27 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ReloadWiimot
Wiimote::LoadConfig(); Wiimote::LoadConfig();
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ReloadConfig(JNIEnv* env,
jobject obj)
{
SConfig::GetInstance().LoadSettings();
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Initialize(JNIEnv* env,
jobject obj)
{
Common::RegisterMsgAlertHandler(&MsgAlert);
Common::AndroidSetReportHandler(&ReportSend);
DolphinAnalytics::AndroidSetGetValFunc(&GetAnalyticValue);
UICommon::Init();
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_ReportStartToAnalytics(JNIEnv* env, jobject obj)
{
DolphinAnalytics::Instance().ReportDolphinStart(GetAnalyticValue("DEVICE_TYPE"));
}
// Returns the scale factor for imgui rendering. // Returns the scale factor for imgui rendering.
// Based on the scaledDensity of the device's display metrics. // Based on the scaledDensity of the device's display metrics.
static float GetRenderSurfaceScale(JNIEnv* env) static float GetRenderSurfaceScale(JNIEnv* env)
@ -630,23 +653,13 @@ static float GetRenderSurfaceScale(JNIEnv* env)
return scaled_density; return scaled_density;
} }
static void Run(JNIEnv* env, const std::vector<std::string>& paths, bool first_open, static void Run(JNIEnv* env, const std::vector<std::string>& paths,
std::optional<std::string> savestate_path = {}, bool delete_savestate = false) std::optional<std::string> savestate_path = {}, bool delete_savestate = false)
{ {
ASSERT(!paths.empty()); ASSERT(!paths.empty());
__android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Running : %s", paths[0].c_str()); __android_log_print(ANDROID_LOG_INFO, DOLPHIN_TAG, "Running : %s", paths[0].c_str());
Common::RegisterMsgAlertHandler(&MsgAlert);
Common::AndroidSetReportHandler(&ReportSend);
DolphinAnalytics::AndroidSetGetValFunc(&GetAnalyticValue);
std::unique_lock<std::mutex> guard(s_host_identity_lock); std::unique_lock<std::mutex> guard(s_host_identity_lock);
UICommon::Init();
if (first_open)
{
DolphinAnalytics::Instance().ReportDolphinStart(GetAnalyticValue("DEVICE_TYPE"));
}
WiimoteReal::InitAdapterClass(); WiimoteReal::InitAdapterClass();
@ -679,7 +692,6 @@ static void Run(JNIEnv* env, const std::vector<std::string>& paths, bool first_o
Core::Shutdown(); Core::Shutdown();
ButtonManager::Shutdown(); ButtonManager::Shutdown();
UICommon::Shutdown();
guard.unlock(); guard.unlock();
if (s_surf) if (s_surf)
@ -689,17 +701,17 @@ static void Run(JNIEnv* env, const std::vector<std::string>& paths, bool first_o
} }
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run___3Ljava_lang_String_2Z( JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_Run___3Ljava_lang_String_2(
JNIEnv* env, jobject obj, jobjectArray jPaths, jboolean jfirstOpen) JNIEnv* env, jobject obj, jobjectArray jPaths)
{ {
Run(env, JStringArrayToVector(env, jPaths), jfirstOpen); Run(env, JStringArrayToVector(env, jPaths));
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_Run___3Ljava_lang_String_2Ljava_lang_String_2Z( Java_org_dolphinemu_dolphinemu_NativeLibrary_Run___3Ljava_lang_String_2Ljava_lang_String_2Z(
JNIEnv* env, jobject obj, jobjectArray jPaths, jstring jSavestate, jboolean jDeleteSavestate) JNIEnv* env, jobject obj, jobjectArray jPaths, jstring jSavestate, jboolean jDeleteSavestate)
{ {
Run(env, JStringArrayToVector(env, jPaths), false, GetJString(env, jSavestate), jDeleteSavestate); Run(env, JStringArrayToVector(env, jPaths), GetJString(env, jSavestate), jDeleteSavestate);
} }
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ChangeDisc(JNIEnv* env, JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_ChangeDisc(JNIEnv* env,