Skip to content

Commit

Permalink
ANDROID: Use a build time constant to determine if we are updating
Browse files Browse the repository at this point in the history
  • Loading branch information
lephilousophe committed Nov 12, 2024
1 parent f762c06 commit bcaeeb0
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 47 deletions.
6 changes: 5 additions & 1 deletion backends/platform/android/android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,10 @@ void OSystem_Android::initBackend() {
}
}

// Set up our current build date
ConfMan.set("androidversiondate", Common::String::format("%" PRId64, JNI::pkg_build_date),
Common::ConfigManager::kApplicationDomain);

// Warning: ConfMan.registerDefault() can be used for a Session of ScummVM
// but:
// 1. The values will NOT persist to storage
Expand Down Expand Up @@ -589,7 +593,7 @@ void OSystem_Android::engineDone() {

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::is_side_upgrading) {
if (!JNI::changing_version) {
return;
}

Expand Down
10 changes: 6 additions & 4 deletions backends/platform/android/jni-android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ int JNI::_egl_version = 0;
Common::Archive *JNI::_asset_archive = 0;
OSystem_Android *JNI::_system = 0;

bool JNI::is_side_upgrading = false;
int64 JNI::pkg_build_date = 0;
bool JNI::changing_version = false;

bool JNI::pause = false;
sem_t JNI::pause_sem;
Expand Down Expand Up @@ -122,7 +123,7 @@ const JNINativeMethod JNI::_natives[] = {
{ "create", "(Landroid/content/res/AssetManager;"
"Ljavax/microedition/khronos/egl/EGL10;"
"Ljavax/microedition/khronos/egl/EGLDisplay;"
"Landroid/media/AudioTrack;IIZ)V",
"Landroid/media/AudioTrack;IIJZ)V",
(void *)JNI::create },
{ "destroy", "()V",
(void *)JNI::destroy },
Expand Down Expand Up @@ -724,7 +725,7 @@ 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,
jboolean is_side_upgrading_) {
jlong pkg_build_date_, jboolean changing_version_) {
LOGI("Native version: %s", gScummVMFullVersion);

assert(!_system);
Expand Down Expand Up @@ -801,7 +802,8 @@ void JNI::create(JNIEnv *env, jobject self, jobject asset_manager,
env->DeleteLocalRef(cls);
#undef FIND_METHOD

is_side_upgrading = is_side_upgrading_;
pkg_build_date = pkg_build_date_;
changing_version = changing_version_;

pause = false;
// initial value of zero!
Expand Down
5 changes: 3 additions & 2 deletions backends/platform/android/jni-android.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class JNI {
virtual ~JNI();

public:
static bool is_side_upgrading;
static int64 pkg_build_date;
static bool changing_version;

static bool pause;
static sem_t pause_sem;
Expand Down Expand Up @@ -186,7 +187,7 @@ class JNI {
jobject egl, jobject egl_display,
jobject at, jint audio_sample_rate,
jint audio_buffer_size,
jboolean is_side_upgrading);
jlong pkg_build_date_, jboolean changing_version_);
static void destroy(JNIEnv *env, jobject self);

static void setSurface(JNIEnv *env, jobject self, jint width, jint height, jint bpp);
Expand Down
11 changes: 6 additions & 5 deletions backends/platform/android/org/scummvm/scummvm/ScummVM.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public abstract class ScummVM implements SurfaceHolder.Callback,
private int _sample_rate = 0;
private int _buffer_size = 0;

private boolean _isSideUpgrading;
private boolean _changingVersion;
private String[] _args;

private native void create(AssetManager asset_manager,
Expand All @@ -53,7 +53,8 @@ private native void create(AssetManager asset_manager,
AudioTrack audio_track,
int sample_rate,
int buffer_size,
boolean isSideUpgrading);
long pkgBuildDate,
boolean changingVersion);
private native void destroy();
private native void setSurface(int width, int height, int bpp);
private native int main(String[] args);
Expand Down Expand Up @@ -153,8 +154,8 @@ final public void surfaceDestroyed(SurfaceHolder holder) {
setSurface(0, 0, 0);
}

final public void setIsSideUpgrading(boolean isSideUpgrading) {
_isSideUpgrading = isSideUpgrading;
final public void setChangingVersion(boolean changingVersion) {
_changingVersion = changingVersion;
}

final public void setArgs(String[] args) {
Expand All @@ -180,7 +181,7 @@ final public void run() {

create(_asset_manager, _egl, _egl_display,
_audio_track, _sample_rate, _buffer_size,
_isSideUpgrading);
BuildConfig.BUILD_DATE, _changingVersion);

int res = main(_args);

Expand Down
76 changes: 41 additions & 35 deletions backends/platform/android/org/scummvm/scummvm/ScummVMActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public class ScummVMActivity extends Activity implements OnKeyboardVisibilityLis
private ClipboardManager _clipboardManager;

private Version _currentScummVMVersion;
private boolean _isSideUpgrading;
private boolean _changingVersion;
private File _configScummvmFile;
private File _logScummvmFile;
private File _actualScummVMDataDir;
Expand Down Expand Up @@ -1011,7 +1011,7 @@ public void handle(int exitResult) {
// in fact in all the cases where we return false, we also called finish()
return;
}
_scummvm.setIsSideUpgrading(_isSideUpgrading);
_scummvm.setChangingVersion(_changingVersion);

// We should have a valid path to a configuration file here

Expand Down Expand Up @@ -1430,6 +1430,25 @@ private static String getVersionInfoFromScummvmConfiguration(String fullIniFileP
return INIParser.get(parsedIniMap, "scummvm", "versioninfo", null);
}

// As we are called later, we have a File object instead of a String
private static Long getAndroidVersionDateFromScummvmConfiguration(File iniFile) {
Map<String, Map<String, String>> parsedIniMap;
try (FileReader reader = new FileReader(iniFile)) {
parsedIniMap = INIParser.parse(reader);
} catch (IOException ignored) {
return null;
}
String versiondate = INIParser.get(parsedIniMap, "scummvm", "androidversiondate", null);
if (versiondate == null) {
return null;
}
try {
return Long.parseLong(versiondate, 10);
} catch (NumberFormatException e) {
return null;
}
}

private boolean seekAndInitScummvmConfiguration() {

// https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)
Expand Down Expand Up @@ -1571,6 +1590,7 @@ private boolean seekAndInitScummvmConfiguration() {
boolean scummVMConfigHandled = false;
Version maxOldVersionFound = new Version("0"); // dummy initializer
Version existingVersionFoundInScummVMDataDir = new Version("0"); // dummy initializer
Long maxOldVersionDate = null;

final Version version2_2_1_forPatch = new Version("2.2.1"); // patch for 2.2.1 Beta1 purposes
boolean existingConfigInScummVMDataDirReplacedOnce = false; // patch for 2.2.1 Beta1 purposes
Expand Down Expand Up @@ -1684,29 +1704,18 @@ public void onClick(DialogInterface dialog, int which) {
}

if (maxOldVersionFound.compareTo(new Version("0")) != 0) {
Log.d(ScummVM.LOG_TAG, "Maximum ScummVM version found and (re)used is: " + maxOldVersionFound.getDescription() +" (" + maxOldVersionFound.get() +")");
maxOldVersionDate = getAndroidVersionDateFromScummvmConfiguration(_configScummvmFile);
Log.d(ScummVM.LOG_TAG, "Maximum ScummVM version found and (re)used is: " + maxOldVersionFound.getDescription() +
" (" + maxOldVersionFound.get() +") with timestamp " + (maxOldVersionDate != null ? maxOldVersionDate.toString() : "unknown"));
} else {
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))
_isSideUpgrading = (!_currentScummVMVersion.isDirty()
&& !maxOldVersionFound.isDirty()
&& maxOldVersionFound.compareTo(_currentScummVMVersion) == 0);
// We determine if we are changing the version (upgrading or downgrading) by comparing the raw version
// But also by checking the build date minted in by Gradle
_changingVersion = (!maxOldVersionFound.getDescription().equals(_currentScummVMVersion.getDescription()) ||
maxOldVersionDate == null ||
maxOldVersionDate.longValue() != BuildConfig.BUILD_DATE);
copyAssetsToInternalMemory();

//
Expand Down Expand Up @@ -2023,10 +2032,9 @@ private static void internalAppFolderCleanup(File dataDir) {

// 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();
Expand All @@ -2039,7 +2047,7 @@ private static boolean assetsFolderCleanup(boolean sideUpgrade, File dataDir, St
for (File extfile : extfiles) {
String name = extfile.getName();

if (filesToKeep.contains(name) && sideUpgrade) {
if (filesToKeep.contains(name)) {
continue;
}

Expand All @@ -2061,7 +2069,7 @@ private static boolean assetsFolderCleanup(boolean sideUpgrade, File dataDir, St
// - 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) {
String[] files = null;
try {
files = assetManager.list(assetDir);
Expand All @@ -2080,7 +2088,7 @@ private static boolean extractAssets(boolean sideUpgrade, AssetManager assetMana
// 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()) {
Expand All @@ -2103,7 +2111,7 @@ private static boolean extractAssets(boolean sideUpgrade, AssetManager assetMana
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;
}
Expand All @@ -2112,12 +2120,6 @@ private static boolean extractAssets(boolean sideUpgrade, AssetManager assetMana
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);
Expand Down Expand Up @@ -2148,11 +2150,15 @@ private void copyAssetsToInternalMemory() {
if (_actualScummVMDataDir == null) {
return;
}
// If our version didn't change since last time, no need to refresh the assets
if (!_changingVersion) {
return;
}

internalAppFolderCleanup(_actualScummVMDataDir);

AssetManager assetManager = getAssets();
extractAssets(_isSideUpgrading, assetManager, "assets", new File(_actualScummVMDataDir, "assets"));
extractAssets(assetManager, "assets", new File(_actualScummVMDataDir, "assets"));
}

// -------------------------------------------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions dists/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ android {
// ScummVM 1.9.0: 19
// ScummVM 1.8.1: 15

buildConfigField "long", "BUILD_DATE", System.currentTimeMillis() + "L"
}
buildFeatures {
buildConfig = true
}
buildTypes {
debug{
Expand Down

0 comments on commit bcaeeb0

Please sign in to comment.