Add content URI support to LocalFileLoader, remove ContentUriFileLoader

This commit is contained in:
Henrik Rydgård 2021-06-05 14:03:06 +02:00
parent ad72dc8748
commit 1aed8ce7b1
3 changed files with 43 additions and 46 deletions

View File

@ -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<std::mutex> guard(readLock_);

View File

@ -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;
};

View File

@ -337,6 +337,9 @@ std::vector<File::FileInfo> Android_ListContentUri(const std::string &path) {
return std::vector<File::FileInfo>();
}
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<File::FileInfo> 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<FileLoaderFactory> factory(new AndroidContentLoaderFactory());
// Register a content URI file loader.
RegisterFileLoaderFactory("content://", std::move(factory));
// No need to use EARLY_LOG anymore.
retry: