diff options
| author | Mai <mathew1800@gmail.com> | 2022-09-29 09:02:47 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-09-29 09:02:47 -0400 |
| commit | 865348cfb171cd1655fb3411982d37a99116ff1b (patch) | |
| tree | edc3b934b7a46efbbbdb050b4121a69551f39ff8 /Source/Android/app/src/main/java | |
| parent | 4f5a6ee461f3624816b9d6e44855d0761c463ba3 (diff) | |
| parent | d4709ce0ba3e81f4616b873a1139c05d3108ffd5 (diff) | |
Merge pull request #11103 from JosJuice/android-gamefilecache-not-null
Android: Allocate GameFileCache on GUI thread
Diffstat (limited to 'Source/Android/app/src/main/java')
7 files changed, 77 insertions, 72 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 2699322a96..924b5911c0 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 @@ -74,7 +74,7 @@ public class AppLinkActivity extends FragmentActivity }); DirectoryInitialization.start(this); - GameFileCacheManager.startLoad(this); + GameFileCacheManager.startLoad(); } /** diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java index 51d10ecdbc..d042ae32f5 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java @@ -233,7 +233,7 @@ public class Settings implements Closeable if (mLoadedRecursiveIsoPathsValue != BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBoolean(this)) { // Refresh game library - GameFileCacheManager.startRescan(context); + GameFileCacheManager.startRescan(); } } else 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 8ea8d82757..7b29370c53 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 @@ -109,11 +109,11 @@ public class GameFileCache public static native String[] getAllGamePaths(String[] folderPaths, boolean recursiveScan); - public native int getSize(); + public synchronized native int getSize(); - public native GameFile[] getAllGames(); + public synchronized native GameFile[] getAllGames(); - public native GameFile addOrGet(String gamePath); + public synchronized native GameFile addOrGet(String gamePath); /** * Sets the list of games to cache. @@ -123,7 +123,7 @@ public class GameFileCache * * @return true if the cache was modified */ - public native boolean update(String[] gamePaths); + public synchronized native boolean update(String[] gamePaths); /** * For each game that already is in the cache, scans the folder that contains the game @@ -131,9 +131,9 @@ public class GameFileCache * * @return true if the cache was modified */ - public native boolean updateAdditionalMetadata(); + public synchronized native boolean updateAdditionalMetadata(); - public native boolean load(); + public synchronized native boolean load(); - public native boolean save(); + public synchronized native boolean save(); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java index f53e3de56f..a979ee599f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java @@ -2,8 +2,6 @@ package org.dolphinemu.dolphinemu.services; -import android.content.Context; - import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; @@ -23,14 +21,15 @@ import java.util.concurrent.Executors; */ public final class GameFileCacheManager { - private static GameFileCache gameFileCache = null; - private static final MutableLiveData<GameFile[]> gameFiles = + private static GameFileCache sGameFileCache = null; + private static final MutableLiveData<GameFile[]> sGameFiles = new MutableLiveData<>(new GameFile[]{}); - private static boolean runRescanAfterLoad = false; + private static boolean sFirstLoadDone = false; + private static boolean sRunRescanAfterLoad = false; - private static final ExecutorService executor = Executors.newFixedThreadPool(1); - private static final MutableLiveData<Boolean> loadInProgress = new MutableLiveData<>(false); - private static final MutableLiveData<Boolean> rescanInProgress = new MutableLiveData<>(false); + private static final ExecutorService sExecutor = Executors.newFixedThreadPool(1); + private static final MutableLiveData<Boolean> sLoadInProgress = new MutableLiveData<>(false); + private static final MutableLiveData<Boolean> sRescanInProgress = new MutableLiveData<>(false); private GameFileCacheManager() { @@ -38,12 +37,12 @@ public final class GameFileCacheManager public static LiveData<GameFile[]> getGameFiles() { - return gameFiles; + return sGameFiles; } public static List<GameFile> getGameFilesForPlatform(Platform platform) { - GameFile[] allGames = gameFiles.getValue(); + GameFile[] allGames = sGameFiles.getValue(); ArrayList<GameFile> platformGames = new ArrayList<>(); for (GameFile game : allGames) { @@ -57,7 +56,7 @@ public final class GameFileCacheManager public static GameFile getGameFileByGameId(String gameId) { - GameFile[] allGames = gameFiles.getValue(); + GameFile[] allGames = sGameFiles.getValue(); for (GameFile game : allGames) { if (game.getGameId().equals(gameId)) @@ -72,7 +71,7 @@ public final class GameFileCacheManager { GameFile matchWithoutRevision = null; - GameFile[] allGames = gameFiles.getValue(); + GameFile[] allGames = sGameFiles.getValue(); for (GameFile otherGame : allGames) { if (game.getGameId().equals(otherGame.getGameId()) && @@ -102,7 +101,7 @@ public final class GameFileCacheManager */ public static LiveData<Boolean> isLoading() { - return loadInProgress; + return sLoadInProgress; } /** @@ -110,12 +109,12 @@ public final class GameFileCacheManager */ public static LiveData<Boolean> isRescanning() { - return rescanInProgress; + return sRescanInProgress; } public static boolean isLoadingOrRescanning() { - return loadInProgress.getValue() || rescanInProgress.getValue(); + return sLoadInProgress.getValue() || sRescanInProgress.getValue(); } /** @@ -123,13 +122,15 @@ public final class GameFileCacheManager * if the games are still present in the user's configured folders. * If this has already been called, calling it again has no effect. */ - public static void startLoad(Context context) + public static void startLoad() { - if (!loadInProgress.getValue()) + createGameFileCacheIfNeeded(); + + if (!sLoadInProgress.getValue()) { - loadInProgress.setValue(true); + sLoadInProgress.setValue(true); new AfterDirectoryInitializationRunner().runWithoutLifecycle( - () -> executor.execute(GameFileCacheManager::load)); + () -> sExecutor.execute(GameFileCacheManager::load)); } } @@ -139,13 +140,15 @@ public final class GameFileCacheManager * If loading the game file cache hasn't started or hasn't finished, * the execution of this will be postponed until it finishes. */ - public static void startRescan(Context context) + public static void startRescan() { - if (!rescanInProgress.getValue()) + createGameFileCacheIfNeeded(); + + if (!sRescanInProgress.getValue()) { - rescanInProgress.setValue(true); + sRescanInProgress.setValue(true); new AfterDirectoryInitializationRunner().runWithoutLifecycle( - () -> executor.execute(GameFileCacheManager::rescan)); + () -> sExecutor.execute(GameFileCacheManager::rescan)); } } @@ -153,8 +156,8 @@ public final class GameFileCacheManager { // Common case: The game is in the cache, so just grab it from there. // (Actually, addOrGet already checks for this case, but we want to avoid calling it if possible - // because onHandleIntent may hold a lock on gameFileCache for extended periods of time.) - GameFile[] allGames = gameFiles.getValue(); + // because the executor thread may hold a lock on sGameFileCache for extended periods of time.) + GameFile[] allGames = sGameFiles.getValue(); for (GameFile game : allGames) { if (game.getPath().equals(gamePath)) @@ -165,10 +168,8 @@ public final class GameFileCacheManager // Unusual case: The game wasn't found in the cache. // Scan the game and add it to the cache so that we can return it. - synchronized (gameFileCache) - { - return gameFileCache.addOrGet(gamePath); - } + createGameFileCacheIfNeeded(); + return sGameFileCache.addOrGet(gamePath); } /** @@ -178,30 +179,26 @@ public final class GameFileCacheManager */ private static void load() { - if (gameFileCache == null) + if (!sFirstLoadDone) { - GameFileCache temp = new GameFileCache(); - synchronized (temp) + sFirstLoadDone = true; + sGameFileCache.load(); + if (sGameFileCache.getSize() != 0) { - gameFileCache = temp; - gameFileCache.load(); - if (gameFileCache.getSize() != 0) - { - updateGameFileArray(); - } + updateGameFileArray(); } } - if (runRescanAfterLoad) + if (sRunRescanAfterLoad) { - rescanInProgress.postValue(true); + sRescanInProgress.postValue(true); } - loadInProgress.postValue(false); + sLoadInProgress.postValue(false); - if (runRescanAfterLoad) + if (sRunRescanAfterLoad) { - runRescanAfterLoad = false; + sRunRescanAfterLoad = false; rescan(); } } @@ -214,25 +211,21 @@ public final class GameFileCacheManager */ private static void rescan() { - if (gameFileCache == null) + if (!sFirstLoadDone) { - runRescanAfterLoad = true; + sRunRescanAfterLoad = true; } else { String[] gamePaths = GameFileCache.getAllGamePaths(); - boolean changed; - synchronized (gameFileCache) - { - changed = gameFileCache.update(gamePaths); - } + boolean changed = sGameFileCache.update(gamePaths); if (changed) { updateGameFileArray(); } - boolean additionalMetadataChanged = gameFileCache.updateAdditionalMetadata(); + boolean additionalMetadataChanged = sGameFileCache.updateAdditionalMetadata(); if (additionalMetadataChanged) { updateGameFileArray(); @@ -240,17 +233,29 @@ public final class GameFileCacheManager if (changed || additionalMetadataChanged) { - gameFileCache.save(); + sGameFileCache.save(); } } - rescanInProgress.postValue(false); + sRescanInProgress.postValue(false); } private static void updateGameFileArray() { - GameFile[] gameFilesTemp = gameFileCache.getAllGames(); + GameFile[] gameFilesTemp = sGameFileCache.getAllGames(); Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle())); - gameFiles.postValue(gameFilesTemp); + sGameFiles.postValue(gameFilesTemp); + } + + private static void createGameFileCacheIfNeeded() + { + // Creating the GameFileCache in the static initializer may be unsafe, because GameFileCache + // relies on native code, and the native library isn't loaded right when the app starts. + // We create it here instead. + + if (sGameFileCache == null) + { + sGameFileCache = new GameFileCache(); + } } } 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 bfa9e48c4f..480e7472e3 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 @@ -301,7 +301,7 @@ public final class MainActivity extends AppCompatActivity public void onRefresh() { setRefreshing(true); - GameFileCacheManager.startRescan(this); + GameFileCacheManager.startRescan(); } /** @@ -368,7 +368,7 @@ public final class MainActivity extends AppCompatActivity mViewPager.setCurrentItem(IntSetting.MAIN_LAST_PLATFORM_TAB.getIntGlobal()); showGames(); - GameFileCacheManager.startLoad(this); + GameFileCacheManager.startLoad(); } @Override 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 382dbc274d..c6af492e63 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 @@ -96,7 +96,7 @@ public final class MainPresenter case R.id.menu_refresh: mView.setRefreshing(true); - GameFileCacheManager.startRescan(activity); + GameFileCacheManager.startRescan(); return true; case R.id.button_add_directory: @@ -146,7 +146,7 @@ public final class MainPresenter if (sShouldRescanLibrary) { - GameFileCacheManager.startRescan(mActivity); + GameFileCacheManager.startRescan(); } sShouldRescanLibrary = true; 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 4b2b22de33..32db29e802 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 @@ -79,7 +79,7 @@ public final class TvMainActivity extends FragmentActivity if (DirectoryInitialization.shouldStart(this)) { DirectoryInitialization.start(this); - GameFileCacheManager.startLoad(this); + GameFileCacheManager.startLoad(); } mPresenter.onResume(); @@ -292,7 +292,7 @@ public final class TvMainActivity extends FragmentActivity } DirectoryInitialization.start(this); - GameFileCacheManager.startLoad(this); + GameFileCacheManager.startLoad(); } } @@ -303,7 +303,7 @@ public final class TvMainActivity extends FragmentActivity public void onRefresh() { setRefreshing(true); - GameFileCacheManager.startRescan(this); + GameFileCacheManager.startRescan(); } private void buildRowsAdapter() @@ -313,7 +313,7 @@ public final class TvMainActivity extends FragmentActivity if (!DirectoryInitialization.isWaitingForWriteAccess(this)) { - GameFileCacheManager.startLoad(this); + GameFileCacheManager.startLoad(); } for (Platform platform : Platform.values()) |
