From d6187f7af779d7ef7873879004542c3119ea38c0 Mon Sep 17 00:00:00 2001 From: gabriel Date: Sat, 3 Feb 2024 01:25:10 -0400 Subject: [PATCH] basic saf impl --- include/android_utils.hpp | 6 ++++ src/io_file.cpp | 15 +++++++- src/jni_driver.cpp | 18 ++++++++++ .../com/panda3ds/pandroid/AlberDriver.java | 34 +++++++++++++++++++ .../panda3ds/pandroid/utils/FileUtils.java | 5 +++ .../panda3ds/pandroid/utils/GameUtils.java | 4 ++- 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 include/android_utils.hpp diff --git a/include/android_utils.hpp b/include/android_utils.hpp new file mode 100644 index 00000000..f1464161 --- /dev/null +++ b/include/android_utils.hpp @@ -0,0 +1,6 @@ +#pragma once + +class AndroidUtils { + public: + static int openDocument(const char* directory, const char* mode); +}; \ No newline at end of file diff --git a/src/io_file.cpp b/src/io_file.cpp index 1f794284..74a3f51a 100644 --- a/src/io_file.cpp +++ b/src/io_file.cpp @@ -21,6 +21,10 @@ #include // For ftruncate #endif +#ifdef __ANDROID__ +#include "android_utils.hpp" +#endif + IOFile::IOFile(const std::filesystem::path& path, const char* permissions) : handle(nullptr) { open(path, permissions); } bool IOFile::open(const std::filesystem::path& path, const char* permissions) { @@ -34,8 +38,17 @@ bool IOFile::open(const char* filename, const char* permissions) { if (isOpen()) { close(); } + #ifdef __ANDROID__ + std::string path(filename); - handle = std::fopen(filename, permissions); + if(path.find("://") != std::string::npos){ //IF SAF URI + handle = fdopen(AndroidUtils::openDocument(filename, permissions), permissions); + } else { + handle = std::fopen(filename, permissions); + } + #else + handle = std::fopen(filename, permissions); + #endif return isOpen(); } diff --git a/src/jni_driver.cpp b/src/jni_driver.cpp index 1af325e3..bde4824a 100644 --- a/src/jni_driver.cpp +++ b/src/jni_driver.cpp @@ -7,6 +7,7 @@ #include "emulator.hpp" #include "renderer_gl/renderer_gl.hpp" #include "services/hid.hpp" +#include "android_utils.hpp" std::unique_ptr emulator = nullptr; HIDService* hidService = nullptr; @@ -33,6 +34,23 @@ JNIEnv* jniEnv() { return env; } +int AndroidUtils::openDocument(const char* path, const char* perms) { + auto env = jniEnv(); + + auto clazz = env->FindClass("com/panda3ds/pandroid/AlberDriver"); + auto method = env->GetStaticMethodID(clazz, "openDocument", "(Ljava/lang/String;Ljava/lang/String;)I"); + + jstring uri = env->NewStringUTF(path); + jstring jmode = env->NewStringUTF(perms); + + jint result = env->CallStaticIntMethod(clazz, method, uri, jmode); + + env->DeleteLocalRef(uri); + env->DeleteLocalRef(jmode); + + return (int)result; +} + extern "C" { #define MAKE_SETTING(functionName, type, settingName) \ diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/AlberDriver.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/AlberDriver.java index 7367a447..2a44cb43 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/AlberDriver.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/AlberDriver.java @@ -1,7 +1,21 @@ package com.panda3ds.pandroid; +import android.content.Context; +import android.net.Uri; +import android.os.ParcelFileDescriptor; +import android.os.Process; +import android.system.Os; +import android.system.OsConstants; import android.util.Log; +import com.panda3ds.pandroid.app.PandroidApplication; +import com.panda3ds.pandroid.utils.Constants; +import com.panda3ds.pandroid.utils.FileUtils; +import com.panda3ds.pandroid.utils.GameUtils; + +import java.io.File; +import java.util.Objects; + public class AlberDriver { AlberDriver() { super(); } @@ -24,5 +38,25 @@ public class AlberDriver { public static native void setShaderJitEnabled(boolean enable); + public static int openDocument(String path, String mode){ + try { + mode = mode.substring(0,1); + Context context = PandroidApplication.getAppContext(); + Uri uri = FileUtils.obtainUri(path); + ParcelFileDescriptor parcel; + if (Objects.equals(uri.getScheme(), "game")) { + uri = FileUtils.obtainUri(GameUtils.getCurrentGame().getRomPath()); + parcel = context.getContentResolver().openFileDescriptor(uri, "r"); + } else { + parcel = context.getContentResolver().openFileDescriptor(uri, mode); + } + int fd = parcel.detachFd(); + parcel.close(); + + return fd; + } catch (Exception e){ + throw new RuntimeException(e); + } + } static { System.loadLibrary("Alber"); } } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/FileUtils.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/FileUtils.java index 1746f1c9..d647077f 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/FileUtils.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/FileUtils.java @@ -5,6 +5,7 @@ import android.content.Intent; import android.net.Uri; import android.os.ParcelFileDescriptor; import android.system.Os; +import android.system.OsConstants; import android.util.Log; import androidx.documentfile.provider.DocumentFile; @@ -243,4 +244,8 @@ public class FileUtils { return result; } + + public static Uri obtainUri(String path) { + return parseFile(path).getUri(); + } } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/GameUtils.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/GameUtils.java index b763f7b2..ee79e826 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/GameUtils.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/utils/GameUtils.java @@ -40,7 +40,9 @@ public class GameUtils { public static void launch(Context context, GameMetadata game) { currentGame = game; - String path = FileUtils.obtainRealPath(game.getRomPath()); + String[] parts = Uri.decode(game.getRomPath()).split("/"); + String name = parts[parts.length-1]; + String path = "game://internal/"+name; context.startActivity(new Intent(context, GameActivity.class).putExtra(Constants.ACTIVITY_PARAMETER_PATH, path)); }