summaryrefslogtreecommitdiff
path: root/src/android
diff options
context:
space:
mode:
authorGravatar t8952024-01-19 00:56:43 -0500
committerGravatar t8952024-01-19 17:09:35 -0500
commitccd3dd842f2bf7cf16c7b93e3b83a2afc8af4a69 (patch)
tree552347f0f71c9341a139f929907fef9243c6e337 /src/android
parentMerge pull request #12713 from shinra-electric/mvk-127 (diff)
downloadyuzu-ccd3dd842f2bf7cf16c7b93e3b83a2afc8af4a69.tar.gz
yuzu-ccd3dd842f2bf7cf16c7b93e3b83a2afc8af4a69.tar.xz
yuzu-ccd3dd842f2bf7cf16c7b93e3b83a2afc8af4a69.zip
frontend_common: Add content manager utility functions
Creates utility functions to remove/install DLC, updates, and base game content
Diffstat (limited to 'src/android')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt19
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt15
-rw-r--r--src/android/app/src/main/jni/android_common/android_common.cpp16
-rw-r--r--src/android/app/src/main/jni/android_common/android_common.h7
-rw-r--r--src/android/app/src/main/jni/id_cache.cpp46
-rw-r--r--src/android/app/src/main/jni/id_cache.h8
-rw-r--r--src/android/app/src/main/jni/native.cpp80
-rw-r--r--src/android/app/src/main/jni/native.h2
8 files changed, 114 insertions, 79 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 b7556e353..8cb98d6d7 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
@@ -21,6 +21,7 @@ import org.yuzu.yuzu_emu.utils.DocumentsTree
21import org.yuzu.yuzu_emu.utils.FileUtil 21import org.yuzu.yuzu_emu.utils.FileUtil
22import org.yuzu.yuzu_emu.utils.Log 22import org.yuzu.yuzu_emu.utils.Log
23import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable 23import org.yuzu.yuzu_emu.utils.SerializableHelper.serializable
24import org.yuzu.yuzu_emu.model.InstallResult
24 25
25/** 26/**
26 * Class which contains methods that interact 27 * Class which contains methods that interact
@@ -235,9 +236,12 @@ object NativeLibrary {
235 /** 236 /**
236 * Installs a nsp or xci file to nand 237 * Installs a nsp or xci file to nand
237 * @param filename String representation of file uri 238 * @param filename String representation of file uri
238 * @param extension Lowercase string representation of file extension without "." 239 * @return int representation of [InstallResult]
239 */ 240 */
240 external fun installFileToNand(filename: String, extension: String): Int 241 external fun installFileToNand(
242 filename: String,
243 callback: (max: Long, progress: Long) -> Boolean
244 ): Int
241 245
242 external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean 246 external fun doesUpdateMatchProgram(programId: String, updatePath: String): Boolean
243 247
@@ -609,15 +613,4 @@ object NativeLibrary {
609 const val RELEASED = 0 613 const val RELEASED = 0
610 const val PRESSED = 1 614 const val PRESSED = 1
611 } 615 }
612
613 /**
614 * Result from installFileToNand
615 */
616 object InstallFileToNandResult {
617 const val Success = 0
618 const val SuccessFileOverwritten = 1
619 const val Error = 2
620 const val ErrorBaseGame = 3
621 const val ErrorFilenameExtension = 4
622 }
623} 616}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt
new file mode 100644
index 000000000..0c3cd0521
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/InstallResult.kt
@@ -0,0 +1,15 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.model
5
6enum class InstallResult(val int: Int) {
7 Success(0),
8 Overwrite(1),
9 Failure(2),
10 BaseInstallAttempted(3);
11
12 companion object {
13 fun from(int: Int): InstallResult = entries.firstOrNull { it.int == int } ?: Success
14 }
15}
diff --git a/src/android/app/src/main/jni/android_common/android_common.cpp b/src/android/app/src/main/jni/android_common/android_common.cpp
index 1e884ffdd..7018a52af 100644
--- a/src/android/app/src/main/jni/android_common/android_common.cpp
+++ b/src/android/app/src/main/jni/android_common/android_common.cpp
@@ -42,3 +42,19 @@ double GetJDouble(JNIEnv* env, jobject jdouble) {
42jobject ToJDouble(JNIEnv* env, double value) { 42jobject ToJDouble(JNIEnv* env, double value) {
43 return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value); 43 return env->NewObject(IDCache::GetDoubleClass(), IDCache::GetDoubleConstructor(), value);
44} 44}
45
46s32 GetJInteger(JNIEnv* env, jobject jinteger) {
47 return env->GetIntField(jinteger, IDCache::GetIntegerValueField());
48}
49
50jobject ToJInteger(JNIEnv* env, s32 value) {
51 return env->NewObject(IDCache::GetIntegerClass(), IDCache::GetIntegerConstructor(), value);
52}
53
54bool GetJBoolean(JNIEnv* env, jobject jboolean) {
55 return env->GetBooleanField(jboolean, IDCache::GetBooleanValueField());
56}
57
58jobject ToJBoolean(JNIEnv* env, bool value) {
59 return env->NewObject(IDCache::GetBooleanClass(), IDCache::GetBooleanConstructor(), value);
60}
diff --git a/src/android/app/src/main/jni/android_common/android_common.h b/src/android/app/src/main/jni/android_common/android_common.h
index 8eb803e1b..29a338c0a 100644
--- a/src/android/app/src/main/jni/android_common/android_common.h
+++ b/src/android/app/src/main/jni/android_common/android_common.h
@@ -6,6 +6,7 @@
6#include <string> 6#include <string>
7 7
8#include <jni.h> 8#include <jni.h>
9#include "common/common_types.h"
9 10
10std::string GetJString(JNIEnv* env, jstring jstr); 11std::string GetJString(JNIEnv* env, jstring jstr);
11jstring ToJString(JNIEnv* env, std::string_view str); 12jstring ToJString(JNIEnv* env, std::string_view str);
@@ -13,3 +14,9 @@ jstring ToJString(JNIEnv* env, std::u16string_view str);
13 14
14double GetJDouble(JNIEnv* env, jobject jdouble); 15double GetJDouble(JNIEnv* env, jobject jdouble);
15jobject ToJDouble(JNIEnv* env, double value); 16jobject ToJDouble(JNIEnv* env, double value);
17
18s32 GetJInteger(JNIEnv* env, jobject jinteger);
19jobject ToJInteger(JNIEnv* env, s32 value);
20
21bool GetJBoolean(JNIEnv* env, jobject jboolean);
22jobject ToJBoolean(JNIEnv* env, bool value);
diff --git a/src/android/app/src/main/jni/id_cache.cpp b/src/android/app/src/main/jni/id_cache.cpp
index c79ad7d76..19ced175f 100644
--- a/src/android/app/src/main/jni/id_cache.cpp
+++ b/src/android/app/src/main/jni/id_cache.cpp
@@ -47,6 +47,14 @@ static jclass s_double_class;
47static jmethodID s_double_constructor; 47static jmethodID s_double_constructor;
48static jfieldID s_double_value_field; 48static jfieldID s_double_value_field;
49 49
50static jclass s_integer_class;
51static jmethodID s_integer_constructor;
52static jfieldID s_integer_value_field;
53
54static jclass s_boolean_class;
55static jmethodID s_boolean_constructor;
56static jfieldID s_boolean_value_field;
57
50static constexpr jint JNI_VERSION = JNI_VERSION_1_6; 58static constexpr jint JNI_VERSION = JNI_VERSION_1_6;
51 59
52namespace IDCache { 60namespace IDCache {
@@ -198,6 +206,30 @@ jfieldID GetDoubleValueField() {
198 return s_double_value_field; 206 return s_double_value_field;
199} 207}
200 208
209jclass GetIntegerClass() {
210 return s_integer_class;
211}
212
213jmethodID GetIntegerConstructor() {
214 return s_integer_constructor;
215}
216
217jfieldID GetIntegerValueField() {
218 return s_integer_value_field;
219}
220
221jclass GetBooleanClass() {
222 return s_boolean_class;
223}
224
225jmethodID GetBooleanConstructor() {
226 return s_boolean_constructor;
227}
228
229jfieldID GetBooleanValueField() {
230 return s_boolean_value_field;
231}
232
201} // namespace IDCache 233} // namespace IDCache
202 234
203#ifdef __cplusplus 235#ifdef __cplusplus
@@ -284,6 +316,18 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved) {
284 s_double_value_field = env->GetFieldID(double_class, "value", "D"); 316 s_double_value_field = env->GetFieldID(double_class, "value", "D");
285 env->DeleteLocalRef(double_class); 317 env->DeleteLocalRef(double_class);
286 318
319 const jclass int_class = env->FindClass("java/lang/Integer");
320 s_integer_class = reinterpret_cast<jclass>(env->NewGlobalRef(int_class));
321 s_integer_constructor = env->GetMethodID(int_class, "<init>", "(I)V");
322 s_integer_value_field = env->GetFieldID(int_class, "value", "I");
323 env->DeleteLocalRef(int_class);
324
325 const jclass boolean_class = env->FindClass("java/lang/Boolean");
326 s_boolean_class = reinterpret_cast<jclass>(env->NewGlobalRef(boolean_class));
327 s_boolean_constructor = env->GetMethodID(boolean_class, "<init>", "(Z)V");
328 s_boolean_value_field = env->GetFieldID(boolean_class, "value", "Z");
329 env->DeleteLocalRef(boolean_class);
330
287 // Initialize Android Storage 331 // Initialize Android Storage
288 Common::FS::Android::RegisterCallbacks(env, s_native_library_class); 332 Common::FS::Android::RegisterCallbacks(env, s_native_library_class);
289 333
@@ -310,6 +354,8 @@ void JNI_OnUnload(JavaVM* vm, void* reserved) {
310 env->DeleteGlobalRef(s_pair_class); 354 env->DeleteGlobalRef(s_pair_class);
311 env->DeleteGlobalRef(s_overlay_control_data_class); 355 env->DeleteGlobalRef(s_overlay_control_data_class);
312 env->DeleteGlobalRef(s_double_class); 356 env->DeleteGlobalRef(s_double_class);
357 env->DeleteGlobalRef(s_integer_class);
358 env->DeleteGlobalRef(s_boolean_class);
313 359
314 // UnInitialize applets 360 // UnInitialize applets
315 SoftwareKeyboard::CleanupJNI(env); 361 SoftwareKeyboard::CleanupJNI(env);
diff --git a/src/android/app/src/main/jni/id_cache.h b/src/android/app/src/main/jni/id_cache.h
index 784d1412f..0e5267b73 100644
--- a/src/android/app/src/main/jni/id_cache.h
+++ b/src/android/app/src/main/jni/id_cache.h
@@ -47,4 +47,12 @@ jclass GetDoubleClass();
47jmethodID GetDoubleConstructor(); 47jmethodID GetDoubleConstructor();
48jfieldID GetDoubleValueField(); 48jfieldID GetDoubleValueField();
49 49
50jclass GetIntegerClass();
51jmethodID GetIntegerConstructor();
52jfieldID GetIntegerValueField();
53
54jclass GetBooleanClass();
55jmethodID GetBooleanConstructor();
56jfieldID GetBooleanValueField();
57
50} // namespace IDCache 58} // namespace IDCache
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index ed3b1353a..b8fef5c6f 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -17,6 +17,7 @@
17#include <core/file_sys/patch_manager.h> 17#include <core/file_sys/patch_manager.h>
18#include <core/file_sys/savedata_factory.h> 18#include <core/file_sys/savedata_factory.h>
19#include <core/loader/nro.h> 19#include <core/loader/nro.h>
20#include <frontend_common/content_manager.h>
20#include <jni.h> 21#include <jni.h>
21 22
22#include "common/detached_tasks.h" 23#include "common/detached_tasks.h"
@@ -100,67 +101,6 @@ void EmulationSession::SetNativeWindow(ANativeWindow* native_window) {
100 m_native_window = native_window; 101 m_native_window = native_window;
101} 102}
102 103
103int EmulationSession::InstallFileToNand(std::string filename, std::string file_extension) {
104 jconst copy_func = [](const FileSys::VirtualFile& src, const FileSys::VirtualFile& dest,
105 std::size_t block_size) {
106 if (src == nullptr || dest == nullptr) {
107 return false;
108 }
109 if (!dest->Resize(src->GetSize())) {
110 return false;
111 }
112
113 using namespace Common::Literals;
114 [[maybe_unused]] std::vector<u8> buffer(1_MiB);
115
116 for (std::size_t i = 0; i < src->GetSize(); i += buffer.size()) {
117 jconst read = src->Read(buffer.data(), buffer.size(), i);
118 dest->Write(buffer.data(), read, i);
119 }
120 return true;
121 };
122
123 enum InstallResult {
124 Success = 0,
125 SuccessFileOverwritten = 1,
126 InstallError = 2,
127 ErrorBaseGame = 3,
128 ErrorFilenameExtension = 4,
129 };
130
131 [[maybe_unused]] std::shared_ptr<FileSys::NSP> nsp;
132 if (file_extension == "nsp") {
133 nsp = std::make_shared<FileSys::NSP>(m_vfs->OpenFile(filename, FileSys::Mode::Read));
134 if (nsp->IsExtractedType()) {
135 return InstallError;
136 }
137 } else {
138 return ErrorFilenameExtension;
139 }
140
141 if (!nsp) {
142 return InstallError;
143 }
144
145 if (nsp->GetStatus() != Loader::ResultStatus::Success) {
146 return InstallError;
147 }
148
149 jconst res = m_system.GetFileSystemController().GetUserNANDContents()->InstallEntry(*nsp, true,
150 copy_func);
151
152 switch (res) {
153 case FileSys::InstallResult::Success:
154 return Success;
155 case FileSys::InstallResult::OverwriteExisting:
156 return SuccessFileOverwritten;
157 case FileSys::InstallResult::ErrorBaseInstall:
158 return ErrorBaseGame;
159 default:
160 return InstallError;
161 }
162}
163
164void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir, 104void EmulationSession::InitializeGpuDriver(const std::string& hook_lib_dir,
165 const std::string& custom_driver_dir, 105 const std::string& custom_driver_dir,
166 const std::string& custom_driver_name, 106 const std::string& custom_driver_name,
@@ -512,10 +452,20 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_setAppDirectory(JNIEnv* env, jobject
512} 452}
513 453
514int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance, 454int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject instance,
515 jstring j_file, 455 jstring j_file, jobject jcallback) {
516 jstring j_file_extension) { 456 auto jlambdaClass = env->GetObjectClass(jcallback);
517 return EmulationSession::GetInstance().InstallFileToNand(GetJString(env, j_file), 457 auto jlambdaInvokeMethod = env->GetMethodID(
518 GetJString(env, j_file_extension)); 458 jlambdaClass, "invoke", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
459 const auto callback = [env, jcallback, jlambdaInvokeMethod](size_t max, size_t progress) {
460 auto jwasCancelled = env->CallObjectMethod(jcallback, jlambdaInvokeMethod,
461 ToJDouble(env, max), ToJDouble(env, progress));
462 return GetJBoolean(env, jwasCancelled);
463 };
464
465 return static_cast<int>(
466 ContentManager::InstallNSP(&EmulationSession::GetInstance().System(),
467 EmulationSession::GetInstance().System().GetFilesystem().get(),
468 GetJString(env, j_file), callback));
519} 469}
520 470
521jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj, 471jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj,
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
index 4a8049578..dadb138ad 100644
--- a/src/android/app/src/main/jni/native.h
+++ b/src/android/app/src/main/jni/native.h
@@ -7,6 +7,7 @@
7#include "core/file_sys/registered_cache.h" 7#include "core/file_sys/registered_cache.h"
8#include "core/hle/service/acc/profile_manager.h" 8#include "core/hle/service/acc/profile_manager.h"
9#include "core/perf_stats.h" 9#include "core/perf_stats.h"
10#include "frontend_common/content_manager.h"
10#include "jni/applets/software_keyboard.h" 11#include "jni/applets/software_keyboard.h"
11#include "jni/emu_window/emu_window.h" 12#include "jni/emu_window/emu_window.h"
12#include "video_core/rasterizer_interface.h" 13#include "video_core/rasterizer_interface.h"
@@ -29,7 +30,6 @@ public:
29 void SetNativeWindow(ANativeWindow* native_window); 30 void SetNativeWindow(ANativeWindow* native_window);
30 void SurfaceChanged(); 31 void SurfaceChanged();
31 32
32 int InstallFileToNand(std::string filename, std::string file_extension);
33 void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir, 33 void InitializeGpuDriver(const std::string& hook_lib_dir, const std::string& custom_driver_dir,
34 const std::string& custom_driver_name, 34 const std::string& custom_driver_name,
35 const std::string& file_redirect_dir); 35 const std::string& file_redirect_dir);