From 481df6b6606807360d75f2f63a067587f178471b Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 27 Sep 2022 18:38:32 +0200 Subject: [PATCH] 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. --- .../services/GameFileCacheManager.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) 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 ad5f225374..b359915901 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 @@ -26,6 +26,7 @@ public final class GameFileCacheManager private static GameFileCache sGameFileCache = null; private static final MutableLiveData sGameFiles = new MutableLiveData<>(new GameFile[]{}); + private static boolean sFirstLoadDone = false; private static boolean sRunRescanAfterLoad = false; private static final ExecutorService sExecutor = Executors.newFixedThreadPool(1); @@ -125,6 +126,8 @@ public final class GameFileCacheManager */ public static void startLoad(Context context) { + createGameFileCacheIfNeeded(); + if (!sLoadInProgress.getValue()) { sLoadInProgress.setValue(true); @@ -141,6 +144,8 @@ public final class GameFileCacheManager */ public static void startRescan(Context context) { + createGameFileCacheIfNeeded(); + if (!sRescanInProgress.getValue()) { sRescanInProgress.setValue(true); @@ -165,6 +170,7 @@ 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. + createGameFileCacheIfNeeded(); synchronized (sGameFileCache) { return sGameFileCache.addOrGet(gamePath); @@ -178,12 +184,11 @@ public final class GameFileCacheManager */ private static void load() { - if (sGameFileCache == null) + if (!sFirstLoadDone) { - GameFileCache temp = new GameFileCache(); - synchronized (temp) + synchronized (sGameFileCache) { - sGameFileCache = temp; + sFirstLoadDone = true; sGameFileCache.load(); if (sGameFileCache.getSize() != 0) { @@ -214,7 +219,7 @@ public final class GameFileCacheManager */ private static void rescan() { - if (sGameFileCache == null) + if (!sFirstLoadDone) { sRunRescanAfterLoad = true; } @@ -253,4 +258,16 @@ public final class GameFileCacheManager Arrays.sort(gameFilesTemp, (lhs, rhs) -> lhs.getTitle().compareToIgnoreCase(rhs.getTitle())); 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(); + } + } }