summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
authorAnthony <Helios747@users.noreply.github.com>2019-08-21 10:14:08 -0700
committerGitHub <noreply@github.com>2019-08-21 10:14:08 -0700
commit998c171b65e57c669e217e6995f525bc34f2a71e (patch)
tree1e7586764bcc16234a634b6893a49246fc5791f5 /Source/Android/app/src/main/java
parent2a95227f64c26b8688c2346af15fb54644779571 (diff)
parente4ef2193e0512878517d20ccedfcef3d712488c3 (diff)
Merge pull request #8196 from JosJuice/android-applinkactivity-race
Android: Fix race condition in AppLinkActivity
Diffstat (limited to 'Source/Android/app/src/main/java')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java49
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java26
2 files changed, 64 insertions, 11 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java
index ca1197bc73..5b5c310f75 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java
@@ -1,5 +1,7 @@
package org.dolphinemu.dolphinemu.activities;
+import android.content.BroadcastReceiver;
+import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
@@ -26,6 +28,7 @@ public class AppLinkActivity extends FragmentActivity
private AppLinkHelper.PlayAction playAction;
private DirectoryStateReceiver directoryStateReceiver;
+ private BroadcastReceiver gameFileCacheReceiver;
@Override
protected void onCreate(Bundle savedInstanceState)
@@ -63,16 +66,19 @@ public class AppLinkActivity extends FragmentActivity
*/
private void initResources()
{
- IntentFilter statusIntentFilter = new IntentFilter(
+ IntentFilter directoryStateIntentFilter = new IntentFilter(
DirectoryInitialization.BROADCAST_ACTION);
+ IntentFilter gameFileCacheIntentFilter = new IntentFilter(
+ GameFileCacheService.BROADCAST_ACTION);
+
directoryStateReceiver =
new DirectoryStateReceiver(directoryInitializationState ->
{
if (directoryInitializationState ==
DirectoryInitialization.DirectoryInitializationState.DOLPHIN_DIRECTORIES_INITIALIZED)
{
- play(playAction);
+ tryPlay(playAction);
}
else if (directoryInitializationState ==
DirectoryInitialization.DirectoryInitializationState.EXTERNAL_STORAGE_PERMISSION_NEEDED)
@@ -88,10 +94,23 @@ public class AppLinkActivity extends FragmentActivity
}
});
- // Registers the DirectoryStateReceiver and its intent filters
- LocalBroadcastManager.getInstance(this).registerReceiver(
- directoryStateReceiver,
- statusIntentFilter);
+ gameFileCacheReceiver =
+ new BroadcastReceiver()
+ {
+ @Override
+ public void onReceive(Context context, Intent intent)
+ {
+ if (DirectoryInitialization.areDolphinDirectoriesReady())
+ {
+ tryPlay(playAction);
+ }
+ }
+ };
+
+ LocalBroadcastManager broadcastManager = LocalBroadcastManager.getInstance(this);
+ broadcastManager.registerReceiver(directoryStateReceiver, directoryStateIntentFilter);
+ broadcastManager.registerReceiver(gameFileCacheReceiver, gameFileCacheIntentFilter);
+
DirectoryInitialization.start(this);
GameFileCacheService.startLoad(this);
}
@@ -107,17 +126,31 @@ public class AppLinkActivity extends FragmentActivity
finish();
}
+ private void tryPlay(AppLinkHelper.PlayAction action)
+ {
+ // TODO: This approach of getting the game from the game file cache without rescanning
+ // the library means that we can fail to launch games if the cache file has been deleted.
+
+ GameFile game = GameFileCacheService.getGameFileByGameId(action.getGameId());
+
+ // If game == null and the load isn't done, wait for the next GameFileCacheService broadcast.
+ // If game == null and the load is done, call play with a null game, making us exit in failure.
+ if (game != null || GameFileCacheService.hasLoadedCache())
+ {
+ play(action, game);
+ }
+ }
+
/**
* Action if program(game) is selected
*/
- private void play(AppLinkHelper.PlayAction action)
+ private void play(AppLinkHelper.PlayAction action, GameFile game)
{
Log.d(TAG, "Playing game "
+ action.getGameId()
+ " from channel "
+ action.getChannelId());
- GameFile game = GameFileCacheService.getGameFileByGameId(action.getGameId());
if (game == null)
Log.e(TAG, "Invalid Game: " + action.getGameId());
else
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java
index 17aef0cd35..5cddf93f5d 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheService.java
@@ -13,6 +13,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -27,6 +28,8 @@ public final class GameFileCacheService extends IntentService
private static GameFileCache gameFileCache = null;
private static AtomicReference<GameFile[]> gameFiles = new AtomicReference<>(new GameFile[]{});
+ private static AtomicBoolean hasLoadedCache = new AtomicBoolean(false);
+ private static AtomicBoolean hasScannedLibrary = new AtomicBoolean(false);
public GameFileCacheService()
{
@@ -81,6 +84,16 @@ public final class GameFileCacheService extends IntentService
return matchWithoutRevision;
}
+ public static boolean hasLoadedCache()
+ {
+ return hasLoadedCache.get();
+ }
+
+ public static boolean hasScannedLibrary()
+ {
+ return hasScannedLibrary.get();
+ }
+
private static void startService(Context context, String action)
{
Intent intent = new Intent(context, GameFileCacheService.class);
@@ -130,6 +143,8 @@ public final class GameFileCacheService extends IntentService
gameFileCache = temp;
gameFileCache.load();
updateGameFileArray();
+ hasLoadedCache.set(true);
+ sendBroadcast();
}
}
@@ -138,10 +153,11 @@ public final class GameFileCacheService extends IntentService
{
synchronized (gameFileCache)
{
- if (gameFileCache.scanLibrary(this))
- {
+ boolean changed = gameFileCache.scanLibrary(this);
+ if (changed)
updateGameFileArray();
- }
+ hasScannedLibrary.set(true);
+ sendBroadcast();
}
}
}
@@ -151,6 +167,10 @@ public final class GameFileCacheService extends IntentService
GameFile[] gameFilesTemp = gameFileCache.getAllGames();
Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle()));
gameFiles.set(gameFilesTemp);
+ }
+
+ private void sendBroadcast()
+ {
LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_ACTION));
}
}