Skip to content

Commit

Permalink
More usage of URI-base-SAF-API (instead of DocumentFile) in SAF to av…
Browse files Browse the repository at this point in the history
…oid calls to listFiles() which is very slow, but use cursor to list children, see GH issues wolpi#372 and wolpi#376
  • Loading branch information
wolpi authored and lmagyar committed Oct 19, 2024
1 parent ae8a6b7 commit 3bbfb0d
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 7 deletions.
1 change: 1 addition & 0 deletions primitiveFTPd/src/org/primftpd/filesystem/RoSafFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public abstract class RoSafFile<TMina, TFileSystemView extends RoSafFileSystemVi
private boolean writable;
private boolean deletable;

static final int CURSOR_INDEX_ID = 0;
static final int CURSOR_INDEX_NAME = 1;
static final String[] SAF_QUERY_COLUMNS = {
DocumentsContract.Document.COLUMN_DOCUMENT_ID,
Expand Down
63 changes: 56 additions & 7 deletions primitiveFTPd/src/org/primftpd/filesystem/SafFile.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package org.primftpd.filesystem;

import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.DocumentsContract;
import android.widget.Toast;

import org.primftpd.events.ClientActionEvent;
Expand Down Expand Up @@ -80,6 +83,10 @@ public SafFile(
this.parentNonexistentDirs = parentNonexistentDirs;
}

protected final Uri getStartUrl() {
return getFileSystemView().getStartUrl();
}

private boolean mkParentNonexistentDirs() {
if (0 < parentNonexistentDirs.size()) {
DocumentFile parentDoc = parentDocumentFile;
Expand Down Expand Up @@ -216,18 +223,60 @@ public List<TMina> listFiles() {
logger.trace("[{}] listFiles()", name);
postClientAction(ClientActionEvent.ClientAction.LIST_DIR);

DocumentFile[] children = documentFile.listFiles();
List<TMina> result = new ArrayList<>(children.length);
for (DocumentFile child : children) {
String absPath = this.absPath.endsWith("/")
? this.absPath + child.getName()
: this.absPath + "/" + child.getName();
result.add(createFile(absPath, documentFile, child));
// listFiles() is very slow, use URI-based-SAF-API as in RoSAF instead
// DocumentFile[] children = documentFile.listFiles();
// List<TMina> result = new ArrayList<>(children.length);
// for (DocumentFile child : children) {
// String absPath = this.absPath.endsWith("/")
// ? this.absPath + child.getName()
// : this.absPath + "/" + child.getName();
// result.add(createFile(absPath, documentFile, child));
// }

List<TMina> result = new ArrayList<>();
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
Uri startUrl = getStartUrl();
Context context = getPftpdService().getContext();

Cursor childCursor = null;
try {
String documentId = DocumentsContract.getDocumentId(documentFile.getUri());
Uri childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(
startUrl,
documentId);
childCursor = context.getContentResolver().query(
childrenUri,
RoSafFile.SAF_QUERY_COLUMNS,
null,
null,
null);
while (childCursor.moveToNext()) {
String absPath = this.absPath.endsWith("/")
? this.absPath + childCursor.getString(RoSafFile.CURSOR_INDEX_NAME)
: this.absPath + "/" + childCursor.getString(RoSafFile.CURSOR_INDEX_NAME);
String childId = childCursor.getString(RoSafFile.CURSOR_INDEX_ID);
Uri childUri = DocumentsContract.buildDocumentUriUsingTree(startUrl, childId);
DocumentFile childDocFile = DocumentFile.fromTreeUri(context, childUri);
result.add(createFile(absPath, documentFile, childDocFile));
}
} catch (Exception e) {
logger.error("", e);
Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show();
} finally {
closeQuietly(childCursor);
}
}

logger.trace(" [{}] listFiles(): num children: {}", name, result.size());
return result;
}

private void closeQuietly(Cursor cursor) {
if (cursor != null) {
cursor.close();
}
}

public OutputStream createOutputStream(long offset) throws IOException {
logger.trace("[{}] createOutputStream(offset: {})", name, offset);
postClientAction(ClientActionEvent.ClientAction.UPLOAD);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public SafFileSystemView(PftpdService pftpdService, Uri startUrl) {
this.timeResolution = StorageManagerUtil.getFilesystemTimeResolutionForTreeUri(startUrl);
}

public final Uri getStartUrl() {
return startUrl;
}

protected abstract TFile createFile(
String absPath,
DocumentFile parentDocumentFile,
Expand Down

0 comments on commit 3bbfb0d

Please sign in to comment.