diff options
| author | JosJuice <josjuice@gmail.com> | 2020-11-04 20:59:39 +0100 |
|---|---|---|
| committer | JosJuice <josjuice@gmail.com> | 2020-11-06 17:40:03 +0100 |
| commit | 70df5446d3f0bc203363ad74e737fd772e8e9c2c (patch) | |
| tree | e840595646f5fd6ae8293def17ee60973cf37ea2 /Source/Android | |
| parent | 6a4ac74ec407a20b0347c4c764ca528e8d692cc1 (diff) | |
Android: Make the handling of SAF open modes more robust
Diffstat (limited to 'Source/Android')
3 files changed, 39 insertions, 13 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java index 83b9c585c9..dc4472a212 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java @@ -17,7 +17,9 @@ public class ContentHandler return DolphinApplication.getAppContext().getContentResolver() .openFileDescriptor(Uri.parse(uri), mode).detachFd(); } - catch (FileNotFoundException | NullPointerException e) + // Some content providers throw IllegalArgumentException for invalid modes, + // despite the documentation saying that invalid modes result in a FileNotFoundException + catch (FileNotFoundException | IllegalArgumentException | NullPointerException e) { return -1; } diff --git a/Source/Android/jni/AndroidCommon/AndroidCommon.cpp b/Source/Android/jni/AndroidCommon/AndroidCommon.cpp index 73405b6d8e..344e34c7b6 100644 --- a/Source/Android/jni/AndroidCommon/AndroidCommon.cpp +++ b/Source/Android/jni/AndroidCommon/AndroidCommon.cpp @@ -10,6 +10,7 @@ #include <jni.h> +#include "Common/Assert.h" #include "Common/StringUtil.h" #include "jni/AndroidCommon/IDCache.h" @@ -42,21 +43,35 @@ std::vector<std::string> JStringArrayToVector(JNIEnv* env, jobjectArray array) return result; } -int OpenAndroidContent(const std::string& uri, const std::string& mode) +bool IsPathAndroidContent(const std::string& uri) { - JNIEnv* env = IDCache::GetEnvForThread(); - const jint fd = env->CallStaticIntMethod(IDCache::GetContentHandlerClass(), - IDCache::GetContentHandlerOpenFd(), ToJString(env, uri), - ToJString(env, mode)); + return StringBeginsWith(uri, "content://"); +} + +std::string OpenModeToAndroid(std::string mode) +{ + // The 'b' specifier is not supported. Since we're on POSIX, it's fine to just skip it. + if (!mode.empty() && mode.back() == 'b') + mode.pop_back(); - // We can get an IllegalArgumentException when passing an invalid mode - if (env->ExceptionCheck()) - { - env->ExceptionDescribe(); - abort(); - } + if (mode == "r+") + mode = "rw"; + else if (mode == "w+") + mode = "rwt"; + else if (mode == "a+") + mode = "rwa"; + else if (mode == "a") + mode = "wa"; - return fd; + return mode; +} + +int OpenAndroidContent(const std::string& uri, const std::string& mode) +{ + JNIEnv* env = IDCache::GetEnvForThread(); + return env->CallStaticIntMethod(IDCache::GetContentHandlerClass(), + IDCache::GetContentHandlerOpenFd(), ToJString(env, uri), + ToJString(env, mode)); } bool DeleteAndroidContent(const std::string& uri) diff --git a/Source/Android/jni/AndroidCommon/AndroidCommon.h b/Source/Android/jni/AndroidCommon/AndroidCommon.h index ca8245182d..967933bdf8 100644 --- a/Source/Android/jni/AndroidCommon/AndroidCommon.h +++ b/Source/Android/jni/AndroidCommon/AndroidCommon.h @@ -12,5 +12,14 @@ std::string GetJString(JNIEnv* env, jstring jstr); jstring ToJString(JNIEnv* env, const std::string& str); std::vector<std::string> JStringArrayToVector(JNIEnv* env, jobjectArray array); +// Returns true if the given path should be opened as Android content instead of a normal file. +bool IsPathAndroidContent(const std::string& uri); + +// Turns a C/C++ style mode (e.g. "rb") into one which can be used with OpenAndroidContent. +std::string OpenModeToAndroid(std::string mode); + +// Opens a given file and returns a file descriptor. int OpenAndroidContent(const std::string& uri, const std::string& mode); + +// Deletes a given file. bool DeleteAndroidContent(const std::string& uri); |
