[Scummvm-git-logs] scummvm master -> aef1690c1d115e3d15b043ab5ef61ff46aa7d531
lephilousophe
noreply at scummvm.org
Tue Nov 12 21:46:26 UTC 2024
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
eed4d8a219 ANDROID: Add folders support to copyAssetsToInternalMemory
5603f64873 ANDROID: Use a checksum of all assets to determine if an update is needed
90f7892e3b ANDROID: Forward to C++ side the assets change status
aef1690c1d ANDROID: Allow packagers to bundle games in the assets
Commit: eed4d8a21971e03786bd672c3576f3f9d941d634
https://github.com/scummvm/scummvm/commit/eed4d8a21971e03786bd672c3576f3f9d941d634
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-11-12T22:46:21+01:00
Commit Message:
ANDROID: Add folders support to copyAssetsToInternalMemory
This allows to extract shaders too.
Move the assets inside a specific subfolder.
This avoid extracting some data from system assets.
Changed paths:
backends/platform/android/android.mk
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index 4011f83a705..9a63072bd1f 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -5,7 +5,8 @@ GRADLE_FILES = $(shell find $(PATH_DIST)/gradle -type f)
PATH_BUILD = ./android_project
PATH_BUILD_GRADLE = $(PATH_BUILD)/gradle/.timestamp $(PATH_BUILD)/gradlew $(PATH_BUILD)/build.gradle $(PATH_BUILD)/settings.gradle $(PATH_BUILD)/mainAssets/build.gradle $(PATH_BUILD)/gradle.properties $(PATH_BUILD)/local.properties $(PATH_BUILD)/src.properties
-PATH_BUILD_ASSETS = $(PATH_BUILD)/mainAssets/src/main/assets
+# $(PATH_BUILD)/mainAssets/src/main/assets is the root and everything is placed in the assets subdirectory
+PATH_BUILD_ASSETS = $(PATH_BUILD)/mainAssets/src/main/assets/assets
PATH_BUILD_LIB = $(PATH_BUILD)/lib/$(ABI)
PATH_BUILD_LIBSCUMMVM = $(PATH_BUILD)/lib/$(ABI)/libscummvm.so
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index a792ea29654..429c6e147f1 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -53,6 +53,7 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -839,11 +840,14 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
@Override
protected String[] getSysArchives() {
- Log.d(ScummVM.LOG_TAG, "Adding to Search Archive: " + _actualScummVMDataDir.getPath());
+ File assetsDir = new File(_actualScummVMDataDir, "assets");
+ Log.d(ScummVM.LOG_TAG, "Adding to Search Archive: " + assetsDir.getPath());
if (_externalPathAvailableForReadAccess && _possibleExternalScummVMDir != null) {
Log.d(ScummVM.LOG_TAG, "Adding to Search Archive: " + _possibleExternalScummVMDir.getPath());
- return new String[]{_actualScummVMDataDir.getPath(), _possibleExternalScummVMDir.getPath()};
- } else return new String[]{_actualScummVMDataDir.getPath()};
+ return new String[]{assetsDir.getPath(), _possibleExternalScummVMDir.getPath()};
+ } else {
+ return new String[]{assetsDir.getPath()};
+ }
}
@Override
@@ -1964,97 +1968,189 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return true;
}
+ // Deletes recursively a directory and its contents
+ private static void deleteDir(File dir) {
+ for (File child : dir.listFiles()) {
+ if (child.isDirectory()) {
+ deleteDir(child);
+ } else {
+ if (!child.delete()) {
+ Log.e(ScummVM.LOG_TAG, "Failed to delete file:" + child.getPath());
+ }
+ }
+ }
+ if (!dir.delete()) {
+ Log.e(ScummVM.LOG_TAG, "Failed to delete dir:" + dir.getPath());
+ }
+ }
- private boolean containsStringEntry(@NonNull String[] stringItenary, String targetEntry) {
- for (String sourceEntry : stringItenary) {
- // Log.d(ScummVM.LOG_TAG, "Comparing filename: " + sourceEntry + " to filename: " + targetEntry);
- if (sourceEntry.compareToIgnoreCase(targetEntry) == 0) {
- return true;
+ // clear up all files in the root of the internal app directory
+ // Don't remove the scummvm.ini nor the scummvm.log file!
+ private static void internalAppFolderCleanup(File dataDir) {
+ // We check if we already did the cleanup before by using a known to exist file
+ // scummmodern.zip has always been there in the Android port
+ if (!(new File(dataDir, "scummmodern.zip")).exists()) {
+ // We already did the cleanup: nothing to do
+ return;
+ }
+
+ File[] extfiles = dataDir.listFiles();
+ if (extfiles == null) {
+ // This should not happen
+ return;
+ }
+
+ Log.d(ScummVM.LOG_TAG, "Cleaning up old files in " + dataDir.getPath());
+ for (File extfile : extfiles) {
+ if (extfile.isDirectory()) {
+ // We never extracted folders before
+ continue;
+ }
+ // Skip scummvm.ini, scummvm.log at root
+ String name = extfile.getName();
+ if ((name.compareToIgnoreCase("scummvm.ini") == 0) ||
+ (name.compareToIgnoreCase("scummvm.log") == 0)) {
+ continue;
+ }
+ Log.d(ScummVM.LOG_TAG, "Deleting file:" + extfile.getName());
+ if (!extfile.delete()) {
+ Log.e(ScummVM.LOG_TAG, "Failed to delete file:" + extfile.getName());
}
}
- return false;
}
// clear up any possibly deprecated assets (when upgrading to a new version)
// Don't remove the scummvm.ini nor the scummvm.log file!
// Remove any files not in the filesItenary, even in a sideUpgrade
// Remove any files in the filesItenary only if not a sideUpgrade
- private void internalAppFolderCleanup(String[] filesItenary, boolean sideUpgrade) {
- if (_actualScummVMDataDir != null) {
- File[] extfiles = _actualScummVMDataDir.listFiles();
- if (extfiles != null) {
- Log.d(ScummVM.LOG_TAG, "Cleaning up files in internal app space");
- for (File extfile : extfiles) {
- if (extfile.isFile()) {
- if (extfile.getName().compareToIgnoreCase("scummvm.ini") != 0
- && extfile.getName().compareToIgnoreCase("scummvm.log") != 0
- && (!containsStringEntry(filesItenary, extfile.getName())
- || !sideUpgrade)
- ) {
- Log.d(ScummVM.LOG_TAG, "Deleting file:" + extfile.getName());
- if (!extfile.delete()) {
- Log.e(ScummVM.LOG_TAG, "Failed to delete file:" + extfile.getName());
- }
- }
- }
+ // Returns true if the dataDir was a directory and false otherwise
+ private static boolean assetsFolderCleanup(boolean sideUpgrade, File dataDir, String[] assetsToExtract) {
+ HashSet<String> filesToKeep = new HashSet<>(Arrays.asList(assetsToExtract));
+
+ File[] extfiles = dataDir.listFiles();
+ if (extfiles == null) {
+ // If we are here, this means dataDir is a file
+ return false;
+ }
+
+ Log.d(ScummVM.LOG_TAG, "Cleaning up files in " + dataDir.getPath());
+ for (File extfile : extfiles) {
+ String name = extfile.getName();
+
+ if (filesToKeep.contains(name) && sideUpgrade) {
+ continue;
+ }
+
+ if (extfile.isDirectory()) {
+ Log.d(ScummVM.LOG_TAG, "Deleting folder:" + extfile.getName());
+ deleteDir(extfile);
+ } else {
+ Log.d(ScummVM.LOG_TAG, "Deleting file:" + extfile.getName());
+ if (!extfile.delete()) {
+ Log.e(ScummVM.LOG_TAG, "Failed to delete file:" + extfile.getName());
}
}
}
+ return true;
}
// code based on https://stackoverflow.com/a/4530294
// Note, the following assumptions are made (since they are true as of yet)
- // - We don't need to copy (sub)folders
// - We copy all the files from our assets (not a subset of them)
// Otherwise we would probably need to create a specifically named zip file with the selection of files we'd need to extract to the internal memory
- private void copyAssetsToInternalMemory(boolean sideUpgrade) {
- // sideUpgrade is set to true, if we upgrade to the same version -- just check for the files existence before copying
- if (_actualScummVMDataDir != null) {
- AssetManager assetManager = getAssets();
- String[] files = null;
- try {
- files = assetManager.list("");
- } catch (IOException e) {
- Log.e(ScummVM.LOG_TAG, "Failed to get asset file list.", e);
+ // Returns true if the assetDir was a directory and false otherwise
+ private static boolean extractAssets(boolean sideUpgrade, AssetManager assetManager, String assetDir, File dataDir) {
+ String[] files = null;
+ try {
+ files = assetManager.list(assetDir);
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "Failed to get asset file list.", e);
+ }
+
+ if (files == null || files.length == 0) {
+ // The asset is a file: remove any directory with the same name
+ if (dataDir.isDirectory()) {
+ deleteDir(dataDir);
+ }
+ return false;
+ }
+
+ // Starting from here, assetDir is a directory
+
+ // Cleanup old files
+ if (!assetsFolderCleanup(sideUpgrade, dataDir, files)) {
+ // dataDir is a file but we need a folder
+ if (dataDir.exists()) {
+ if (!dataDir.delete()) {
+ Log.e(ScummVM.LOG_TAG, "Failed to delete file:" + dataDir.getName());
+ // There is no point on continuing this
+ return true;
+ }
+ }
+ }
+
+ if (!dataDir.exists()) {
+ if (!dataDir.mkdir()) {
+ Log.e(ScummVM.LOG_TAG, "Failed to create directory: " + dataDir.getPath());
+ // There is no point on continuing this
+ return true;
}
+ }
- internalAppFolderCleanup(files, sideUpgrade);
+ for (String filename : files) {
+ String assetPath = (assetDir.length() > 0 ? assetDir + File.separator : "") + filename;
+ File dataPath = new File(dataDir, filename);
+
+ if (extractAssets(sideUpgrade, assetManager, assetPath, dataPath)) {
+ // This was a directory: no data to extract
+ continue;
+ }
- if (files != null) {
- for (String filename : files) {
- InputStream in = null;
- OutputStream out = null;
+ // This must be a file: extract it
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ // sideUpgrade is set to true, if we upgrade to the same version -- just check for the files existence before copying
+ if (sideUpgrade && dataPath.exists()) {
+ Log.d(ScummVM.LOG_TAG, "Side-upgrade. No need to update asset file: " + assetPath);
+ continue;
+ }
+
+ Log.d(ScummVM.LOG_TAG, "Copying asset file: " + assetPath);
+ in = assetManager.open(assetPath);
+ out = new FileOutputStream(dataPath);
+ copyStreamToStream(in, out);
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "Failed to copy asset file: " + assetPath);
+ } finally {
+ if (in != null) {
try {
- in = assetManager.open(filename);
- File outFile = new File(_actualScummVMDataDir, filename);
- if (sideUpgrade && outFile.exists()) {
- Log.d(ScummVM.LOG_TAG, "Side-upgrade. No need to update asset file: " + filename);
- } else {
- Log.d(ScummVM.LOG_TAG, "Copying asset file: " + filename);
- out = new FileOutputStream(outFile);
- copyStreamToStream(in, out);
- }
+ in.close();
} catch (IOException e) {
- Log.e(ScummVM.LOG_TAG, "Failed to copy asset file: " + filename);
- } finally {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- // NOOP
- }
- }
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {
- // NOOP
- }
- }
+ // NOOP
+ }
+ }
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ // NOOP
}
}
}
}
+ return true;
+ }
+
+ private void copyAssetsToInternalMemory(boolean sideUpgrade) {
+ if (_actualScummVMDataDir == null) {
+ return;
+ }
+
+ internalAppFolderCleanup(_actualScummVMDataDir);
+
+ AssetManager assetManager = getAssets();
+ extractAssets(sideUpgrade, assetManager, "assets", new File(_actualScummVMDataDir, "assets"));
}
// -------------------------------------------------------------------------------------------
Commit: 5603f64873ff25cba6bc2fab4b2a2af4c525439f
https://github.com/scummvm/scummvm/commit/5603f64873ff25cba6bc2fab4b2a2af4c525439f
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-11-12T22:46:21+01:00
Commit Message:
ANDROID: Use a checksum of all assets to determine if an update is needed
Changed paths:
backends/platform/android/android.mk
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index 9a63072bd1f..62ae69793d1 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -6,7 +6,7 @@ GRADLE_FILES = $(shell find $(PATH_DIST)/gradle -type f)
PATH_BUILD = ./android_project
PATH_BUILD_GRADLE = $(PATH_BUILD)/gradle/.timestamp $(PATH_BUILD)/gradlew $(PATH_BUILD)/build.gradle $(PATH_BUILD)/settings.gradle $(PATH_BUILD)/mainAssets/build.gradle $(PATH_BUILD)/gradle.properties $(PATH_BUILD)/local.properties $(PATH_BUILD)/src.properties
# $(PATH_BUILD)/mainAssets/src/main/assets is the root and everything is placed in the assets subdirectory
-PATH_BUILD_ASSETS = $(PATH_BUILD)/mainAssets/src/main/assets/assets
+PATH_BUILD_ASSETS = $(PATH_BUILD)/mainAssets/src/main/assets
PATH_BUILD_LIB = $(PATH_BUILD)/lib/$(ABI)
PATH_BUILD_LIBSCUMMVM = $(PATH_BUILD)/lib/$(ABI)/libscummvm.so
@@ -42,43 +42,51 @@ $(PATH_BUILD)/local.properties: configure.stamp | $(PATH_BUILD)
$(PATH_BUILD)/src.properties: configure.stamp | $(PATH_BUILD)
$(ECHO) "srcdir=$(realpath $(srcdir))\n" > $(PATH_BUILD)/src.properties
-$(PATH_BUILD)/mainAssets/build.gradle: $(PATH_DIST)/mainAssets.gradle | $(PATH_BUILD_ASSETS)
+$(PATH_BUILD)/mainAssets/build.gradle: $(PATH_DIST)/mainAssets.gradle | $(PATH_BUILD_ASSETS)/MD5SUMS
$(INSTALL) -c -m 644 $< $@
-$(PATH_BUILD_ASSETS): $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_ENGINEDATA_BIG) $(DIST_FILES_SOUNDFONTS) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_FILES_DOCS) $(DIST_FILES_PLATFORM) $(DIST_FILES_SHADERS) | $(PATH_BUILD)
- $(INSTALL) -d $(PATH_BUILD_ASSETS)
- $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_ENGINEDATA_BIG) $(DIST_FILES_SOUNDFONTS) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_FILES_DOCS) $(DIST_FILES_PLATFORM) $(PATH_BUILD_ASSETS)/
+$(PATH_BUILD_ASSETS)/MD5SUMS: $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_ENGINEDATA_BIG) $(DIST_FILES_SOUNDFONTS) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_FILES_DOCS) $(DIST_FILES_PLATFORM) $(DIST_FILES_SHADERS) | $(PATH_BUILD)
+ $(INSTALL) -d $(PATH_BUILD_ASSETS)/assets/
+ $(INSTALL) -c -m 644 $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DIST_FILES_ENGINEDATA_BIG) $(DIST_FILES_SOUNDFONTS) $(DIST_FILES_NETWORKING) $(DIST_FILES_VKEYBD) $(DIST_FILES_DOCS) $(DIST_FILES_PLATFORM) $(PATH_BUILD_ASSETS)/assets/
ifneq ($(DIST_FILES_SHADERS),)
- $(INSTALL) -d $(PATH_BUILD_ASSETS)/shaders
- $(INSTALL) -c -m 644 $(DIST_FILES_SHADERS) $(PATH_BUILD_ASSETS)/shaders
+ $(INSTALL) -d $(PATH_BUILD_ASSETS)/assets/shaders
+ $(INSTALL) -c -m 644 $(DIST_FILES_SHADERS) $(PATH_BUILD_ASSETS)/assets/shaders
endif
+ (cd $(PATH_BUILD_ASSETS)/ && find assets -type f | sort | xargs md5sum) > $@
ifdef DIST_ANDROID_CACERT_PEM
-$(PATH_BUILD_ASSETS)/cacert.pem: $(DIST_ANDROID_CACERT_PEM) | $(PATH_BUILD_ASSETS)
- $(INSTALL) -c -m 644 $(DIST_ANDROID_CACERT_PEM) $(PATH_BUILD_ASSETS)/cacert.pem
+$(PATH_BUILD_ASSETS)/assets/cacert.pem: $(DIST_ANDROID_CACERT_PEM)
+ $(INSTALL) -d $(PATH_BUILD_ASSETS)/assets/
+ $(INSTALL) -c -m 644 $(DIST_ANDROID_CACERT_PEM) $(PATH_BUILD_ASSETS)/assets/cacert.pem
+$(PATH_BUILD_ASSETS)/MD5SUMS: $(PATH_BUILD_ASSETS)/assets/cacert.pem
else
ifdef USE_CURL
-$(PATH_BUILD_ASSETS)/cacert.pem: | $(PATH_BUILD_ASSETS)
- $(QUIET_CURL)$(CURL) -s https://curl.se/ca/cacert.pem --time-cond $(PATH_BUILD_ASSETS)/cacert.pem --output $(PATH_BUILD_ASSETS)/cacert.pem
-androidcacert: | $(PATH_BUILD_ASSETS)
- $(QUIET_CURL)$(CURL) -s https://curl.se/ca/cacert.pem --time-cond $(PATH_BUILD_ASSETS)/cacert.pem --output $(PATH_BUILD_ASSETS)/cacert.pem
+$(PATH_BUILD_ASSETS)/cacert.pem:
+ $(INSTALL) -d $(PATH_BUILD_ASSETS)/assets/
+ $(QUIET_CURL)$(CURL) -s https://curl.se/ca/cacert.pem --time-cond $(PATH_BUILD_ASSETS)/assets/cacert.pem --output $(PATH_BUILD_ASSETS)/assets/cacert.pem
+androidcacert:
+ $(INSTALL) -d $(PATH_BUILD_ASSETS)/assets/
+ $(QUIET_CURL)$(CURL) -s https://curl.se/ca/cacert.pem --time-cond $(PATH_BUILD_ASSETS)/assets/cacert.pem --output $(PATH_BUILD_ASSETS)/assets/cacert.pem
+
.PHONY: androidcacert
endif
endif
+# Make MD5SUMS depend on cacert. If it's not here and neither DIST_ANDROID_CACERT_PEM nor USE_CURL are defined, it will error out
+$(PATH_BUILD_ASSETS)/MD5SUMS: $(PATH_BUILD_ASSETS)/assets/cacert.pem
$(PATH_BUILD_LIBSCUMMVM): libscummvm.so | $(PATH_BUILD)
$(INSTALL) -d $(PATH_BUILD_LIB)
$(INSTALL) -c -m 644 libscummvm.so $(PATH_BUILD_LIBSCUMMVM)
-$(APK_MAIN): $(PATH_BUILD_GRADLE) $(PATH_BUILD_ASSETS) $(PATH_BUILD_ASSETS)/cacert.pem $(PATH_BUILD_LIBSCUMMVM) | $(PATH_BUILD)
+$(APK_MAIN): $(PATH_BUILD_GRADLE) $(PATH_BUILD_ASSETS)/MD5SUMS $(PATH_BUILD_LIBSCUMMVM) | $(PATH_BUILD)
(cd $(PATH_BUILD); ./gradlew assembleDebug)
$(CP) $(PATH_BUILD)/build/outputs/apk/debug/$(APK_MAIN) $@
-$(APK_MAIN_RELEASE): $(PATH_BUILD_GRADLE) $(PATH_BUILD_ASSETS) $(PATH_BUILD_ASSETS)/cacert.pem $(PATH_BUILD_LIBSCUMMVM) | $(PATH_BUILD)
+$(APK_MAIN_RELEASE): $(PATH_BUILD_GRADLE) $(PATH_BUILD_ASSETS)/MD5SUMS $(PATH_BUILD_LIBSCUMMVM) | $(PATH_BUILD)
(cd $(PATH_BUILD); ./gradlew assembleRelease)
$(CP) $(PATH_BUILD)/build/outputs/apk/release/$(APK_MAIN_RELEASE) $@
-$(AAB_MAIN_RELEASE): $(PATH_BUILD_GRADLE) $(PATH_BUILD_ASSETS) $(PATH_BUILD_ASSETS)/cacert.pem $(PATH_BUILD_LIBSCUMMVM) | $(PATH_BUILD)
+$(AAB_MAIN_RELEASE): $(PATH_BUILD_GRADLE) $(PATH_BUILD_ASSETS)/MD5SUMS $(PATH_BUILD_LIBSCUMMVM) | $(PATH_BUILD)
(cd $(PATH_BUILD); ./gradlew bundleRelease -PsplitAssets)
$(CP) $(PATH_BUILD)/build/outputs/bundle/release/$(AAB_MAIN_RELEASE) $@
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 429c6e147f1..320b61ab43a 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -46,6 +46,8 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
@@ -1418,6 +1420,27 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
}
}
+ private static boolean equalsStreamToStream(InputStream is1, InputStream is2) throws IOException {
+ byte[] buffer1 = new byte[1024];
+ byte[] buffer2 = new byte[1024];
+ int length1, length2;
+
+ while (true) {
+ length1 = is1.read(buffer1);
+ length2 = is2.read(buffer2);
+ if (length1 != length2) {
+ return false;
+ }
+ if (length1 == -1) {
+ // Both streams are finished at the same point
+ return true;
+ }
+ if (!Arrays.equals(buffer1, buffer2)) {
+ return false;
+ }
+ }
+ }
+
private static String getVersionInfoFromScummvmConfiguration(String fullIniFilePath) {
Map<String, Map<String, String>> parsedIniMap;
try (FileReader reader = new FileReader(fullIniFilePath)) {
@@ -1687,25 +1710,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
Log.d(ScummVM.LOG_TAG, "No viable existing ScummVM config version found");
}
- //
- // TODO The assets cleanup upgrading system is not perfect but it will have to do
- // A more efficient way would be to compare hash (when we deem that an upgrade is happening, so we will also still have to compare versions)
- // Note that isSideUpgrading is also true each time we re-launch the app
- // Also even during a side-upgrade we cleanup any redundant files (no longer part of our assets)
-
- // By first checking for isDirty() and then comparing the Version objects,
- // we don't need to also compare the Version descriptions (full version text) for a match too,
- // since, if the full versions text do not match, it's because at least one of them is dirty.
- // TODO: This does mean that "pre" (or similar) versions (eg. 2.2.1pre) will always be considered non-side-upgrades
- // and will re-copy the assets upon each launch
- // This should have a slight performance impact (for launch time) for those intermediate version releases,
- // but it's better than the alternative (comparing MD5 hashes for all files), and it should go away with the next proper release.
- // This solution should cover "git" versions properly
- // (ie. developer builds, built with release configuration (eg 2.3.0git) or debug configuration (eg. 2.3.0git9272-gc71ac4748b))
- boolean isSideUpgrading = (!_currentScummVMVersion.isDirty()
- && !maxOldVersionFound.isDirty()
- && maxOldVersionFound.compareTo(_currentScummVMVersion) == 0);
- copyAssetsToInternalMemory(isSideUpgrading);
+ updateAssetsToInternalMemory();
//
// Set global savepath
@@ -2021,10 +2026,9 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// clear up any possibly deprecated assets (when upgrading to a new version)
// Don't remove the scummvm.ini nor the scummvm.log file!
- // Remove any files not in the filesItenary, even in a sideUpgrade
- // Remove any files in the filesItenary only if not a sideUpgrade
+ // Remove any files not in the assetsToExtract
// Returns true if the dataDir was a directory and false otherwise
- private static boolean assetsFolderCleanup(boolean sideUpgrade, File dataDir, String[] assetsToExtract) {
+ private static boolean assetsFolderCleanup(File dataDir, String[] assetsToExtract) {
HashSet<String> filesToKeep = new HashSet<>(Arrays.asList(assetsToExtract));
File[] extfiles = dataDir.listFiles();
@@ -2037,7 +2041,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
for (File extfile : extfiles) {
String name = extfile.getName();
- if (filesToKeep.contains(name) && sideUpgrade) {
+ if (filesToKeep.contains(name)) {
continue;
}
@@ -2048,6 +2052,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
Log.d(ScummVM.LOG_TAG, "Deleting file:" + extfile.getName());
if (!extfile.delete()) {
Log.e(ScummVM.LOG_TAG, "Failed to delete file:" + extfile.getName());
+ // Ignore error, that will be a leftover
}
}
}
@@ -2059,12 +2064,13 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// - We copy all the files from our assets (not a subset of them)
// Otherwise we would probably need to create a specifically named zip file with the selection of files we'd need to extract to the internal memory
// Returns true if the assetDir was a directory and false otherwise
- private static boolean extractAssets(boolean sideUpgrade, AssetManager assetManager, String assetDir, File dataDir) {
+ private static boolean extractAssets(AssetManager assetManager, String assetDir, File dataDir) throws IOException {
String[] files = null;
try {
files = assetManager.list(assetDir);
} catch (IOException e) {
Log.e(ScummVM.LOG_TAG, "Failed to get asset file list.", e);
+ throw e;
}
if (files == null || files.length == 0) {
@@ -2078,13 +2084,13 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// Starting from here, assetDir is a directory
// Cleanup old files
- if (!assetsFolderCleanup(sideUpgrade, dataDir, files)) {
+ if (!assetsFolderCleanup(dataDir, files)) {
// dataDir is a file but we need a folder
if (dataDir.exists()) {
if (!dataDir.delete()) {
Log.e(ScummVM.LOG_TAG, "Failed to delete file:" + dataDir.getName());
// There is no point on continuing this
- return true;
+ throw new IOException("Failed to delete file:" + dataDir.getName());
}
}
}
@@ -2093,7 +2099,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
if (!dataDir.mkdir()) {
Log.e(ScummVM.LOG_TAG, "Failed to create directory: " + dataDir.getPath());
// There is no point on continuing this
- return true;
+ throw new IOException("Failed to create directory:" + dataDir.getName());
}
}
@@ -2101,7 +2107,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
String assetPath = (assetDir.length() > 0 ? assetDir + File.separator : "") + filename;
File dataPath = new File(dataDir, filename);
- if (extractAssets(sideUpgrade, assetManager, assetPath, dataPath)) {
+ if (extractAssets(assetManager, assetPath, dataPath)) {
// This was a directory: no data to extract
continue;
}
@@ -2110,12 +2116,6 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
InputStream in = null;
OutputStream out = null;
try {
- // sideUpgrade is set to true, if we upgrade to the same version -- just check for the files existence before copying
- if (sideUpgrade && dataPath.exists()) {
- Log.d(ScummVM.LOG_TAG, "Side-upgrade. No need to update asset file: " + assetPath);
- continue;
- }
-
Log.d(ScummVM.LOG_TAG, "Copying asset file: " + assetPath);
in = assetManager.open(assetPath);
out = new FileOutputStream(dataPath);
@@ -2142,7 +2142,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return true;
}
- private void copyAssetsToInternalMemory(boolean sideUpgrade) {
+ private void updateAssetsToInternalMemory() {
if (_actualScummVMDataDir == null) {
return;
}
@@ -2150,7 +2150,87 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
internalAppFolderCleanup(_actualScummVMDataDir);
AssetManager assetManager = getAssets();
- extractAssets(sideUpgrade, assetManager, "assets", new File(_actualScummVMDataDir, "assets"));
+
+ // We need to compare MD5SUMS from our assets with what is on disk
+ File md5sumsPath = new File(_actualScummVMDataDir, "MD5SUMS");
+
+ Log.d(ScummVM.LOG_TAG, "Checking status of MD5SUMS");
+ // First: read MD5SUMS from our assets, we will need it
+ byte[] newSums = null;
+ {
+ InputStream newStreamAsset = null;
+ try {
+ newStreamAsset = assetManager.open("MD5SUMS");
+ ByteArrayOutputStream newStream = new ByteArrayOutputStream();
+ copyStreamToStream(newStreamAsset, newStream);
+ newSums = newStream.toByteArray();
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "Failed to read MD5SUMS asset");
+ } finally {
+ if (newStreamAsset != null) {
+ try {
+ newStreamAsset.close();
+ } catch (IOException e) {
+ // NOOP
+ }
+ }
+ // Closing a ByteArrayOutputStream is useless
+ }
+ }
+
+ // Then: open the on disk file, check its size and if they match, compare the contents
+ if (newSums != null && newSums.length > 0) {
+ FileInputStream oldStream = null;
+ try {
+ oldStream = new FileInputStream(md5sumsPath);
+ if (oldStream.getChannel().size() == newSums.length &&
+ equalsStreamToStream(new ByteArrayInputStream(newSums), oldStream)) {
+ // The files are identical: nothing to do
+ Log.d(ScummVM.LOG_TAG, "MD5SUMS is already up to date");
+ return;
+ }
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "Failed to read MD5SUMS file");
+ } finally {
+ if (oldStream != null) {
+ try {
+ oldStream.close();
+ } catch (IOException e) {
+ // NOOP
+ }
+ }
+ }
+ }
+
+ // Continue: with extracting the whole assets
+ try {
+ extractAssets(assetManager, "assets", new File(_actualScummVMDataDir, "assets"));
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "An error happened while extracting the assets");
+ // Don't write the new MD5SUMS: we did not finish our work well
+ return;
+ }
+
+
+ // Finally: everything is now fresh, store the new sums
+ if (newSums != null) {
+ FileOutputStream newStream = null;
+ try {
+ newStream = new FileOutputStream(md5sumsPath);
+ newStream.write(newSums);
+ } catch (IOException e) {
+ Log.e(ScummVM.LOG_TAG, "Failed to write MD5SUMS file");
+ // If we fail to write MD5SUMS, we will try again at the next startup
+ } finally {
+ if (newStream != null) {
+ try {
+ newStream.close();
+ } catch (IOException e) {
+ // NOOP
+ }
+ }
+ }
+ }
}
// -------------------------------------------------------------------------------------------
Commit: 90f7892e3b8165f3a43e90269aca8f3d6cff6e7e
https://github.com/scummvm/scummvm/commit/90f7892e3b8165f3a43e90269aca8f3d6cff6e7e
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-11-12T22:46:21+01:00
Commit Message:
ANDROID: Forward to C++ side the assets change status
Changed paths:
backends/platform/android/jni-android.cpp
backends/platform/android/jni-android.h
backends/platform/android/org/scummvm/scummvm/ScummVM.java
backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
diff --git a/backends/platform/android/jni-android.cpp b/backends/platform/android/jni-android.cpp
index c8808bbc7dc..f2f43971064 100644
--- a/backends/platform/android/jni-android.cpp
+++ b/backends/platform/android/jni-android.cpp
@@ -69,6 +69,8 @@ int JNI::_egl_version = 0;
Common::Archive *JNI::_asset_archive = 0;
OSystem_Android *JNI::_system = 0;
+bool JNI::assets_updated = false;
+
bool JNI::pause = false;
sem_t JNI::pause_sem;
@@ -120,7 +122,7 @@ const JNINativeMethod JNI::_natives[] = {
{ "create", "(Landroid/content/res/AssetManager;"
"Ljavax/microedition/khronos/egl/EGL10;"
"Ljavax/microedition/khronos/egl/EGLDisplay;"
- "Landroid/media/AudioTrack;II)V",
+ "Landroid/media/AudioTrack;IIZ)V",
(void *)JNI::create },
{ "destroy", "()V",
(void *)JNI::destroy },
@@ -721,7 +723,8 @@ void JNI::setAudioStop() {
void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
jobject egl, jobject egl_display,
- jobject at, jint audio_sample_rate, jint audio_buffer_size) {
+ jobject at, jint audio_sample_rate, jint audio_buffer_size,
+ jboolean assets_updated_) {
LOGI("Native version: %s", gScummVMFullVersion);
assert(!_system);
@@ -798,6 +801,8 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
env->DeleteLocalRef(cls);
#undef FIND_METHOD
+ assets_updated = assets_updated_;
+
pause = false;
// initial value of zero!
sem_init(&pause_sem, 0, 0);
diff --git a/backends/platform/android/jni-android.h b/backends/platform/android/jni-android.h
index 3ceb3f76f04..d5d55b3a172 100644
--- a/backends/platform/android/jni-android.h
+++ b/backends/platform/android/jni-android.h
@@ -44,6 +44,8 @@ private:
virtual ~JNI();
public:
+ static bool assets_updated;
+
static bool pause;
static sem_t pause_sem;
@@ -183,7 +185,8 @@ private:
static void create(JNIEnv *env, jobject self, jobject asset_manager,
jobject egl, jobject egl_display,
jobject at, jint audio_sample_rate,
- jint audio_buffer_size);
+ jint audio_buffer_size,
+ jboolean assets_updated_);
static void destroy(JNIEnv *env, jobject self);
static void setSurface(JNIEnv *env, jobject self, jint width, jint height, jint bpp);
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVM.java b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
index ced347e1ee3..a21af60e1d6 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVM.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVM.java
@@ -44,14 +44,16 @@ public abstract class ScummVM implements SurfaceHolder.Callback,
private int _sample_rate = 0;
private int _buffer_size = 0;
+ private boolean _assetsUpdated;
private String[] _args;
private native void create(AssetManager asset_manager,
EGL10 egl,
- EGLDisplay egl_display,
+ EGLDisplay egl_display,
AudioTrack audio_track,
- int sample_rate,
- int buffer_size);
+ int sample_rate,
+ int buffer_size,
+ boolean assetsUpdated);
private native void destroy();
private native void setSurface(int width, int height, int bpp);
private native int main(String[] args);
@@ -151,6 +153,10 @@ public abstract class ScummVM implements SurfaceHolder.Callback,
setSurface(0, 0, 0);
}
+ final public void setAssetsUpdated(boolean assetsUpdated) {
+ _assetsUpdated = assetsUpdated;
+ }
+
final public void setArgs(String[] args) {
_args = args;
}
@@ -173,7 +179,8 @@ public abstract class ScummVM implements SurfaceHolder.Callback,
}
create(_asset_manager, _egl, _egl_display,
- _audio_track, _sample_rate, _buffer_size);
+ _audio_track, _sample_rate, _buffer_size,
+ _assetsUpdated);
int res = main(_args);
diff --git a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
index 320b61ab43a..9b969bbe9cc 100644
--- a/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
+++ b/backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
@@ -68,6 +68,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private ClipboardManager _clipboardManager;
private Version _currentScummVMVersion;
+ private boolean _assetsUpdated;
private File _configScummvmFile;
private File _logScummvmFile;
private File _actualScummVMDataDir;
@@ -1012,6 +1013,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
// in fact in all the cases where we return false, we also called finish()
return;
}
+ _scummvm.setAssetsUpdated(_assetsUpdated);
// We should have a valid path to a configuration file here
@@ -2147,6 +2149,8 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
return;
}
+ _assetsUpdated = true;
+
internalAppFolderCleanup(_actualScummVMDataDir);
AssetManager assetManager = getAssets();
@@ -2187,6 +2191,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
equalsStreamToStream(new ByteArrayInputStream(newSums), oldStream)) {
// The files are identical: nothing to do
Log.d(ScummVM.LOG_TAG, "MD5SUMS is already up to date");
+ _assetsUpdated = false;
return;
}
} catch (IOException e) {
Commit: aef1690c1d115e3d15b043ab5ef61ff46aa7d531
https://github.com/scummvm/scummvm/commit/aef1690c1d115e3d15b043ab5ef61ff46aa7d531
Author: Le Philousophe (lephilousophe at users.noreply.github.com)
Date: 2024-11-12T22:46:21+01:00
Commit Message:
ANDROID: Allow packagers to bundle games in the assets
They get copied on update and automatically added.
Removed games located in the assets are cleaned up too.
Changed paths:
backends/platform/android/android.cpp
backends/platform/android/android.h
backends/platform/android/android.mk
diff --git a/backends/platform/android/android.cpp b/backends/platform/android/android.cpp
index 6a1521a66e4..ea26cfeaf77 100644
--- a/backends/platform/android/android.cpp
+++ b/backends/platform/android/android.cpp
@@ -74,14 +74,14 @@
#include "backends/keymapper/keymapper-defaults.h"
#include "backends/keymapper/standard-actions.h"
-#include "common/util.h"
-#include "common/textconsole.h"
-#include "common/rect.h"
-#include "common/queue.h"
-#include "common/mutex.h"
-#include "common/events.h"
#include "common/config-manager.h"
+#include "common/events.h"
+#include "common/mutex.h"
+#include "common/queue.h"
+#include "common/textconsole.h"
#include "common/translation.h"
+#include "common/util.h"
+
#include "graphics/cursorman.h"
const char *android_log_tag = "ScummVM";
@@ -587,6 +587,53 @@ void OSystem_Android::engineDone() {
JNI::setCurrentGame("");
}
+void OSystem_Android::updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &settings, Common::StringArray& additionalArgs) {
+ // We only try to detect bundled games only on an app version update
+ if (!JNI::assets_updated) {
+ return;
+ }
+
+ Common::Path gamesPath(JNI::getScummVMBasePath(), Common::Path::kNativeSeparator);
+ gamesPath.joinInPlace("assets/games");
+
+ // We need to init the ConfMan ourselves to cleanup outdated games
+ Common::SeekableReadStream *configStream = createConfigReadStream();
+ if (configStream) {
+ // The configuration file exists, we can load it and clean it
+ delete configStream;
+ ConfMan.loadDefaultConfigFile(Common::Path());
+
+ for (Common::ConfigManager::DomainMap::iterator it = ConfMan.beginGameDomains(), end = ConfMan.endGameDomains(); it != end; ++it) {
+ if (!it->_value.contains("path")) {
+ continue;
+ }
+ Common::Path path = Common::Path::fromConfig(it->_value.getVal("path"));
+ if (!path.isRelativeTo(gamesPath)) {
+ continue;
+ }
+ if (Common::FSNode(path).isDirectory()) {
+ continue;
+ }
+ LOGI("Cleanup up: %s, %s not found", it->_key.c_str(), path.toString().c_str());
+ // path is inside our assets games directory and doesn't exist anymore: cleanup
+ ConfMan.removeGameDomain(it->_key);
+ }
+ ConfMan.flushToDisk();
+ }
+
+ Common::FSNode node(gamesPath);
+ if (!node.exists() || !node.isDirectory() ) {
+ return;
+ }
+
+ // As this detection happens only once per version upgrade, ignore command and override it
+ LOGD("Searching games");
+ command = "add";
+ settings["path"] = gamesPath.toConfig();
+ settings["recursive"] = "true";
+ settings["exit"] = "false";
+}
+
void OSystem_Android::updateOnScreenControls() {
int enableMask = SHOW_ON_SCREEN_ALL;
if (!ConfMan.getBool("onscreen_control")) {
diff --git a/backends/platform/android/android.h b/backends/platform/android/android.h
index 4c89a514a3c..6e277a11073 100644
--- a/backends/platform/android/android.h
+++ b/backends/platform/android/android.h
@@ -215,6 +215,8 @@ public:
void engineInit() override;
void engineDone() override;
+ void updateStartSettings(const Common::String &executable, Common::String &command, Common::StringMap &startSettings, Common::StringArray& additionalArgs) override;
+
bool hasFeature(OSystem::Feature f) override;
void setFeatureState(OSystem::Feature f, bool enable) override;
bool getFeatureState(OSystem::Feature f) override;
diff --git a/backends/platform/android/android.mk b/backends/platform/android/android.mk
index 62ae69793d1..d9e50135a6f 100644
--- a/backends/platform/android/android.mk
+++ b/backends/platform/android/android.mk
@@ -51,6 +51,10 @@ $(PATH_BUILD_ASSETS)/MD5SUMS: $(DIST_FILES_THEMES) $(DIST_FILES_ENGINEDATA) $(DI
ifneq ($(DIST_FILES_SHADERS),)
$(INSTALL) -d $(PATH_BUILD_ASSETS)/assets/shaders
$(INSTALL) -c -m 644 $(DIST_FILES_SHADERS) $(PATH_BUILD_ASSETS)/assets/shaders
+endif
+ifneq ($(GAMES_BUNDLE_DIRECTORY),)
+ $(INSTALL) -d $(PATH_BUILD_ASSETS)/assets/games
+ $(CP) -r $(GAMES_BUNDLE_DIRECTORY)/. $(PATH_BUILD_ASSETS)/assets/games/
endif
(cd $(PATH_BUILD_ASSETS)/ && find assets -type f | sort | xargs md5sum) > $@
More information about the Scummvm-git-logs
mailing list