From 1311f84706041d313abb4dbf2e0ca50893399e80 Mon Sep 17 00:00:00 2001 From: zackhow Date: Fri, 14 Sep 2018 00:46:30 -0400 Subject: [PATCH] Android: Run Directory Initialization as a thread instead of service Two reasons for this change. First, it appears that some android launchers do some sort of call into the application when long pressing the app icon, which in turn calls the DirectoryInit service. This was ok to do prior to Oreo but will cause crashes with the new restrictions on services running in the background. Which leads to the second reason that DirectoryInit doesn't need to be a service at all since these actions are required for dolphin to function and shouldn't be a scheduled action. So we instead just kick this off in a new thread and send the broadcast when done. --- .../Android/app/src/main/AndroidManifest.xml | 2 +- .../dolphinemu/DolphinApplication.java | 4 +- .../activities/AppLinkActivity.java | 12 +-- .../dolphinemu/adapters/GameAdapter.java | 4 +- .../dolphinemu/adapters/GameRowPresenter.java | 4 +- .../settings/ui/SettingsActivity.java | 4 +- .../ui/SettingsActivityPresenter.java | 8 +- .../settings/ui/SettingsActivityView.java | 6 +- .../ui/SettingsFragmentPresenter.java | 4 +- .../features/settings/utils/SettingsFile.java | 10 +-- .../fragments/EmulationFragment.java | 10 +-- .../dolphinemu/ui/main/MainActivity.java | 4 +- .../dolphinemu/ui/main/TvMainActivity.java | 6 +- .../dolphinemu/utils/Analytics.java | 7 +- .../DirectoryInitialization.java} | 88 +++++++++---------- .../utils/DirectoryStateReceiver.java | 5 +- Source/Android/jni/MainAndroid.cpp | 11 ++- 17 files changed, 90 insertions(+), 99 deletions(-) rename Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/{services/DirectoryInitializationService.java => utils/DirectoryInitialization.java} (70%) diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml index 975a493860..8bf06262da 100644 --- a/Source/Android/app/src/main/AndroidManifest.xml +++ b/Source/Android/app/src/main/AndroidManifest.xml @@ -84,7 +84,7 @@ - + { if (directoryInitializationState == - DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) + DirectoryInitialization.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) { play(playAction); } else if (directoryInitializationState == - DirectoryInitializationService.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) + DirectoryInitialization.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED) { Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT) .show(); } else if (directoryInitializationState == - DirectoryInitializationService.DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE) + DirectoryInitialization.DirectoryInitializationState.CANT_FIND_EXTERNAL_STORAGE) { Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT) .show(); @@ -92,7 +92,7 @@ public class AppLinkActivity extends FragmentActivity LocalBroadcastManager.getInstance(this).registerReceiver( directoryStateReceiver, statusIntentFilter); - DirectoryInitializationService.startService(this); + DirectoryInitialization.start(this); GameFileCacheService.startLoad(this); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java index 4b07d834fd..17ae613be6 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.java @@ -15,7 +15,7 @@ import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; import org.dolphinemu.dolphinemu.model.GameFile; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.PicassoUtils; import org.dolphinemu.dolphinemu.viewholders.GameViewHolder; @@ -166,7 +166,7 @@ public final class GameAdapter extends RecyclerView.Adapter impl break; case 2: String path = - DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + + DirectoryInitialization.getUserDirectory() + "/GameSettings/" + gameId + ".ini"; File gameSettingsFile = new File(path); if (gameSettingsFile.exists()) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java index 0cbf0a9cfd..2cf23080b1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.java @@ -17,7 +17,7 @@ import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; import org.dolphinemu.dolphinemu.model.GameFile; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.utils.PicassoUtils; import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; @@ -113,7 +113,7 @@ public final class GameRowPresenter extends Presenter SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId); break; case 2: - String path = DirectoryInitializationService.getUserDirectory() + + String path = DirectoryInitialization.getUserDirectory() + "/GameSettings/" + gameId + ".ini"; File gameSettingsFile = new File(path); if (gameSettingsFile.exists()) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java index 256b38f22a..78b8ef2d1f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivity.java @@ -15,7 +15,7 @@ import android.view.MenuItem; import android.widget.Toast; import org.dolphinemu.dolphinemu.R; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView @@ -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/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java index acf1abd7dd..57bbe9d6cc 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityPresenter.java @@ -6,8 +6,8 @@ import android.text.TextUtils; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.features.settings.model.Settings; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState; import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.Log; @@ -71,7 +71,7 @@ public final class SettingsActivityPresenter private void prepareDolphinDirectoriesIfNeeded() { - if (DirectoryInitializationService.areDolphinDirectoriesReady()) + if (DirectoryInitialization.areDolphinDirectoriesReady()) { loadSettingsUI(); } @@ -79,7 +79,7 @@ public final class SettingsActivityPresenter { mView.showLoading(); IntentFilter statusIntentFilter = new IntentFilter( - DirectoryInitializationService.BROADCAST_ACTION); + DirectoryInitialization.BROADCAST_ACTION); directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java index 278c732556..910c9f0014 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsActivityView.java @@ -120,15 +120,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/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java index 1aaf8eb4a3..39e380f446 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/ui/SettingsFragmentPresenter.java @@ -20,7 +20,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting; import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting; import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting; import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.EGLHelper; import org.dolphinemu.dolphinemu.utils.Log; @@ -473,7 +473,7 @@ public final class SettingsFragmentPresenter try { String shadersPath = - DirectoryInitializationService.getDolphinInternalDirectory() + "/Shaders"; + DirectoryInitialization.getDolphinInternalDirectory() + "/Shaders"; if (!TextUtils.isEmpty(subDir)) { shadersPath += "/" + subDir; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java index e86b68af69..23763ebee1 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/utils/SettingsFile.java @@ -11,7 +11,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.SettingSection; import org.dolphinemu.dolphinemu.features.settings.model.Settings; import org.dolphinemu.dolphinemu.features.settings.model.StringSetting; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivityView; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.utils.BiMap; import org.dolphinemu.dolphinemu.utils.Log; @@ -462,7 +462,7 @@ public final class SettingsFile private static File getSettingsFile(String fileName) { return new File( - DirectoryInitializationService.getUserDirectory() + "/Config/" + fileName + ".ini"); + DirectoryInitialization.getUserDirectory() + "/Config/" + fileName + ".ini"); } private static File getGenericGameSettingsForAllRegions(String gameId) @@ -470,21 +470,21 @@ public final class SettingsFile // Use the first 3 chars from the gameId to load the generic game settings for all regions gameId = gameId.substring(0, 3); return new File( - DirectoryInitializationService.getDolphinInternalDirectory() + "/GameSettings/" + + DirectoryInitialization.getDolphinInternalDirectory() + "/GameSettings/" + gameId + ".ini"); } private static File getGenericGameSettingsFile(String gameId) { return new File( - DirectoryInitializationService.getDolphinInternalDirectory() + "/GameSettings/" + + DirectoryInitialization.getDolphinInternalDirectory() + "/GameSettings/" + gameId + ".ini"); } private static File getCustomGameSettingsFile(String gameId) { return new File( - DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + gameId + ".ini"); + DirectoryInitialization.getUserDirectory() + "/GameSettings/" + gameId + ".ini"); } private static SettingSection sectionFromLine(String line, boolean isCustomGame) 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 68d0939da7..15d1ee8298 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 @@ -20,8 +20,8 @@ import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.overlay.InputOverlay; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState; import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.StartupHandler; @@ -127,7 +127,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C public void onResume() { super.onResume(); - if (DirectoryInitializationService.areDolphinDirectoriesReady()) + if (DirectoryInitialization.areDolphinDirectoriesReady()) { mEmulationState.run(activity.isActivityRecreated()); } @@ -160,7 +160,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C private void setupDolphinDirectoriesThenStartEmulation() { IntentFilter statusIntentFilter = new IntentFilter( - DirectoryInitializationService.BROADCAST_ACTION); + DirectoryInitialization.BROADCAST_ACTION); directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> @@ -189,7 +189,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C LocalBroadcastManager.getInstance(getActivity()).registerReceiver( directoryStateReceiver, statusIntentFilter); - DirectoryInitializationService.startService(getActivity()); + DirectoryInitialization.start(getActivity()); } public void toggleInputOverlayVisibility() diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java index ed95cab7d6..f5eee1bc68 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java @@ -19,7 +19,7 @@ import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter; import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.services.GameFileCacheService; import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView; @@ -188,7 +188,7 @@ public final class MainActivity extends AppCompatActivity implements MainView case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - DirectoryInitializationService.startService(this); + DirectoryInitialization.start(this); PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter( getSupportFragmentManager(), this); mViewPager.setAdapter(platformPagerAdapter); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java index 6f73be35c9..f8b71eaed0 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java @@ -22,7 +22,7 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; import org.dolphinemu.dolphinemu.model.GameFile; import org.dolphinemu.dolphinemu.model.TvSettingsItem; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization; import org.dolphinemu.dolphinemu.services.GameFileCacheService; import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.utils.FileBrowserHelper; @@ -158,7 +158,7 @@ public final class TvMainActivity extends FragmentActivity implements MainView // Kicks off the program services to update all channels TvUtil.updateAllChannels(getApplicationContext()); - recreate(); + buildRowsAdapter(); } /** @@ -195,7 +195,7 @@ public final class TvMainActivity extends FragmentActivity implements MainView case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { - DirectoryInitializationService.startService(this); + DirectoryInitialization.start(this); GameFileCacheService.startLoad(this); } else diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java index e68852233c..6f3e07cbb5 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/Analytics.java @@ -15,7 +15,6 @@ import org.dolphinemu.dolphinemu.DolphinApplication; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.features.settings.model.Settings; import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; public class Analytics { @@ -36,16 +35,16 @@ public class Analytics SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); if (!preferences.getBoolean(analyticsAsked, false)) { - if (!DirectoryInitializationService.areDolphinDirectoriesReady()) + if (!DirectoryInitialization.areDolphinDirectoriesReady()) { // Wait for directories to get initialized IntentFilter statusIntentFilter = new IntentFilter( - DirectoryInitializationService.BROADCAST_ACTION); + DirectoryInitialization.BROADCAST_ACTION); directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> { if (directoryInitializationState == - DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) + DirectoryInitialization.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) { LocalBroadcastManager.getInstance(context).unregisterReceiver(directoryStateReceiver); directoryStateReceiver = null; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/DirectoryInitializationService.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java similarity index 70% rename from Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/DirectoryInitializationService.java rename to Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java index 74e8a63fa4..b0132c215f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/DirectoryInitializationService.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryInitialization.java @@ -4,9 +4,8 @@ * Refer to the license.txt file included. */ -package org.dolphinemu.dolphinemu.services; +package org.dolphinemu.dolphinemu.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.dolphinemu.dolphinemu.NativeLibrary; -import org.dolphinemu.dolphinemu.utils.Log; -import org.dolphinemu.dolphinemu.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.dolphinemu.dolphinemu.DIRECTORY_INITIALIZATION"; @@ -48,31 +45,26 @@ public final class DirectoryInitializationService extends IntentService CANT_FIND_EXTERNAL_STORAGE } - public DirectoryInitializationService() + public static void start(Context context) { - // Superclass constructor is called to name the thread on which this service executes. - super("DirectoryInitializationService"); + // 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) + private static void init(Context context) { - Intent intent = new Intent(context, DirectoryInitializationService.class); - context.startService(intent); - } - - @Override - protected void onHandleIntent(Intent intent) - { - isDolphinDirectoryInitializationRunning.set(true); + if (!isDolphinDirectoryInitializationRunning.compareAndSet(false, true)) + return; if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) { - if (PermissionsHandler.hasWriteAccess(this)) + if (PermissionsHandler.hasWriteAccess(context)) { if (setDolphinUserDirectory()) { - initializeInternalStorage(); - initializeExternalStorage(); + initializeInternalStorage(context); + initializeExternalStorage(context); directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; } @@ -88,10 +80,10 @@ public final class DirectoryInitializationService extends IntentService } isDolphinDirectoryInitializationRunning.set(false); - sendBroadcastState(directoryState); + sendBroadcastState(directoryState, context); } - private boolean setDolphinUserDirectory() + private static boolean setDolphinUserDirectory() { if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { @@ -99,7 +91,7 @@ public final class DirectoryInitializationService extends IntentService if (externalPath != null) { userPath = externalPath.getAbsolutePath() + "/dolphin-emu"; - Log.debug("[DirectoryInitializationService] User Dir: " + userPath); + Log.debug("[DirectoryInitialization] User Dir: " + userPath); NativeLibrary.SetUserDirectory(userPath); return true; } @@ -109,19 +101,19 @@ public final class DirectoryInitializationService extends IntentService return false; } - private void initializeInternalStorage() + private static void initializeInternalStorage(Context context) { - File sysDirectory = new File(getFilesDir(), "Sys"); + File sysDirectory = new File(context.getFilesDir(), "Sys"); internalPath = sysDirectory.getAbsolutePath(); - 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); @@ -132,7 +124,7 @@ public final class DirectoryInitializationService extends IntentService SetSysDirectory(sysDirectory.getPath()); } - private void initializeExternalStorage() + private static void initializeExternalStorage(Context context) { // Create User directory structure and copy some NAND files from the extracted Sys directory. CreateUserDirectories(); @@ -147,8 +139,8 @@ public final class DirectoryInitializationService extends IntentService // // 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); + copyAsset("GCPadNew.ini", new File(configDirectory, "GCPadNew.ini"), true, context); + copyAsset("WiimoteNew.ini", new File(configDirectory, "WiimoteNew.ini"), false, context); } private static void deleteDirectoryRecursively(File file) @@ -170,12 +162,12 @@ public final class DirectoryInitializationService extends IntentService { 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; @@ -185,34 +177,34 @@ public final class DirectoryInitializationService extends IntentService { 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 internalPath; } - 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) + private static void copyAsset(String asset, File output, Boolean overwrite, Context context) { - Log.verbose("[DirectoryInitializationService] Copying File " + asset + " to " + output); + 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(); @@ -221,20 +213,21 @@ public final class DirectoryInitializationService extends IntentService } 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) + private static void copyAssetFolder(String assetFolder, File outputFolder, Boolean overwrite, + Context context) { - Log.verbose("[DirectoryInitializationService] Copying Folder " + assetFolder + " to " + + 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) { @@ -242,18 +235,19 @@ public final class DirectoryInitializationService extends IntentService 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/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryStateReceiver.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryStateReceiver.java index 2471e50a32..fe51b41c3f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryStateReceiver.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/DirectoryStateReceiver.java @@ -4,8 +4,7 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; -import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState; +import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState; import rx.functions.Action1; @@ -22,7 +21,7 @@ public class DirectoryStateReceiver extends BroadcastReceiver 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/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index a160786063..089d0b776d 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -246,8 +246,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs( jobject obj, jstring path); JNIEXPORT void JNICALL -Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_CreateUserDirectories( - JNIEnv* env, jobject obj); +Java_org_dolphinemu_dolphinemu_utils_DirectoryInitialization_CreateUserDirectories(JNIEnv* env, + jobject obj); JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory( JNIEnv* env, jobject obj, jstring jDirectory); JNIEXPORT jstring JNICALL @@ -457,8 +457,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs( State::LoadAs(GetJString(env, path)); } -JNIEXPORT void JNICALL -Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_SetSysDirectory( +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_DirectoryInitialization_SetSysDirectory( JNIEnv* env, jobject obj, jstring jPath) { const std::string path = GetJString(env, jPath); @@ -466,8 +465,8 @@ Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_SetSysDir } JNIEXPORT void JNICALL -Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_CreateUserDirectories( - JNIEnv* env, jobject obj) +Java_org_dolphinemu_dolphinemu_utils_DirectoryInitialization_CreateUserDirectories(JNIEnv* env, + jobject obj) { UICommon::CreateDirectories(); }