summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Charles Lombardo2023-10-24 22:51:09 -0400
committerGravatar Charles Lombardo2023-10-30 11:38:10 -0400
commit585b6e9d46b207a6b48a021ea35636fb8c92b405 (patch)
tree8909909ba82a90979748d6fa2bd875aa47cea050
parentandroid: Refactor game metadata collection to new file (diff)
downloadyuzu-585b6e9d46b207a6b48a021ea35636fb8c92b405.tar.gz
yuzu-585b6e9d46b207a6b48a021ea35636fb8c92b405.tar.xz
yuzu-585b6e9d46b207a6b48a021ea35636fb8c92b405.zip
android: Fix resolving android URIs in native code
Diffstat (limited to '')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt29
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DocumentsTree.kt17
-rw-r--r--src/android/app/src/main/jni/native.h8
-rw-r--r--src/common/fs/fs_android.cpp33
-rw-r--r--src/common/fs/fs_android.h15
-rw-r--r--src/common/fs/path_util.cpp10
-rw-r--r--src/common/string_util.cpp12
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
5 5
6import android.app.Dialog 6import android.app.Dialog
7import android.content.DialogInterface 7import android.content.DialogInterface
8import android.net.Uri
8import android.os.Bundle 9import android.os.Bundle
9import android.text.Html 10import android.text.Html
10import android.text.method.LinkMovementMethod 11import android.text.method.LinkMovementMethod
@@ -16,7 +17,7 @@ import androidx.fragment.app.DialogFragment
16import com.google.android.material.dialog.MaterialAlertDialogBuilder 17import com.google.android.material.dialog.MaterialAlertDialogBuilder
17import java.lang.ref.WeakReference 18import java.lang.ref.WeakReference
18import org.yuzu.yuzu_emu.activities.EmulationActivity 19import org.yuzu.yuzu_emu.activities.EmulationActivity
19import org.yuzu.yuzu_emu.utils.DocumentsTree.Companion.isNativePath 20import org.yuzu.yuzu_emu.utils.DocumentsTree
20import org.yuzu.yuzu_emu.utils.FileUtil 21import org.yuzu.yuzu_emu.utils.FileUtil
21import org.yuzu.yuzu_emu.utils.Log 22import org.yuzu.yuzu_emu.utils.Log
22import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable 23import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
@@ -68,7 +69,7 @@ object NativeLibrary {
68 @Keep 69 @Keep
69 @JvmStatic 70 @JvmStatic
70 fun openContentUri(path: String?, openmode: String?): Int { 71 fun openContentUri(path: String?, openmode: String?): Int {
71 return if (isNativePath(path!!)) { 72 return if (DocumentsTree.isNativePath(path!!)) {
72 YuzuApplication.documentsTree!!.openContentUri(path, openmode) 73 YuzuApplication.documentsTree!!.openContentUri(path, openmode)
73 } else { 74 } else {
74 FileUtil.openContentUri(path, openmode) 75 FileUtil.openContentUri(path, openmode)
@@ -78,7 +79,7 @@ object NativeLibrary {
78 @Keep 79 @Keep
79 @JvmStatic 80 @JvmStatic
80 fun getSize(path: String?): Long { 81 fun getSize(path: String?): Long {
81 return if (isNativePath(path!!)) { 82 return if (DocumentsTree.isNativePath(path!!)) {
82 YuzuApplication.documentsTree!!.getFileSize(path) 83 YuzuApplication.documentsTree!!.getFileSize(path)
83 } else { 84 } else {
84 FileUtil.getFileSize(path) 85 FileUtil.getFileSize(path)
@@ -88,7 +89,7 @@ object NativeLibrary {
88 @Keep 89 @Keep
89 @JvmStatic 90 @JvmStatic
90 fun exists(path: String?): Boolean { 91 fun exists(path: String?): Boolean {
91 return if (isNativePath(path!!)) { 92 return if (DocumentsTree.isNativePath(path!!)) {
92 YuzuApplication.documentsTree!!.exists(path) 93 YuzuApplication.documentsTree!!.exists(path)
93 } else { 94 } else {
94 FileUtil.exists(path) 95 FileUtil.exists(path)
@@ -98,13 +99,31 @@ object NativeLibrary {
98 @Keep 99 @Keep
99 @JvmStatic 100 @JvmStatic
100 fun isDirectory(path: String?): Boolean { 101 fun isDirectory(path: String?): Boolean {
101 return if (isNativePath(path!!)) { 102 return if (DocumentsTree.isNativePath(path!!)) {
102 YuzuApplication.documentsTree!!.isDirectory(path) 103 YuzuApplication.documentsTree!!.isDirectory(path)
103 } else { 104 } else {
104 FileUtil.isDirectory(path) 105 FileUtil.isDirectory(path)
105 } 106 }
106 } 107 }
107 108
109 @Keep
110 @JvmStatic
111 fun getParentDirectory(path: String): String =
112 if (DocumentsTree.isNativePath(path)) {
113 YuzuApplication.documentsTree!!.getParentDirectory(path)
114 } else {
115 path
116 }
117
118 @Keep
119 @JvmStatic
120 fun getFilename(path: String): String =
121 if (DocumentsTree.isNativePath(path)) {
122 YuzuApplication.documentsTree!!.getFilename(path)
123 } else {
124 FileUtil.getFilename(Uri.parse(path))
125 }
126
108 /** 127 /**
109 * Returns true if pro controller isn't available and handheld is 128 * Returns true if pro controller isn't available and handheld is
110 */ 129 */
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 {
42 return node != null && node.isDirectory 42 return node != null && node.isDirectory
43 } 43 }
44 44
45 fun getParentDirectory(filepath: String): String {
46 val node = resolvePath(filepath)!!
47 val parentNode = node.parent
48 if (parentNode != null && parentNode.isDirectory) {
49 return parentNode.uri!!.toString()
50 }
51 return node.uri!!.toString()
52 }
53
54 fun getFilename(filepath: String): String {
55 val node = resolvePath(filepath)
56 if (node != null) {
57 return node.name!!
58 }
59 return filepath
60 }
61
45 private fun resolvePath(filepath: String): DocumentsNode? { 62 private fun resolvePath(filepath: String): DocumentsNode? {
46 val tokens = StringTokenizer(filepath, File.separator, false) 63 val tokens = StringTokenizer(filepath, File.separator, false)
47 var iterator = root 64 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 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include <android/native_window_jni.h> 4#include <android/native_window_jni.h>
5#include "common/detached_tasks.h"
5#include "core/core.h" 6#include "core/core.h"
7#include "core/file_sys/registered_cache.h"
8#include "core/hle/service/acc/profile_manager.h"
6#include "core/perf_stats.h" 9#include "core/perf_stats.h"
7#include "jni/emu_window/emu_window.h"
8#include "jni/applets/software_keyboard.h" 10#include "jni/applets/software_keyboard.h"
11#include "jni/emu_window/emu_window.h"
9#include "video_core/rasterizer_interface.h" 12#include "video_core/rasterizer_interface.h"
10#include "common/detached_tasks.h"
11#include "core/hle/service/acc/profile_manager.h"
12#include "core/file_sys/registered_cache.h"
13 13
14#pragma once 14#pragma once
15 15
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 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "common/fs/fs_android.h" 4#include "common/fs/fs_android.h"
5#include "common/string_util.h"
5 6
6namespace Common::FS::Android { 7namespace Common::FS::Android {
7 8
@@ -28,28 +29,35 @@ void RegisterCallbacks(JNIEnv* env, jclass clazz) {
28 env->GetJavaVM(&g_jvm); 29 env->GetJavaVM(&g_jvm);
29 native_library = clazz; 30 native_library = clazz;
30 31
32#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) \
33 F(JMethodID, JMethodName, Signature)
31#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \ 34#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) \
32 F(JMethodID, JMethodName, Signature) 35 F(JMethodID, JMethodName, Signature)
33#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \ 36#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) \
34 F(JMethodID, JMethodName, Signature) 37 F(JMethodID, JMethodName, Signature)
35#define F(JMethodID, JMethodName, Signature) \ 38#define F(JMethodID, JMethodName, Signature) \
36 JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature); 39 JMethodID = env->GetStaticMethodID(native_library, JMethodName, Signature);
40 ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
37 ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) 41 ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
38 ANDROID_STORAGE_FUNCTIONS(FS) 42 ANDROID_STORAGE_FUNCTIONS(FS)
39#undef F 43#undef F
40#undef FS 44#undef FS
41#undef FR 45#undef FR
46#undef FH
42} 47}
43 48
44void UnRegisterCallbacks() { 49void UnRegisterCallbacks() {
50#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(JMethodID)
45#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) 51#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID)
46#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) 52#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID)
47#define F(JMethodID) JMethodID = nullptr; 53#define F(JMethodID) JMethodID = nullptr;
54 ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
48 ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) 55 ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
49 ANDROID_STORAGE_FUNCTIONS(FS) 56 ANDROID_STORAGE_FUNCTIONS(FS)
50#undef F 57#undef F
51#undef FS 58#undef FS
52#undef FR 59#undef FR
60#undef FH
53} 61}
54 62
55bool IsContentUri(const std::string& path) { 63bool IsContentUri(const std::string& path) {
@@ -95,4 +103,29 @@ ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
95#undef F 103#undef F
96#undef FR 104#undef FR
97 105
106#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) \
107 F(FunctionName, JMethodID, Caller)
108#define F(FunctionName, JMethodID, Caller) \
109 std::string FunctionName(const std::string& filepath) { \
110 if (JMethodID == nullptr) { \
111 return 0; \
112 } \
113 auto env = GetEnvForThread(); \
114 jstring j_filepath = env->NewStringUTF(filepath.c_str()); \
115 jstring j_return = \
116 static_cast<jstring>(env->Caller(native_library, JMethodID, j_filepath)); \
117 if (!j_return) { \
118 return {}; \
119 } \
120 const jchar* jchars = env->GetStringChars(j_return, nullptr); \
121 const jsize length = env->GetStringLength(j_return); \
122 const std::u16string_view string_view(reinterpret_cast<const char16_t*>(jchars), length); \
123 const std::string converted_string = Common::UTF16ToUTF8(string_view); \
124 env->ReleaseStringChars(j_return, jchars); \
125 return converted_string; \
126 }
127ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
128#undef F
129#undef FH
130
98} // namespace Common::FS::Android 131} // 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 @@
17 "(Ljava/lang/String;)Z") \ 17 "(Ljava/lang/String;)Z") \
18 V(Exists, bool, file_exists, CallStaticBooleanMethod, "exists", "(Ljava/lang/String;)Z") 18 V(Exists, bool, file_exists, CallStaticBooleanMethod, "exists", "(Ljava/lang/String;)Z")
19 19
20#define ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(V) \
21 V(GetParentDirectory, get_parent_directory, CallStaticObjectMethod, "getParentDirectory", \
22 "(Ljava/lang/String;)Ljava/lang/String;") \
23 V(GetFilename, get_filename, CallStaticObjectMethod, "getFilename", \
24 "(Ljava/lang/String;)Ljava/lang/String;")
25
20namespace Common::FS::Android { 26namespace Common::FS::Android {
21 27
22static JavaVM* g_jvm = nullptr; 28static JavaVM* g_jvm = nullptr;
23static jclass native_library = nullptr; 29static jclass native_library = nullptr;
24 30
31#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(JMethodID)
25#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID) 32#define FR(FunctionName, ReturnValue, JMethodID, Caller, JMethodName, Signature) F(JMethodID)
26#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID) 33#define FS(FunctionName, ReturnValue, Parameters, JMethodID, JMethodName, Signature) F(JMethodID)
27#define F(JMethodID) static jmethodID JMethodID = nullptr; 34#define F(JMethodID) static jmethodID JMethodID = nullptr;
35ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
28ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR) 36ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
29ANDROID_STORAGE_FUNCTIONS(FS) 37ANDROID_STORAGE_FUNCTIONS(FS)
30#undef F 38#undef F
31#undef FS 39#undef FS
32#undef FR 40#undef FR
41#undef FH
33 42
34enum class OpenMode { 43enum class OpenMode {
35 Read, 44 Read,
@@ -62,4 +71,10 @@ ANDROID_SINGLE_PATH_DETERMINE_FUNCTIONS(FR)
62#undef F 71#undef F
63#undef FR 72#undef FR
64 73
74#define FH(FunctionName, JMethodID, Caller, JMethodName, Signature) F(FunctionName)
75#define F(FunctionName) std::string FunctionName(const std::string& filepath);
76ANDROID_SINGLE_PATH_HELPER_FUNCTIONS(FH)
77#undef F
78#undef FH
79
65} // namespace Common::FS::Android 80} // 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
401} 401}
402 402
403std::string_view GetParentPath(std::string_view path) { 403std::string_view GetParentPath(std::string_view path) {
404 if (path.empty()) {
405 return path;
406 }
407
408#ifdef ANDROID
409 if (path[0] != '/') {
410 std::string path_string{path};
411 return FS::Android::GetParentDirectory(path_string);
412 }
413#endif
404 const auto name_bck_index = path.rfind('\\'); 414 const auto name_bck_index = path.rfind('\\');
405 const auto name_fwd_index = path.rfind('/'); 415 const auto name_fwd_index = path.rfind('/');
406 std::size_t name_index; 416 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 @@
14#include <windows.h> 14#include <windows.h>
15#endif 15#endif
16 16
17#ifdef ANDROID
18#include <common/fs/fs_android.h>
19#endif
20
17namespace Common { 21namespace Common {
18 22
19/// Make a string lowercase 23/// Make a string lowercase
@@ -63,6 +67,14 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
63 if (full_path.empty()) 67 if (full_path.empty())
64 return false; 68 return false;
65 69
70#ifdef ANDROID
71 if (full_path[0] != '/') {
72 *_pPath = Common::FS::Android::GetParentDirectory(full_path);
73 *_pFilename = Common::FS::Android::GetFilename(full_path);
74 return true;
75 }
76#endif
77
66 std::size_t dir_end = full_path.find_last_of("/" 78 std::size_t dir_end = full_path.find_last_of("/"
67// windows needs the : included for something like just "C:" to be considered a directory 79// windows needs the : included for something like just "C:" to be considered a directory
68#ifdef _WIN32 80#ifdef _WIN32