Merge pull request #7413 from zackhow/launcher-crash

Android: Run Directory Initialization as a thread instead of service
This commit is contained in:
JosJuice 2018-10-05 15:45:36 +02:00 committed by GitHub
commit 683eef3044
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 90 additions and 99 deletions

View File

@ -85,7 +85,7 @@
</intent-filter> </intent-filter>
</activity> </activity>
<service android:name=".services.DirectoryInitializationService"/> <service android:name=".utils.DirectoryInitialization"/>
<service android:name=".services.GameFileCacheService"/> <service android:name=".services.GameFileCacheService"/>
<service <service
android:name=".services.SyncChannelJobService" android:name=".services.SyncChannelJobService"

View File

@ -3,7 +3,7 @@ package org.dolphinemu.dolphinemu;
import android.app.Application; import android.app.Application;
import android.content.Context; import android.content.Context;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.utils.PermissionsHandler; import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
import org.dolphinemu.dolphinemu.utils.VolleyUtil; import org.dolphinemu.dolphinemu.utils.VolleyUtil;
@ -20,7 +20,7 @@ public class DolphinApplication extends Application
System.loadLibrary("main"); System.loadLibrary("main");
if (PermissionsHandler.hasWriteAccess(getApplicationContext())) if (PermissionsHandler.hasWriteAccess(getApplicationContext()))
DirectoryInitializationService.startService(getApplicationContext()); DirectoryInitialization.start(getApplicationContext());
} }
public static Context getAppContext() public static Context getAppContext()

View File

@ -11,7 +11,7 @@ import android.widget.Toast;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.GameFile; import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.services.GameFileCacheService; import org.dolphinemu.dolphinemu.services.GameFileCacheService;
import org.dolphinemu.dolphinemu.ui.main.TvMainActivity; import org.dolphinemu.dolphinemu.ui.main.TvMainActivity;
import org.dolphinemu.dolphinemu.utils.AppLinkHelper; import org.dolphinemu.dolphinemu.utils.AppLinkHelper;
@ -64,24 +64,24 @@ public class AppLinkActivity extends FragmentActivity
private void initResources() private void initResources()
{ {
IntentFilter statusIntentFilter = new IntentFilter( IntentFilter statusIntentFilter = new IntentFilter(
DirectoryInitializationService.BROADCAST_ACTION); DirectoryInitialization.BROADCAST_ACTION);
directoryStateReceiver = directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState -> new DirectoryStateReceiver(directoryInitializationState ->
{ {
if (directoryInitializationState == if (directoryInitializationState ==
DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) DirectoryInitialization.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{ {
play(playAction); play(playAction);
} }
else if (directoryInitializationState == 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) Toast.makeText(this, R.string.write_permission_needed, Toast.LENGTH_SHORT)
.show(); .show();
} }
else if (directoryInitializationState == 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) Toast.makeText(this, R.string.external_storage_not_mounted, Toast.LENGTH_SHORT)
.show(); .show();
@ -92,7 +92,7 @@ public class AppLinkActivity extends FragmentActivity
LocalBroadcastManager.getInstance(this).registerReceiver( LocalBroadcastManager.getInstance(this).registerReceiver(
directoryStateReceiver, directoryStateReceiver,
statusIntentFilter); statusIntentFilter);
DirectoryInitializationService.startService(this); DirectoryInitialization.start(this);
GameFileCacheService.startLoad(this); GameFileCacheService.startLoad(this);
} }

View File

@ -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.MenuTag;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
import org.dolphinemu.dolphinemu.model.GameFile; 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.utils.PicassoUtils;
import org.dolphinemu.dolphinemu.viewholders.GameViewHolder; import org.dolphinemu.dolphinemu.viewholders.GameViewHolder;
@ -166,7 +166,7 @@ public final class GameAdapter extends RecyclerView.Adapter<GameViewHolder> impl
break; break;
case 2: case 2:
String path = String path =
DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + DirectoryInitialization.getUserDirectory() + "/GameSettings/" +
gameId + ".ini"; gameId + ".ini";
File gameSettingsFile = new File(path); File gameSettingsFile = new File(path);
if (gameSettingsFile.exists()) if (gameSettingsFile.exists())

View File

@ -17,7 +17,7 @@ import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
import org.dolphinemu.dolphinemu.model.GameFile; 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.ui.platform.Platform;
import org.dolphinemu.dolphinemu.utils.PicassoUtils; import org.dolphinemu.dolphinemu.utils.PicassoUtils;
import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder;
@ -113,7 +113,7 @@ public final class GameRowPresenter extends Presenter
SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId); SettingsActivity.launch(activity, MenuTag.GRAPHICS, gameId);
break; break;
case 2: case 2:
String path = DirectoryInitializationService.getUserDirectory() + String path = DirectoryInitialization.getUserDirectory() +
"/GameSettings/" + gameId + ".ini"; "/GameSettings/" + gameId + ".ini";
File gameSettingsFile = new File(path); File gameSettingsFile = new File(path);
if (gameSettingsFile.exists()) if (gameSettingsFile.exists())

View File

@ -15,7 +15,7 @@ import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView
@ -142,7 +142,7 @@ public final class SettingsActivity extends AppCompatActivity implements Setting
LocalBroadcastManager.getInstance(this).registerReceiver( LocalBroadcastManager.getInstance(this).registerReceiver(
receiver, receiver,
filter); filter);
DirectoryInitializationService.startService(this); DirectoryInitialization.start(this);
} }
@Override @Override

View File

@ -6,8 +6,8 @@ import android.text.TextUtils;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.Settings; import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
@ -71,7 +71,7 @@ public final class SettingsActivityPresenter
private void prepareDolphinDirectoriesIfNeeded() private void prepareDolphinDirectoriesIfNeeded()
{ {
if (DirectoryInitializationService.areDolphinDirectoriesReady()) if (DirectoryInitialization.areDolphinDirectoriesReady())
{ {
loadSettingsUI(); loadSettingsUI();
} }
@ -79,7 +79,7 @@ public final class SettingsActivityPresenter
{ {
mView.showLoading(); mView.showLoading();
IntentFilter statusIntentFilter = new IntentFilter( IntentFilter statusIntentFilter = new IntentFilter(
DirectoryInitializationService.BROADCAST_ACTION); DirectoryInitialization.BROADCAST_ACTION);
directoryStateReceiver = directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState -> new DirectoryStateReceiver(directoryInitializationState ->

View File

@ -120,15 +120,15 @@ public interface SettingsActivityView
void showExternalStorageNotMountedHint(); 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. * @param filter the Intent broadcasts to be received.
*/ */
void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter); void startDirectoryInitializationService(DirectoryStateReceiver receiver, IntentFilter filter);
/** /**
* Stop listening to the DirectoryInitializationService. * Stop listening to the DirectoryInitialization.
* *
* @param receiver The broadcast receiver to unregister. * @param receiver The broadcast receiver to unregister.
*/ */

View File

@ -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.StringSingleChoiceSetting;
import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting; import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile; 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.EGLHelper;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
@ -473,7 +473,7 @@ public final class SettingsFragmentPresenter
try try
{ {
String shadersPath = String shadersPath =
DirectoryInitializationService.getDolphinInternalDirectory() + "/Shaders"; DirectoryInitialization.getDolphinInternalDirectory() + "/Shaders";
if (!TextUtils.isEmpty(subDir)) if (!TextUtils.isEmpty(subDir))
{ {
shadersPath += "/" + subDir; shadersPath += "/" + subDir;

View File

@ -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.Settings;
import org.dolphinemu.dolphinemu.features.settings.model.StringSetting; import org.dolphinemu.dolphinemu.features.settings.model.StringSetting;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivityView; 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.BiMap;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
@ -462,7 +462,7 @@ public final class SettingsFile
private static File getSettingsFile(String fileName) private static File getSettingsFile(String fileName)
{ {
return new File( return new File(
DirectoryInitializationService.getUserDirectory() + "/Config/" + fileName + ".ini"); DirectoryInitialization.getUserDirectory() + "/Config/" + fileName + ".ini");
} }
private static File getGenericGameSettingsForAllRegions(String gameId) 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 // Use the first 3 chars from the gameId to load the generic game settings for all regions
gameId = gameId.substring(0, 3); gameId = gameId.substring(0, 3);
return new File( return new File(
DirectoryInitializationService.getDolphinInternalDirectory() + "/GameSettings/" + DirectoryInitialization.getDolphinInternalDirectory() + "/GameSettings/" +
gameId + ".ini"); gameId + ".ini");
} }
private static File getGenericGameSettingsFile(String gameId) private static File getGenericGameSettingsFile(String gameId)
{ {
return new File( return new File(
DirectoryInitializationService.getDolphinInternalDirectory() + "/GameSettings/" + DirectoryInitialization.getDolphinInternalDirectory() + "/GameSettings/" +
gameId + ".ini"); gameId + ".ini");
} }
private static File getCustomGameSettingsFile(String gameId) private static File getCustomGameSettingsFile(String gameId)
{ {
return new File( return new File(
DirectoryInitializationService.getUserDirectory() + "/GameSettings/" + gameId + ".ini"); DirectoryInitialization.getUserDirectory() + "/GameSettings/" + gameId + ".ini");
} }
private static SettingSection sectionFromLine(String line, boolean isCustomGame) private static SettingSection sectionFromLine(String line, boolean isCustomGame)

View File

@ -20,8 +20,8 @@ import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.activities.EmulationActivity; import org.dolphinemu.dolphinemu.activities.EmulationActivity;
import org.dolphinemu.dolphinemu.overlay.InputOverlay; import org.dolphinemu.dolphinemu.overlay.InputOverlay;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver; import org.dolphinemu.dolphinemu.utils.DirectoryStateReceiver;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
import org.dolphinemu.dolphinemu.utils.StartupHandler; import org.dolphinemu.dolphinemu.utils.StartupHandler;
@ -127,7 +127,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
public void onResume() public void onResume()
{ {
super.onResume(); super.onResume();
if (DirectoryInitializationService.areDolphinDirectoriesReady()) if (DirectoryInitialization.areDolphinDirectoriesReady())
{ {
mEmulationState.run(activity.isActivityRecreated()); mEmulationState.run(activity.isActivityRecreated());
} }
@ -160,7 +160,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
private void setupDolphinDirectoriesThenStartEmulation() private void setupDolphinDirectoriesThenStartEmulation()
{ {
IntentFilter statusIntentFilter = new IntentFilter( IntentFilter statusIntentFilter = new IntentFilter(
DirectoryInitializationService.BROADCAST_ACTION); DirectoryInitialization.BROADCAST_ACTION);
directoryStateReceiver = directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState -> new DirectoryStateReceiver(directoryInitializationState ->
@ -189,7 +189,7 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
LocalBroadcastManager.getInstance(getActivity()).registerReceiver( LocalBroadcastManager.getInstance(getActivity()).registerReceiver(
directoryStateReceiver, directoryStateReceiver,
statusIntentFilter); statusIntentFilter);
DirectoryInitializationService.startService(getActivity()); DirectoryInitialization.start(getActivity());
} }
public void toggleInputOverlayVisibility() public void toggleInputOverlayVisibility()

View File

@ -19,7 +19,7 @@ import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter; import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter;
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag; import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; 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.services.GameFileCacheService;
import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView; 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: case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{ {
DirectoryInitializationService.startService(this); DirectoryInitialization.start(this);
PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter( PlatformPagerAdapter platformPagerAdapter = new PlatformPagerAdapter(
getSupportFragmentManager(), this); getSupportFragmentManager(), this);
mViewPager.setAdapter(platformPagerAdapter); mViewPager.setAdapter(platformPagerAdapter);

View File

@ -22,7 +22,7 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag;
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity;
import org.dolphinemu.dolphinemu.model.GameFile; import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.model.TvSettingsItem; 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.services.GameFileCacheService;
import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper; 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 // Kicks off the program services to update all channels
TvUtil.updateAllChannels(getApplicationContext()); TvUtil.updateAllChannels(getApplicationContext());
recreate(); buildRowsAdapter();
} }
/** /**
@ -195,7 +195,7 @@ public final class TvMainActivity extends FragmentActivity implements MainView
case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION: case PermissionsHandler.REQUEST_CODE_WRITE_PERMISSION:
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
{ {
DirectoryInitializationService.startService(this); DirectoryInitialization.start(this);
GameFileCacheService.startLoad(this); GameFileCacheService.startLoad(this);
} }
else else

View File

@ -15,7 +15,6 @@ import org.dolphinemu.dolphinemu.DolphinApplication;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.features.settings.model.Settings; import org.dolphinemu.dolphinemu.features.settings.model.Settings;
import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile; import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService;
public class Analytics public class Analytics
{ {
@ -36,16 +35,16 @@ public class Analytics
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
if (!preferences.getBoolean(analyticsAsked, false)) if (!preferences.getBoolean(analyticsAsked, false))
{ {
if (!DirectoryInitializationService.areDolphinDirectoriesReady()) if (!DirectoryInitialization.areDolphinDirectoriesReady())
{ {
// Wait for directories to get initialized // Wait for directories to get initialized
IntentFilter statusIntentFilter = new IntentFilter( IntentFilter statusIntentFilter = new IntentFilter(
DirectoryInitializationService.BROADCAST_ACTION); DirectoryInitialization.BROADCAST_ACTION);
directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState -> directoryStateReceiver = new DirectoryStateReceiver(directoryInitializationState ->
{ {
if (directoryInitializationState == if (directoryInitializationState ==
DirectoryInitializationService.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) DirectoryInitialization.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{ {
LocalBroadcastManager.getInstance(context).unregisterReceiver(directoryStateReceiver); LocalBroadcastManager.getInstance(context).unregisterReceiver(directoryStateReceiver);
directoryStateReceiver = null; directoryStateReceiver = null;

View File

@ -4,9 +4,8 @@
* Refer to the license.txt file included. * 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.Context;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
@ -15,8 +14,6 @@ import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager; import android.support.v4.content.LocalBroadcastManager;
import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.NativeLibrary;
import org.dolphinemu.dolphinemu.utils.Log;
import org.dolphinemu.dolphinemu.utils.PermissionsHandler;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; 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 * 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. * 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 = public static final String BROADCAST_ACTION =
"org.dolphinemu.dolphinemu.DIRECTORY_INITIALIZATION"; "org.dolphinemu.dolphinemu.DIRECTORY_INITIALIZATION";
@ -48,31 +45,26 @@ public final class DirectoryInitializationService extends IntentService
CANT_FIND_EXTERNAL_STORAGE 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. // Can take a few seconds to run, so don't block UI thread.
super("DirectoryInitializationService"); //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); if (!isDolphinDirectoryInitializationRunning.compareAndSet(false, true))
context.startService(intent); return;
}
@Override
protected void onHandleIntent(Intent intent)
{
isDolphinDirectoryInitializationRunning.set(true);
if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED) if (directoryState != DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{ {
if (PermissionsHandler.hasWriteAccess(this)) if (PermissionsHandler.hasWriteAccess(context))
{ {
if (setDolphinUserDirectory()) if (setDolphinUserDirectory())
{ {
initializeInternalStorage(); initializeInternalStorage(context);
initializeExternalStorage(); initializeExternalStorage(context);
directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED; directoryState = DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED;
} }
@ -88,10 +80,10 @@ public final class DirectoryInitializationService extends IntentService
} }
isDolphinDirectoryInitializationRunning.set(false); isDolphinDirectoryInitializationRunning.set(false);
sendBroadcastState(directoryState); sendBroadcastState(directoryState, context);
} }
private boolean setDolphinUserDirectory() private static boolean setDolphinUserDirectory()
{ {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState()))
{ {
@ -99,7 +91,7 @@ public final class DirectoryInitializationService extends IntentService
if (externalPath != null) if (externalPath != null)
{ {
userPath = externalPath.getAbsolutePath() + "/dolphin-emu"; userPath = externalPath.getAbsolutePath() + "/dolphin-emu";
Log.debug("[DirectoryInitializationService] User Dir: " + userPath); Log.debug("[DirectoryInitialization] User Dir: " + userPath);
NativeLibrary.SetUserDirectory(userPath); NativeLibrary.SetUserDirectory(userPath);
return true; return true;
} }
@ -109,19 +101,19 @@ public final class DirectoryInitializationService extends IntentService
return false; 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(); internalPath = sysDirectory.getAbsolutePath();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
String revision = NativeLibrary.GetGitRevision(); String revision = NativeLibrary.GetGitRevision();
if (!preferences.getString("sysDirectoryVersion", "").equals(revision)) if (!preferences.getString("sysDirectoryVersion", "").equals(revision))
{ {
// There is no extracted Sys directory, or there is a Sys directory from another // 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. // version of Dolphin that might contain outdated files. Let's (re-)extract Sys.
deleteDirectoryRecursively(sysDirectory); deleteDirectoryRecursively(sysDirectory);
copyAssetFolder("Sys", sysDirectory, true); copyAssetFolder("Sys", sysDirectory, true, context);
SharedPreferences.Editor editor = preferences.edit(); SharedPreferences.Editor editor = preferences.edit();
editor.putString("sysDirectoryVersion", revision); editor.putString("sysDirectoryVersion", revision);
@ -132,7 +124,7 @@ public final class DirectoryInitializationService extends IntentService
SetSysDirectory(sysDirectory.getPath()); 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. // Create User directory structure and copy some NAND files from the extracted Sys directory.
CreateUserDirectories(); 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. // TODO: Redo the Android controller system so that we don't have to extract these INIs.
String configDirectory = NativeLibrary.GetUserDirectory() + File.separator + "Config"; String configDirectory = NativeLibrary.GetUserDirectory() + File.separator + "Config";
copyAsset("GCPadNew.ini", new File(configDirectory, "GCPadNew.ini"), true); copyAsset("GCPadNew.ini", new File(configDirectory, "GCPadNew.ini"), true, context);
copyAsset("WiimoteNew.ini", new File(configDirectory, "WiimoteNew.ini"), false); copyAsset("WiimoteNew.ini", new File(configDirectory, "WiimoteNew.ini"), false, context);
} }
private static void deleteDirectoryRecursively(File file) private static void deleteDirectoryRecursively(File file)
@ -170,12 +162,12 @@ public final class DirectoryInitializationService extends IntentService
{ {
if (directoryState == null) 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()) else if (isDolphinDirectoryInitializationRunning.get())
{ {
throw new IllegalStateException( throw new IllegalStateException(
"DirectoryInitializationService has to finish running first!"); "DirectoryInitialization has to finish running first!");
} }
return userPath; return userPath;
@ -185,34 +177,34 @@ public final class DirectoryInitializationService extends IntentService
{ {
if (directoryState == null) 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()) else if (isDolphinDirectoryInitializationRunning.get())
{ {
throw new IllegalStateException( throw new IllegalStateException(
"DirectoryInitializationService has to finish running first!"); "DirectoryInitialization has to finish running first!");
} }
return internalPath; return internalPath;
} }
private void sendBroadcastState(DirectoryInitializationState state) private static void sendBroadcastState(DirectoryInitializationState state, Context context)
{ {
Intent localIntent = Intent localIntent =
new Intent(BROADCAST_ACTION) new Intent(BROADCAST_ACTION)
.putExtra(EXTRA_STATE, state); .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 try
{ {
if (!output.exists() || overwrite) if (!output.exists() || overwrite)
{ {
InputStream in = getAssets().open(asset); InputStream in = context.getAssets().open(asset);
OutputStream out = new FileOutputStream(output); OutputStream out = new FileOutputStream(output);
copyFile(in, out); copyFile(in, out);
in.close(); in.close();
@ -221,20 +213,21 @@ public final class DirectoryInitializationService extends IntentService
} }
catch (IOException e) catch (IOException e)
{ {
Log.error("[DirectoryInitializationService] Failed to copy asset file: " + asset + Log.error("[DirectoryInitialization] Failed to copy asset file: " + asset +
e.getMessage()); 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); outputFolder);
try try
{ {
boolean createdFolder = false; boolean createdFolder = false;
for (String file : getAssets().list(assetFolder)) for (String file : context.getAssets().list(assetFolder))
{ {
if (!createdFolder) if (!createdFolder)
{ {
@ -242,18 +235,19 @@ public final class DirectoryInitializationService extends IntentService
createdFolder = true; createdFolder = true;
} }
copyAssetFolder(assetFolder + File.separator + file, new File(outputFolder, file), copyAssetFolder(assetFolder + File.separator + file, new File(outputFolder, file),
overwrite); overwrite, context);
copyAsset(assetFolder + File.separator + file, new File(outputFolder, file), overwrite); copyAsset(assetFolder + File.separator + file, new File(outputFolder, file), overwrite,
context);
} }
} }
catch (IOException e) catch (IOException e)
{ {
Log.error("[DirectoryInitializationService] Failed to copy asset folder: " + assetFolder + Log.error("[DirectoryInitialization] Failed to copy asset folder: " + assetFolder +
e.getMessage()); 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]; byte[] buffer = new byte[1024];
int read; int read;

View File

@ -4,8 +4,7 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService; import org.dolphinemu.dolphinemu.utils.DirectoryInitialization.DirectoryInitializationState;
import org.dolphinemu.dolphinemu.services.DirectoryInitializationService.DirectoryInitializationState;
import rx.functions.Action1; import rx.functions.Action1;
@ -22,7 +21,7 @@ public class DirectoryStateReceiver extends BroadcastReceiver
public void onReceive(Context context, Intent intent) public void onReceive(Context context, Intent intent)
{ {
DirectoryInitializationState state = (DirectoryInitializationState) intent DirectoryInitializationState state = (DirectoryInitializationState) intent
.getSerializableExtra(DirectoryInitializationService.EXTRA_STATE); .getSerializableExtra(DirectoryInitialization.EXTRA_STATE);
callback.call(state); callback.call(state);
} }
} }

View File

@ -246,8 +246,8 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs(
jobject obj, jobject obj,
jstring path); jstring path);
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_CreateUserDirectories( Java_org_dolphinemu_dolphinemu_utils_DirectoryInitialization_CreateUserDirectories(JNIEnv* env,
JNIEnv* env, jobject obj); jobject obj);
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory( JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SetUserDirectory(
JNIEnv* env, jobject obj, jstring jDirectory); JNIEnv* env, jobject obj, jstring jDirectory);
JNIEXPORT jstring JNICALL JNIEXPORT jstring JNICALL
@ -457,8 +457,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_LoadStateAs(
State::LoadAs(GetJString(env, path)); State::LoadAs(GetJString(env, path));
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_utils_DirectoryInitialization_SetSysDirectory(
Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_SetSysDirectory(
JNIEnv* env, jobject obj, jstring jPath) JNIEnv* env, jobject obj, jstring jPath)
{ {
const std::string path = GetJString(env, jPath); const std::string path = GetJString(env, jPath);
@ -466,8 +465,8 @@ Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_SetSysDir
} }
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_services_DirectoryInitializationService_CreateUserDirectories( Java_org_dolphinemu_dolphinemu_utils_DirectoryInitialization_CreateUserDirectories(JNIEnv* env,
JNIEnv* env, jobject obj) jobject obj)
{ {
UICommon::CreateDirectories(); UICommon::CreateDirectories();
} }