diff options
| author | Anthony <Helios747@users.noreply.github.com> | 2019-08-21 10:14:08 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2019-08-21 10:14:08 -0700 |
| commit | 998c171b65e57c669e217e6995f525bc34f2a71e (patch) | |
| tree | 1e7586764bcc16234a634b6893a49246fc5791f5 /Source/Android/app/src/main/java | |
| parent | 2a95227f64c26b8688c2346af15fb54644779571 (diff) | |
| parent | e4ef2193e0512878517d20ccedfcef3d712488c3 (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')
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));
}
}
|
