From dbcdead04d7ceeedc9f26a7ede2aeb69ce9be7df Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sat, 20 Feb 2021 19:41:41 +0100 Subject: [PATCH] Android: Split GameFileCacheService broadcasts into two types --- .../activities/AppLinkActivity.java | 5 +- .../dolphinemu/model/GameFileCache.java | 2 + .../services/GameFileCacheService.java | 53 ++++++++++++------- .../dolphinemu/ui/main/MainPresenter.java | 2 +- Source/Android/jni/GameList/GameFileCache.cpp | 6 +++ 5 files changed, 46 insertions(+), 22 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 156995e26d..4e19b05334 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 @@ -67,8 +67,7 @@ public class AppLinkActivity extends FragmentActivity mAfterDirectoryInitializationRunner = new AfterDirectoryInitializationRunner(); mAfterDirectoryInitializationRunner.run(this, true, () -> tryPlay(playAction)); - IntentFilter gameFileCacheIntentFilter = new IntentFilter( - GameFileCacheService.BROADCAST_ACTION); + IntentFilter gameFileCacheIntentFilter = new IntentFilter(GameFileCacheService.DONE_LOADING); BroadcastReceiver gameFileCacheReceiver = new BroadcastReceiver() { @@ -109,7 +108,7 @@ public class AppLinkActivity extends FragmentActivity // 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()) + if (game != null || !GameFileCacheService.isLoading()) { play(action, game); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java index a15e734d0b..e359d701bc 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java @@ -116,6 +116,8 @@ public class GameFileCache return cacheChanged; } + public native int getSize(); + public native GameFile[] getAllGames(); public native GameFile addOrGet(String gamePath); 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 ab295c5550..34bf1afa0a 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 @@ -15,7 +15,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.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; /** @@ -23,7 +23,17 @@ import java.util.concurrent.atomic.AtomicReference; */ public final class GameFileCacheService extends IntentService { - public static final String BROADCAST_ACTION = "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_UPDATED"; + /** + * This is broadcast when the contents of the cache change. + */ + public static final String CACHE_UPDATED = "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_UPDATED"; + + /** + * This is broadcast when the service is done with all requested work, regardless of whether + * the contents of the cache actually changed. (Maybe the cache was already up to date.) + */ + public static final String DONE_LOADING = + "org.dolphinemu.dolphinemu.GAME_FILE_CACHE_DONE_LOADING"; private static final String ACTION_LOAD = "org.dolphinemu.dolphinemu.LOAD_GAME_FILE_CACHE"; private static final String ACTION_RESCAN = "org.dolphinemu.dolphinemu.RESCAN_GAME_FILE_CACHE"; @@ -31,8 +41,7 @@ public final class GameFileCacheService extends IntentService private static GameFileCache gameFileCache = null; private static final AtomicReference gameFiles = new AtomicReference<>(new GameFile[]{}); - private static final AtomicBoolean hasLoadedCache = new AtomicBoolean(false); - private static final AtomicBoolean hasScannedLibrary = new AtomicBoolean(false); + private static final AtomicInteger unhandledIntents = new AtomicInteger(0); public GameFileCacheService() { @@ -96,14 +105,9 @@ public final class GameFileCacheService extends IntentService return new String[]{gameFile.getPath(), secondFile.getPath()}; } - public static boolean hasLoadedCache() + public static boolean isLoading() { - return hasLoadedCache.get(); - } - - public static boolean hasScannedLibrary() - { - return hasScannedLibrary.get(); + return unhandledIntents.get() != 0; } private static void startService(Context context, String action) @@ -119,6 +123,8 @@ public final class GameFileCacheService extends IntentService */ public static void startLoad(Context context) { + unhandledIntents.getAndIncrement(); + new AfterDirectoryInitializationRunner().run(context, false, () -> startService(context, ACTION_LOAD)); } @@ -130,6 +136,8 @@ public final class GameFileCacheService extends IntentService */ public static void startRescan(Context context) { + unhandledIntents.getAndIncrement(); + new AfterDirectoryInitializationRunner().run(context, false, () -> startService(context, ACTION_RESCAN)); } @@ -156,9 +164,11 @@ public final class GameFileCacheService extends IntentService { gameFileCache = temp; gameFileCache.load(); - updateGameFileArray(); - hasLoadedCache.set(true); - sendBroadcast(); + if (gameFileCache.getSize() != 0) + { + updateGameFileArray(); + sendBroadcast(CACHE_UPDATED); + } } } @@ -169,11 +179,18 @@ public final class GameFileCacheService extends IntentService { boolean changed = gameFileCache.scanLibrary(); if (changed) + { updateGameFileArray(); - hasScannedLibrary.set(true); - sendBroadcast(); + sendBroadcast(CACHE_UPDATED); + } } } + + int intentsLeft = unhandledIntents.decrementAndGet(); + if (intentsLeft == 0) + { + sendBroadcast(DONE_LOADING); + } } private void updateGameFileArray() @@ -183,8 +200,8 @@ public final class GameFileCacheService extends IntentService gameFiles.set(gameFilesTemp); } - private void sendBroadcast() + private void sendBroadcast(String action) { - LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(BROADCAST_ACTION)); + LocalBroadcastManager.getInstance(this).sendBroadcast(new Intent(action)); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java index ebd43513ab..ff594b3245 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java @@ -53,7 +53,7 @@ public final class MainPresenter mView.setVersionString(versionName); IntentFilter filter = new IntentFilter(); - filter.addAction(GameFileCacheService.BROADCAST_ACTION); + filter.addAction(GameFileCacheService.CACHE_UPDATED); mBroadcastReceiver = new BroadcastReceiver() { @Override diff --git a/Source/Android/jni/GameList/GameFileCache.cpp b/Source/Android/jni/GameList/GameFileCache.cpp index d5fce915b8..9a3bb49556 100644 --- a/Source/Android/jni/GameList/GameFileCache.cpp +++ b/Source/Android/jni/GameList/GameFileCache.cpp @@ -39,6 +39,12 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_finali delete GetPointer(env, obj); } +JNIEXPORT jint JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_getSize(JNIEnv* env, + jobject obj) +{ + return static_cast(GetPointer(env, obj)->GetSize()); +} + JNIEXPORT jobjectArray JNICALL Java_org_dolphinemu_dolphinemu_model_GameFileCache_getAllGames(JNIEnv* env, jobject obj) {