Add untested function Android_ComputeRecursiveDirectorySize

This commit is contained in:
Henrik Rydgård 2021-09-11 16:36:35 +02:00
parent cd79a1d92f
commit e842d395fa
4 changed files with 69 additions and 2 deletions

View File

@ -20,6 +20,7 @@ static jmethodID contentUriFileExists;
static jmethodID contentUriGetFreeStorageSpace;
static jmethodID filePathGetFreeStorageSpace;
static jmethodID isExternalStoragePreservedLegacy;
static jmethodID computeRecursiveDirectorySize;
static jobject g_nativeActivity;
@ -54,6 +55,8 @@ void Android_RegisterStorageCallbacks(JNIEnv * env, jobject obj) {
_dbg_assert_(filePathGetFreeStorageSpace);
isExternalStoragePreservedLegacy = env->GetMethodID(env->GetObjectClass(obj), "isExternalStoragePreservedLegacy", "()Z");
_dbg_assert_(isExternalStoragePreservedLegacy);
computeRecursiveDirectorySize = env->GetMethodID(env->GetObjectClass(obj), "computeRecursiveDirectorySize", "(Ljava/lang/String;)J");
_dbg_assert_(computeRecursiveDirectorySize);
}
bool Android_IsContentUri(const std::string &filename) {
@ -258,6 +261,16 @@ int64_t Android_GetFreeSpaceByFilePath(const std::string &filePath) {
return env->CallLongMethod(g_nativeActivity, filePathGetFreeStorageSpace, param);
}
int64_t Android_ComputeRecursiveDirectorySize(const std::string &uri) {
if (!g_nativeActivity) {
return false;
}
auto env = getEnv();
jstring param = env->NewStringUTF(uri.c_str());
return env->CallLongMethod(g_nativeActivity, computeRecursiveDirectorySize, param);
}
bool Android_IsExternalStoragePreservedLegacy() {
if (!g_nativeActivity) {
return false;

View File

@ -49,6 +49,7 @@ StorageError Android_RemoveFile(const std::string &fileUri);
StorageError Android_RenameFileTo(const std::string &fileUri, const std::string &newName);
bool Android_GetFileInfo(const std::string &fileUri, File::FileInfo *info);
bool Android_FileExists(const std::string &fileUri);
int64_t Android_ComputeRecursiveDirectorySize(const std::string &fileUri);
int64_t Android_GetFreeSpaceByContentUri(const std::string &uri);
int64_t Android_GetFreeSpaceByFilePath(const std::string &filePath);
bool Android_IsExternalStoragePreservedLegacy();
@ -72,6 +73,7 @@ inline StorageError Android_RemoveFile(const std::string &fileUri) { return Stor
inline StorageError Android_RenameFileTo(const std::string &fileUri, const std::string &newName) { return StorageError::UNKNOWN; }
inline bool Android_GetFileInfo(const std::string &fileUri, File::FileInfo *info) { return false; }
inline bool Android_FileExists(const std::string &fileUri) { return false; }
inline int64_t Android_GetRecursiveDirectorySize(const std::string &fileUri) { return -1; }
inline int64_t Android_GetFreeSpaceByContentUri(const std::string &uri) { return -1; }
inline int64_t Android_GetFreeSpaceByFilePath(const std::string &filePath) { return -1; }
inline bool Android_IsExternalStoragePreservedLegacy() { return false; }

View File

@ -343,13 +343,11 @@ public:
void Run() override {
// An early-return will result in the destructor running, where we can set
// flags like working and pending.
if (!info_->LoadFromPath(gamePath_)) {
return;
}
// In case of a remote file, check if it actually exists before locking.
// This is likely not necessary at a
if (!info_->GetFileLoader()->Exists()) {
return;
}

View File

@ -178,6 +178,60 @@ public class PpssppActivity extends NativeActivity {
return str + size + "|" + documentName + "|" + lastModified;
}
private long directorySizeRecursion(Uri uri, String documentId) {
Cursor c = null;
try {
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 Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, documentId);
c = resolver.query(childrenUri, columns, null, null, null);
long sizeSum = 0;
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;
}
} else {
final long fileSize = c.getLong(1);
sizeSum += fileSize;
}
}
return sizeSum;
} catch (Exception e) {
return -1;
} finally {
if (c != null) {
c.close();
}
}
}
public long computeRecursiveDirectorySize(String uriString) {
try {
Uri uri = Uri.parse(uriString);
String documentId = DocumentsContract.getDocumentId(uri);
long totalSize = directorySizeRecursion(uri, documentId);
Log.i(TAG, "directorySizeRecursion(" + uriString + ") returned " + totalSize);
return totalSize;
}
catch (Exception e) {
Log.e(TAG, "computeRecursiveSize exception: " + e.toString());
return -1;
}
}
// TODO: Maybe add a cheaper version that doesn't extract all the file information?
// TODO: Replace with a proper query:
// * https://stackoverflow.com/questions/42186820/documentfile-is-very-slow