diff options
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt | 29 | ||||
| -rw-r--r-- | src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt | 17 | ||||
| -rw-r--r-- | src/android/app/src/main/jni/native.h | 8 | ||||
| -rw-r--r-- | src/common/fs/fs_android.cpp | 33 | ||||
| -rw-r--r-- | src/common/fs/fs_android.h | 15 | ||||
| -rw-r--r-- | src/common/fs/path_util.cpp | 10 | ||||
| -rw-r--r-- | src/common/string_util.cpp | 12 | 
7 files changed, 115 insertions, 9 deletions
| diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt index 22c9b05de..5fe235dba 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt @@ -5,6 +5,7 @@ package org.yuzu.yuzu_emu  import android.app.Dialog  import android.content.DialogInterface +import android.net.Uri  import android.os.Bundle  import android.text.Html  import android.text.method.LinkMovementMethod @@ -16,7 +17,7 @@ import androidx.fragment.app.DialogFragment  import com.google.android.material.dialog.MaterialAlertDialogBuilder  import java.lang.ref.WeakReference  import org.yuzu.yuzu_emu.activities.EmulationActivity -import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath +import org.yuzu.yuzu_emu.utils.DocumentsTree  import org.yuzu.yuzu_emu.utils.FileUtil  import org.yuzu.yuzu_emu.utils.Log  import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable @@ -68,7 +69,7 @@ object NativeLibrary {      @Keep      @JvmStatic      fun openContentUri(path: String?, openmode: String?): Int { -        return if (isNativePath(path!!)) { +        return if (DocumentsTree.isNativePath(path!!)) {              YuzuApplication.documentsTree!!.openContentUri(path, openmode)          } else {              FileUtil.openContentUri(path, openmode) @@ -78,7 +79,7 @@ object NativeLibrary {      @Keep      @JvmStatic      fun getSize(path: String?): Long { -        return if (isNativePath(path!!)) { +        return if (DocumentsTree.isNativePath(path!!)) {              YuzuApplication.documentsTree!!.getFileSize(path)          } else {              FileUtil.getFileSize(path) @@ -88,7 +89,7 @@ object NativeLibrary {      @Keep      @JvmStatic      fun exists(path: String?): Boolean { -        return if (isNativePath(path!!)) { +        return if (DocumentsTree.isNativePath(path!!)) {              YuzuApplication.documentsTree!!.exists(path)          } else {              FileUtil.exists(path) @@ -98,13 +99,31 @@ object NativeLibrary {      @Keep      @JvmStatic      fun isDirectory(path: String?): Boolean { -        return if (isNativePath(path!!)) { +        return if (DocumentsTree.isNativePath(path!!)) {              YuzuApplication.documentsTree!!.isDirectory(path)          } else {              FileUtil.isDirectory(path)          }      } +    @Keep +    @JvmStatic +    fun getParentDirectory(path: String): String = +        if (DocumentsTree.isNativePath(path)) { +            YuzuApplication.documentsTree!!.getParentDirectory(path) +        } else { +            path +        } + +    @Keep +    @JvmStatic +    fun getFilename(path: String): String = +        if (DocumentsTree.isNativePath(path)) { +            YuzuApplication.documentsTree!!.getFilename(path) +        } else { +            FileUtil.getFilename(Uri.parse(path)) +        } +      /**       * Returns true if pro controller isn't available and handheld is       */ diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt index eafcf9e42..738275297 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt @@ -42,6 +42,23 @@ class DocumentsTree {          return node != null && node.isDirectory      } +    fun getParentDirectory(filepath: String): String { +        val node = resolvePath(filepath)!! +        val parentNode = node.parent +        if (parentNode != null && parentNode.isDirectory) { +            return parentNode.uri!!.toString() +        } +        return node.uri!!.toString() +    } + +    fun getFilename(filepath: String): String { +        val node = resolvePath(filepath) +        if (node != null) { +            return node.name!! +        } +        return filepath +    } +      private fun resolvePath(filepath: String): DocumentsNode? {          val tokens = StringTokenizer(filepath, File.separator, false)          var iterator = root diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h index 2eb5c4349..b1db87e41 100644 --- a/src/android/app/src/main/jni/native.h +++ b/src/android/app/src/main/jni/native.h @@ -2,14 +2,14 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include <android/native_window_jni.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 "jni/emu_window/emu_window.h"  #include "jni/applets/software_keyboard.h" +#include "jni/emu_window/emu_window.h"  #include "video_core/rasterizer_interface.h" -#include "common/detached_tasks.h" -#include "core/hle/service/acc/profile_manager.h" -#include "core/file_sys/registered_cache.h"  #pragma once diff --git a/src/common/fs/fs_android.cpp b/src/common/fs/fs_android.cpp index 298a79bac..1dd826a4a 100644 --- a/src/common/fs/fs_android.cpp +++ b/src/common/fs/fs_android.cpp @@ -2,6 +2,7 @@  // SPDX-License-Identifier: GPL-2.0-or-later  #include "common/fs/fs_android.h" +#include "common/string_util.h"  namespace Common::FS::Android { @@ -28,28 +29,35 @@ 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  }  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  }  bool IsContentUri(const std::string& path) { @@ -95,4 +103,29 @@ ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)  #undef F  #undef FR +#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;                                                                   \ +    } +ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH) +#undef F +#undef FH +  } // namespace Common::FS::Android diff --git a/src/common/fs/fs_android.h b/src/common/fs/fs_android.h index b441c2a12..2c9234313 100644 --- a/src/common/fs/fs_android.h +++ b/src/common/fs/fs_android.h @@ -17,19 +17,28 @@        "(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  enum class OpenMode {      Read, @@ -62,4 +71,10 @@ 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 +  } // namespace Common::FS::Android diff --git a/src/common/fs/path_util.cpp b/src/common/fs/path_util.cpp index 0c4c88cde..c3a81f9a9 100644 --- a/src/common/fs/path_util.cpp +++ b/src/common/fs/path_util.cpp @@ -401,6 +401,16 @@ std::string SanitizePath(std::string_view path_, DirectorySeparator directory_se  }  std::string_view GetParentPath(std::string_view path) { +    if (path.empty()) { +        return path; +    } + +#ifdef ANDROID +    if (path[0] != '/') { +        std::string path_string{path}; +        return FS::Android::GetParentDirectory(path_string); +    } +#endif      const auto name_bck_index = path.rfind('\\');      const auto name_fwd_index = path.rfind('/');      std::size_t name_index; diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 4c7aba3f5..72c481798 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -14,6 +14,10 @@  #include <windows.h>  #endif +#ifdef ANDROID +#include <common/fs/fs_android.h> +#endif +  namespace Common {  /// Make a string lowercase @@ -63,6 +67,14 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _      if (full_path.empty())          return false; +#ifdef ANDROID +    if (full_path[0] != '/') { +        *_pPath = Common::FS::Android::GetParentDirectory(full_path); +        *_pFilename = Common::FS::Android::GetFilename(full_path); +        return true; +    } +#endif +      std::size_t dir_end = full_path.find_last_of("/"  // windows needs the : included for something like just "C:" to be considered a directory  #ifdef _WIN32 | 
