summaryrefslogtreecommitdiffstats
path: root/platform/android
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android')
-rw-r--r--platform/android/SCsub28
-rw-r--r--platform/android/detect.py2
-rw-r--r--platform/android/display_server_android.cpp121
-rw-r--r--platform/android/display_server_android.h12
-rw-r--r--platform/android/export/export.cpp1
-rw-r--r--platform/android/export/export_plugin.cpp59
-rw-r--r--platform/android/export/export_plugin.h1
-rw-r--r--platform/android/file_access_android.cpp81
-rw-r--r--platform/android/file_access_android.h6
-rw-r--r--platform/android/file_access_filesystem_jandroid.cpp51
-rw-r--r--platform/android/file_access_filesystem_jandroid.h6
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/Godot.kt16
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java26
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java44
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotIO.java8
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java5
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java44
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java16
-rw-r--r--platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt4
-rw-r--r--platform/android/java_godot_wrapper.cpp2
-rw-r--r--platform/android/java_godot_wrapper.h2
-rw-r--r--platform/android/os_android.cpp2
-rw-r--r--platform/android/vulkan_context_android.cpp12
-rw-r--r--platform/android/vulkan_context_android.h7
24 files changed, 426 insertions, 130 deletions
diff --git a/platform/android/SCsub b/platform/android/SCsub
index dfc921cc54..97262cf148 100644
--- a/platform/android/SCsub
+++ b/platform/android/SCsub
@@ -1,5 +1,7 @@
#!/usr/bin/env python
+import subprocess
+
Import("env")
android_files = [
@@ -77,3 +79,29 @@ if lib_arch_dir != "":
str(env["ANDROID_NDK_ROOT"]) + "/sources/cxx-stl/llvm-libc++/libs/" + lib_arch_dir + "/libc++_shared.so"
)
env_android.Command(out_dir + "/libc++_shared.so", stl_lib_path, Copy("$TARGET", "$SOURCE"))
+
+ def generate_apk(target, source, env):
+ if env["target"] != "editor" and env["dev_build"]:
+ subprocess.run(
+ [
+ "./gradlew",
+ "generateDevTemplate",
+ "--quiet",
+ ],
+ cwd="platform/android/java",
+ )
+ else:
+ # Android editor with `dev_build=yes` is handled by the `generateGodotEditor` task.
+ subprocess.run(
+ [
+ "./gradlew",
+ "generateGodotEditor" if env["target"] == "editor" else "generateGodotTemplates",
+ "--quiet",
+ ],
+ cwd="platform/android/java",
+ )
+
+ if env["generate_apk"]:
+ generate_apk_command = env_android.Command("generate_apk", [], generate_apk)
+ command = env_android.AlwaysBuild(generate_apk_command)
+ env_android.Depends(command, [lib])
diff --git a/platform/android/detect.py b/platform/android/detect.py
index a417ef454b..b396e5eb2d 100644
--- a/platform/android/detect.py
+++ b/platform/android/detect.py
@@ -200,7 +200,7 @@ def configure(env: "Environment"):
env.Append(LIBS=["OpenSLES", "EGL", "android", "log", "z", "dl"])
if env["vulkan"]:
- env.Append(CPPDEFINES=["VULKAN_ENABLED"])
+ env.Append(CPPDEFINES=["VULKAN_ENABLED", "RD_ENABLED"])
if not env["use_volk"]:
env.Append(LIBS=["vulkan"])
diff --git a/platform/android/display_server_android.cpp b/platform/android/display_server_android.cpp
index dd5ab46bd7..340823baac 100644
--- a/platform/android/display_server_android.cpp
+++ b/platform/android/display_server_android.cpp
@@ -37,11 +37,13 @@
#include "core/config/project_settings.h"
+#if defined(RD_ENABLED)
+#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#include "servers/rendering/rendering_device.h"
+
#if defined(VULKAN_ENABLED)
#include "vulkan_context_android.h"
-
-#include "drivers/vulkan/rendering_device_vulkan.h"
-#include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
+#endif
#endif
#ifdef GLES3_ENABLED
@@ -515,20 +517,30 @@ void DisplayServerAndroid::register_android_driver() {
}
void DisplayServerAndroid::reset_window() {
-#if defined(VULKAN_ENABLED)
- if (rendering_driver == "vulkan") {
- ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();
- ERR_FAIL_NULL(native_window);
-
- ERR_FAIL_NULL(context_vulkan);
- VSyncMode last_vsync_mode = context_vulkan->get_vsync_mode(MAIN_WINDOW_ID);
- context_vulkan->window_destroy(MAIN_WINDOW_ID);
+#if defined(RD_ENABLED)
+ if (context_rd) {
+ VSyncMode last_vsync_mode = context_rd->get_vsync_mode(MAIN_WINDOW_ID);
+ context_rd->window_destroy(MAIN_WINDOW_ID);
Size2i display_size = OS_Android::get_singleton()->get_display_size();
- if (context_vulkan->window_create(native_window, last_vsync_mode, display_size.width, display_size.height) != OK) {
- memdelete(context_vulkan);
- context_vulkan = nullptr;
- ERR_FAIL_MSG("Failed to reset Vulkan window.");
+
+ union {
+#ifdef VULKAN_ENABLED
+ VulkanContextAndroid::WindowPlatformData vulkan;
+#endif
+ } wpd;
+#ifdef VULKAN_ENABLED
+ if (rendering_driver == "vulkan") {
+ ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();
+ ERR_FAIL_NULL(native_window);
+ wpd.vulkan.window = native_window;
+ }
+#endif
+
+ if (context_rd->window_create(MAIN_WINDOW_ID, last_vsync_mode, display_size.width, display_size.height, &wpd) != OK) {
+ memdelete(context_rd);
+ context_rd = nullptr;
+ ERR_FAIL_MSG(vformat("Failed to reset %s window.", context_rd->get_api_name()));
}
}
#endif
@@ -551,30 +563,46 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
}
#endif
-#if defined(VULKAN_ENABLED)
- context_vulkan = nullptr;
- rendering_device_vulkan = nullptr;
+#if defined(RD_ENABLED)
+ context_rd = nullptr;
+ rendering_device = nullptr;
+#if defined(VULKAN_ENABLED)
if (rendering_driver == "vulkan") {
- ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();
- ERR_FAIL_NULL(native_window);
-
- context_vulkan = memnew(VulkanContextAndroid);
- if (context_vulkan->initialize() != OK) {
- memdelete(context_vulkan);
- context_vulkan = nullptr;
- ERR_FAIL_MSG("Failed to initialize Vulkan context");
+ context_rd = memnew(VulkanContextAndroid);
+ }
+#endif
+
+ if (context_rd) {
+ if (context_rd->initialize() != OK) {
+ memdelete(context_rd);
+ context_rd = nullptr;
+ ERR_FAIL_MSG(vformat("Failed to initialize %s context", context_rd->get_api_name()));
}
Size2i display_size = OS_Android::get_singleton()->get_display_size();
- if (context_vulkan->window_create(native_window, p_vsync_mode, display_size.width, display_size.height) != OK) {
- memdelete(context_vulkan);
- context_vulkan = nullptr;
- ERR_FAIL_MSG("Failed to create Vulkan window.");
+
+ union {
+#ifdef VULKAN_ENABLED
+ VulkanContextAndroid::WindowPlatformData vulkan;
+#endif
+ } wpd;
+#ifdef VULKAN_ENABLED
+ if (rendering_driver == "vulkan") {
+ ANativeWindow *native_window = OS_Android::get_singleton()->get_native_window();
+ ERR_FAIL_NULL(native_window);
+ wpd.vulkan.window = native_window;
+ }
+#endif
+
+ if (context_rd->window_create(MAIN_WINDOW_ID, p_vsync_mode, display_size.width, display_size.height, &wpd) != OK) {
+ memdelete(context_rd);
+ context_rd = nullptr;
+ ERR_FAIL_MSG(vformat("Failed to create %s window.", context_rd->get_api_name()));
}
- rendering_device_vulkan = memnew(RenderingDeviceVulkan);
- rendering_device_vulkan->initialize(context_vulkan);
+ rendering_device = memnew(RenderingDevice);
+ rendering_device->initialize(context_rd);
RendererCompositorRD::make_current();
}
@@ -587,16 +615,13 @@ DisplayServerAndroid::DisplayServerAndroid(const String &p_rendering_driver, Dis
}
DisplayServerAndroid::~DisplayServerAndroid() {
-#if defined(VULKAN_ENABLED)
- if (rendering_driver == "vulkan") {
- if (rendering_device_vulkan) {
- rendering_device_vulkan->finalize();
- memdelete(rendering_device_vulkan);
- }
-
- if (context_vulkan) {
- memdelete(context_vulkan);
- }
+#if defined(RD_ENABLED)
+ if (rendering_device) {
+ rendering_device->finalize();
+ memdelete(rendering_device);
+ }
+ if (context_rd) {
+ memdelete(context_rd);
}
#endif
}
@@ -687,17 +712,17 @@ void DisplayServerAndroid::cursor_set_custom_image(const Ref<Resource> &p_cursor
}
void DisplayServerAndroid::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) {
-#if defined(VULKAN_ENABLED)
- if (context_vulkan) {
- context_vulkan->set_vsync_mode(p_window, p_vsync_mode);
+#if defined(RD_ENABLED)
+ if (context_rd) {
+ context_rd->set_vsync_mode(p_window, p_vsync_mode);
}
#endif
}
DisplayServer::VSyncMode DisplayServerAndroid::window_get_vsync_mode(WindowID p_window) const {
-#if defined(VULKAN_ENABLED)
- if (context_vulkan) {
- return context_vulkan->get_vsync_mode(p_window);
+#if defined(RD_ENABLED)
+ if (context_rd) {
+ return context_rd->get_vsync_mode(p_window);
}
#endif
return DisplayServer::VSYNC_ENABLED;
diff --git a/platform/android/display_server_android.h b/platform/android/display_server_android.h
index 54912212dc..80af4f00c1 100644
--- a/platform/android/display_server_android.h
+++ b/platform/android/display_server_android.h
@@ -33,9 +33,9 @@
#include "servers/display_server.h"
-#if defined(VULKAN_ENABLED)
-class VulkanContextAndroid;
-class RenderingDeviceVulkan;
+#if defined(RD_ENABLED)
+class ApiContextRD;
+class RenderingDevice;
#endif
class DisplayServerAndroid : public DisplayServer {
@@ -72,9 +72,9 @@ class DisplayServerAndroid : public DisplayServer {
CursorShape cursor_shape = CursorShape::CURSOR_ARROW;
-#if defined(VULKAN_ENABLED)
- VulkanContextAndroid *context_vulkan = nullptr;
- RenderingDeviceVulkan *rendering_device_vulkan = nullptr;
+#if defined(RD_ENABLED)
+ ApiContextRD *context_rd = nullptr;
+ RenderingDevice *rendering_device = nullptr;
#endif
ObjectID window_attached_instance_id;
diff --git a/platform/android/export/export.cpp b/platform/android/export/export.cpp
index ee1ec2790d..e276048d40 100644
--- a/platform/android/export/export.cpp
+++ b/platform/android/export/export.cpp
@@ -48,6 +48,7 @@ void register_android_exporter() {
EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks"));
EDITOR_DEF("export/android/debug_keystore_user", "androiddebugkey");
EDITOR_DEF("export/android/debug_keystore_pass", "android");
+ EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/android/debug_keystore_pass", PROPERTY_HINT_PASSWORD));
EDITOR_DEF("export/android/force_system_user", false);
EDITOR_DEF("export/android/shutdown_adb_on_exit", true);
diff --git a/platform/android/export/export_plugin.cpp b/platform/android/export/export_plugin.cpp
index 10d54e8d97..762e5a8323 100644
--- a/platform/android/export/export_plugin.cpp
+++ b/platform/android/export/export_plugin.cpp
@@ -1111,7 +1111,7 @@ void EditorExportPlatformAndroid::_fix_manifest(const Ref<EditorExportPreset> &p
}
for (int i = 0; i < feature_names.size(); i++) {
- String feature_name = feature_names[i];
+ const String &feature_name = feature_names[i];
bool feature_required = feature_required_list[i];
int feature_version = feature_versions[i];
bool has_version_attribute = feature_version != -1;
@@ -1823,10 +1823,10 @@ void EditorExportPlatformAndroid::get_export_options(List<ExportOption> *r_optio
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/debug_password", PROPERTY_HINT_PASSWORD, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release", PROPERTY_HINT_GLOBAL_FILE, "*.keystore,*.jks", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_user", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
- r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
+ r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "keystore/release_password", PROPERTY_HINT_PASSWORD, "", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SECRET), ""));
r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "version/code", PROPERTY_HINT_RANGE, "1,4096,1,or_greater"), 1));
r_options->push_back(ExportOption(PropertyInfo(Variant::STRING, "version/name", PROPERTY_HINT_PLACEHOLDER_TEXT, "Leave empty to use project version"), ""));
@@ -2229,6 +2229,54 @@ String EditorExportPlatformAndroid::get_apksigner_path(int p_target_sdk, bool p_
return apksigner_path;
}
+static bool has_valid_keystore_credentials(String &r_error_str, const String &p_keystore, const String &p_username, const String &p_password, const String &p_type) {
+ String output;
+ List<String> args;
+ args.push_back("-list");
+ args.push_back("-keystore");
+ args.push_back(p_keystore);
+ args.push_back("-storepass");
+ args.push_back(p_password);
+ args.push_back("-alias");
+ args.push_back(p_username);
+ Error error = OS::get_singleton()->execute("keytool", args, &output, nullptr, true);
+ String keytool_error = "keytool error:";
+ bool valid = output.substr(0, keytool_error.length()) != keytool_error;
+
+ if (error != OK) {
+ r_error_str = TTR("Error: There was a problem validating the keystore username and password");
+ return false;
+ }
+ if (!valid) {
+ r_error_str = TTR(p_type + " Username and/or Password is invalid for the given " + p_type + " Keystore");
+ return false;
+ }
+ r_error_str = "";
+ return true;
+}
+
+bool EditorExportPlatformAndroid::has_valid_username_and_password(const Ref<EditorExportPreset> &p_preset, String &r_error) {
+ String dk = p_preset->get_or_env("keystore/debug", ENV_ANDROID_KEYSTORE_DEBUG_PATH);
+ String dk_user = p_preset->get_or_env("keystore/debug_user", ENV_ANDROID_KEYSTORE_DEBUG_USER);
+ String dk_password = p_preset->get_or_env("keystore/debug_password", ENV_ANDROID_KEYSTORE_DEBUG_PASS);
+ String rk = p_preset->get_or_env("keystore/release", ENV_ANDROID_KEYSTORE_RELEASE_PATH);
+ String rk_user = p_preset->get_or_env("keystore/release_user", ENV_ANDROID_KEYSTORE_RELEASE_USER);
+ String rk_password = p_preset->get_or_env("keystore/release_password", ENV_ANDROID_KEYSTORE_RELEASE_PASS);
+
+ bool valid = true;
+ if (!dk.is_empty() && !dk_user.is_empty() && !dk_password.is_empty()) {
+ String err = "";
+ valid = has_valid_keystore_credentials(err, dk, dk_user, dk_password, "Debug");
+ r_error += err;
+ }
+ if (!rk.is_empty() && !rk_user.is_empty() && !rk_password.is_empty()) {
+ String err = "";
+ valid = has_valid_keystore_credentials(err, rk, rk_user, rk_password, "Release");
+ r_error += err;
+ }
+ return valid;
+}
+
bool EditorExportPlatformAndroid::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
String err;
bool valid = false;
@@ -2842,6 +2890,11 @@ Error EditorExportPlatformAndroid::export_project_helper(const Ref<EditorExportP
add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR("Unsupported export format!"));
return ERR_UNCONFIGURED;
}
+ String err_string;
+ if (!has_valid_username_and_password(p_preset, err_string)) {
+ add_message(EXPORT_MESSAGE_ERROR, TTR("Export"), TTR(err_string));
+ return ERR_UNCONFIGURED;
+ }
if (use_gradle_build) {
print_verbose("Starting gradle build...");
diff --git a/platform/android/export/export_plugin.h b/platform/android/export/export_plugin.h
index a2d0417c5d..5b585581b0 100644
--- a/platform/android/export/export_plugin.h
+++ b/platform/android/export/export_plugin.h
@@ -228,6 +228,7 @@ public:
virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
virtual bool has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const override;
+ static bool has_valid_username_and_password(const Ref<EditorExportPreset> &p_preset, String &r_error);
virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
diff --git a/platform/android/file_access_android.cpp b/platform/android/file_access_android.cpp
index 1249f2219f..f56eda4694 100644
--- a/platform/android/file_access_android.cpp
+++ b/platform/android/file_access_android.cpp
@@ -121,6 +121,75 @@ uint8_t FileAccessAndroid::get_8() const {
return byte;
}
+uint16_t FileAccessAndroid::get_16() const {
+ if (pos >= len) {
+ eof = true;
+ return 0;
+ }
+
+ uint16_t bytes = 0;
+ int r = AAsset_read(asset, &bytes, 2);
+
+ if (r >= 0) {
+ pos += r;
+ if (pos >= len) {
+ eof = true;
+ }
+ }
+
+ if (big_endian) {
+ bytes = BSWAP16(bytes);
+ }
+
+ return bytes;
+}
+
+uint32_t FileAccessAndroid::get_32() const {
+ if (pos >= len) {
+ eof = true;
+ return 0;
+ }
+
+ uint32_t bytes = 0;
+ int r = AAsset_read(asset, &bytes, 4);
+
+ if (r >= 0) {
+ pos += r;
+ if (pos >= len) {
+ eof = true;
+ }
+ }
+
+ if (big_endian) {
+ bytes = BSWAP32(bytes);
+ }
+
+ return bytes;
+}
+
+uint64_t FileAccessAndroid::get_64() const {
+ if (pos >= len) {
+ eof = true;
+ return 0;
+ }
+
+ uint64_t bytes = 0;
+ int r = AAsset_read(asset, &bytes, 8);
+
+ if (r >= 0) {
+ pos += r;
+ if (pos >= len) {
+ eof = true;
+ }
+ }
+
+ if (big_endian) {
+ bytes = BSWAP64(bytes);
+ }
+
+ return bytes;
+}
+
uint64_t FileAccessAndroid::get_buffer(uint8_t *p_dst, uint64_t p_length) const {
ERR_FAIL_COND_V(!p_dst && p_length > 0, -1);
@@ -151,6 +220,18 @@ void FileAccessAndroid::store_8(uint8_t p_dest) {
ERR_FAIL();
}
+void FileAccessAndroid::store_16(uint16_t p_dest) {
+ ERR_FAIL();
+}
+
+void FileAccessAndroid::store_32(uint32_t p_dest) {
+ ERR_FAIL();
+}
+
+void FileAccessAndroid::store_64(uint64_t p_dest) {
+ ERR_FAIL();
+}
+
bool FileAccessAndroid::file_exists(const String &p_path) {
String path = fix_path(p_path).simplify_path();
if (path.begins_with("/")) {
diff --git a/platform/android/file_access_android.h b/platform/android/file_access_android.h
index 3aa4ca98fc..ec613b6687 100644
--- a/platform/android/file_access_android.h
+++ b/platform/android/file_access_android.h
@@ -66,12 +66,18 @@ public:
virtual bool eof_reached() const override; // reading passed EOF
virtual uint8_t get_8() const override; // get a byte
+ virtual uint16_t get_16() const override;
+ virtual uint32_t get_32() const override;
+ virtual uint64_t get_64() const override;
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
virtual Error get_error() const override; // get last error
virtual void flush() override;
virtual void store_8(uint8_t p_dest) override; // store a byte
+ virtual void store_16(uint16_t p_dest) override;
+ virtual void store_32(uint32_t p_dest) override;
+ virtual void store_64(uint64_t p_dest) override;
virtual bool file_exists(const String &p_path) override; // return true if a file exists
diff --git a/platform/android/file_access_filesystem_jandroid.cpp b/platform/android/file_access_filesystem_jandroid.cpp
index beea73fd61..46d9728632 100644
--- a/platform/android/file_access_filesystem_jandroid.cpp
+++ b/platform/android/file_access_filesystem_jandroid.cpp
@@ -181,6 +181,36 @@ uint8_t FileAccessFilesystemJAndroid::get_8() const {
return byte;
}
+uint16_t FileAccessFilesystemJAndroid::get_16() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ uint16_t bytes = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&bytes), 2);
+ if (big_endian) {
+ bytes = BSWAP16(bytes);
+ }
+ return bytes;
+}
+
+uint32_t FileAccessFilesystemJAndroid::get_32() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ uint32_t bytes = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&bytes), 4);
+ if (big_endian) {
+ bytes = BSWAP32(bytes);
+ }
+ return bytes;
+}
+
+uint64_t FileAccessFilesystemJAndroid::get_64() const {
+ ERR_FAIL_COND_V_MSG(!is_open(), 0, "File must be opened before use.");
+ uint64_t bytes = 0;
+ get_buffer(reinterpret_cast<uint8_t *>(&bytes), 8);
+ if (big_endian) {
+ bytes = BSWAP64(bytes);
+ }
+ return bytes;
+}
+
String FileAccessFilesystemJAndroid::get_line() const {
ERR_FAIL_COND_V_MSG(!is_open(), String(), "File must be opened before use.");
@@ -250,6 +280,27 @@ void FileAccessFilesystemJAndroid::store_8(uint8_t p_dest) {
store_buffer(&p_dest, 1);
}
+void FileAccessFilesystemJAndroid::store_16(uint16_t p_dest) {
+ if (big_endian) {
+ p_dest = BSWAP16(p_dest);
+ }
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 2);
+}
+
+void FileAccessFilesystemJAndroid::store_32(uint32_t p_dest) {
+ if (big_endian) {
+ p_dest = BSWAP32(p_dest);
+ }
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 4);
+}
+
+void FileAccessFilesystemJAndroid::store_64(uint64_t p_dest) {
+ if (big_endian) {
+ p_dest = BSWAP64(p_dest);
+ }
+ store_buffer(reinterpret_cast<uint8_t *>(&p_dest), 8);
+}
+
void FileAccessFilesystemJAndroid::store_buffer(const uint8_t *p_src, uint64_t p_length) {
if (_file_write) {
ERR_FAIL_COND_MSG(!is_open(), "File must be opened before use.");
diff --git a/platform/android/file_access_filesystem_jandroid.h b/platform/android/file_access_filesystem_jandroid.h
index 0c3f8d7259..f33aa64ebe 100644
--- a/platform/android/file_access_filesystem_jandroid.h
+++ b/platform/android/file_access_filesystem_jandroid.h
@@ -77,6 +77,9 @@ public:
virtual bool eof_reached() const override; ///< reading passed EOF
virtual uint8_t get_8() const override; ///< get a byte
+ virtual uint16_t get_16() const override;
+ virtual uint32_t get_32() const override;
+ virtual uint64_t get_64() const override;
virtual String get_line() const override; ///< get a line
virtual uint64_t get_buffer(uint8_t *p_dst, uint64_t p_length) const override;
@@ -84,6 +87,9 @@ public:
virtual void flush() override;
virtual void store_8(uint8_t p_dest) override; ///< store a byte
+ virtual void store_16(uint16_t p_dest) override;
+ virtual void store_32(uint32_t p_dest) override;
+ virtual void store_64(uint64_t p_dest) override;
virtual void store_buffer(const uint8_t *p_src, uint64_t p_length) override;
virtual bool file_exists(const String &p_path) override; ///< return true if a file exists
diff --git a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
index 217e7a2b60..da86e67c7d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/Godot.kt
@@ -484,6 +484,14 @@ class Godot(private val context: Context) : SensorEventListener {
return containerLayout
}
+ fun onStart(host: GodotHost) {
+ if (host != primaryHost) {
+ return
+ }
+
+ renderView!!.onActivityStarted()
+ }
+
fun onResume(host: GodotHost) {
if (host != primaryHost) {
return
@@ -528,6 +536,14 @@ class Godot(private val context: Context) : SensorEventListener {
}
}
+ fun onStop(host: GodotHost) {
+ if (host != primaryHost) {
+ return
+ }
+
+ renderView!!.onActivityStopped()
+ }
+
fun onDestroy(primaryHost: GodotHost) {
if (this.primaryHost != primaryHost) {
return
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java b/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java
index f1c029e7a1..643c9a658e 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotFragment.java
@@ -271,6 +271,32 @@ public class GodotFragment extends Fragment implements IDownloaderClient, GodotH
}
@Override
+ public void onStop() {
+ super.onStop();
+ if (!godot.isInitialized()) {
+ if (null != mDownloaderClientStub) {
+ mDownloaderClientStub.disconnect(getActivity());
+ }
+ return;
+ }
+
+ godot.onStop(this);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (!godot.isInitialized()) {
+ if (null != mDownloaderClientStub) {
+ mDownloaderClientStub.connect(getActivity());
+ }
+ return;
+ }
+
+ godot.onStart(this);
+ }
+
+ @Override
public void onResume() {
super.onResume();
if (!godot.isInitialized()) {
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
index 52350c12a6..81043ce782 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotGLRenderView.java
@@ -114,12 +114,30 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
@Override
public void onActivityPaused() {
- onPause();
+ queueEvent(() -> {
+ GodotLib.focusout();
+ // Pause the renderer
+ godotRenderer.onActivityPaused();
+ });
+ }
+
+ @Override
+ public void onActivityStopped() {
+ pauseGLThread();
}
@Override
public void onActivityResumed() {
- onResume();
+ queueEvent(() -> {
+ // Resume the renderer
+ godotRenderer.onActivityResumed();
+ GodotLib.focusin();
+ });
+ }
+
+ @Override
+ public void onActivityStarted() {
+ resumeGLThread();
}
@Override
@@ -283,26 +301,4 @@ public class GodotGLRenderView extends GLSurfaceView implements GodotRenderView
/* Set the renderer responsible for frame rendering */
setRenderer(godotRenderer);
}
-
- @Override
- public void onResume() {
- super.onResume();
-
- queueEvent(() -> {
- // Resume the renderer
- godotRenderer.onActivityResumed();
- GodotLib.focusin();
- });
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- queueEvent(() -> {
- GodotLib.focusout();
- // Pause the renderer
- godotRenderer.onActivityPaused();
- });
- }
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
index edcd9c4d1f..4b51bd778d 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotIO.java
@@ -178,12 +178,10 @@ public class GodotIO {
}
public int[] getDisplaySafeArea() {
- DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
- Display display = activity.getWindowManager().getDefaultDisplay();
- Point size = new Point();
- display.getRealSize(size);
+ Rect rect = new Rect();
+ activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
- int[] result = { 0, 0, size.x, size.y };
+ int[] result = { rect.left, rect.top, rect.right, rect.bottom };
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowInsets insets = activity.getWindow().getDecorView().getRootWindowInsets();
DisplayCutout cutout = insets.getDisplayCutout();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
index ebf3a6b2fb..5b2f9f57c7 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotRenderView.java
@@ -47,8 +47,13 @@ public interface GodotRenderView {
void queueOnRenderThread(Runnable event);
void onActivityPaused();
+
+ void onActivityStopped();
+
void onActivityResumed();
+ void onActivityStarted();
+
void onBackPressed();
GodotInputHandler getInputHandler();
diff --git a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
index 48708152be..a1ee9bd6b4 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/GodotVulkanRenderView.java
@@ -92,12 +92,30 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
@Override
public void onActivityPaused() {
- onPause();
+ queueOnVkThread(() -> {
+ GodotLib.focusout();
+ // Pause the renderer
+ mRenderer.onVkPause();
+ });
+ }
+
+ @Override
+ public void onActivityStopped() {
+ pauseRenderThread();
+ }
+
+ @Override
+ public void onActivityStarted() {
+ resumeRenderThread();
}
@Override
public void onActivityResumed() {
- onResume();
+ queueOnVkThread(() -> {
+ // Resume the renderer
+ mRenderer.onVkResume();
+ GodotLib.focusin();
+ });
}
@Override
@@ -211,26 +229,4 @@ public class GodotVulkanRenderView extends VkSurfaceView implements GodotRenderV
}
return super.onResolvePointerIcon(me, pointerIndex);
}
-
- @Override
- public void onResume() {
- super.onResume();
-
- queueOnVkThread(() -> {
- // Resume the renderer
- mRenderer.onVkResume();
- GodotLib.focusin();
- });
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- queueOnVkThread(() -> {
- GodotLib.focusout();
- // Pause the renderer
- mRenderer.onVkPause();
- });
- }
}
diff --git a/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java b/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
index 56397bb2c2..ef97aaeab9 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
+++ b/platform/android/java/lib/src/org/godotengine/godot/gl/GLSurfaceView.java
@@ -122,8 +122,8 @@ import javax.microedition.khronos.opengles.GL10;
* <p>
* <h3>Activity Life-cycle</h3>
* A GLSurfaceView must be notified when to pause and resume rendering. GLSurfaceView clients
- * are required to call {@link #onPause()} when the activity stops and
- * {@link #onResume()} when the activity starts. These calls allow GLSurfaceView to
+ * are required to call {@link #pauseGLThread()} when the activity stops and
+ * {@link #resumeGLThread()} when the activity starts. These calls allow GLSurfaceView to
* pause and resume the rendering thread, and also allow GLSurfaceView to release and recreate
* the OpenGL display.
* <p>
@@ -339,8 +339,8 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
* setRenderer is called:
* <ul>
* <li>{@link #getRenderMode()}
- * <li>{@link #onPause()}
- * <li>{@link #onResume()}
+ * <li>{@link #pauseGLThread()}
+ * <li>{@link #resumeGLThread()}
* <li>{@link #queueEvent(Runnable)}
* <li>{@link #requestRender()}
* <li>{@link #setRenderMode(int)}
@@ -568,6 +568,7 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
}
+ // -- GODOT start --
/**
* Pause the rendering thread, optionally tearing down the EGL context
* depending upon the value of {@link #setPreserveEGLContextOnPause(boolean)}.
@@ -578,22 +579,23 @@ public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback
*
* Must not be called before a renderer has been set.
*/
- public void onPause() {
+ protected final void pauseGLThread() {
mGLThread.onPause();
}
/**
* Resumes the rendering thread, re-creating the OpenGL context if necessary. It
- * is the counterpart to {@link #onPause()}.
+ * is the counterpart to {@link #pauseGLThread()}.
*
* This method should typically be called in
* {@link android.app.Activity#onStart Activity.onStart}.
*
* Must not be called before a renderer has been set.
*/
- public void onResume() {
+ protected final void resumeGLThread() {
mGLThread.onResume();
}
+ // -- GODOT end --
/**
* Queue a runnable to be run on the GL rendering thread. This can be used
diff --git a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
index 3828004198..791b425444 100644
--- a/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
+++ b/platform/android/java/lib/src/org/godotengine/godot/vulkan/VkSurfaceView.kt
@@ -99,7 +99,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf
*
* Must not be called before a [VkRenderer] has been set.
*/
- open fun onResume() {
+ protected fun resumeRenderThread() {
vkThread.onResume()
}
@@ -108,7 +108,7 @@ open internal class VkSurfaceView(context: Context) : SurfaceView(context), Surf
*
* Must not be called before a [VkRenderer] has been set.
*/
- open fun onPause() {
+ protected fun pauseRenderThread() {
vkThread.onPause()
}
diff --git a/platform/android/java_godot_wrapper.cpp b/platform/android/java_godot_wrapper.cpp
index 4e401e633e..3c950bb1b1 100644
--- a/platform/android/java_godot_wrapper.cpp
+++ b/platform/android/java_godot_wrapper.cpp
@@ -334,7 +334,7 @@ void GodotJavaWrapper::vibrate(int p_duration_ms) {
}
}
-int GodotJavaWrapper::create_new_godot_instance(List<String> args) {
+int GodotJavaWrapper::create_new_godot_instance(const List<String> &args) {
if (_create_new_godot_instance) {
JNIEnv *env = get_jni_env();
ERR_FAIL_NULL_V(env, 0);
diff --git a/platform/android/java_godot_wrapper.h b/platform/android/java_godot_wrapper.h
index 52043c6027..93998021a9 100644
--- a/platform/android/java_godot_wrapper.h
+++ b/platform/android/java_godot_wrapper.h
@@ -104,7 +104,7 @@ public:
void init_input_devices();
void vibrate(int p_duration_ms);
String get_input_fallback_mapping();
- int create_new_godot_instance(List<String> args);
+ int create_new_godot_instance(const List<String> &args);
void begin_benchmark_measure(const String &p_context, const String &p_label);
void end_benchmark_measure(const String &p_context, const String &p_label);
void dump_benchmark(const String &benchmark_file);
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp
index 0d82bec75d..35d4222152 100644
--- a/platform/android/os_android.cpp
+++ b/platform/android/os_android.cpp
@@ -170,6 +170,8 @@ Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_han
so_file_exists = false;
}
+ ERR_FAIL_COND_V(!FileAccess::exists(path), ERR_FILE_NOT_FOUND);
+
p_library_handle = dlopen(path.utf8().get_data(), RTLD_NOW);
if (!p_library_handle && so_file_exists) {
// The library may be on the sdcard and thus inaccessible. Try to copy it to the internal
diff --git a/platform/android/vulkan_context_android.cpp b/platform/android/vulkan_context_android.cpp
index 01e6d14438..4f9140bf3e 100644
--- a/platform/android/vulkan_context_android.cpp
+++ b/platform/android/vulkan_context_android.cpp
@@ -42,14 +42,14 @@ const char *VulkanContextAndroid::_get_platform_surface_extension() const {
return VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
}
-Error VulkanContextAndroid::window_create(ANativeWindow *p_window, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height) {
- VkAndroidSurfaceCreateInfoKHR createInfo;
+Error VulkanContextAndroid::window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) {
+ const WindowPlatformData *wpd = (const WindowPlatformData *)p_platform_data;
+
+ VkAndroidSurfaceCreateInfoKHR createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
- createInfo.pNext = nullptr;
- createInfo.flags = 0;
- createInfo.window = p_window;
+ createInfo.window = wpd->window;
- VkSurfaceKHR surface;
+ VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult err = vkCreateAndroidSurfaceKHR(get_instance(), &createInfo, nullptr, &surface);
if (err != VK_SUCCESS) {
ERR_FAIL_V_MSG(ERR_CANT_CREATE, "vkCreateAndroidSurfaceKHR failed with error " + itos(err));
diff --git a/platform/android/vulkan_context_android.h b/platform/android/vulkan_context_android.h
index f253149ef6..3cee3feb86 100644
--- a/platform/android/vulkan_context_android.h
+++ b/platform/android/vulkan_context_android.h
@@ -38,10 +38,13 @@
struct ANativeWindow;
class VulkanContextAndroid : public VulkanContext {
- virtual const char *_get_platform_surface_extension() const override;
+ virtual const char *_get_platform_surface_extension() const override final;
public:
- Error window_create(ANativeWindow *p_window, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height);
+ struct WindowPlatformData {
+ ANativeWindow *window;
+ };
+ virtual Error window_create(DisplayServer::WindowID p_window_id, DisplayServer::VSyncMode p_vsync_mode, int p_width, int p_height, const void *p_platform_data) override final;
VulkanContextAndroid() = default;
~VulkanContextAndroid() override = default;