Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28cfb113 authored by Mike Lockwood's avatar Mike Lockwood Committed by Android (Google) Code Review
Browse files

Merge "MediaScanner: Add support for scanning empty directories"

parents 43c0db48 076e05b4
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -71,7 +71,8 @@ public:
    bool addStringTag(const char* name, const char* value);
    void endFile();

    virtual bool scanFile(const char* path, long long lastModified, long long fileSize) = 0;
    virtual bool scanFile(const char* path, long long lastModified,
            long long fileSize, bool isDirectory) = 0;
    virtual bool handleStringTag(const char* name, const char* value) = 0;
    virtual bool setMimeType(const char* mimeType) = 0;
    virtual bool addNoMediaFolder(const char* path) = 0;
+63 −54
Original line number Diff line number Diff line
@@ -407,8 +407,13 @@ public class MediaScanner
        private long mFileSize;
        private String mWriter;

        public FileCacheEntry beginFile(String path, String mimeType, long lastModified, long fileSize) {
        public FileCacheEntry beginFile(String path, String mimeType, long lastModified,
                long fileSize, boolean isDirectory) {
            mMimeType = mimeType;
            mFileType = 0;
            mFileSize = fileSize;

            if (!isDirectory) {
                // special case certain file names
                // I use regionMatches() instead of substring() below
                // to avoid memory allocation
@@ -420,24 +425,23 @@ public class MediaScanner
                    }

                    // ignore album art files created by Windows Media Player:
                // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg and AlbumArt_{...}_Small.jpg
                    // Folder.jpg, AlbumArtSmall.jpg, AlbumArt_{...}_Large.jpg
                    // and AlbumArt_{...}_Small.jpg
                    if (path.regionMatches(true, path.length() - 4, ".jpg", 0, 4)) {
                        if (path.regionMatches(true, lastSlash + 1, "AlbumArt_{", 0, 10) ||
                                path.regionMatches(true, lastSlash + 1, "AlbumArt.", 0, 9)) {
                            return null;
                        }
                        int length = path.length() - lastSlash - 1;
                    if ((length == 17 && path.regionMatches(true, lastSlash + 1, "AlbumArtSmall", 0, 13)) ||
                            (length == 10 && path.regionMatches(true, lastSlash + 1, "Folder", 0, 6))) {
                        if ((length == 17 && path.regionMatches(
                                true, lastSlash + 1, "AlbumArtSmall", 0, 13)) ||
                                (length == 10
                                 && path.regionMatches(true, lastSlash + 1, "Folder", 0, 6))) {
                            return null;
                        }
                    }
                }

            mMimeType = mimeType;
            mFileType = 0;
            mFileSize = fileSize;

                // try mimeType first, if it is specified
                if (mimeType != null) {
                    mFileType = MediaFile.getFileTypeForMimeType(mimeType);
@@ -457,6 +461,7 @@ public class MediaScanner
                if (isDrmEnabled() && MediaFile.isDrmFileType(mFileType)) {
                    mFileType = getFileTypeFromDrm(path);
                }
            }

            String key = path;
            if (mMediaStoragePath != null && key.startsWith(mMediaStoragePath)) {
@@ -470,7 +475,9 @@ public class MediaScanner
            FileCacheEntry entry = mFileCache.get(key);
            if (entry == null) {
                Uri tableUri;
                if (MediaFile.isVideoFileType(mFileType)) {
                if (isDirectory) {
                    tableUri = mFilesUri;
                } else if (MediaFile.isVideoFileType(mFileType)) {
                    tableUri = mVideoUri;
                } else if (MediaFile.isImageFileType(mFileType)) {
                    tableUri = mImagesUri;
@@ -479,7 +486,8 @@ public class MediaScanner
                } else {
                    tableUri = mFilesUri;
                }
                entry = new FileCacheEntry(tableUri, 0, path, 0, 0);
                entry = new FileCacheEntry(tableUri, 0, path, 0,
                        (isDirectory ? MtpConstants.FORMAT_ASSOCIATION : 0));
                mFileCache.put(key, entry);
            }
            entry.mSeenInFileSystem = true;
@@ -514,22 +522,19 @@ public class MediaScanner
            return entry;
        }

        public void scanFile(String path, long lastModified, long fileSize) {
        public void scanFile(String path, long lastModified, long fileSize, boolean isDirectory) {
            // This is the callback funtion from native codes.
            // Log.v(TAG, "scanFile: "+path);
            doScanFile(path, null, lastModified, fileSize, false);
        }

        public void scanFile(String path, String mimeType, long lastModified, long fileSize) {
            doScanFile(path, mimeType, lastModified, fileSize, false);
            doScanFile(path, null, lastModified, fileSize, isDirectory, false);
        }

        public Uri doScanFile(String path, String mimeType, long lastModified,
                long fileSize, boolean scanAlways) {
                long fileSize, boolean isDirectory, boolean scanAlways) {
            Uri result = null;
//            long t1 = System.currentTimeMillis();
            try {
                FileCacheEntry entry = beginFile(path, mimeType, lastModified, fileSize);
                FileCacheEntry entry = beginFile(path, mimeType, lastModified,
                        fileSize, isDirectory);
                // rescan for metadata if file was modified since last scan
                if (entry != null && (entry.mLastModifiedChanged || scanAlways)) {
                    String lowpath = path.toLowerCase();
@@ -775,7 +780,11 @@ public class MediaScanner
                    values.put(MediaStore.MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, mMtpObjectHandle);
                }
                if (tableUri == mFilesUri) {
                    values.put(Files.FileColumns.FORMAT, MediaFile.getFormatCode(entry.mPath, mMimeType));
                    int format = entry.mFormat;
                    if (format == 0) {
                        format = MediaFile.getFormatCode(entry.mPath, mMimeType);
                    }
                    values.put(Files.FileColumns.FORMAT, format);
                }
                // new file, insert it
                result = mMediaProvider.insert(tableUri, values);
@@ -1060,8 +1069,7 @@ public class MediaScanner
            boolean fileMissing = false;

            if (!entry.mSeenInFileSystem && !MtpConstants.isAbstractObject(entry.mFormat)) {
                if (entry.mFormat != MtpConstants.FORMAT_ASSOCIATION &&
                        inScanDirectory(path, directories)) {
                if (inScanDirectory(path, directories)) {
                    // we didn't see this file in the scan directory.
                    fileMissing = true;
                } else {
@@ -1180,7 +1188,7 @@ public class MediaScanner
            long lastModifiedSeconds = file.lastModified() / 1000;

            // always scan the file, so we can return the content://media Uri for existing files
            return mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(), true);
            return mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(),false, true);
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
            return null;
@@ -1227,7 +1235,8 @@ public class MediaScanner
                long lastModifiedSeconds = file.lastModified() / 1000;

                // always scan the file, so we can return the content://media Uri for existing files
                mClient.doScanFile(path, mediaFileType.mimeType, lastModifiedSeconds, file.length(), true);
                mClient.doScanFile(path, mediaFileType.mimeType, lastModifiedSeconds, file.length(),
                    (format == MtpConstants.FORMAT_ASSOCIATION), true);
            }
        } catch (RemoteException e) {
            Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
+1 −3
Original line number Diff line number Diff line
@@ -21,9 +21,7 @@ package android.media;
 */
public interface MediaScannerClient
{    
    public void scanFile(String path, long lastModified, long fileSize);
    
    public void scanFile(String path, String mimeType, long lastModified, long fileSize);
    public void scanFile(String path, long lastModified, long fileSize, boolean isDirectory);

    public void addNoMediaFolder(String path);

+5 −3
Original line number Diff line number Diff line
@@ -62,7 +62,7 @@ public:
        }
        else {
            mScanFileMethodID = env->GetMethodID(mediaScannerClientInterface, "scanFile",
                                                     "(Ljava/lang/String;JJ)V");
                                                     "(Ljava/lang/String;JJZ)V");
            mHandleStringTagMethodID = env->GetMethodID(mediaScannerClientInterface, "handleStringTag",
                                                     "(Ljava/lang/String;Ljava/lang/String;)V");
            mSetMimeTypeMethodID = env->GetMethodID(mediaScannerClientInterface, "setMimeType",
@@ -78,12 +78,14 @@ public:
    }
    
    // returns true if it succeeded, false if an exception occured in the Java code
    virtual bool scanFile(const char* path, long long lastModified, long long fileSize)
    virtual bool scanFile(const char* path, long long lastModified,
            long long fileSize, bool isDirectory)
    {
        jstring pathStr;
        if ((pathStr = mEnv->NewStringUTF(path)) == NULL) return false;

        mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified, fileSize);
        mEnv->CallVoidMethod(mClient, mScanFileMethodID, pathStr, lastModified,
                fileSize, isDirectory);

        mEnv->DeleteLocalRef(pathStr);
        return (!mEnv->ExceptionCheck());
+10 −6
Original line number Diff line number Diff line
@@ -84,6 +84,7 @@ status_t MediaScanner::doProcessDirectory(
    // place to copy file or directory name
    char* fileSpot = path + strlen(path);
    struct dirent* entry;
    struct stat statbuf;

    // ignore directories that contain a  ".nomedia" file
    if (pathRemaining >= 8 /* strlen(".nomedia") */ ) {
@@ -125,7 +126,6 @@ status_t MediaScanner::doProcessDirectory(
            // If the type is unknown, stat() the file instead.
            // This is sometimes necessary when accessing NFS mounted filesystems, but
            // could be needed in other cases well.
            struct stat statbuf;
            if (stat(path, &statbuf) == 0) {
                if (S_ISREG(statbuf.st_mode)) {
                    type = DT_REG;
@@ -142,8 +142,15 @@ status_t MediaScanner::doProcessDirectory(
                // for example, the Mac ".Trashes" directory
                if (name[0] == '.') continue;

                // report the directory to the client
                if (stat(path, &statbuf) == 0) {
                    client.scanFile(path, statbuf.st_mtime, 0, true);
                }

                // and now process its contents
                strcat(fileSpot, "/");
                int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client, exceptionCheck, exceptionEnv);
                int err = doProcessDirectory(path, pathRemaining - nameLength - 1, client,
                        exceptionCheck, exceptionEnv);
                if (err) {
                    // pass exceptions up - ignore other errors
                    if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
@@ -151,11 +158,8 @@ status_t MediaScanner::doProcessDirectory(
                    continue;
                }
            } else {
                struct stat statbuf;
                stat(path, &statbuf);
                if (statbuf.st_size > 0) {
                    client.scanFile(path, statbuf.st_mtime, statbuf.st_size);
                }
                client.scanFile(path, statbuf.st_mtime, statbuf.st_size, false);
                if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
            }
        }