From fcc0337576e5cf9eadcb15f433d93418d4c72254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sat, 11 Sep 2021 17:50:07 +0200 Subject: [PATCH] Fix the Android recursive size computation and hook it up. --- Common/File/DirListing.cpp | 13 ------- Common/File/DirListing.h | 1 - Common/File/FileUtil.cpp | 12 +++---- Core/FileSystems/DirectoryFileSystem.cpp | 12 +++++++ Core/FileSystems/DirectoryFileSystem.h | 2 +- UI/GameInfoCache.cpp | 2 +- UI/SavedataScreen.cpp | 3 +- .../src/org/ppsspp/ppsspp/PpssppActivity.java | 35 +++++++++++++------ 8 files changed, 44 insertions(+), 36 deletions(-) diff --git a/Common/File/DirListing.cpp b/Common/File/DirListing.cpp index 0d1d07ed7..b4b335266 100644 --- a/Common/File/DirListing.cpp +++ b/Common/File/DirListing.cpp @@ -285,19 +285,6 @@ bool GetFilesInDir(const Path &directory, std::vector *files, const ch return true; } -int64_t GetDirectoryRecursiveSize(const Path &path, const char *filter, int flags) { - std::vector fileInfo; - GetFilesInDir(path, &fileInfo, filter, flags); - int64_t sizeSum = 0; - for (const auto &finfo : fileInfo) { - if (!finfo.isDirectory) - sizeSum += finfo.size; - else - sizeSum += GetDirectoryRecursiveSize(finfo.fullName, filter, flags); - } - return sizeSum; -} - #if PPSSPP_PLATFORM(WINDOWS) // Returns a vector with the device names std::vector GetWindowsDrives() diff --git a/Common/File/DirListing.h b/Common/File/DirListing.h index 99c938630..c53d42058 100644 --- a/Common/File/DirListing.h +++ b/Common/File/DirListing.h @@ -35,7 +35,6 @@ enum { }; bool GetFilesInDir(const Path &directory, std::vector *files, const char *filter = nullptr, int flags = 0); -int64_t GetDirectoryRecursiveSize(const Path &path, const char *filter = nullptr, int flags = 0); std::vector ApplyFilter(std::vector files, const char *filter); #ifdef _WIN32 diff --git a/Common/File/FileUtil.cpp b/Common/File/FileUtil.cpp index 2de9d8959..a9b349811 100644 --- a/Common/File/FileUtil.cpp +++ b/Common/File/FileUtil.cpp @@ -327,20 +327,18 @@ std::string ResolvePath(const std::string &path) { static int64_t RecursiveSize(const Path &path) { // TODO: Some file systems can optimize this. std::vector fileInfo; - if (!GetFilesInDir(path, &fileInfo)) { + if (!GetFilesInDir(path, &fileInfo, nullptr, GETFILES_GETHIDDEN)) { return -1; } - int64_t result = 0; + int64_t sizeSum = 0; for (const auto &file : fileInfo) { - if (file.name == "." || file.name == "..") - continue; if (file.isDirectory) { - result += RecursiveSize(file.fullName); + sizeSum += RecursiveSize(file.fullName); } else { - result += file.size; + sizeSum += file.size; } } - return result; + return sizeSum; } uint64_t ComputeRecursiveDirectorySize(const Path &path) { diff --git a/Core/FileSystems/DirectoryFileSystem.cpp b/Core/FileSystems/DirectoryFileSystem.cpp index abad3b9b9..1da549931 100644 --- a/Core/FileSystems/DirectoryFileSystem.cpp +++ b/Core/FileSystems/DirectoryFileSystem.cpp @@ -878,6 +878,18 @@ static std::string SimulateVFATBug(std::string filename) { return filename; } +bool DirectoryFileSystem::ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) { + Path localPath = GetLocalPath(path); + + int64_t sizeTemp = File::ComputeRecursiveDirectorySize(localPath); + if (sizeTemp >= 0) { + *size = sizeTemp; + return true; + } else { + return false; + } +} + std::vector DirectoryFileSystem::GetDirListing(std::string path) { std::vector myVector; diff --git a/Core/FileSystems/DirectoryFileSystem.h b/Core/FileSystems/DirectoryFileSystem.h index daf900a16..fa2b24d01 100644 --- a/Core/FileSystems/DirectoryFileSystem.h +++ b/Core/FileSystems/DirectoryFileSystem.h @@ -116,7 +116,7 @@ public: u64 FreeSpace(const std::string &path) override; // TODO: Replace with optimized implementation. - bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override { return false; } + bool ComputeRecursiveDirSizeIfFast(const std::string &path, int64_t *size) override; private: struct OpenFileEntry { diff --git a/UI/GameInfoCache.cpp b/UI/GameInfoCache.cpp index 25c426f5d..e3bbfb34d 100644 --- a/UI/GameInfoCache.cpp +++ b/UI/GameInfoCache.cpp @@ -114,7 +114,7 @@ u64 GameInfo::GetGameSizeInBytes() { switch (fileType) { case IdentifiedFileType::PSP_PBP_DIRECTORY: case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY: - return File::GetDirectoryRecursiveSize(ResolvePBPDirectory(filePath_), nullptr, File::GETFILES_GETHIDDEN); + return File::ComputeRecursiveDirectorySize(ResolvePBPDirectory(filePath_)); default: return GetFileLoader()->FileSize(); diff --git a/UI/SavedataScreen.cpp b/UI/SavedataScreen.cpp index 747ebd5ed..cfd61045a 100644 --- a/UI/SavedataScreen.cpp +++ b/UI/SavedataScreen.cpp @@ -430,8 +430,7 @@ static time_t GetTotalSize(const SavedataButton *b) { switch (Identify_File(fileLoader.get(), &errorString)) { case IdentifiedFileType::PSP_PBP_DIRECTORY: case IdentifiedFileType::PSP_SAVEDATA_DIRECTORY: - return File::GetDirectoryRecursiveSize(ResolvePBPDirectory(b->GamePath()), nullptr, File::GETFILES_GETHIDDEN); - + return File::ComputeRecursiveDirectorySize(ResolvePBPDirectory(b->GamePath())); default: return fileLoader->FileSize(); } diff --git a/android/src/org/ppsspp/ppsspp/PpssppActivity.java b/android/src/org/ppsspp/ppsspp/PpssppActivity.java index 67b74014b..4a37e21e4 100644 --- a/android/src/org/ppsspp/ppsspp/PpssppActivity.java +++ b/android/src/org/ppsspp/ppsspp/PpssppActivity.java @@ -17,6 +17,8 @@ import android.database.Cursor; import android.provider.DocumentsContract; import android.os.Environment; import androidx.documentfile.provider.DocumentFile; + +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.UUID; import java.io.File; @@ -178,36 +180,48 @@ public class PpssppActivity extends NativeActivity { return str + size + "|" + documentName + "|" + lastModified; } - private long directorySizeRecursion(Uri uri, String documentId) { + private long directorySizeRecursion(Uri uri) { Cursor c = null; try { - Log.i(TAG, "recursing into " + uri.toString()); + // Log.i(TAG, "recursing into " + uri.toString()); final String[] columns = new String[]{ DocumentsContract.Document.COLUMN_DOCUMENT_ID, DocumentsContract.Document.COLUMN_SIZE, DocumentsContract.Document.COLUMN_MIME_TYPE, // check for MIME_TYPE_DIR }; final ContentResolver resolver = getContentResolver(); + final String documentId = DocumentsContract.getDocumentId(uri); final Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, documentId); c = resolver.query(childrenUri, columns, null, null, null); long sizeSum = 0; + + // Buffer the URIs so we only have one cursor active at once. I don't trust the storage framework + // to handle more than one... + ArrayList childDirs = new ArrayList(); + while (c.moveToNext()) { final String mimeType = c.getString(2); final boolean isDirectory = mimeType.equals(DocumentsContract.Document.MIME_TYPE_DIR); if (isDirectory) { final String childDocumentId = c.getString(0); - long dirSize = directorySizeRecursion( - DocumentsContract.buildDocumentUriUsingTree(uri, childDocumentId), - documentId - ); - if (dirSize >= 0) { - sizeSum += dirSize; - } + final Uri childUri = DocumentsContract.buildDocumentUriUsingTree(uri, childDocumentId); + childDirs.add(childUri); } else { final long fileSize = c.getLong(1); sizeSum += fileSize; } } + c.close(); + c = null; + + for (Uri childUri : childDirs) { + long dirSize = directorySizeRecursion(childUri); + if (dirSize >= 0) { + sizeSum += dirSize; + } else { + return dirSize; + } + } return sizeSum; } catch (Exception e) { return -1; @@ -221,8 +235,7 @@ public class PpssppActivity extends NativeActivity { public long computeRecursiveDirectorySize(String uriString) { try { Uri uri = Uri.parse(uriString); - String documentId = DocumentsContract.getDocumentId(uri); - long totalSize = directorySizeRecursion(uri, documentId); + long totalSize = directorySizeRecursion(uri); Log.i(TAG, "directorySizeRecursion(" + uriString + ") returned " + totalSize); return totalSize; }