diff options
author | Mike Lockwood <lockwood@android.com> | 2010-12-16 12:54:24 -0800 |
---|---|---|
committer | Mike Lockwood <lockwood@android.com> | 2010-12-16 15:35:36 -0800 |
commit | 076e05b488e40fdd946f0d35137fe66a576efe09 (patch) | |
tree | c2b732777b51e1f6d8ba92047c2446bd0f2d0582 /media | |
parent | dcaa10cd361a543cfa93bbb5c53444f437bd07a4 (diff) | |
download | frameworks_base-076e05b488e40fdd946f0d35137fe66a576efe09.zip frameworks_base-076e05b488e40fdd946f0d35137fe66a576efe09.tar.gz frameworks_base-076e05b488e40fdd946f0d35137fe66a576efe09.tar.bz2 |
MediaScanner: Add support for scanning empty directories
Currently the media scanner does not create database entries for directories
unless they contain a file that is scanned.
Fixing this so we provide a consistent view of the world to MTP.
Change-Id: Ia776acfeae23192183e7192d63cdc34d830ea889
Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/MediaScanner.java | 117 | ||||
-rw-r--r-- | media/java/android/media/MediaScannerClient.java | 4 | ||||
-rw-r--r-- | media/jni/android_media_MediaScanner.cpp | 8 | ||||
-rw-r--r-- | media/libmedia/MediaScanner.cpp | 16 |
4 files changed, 79 insertions, 66 deletions
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java index 63ec6b2..365fd65 100644 --- a/media/java/android/media/MediaScanner.java +++ b/media/java/android/media/MediaScanner.java @@ -407,55 +407,60 @@ public class MediaScanner private long mFileSize; private String mWriter; - public FileCacheEntry beginFile(String path, String mimeType, long lastModified, long fileSize) { - - // special case certain file names - // I use regionMatches() instead of substring() below - // to avoid memory allocation - int lastSlash = path.lastIndexOf('/'); - if (lastSlash >= 0 && lastSlash + 2 < path.length()) { - // ignore those ._* files created by MacOS - if (path.regionMatches(lastSlash + 1, "._", 0, 2)) { - return null; - } + public FileCacheEntry beginFile(String path, String mimeType, long lastModified, + long fileSize, boolean isDirectory) { + mMimeType = mimeType; + mFileType = 0; + mFileSize = fileSize; - // ignore album art files created by Windows Media Player: - // 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)) { + if (!isDirectory) { + // special case certain file names + // I use regionMatches() instead of substring() below + // to avoid memory allocation + int lastSlash = path.lastIndexOf('/'); + if (lastSlash >= 0 && lastSlash + 2 < path.length()) { + // ignore those ._* files created by MacOS + if (path.regionMatches(lastSlash + 1, "._", 0, 2)) { 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))) { - return null; + + // ignore album art files created by Windows Media Player: + // 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))) { + return null; + } } } - } - mMimeType = mimeType; - mFileType = 0; - mFileSize = fileSize; - - // try mimeType first, if it is specified - if (mimeType != null) { - mFileType = MediaFile.getFileTypeForMimeType(mimeType); - } + // try mimeType first, if it is specified + if (mimeType != null) { + mFileType = MediaFile.getFileTypeForMimeType(mimeType); + } - // if mimeType was not specified, compute file type based on file extension. - if (mFileType == 0) { - MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path); - if (mediaFileType != null) { - mFileType = mediaFileType.fileType; - if (mMimeType == null) { - mMimeType = mediaFileType.mimeType; + // if mimeType was not specified, compute file type based on file extension. + if (mFileType == 0) { + MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path); + if (mediaFileType != null) { + mFileType = mediaFileType.fileType; + if (mMimeType == null) { + mMimeType = mediaFileType.mimeType; + } } } - } - if (isDrmEnabled() && MediaFile.isDrmFileType(mFileType)) { - mFileType = getFileTypeFromDrm(path); + if (isDrmEnabled() && MediaFile.isDrmFileType(mFileType)) { + mFileType = getFileTypeFromDrm(path); + } } String key = path; @@ -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); diff --git a/media/java/android/media/MediaScannerClient.java b/media/java/android/media/MediaScannerClient.java index 258c3b4..ac326ef 100644 --- a/media/java/android/media/MediaScannerClient.java +++ b/media/java/android/media/MediaScannerClient.java @@ -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); diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp index fd0b233..a5176fa 100644 --- a/media/jni/android_media_MediaScanner.cpp +++ b/media/jni/android_media_MediaScanner.cpp @@ -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()); diff --git a/media/libmedia/MediaScanner.cpp b/media/libmedia/MediaScanner.cpp index c31b622..5ec573e 100644 --- a/media/libmedia/MediaScanner.cpp +++ b/media/libmedia/MediaScanner.cpp @@ -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; } } |