summaryrefslogtreecommitdiff
path: root/Source/Android
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2020-11-04 20:59:39 +0100
committerJosJuice <josjuice@gmail.com>2020-11-06 17:40:03 +0100
commit70df5446d3f0bc203363ad74e737fd772e8e9c2c (patch)
treee840595646f5fd6ae8293def17ee60973cf37ea2 /Source/Android
parent6a4ac74ec407a20b0347c4c764ca528e8d692cc1 (diff)
Android: Make the handling of SAF open modes more robust
Diffstat (limited to 'Source/Android')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/ContentHandler.java4
-rw-r--r--Source/Android/jni/AndroidCommon/AndroidCommon.cpp39
-rw-r--r--Source/Android/jni/AndroidCommon/AndroidCommon.h9
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);