summaryrefslogtreecommitdiff
path: root/Source/Android/app/src/main/java
diff options
context:
space:
mode:
authorMai <mathew1800@gmail.com>2022-09-29 09:02:47 -0400
committerGitHub <noreply@github.com>2022-09-29 09:02:47 -0400
commit865348cfb171cd1655fb3411982d37a99116ff1b (patch)
treeedc3b934b7a46efbbbdb050b4121a69551f39ff8 /Source/Android/app/src/main/java
parent4f5a6ee461f3624816b9d6e44855d0761c463ba3 (diff)
parentd4709ce0ba3e81f4616b873a1139c05d3108ffd5 (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')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/AppLinkActivity.java2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/features/settings/model/Settings.java2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java14
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/GameFileCacheManager.java115
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java4
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.java4
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java8
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())