Android: Allocate GameFileCache on GUI thread

This is intended to fix https://bugs.dolphin-emu.org/issues/13053,
which is a crash caused by sGameFileCache being null when addOrGet
is called.
This commit is contained in:
JosJuice 2022-09-27 18:38:32 +02:00
parent f857fa6529
commit 481df6b660

View File

@ -26,6 +26,7 @@ public final class GameFileCacheManager
private static GameFileCache sGameFileCache = null; private static GameFileCache sGameFileCache = null;
private static final MutableLiveData<GameFile[]> sGameFiles = private static final MutableLiveData<GameFile[]> sGameFiles =
new MutableLiveData<>(new GameFile[]{}); new MutableLiveData<>(new GameFile[]{});
private static boolean sFirstLoadDone = false;
private static boolean sRunRescanAfterLoad = false; private static boolean sRunRescanAfterLoad = false;
private static final ExecutorService sExecutor = Executors.newFixedThreadPool(1); private static final ExecutorService sExecutor = Executors.newFixedThreadPool(1);
@ -125,6 +126,8 @@ public final class GameFileCacheManager
*/ */
public static void startLoad(Context context) public static void startLoad(Context context)
{ {
createGameFileCacheIfNeeded();
if (!sLoadInProgress.getValue()) if (!sLoadInProgress.getValue())
{ {
sLoadInProgress.setValue(true); sLoadInProgress.setValue(true);
@ -141,6 +144,8 @@ public final class GameFileCacheManager
*/ */
public static void startRescan(Context context) public static void startRescan(Context context)
{ {
createGameFileCacheIfNeeded();
if (!sRescanInProgress.getValue()) if (!sRescanInProgress.getValue())
{ {
sRescanInProgress.setValue(true); sRescanInProgress.setValue(true);
@ -165,6 +170,7 @@ public final class GameFileCacheManager
// Unusual case: The game wasn't found in the cache. // 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. // Scan the game and add it to the cache so that we can return it.
createGameFileCacheIfNeeded();
synchronized (sGameFileCache) synchronized (sGameFileCache)
{ {
return sGameFileCache.addOrGet(gamePath); return sGameFileCache.addOrGet(gamePath);
@ -178,12 +184,11 @@ public final class GameFileCacheManager
*/ */
private static void load() private static void load()
{ {
if (sGameFileCache == null) if (!sFirstLoadDone)
{ {
GameFileCache temp = new GameFileCache(); synchronized (sGameFileCache)
synchronized (temp)
{ {
sGameFileCache = temp; sFirstLoadDone = true;
sGameFileCache.load(); sGameFileCache.load();
if (sGameFileCache.getSize() != 0) if (sGameFileCache.getSize() != 0)
{ {
@ -214,7 +219,7 @@ public final class GameFileCacheManager
*/ */
private static void rescan() private static void rescan()
{ {
if (sGameFileCache == null) if (!sFirstLoadDone)
{ {
sRunRescanAfterLoad = true; sRunRescanAfterLoad = true;
} }
@ -253,4 +258,16 @@ public final class GameFileCacheManager
Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle())); Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle()));
sGameFiles.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();
}
}
} }