Skip to content

Commit

Permalink
#169: saf-(DocumentFile) Performance improvements. Media scanner now …
Browse files Browse the repository at this point in the history
…processes 120 photos per minute (was 30 per minute before)
  • Loading branch information
k3b committed Mar 9, 2021
1 parent c955404 commit dd2aa8f
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 16 deletions.
64 changes: 52 additions & 12 deletions app/src/main/java/de/k3b/android/io/DocumentFileTranslator.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.Map;

import de.k3b.io.filefacade.FileFacade;
import de.k3b.media.PhotoPropertiesUtil;

/**
* Handles Translation from File to android specific DocumentFileUtils
Expand Down Expand Up @@ -63,9 +64,16 @@ public class DocumentFileTranslator {
private int dirCacheGeneratetionID = dirCacheGlobalGeneratetionID;

/**
* Mapping from known File to DocumentFile translation
* Mapping from known File to DocumentFile-Directory translation
*/
private final Map<File, DocumentFile> dirCache = new HashMap<>();

/**
* Mapping from local file name inside lastParentFile to photo-related-DocumentFiles
*/
private final File lastParentFile = null;
private final HashMap<String, DocumentFile> lastChildDocFiles = new HashMap<>();

private static final File internalRootCandidate = new File("/storage/emulated/0");
// for debugging
private static int id = 1;
Expand Down Expand Up @@ -173,22 +181,57 @@ public DocumentFileTranslator add(File directory, DocumentFile documentFileDir)
return this;
}

private DocumentFile getDocumentFileOrDirImpl(File fileOrDir) {
private DocumentFile getDocumentFileOrDirImpl(File fileOrDir, boolean isDir) {
DocumentFile result = null;
if (fileOrDir != null) {
result = getFromCache(fileOrDir);
if (result == null) {
DocumentFile parent = getDocumentFileOrDirImpl(fileOrDir.getParentFile());
DocumentFile parent = getDocumentFileOrDirImpl(fileOrDir.getParentFile(), true);
if (parent != null) {
result = parent.findFile(fileOrDir.getName());
result = findFile(parent, fileOrDir, isDir);
}
}
}
return result;
}

if ((result != null) && result.isDirectory()) {
add(fileOrDir, result);
private DocumentFile findFile(DocumentFile parentDoc, File fileOrDir, boolean isDir) {
String displayName = fileOrDir.getName();
File parentFile = fileOrDir.getParentFile();
if (isDir) {
// The original parentDoc.findFile(fileOrDir.getName()) is implemented
// as expensive, frequent called parentDoc.listFiles().
// Optimisation: Sideeffect fill the dir cache while searching for file.
DocumentFile foundDoc = null;
for (DocumentFile childDoc : parentDoc.listFiles()) {
String childDocName = childDoc.getName();
if (foundDoc == null && displayName.equals(childDocName)) {
foundDoc = childDoc;
}
if (childDoc.isDirectory()) {
add(new File(parentFile, childDocName), foundDoc);
}
}
return foundDoc;
} else {
if (!parentFile.equals(lastParentFile)) {
lastChildDocFiles.clear();
for (DocumentFile childDoc : parentDoc.listFiles()) {
if (childDoc.isFile()) {
String childDocName = childDoc.getName().toLowerCase();
if (PhotoPropertiesUtil.isImage(childDocName, PhotoPropertiesUtil.IMG_TYPE_ALL | PhotoPropertiesUtil.IMG_TYPE_XMP)) {
lastChildDocFiles.put(childDocName, childDoc);
}
}
}

}

if (PhotoPropertiesUtil.isImage(displayName, PhotoPropertiesUtil.IMG_TYPE_ALL | PhotoPropertiesUtil.IMG_TYPE_XMP)) {
return lastChildDocFiles.get(displayName.toLowerCase());
}
return parentDoc.findFile(fileOrDir.getName());
}
return result;
}

/**
Expand All @@ -203,13 +246,10 @@ public DocumentFile getOrCreateDirectory(File directory) {
if (result == null) {
DocumentFile parent = getOrCreateDirectory(directory.getParentFile());
if ((parent != null) && parent.isDirectory()) {
result = parent.findFile(directory.getName());
result = findFile(parent, directory, true);

if (result == null) {
result = parent.createDirectory(directory.getName());
}

if (result != null) {
add(directory, result);
}
}
Expand All @@ -232,7 +272,7 @@ public DocumentFile getDocumentFileOrDirOrNull(File fileOrDir, Boolean isDir) {
final String context = FileFacade.debugLogFacade ? (mDebugPrefix + "getDocumentFile('"
+ path + "') ") : null;
try {
result = getDocumentFileOrDirImpl(fileOrDir);
result = getDocumentFileOrDirImpl(fileOrDir, isDir == Boolean.TRUE);
if ((context != null) && (result == null)) {
Log.i(TAG, context + "not found");
}
Expand Down
1 change: 1 addition & 0 deletions fastlane/metadata/android/en-US/changelogs/48.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ Changes from 0.8.3 to ???
* #169: Add sd-card-saf-write-permission support (experimental)
* #155: Android-10 support (experimental)
* #173: incremental media scanner
* #173: Ao10-performance-Optimized-Mediacanner
* #180: Fixed: Show image with uri that cannot be translated to file (i.e. WhatsApp show photo in gallery)
* #93: Bugfix crash in Autoprocessing with date-based-rename when photo has no dateCreated
* fixed CSV IPhotoProperties import
Expand Down
16 changes: 12 additions & 4 deletions fotolib2/src/main/java/de/k3b/media/PhotoPropertiesUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,15 @@ public class PhotoPropertiesUtil {
* with this extension. */
public static final String EXT_JPG_PRIVATE = ".jpg-p";

/** types of images currently supported */
public static final int IMG_TYPE_ALL = 0xffff;
public static final int IMG_TYPE_JPG = 0x0001; // jp(e)g
/**
* types of images currently supported
*/
public static final int IMG_TYPE_ALL = 0x7fff;
public static final int IMG_TYPE_JPG = 0x0001; // jp(e)g
public static final int IMG_TYPE_COMPRESSED_NON_JPG = 0x0010; // png, gif, ...
public static final int IMG_TYPE_UNCOMPRESSED_NON_JPG = 0x0020; // BMP, TIFF, ...
public static final int IMG_TYPE_PRIVATE = 0x1000; // jpg-p
public static final int IMG_TYPE_PRIVATE = 0x1000; // jpg-p
public static final int IMG_TYPE_XMP = 0x8000; // xmp

public static final int IMG_TYPE_COMPRESSED = IMG_TYPE_JPG | IMG_TYPE_COMPRESSED_NON_JPG | IMG_TYPE_PRIVATE;

Expand Down Expand Up @@ -316,6 +319,11 @@ public static boolean isImage(String path, int imageTypeFlags) {
return true;
}

if ((IMG_TYPE_XMP == (imageTypeFlags & IMG_TYPE_XMP)) &&
(lcPath.endsWith(".xmp"))) {
return true;
}

return (IMG_TYPE_PRIVATE == (imageTypeFlags & IMG_TYPE_PRIVATE)) &&
isPrivateImage(lcPath);

Expand Down

0 comments on commit dd2aa8f

Please sign in to comment.