Merge pull request #6051 from JosJuice/android-sys

Android: Extract Sys to a different folder than the User folder
This commit is contained in:
JosJuice 2017-12-27 17:34:24 +01:00 committed by GitHub
commit 1df69c5750
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 149 additions and 90 deletions

View File

@ -283,6 +283,8 @@ public final class NativeLibrary
*/
public static native String GetVersionString();
public static native String GetGitRevision();
/**
* Saves a screen capture of the game
*/
@ -302,11 +304,6 @@ public final class NativeLibrary
*/
public static native void LoadState(int slot);
/**
* Creates the initial folder structure in /sdcard/dolphin-emu/
*/
public static native void CreateUserFolders();
/**
* Sets the current working user directory
* If not set, it auto-detects a location

View File

@ -9,6 +9,8 @@ package org.dolphinemu.dolphinemu.services;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import org.dolphinemu.dolphinemu.NativeLibrary;
@ -59,7 +61,8 @@ public final class DirectoryInitializationService extends IntentService
}
else if (PermissionsHandler.hasWriteAccess(this))
{
initDolphinDirectories();
initializeInternalStorage();
initializeExternalStorage();
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
sendBroadcastState(directoryState);
}
@ -69,21 +72,55 @@ public final class DirectoryInitializationService extends IntentService
}
}
private void initDolphinDirectories()
private void initializeInternalStorage()
{
String BaseDir = NativeLibrary.GetUserDirectory();
String ConfigDir = BaseDir + File.separator + "Config";
File sysDirectory = new File(getFilesDir(), "Sys");
// Copy assets if needed
NativeLibrary.CreateUserFolders();
copyAssetFolder("GC", BaseDir + File.separator + "GC", false);
copyAssetFolder("Shaders", BaseDir + File.separator + "Shaders", false);
copyAssetFolder("Wii", BaseDir + File.separator + "Wii", false);
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String revision = NativeLibrary.GetGitRevision();
if (!preferences.getString("sysDirectoryVersion", "").equals(revision))
{
// There is no extracted Sys directory, or there is a Sys directory from another
// version of Dolphin that might contain outdated files. Let's (re-)extract Sys.
deleteDirectoryRecursively(sysDirectory);
copyAssetFolder("Sys", sysDirectory, true);
// Always copy over the GCPad config in case of change or corruption.
// Not a user configurable file.
copyAsset("GCPadNew.ini", ConfigDir + File.separator + "GCPadNew.ini", true);
copyAsset("WiimoteNew.ini", ConfigDir + File.separator + "WiimoteNew.ini", false);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("sysDirectoryVersion", revision);
editor.apply();
}
// Let the native code know where the Sys directory is.
SetSysDirectory(sysDirectory.getPath());
}
private void initializeExternalStorage()
{
// Create User directory structure and copy some NAND files from the extracted Sys directory.
CreateUserDirectories();
// GCPadNew.ini and WiimoteNew.ini must contain specific values in order for controller
// input to work as intended (they aren't user configurable), so we overwrite them just
// in case the user has tried to modify them manually.
//
// ...Except WiimoteNew.ini contains the user configurable settings for Wii Remote
// extensions in addition to all of its lines that aren't user configurable, so since we
// don't want to lose the selected extensions, we don't overwrite that file if it exists.
//
// TODO: Redo the Android controller system so that we don't have to extract these INIs.
String configDirectory = NativeLibrary.GetUserDirectory() + File.separator + "Config";
copyAsset("GCPadNew.ini", new File(configDirectory, "GCPadNew.ini"), true);
copyAsset("WiimoteNew.ini", new File(configDirectory,"WiimoteNew.ini"), false);
}
private static void deleteDirectoryRecursively(File file)
{
if (file.isDirectory())
{
for (File child : file.listFiles())
deleteDirectoryRecursively(child);
}
file.delete();
}
public static boolean areDolphinDirectoriesReady()
@ -99,19 +136,16 @@ public final class DirectoryInitializationService extends IntentService
LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent);
}
private void copyAsset(String asset, String output, Boolean overwrite)
private void copyAsset(String asset, File output, Boolean overwrite)
{
Log.verbose("[DirectoryInitializationService] Copying File " + asset + " to " + output);
InputStream in;
OutputStream out;
try
{
File file = new File(output);
if (!file.exists() || overwrite)
if (!output.exists() || overwrite)
{
in = getAssets().open(asset);
out = new FileOutputStream(output);
InputStream in = getAssets().open(asset);
OutputStream out = new FileOutputStream(output);
copyFile(in, out);
in.close();
out.close();
@ -123,16 +157,22 @@ public final class DirectoryInitializationService extends IntentService
}
}
private void copyAssetFolder(String assetFolder, String outputFolder, Boolean overwrite)
private void copyAssetFolder(String assetFolder, File outputFolder, Boolean overwrite)
{
Log.verbose("[DirectoryInitializationService] Copying Folder " + assetFolder + " to " + outputFolder);
try
{
boolean createdFolder = false;
for (String file : getAssets().list(assetFolder))
{
copyAssetFolder(assetFolder + File.separator + file, outputFolder + File.separator + file, overwrite);
copyAsset(assetFolder + File.separator + file, outputFolder + File.separator + file, overwrite);
if (!createdFolder)
{
outputFolder.mkdir();
createdFolder = true;
}
copyAssetFolder(assetFolder + File.separator + file, new File(outputFolder, file), overwrite);
copyAsset(assetFolder + File.separator + file, new File(outputFolder, file), overwrite);
}
}
catch (IOException e)
@ -151,4 +191,7 @@ public final class DirectoryInitializationService extends IntentService
out.write(buffer, 0, read);
}
}
private static native void CreateUserDirectories();
private static native void SetSysDirectory(String path);
}

View File

@ -13,33 +13,31 @@ public final class StartupHandler
{
public static boolean HandleInit(FragmentActivity parent)
{
NativeLibrary.SetUserDirectory(""); // Auto-Detect
if (PermissionsHandler.checkWritePermission(parent)) {
DirectoryInitializationService.startService(parent);
}
Intent intent = parent.getIntent();
Bundle extras = intent.getExtras();
String user_dir = "";
String start_file = "";
Bundle extras = parent.getIntent().getExtras();
if (extras != null)
{
String user_dir = extras.getString("UserDir");
String start_file = extras.getString("AutoStartFile");
if (!TextUtils.isEmpty(user_dir))
NativeLibrary.SetUserDirectory(user_dir);
if (!TextUtils.isEmpty(start_file))
{
// Start the emulation activity, send the ISO passed in and finish the main activity
Intent emulation_intent = new Intent(parent, EmulationActivity.class);
emulation_intent.putExtra("SelectedGame", start_file);
parent.startActivity(emulation_intent);
parent.finish();
return false;
}
user_dir = extras.getString("UserDir");
start_file = extras.getString("AutoStartFile");
}
NativeLibrary.SetUserDirectory(user_dir); // Uses default path if user_dir equals ""
if (PermissionsHandler.checkWritePermission(parent))
DirectoryInitializationService.startService(parent);
if (!TextUtils.isEmpty(start_file))
{
// Start the emulation activity, send the ISO passed in and finish the main activity
Intent emulation_intent = new Intent(parent, EmulationActivity.class);
emulation_intent.putExtra("SelectedGame", start_file);
parent.startActivity(emulation_intent);
parent.finish();
return false;
}
return false;
}
}

View File

@ -15,6 +15,8 @@ ${LIBS}
)
file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/)
file(COPY ${CMAKE_SOURCE_DIR}/Data/Sys/GameSettings ${CMAKE_SOURCE_DIR}/Data/Sys/GC ${CMAKE_SOURCE_DIR}/Data/Sys/Wii ${CMAKE_SOURCE_DIR}/Data/Sys/Shaders DESTINATION ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/)
file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/Sys/)
file(COPY ${CMAKE_SOURCE_DIR}/Data/Sys DESTINATION ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/)
file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/Sys/Resources/) # not used on Android
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} ${SHARED_LIB})

View File

@ -432,6 +432,8 @@ JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetPlatform(
jstring jFilename);
JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv* env, jobject obj);
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGitRevision(JNIEnv* env,
jobject obj);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv* env,
jobject obj);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_eglBindAPI(JNIEnv* env,
@ -450,8 +452,9 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveState(JN
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JNIEnv* env,
jobject obj,
jint slot);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_CreateUserFolders(JNIEnv* env,
jobject obj);
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_CreateUserDirectories(
JNIEnv* env, jobject obj);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory(
JNIEnv* env, jobject obj, jstring jDirectory);
JNIEXPORT jstring JNICALL
@ -588,6 +591,12 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersio
return env->NewStringUTF(Common::scm_rev_str.c_str());
}
JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetGitRevision(JNIEnv* env,
jobject obj)
{
return env->NewStringUTF(Common::scm_rev_git_str.c_str());
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv* env,
jobject obj)
{
@ -649,28 +658,19 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadState(JN
State::Load(slot);
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_CreateUserFolders(JNIEnv* env,
jobject obj)
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_SetSysDirectory(
JNIEnv* env, jobject obj, jstring jPath)
{
File::CreateFullPath(File::GetUserPath(D_CONFIG_IDX));
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX));
File::CreateFullPath(File::GetUserPath(D_WIIROOT_IDX) + DIR_SEP WII_WC24CONF_DIR DIR_SEP
"mbox" DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_WIIROOT_IDX) + DIR_SEP "shared2" DIR_SEP
"succession" DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_WIIROOT_IDX) + DIR_SEP "shared2" DIR_SEP "ec" DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_WIIROOT_IDX) + DIR_SEP WII_SYSCONF_DIR DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_CACHE_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPDSP_IDX));
File::CreateFullPath(File::GetUserPath(D_DUMPTEXTURES_IDX));
File::CreateFullPath(File::GetUserPath(D_HIRESTEXTURES_IDX));
File::CreateFullPath(File::GetUserPath(D_SCREENSHOTS_IDX));
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
File::CreateFullPath(File::GetUserPath(D_MAILLOGS_IDX));
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX) + "Anaglyph" DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + USA_DIR DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + EUR_DIR DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_GCUSER_IDX) + JAP_DIR DIR_SEP);
const std::string path = GetJString(env, jPath);
File::SetSysDirectory(path);
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_CreateUserDirectories(
JNIEnv* env, jobject obj)
{
UICommon::CreateDirectories();
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory(

View File

@ -27,21 +27,6 @@
#define DOLPHIN_DATA_DIR "dolphin-emu"
#endif
// Shared data dirs (Sys and shared User for Linux)
#if defined(_WIN32) || defined(LINUX_LOCAL_DEV)
#define SYSDATA_DIR "Sys"
#elif defined __APPLE__
#define SYSDATA_DIR "Contents/Resources/Sys"
#elif defined ANDROID
#define SYSDATA_DIR "/sdcard/dolphin-emu"
#else
#ifdef DATA_DIR
#define SYSDATA_DIR DATA_DIR "sys"
#else
#define SYSDATA_DIR "sys"
#endif
#endif
// Dirs in both User and Sys
#define EUR_DIR "EUR"
#define USA_DIR "USA"

View File

@ -13,6 +13,7 @@
#include <sys/stat.h>
#include <vector>
#include "Common/Assert.h"
#include "Common/Common.h"
#include "Common/CommonFuncs.h"
#include "Common/CommonPaths.h"
@ -52,6 +53,10 @@
// REMEMBER: strdup considered harmful!
namespace File
{
#ifdef ANDROID
static std::string s_android_sys_directory;
#endif
#ifdef _WIN32
FileInfo::FileInfo(const std::string& path)
{
@ -692,10 +697,25 @@ std::string GetSysDirectory()
{
std::string sysDir;
#if defined(_WIN32) || defined(LINUX_LOCAL_DEV)
#define SYSDATA_DIR "Sys"
#elif defined __APPLE__
#define SYSDATA_DIR "Contents/Resources/Sys"
#else
#ifdef DATA_DIR
#define SYSDATA_DIR DATA_DIR "sys"
#else
#define SYSDATA_DIR "sys"
#endif
#endif
#if defined(__APPLE__)
sysDir = GetBundleDirectory() + DIR_SEP + SYSDATA_DIR;
#elif defined(_WIN32) || defined(LINUX_LOCAL_DEV)
sysDir = GetExeDirectory() + DIR_SEP + SYSDATA_DIR;
#elif defined ANDROID
sysDir = s_android_sys_directory;
_assert_msg_(COMMON, !sysDir.empty(), "Sys directory has not been set");
#else
sysDir = SYSDATA_DIR;
#endif
@ -705,6 +725,14 @@ std::string GetSysDirectory()
return sysDir;
}
#ifdef ANDROID
void SetSysDirectory(const std::string& path)
{
INFO_LOG(COMMON, "Setting Sys directory to %s", path.c_str());
s_android_sys_directory = path;
}
#endif
static std::string s_user_paths[NUM_PATH_INDICES];
static void RebuildUserDirectories(unsigned int dir_index)
{

View File

@ -183,6 +183,10 @@ std::string GetThemeDir(const std::string& theme_name);
// Returns the path to where the sys file are
std::string GetSysDirectory();
#ifdef ANDROID
void SetSysDirectory(const std::string& path);
#endif
#ifdef __APPLE__
std::string GetBundleDirectory();
#endif

View File

@ -77,7 +77,9 @@ void CreateDirectories()
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX));
File::CreateFullPath(File::GetUserPath(D_SHADERS_IDX) + ANAGLYPH_DIR DIR_SEP);
File::CreateFullPath(File::GetUserPath(D_STATESAVES_IDX));
#ifndef ANDROID
File::CreateFullPath(File::GetUserPath(D_THEMES_IDX));
#endif
}
void SetUserDirectory(const std::string& custom_path)