From 1aed8ce7b11ab7a0905148bcea27dd0c03e26f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 5 Jun 2021 14:03:06 +0200 Subject: [PATCH] Add content URI support to LocalFileLoader, remove ContentUriFileLoader --- Core/FileLoaders/LocalFileLoader.cpp | 42 ++++++++++++++++++++++------ Core/FileLoaders/LocalFileLoader.h | 9 +++--- android/jni/app-android.cpp | 38 ++++--------------------- 3 files changed, 43 insertions(+), 46 deletions(-) diff --git a/Core/FileLoaders/LocalFileLoader.cpp b/Core/FileLoaders/LocalFileLoader.cpp index df3593c585..d0c4c6828c 100644 --- a/Core/FileLoaders/LocalFileLoader.cpp +++ b/Core/FileLoaders/LocalFileLoader.cpp @@ -25,6 +25,10 @@ #include "Common/File/DirListing.h" #include "Core/FileLoaders/LocalFileLoader.h" +#if PPSSPP_PLATFORM(ANDROID) +#include "android/jni/app-android.h" +#endif + #ifdef _WIN32 #include "Common/CommonWindows.h" #else @@ -32,11 +36,6 @@ #endif #ifndef _WIN32 -LocalFileLoader::LocalFileLoader(int fd, const Path &filename) : fd_(fd), filename_(filename), isOpenedByFd_(fd != -1) { - if (fd != -1) { - DetectSizeFd(); - } -} void LocalFileLoader::DetectSizeFd() { #if PPSSPP_PLATFORM(ANDROID) || (defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS < 64) @@ -52,11 +51,27 @@ void LocalFileLoader::DetectSizeFd() { #endif LocalFileLoader::LocalFileLoader(const Path &filename) - : filesize_(0), filename_(filename), isOpenedByFd_(false) { + : filesize_(0), filename_(filename) { if (filename.empty()) { ERROR_LOG(FILESYS, "LocalFileLoader can't load empty filenames"); return; } + +#if PPSSPP_PLATFORM(ANDROID) + if (filename.Type() == PathType::CONTENT_URI) { + int fd = Android_OpenContentUriFd(filename.ToString(), Android_OpenContentUriMode::READ); + INFO_LOG(SYSTEM, "Fd %d for content URI: '%s'", fd, filename.c_str()); + if (fd == -1) { + ERROR_LOG(FILESYS, "LoadFileLoader failed to open content URI: '%s'", filename.c_str()); + return; + } + fd_ = fd; + isOpenedByFd_ = true; + DetectSizeFd(); + return; + } +#endif + #ifndef _WIN32 fd_ = open(filename.c_str(), O_RDONLY | O_CLOEXEC); @@ -106,14 +121,18 @@ bool LocalFileLoader::Exists() { // If we couldn't open it for reading, we say it does not exist. #ifndef _WIN32 if (isOpenedByFd_) { - return true; + return fd_ != -1; } if (fd_ != -1 || IsDirectory()) { #else if (handle_ != INVALID_HANDLE_VALUE || IsDirectory()) { #endif File::FileInfo info; - return File::GetFileInfo(filename_, &info); + if (File::GetFileInfo(filename_, &info)) { + return info.exists; + } else { + return false; + } } return false; } @@ -121,7 +140,7 @@ bool LocalFileLoader::Exists() { bool LocalFileLoader::IsDirectory() { File::FileInfo info; if (File::GetFileInfo(filename_, &info)) { - return info.isDirectory; + return info.exists && info.isDirectory; } return false; } @@ -134,6 +153,11 @@ size_t LocalFileLoader::ReadAt(s64 absolutePos, size_t bytes, size_t count, void if (bytes == 0) return 0; + if (filesize_ == 0) { + ERROR_LOG(FILESYS, "ReadAt from 0-sized file: %s", filename_.c_str()); + return 0; + } + #if PPSSPP_PLATFORM(SWITCH) // Toolchain has no fancy IO API. We must lock. std::lock_guard guard(readLock_); diff --git a/Core/FileLoaders/LocalFileLoader.h b/Core/FileLoaders/LocalFileLoader.h index 9ed9b185fa..9e1f37c10f 100644 --- a/Core/FileLoaders/LocalFileLoader.h +++ b/Core/FileLoaders/LocalFileLoader.h @@ -30,7 +30,6 @@ typedef void *HANDLE; class LocalFileLoader : public FileLoader { public: LocalFileLoader(const Path &filename); - LocalFileLoader(const int fd, const Path &filename); virtual ~LocalFileLoader(); virtual bool Exists() override; @@ -44,12 +43,12 @@ public: private: #ifndef _WIN32 void DetectSizeFd(); - int fd_; + int fd_ = -1; #else - HANDLE handle_; + HANDLE handle_ = 0; #endif - u64 filesize_; + u64 filesize_ = 0; Path filename_; std::mutex readLock_; - bool isOpenedByFd_; + bool isOpenedByFd_ = false; }; diff --git a/android/jni/app-android.cpp b/android/jni/app-android.cpp index 5a5448e6e3..76fbfba0d5 100644 --- a/android/jni/app-android.cpp +++ b/android/jni/app-android.cpp @@ -337,6 +337,9 @@ std::vector Android_ListContentUri(const std::string &path) { return std::vector(); } auto env = getEnv(); + + double start = time_now_d(); + jstring param = env->NewStringUTF(path.c_str()); jobject retval = env->CallObjectMethod(nativeActivity, listContentUriDir, param); @@ -357,6 +360,9 @@ std::vector Android_ListContentUri(const std::string &path) { env->DeleteLocalRef(str); } env->DeleteLocalRef(fileList); + + double elapsed = time_now_d() - start; + INFO_LOG(FILESYS, "Listing directory on content URI took %0.3f s"); return items; } @@ -380,33 +386,6 @@ int64_t Android_GetFreeSpaceByFilePath(const std::string &filePath) { return env->CallLongMethod(nativeActivity, filePathGetFreeStorageSpace, param); } - -class ContentURIFileLoader : public ProxiedFileLoader { -public: - ContentURIFileLoader(const Path &filename) - : ProxiedFileLoader(nullptr) { // we overwrite the nullptr below - int fd = Android_OpenContentUriFd(filename.ToString(), Android_OpenContentUriMode::READ); - INFO_LOG(SYSTEM, "Fd %d for content URI: '%s'", fd, filename.c_str()); - backend_ = new LocalFileLoader(fd, filename); - } - - bool ExistsFast() override { - if (!nativeActivity) { - // Assume it does if we don't have a NativeActivity right now. - return true; - } - return backend_->ExistsFast(); - } -}; - -class AndroidContentLoaderFactory : public FileLoaderFactory { -public: - AndroidContentLoaderFactory() {} - FileLoader *ConstructFileLoader(const Path &filename) override { - return new ContentURIFileLoader(filename); - } -}; - JNIEnv* getEnv() { JNIEnv *env; int status = gJvm->GetEnv((void**)&env, JNI_VERSION_1_6); @@ -851,11 +830,6 @@ extern "C" void Java_org_ppsspp_ppsspp_NativeApp_init NativeInit((int)args.size(), &args[0], user_data_path.c_str(), externalStorageDir.c_str(), cacheDir.c_str()); - std::unique_ptr factory(new AndroidContentLoaderFactory()); - - // Register a content URI file loader. - RegisterFileLoaderFactory("content://", std::move(factory)); - // No need to use EARLY_LOG anymore. retry: