diff --git a/src/android/app/src/main/AndroidManifest.xml b/src/android/app/src/main/AndroidManifest.xml index 674ee214d..df1215e60 100644 --- a/src/android/app/src/main/AndroidManifest.xml +++ b/src/android/app/src/main/AndroidManifest.xml @@ -73,7 +73,7 @@ - + @@ -163,7 +163,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C LocalBroadcastManager.getInstance(getActivity()).registerReceiver( directoryStateReceiver, statusIntentFilter); - DirectoryInitializationService.startService(getActivity()); + DirectoryInitialization.start(getActivity()); } public void refreshInputOverlay() { @@ -190,8 +190,8 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C { final double[] perfStats = NativeLibrary.GetPerfStats(); if (perfStats[FPS] > 0) { - mPerfStats.setText(String.format("FPS: %d Speed: %d%%", (int)(perfStats[FPS] + 0.5), - (int)(perfStats[SPEED] * 100.0 + 0.5))); + mPerfStats.setText(String.format("FPS: %d Speed: %d%%", (int) (perfStats[FPS] + 0.5), + (int) (perfStats[SPEED] * 100.0 + 0.5))); } perfStatsUpdateHandler.postDelayed(perfStatsUpdater, 3000); diff --git a/src/android/app/src/main/java/org/citra/citra_emu/ui/main/MainActivity.java b/src/android/app/src/main/java/org/citra/citra_emu/ui/main/MainActivity.java index 30585257e..99c29ffc9 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/ui/main/MainActivity.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/ui/main/MainActivity.java @@ -15,7 +15,7 @@ import android.widget.Toast; import org.citra.citra_emu.R; import org.citra.citra_emu.activities.EmulationActivity; import org.citra.citra_emu.model.GameProvider; -import org.citra.citra_emu.services.DirectoryInitializationService; +import org.citra.citra_emu.utils.DirectoryInitialization; import org.citra.citra_emu.ui.platform.PlatformGamesFragment; import org.citra.citra_emu.ui.platform.PlatformGamesView; import org.citra.citra_emu.ui.settings.SettingsActivity; @@ -168,7 +168,7 @@ public final class MainActivity extends AppCompatActivity implements MainView { switch (requestCode) { case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - DirectoryInitializationService.startService(this); + DirectoryInitialization.start(this); mPlatformGamesFragment = new PlatformGamesFragment(); getSupportFragmentManager().beginTransaction().add(mFrameLayoutId, mPlatformGamesFragment) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/ui/main/TvMainActivity.java b/src/android/app/src/main/java/org/citra/citra_emu/ui/main/TvMainActivity.java index 3ea8896f4..352f08949 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/ui/main/TvMainActivity.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/ui/main/TvMainActivity.java @@ -23,7 +23,7 @@ import org.citra.citra_emu.adapters.GameRowPresenter; import org.citra.citra_emu.adapters.SettingsRowPresenter; import org.citra.citra_emu.model.Game; import org.citra.citra_emu.model.TvSettingsItem; -import org.citra.citra_emu.services.DirectoryInitializationService; +import org.citra.citra_emu.utils.DirectoryInitialization; import org.citra.citra_emu.ui.settings.SettingsActivity; import org.citra.citra_emu.utils.AddDirectoryHelper; import org.citra.citra_emu.utils.FileBrowserHelper; @@ -160,7 +160,7 @@ public final class TvMainActivity extends FragmentActivity implements MainView { switch (requestCode) { case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - DirectoryInitializationService.startService(this); + DirectoryInitialization.start(this); loadGames(); } else { Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivity.java b/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivity.java index e8aa935a8..e01d0b4d5 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivity.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivity.java @@ -16,7 +16,7 @@ import android.widget.Toast; import org.citra.citra_emu.R; import org.citra.citra_emu.model.settings.SettingSection; -import org.citra.citra_emu.services.DirectoryInitializationService; +import org.citra.citra_emu.utils.DirectoryInitialization; import org.citra.citra_emu.utils.DirectoryStateReceiver; import java.util.ArrayList; @@ -142,7 +142,7 @@ public final class SettingsActivity extends AppCompatActivity implements Setting LocalBroadcastManager.getInstance(this).registerReceiver( receiver, filter); - DirectoryInitializationService.startService(this); + DirectoryInitialization.start(this); } @Override diff --git a/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivityPresenter.java b/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivityPresenter.java index b4df11354..04b843592 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivityPresenter.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivityPresenter.java @@ -6,8 +6,8 @@ import android.text.TextUtils; import org.citra.citra_emu.NativeLibrary; import org.citra.citra_emu.model.settings.SettingSection; -import org.citra.citra_emu.services.DirectoryInitializationService; -import org.citra.citra_emu.services.DirectoryInitializationService.DirectoryInitializationState; +import org.citra.citra_emu.utils.DirectoryInitialization; +import org.citra.citra_emu.utils.DirectoryInitialization.DirectoryInitializationState; import org.citra.citra_emu.utils.DirectoryStateReceiver; import org.citra.citra_emu.utils.Log; import org.citra.citra_emu.utils.SettingsFile; @@ -63,16 +63,16 @@ public final class SettingsActivityPresenter { } private void prepareDolphinDirectoriesIfNeeded() { - File configFile = new File(DirectoryInitializationService.getUserDirectory() + "/config/" + SettingsFile.FILE_NAME_CONFIG + ".ini"); + File configFile = new File(DirectoryInitialization.getUserDirectory() + "/config/" + SettingsFile.FILE_NAME_CONFIG + ".ini"); if (!configFile.exists()) { } - if (DirectoryInitializationService.areDolphinDirectoriesReady()) { + if (DirectoryInitialization.areDolphinDirectoriesReady()) { loadSettingsUI(); } else { mView.showLoading(); IntentFilter statusIntentFilter = new IntentFilter( - DirectoryInitializationService.BROADCAST_ACTION); + DirectoryInitialization.BROADCAST_ACTION); directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> diff --git a/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivityView.java b/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivityView.java index 2b6924fd0..1785b6378 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivityView.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/ui/settings/SettingsActivityView.java @@ -124,15 +124,15 @@ public interface SettingsActivityView { void showExternalStorageNotMountedHint(); /** - * Start the DirectoryInitializationService and listen for the result. + * Start the DirectoryInitialization and listen for the result. * - * @param receiver the broadcast receiver for the DirectoryInitializationService + * @param receiver the broadcast receiver for the DirectoryInitialization * @param filter the Intent broadcasts to be received. */ void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter); /** - * Stop listening to the DirectoryInitializationService. + * Stop listening to the DirectoryInitialization. * * @param receiver The broadcast receiver to unregister. */ diff --git a/src/android/app/src/main/java/org/citra/citra_emu/services/DirectoryInitializationService.java b/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryInitialization.java similarity index 68% rename from src/android/app/src/main/java/org/citra/citra_emu/services/DirectoryInitializationService.java rename to src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryInitialization.java index 861961370..e47d1f4b6 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/services/DirectoryInitializationService.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryInitialization.java @@ -4,9 +4,8 @@ * Refer to the license.txt file included. */ -package org.citra.citra_emu.services; +package org.citra.citra_emu.utils; -import android.app.IntentService; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -15,8 +14,6 @@ import android.preference.PreferenceManager; import android.support.v4.content.LocalBroadcastManager; import org.citra.citra_emu.NativeLibrary; -import org.citra.citra_emu.utils.Log; -import org.citra.citra_emu.utils.PermissionsHandler; import java.io.File; import java.io.FileOutputStream; @@ -30,7 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * A service that spawns its own thread in order to copy several binary and shader files * from the Dolphin APK to the external file system. */ -public final class DirectoryInitializationService extends IntentService { +public final class DirectoryInitialization { public static final String BROADCAST_ACTION = "org.citra.citra_emu.BROADCAST"; public static final String EXTRA_STATE = "directoryState"; @@ -38,14 +35,33 @@ public final class DirectoryInitializationService extends IntentService { private static String userPath; private static AtomicBoolean isDolphinDirectoryInitializationRunning = new AtomicBoolean(false); - public DirectoryInitializationService() { - // Superclass constructor is called to name the thread on which this service executes. - super("DirectoryInitializationService"); + public static void start(Context context) { + // Can take a few seconds to run, so don't block UI thread. + //noinspection TrivialFunctionalExpressionUsage + ((Runnable) () -> init(context)).run(); } - public static void startService(Context context) { - Intent intent = new Intent(context, DirectoryInitializationService.class); - context.startService(intent); + private static void init(Context context) { + if (!isDolphinDirectoryInitializationRunning.compareAndSet(false, true)) + return; + + if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) { + if (PermissionsHandler.hasWriteAccess(context)) { + if (setDolphinUserDirectory()) { + initializeInternalStorage(context); + CreateUserDirectories(); + NativeLibrary.CreateConfigFile(); + directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; + } else { + directoryState = DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE; + } + } else { + directoryState = DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED; + } + } + + isDolphinDirectoryInitializationRunning.set(false); + sendBroadcastState(directoryState, context); } private static void deleteDirectoryRecursively(File file) { @@ -62,10 +78,10 @@ public final class DirectoryInitializationService extends IntentService { public static String getUserDirectory() { if (directoryState == null) { - throw new IllegalStateException("DirectoryInitializationService has to run at least once!"); + throw new IllegalStateException("DirectoryInitialization has to run at least once!"); } else if (isDolphinDirectoryInitializationRunning.get()) { throw new IllegalStateException( - "DirectoryInitializationService has to finish running first!"); + "DirectoryInitialization has to finish running first!"); } return userPath; @@ -75,35 +91,12 @@ public final class DirectoryInitializationService extends IntentService { private static native void SetSysDirectory(String path); - @Override - protected void onHandleIntent(Intent intent) { - isDolphinDirectoryInitializationRunning.set(true); - - if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) { - if (PermissionsHandler.hasWriteAccess(this)) { - if (setDolphinUserDirectory()) { - initializeInternalStorage(); - CreateUserDirectories(); - NativeLibrary.CreateConfigFile(); - directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; - } else { - directoryState = DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE; - } - } else { - directoryState = DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED; - } - } - - isDolphinDirectoryInitializationRunning.set(false); - sendBroadcastState(directoryState); - } - - private boolean setDolphinUserDirectory() { + private static boolean setDolphinUserDirectory() { if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { File externalPath = Environment.getExternalStorageDirectory(); if (externalPath != null) { userPath = externalPath.getAbsolutePath() + "/citra-emu"; - Log.debug("[DirectoryInitializationService] User Dir: " + userPath); + Log.debug("[DirectoryInitialization] User Dir: " + userPath); // NativeLibrary.SetUserDirectory(userPath); return true; } @@ -113,16 +106,16 @@ public final class DirectoryInitializationService extends IntentService { return false; } - private void initializeInternalStorage() { - File sysDirectory = new File(getFilesDir(), "Sys"); + private static void initializeInternalStorage(Context context) { + File sysDirectory = new File(context.getFilesDir(), "Sys"); - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); + SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); 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); + copyAssetFolder("Sys", sysDirectory, true, context); SharedPreferences.Editor editor = preferences.edit(); editor.putString("sysDirectoryVersion", revision); @@ -133,52 +126,54 @@ public final class DirectoryInitializationService extends IntentService { SetSysDirectory(sysDirectory.getPath()); } - private void sendBroadcastState(DirectoryInitializationState state) { + private static void sendBroadcastState(DirectoryInitializationState state, Context context) { Intent localIntent = new Intent(BROADCAST_ACTION) .putExtra(EXTRA_STATE, state); - LocalBroadcastManager.getInstance(this).sendBroadcast(localIntent); + LocalBroadcastManager.getInstance(context).sendBroadcast(localIntent); } - private void copyAsset(String asset, File output, Boolean overwrite) { - Log.verbose("[DirectoryInitializationService] Copying File " + asset + " to " + output); + private static void copyAsset(String asset, File output, Boolean overwrite, Context context) { + Log.verbose("[DirectoryInitialization] Copying File " + asset + " to " + output); try { if (!output.exists() || overwrite) { - InputStream in = getAssets().open(asset); + InputStream in = context.getAssets().open(asset); OutputStream out = new FileOutputStream(output); copyFile(in, out); in.close(); out.close(); } } catch (IOException e) { - Log.error("[DirectoryInitializationService] Failed to copy asset file: " + asset + + Log.error("[DirectoryInitialization] Failed to copy asset file: " + asset + e.getMessage()); } } - private void copyAssetFolder(String assetFolder, File outputFolder, Boolean overwrite) { - Log.verbose("[DirectoryInitializationService] Copying Folder " + assetFolder + " to " + + private static void copyAssetFolder(String assetFolder, File outputFolder, Boolean overwrite, + Context context) { + Log.verbose("[DirectoryInitialization] Copying Folder " + assetFolder + " to " + outputFolder); try { boolean createdFolder = false; - for (String file : getAssets().list(assetFolder)) { + for (String file : context.getAssets().list(assetFolder)) { 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); + overwrite, context); + copyAsset(assetFolder + File.separator + file, new File(outputFolder, file), overwrite, + context); } } catch (IOException e) { - Log.error("[DirectoryInitializationService] Failed to copy asset folder: " + assetFolder + + Log.error("[DirectoryInitialization] Failed to copy asset folder: " + assetFolder + e.getMessage()); } } - private void copyFile(InputStream in, OutputStream out) throws IOException { + private static void copyFile(InputStream in, OutputStream out) throws IOException { byte[] buffer = new byte[1024]; int read; diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryStateReceiver.java b/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryStateReceiver.java index 60c7931f2..851f1e1d6 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryStateReceiver.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/DirectoryStateReceiver.java @@ -4,8 +4,8 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import org.citra.citra_emu.services.DirectoryInitializationService; -import org.citra.citra_emu.services.DirectoryInitializationService.DirectoryInitializationState; +import org.citra.citra_emu.utils.DirectoryInitialization; +import org.citra.citra_emu.utils.DirectoryInitialization.DirectoryInitializationState; import rx.functions.Action1; @@ -19,7 +19,7 @@ public class DirectoryStateReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { DirectoryInitializationState state = (DirectoryInitializationState) intent - .getSerializableExtra(DirectoryInitializationService.EXTRA_STATE); + .getSerializableExtra(DirectoryInitialization.EXTRA_STATE); callback.call(state); } } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/SettingsFile.java b/src/android/app/src/main/java/org/citra/citra_emu/utils/SettingsFile.java index 044469530..1e64b477e 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/SettingsFile.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/SettingsFile.java @@ -7,7 +7,7 @@ import org.citra.citra_emu.model.settings.IntSetting; import org.citra.citra_emu.model.settings.Setting; import org.citra.citra_emu.model.settings.SettingSection; import org.citra.citra_emu.model.settings.StringSetting; -import org.citra.citra_emu.services.DirectoryInitializationService; +import org.citra.citra_emu.utils.DirectoryInitialization; import org.citra.citra_emu.ui.settings.SettingsActivityView; import org.ini4j.Wini; @@ -212,7 +212,7 @@ public final class SettingsFile { @NonNull private static File getSettingsFile(String fileName) { return new File( - DirectoryInitializationService.getUserDirectory() + "/config/" + fileName + ".ini"); + DirectoryInitialization.getUserDirectory() + "/config/" + fileName + ".ini"); } private static SettingSection sectionFromLine(String line) { diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp index ff38430a0..c8a028e7d 100644 --- a/src/android/app/src/main/jni/native.cpp +++ b/src/android/app/src/main/jni/native.cpp @@ -374,11 +374,10 @@ void Java_org_citra_citra_1emu_NativeLibrary_LoadState(JNIEnv* env, jobject obj, void Java_org_citra_citra_1emu_NativeLibrary_LoadStateAs(JNIEnv* env, jobject obj, jstring path) {} -void Java_org_citra_citra_1emu_services_DirectoryInitializationService_CreateUserDirectories( +void Java_org_citra_citra_1emu_utils_DirectoryInitialization_CreateUserDirectories( JNIEnv* env, jobject obj) {} jstring Java_org_citra_citra_1emu_NativeLibrary_GetUserDirectory(JNIEnv* env, jobject obj) { - return nullptr; } @@ -461,7 +460,7 @@ jdoubleArray Java_org_citra_citra_1emu_NativeLibrary_GetPerfStats(JNIEnv* env, j return jstats; } -void Java_org_citra_citra_1emu_services_DirectoryInitializationService_SetSysDirectory( +void Java_org_citra_citra_1emu_utils_DirectoryInitialization_SetSysDirectory( JNIEnv* env, jclass type, jstring path_) { const char* path = env->GetStringUTFChars(path_, 0); diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index 535d8214c..a544bd9c4 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h @@ -109,14 +109,14 @@ JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_LoadStateAs(JNIEn jstring path); JNIEXPORT void JNICALL -Java_org_citra_citra_1emu_services_DirectoryInitializationService_CreateUserDirectories( +Java_org_citra_citra_1emu_utils_DirectoryInitialization_CreateUserDirectories( JNIEnv* env, jobject obj); JNIEXPORT void JNICALL Java_org_citra_citra_1emu_NativeLibrary_SetUserDirectory( JNIEnv* env, jobject obj, jstring jDirectory); JNIEXPORT void JNICALL -Java_org_citra_citra_1emu_services_DirectoryInitializationService_SetSysDirectory( +Java_org_citra_citra_1emu_utils_DirectoryInitialization_SetSysDirectory( JNIEnv* env, jclass type, jstring path_); JNIEXPORT jstring JNICALL Java_org_citra_citra_1emu_NativeLibrary_GetUserDirectory(JNIEnv* env,