Merge pull request #12920 from t895/jni-common
android: Move JNI setup and helpers to common
This commit is contained in:
		| @@ -2,14 +2,8 @@ | ||||
| # SPDX-License-Identifier: GPL-3.0-or-later | ||||
|  | ||||
| add_library(yuzu-android SHARED | ||||
|     android_common/android_common.cpp | ||||
|     android_common/android_common.h | ||||
|     applets/software_keyboard.cpp | ||||
|     applets/software_keyboard.h | ||||
|     emu_window/emu_window.cpp | ||||
|     emu_window/emu_window.h | ||||
|     id_cache.cpp | ||||
|     id_cache.h | ||||
|     native.cpp | ||||
|     native.h | ||||
|     native_config.cpp | ||||
|   | ||||
| @@ -3,6 +3,7 @@ | ||||
|  | ||||
| #include <android/native_window_jni.h> | ||||
|  | ||||
| #include "common/android/id_cache.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "input_common/drivers/touch_screen.h" | ||||
| #include "input_common/drivers/virtual_amiibo.h" | ||||
| @@ -60,7 +61,8 @@ void EmuWindow_Android::OnRemoveNfcTag() { | ||||
|  | ||||
| void EmuWindow_Android::OnFrameDisplayed() { | ||||
|     if (!m_first_frame) { | ||||
|         EmulationSession::GetInstance().OnEmulationStarted(); | ||||
|         Common::Android::RunJNIOnFiber<void>( | ||||
|             [&](JNIEnv* env) { EmulationSession::GetInstance().OnEmulationStarted(); }); | ||||
|         m_first_frame = true; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,13 +1,12 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "common/android/android_common.h" | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/fs_filesystem.h" | ||||
| #include "core/file_sys/patch_manager.h" | ||||
| #include "core/loader/loader.h" | ||||
| #include "core/loader/nro.h" | ||||
| #include "jni.h" | ||||
| #include "jni/android_common/android_common.h" | ||||
| #include "native.h" | ||||
|  | ||||
| struct RomMetadata { | ||||
| @@ -79,7 +78,7 @@ extern "C" { | ||||
| jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj, | ||||
|                                                                jstring jpath) { | ||||
|     const auto file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile( | ||||
|         GetJString(env, jpath), FileSys::OpenMode::Read); | ||||
|         Common::Android::GetJString(env, jpath), FileSys::OpenMode::Read); | ||||
|     if (!file) { | ||||
|         return false; | ||||
|     } | ||||
| @@ -104,27 +103,31 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobj | ||||
|  | ||||
| jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj, | ||||
|                                                             jstring jpath) { | ||||
|     return ToJString(env, GetRomMetadata(GetJString(env, jpath)).title); | ||||
|     return Common::Android::ToJString( | ||||
|         env, GetRomMetadata(Common::Android::GetJString(env, jpath)).title); | ||||
| } | ||||
|  | ||||
| jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getProgramId(JNIEnv* env, jobject obj, | ||||
|                                                                 jstring jpath) { | ||||
|     return ToJString(env, std::to_string(GetRomMetadata(GetJString(env, jpath)).programId)); | ||||
|     return Common::Android::ToJString( | ||||
|         env, std::to_string(GetRomMetadata(Common::Android::GetJString(env, jpath)).programId)); | ||||
| } | ||||
|  | ||||
| jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, jobject obj, | ||||
|                                                                 jstring jpath) { | ||||
|     return ToJString(env, GetRomMetadata(GetJString(env, jpath)).developer); | ||||
|     return Common::Android::ToJString( | ||||
|         env, GetRomMetadata(Common::Android::GetJString(env, jpath)).developer); | ||||
| } | ||||
|  | ||||
| jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj, | ||||
|                                                               jstring jpath, jboolean jreload) { | ||||
|     return ToJString(env, GetRomMetadata(GetJString(env, jpath), jreload).version); | ||||
|     return Common::Android::ToJString( | ||||
|         env, GetRomMetadata(Common::Android::GetJString(env, jpath), jreload).version); | ||||
| } | ||||
|  | ||||
| jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj, | ||||
|                                                               jstring jpath) { | ||||
|     auto icon_data = GetRomMetadata(GetJString(env, jpath)).icon; | ||||
|     auto icon_data = GetRomMetadata(Common::Android::GetJString(env, jpath)).icon; | ||||
|     jbyteArray icon = env->NewByteArray(static_cast<jsize>(icon_data.size())); | ||||
|     env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon), | ||||
|                             reinterpret_cast<jbyte*>(icon_data.data())); | ||||
| @@ -133,7 +136,8 @@ jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobje | ||||
|  | ||||
| jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, jobject obj, | ||||
|                                                                   jstring jpath) { | ||||
|     return static_cast<jboolean>(GetRomMetadata(GetJString(env, jpath)).isHomebrew); | ||||
|     return static_cast<jboolean>( | ||||
|         GetRomMetadata(Common::Android::GetJString(env, jpath)).isHomebrew); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_utils_GameMetadata_resetMetadata(JNIEnv* env, jobject obj) { | ||||
|   | ||||
| @@ -20,6 +20,8 @@ | ||||
| #include <frontend_common/content_manager.h> | ||||
| #include <jni.h> | ||||
|  | ||||
| #include "common/android/android_common.h" | ||||
| #include "common/android/id_cache.h" | ||||
| #include "common/detached_tasks.h" | ||||
| #include "common/dynamic_library.h" | ||||
| #include "common/fs/path_util.h" | ||||
| @@ -57,8 +59,6 @@ | ||||
| #include "hid_core/frontend/emulated_controller.h" | ||||
| #include "hid_core/hid_core.h" | ||||
| #include "hid_core/hid_types.h" | ||||
| #include "jni/android_common/android_common.h" | ||||
| #include "jni/id_cache.h" | ||||
| #include "jni/native.h" | ||||
| #include "video_core/renderer_base.h" | ||||
| #include "video_core/renderer_vulkan/renderer_vulkan.h" | ||||
| @@ -228,7 +228,7 @@ Core::SystemResultStatus EmulationSession::InitializeEmulation(const std::string | ||||
|         std::make_unique<EmuWindow_Android>(&m_input_subsystem, m_native_window, m_vulkan_library); | ||||
|  | ||||
|     // Initialize system. | ||||
|     jauto android_keyboard = std::make_unique<SoftwareKeyboard::AndroidKeyboard>(); | ||||
|     jauto android_keyboard = std::make_unique<Common::Android::SoftwareKeyboard::AndroidKeyboard>(); | ||||
|     m_software_keyboard = android_keyboard.get(); | ||||
|     m_system.SetShuttingDown(false); | ||||
|     m_system.ApplySettings(); | ||||
| @@ -411,37 +411,39 @@ void EmulationSession::OnGamepadDisconnectEvent([[maybe_unused]] int index) { | ||||
|     controller->Disconnect(); | ||||
| } | ||||
|  | ||||
| SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() { | ||||
| Common::Android::SoftwareKeyboard::AndroidKeyboard* EmulationSession::SoftwareKeyboard() { | ||||
|     return m_software_keyboard; | ||||
| } | ||||
|  | ||||
| void EmulationSession::LoadDiskCacheProgress(VideoCore::LoadCallbackStage stage, int progress, | ||||
|                                              int max) { | ||||
|     JNIEnv* env = IDCache::GetEnvForThread(); | ||||
|     env->CallStaticVoidMethod(IDCache::GetDiskCacheProgressClass(), | ||||
|                               IDCache::GetDiskCacheLoadProgress(), static_cast<jint>(stage), | ||||
|     JNIEnv* env = Common::Android::GetEnvForThread(); | ||||
|     env->CallStaticVoidMethod(Common::Android::GetDiskCacheProgressClass(), | ||||
|                               Common::Android::GetDiskCacheLoadProgress(), static_cast<jint>(stage), | ||||
|                               static_cast<jint>(progress), static_cast<jint>(max)); | ||||
| } | ||||
|  | ||||
| void EmulationSession::OnEmulationStarted() { | ||||
|     JNIEnv* env = IDCache::GetEnvForThread(); | ||||
|     env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnEmulationStarted()); | ||||
|     JNIEnv* env = Common::Android::GetEnvForThread(); | ||||
|     env->CallStaticVoidMethod(Common::Android::GetNativeLibraryClass(), | ||||
|                               Common::Android::GetOnEmulationStarted()); | ||||
| } | ||||
|  | ||||
| void EmulationSession::OnEmulationStopped(Core::SystemResultStatus result) { | ||||
|     JNIEnv* env = IDCache::GetEnvForThread(); | ||||
|     env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnEmulationStopped(), | ||||
|                               static_cast<jint>(result)); | ||||
|     JNIEnv* env = Common::Android::GetEnvForThread(); | ||||
|     env->CallStaticVoidMethod(Common::Android::GetNativeLibraryClass(), | ||||
|                               Common::Android::GetOnEmulationStopped(), static_cast<jint>(result)); | ||||
| } | ||||
|  | ||||
| void EmulationSession::ChangeProgram(std::size_t program_index) { | ||||
|     JNIEnv* env = IDCache::GetEnvForThread(); | ||||
|     env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), IDCache::GetOnProgramChanged(), | ||||
|     JNIEnv* env = Common::Android::GetEnvForThread(); | ||||
|     env->CallStaticVoidMethod(Common::Android::GetNativeLibraryClass(), | ||||
|                               Common::Android::GetOnProgramChanged(), | ||||
|                               static_cast<jint>(program_index)); | ||||
| } | ||||
|  | ||||
| u64 EmulationSession::GetProgramId(JNIEnv* env, jstring jprogramId) { | ||||
|     auto program_id_string = GetJString(env, jprogramId); | ||||
|     auto program_id_string = Common::Android::GetJString(env, jprogramId); | ||||
|     try { | ||||
|         return std::stoull(program_id_string); | ||||
|     } catch (...) { | ||||
| @@ -491,7 +493,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_surfaceDestroyed(JNIEnv* env, jobject | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, jobject instance, | ||||
|                                                            [[maybe_unused]] jstring j_directory) { | ||||
|     Common::FS::SetAppDirectory(GetJString(env, j_directory)); | ||||
|     Common::FS::SetAppDirectory(Common::Android::GetJString(env, j_directory)); | ||||
| } | ||||
|  | ||||
| int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, | ||||
| @@ -501,21 +503,22 @@ int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject | ||||
|         jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); | ||||
|     const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { | ||||
|         auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, | ||||
|                                                    ToJDouble(env, max), ToJDouble(env, progress)); | ||||
|         return GetJBoolean(env, jwasCancelled); | ||||
|                                                    Common::Android::ToJDouble(env, max), | ||||
|                                                    Common::Android::ToJDouble(env, progress)); | ||||
|         return Common::Android::GetJBoolean(env, jwasCancelled); | ||||
|     }; | ||||
|  | ||||
|     return static_cast<int>( | ||||
|         ContentManager::InstallNSP(EmulationSession::GetInstance().System(), | ||||
|                                    *EmulationSession::GetInstance().System().GetFilesystem(), | ||||
|                                    GetJString(env, j_file), callback)); | ||||
|                                    Common::Android::GetJString(env, j_file), callback)); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj, | ||||
|                                                                       jstring jprogramId, | ||||
|                                                                       jstring jupdatePath) { | ||||
|     u64 program_id = EmulationSession::GetProgramId(env, jprogramId); | ||||
|     std::string updatePath = GetJString(env, jupdatePath); | ||||
|     std::string updatePath = Common::Android::GetJString(env, jupdatePath); | ||||
|     std::shared_ptr<FileSys::NSP> nsp = std::make_shared<FileSys::NSP>( | ||||
|         EmulationSession::GetInstance().System().GetFilesystem()->OpenFile( | ||||
|             updatePath, FileSys::OpenMode::Read)); | ||||
| @@ -538,8 +541,10 @@ void JNICALL Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeGpuDriver(JNIEnv* e | ||||
|                                                                        jstring custom_driver_name, | ||||
|                                                                        jstring file_redirect_dir) { | ||||
|     EmulationSession::GetInstance().InitializeGpuDriver( | ||||
|         GetJString(env, hook_lib_dir), GetJString(env, custom_driver_dir), | ||||
|         GetJString(env, custom_driver_name), GetJString(env, file_redirect_dir)); | ||||
|         Common::Android::GetJString(env, hook_lib_dir), | ||||
|         Common::Android::GetJString(env, custom_driver_dir), | ||||
|         Common::Android::GetJString(env, custom_driver_name), | ||||
|         Common::Android::GetJString(env, file_redirect_dir)); | ||||
| } | ||||
|  | ||||
| [[maybe_unused]] static bool CheckKgslPresent() { | ||||
| @@ -566,7 +571,7 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo( | ||||
|     JNIEnv* env, jobject j_obj, jobject j_surf, jstring j_hook_lib_dir) { | ||||
|     const char* file_redirect_dir_{}; | ||||
|     int featureFlags{}; | ||||
|     std::string hook_lib_dir = GetJString(env, j_hook_lib_dir); | ||||
|     std::string hook_lib_dir = Common::Android::GetJString(env, j_hook_lib_dir); | ||||
|     auto handle = adrenotools_open_libvulkan(RTLD_NOW, featureFlags, nullptr, hook_lib_dir.c_str(), | ||||
|                                              nullptr, nullptr, file_redirect_dir_, nullptr); | ||||
|     auto driver_library = std::make_shared<Common::DynamicLibrary>(handle); | ||||
| @@ -587,9 +592,10 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_GpuDriverHelper_getSystemDriverInfo( | ||||
|         fmt::format("{}.{}.{}", VK_API_VERSION_MAJOR(driver_version), | ||||
|                     VK_API_VERSION_MINOR(driver_version), VK_API_VERSION_PATCH(driver_version)); | ||||
|  | ||||
|     jobjectArray j_driver_info = | ||||
|         env->NewObjectArray(2, IDCache::GetStringClass(), ToJString(env, version_string)); | ||||
|     env->SetObjectArrayElement(j_driver_info, 1, ToJString(env, device.GetDriverName())); | ||||
|     jobjectArray j_driver_info = env->NewObjectArray( | ||||
|         2, Common::Android::GetStringClass(), Common::Android::ToJString(env, version_string)); | ||||
|     env->SetObjectArrayElement(j_driver_info, 1, | ||||
|                                Common::Android::ToJString(env, device.GetDriverName())); | ||||
|     return j_driver_info; | ||||
| } | ||||
|  | ||||
| @@ -742,15 +748,15 @@ jdoubleArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPerfStats(JNIEnv* env, jcl | ||||
|  | ||||
| jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getCpuBackend(JNIEnv* env, jclass clazz) { | ||||
|     if (Settings::IsNceEnabled()) { | ||||
|         return ToJString(env, "NCE"); | ||||
|         return Common::Android::ToJString(env, "NCE"); | ||||
|     } | ||||
|  | ||||
|     return ToJString(env, "JIT"); | ||||
|     return Common::Android::ToJString(env, "JIT"); | ||||
| } | ||||
|  | ||||
| jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getGpuDriver(JNIEnv* env, jobject jobj) { | ||||
|     return ToJString(env, | ||||
|                      EmulationSession::GetInstance().System().GPU().Renderer().GetDeviceVendor()); | ||||
|     return Common::Android::ToJString( | ||||
|         env, EmulationSession::GetInstance().System().GPU().Renderer().GetDeviceVendor()); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_applySettings(JNIEnv* env, jobject jobj) { | ||||
| @@ -764,13 +770,14 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logSettings(JNIEnv* env, jobject jobj | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_run(JNIEnv* env, jobject jobj, jstring j_path, | ||||
|                                                jint j_program_index, | ||||
|                                                jboolean j_frontend_initiated) { | ||||
|     const std::string path = GetJString(env, j_path); | ||||
|     const std::string path = Common::Android::GetJString(env, j_path); | ||||
|  | ||||
|     const Core::SystemResultStatus result{ | ||||
|         RunEmulation(path, j_program_index, j_frontend_initiated)}; | ||||
|     if (result != Core::SystemResultStatus::Success) { | ||||
|         env->CallStaticVoidMethod(IDCache::GetNativeLibraryClass(), | ||||
|                                   IDCache::GetExitEmulationActivity(), static_cast<int>(result)); | ||||
|         env->CallStaticVoidMethod(Common::Android::GetNativeLibraryClass(), | ||||
|                                   Common::Android::GetExitEmulationActivity(), | ||||
|                                   static_cast<int>(result)); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -781,7 +788,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_logDeviceInfo(JNIEnv* env, jclass cla | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_submitInlineKeyboardText(JNIEnv* env, jclass clazz, | ||||
|                                                                     jstring j_text) { | ||||
|     const std::u16string input = Common::UTF8ToUTF16(GetJString(env, j_text)); | ||||
|     const std::u16string input = Common::UTF8ToUTF16(Common::Android::GetJString(env, j_text)); | ||||
|     EmulationSession::GetInstance().SoftwareKeyboard()->SubmitInlineKeyboardText(input); | ||||
| } | ||||
|  | ||||
| @@ -815,16 +822,16 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getAppletLaunchPath(JNIEnv* env, j | ||||
|     auto bis_system = | ||||
|         EmulationSession::GetInstance().System().GetFileSystemController().GetSystemNANDContents(); | ||||
|     if (!bis_system) { | ||||
|         return ToJString(env, ""); | ||||
|         return Common::Android::ToJString(env, ""); | ||||
|     } | ||||
|  | ||||
|     auto applet_nca = | ||||
|         bis_system->GetEntry(static_cast<u64>(jid), FileSys::ContentRecordType::Program); | ||||
|     if (!applet_nca) { | ||||
|         return ToJString(env, ""); | ||||
|         return Common::Android::ToJString(env, ""); | ||||
|     } | ||||
|  | ||||
|     return ToJString(env, applet_nca->GetFullPath()); | ||||
|     return Common::Android::ToJString(env, applet_nca->GetFullPath()); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_setCurrentAppletId(JNIEnv* env, jclass clazz, | ||||
| @@ -857,7 +864,7 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_isFirmwareAvailable(JNIEnv* env, | ||||
| jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env, jobject jobj, | ||||
|                                                                      jstring jpath, | ||||
|                                                                      jstring jprogramId) { | ||||
|     const auto path = GetJString(env, jpath); | ||||
|     const auto path = Common::Android::GetJString(env, jpath); | ||||
|     const auto vFile = | ||||
|         Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path); | ||||
|     if (vFile == nullptr) { | ||||
| @@ -875,14 +882,15 @@ jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env | ||||
|  | ||||
|     auto patches = pm.GetPatches(update_raw); | ||||
|     jobjectArray jpatchArray = | ||||
|         env->NewObjectArray(patches.size(), IDCache::GetPatchClass(), nullptr); | ||||
|         env->NewObjectArray(patches.size(), Common::Android::GetPatchClass(), nullptr); | ||||
|     int i = 0; | ||||
|     for (const auto& patch : patches) { | ||||
|         jobject jpatch = env->NewObject( | ||||
|             IDCache::GetPatchClass(), IDCache::GetPatchConstructor(), patch.enabled, | ||||
|             ToJString(env, patch.name), ToJString(env, patch.version), | ||||
|             static_cast<jint>(patch.type), ToJString(env, std::to_string(patch.program_id)), | ||||
|             ToJString(env, std::to_string(patch.title_id))); | ||||
|             Common::Android::GetPatchClass(), Common::Android::GetPatchConstructor(), patch.enabled, | ||||
|             Common::Android::ToJString(env, patch.name), | ||||
|             Common::Android::ToJString(env, patch.version), static_cast<jint>(patch.type), | ||||
|             Common::Android::ToJString(env, std::to_string(patch.program_id)), | ||||
|             Common::Android::ToJString(env, std::to_string(patch.title_id))); | ||||
|         env->SetObjectArrayElement(jpatchArray, i, jpatch); | ||||
|         ++i; | ||||
|     } | ||||
| @@ -906,7 +914,7 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj, | ||||
|                                                      jstring jname) { | ||||
|     auto program_id = EmulationSession::GetProgramId(env, jprogramId); | ||||
|     ContentManager::RemoveMod(EmulationSession::GetInstance().System().GetFileSystemController(), | ||||
|                               program_id, GetJString(env, jname)); | ||||
|                               program_id, Common::Android::GetJString(env, jname)); | ||||
| } | ||||
|  | ||||
| jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyInstalledContents(JNIEnv* env, | ||||
| @@ -917,17 +925,18 @@ jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyInstalledContents(JNIEn | ||||
|         jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); | ||||
|     const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { | ||||
|         auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, | ||||
|                                                    ToJDouble(env, max), ToJDouble(env, progress)); | ||||
|         return GetJBoolean(env, jwasCancelled); | ||||
|                                                    Common::Android::ToJDouble(env, max), | ||||
|                                                    Common::Android::ToJDouble(env, progress)); | ||||
|         return Common::Android::GetJBoolean(env, jwasCancelled); | ||||
|     }; | ||||
|  | ||||
|     auto& session = EmulationSession::GetInstance(); | ||||
|     std::vector<std::string> result = ContentManager::VerifyInstalledContents( | ||||
|         session.System(), *session.GetContentProvider(), callback); | ||||
|     jobjectArray jresult = | ||||
|         env->NewObjectArray(result.size(), IDCache::GetStringClass(), ToJString(env, "")); | ||||
|     jobjectArray jresult = env->NewObjectArray(result.size(), Common::Android::GetStringClass(), | ||||
|                                                Common::Android::ToJString(env, "")); | ||||
|     for (size_t i = 0; i < result.size(); ++i) { | ||||
|         env->SetObjectArrayElement(jresult, i, ToJString(env, result[i])); | ||||
|         env->SetObjectArrayElement(jresult, i, Common::Android::ToJString(env, result[i])); | ||||
|     } | ||||
|     return jresult; | ||||
| } | ||||
| @@ -939,19 +948,20 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyGameContents(JNIEnv* env, jobje | ||||
|         jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); | ||||
|     const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) { | ||||
|         auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod, | ||||
|                                                    ToJDouble(env, max), ToJDouble(env, progress)); | ||||
|         return GetJBoolean(env, jwasCancelled); | ||||
|                                                    Common::Android::ToJDouble(env, max), | ||||
|                                                    Common::Android::ToJDouble(env, progress)); | ||||
|         return Common::Android::GetJBoolean(env, jwasCancelled); | ||||
|     }; | ||||
|     auto& session = EmulationSession::GetInstance(); | ||||
|     return static_cast<jint>( | ||||
|         ContentManager::VerifyGameContents(session.System(), GetJString(env, jpath), callback)); | ||||
|     return static_cast<jint>(ContentManager::VerifyGameContents( | ||||
|         session.System(), Common::Android::GetJString(env, jpath), callback)); | ||||
| } | ||||
|  | ||||
| jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj, | ||||
|                                                           jstring jprogramId) { | ||||
|     auto program_id = EmulationSession::GetProgramId(env, jprogramId); | ||||
|     if (program_id == 0) { | ||||
|         return ToJString(env, ""); | ||||
|         return Common::Android::ToJString(env, ""); | ||||
|     } | ||||
|  | ||||
|     auto& system = EmulationSession::GetInstance().System(); | ||||
| @@ -968,7 +978,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject j | ||||
|     const auto user_save_data_path = FileSys::SaveDataFactory::GetFullPath( | ||||
|         {}, vfsNandDir, FileSys::SaveDataSpaceId::NandUser, FileSys::SaveDataType::SaveData, | ||||
|         program_id, user_id->AsU128(), 0); | ||||
|     return ToJString(env, user_save_data_path); | ||||
|     return Common::Android::ToJString(env, user_save_data_path); | ||||
| } | ||||
|  | ||||
| jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getDefaultProfileSaveDataRoot(JNIEnv* env, | ||||
| @@ -981,12 +991,13 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getDefaultProfileSaveDataRoot(JNIE | ||||
|  | ||||
|     const auto user_save_data_root = | ||||
|         FileSys::SaveDataFactory::GetUserGameSaveDataRoot(user_id->AsU128(), jfuture); | ||||
|     return ToJString(env, user_save_data_root); | ||||
|     return Common::Android::ToJString(env, user_save_data_root); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_addFileToFilesystemProvider(JNIEnv* env, jobject jobj, | ||||
|                                                                        jstring jpath) { | ||||
|     EmulationSession::GetInstance().ConfigureFilesystemProvider(GetJString(env, jpath)); | ||||
|     EmulationSession::GetInstance().ConfigureFilesystemProvider( | ||||
|         Common::Android::GetJString(env, jpath)); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_NativeLibrary_clearFilesystemProvider(JNIEnv* env, jobject jobj) { | ||||
|   | ||||
| @@ -2,13 +2,13 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include <android/native_window_jni.h> | ||||
| #include "common/android/applets/software_keyboard.h" | ||||
| #include "common/detached_tasks.h" | ||||
| #include "core/core.h" | ||||
| #include "core/file_sys/registered_cache.h" | ||||
| #include "core/hle/service/acc/profile_manager.h" | ||||
| #include "core/perf_stats.h" | ||||
| #include "frontend_common/content_manager.h" | ||||
| #include "jni/applets/software_keyboard.h" | ||||
| #include "jni/emu_window/emu_window.h" | ||||
| #include "video_core/rasterizer_interface.h" | ||||
|  | ||||
| @@ -54,7 +54,7 @@ public: | ||||
|     void SetDeviceType([[maybe_unused]] int index, int type); | ||||
|     void OnGamepadConnectEvent([[maybe_unused]] int index); | ||||
|     void OnGamepadDisconnectEvent([[maybe_unused]] int index); | ||||
|     SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard(); | ||||
|     Common::Android::SoftwareKeyboard::AndroidKeyboard* SoftwareKeyboard(); | ||||
|  | ||||
|     static void OnEmulationStarted(); | ||||
|  | ||||
| @@ -79,7 +79,7 @@ private: | ||||
|     Core::SystemResultStatus m_load_result{Core::SystemResultStatus::ErrorNotInitialized}; | ||||
|     std::atomic<bool> m_is_running = false; | ||||
|     std::atomic<bool> m_is_paused = false; | ||||
|     SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{}; | ||||
|     Common::Android::SoftwareKeyboard::AndroidKeyboard* m_software_keyboard{}; | ||||
|     std::unique_ptr<FileSys::ManualContentProvider> m_manual_provider; | ||||
|     int m_applet_id{1}; | ||||
|  | ||||
|   | ||||
| @@ -8,11 +8,11 @@ | ||||
|  | ||||
| #include "android_config.h" | ||||
| #include "android_settings.h" | ||||
| #include "common/android/android_common.h" | ||||
| #include "common/android/id_cache.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/settings.h" | ||||
| #include "frontend_common/config.h" | ||||
| #include "jni/android_common/android_common.h" | ||||
| #include "jni/id_cache.h" | ||||
| #include "native.h" | ||||
|  | ||||
| std::unique_ptr<AndroidConfig> global_config; | ||||
| @@ -20,7 +20,7 @@ std::unique_ptr<AndroidConfig> per_game_config; | ||||
|  | ||||
| template <typename T> | ||||
| Settings::Setting<T>* getSetting(JNIEnv* env, jstring jkey) { | ||||
|     auto key = GetJString(env, jkey); | ||||
|     auto key = Common::Android::GetJString(env, jkey); | ||||
|     auto basic_setting = Settings::values.linkage.by_key[key]; | ||||
|     if (basic_setting != 0) { | ||||
|         return static_cast<Settings::Setting<T>*>(basic_setting); | ||||
| @@ -55,7 +55,7 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializePerGameConfig(JNIEnv* | ||||
|                                                                         jstring jprogramId, | ||||
|                                                                         jstring jfileName) { | ||||
|     auto program_id = EmulationSession::GetProgramId(env, jprogramId); | ||||
|     auto file_name = GetJString(env, jfileName); | ||||
|     auto file_name = Common::Android::GetJString(env, jfileName); | ||||
|     const auto config_file_name = program_id == 0 ? file_name : fmt::format("{:016X}", program_id); | ||||
|     per_game_config = | ||||
|         std::make_unique<AndroidConfig>(config_file_name, Config::ConfigType::PerGameConfig); | ||||
| @@ -186,9 +186,9 @@ jstring Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getString(JNIEnv* env, jobjec | ||||
|                                                              jboolean needGlobal) { | ||||
|     auto setting = getSetting<std::string>(env, jkey); | ||||
|     if (setting == nullptr) { | ||||
|         return ToJString(env, ""); | ||||
|         return Common::Android::ToJString(env, ""); | ||||
|     } | ||||
|     return ToJString(env, setting->GetValue(static_cast<bool>(needGlobal))); | ||||
|     return Common::Android::ToJString(env, setting->GetValue(static_cast<bool>(needGlobal))); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setString(JNIEnv* env, jobject obj, jstring jkey, | ||||
| @@ -198,7 +198,7 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setString(JNIEnv* env, jobject o | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     setting->SetValue(GetJString(env, value)); | ||||
|     setting->SetValue(Common::Android::GetJString(env, value)); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getIsRuntimeModifiable(JNIEnv* env, jobject obj, | ||||
| @@ -214,13 +214,13 @@ jstring Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getPairedSettingKey(JNIEnv* e | ||||
|                                                                        jstring jkey) { | ||||
|     auto setting = getSetting<std::string>(env, jkey); | ||||
|     if (setting == nullptr) { | ||||
|         return ToJString(env, ""); | ||||
|         return Common::Android::ToJString(env, ""); | ||||
|     } | ||||
|     if (setting->PairedSetting() == nullptr) { | ||||
|         return ToJString(env, ""); | ||||
|         return Common::Android::ToJString(env, ""); | ||||
|     } | ||||
|  | ||||
|     return ToJString(env, setting->PairedSetting()->GetLabel()); | ||||
|     return Common::Android::ToJString(env, setting->PairedSetting()->GetLabel()); | ||||
| } | ||||
|  | ||||
| jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getIsSwitchable(JNIEnv* env, jobject obj, | ||||
| @@ -262,21 +262,21 @@ jstring Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getDefaultToString(JNIEnv* en | ||||
|                                                                       jstring jkey) { | ||||
|     auto setting = getSetting<std::string>(env, jkey); | ||||
|     if (setting != nullptr) { | ||||
|         return ToJString(env, setting->DefaultToString()); | ||||
|         return Common::Android::ToJString(env, setting->DefaultToString()); | ||||
|     } | ||||
|     return ToJString(env, ""); | ||||
|     return Common::Android::ToJString(env, ""); | ||||
| } | ||||
|  | ||||
| jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getGameDirs(JNIEnv* env, jobject obj) { | ||||
|     jclass gameDirClass = IDCache::GetGameDirClass(); | ||||
|     jmethodID gameDirConstructor = IDCache::GetGameDirConstructor(); | ||||
|     jclass gameDirClass = Common::Android::GetGameDirClass(); | ||||
|     jmethodID gameDirConstructor = Common::Android::GetGameDirConstructor(); | ||||
|     jobjectArray jgameDirArray = | ||||
|         env->NewObjectArray(AndroidSettings::values.game_dirs.size(), gameDirClass, nullptr); | ||||
|     for (size_t i = 0; i < AndroidSettings::values.game_dirs.size(); ++i) { | ||||
|         jobject jgameDir = | ||||
|             env->NewObject(gameDirClass, gameDirConstructor, | ||||
|                            ToJString(env, AndroidSettings::values.game_dirs[i].path), | ||||
|                            static_cast<jboolean>(AndroidSettings::values.game_dirs[i].deep_scan)); | ||||
|         jobject jgameDir = env->NewObject( | ||||
|             gameDirClass, gameDirConstructor, | ||||
|             Common::Android::ToJString(env, AndroidSettings::values.game_dirs[i].path), | ||||
|             static_cast<jboolean>(AndroidSettings::values.game_dirs[i].deep_scan)); | ||||
|         env->SetObjectArrayElement(jgameDirArray, i, jgameDir); | ||||
|     } | ||||
|     return jgameDirArray; | ||||
| @@ -292,14 +292,14 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setGameDirs(JNIEnv* env, jobject | ||||
|     } | ||||
|  | ||||
|     jobject dir = env->GetObjectArrayElement(gameDirs, 0); | ||||
|     jclass gameDirClass = IDCache::GetGameDirClass(); | ||||
|     jclass gameDirClass = Common::Android::GetGameDirClass(); | ||||
|     jfieldID uriStringField = env->GetFieldID(gameDirClass, "uriString", "Ljava/lang/String;"); | ||||
|     jfieldID deepScanBooleanField = env->GetFieldID(gameDirClass, "deepScan", "Z"); | ||||
|     for (int i = 0; i < size; ++i) { | ||||
|         dir = env->GetObjectArrayElement(gameDirs, i); | ||||
|         jstring juriString = static_cast<jstring>(env->GetObjectField(dir, uriStringField)); | ||||
|         jboolean jdeepScanBoolean = env->GetBooleanField(dir, deepScanBooleanField); | ||||
|         std::string uriString = GetJString(env, juriString); | ||||
|         std::string uriString = Common::Android::GetJString(env, juriString); | ||||
|         AndroidSettings::values.game_dirs.push_back( | ||||
|             AndroidSettings::GameDir{uriString, static_cast<bool>(jdeepScanBoolean)}); | ||||
|     } | ||||
| @@ -307,13 +307,13 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setGameDirs(JNIEnv* env, jobject | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_addGameDir(JNIEnv* env, jobject obj, | ||||
|                                                            jobject gameDir) { | ||||
|     jclass gameDirClass = IDCache::GetGameDirClass(); | ||||
|     jclass gameDirClass = Common::Android::GetGameDirClass(); | ||||
|     jfieldID uriStringField = env->GetFieldID(gameDirClass, "uriString", "Ljava/lang/String;"); | ||||
|     jfieldID deepScanBooleanField = env->GetFieldID(gameDirClass, "deepScan", "Z"); | ||||
|  | ||||
|     jstring juriString = static_cast<jstring>(env->GetObjectField(gameDir, uriStringField)); | ||||
|     jboolean jdeepScanBoolean = env->GetBooleanField(gameDir, deepScanBooleanField); | ||||
|     std::string uriString = GetJString(env, juriString); | ||||
|     std::string uriString = Common::Android::GetJString(env, juriString); | ||||
|     AndroidSettings::values.game_dirs.push_back( | ||||
|         AndroidSettings::GameDir{uriString, static_cast<bool>(jdeepScanBoolean)}); | ||||
| } | ||||
| @@ -323,9 +323,11 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getDisabledAddons(JNIEnv | ||||
|     auto program_id = EmulationSession::GetProgramId(env, jprogramId); | ||||
|     auto& disabledAddons = Settings::values.disabled_addons[program_id]; | ||||
|     jobjectArray jdisabledAddonsArray = | ||||
|         env->NewObjectArray(disabledAddons.size(), IDCache::GetStringClass(), ToJString(env, "")); | ||||
|         env->NewObjectArray(disabledAddons.size(), Common::Android::GetStringClass(), | ||||
|                             Common::Android::ToJString(env, "")); | ||||
|     for (size_t i = 0; i < disabledAddons.size(); ++i) { | ||||
|         env->SetObjectArrayElement(jdisabledAddonsArray, i, ToJString(env, disabledAddons[i])); | ||||
|         env->SetObjectArrayElement(jdisabledAddonsArray, i, | ||||
|                                    Common::Android::ToJString(env, disabledAddons[i])); | ||||
|     } | ||||
|     return jdisabledAddonsArray; | ||||
| } | ||||
| @@ -339,7 +341,7 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setDisabledAddons(JNIEnv* env, j | ||||
|     const int size = env->GetArrayLength(jdisabledAddons); | ||||
|     for (int i = 0; i < size; ++i) { | ||||
|         auto jaddon = static_cast<jstring>(env->GetObjectArrayElement(jdisabledAddons, i)); | ||||
|         disabled_addons.push_back(GetJString(env, jaddon)); | ||||
|         disabled_addons.push_back(Common::Android::GetJString(env, jaddon)); | ||||
|     } | ||||
|     Settings::values.disabled_addons[program_id] = disabled_addons; | ||||
| } | ||||
| @@ -348,26 +350,27 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getOverlayControlData(JN | ||||
|                                                                               jobject obj) { | ||||
|     jobjectArray joverlayControlDataArray = | ||||
|         env->NewObjectArray(AndroidSettings::values.overlay_control_data.size(), | ||||
|                             IDCache::GetOverlayControlDataClass(), nullptr); | ||||
|                             Common::Android::GetOverlayControlDataClass(), nullptr); | ||||
|     for (size_t i = 0; i < AndroidSettings::values.overlay_control_data.size(); ++i) { | ||||
|         const auto& control_data = AndroidSettings::values.overlay_control_data[i]; | ||||
|         jobject jlandscapePosition = | ||||
|             env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), | ||||
|                            ToJDouble(env, control_data.landscape_position.first), | ||||
|                            ToJDouble(env, control_data.landscape_position.second)); | ||||
|             env->NewObject(Common::Android::GetPairClass(), Common::Android::GetPairConstructor(), | ||||
|                            Common::Android::ToJDouble(env, control_data.landscape_position.first), | ||||
|                            Common::Android::ToJDouble(env, control_data.landscape_position.second)); | ||||
|         jobject jportraitPosition = | ||||
|             env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), | ||||
|                            ToJDouble(env, control_data.portrait_position.first), | ||||
|                            ToJDouble(env, control_data.portrait_position.second)); | ||||
|             env->NewObject(Common::Android::GetPairClass(), Common::Android::GetPairConstructor(), | ||||
|                            Common::Android::ToJDouble(env, control_data.portrait_position.first), | ||||
|                            Common::Android::ToJDouble(env, control_data.portrait_position.second)); | ||||
|         jobject jfoldablePosition = | ||||
|             env->NewObject(IDCache::GetPairClass(), IDCache::GetPairConstructor(), | ||||
|                            ToJDouble(env, control_data.foldable_position.first), | ||||
|                            ToJDouble(env, control_data.foldable_position.second)); | ||||
|             env->NewObject(Common::Android::GetPairClass(), Common::Android::GetPairConstructor(), | ||||
|                            Common::Android::ToJDouble(env, control_data.foldable_position.first), | ||||
|                            Common::Android::ToJDouble(env, control_data.foldable_position.second)); | ||||
|  | ||||
|         jobject jcontrolData = env->NewObject( | ||||
|             IDCache::GetOverlayControlDataClass(), IDCache::GetOverlayControlDataConstructor(), | ||||
|             ToJString(env, control_data.id), control_data.enabled, jlandscapePosition, | ||||
|             jportraitPosition, jfoldablePosition); | ||||
|         jobject jcontrolData = | ||||
|             env->NewObject(Common::Android::GetOverlayControlDataClass(), | ||||
|                            Common::Android::GetOverlayControlDataConstructor(), | ||||
|                            Common::Android::ToJString(env, control_data.id), control_data.enabled, | ||||
|                            jlandscapePosition, jportraitPosition, jfoldablePosition); | ||||
|         env->SetObjectArrayElement(joverlayControlDataArray, i, jcontrolData); | ||||
|     } | ||||
|     return joverlayControlDataArray; | ||||
| @@ -384,33 +387,41 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setOverlayControlData( | ||||
|  | ||||
|     for (int i = 0; i < size; ++i) { | ||||
|         jobject joverlayControlData = env->GetObjectArrayElement(joverlayControlDataArray, i); | ||||
|         jstring jidString = static_cast<jstring>( | ||||
|             env->GetObjectField(joverlayControlData, IDCache::GetOverlayControlDataIdField())); | ||||
|         jstring jidString = static_cast<jstring>(env->GetObjectField( | ||||
|             joverlayControlData, Common::Android::GetOverlayControlDataIdField())); | ||||
|         bool enabled = static_cast<bool>(env->GetBooleanField( | ||||
|             joverlayControlData, IDCache::GetOverlayControlDataEnabledField())); | ||||
|             joverlayControlData, Common::Android::GetOverlayControlDataEnabledField())); | ||||
|  | ||||
|         jobject jlandscapePosition = env->GetObjectField( | ||||
|             joverlayControlData, IDCache::GetOverlayControlDataLandscapePositionField()); | ||||
|             joverlayControlData, Common::Android::GetOverlayControlDataLandscapePositionField()); | ||||
|         std::pair<double, double> landscape_position = std::make_pair( | ||||
|             GetJDouble(env, env->GetObjectField(jlandscapePosition, IDCache::GetPairFirstField())), | ||||
|             GetJDouble(env, | ||||
|                        env->GetObjectField(jlandscapePosition, IDCache::GetPairSecondField()))); | ||||
|             Common::Android::GetJDouble( | ||||
|                 env, env->GetObjectField(jlandscapePosition, Common::Android::GetPairFirstField())), | ||||
|             Common::Android::GetJDouble( | ||||
|                 env, | ||||
|                 env->GetObjectField(jlandscapePosition, Common::Android::GetPairSecondField()))); | ||||
|  | ||||
|         jobject jportraitPosition = env->GetObjectField( | ||||
|             joverlayControlData, IDCache::GetOverlayControlDataPortraitPositionField()); | ||||
|             joverlayControlData, Common::Android::GetOverlayControlDataPortraitPositionField()); | ||||
|         std::pair<double, double> portrait_position = std::make_pair( | ||||
|             GetJDouble(env, env->GetObjectField(jportraitPosition, IDCache::GetPairFirstField())), | ||||
|             GetJDouble(env, env->GetObjectField(jportraitPosition, IDCache::GetPairSecondField()))); | ||||
|             Common::Android::GetJDouble( | ||||
|                 env, env->GetObjectField(jportraitPosition, Common::Android::GetPairFirstField())), | ||||
|             Common::Android::GetJDouble( | ||||
|                 env, | ||||
|                 env->GetObjectField(jportraitPosition, Common::Android::GetPairSecondField()))); | ||||
|  | ||||
|         jobject jfoldablePosition = env->GetObjectField( | ||||
|             joverlayControlData, IDCache::GetOverlayControlDataFoldablePositionField()); | ||||
|             joverlayControlData, Common::Android::GetOverlayControlDataFoldablePositionField()); | ||||
|         std::pair<double, double> foldable_position = std::make_pair( | ||||
|             GetJDouble(env, env->GetObjectField(jfoldablePosition, IDCache::GetPairFirstField())), | ||||
|             GetJDouble(env, env->GetObjectField(jfoldablePosition, IDCache::GetPairSecondField()))); | ||||
|             Common::Android::GetJDouble( | ||||
|                 env, env->GetObjectField(jfoldablePosition, Common::Android::GetPairFirstField())), | ||||
|             Common::Android::GetJDouble( | ||||
|                 env, | ||||
|                 env->GetObjectField(jfoldablePosition, Common::Android::GetPairSecondField()))); | ||||
|  | ||||
|         AndroidSettings::values.overlay_control_data.push_back(AndroidSettings::OverlayControlData{ | ||||
|             GetJString(env, jidString), enabled, landscape_position, portrait_position, | ||||
|             foldable_position}); | ||||
|             Common::Android::GetJString(env, jidString), enabled, landscape_position, | ||||
|             portrait_position, foldable_position}); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -1,31 +1,30 @@ | ||||
| // SPDX-FileCopyrightText: 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include <common/android/android_common.h> | ||||
| #include <common/logging/log.h> | ||||
| #include <jni.h> | ||||
|  | ||||
| #include "android_common/android_common.h" | ||||
|  | ||||
| extern "C" { | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_utils_Log_debug(JNIEnv* env, jobject obj, jstring jmessage) { | ||||
|     LOG_DEBUG(Frontend, "{}", GetJString(env, jmessage)); | ||||
|     LOG_DEBUG(Frontend, "{}", Common::Android::GetJString(env, jmessage)); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_utils_Log_warning(JNIEnv* env, jobject obj, jstring jmessage) { | ||||
|     LOG_WARNING(Frontend, "{}", GetJString(env, jmessage)); | ||||
|     LOG_WARNING(Frontend, "{}", Common::Android::GetJString(env, jmessage)); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_utils_Log_info(JNIEnv* env, jobject obj, jstring jmessage) { | ||||
|     LOG_INFO(Frontend, "{}", GetJString(env, jmessage)); | ||||
|     LOG_INFO(Frontend, "{}", Common::Android::GetJString(env, jmessage)); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_utils_Log_error(JNIEnv* env, jobject obj, jstring jmessage) { | ||||
|     LOG_ERROR(Frontend, "{}", GetJString(env, jmessage)); | ||||
|     LOG_ERROR(Frontend, "{}", Common::Android::GetJString(env, jmessage)); | ||||
| } | ||||
|  | ||||
| void Java_org_yuzu_yuzu_1emu_utils_Log_critical(JNIEnv* env, jobject obj, jstring jmessage) { | ||||
|     LOG_CRITICAL(Frontend, "{}", GetJString(env, jmessage)); | ||||
|     LOG_CRITICAL(Frontend, "{}", Common::Android::GetJString(env, jmessage)); | ||||
| } | ||||
|  | ||||
| } // extern "C" | ||||
|   | ||||
| @@ -182,9 +182,15 @@ endif() | ||||
|  | ||||
| if(ANDROID) | ||||
|     target_sources(common | ||||
|         PRIVATE | ||||
|         PUBLIC | ||||
|             fs/fs_android.cpp | ||||
|             fs/fs_android.h | ||||
|             android/android_common.cpp | ||||
|             android/android_common.h | ||||
|             android/id_cache.cpp | ||||
|             android/id_cache.h | ||||
|             android/applets/software_keyboard.cpp | ||||
|             android/applets/software_keyboard.h | ||||
|     ) | ||||
| endif() | ||||
|  | ||||
|   | ||||
| @@ -1,15 +1,17 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "jni/android_common/android_common.h" | ||||
| #include "android_common.h" | ||||
| 
 | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| 
 | ||||
| #include <jni.h> | ||||
| 
 | ||||
| #include "common/android/id_cache.h" | ||||
| #include "common/string_util.h" | ||||
| #include "jni/id_cache.h" | ||||
| 
 | ||||
| namespace Common::Android { | ||||
| 
 | ||||
| std::string GetJString(JNIEnv* env, jstring jstr) { | ||||
|     if (!jstr) { | ||||
| @@ -18,7 +20,8 @@ std::string GetJString(JNIEnv* env, jstring jstr) { | ||||
| 
 | ||||
|     const jchar* jchars = env->GetStringChars(jstr, nullptr); | ||||
|     const jsize length = env->GetStringLength(jstr); | ||||
|     const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), length); | ||||
|     const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), | ||||
|                                           static_cast<u32>(length)); | ||||
|     const std::string converted_string = Common::UTF16ToUTF8(string_view); | ||||
|     env->ReleaseStringChars(jstr, jchars); | ||||
| 
 | ||||
| @@ -36,25 +39,27 @@ jstring ToJString(JNIEnv* env, std::u16string_view str) { | ||||
| } | ||||
| 
 | ||||
| double GetJDouble(JNIEnv* env, jobject jdouble) { | ||||
|     return env->GetDoubleField(jdouble, IDCache::GetDoubleValueField()); | ||||
|     return env->GetDoubleField(jdouble, GetDoubleValueField()); | ||||
| } | ||||
| 
 | ||||
| jobject ToJDouble(JNIEnv* env, double value) { | ||||
|     return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); | ||||
|     return env->NewObject(GetDoubleClass(), GetDoubleConstructor(), value); | ||||
| } | ||||
| 
 | ||||
| s32 GetJInteger(JNIEnv* env, jobject jinteger) { | ||||
|     return env->GetIntField(jinteger, IDCache::GetIntegerValueField()); | ||||
|     return env->GetIntField(jinteger, GetIntegerValueField()); | ||||
| } | ||||
| 
 | ||||
| jobject ToJInteger(JNIEnv* env, s32 value) { | ||||
|     return env->NewObject(IDCache::GetIntegerClass(), IDCache::GetIntegerConstructor(), value); | ||||
|     return env->NewObject(GetIntegerClass(), GetIntegerConstructor(), value); | ||||
| } | ||||
| 
 | ||||
| bool GetJBoolean(JNIEnv* env, jobject jboolean) { | ||||
|     return env->GetBooleanField(jboolean, IDCache::GetBooleanValueField()); | ||||
|     return env->GetBooleanField(jboolean, GetBooleanValueField()); | ||||
| } | ||||
| 
 | ||||
| jobject ToJBoolean(JNIEnv* env, bool value) { | ||||
|     return env->NewObject(IDCache::GetBooleanClass(), IDCache::GetBooleanConstructor(), value); | ||||
|     return env->NewObject(GetBooleanClass(), GetBooleanConstructor(), value); | ||||
| } | ||||
| 
 | ||||
| } // namespace Common::Android
 | ||||
| @@ -8,6 +8,8 @@ | ||||
| #include <jni.h> | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Common::Android { | ||||
| 
 | ||||
| std::string GetJString(JNIEnv* env, jstring jstr); | ||||
| jstring ToJString(JNIEnv* env, std::string_view str); | ||||
| jstring ToJString(JNIEnv* env, std::u16string_view str); | ||||
| @@ -20,3 +22,5 @@ jobject ToJInteger(JNIEnv* env, s32 value); | ||||
| 
 | ||||
| bool GetJBoolean(JNIEnv* env, jobject jboolean); | ||||
| jobject ToJBoolean(JNIEnv* env, bool value); | ||||
| 
 | ||||
| } // namespace Common::Android
 | ||||
| @@ -6,12 +6,12 @@ | ||||
| 
 | ||||
| #include <jni.h> | ||||
| 
 | ||||
| #include "common/android/android_common.h" | ||||
| #include "common/android/applets/software_keyboard.h" | ||||
| #include "common/android/id_cache.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/string_util.h" | ||||
| #include "core/core.h" | ||||
| #include "jni/android_common/android_common.h" | ||||
| #include "jni/applets/software_keyboard.h" | ||||
| #include "jni/id_cache.h" | ||||
| 
 | ||||
| static jclass s_software_keyboard_class; | ||||
| static jclass s_keyboard_config_class; | ||||
| @@ -19,10 +19,10 @@ static jclass s_keyboard_data_class; | ||||
| static jmethodID s_swkbd_execute_normal; | ||||
| static jmethodID s_swkbd_execute_inline; | ||||
| 
 | ||||
| namespace SoftwareKeyboard { | ||||
| namespace Common::Android::SoftwareKeyboard { | ||||
| 
 | ||||
| static jobject ToJKeyboardParams(const Core::Frontend::KeyboardInitializeParameters& config) { | ||||
|     JNIEnv* env = IDCache::GetEnvForThread(); | ||||
|     JNIEnv* env = GetEnvForThread(); | ||||
|     jobject object = env->AllocObject(s_keyboard_config_class); | ||||
| 
 | ||||
|     env->SetObjectField(object, | ||||
| @@ -78,7 +78,7 @@ static jobject ToJKeyboardParams(const Core::Frontend::KeyboardInitializeParamet | ||||
| } | ||||
| 
 | ||||
| AndroidKeyboard::ResultData AndroidKeyboard::ResultData::CreateFromFrontend(jobject object) { | ||||
|     JNIEnv* env = IDCache::GetEnvForThread(); | ||||
|     JNIEnv* env = GetEnvForThread(); | ||||
|     const jstring string = reinterpret_cast<jstring>(env->GetObjectField( | ||||
|         object, env->GetFieldID(s_keyboard_data_class, "text", "Ljava/lang/String;"))); | ||||
|     return ResultData{GetJString(env, string), | ||||
| @@ -141,7 +141,7 @@ void AndroidKeyboard::ShowNormalKeyboard() const { | ||||
| 
 | ||||
|     // Pivot to a new thread, as we cannot call GetEnvForThread() from a Fiber.
 | ||||
|     std::thread([&] { | ||||
|         data = ResultData::CreateFromFrontend(IDCache::GetEnvForThread()->CallStaticObjectMethod( | ||||
|         data = ResultData::CreateFromFrontend(GetEnvForThread()->CallStaticObjectMethod( | ||||
|             s_software_keyboard_class, s_swkbd_execute_normal, ToJKeyboardParams(parameters))); | ||||
|     }).join(); | ||||
| 
 | ||||
| @@ -183,8 +183,8 @@ void AndroidKeyboard::ShowInlineKeyboard( | ||||
|     // Pivot to a new thread, as we cannot call GetEnvForThread() from a Fiber.
 | ||||
|     m_is_inline_active = true; | ||||
|     std::thread([&] { | ||||
|         IDCache::GetEnvForThread()->CallStaticVoidMethod( | ||||
|             s_software_keyboard_class, s_swkbd_execute_inline, ToJKeyboardParams(parameters)); | ||||
|         GetEnvForThread()->CallStaticVoidMethod(s_software_keyboard_class, s_swkbd_execute_inline, | ||||
|                                                 ToJKeyboardParams(parameters)); | ||||
|     }).join(); | ||||
| } | ||||
| 
 | ||||
| @@ -220,7 +220,7 @@ void AndroidKeyboard::SubmitInlineKeyboardText(std::u16string submitted_text) { | ||||
|     m_current_text += submitted_text; | ||||
| 
 | ||||
|     submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text, | ||||
|                            m_current_text.size()); | ||||
|                            static_cast<int>(m_current_text.size())); | ||||
| } | ||||
| 
 | ||||
| void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) { | ||||
| @@ -242,7 +242,7 @@ void AndroidKeyboard::SubmitInlineKeyboardInput(int key_code) { | ||||
|     case KEYCODE_DEL: | ||||
|         m_current_text.pop_back(); | ||||
|         submit_inline_callback(Service::AM::Frontend::SwkbdReplyType::ChangedString, m_current_text, | ||||
|                                m_current_text.size()); | ||||
|                                static_cast<int>(m_current_text.size())); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| @@ -274,4 +274,4 @@ void CleanupJNI(JNIEnv* env) { | ||||
|     env->DeleteGlobalRef(s_keyboard_data_class); | ||||
| } | ||||
| 
 | ||||
| } // namespace SoftwareKeyboard
 | ||||
| } // namespace Common::Android::SoftwareKeyboard
 | ||||
| @@ -7,7 +7,7 @@ | ||||
| 
 | ||||
| #include "core/frontend/applets/software_keyboard.h" | ||||
| 
 | ||||
| namespace SoftwareKeyboard { | ||||
| namespace Common::Android::SoftwareKeyboard { | ||||
| 
 | ||||
| class AndroidKeyboard final : public Core::Frontend::SoftwareKeyboardApplet { | ||||
| public: | ||||
| @@ -66,7 +66,7 @@ void InitJNI(JNIEnv* env); | ||||
| // Should be called in JNI_Unload
 | ||||
| void CleanupJNI(JNIEnv* env); | ||||
| 
 | ||||
| } // namespace SoftwareKeyboard
 | ||||
| } // namespace Common::Android::SoftwareKeyboard
 | ||||
| 
 | ||||
| // Native function calls
 | ||||
| extern "C" { | ||||
| @@ -3,10 +3,10 @@ | ||||
| 
 | ||||
| #include <jni.h> | ||||
| 
 | ||||
| #include "applets/software_keyboard.h" | ||||
| #include "common/android/id_cache.h" | ||||
| #include "common/assert.h" | ||||
| #include "common/fs/fs_android.h" | ||||
| #include "jni/applets/software_keyboard.h" | ||||
| #include "jni/id_cache.h" | ||||
| #include "video_core/rasterizer_interface.h" | ||||
| 
 | ||||
| static JavaVM* s_java_vm; | ||||
| @@ -67,7 +67,7 @@ static jfieldID s_boolean_value_field; | ||||
| 
 | ||||
| static constexpr jint JNI_VERSION = JNI_VERSION_1_6; | ||||
| 
 | ||||
| namespace IDCache { | ||||
| namespace Common::Android { | ||||
| 
 | ||||
| JNIEnv* GetEnvForThread() { | ||||
|     thread_local static struct OwnedEnv { | ||||
| @@ -276,8 +276,6 @@ jfieldID GetBooleanValueField() { | ||||
|     return s_boolean_value_field; | ||||
| } | ||||
| 
 | ||||
| } // namespace IDCache
 | ||||
| 
 | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
| @@ -393,7 +391,7 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) { | ||||
|     Common::FS::Android::RegisterCallbacks(env, s_native_library_class); | ||||
| 
 | ||||
|     // Initialize applets
 | ||||
|     SoftwareKeyboard::InitJNI(env); | ||||
|     Common::Android::SoftwareKeyboard::InitJNI(env); | ||||
| 
 | ||||
|     return JNI_VERSION; | ||||
| } | ||||
| @@ -426,3 +424,5 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) { | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| } // namespace Common::Android
 | ||||
| @@ -3,20 +3,40 @@ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <future> | ||||
| #include <jni.h> | ||||
| 
 | ||||
| #include "video_core/rasterizer_interface.h" | ||||
| 
 | ||||
| namespace IDCache { | ||||
| namespace Common::Android { | ||||
| 
 | ||||
| JNIEnv* GetEnvForThread(); | ||||
| 
 | ||||
| /**
 | ||||
|  * Starts a new thread to run JNI. Intended to be used when you must run JNI from a fiber. | ||||
|  * @tparam T Typename of the return value for the work param | ||||
|  * @param work Lambda that runs JNI code. This function will take care of attaching this thread to | ||||
|  * the JVM | ||||
|  * @return The result from the work lambda param | ||||
|  */ | ||||
| template <typename T = void> | ||||
| T RunJNIOnFiber(const std::function<T(JNIEnv*)>& work) { | ||||
|     std::future<T> j_result = std::async(std::launch::async, [&] { | ||||
|         auto env = GetEnvForThread(); | ||||
|         return work(env); | ||||
|     }); | ||||
|     return j_result.get(); | ||||
| } | ||||
| 
 | ||||
| jclass GetNativeLibraryClass(); | ||||
| 
 | ||||
| jclass GetDiskCacheProgressClass(); | ||||
| jclass GetDiskCacheLoadCallbackStageClass(); | ||||
| jclass GetGameDirClass(); | ||||
| jmethodID GetGameDirConstructor(); | ||||
| jmethodID GetExitEmulationActivity(); | ||||
| jmethodID GetDiskCacheLoadProgress(); | ||||
| 
 | ||||
| jmethodID GetExitEmulationActivity(); | ||||
| jmethodID GetOnEmulationStarted(); | ||||
| jmethodID GetOnEmulationStopped(); | ||||
| jmethodID GetOnProgramChanged(); | ||||
| @@ -65,4 +85,4 @@ jclass GetBooleanClass(); | ||||
| jmethodID GetBooleanConstructor(); | ||||
| jfieldID GetBooleanValueField(); | ||||
| 
 | ||||
| } // namespace IDCache
 | ||||
| } // namespace Common::Android
 | ||||
| @@ -1,63 +1,38 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "common/android/android_common.h" | ||||
| #include "common/android/id_cache.h" | ||||
| #include "common/assert.h" | ||||
| #include "common/fs/fs_android.h" | ||||
| #include "common/string_util.h" | ||||
|  | ||||
| namespace Common::FS::Android { | ||||
|  | ||||
| JNIEnv* GetEnvForThread() { | ||||
|     thread_local static struct OwnedEnv { | ||||
|         OwnedEnv() { | ||||
|             status = g_jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6); | ||||
|             if (status == JNI_EDETACHED) | ||||
|                 g_jvm->AttachCurrentThread(&env, nullptr); | ||||
|         } | ||||
|  | ||||
|         ~OwnedEnv() { | ||||
|             if (status == JNI_EDETACHED) | ||||
|                 g_jvm->DetachCurrentThread(); | ||||
|         } | ||||
|  | ||||
|         int status; | ||||
|         JNIEnv* env = nullptr; | ||||
|     } owned; | ||||
|     return owned.env; | ||||
| } | ||||
|  | ||||
| void RegisterCallbacks(JNIEnv* env, jclass clazz) { | ||||
|     env->GetJavaVM(&g_jvm); | ||||
|     native_library = clazz; | ||||
|  | ||||
| #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature)                                \ | ||||
|     F(JMethodID, JMethodName, Signature) | ||||
| #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature)                   \ | ||||
|     F(JMethodID, JMethodName, Signature) | ||||
| #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature)               \ | ||||
|     F(JMethodID, JMethodName, Signature) | ||||
| #define F(JMethodID, JMethodName, Signature)                                                       \ | ||||
|     JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature); | ||||
|     ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||||
|     ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||||
|     ANDROID_STORAGE_FUNCTIONS(FS) | ||||
| #undef F | ||||
| #undef FS | ||||
| #undef FR | ||||
| #undef FH | ||||
|     s_get_parent_directory = env->GetStaticMethodID(native_library, "getParentDirectory", | ||||
|                                                     "(Ljava/lang/String;)Ljava/lang/String;"); | ||||
|     s_get_filename = env->GetStaticMethodID(native_library, "getFilename", | ||||
|                                             "(Ljava/lang/String;)Ljava/lang/String;"); | ||||
|     s_get_size = env->GetStaticMethodID(native_library, "getSize", "(Ljava/lang/String;)J"); | ||||
|     s_is_directory = env->GetStaticMethodID(native_library, "isDirectory", "(Ljava/lang/String;)Z"); | ||||
|     s_file_exists = env->GetStaticMethodID(native_library, "exists", "(Ljava/lang/String;)Z"); | ||||
|     s_open_content_uri = env->GetStaticMethodID(native_library, "openContentUri", | ||||
|                                                 "(Ljava/lang/String;Ljava/lang/String;)I"); | ||||
| } | ||||
|  | ||||
| void UnRegisterCallbacks() { | ||||
| #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | ||||
| #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | ||||
| #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) | ||||
| #define F(JMethodID) JMethodID = nullptr; | ||||
|     ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||||
|     ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||||
|     ANDROID_STORAGE_FUNCTIONS(FS) | ||||
| #undef F | ||||
| #undef FS | ||||
| #undef FR | ||||
| #undef FH | ||||
|     s_get_parent_directory = nullptr; | ||||
|     s_get_filename = nullptr; | ||||
|  | ||||
|     s_get_size = nullptr; | ||||
|     s_is_directory = nullptr; | ||||
|     s_file_exists = nullptr; | ||||
|  | ||||
|     s_open_content_uri = nullptr; | ||||
| } | ||||
|  | ||||
| bool IsContentUri(const std::string& path) { | ||||
| @@ -69,8 +44,8 @@ bool IsContentUri(const std::string& path) { | ||||
|     return path.find(prefix) == 0; | ||||
| } | ||||
|  | ||||
| int OpenContentUri(const std::string& filepath, OpenMode openmode) { | ||||
|     if (open_content_uri == nullptr) | ||||
| s32 OpenContentUri(const std::string& filepath, OpenMode openmode) { | ||||
|     if (s_open_content_uri == nullptr) | ||||
|         return -1; | ||||
|  | ||||
|     const char* mode = ""; | ||||
| @@ -82,50 +57,66 @@ int OpenContentUri(const std::string& filepath, OpenMode openmode) { | ||||
|         UNIMPLEMENTED(); | ||||
|         return -1; | ||||
|     } | ||||
|     auto env = GetEnvForThread(); | ||||
|     jstring j_filepath = env->NewStringUTF(filepath.c_str()); | ||||
|     jstring j_mode = env->NewStringUTF(mode); | ||||
|     return env->CallStaticIntMethod(native_library, open_content_uri, j_filepath, j_mode); | ||||
|     auto env = Common::Android::GetEnvForThread(); | ||||
|     jstring j_filepath = Common::Android::ToJString(env, filepath); | ||||
|     jstring j_mode = Common::Android::ToJString(env, mode); | ||||
|     return env->CallStaticIntMethod(native_library, s_open_content_uri, j_filepath, j_mode); | ||||
| } | ||||
|  | ||||
| #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature)                   \ | ||||
|     F(FunctionName, ReturnValue, JMethodID, Caller) | ||||
| #define F(FunctionName, ReturnValue, JMethodID, Caller)                                            \ | ||||
|     ReturnValue FunctionName(const std::string& filepath) {                                        \ | ||||
|         if (JMethodID == nullptr) {                                                                \ | ||||
|             return 0;                                                                              \ | ||||
|         }                                                                                          \ | ||||
|         auto env = GetEnvForThread();                                                              \ | ||||
|         jstring j_filepath = env->NewStringUTF(filepath.c_str());                                  \ | ||||
|         return env->Caller(native_library, JMethodID, j_filepath);                                 \ | ||||
| u64 GetSize(const std::string& filepath) { | ||||
|     if (s_get_size == nullptr) { | ||||
|         return 0; | ||||
|     } | ||||
| ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||||
| #undef F | ||||
| #undef FR | ||||
|     auto env = Common::Android::GetEnvForThread(); | ||||
|     return static_cast<u64>(env->CallStaticLongMethod( | ||||
|         native_library, s_get_size, | ||||
|         Common::Android::ToJString(Common::Android::GetEnvForThread(), filepath))); | ||||
| } | ||||
|  | ||||
| #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature)                                \ | ||||
|     F(FunctionName, JMethodID, Caller) | ||||
| #define F(FunctionName, JMethodID, Caller)                                                         \ | ||||
|     std::string FunctionName(const std::string& filepath) {                                        \ | ||||
|         if (JMethodID == nullptr) {                                                                \ | ||||
|             return 0;                                                                              \ | ||||
|         }                                                                                          \ | ||||
|         auto env = GetEnvForThread();                                                              \ | ||||
|         jstring j_filepath = env->NewStringUTF(filepath.c_str());                                  \ | ||||
|         jstring j_return =                                                                         \ | ||||
|             static_cast<jstring>(env->Caller(native_library, JMethodID, j_filepath));              \ | ||||
|         if (!j_return) {                                                                           \ | ||||
|             return {};                                                                             \ | ||||
|         }                                                                                          \ | ||||
|         const jchar* jchars = env->GetStringChars(j_return, nullptr);                              \ | ||||
|         const jsize length = env->GetStringLength(j_return);                                       \ | ||||
|         const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), length);  \ | ||||
|         const std::string converted_string = Common::UTF16ToUTF8(string_view);                     \ | ||||
|         env->ReleaseStringChars(j_return, jchars);                                                 \ | ||||
|         return converted_string;                                                                   \ | ||||
| bool IsDirectory(const std::string& filepath) { | ||||
|     if (s_is_directory == nullptr) { | ||||
|         return 0; | ||||
|     } | ||||
| ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||||
| #undef F | ||||
| #undef FH | ||||
|     auto env = Common::Android::GetEnvForThread(); | ||||
|     return env->CallStaticBooleanMethod( | ||||
|         native_library, s_is_directory, | ||||
|         Common::Android::ToJString(Common::Android::GetEnvForThread(), filepath)); | ||||
| } | ||||
|  | ||||
| bool Exists(const std::string& filepath) { | ||||
|     if (s_file_exists == nullptr) { | ||||
|         return 0; | ||||
|     } | ||||
|     auto env = Common::Android::GetEnvForThread(); | ||||
|     return env->CallStaticBooleanMethod( | ||||
|         native_library, s_file_exists, | ||||
|         Common::Android::ToJString(Common::Android::GetEnvForThread(), filepath)); | ||||
| } | ||||
|  | ||||
| std::string GetParentDirectory(const std::string& filepath) { | ||||
|     if (s_get_parent_directory == nullptr) { | ||||
|         return 0; | ||||
|     } | ||||
|     auto env = Common::Android::GetEnvForThread(); | ||||
|     jstring j_return = static_cast<jstring>(env->CallStaticObjectMethod( | ||||
|         native_library, s_get_parent_directory, Common::Android::ToJString(env, filepath))); | ||||
|     if (!j_return) { | ||||
|         return {}; | ||||
|     } | ||||
|     return Common::Android::GetJString(env, j_return); | ||||
| } | ||||
|  | ||||
| std::string GetFilename(const std::string& filepath) { | ||||
|     if (s_get_filename == nullptr) { | ||||
|         return 0; | ||||
|     } | ||||
|     auto env = Common::Android::GetEnvForThread(); | ||||
|     jstring j_return = static_cast<jstring>(env->CallStaticObjectMethod( | ||||
|         native_library, s_get_filename, Common::Android::ToJString(env, filepath))); | ||||
|     if (!j_return) { | ||||
|         return {}; | ||||
|     } | ||||
|     return Common::Android::GetJString(env, j_return); | ||||
| } | ||||
|  | ||||
| } // namespace Common::FS::Android | ||||
|   | ||||
| @@ -7,38 +7,17 @@ | ||||
| #include <vector> | ||||
| #include <jni.h> | ||||
|  | ||||
| #define ANDROID_STORAGE_FUNCTIONS(V)                                                               \ | ||||
|     V(OpenContentUri, int, (const std::string& filepath, OpenMode openmode), open_content_uri,     \ | ||||
|       "openContentUri", "(Ljava/lang/String;Ljava/lang/String;)I") | ||||
|  | ||||
| #define ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(V)                                                 \ | ||||
|     V(GetSize, std::uint64_t, get_size, CallStaticLongMethod, "getSize", "(Ljava/lang/String;)J")  \ | ||||
|     V(IsDirectory, bool, is_directory, CallStaticBooleanMethod, "isDirectory",                     \ | ||||
|       "(Ljava/lang/String;)Z")                                                                     \ | ||||
|     V(Exists, bool, file_exists, CallStaticBooleanMethod, "exists", "(Ljava/lang/String;)Z") | ||||
|  | ||||
| #define ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(V)                                                    \ | ||||
|     V(GetParentDirectory, get_parent_directory, CallStaticObjectMethod, "getParentDirectory",      \ | ||||
|       "(Ljava/lang/String;)Ljava/lang/String;")                                                    \ | ||||
|     V(GetFilename, get_filename, CallStaticObjectMethod, "getFilename",                            \ | ||||
|       "(Ljava/lang/String;)Ljava/lang/String;") | ||||
|  | ||||
| namespace Common::FS::Android { | ||||
|  | ||||
| static JavaVM* g_jvm = nullptr; | ||||
| static jclass native_library = nullptr; | ||||
|  | ||||
| #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | ||||
| #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) | ||||
| #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) | ||||
| #define F(JMethodID) static jmethodID JMethodID = nullptr; | ||||
| ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||||
| ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||||
| ANDROID_STORAGE_FUNCTIONS(FS) | ||||
| #undef F | ||||
| #undef FS | ||||
| #undef FR | ||||
| #undef FH | ||||
| static jmethodID s_get_parent_directory; | ||||
| static jmethodID s_get_filename; | ||||
| static jmethodID s_get_size; | ||||
| static jmethodID s_is_directory; | ||||
| static jmethodID s_file_exists; | ||||
| static jmethodID s_open_content_uri; | ||||
|  | ||||
| enum class OpenMode { | ||||
|     Read, | ||||
| @@ -57,24 +36,11 @@ void UnRegisterCallbacks(); | ||||
|  | ||||
| bool IsContentUri(const std::string& path); | ||||
|  | ||||
| #define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature)               \ | ||||
|     F(FunctionName, Parameters, ReturnValue) | ||||
| #define F(FunctionName, Parameters, ReturnValue) ReturnValue FunctionName Parameters; | ||||
| ANDROID_STORAGE_FUNCTIONS(FS) | ||||
| #undef F | ||||
| #undef FS | ||||
|  | ||||
| #define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature)                   \ | ||||
|     F(FunctionName, ReturnValue) | ||||
| #define F(FunctionName, ReturnValue) ReturnValue FunctionName(const std::string& filepath); | ||||
| ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) | ||||
| #undef F | ||||
| #undef FR | ||||
|  | ||||
| #define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(FunctionName) | ||||
| #define F(FunctionName) std::string FunctionName(const std::string& filepath); | ||||
| ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) | ||||
| #undef F | ||||
| #undef FH | ||||
| int OpenContentUri(const std::string& filepath, OpenMode openmode); | ||||
| std::uint64_t GetSize(const std::string& filepath); | ||||
| bool IsDirectory(const std::string& filepath); | ||||
| bool Exists(const std::string& filepath); | ||||
| std::string GetParentDirectory(const std::string& filepath); | ||||
| std::string GetFilename(const std::string& filepath); | ||||
|  | ||||
| } // namespace Common::FS::Android | ||||
|   | ||||
		Reference in New Issue
	
	Block a user