From ef44e63f2255d3ecd6e18cc9772178ee6049ba3d Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio <fhuya@fb.com> Date: Sun, 14 Aug 2022 09:45:22 -0700 Subject: [PATCH 1/3] Fix GodotTTS native initialization --- .../android/java/lib/src/org/godotengine/godot/Godot.java | 2 +- .../android/java/lib/src/org/godotengine/godot/GodotLib.java | 3 ++- platform/android/java_godot_lib_jni.cpp | 4 ++-- platform/android/java_godot_lib_jni.h | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.java b/platform/android/java/lib/src/org/godotengine/godot/Godot.java index 2147607d54d7..8913e0faf569 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/Godot.java +++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.java @@ -587,7 +587,7 @@ private void initializeGodot() { mMagnetometer = mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); mGyroscope = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); - GodotLib.initialize(activity, this, activity.getAssets(), io, netUtils, directoryAccessHandler, fileAccessHandler, use_apk_expansion); + GodotLib.initialize(activity, this, activity.getAssets(), io, netUtils, directoryAccessHandler, fileAccessHandler, use_apk_expansion, tts); result_callback = null; diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java index acad0a7948b6..cf34b95c7667 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java +++ b/platform/android/java/lib/src/org/godotengine/godot/GodotLib.java @@ -32,6 +32,7 @@ import org.godotengine.godot.io.directory.DirectoryAccessHandler; import org.godotengine.godot.io.file.FileAccessHandler; +import org.godotengine.godot.tts.GodotTTS; import org.godotengine.godot.utils.GodotNetUtils; import android.app.Activity; @@ -52,7 +53,7 @@ public class GodotLib { /** * Invoked on the main thread to initialize Godot native layer. */ - public static native void initialize(Activity activity, Godot p_instance, AssetManager p_asset_manager, GodotIO godotIO, GodotNetUtils netUtils, DirectoryAccessHandler directoryAccessHandler, FileAccessHandler fileAccessHandler, boolean use_apk_expansion); + public static native void initialize(Activity activity, Godot p_instance, AssetManager p_asset_manager, GodotIO godotIO, GodotNetUtils netUtils, DirectoryAccessHandler directoryAccessHandler, FileAccessHandler fileAccessHandler, boolean use_apk_expansion, GodotTTS tts); /** * Invoked on the main thread to clean up Godot native layer. diff --git a/platform/android/java_godot_lib_jni.cpp b/platform/android/java_godot_lib_jni.cpp index 87776d861089..6b06bff615d9 100644 --- a/platform/android/java_godot_lib_jni.cpp +++ b/platform/android/java_godot_lib_jni.cpp @@ -120,7 +120,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setVirtualKeyboardHei } } -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion) { +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion, jobject p_godot_tts) { JavaVM *jvm; env->GetJavaVM(&jvm); @@ -137,7 +137,7 @@ JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *en DirAccessJAndroid::setup(p_directory_access_handler); FileAccessFilesystemJAndroid::setup(p_file_access_handler); NetSocketAndroid::setup(p_net_utils); - TTS_Android::setup(godot_java->get_member_object("tts", "Lorg/godotengine/godot/tts/GodotTTS;", env)); + TTS_Android::setup(p_godot_tts); os_android = new OS_Android(godot_java, godot_io_java, p_use_apk_expansion); diff --git a/platform/android/java_godot_lib_jni.h b/platform/android/java_godot_lib_jni.h index a9e677a90718..6c4d11272b24 100644 --- a/platform/android/java_godot_lib_jni.h +++ b/platform/android/java_godot_lib_jni.h @@ -37,7 +37,7 @@ // These functions can be called from within JAVA and are the means by which our JAVA implementation calls back into our C++ code. // See java/src/org/godotengine/godot/GodotLib.java for the JAVA side of this (yes that's why we have the long names) extern "C" { -JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion); +JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_initialize(JNIEnv *env, jclass clazz, jobject p_activity, jobject p_godot_instance, jobject p_asset_manager, jobject p_godot_io, jobject p_net_utils, jobject p_directory_access_handler, jobject p_file_access_handler, jboolean p_use_apk_expansion, jobject p_godot_tts); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_ondestroy(JNIEnv *env, jclass clazz); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_setup(JNIEnv *env, jclass clazz, jobjectArray p_cmdline); JNIEXPORT void JNICALL Java_org_godotengine_godot_GodotLib_resize(JNIEnv *env, jclass clazz, jint width, jint height); From 30479543b07d5869eb024663c6588e608bee3c1b Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio <fhuyakou@gmail.com> Date: Mon, 15 Aug 2022 00:35:21 -0700 Subject: [PATCH 2/3] Fix issue preventing the Android Editor from displaying the project content The issue was causing by a bug within the logic for `FileAccessFilesystemJAndroid#eof_reached()` causing that value to remain false after the eof was reached. This in turn caused an infinite loop in the file scanner preventing the project's content from showing up. --- .../android/file_access_filesystem_jandroid.cpp | 13 +++++++++++++ platform/android/file_access_filesystem_jandroid.h | 3 +++ .../src/org/godotengine/godot/io/file/DataAccess.kt | 8 ++------ .../godotengine/godot/io/file/FileAccessHandler.kt | 5 +++++ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp index ec9ce759c5f1..df23ffc46d29 100644 --- a/platform/android/file_access_filesystem_jandroid.cpp +++ b/platform/android/file_access_filesystem_jandroid.cpp @@ -45,6 +45,7 @@ jmethodID FileAccessFilesystemJAndroid::_file_seek_end = nullptr; jmethodID FileAccessFilesystemJAndroid::_file_read = nullptr; jmethodID FileAccessFilesystemJAndroid::_file_tell = nullptr; jmethodID FileAccessFilesystemJAndroid::_file_eof = nullptr; +jmethodID FileAccessFilesystemJAndroid::_file_set_eof = nullptr; jmethodID FileAccessFilesystemJAndroid::_file_close = nullptr; jmethodID FileAccessFilesystemJAndroid::_file_write = nullptr; jmethodID FileAccessFilesystemJAndroid::_file_flush = nullptr; @@ -161,6 +162,16 @@ bool FileAccessFilesystemJAndroid::eof_reached() const { } } +void FileAccessFilesystemJAndroid::_set_eof(bool eof) { + if (_file_set_eof) { + ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use."); + + JNIEnv *env = get_jni_env(); + ERR_FAIL_COND(env == nullptr); + env->CallVoidMethod(file_access_handler, _file_set_eof, id, eof); + } +} + uint8_t FileAccessFilesystemJAndroid::get_8() const { ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use."); uint8_t byte; @@ -183,6 +194,7 @@ String FileAccessFilesystemJAndroid::get_line() const { while (true) { size_t line_buffer_size = MIN(buffer_size_limit, file_size - get_position()); if (line_buffer_size <= 0) { + const_cast<FileAccessFilesystemJAndroid *>(this)->_set_eof(true); break; } @@ -309,6 +321,7 @@ void FileAccessFilesystemJAndroid::setup(jobject p_file_access_handler) { _file_get_size = env->GetMethodID(cls, "fileGetSize", "(I)J"); _file_tell = env->GetMethodID(cls, "fileGetPosition", "(I)J"); _file_eof = env->GetMethodID(cls, "isFileEof", "(I)Z"); + _file_set_eof = env->GetMethodID(cls, "setFileEof", "(IZ)V"); _file_seek = env->GetMethodID(cls, "fileSeek", "(IJ)V"); _file_seek_end = env->GetMethodID(cls, "fileSeekFromEnd", "(IJ)V"); _file_read = env->GetMethodID(cls, "fileRead", "(ILjava/nio/ByteBuffer;)I"); diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h index 3bf654a0302f..177df87dc142 100644 --- a/platform/android/file_access_filesystem_jandroid.h +++ b/platform/android/file_access_filesystem_jandroid.h @@ -44,6 +44,7 @@ class FileAccessFilesystemJAndroid : public FileAccess { static jmethodID _file_seek_end; static jmethodID _file_tell; static jmethodID _file_eof; + static jmethodID _file_set_eof; static jmethodID _file_read; static jmethodID _file_write; static jmethodID _file_flush; @@ -55,6 +56,8 @@ class FileAccessFilesystemJAndroid : public FileAccess { String absolute_path; String path_src; + void _set_eof(bool eof); + public: virtual Error _open(const String &p_path, int p_mode_flags) override; ///< open a file virtual void close() override; ///< close a file diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt index 463dabfb232b..f23537a29e49 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/DataAccess.kt @@ -104,7 +104,6 @@ internal abstract class DataAccess(private val filePath: String) { protected abstract val fileChannel: FileChannel internal var endOfFile = false - private set fun close() { try { @@ -125,9 +124,7 @@ internal abstract class DataAccess(private val filePath: String) { fun seek(position: Long) { try { fileChannel.position(position) - if (position <= size()) { - endOfFile = false - } + endOfFile = position >= fileChannel.size() } catch (e: Exception) { Log.w(TAG, "Exception when seeking file $filePath.", e) } @@ -161,8 +158,7 @@ internal abstract class DataAccess(private val filePath: String) { fun read(buffer: ByteBuffer): Int { return try { val readBytes = fileChannel.read(buffer) - endOfFile = readBytes == -1 - || (fileChannel.position() >= fileChannel.size() && fileChannel.size() > 0) + endOfFile = readBytes == -1 || (fileChannel.position() >= fileChannel.size()) if (readBytes == -1) { 0 } else { diff --git a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt index 04b6772c4508..83da3a24b3b5 100644 --- a/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt +++ b/platform/android/java/lib/src/org/godotengine/godot/io/file/FileAccessHandler.kt @@ -194,6 +194,11 @@ class FileAccessHandler(val context: Context) { return files[fileId].endOfFile } + fun setFileEof(fileId: Int, eof: Boolean) { + val file = files[fileId] ?: return + file.endOfFile = eof + } + fun fileClose(fileId: Int) { if (hasFileId(fileId)) { files[fileId].close() From 3ac6b6a596dad2f57390a8d7926604e349d2d281 Mon Sep 17 00:00:00 2001 From: Fredia Huya-Kouadio <fhuyakou@gmail.com> Date: Mon, 15 Aug 2022 02:30:08 -0700 Subject: [PATCH 3/3] Disable threads used to check on plugins to load The functionality is unavailable on Android (requires export capability) and unnecessarily consumes resources --- platform/android/export/export_plugin.cpp | 10 ++++++---- platform/android/export/export_plugin.h | 2 ++ platform/iphone/export/export.cpp | 8 ++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp index 9eaad034f8e6..a4e24d124285 100644 --- a/platform/android/export/export_plugin.cpp +++ b/platform/android/export/export_plugin.cpp @@ -228,6 +228,7 @@ static const char *AAB_ASSETS_DIRECTORY = "res://android/build/assetPacks/instal static const int DEFAULT_MIN_SDK_VERSION = 19; // Should match the value in 'platform/android/java/app/config.gradle#minSdk' static const int DEFAULT_TARGET_SDK_VERSION = 32; // Should match the value in 'platform/android/java/app/config.gradle#targetSdk' +#ifndef ANDROID_ENABLED void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { EditorExportPlatformAndroid *ea = (EditorExportPlatformAndroid *)ud; @@ -259,7 +260,6 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { } } -#ifndef ANDROID_ENABLED // Check for devices updates String adb = get_adb_path(); if (FileAccess::exists(adb)) { @@ -373,7 +373,6 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { ea->device_lock.unlock(); } -#endif uint64_t sleep = 300'000; uint64_t wait = 3'000'000; @@ -386,7 +385,6 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { } } -#ifndef ANDROID_ENABLED if (EditorSettings::get_singleton()->get("export/android/shutdown_adb_on_exit")) { String adb = get_adb_path(); if (!FileAccess::exists(adb)) { @@ -397,8 +395,8 @@ void EditorExportPlatformAndroid::_check_for_changes_poll_thread(void *ud) { args.push_back("kill-server"); OS::get_singleton()->execute(adb, args, true); } -#endif } +#endif String EditorExportPlatformAndroid::get_project_name(const String &p_name) const { String aname; @@ -3438,10 +3436,14 @@ EditorExportPlatformAndroid::EditorExportPlatformAndroid() { devices_changed.set(); plugins_changed.set(); +#ifndef ANDROID_ENABLED check_for_changes_thread.start(_check_for_changes_poll_thread, this); +#endif } EditorExportPlatformAndroid::~EditorExportPlatformAndroid() { +#ifndef ANDROID_ENABLED quit_request.set(); check_for_changes_thread.wait_to_finish(); +#endif } diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h index 8898cf695520..22a56db948d5 100644 --- a/platform/android/export/export_plugin.h +++ b/platform/android/export/export_plugin.h @@ -98,10 +98,12 @@ class EditorExportPlatformAndroid : public EditorExportPlatform { Vector<Device> devices; SafeFlag devices_changed; Mutex device_lock; +#ifndef ANDROID_ENABLED Thread check_for_changes_thread; SafeFlag quit_request; static void _check_for_changes_poll_thread(void *ud); +#endif String get_project_name(const String &p_name) const; diff --git a/platform/iphone/export/export.cpp b/platform/iphone/export/export.cpp index 4a12233709ae..52ff17ec54d1 100644 --- a/platform/iphone/export/export.cpp +++ b/platform/iphone/export/export.cpp @@ -57,8 +57,10 @@ class EditorExportPlatformIOS : public EditorExportPlatform { // Plugins SafeFlag plugins_changed; +#ifndef ANDROID_ENABLED Thread check_for_changes_thread; SafeFlag quit_request; +#endif Mutex plugins_lock; Vector<PluginConfigIOS> plugins; @@ -142,6 +144,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { return true; } +#ifndef ANDROID_ENABLED static void _check_for_changes_poll_thread(void *ud) { EditorExportPlatformIOS *ea = (EditorExportPlatformIOS *)ud; @@ -177,6 +180,7 @@ class EditorExportPlatformIOS : public EditorExportPlatform { } } } +#endif protected: virtual void get_preset_features(const Ref<EditorExportPreset> &p_preset, List<String> *r_features); @@ -2159,12 +2163,16 @@ EditorExportPlatformIOS::EditorExportPlatformIOS() { plugins_changed.set(); +#ifndef ANDROID_ENABLED check_for_changes_thread.start(_check_for_changes_poll_thread, this); +#endif } EditorExportPlatformIOS::~EditorExportPlatformIOS() { +#ifndef ANDROID_ENABLED quit_request.set(); check_for_changes_thread.wait_to_finish(); +#endif } void register_iphone_exporter() {