diff --git a/src/common/fs/fs_android.cpp b/src/common/fs/fs_android.cpp index 1dd826a4a..9a8053222 100644 --- a/src/common/fs/fs_android.cpp +++ b/src/common/fs/fs_android.cpp @@ -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(&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(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(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(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(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(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 diff --git a/src/common/fs/fs_android.h b/src/common/fs/fs_android.h index 2c9234313..b33f4beb8 100644 --- a/src/common/fs/fs_android.h +++ b/src/common/fs/fs_android.h @@ -7,38 +7,17 @@ #include #include -#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