Fix the Android recursive size computation and hook it up.

This commit is contained in:
Henrik Rydgård 2021-09-11 17:50:07 +02:00
parent 48310d15a9
commit fcc0337576
8 changed files with 44 additions and 36 deletions

View File

@ -285,19 +285,6 @@ bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const ch
return true;
}
int64_t GetDirectoryRecursiveSize(const Path &path, const char *filter, int flags) {
std::vector<FileInfo> 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<std::string> GetWindowsDrives()

View File

@ -35,7 +35,6 @@ enum {
};
bool GetFilesInDir(const Path &directory, std::vector<FileInfo> *files, const char *filter = nullptr, int flags = 0);
int64_t GetDirectoryRecursiveSize(const Path &path, const char *filter = nullptr, int flags = 0);
std::vector<File::FileInfo> ApplyFilter(std::vector<File::FileInfo> files, const char *filter);
#ifdef _WIN32

View File

@ -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> 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) {

View File

@ -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<PSPFileInfo> DirectoryFileSystem::GetDirListing(std::string path) {
std::vector<PSPFileInfo> myVector;

View File

@ -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 {

View File

@ -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();

View File

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

View File

@ -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<Uri> childDirs = new ArrayList<Uri>();
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;
}