diff options
Diffstat (limited to 'platform/android/os_android.cpp')
-rw-r--r-- | platform/android/os_android.cpp | 71 |
1 files changed, 62 insertions, 9 deletions
diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index c040d8c4c6..82e7fdb320 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -39,6 +39,8 @@ #include "net_socket_android.h" #include "core/config/project_settings.h" +#include "core/extension/gdextension_manager.h" +#include "core/io/xml_parser.h" #include "drivers/unix/dir_access_unix.h" #include "drivers/unix/file_access_unix.h" #include "main/main.h" @@ -58,10 +60,10 @@ String _remove_symlink(const String &dir) { // Change directory to the external data directory. chdir(dir.utf8().get_data()); // Get the actual directory without the potential symlink. - char dir_name_wihout_symlink[2048]; - getcwd(dir_name_wihout_symlink, 2048); + char dir_name_without_symlink[2048]; + getcwd(dir_name_without_symlink, 2048); // Convert back to a String. - String dir_without_symlink(dir_name_wihout_symlink); + String dir_without_symlink(dir_name_without_symlink); // Restore original current directory. chdir(current_dir_name); return dir_without_symlink; @@ -160,13 +162,41 @@ Vector<String> OS_Android::get_granted_permissions() const { return godot_java->get_granted_permissions(); } -Error OS_Android::open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { +Error OS_Android::open_dynamic_library(const String &p_path, void *&p_library_handle, bool p_also_set_library_path, String *r_resolved_path) { String path = p_path; + bool so_file_exists = true; if (!FileAccess::exists(path)) { path = p_path.get_file(); + so_file_exists = false; } 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 + // directory. + uint64_t so_modified_time = FileAccess::get_modified_time(p_path); + String dynamic_library_path = get_dynamic_libraries_path().path_join(String::num_uint64(so_modified_time)); + String internal_path = dynamic_library_path.path_join(p_path.get_file()); + + bool internal_so_file_exists = FileAccess::exists(internal_path); + if (!internal_so_file_exists) { + Ref<DirAccess> da_ref = DirAccess::create_for_path(p_path); + if (da_ref.is_valid()) { + Error create_dir_result = da_ref->make_dir_recursive(dynamic_library_path); + if (create_dir_result == OK || create_dir_result == ERR_ALREADY_EXISTS) { + internal_so_file_exists = da_ref->copy(path, internal_path) == OK; + } + } + } + + if (internal_so_file_exists) { + p_library_handle = dlopen(internal_path.utf8().get_data(), RTLD_NOW); + if (p_library_handle) { + path = internal_path; + } + } + } + ERR_FAIL_NULL_V_MSG(p_library_handle, ERR_CANT_OPEN, vformat("Can't open dynamic library: %s. Error: %s.", p_path, dlerror())); if (r_resolved_path != nullptr) { @@ -294,15 +324,21 @@ void OS_Android::main_loop_end() { void OS_Android::main_loop_focusout() { DisplayServerAndroid::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_OUT); + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT); + } audio_driver_android.set_pause(true); } void OS_Android::main_loop_focusin() { DisplayServerAndroid::get_singleton()->send_window_event(DisplayServer::WINDOW_EVENT_FOCUS_IN); + if (OS::get_singleton()->get_main_loop()) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN); + } audio_driver_android.set_pause(false); } -Error OS_Android::shell_open(String p_uri) { +Error OS_Android::shell_open(const String &p_uri) { return godot_io_java->open_uri(p_uri); } @@ -584,6 +620,10 @@ String OS_Android::get_user_data_dir() const { return "."; } +String OS_Android::get_dynamic_libraries_path() const { + return get_cache_path().path_join("dynamic_libraries"); +} + String OS_Android::get_cache_path() const { if (!cache_dir_cache.is_empty()) { return cache_dir_cache; @@ -674,15 +714,15 @@ String OS_Android::get_config_path() const { return get_user_data_dir().path_join("config"); } -void OS_Android::benchmark_begin_measure(const String &p_what) { +void OS_Android::benchmark_begin_measure(const String &p_context, const String &p_what) { #ifdef TOOLS_ENABLED - godot_java->begin_benchmark_measure(p_what); + godot_java->begin_benchmark_measure(p_context, p_what); #endif } -void OS_Android::benchmark_end_measure(const String &p_what) { +void OS_Android::benchmark_end_measure(const String &p_context, const String &p_what) { #ifdef TOOLS_ENABLED - godot_java->end_benchmark_measure(p_what); + godot_java->end_benchmark_measure(p_context, p_what); #endif } @@ -715,6 +755,11 @@ bool OS_Android::_check_internal_feature_support(const String &p_feature) { return true; } #endif + + if (godot_java->has_feature(p_feature)) { + return true; + } + return false; } @@ -791,5 +836,13 @@ Error OS_Android::setup_remote_filesystem(const String &p_server_host, int p_por return err; } +void OS_Android::load_platform_gdextensions() const { + Vector<String> extension_list_config_file = godot_java->get_gdextension_list_config_file(); + for (String config_file_path : extension_list_config_file) { + GDExtensionManager::LoadStatus err = GDExtensionManager::get_singleton()->load_extension(config_file_path); + ERR_CONTINUE_MSG(err == GDExtensionManager::LOAD_STATUS_FAILED, "Error loading platform extension: " + config_file_path); + } +} + OS_Android::~OS_Android() { } |