summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/content/ContentResolver.java6
-rw-r--r--core/java/android/os/FileUtils.java3
-rw-r--r--core/java/com/android/internal/content/FileSystemProvider.java6
-rw-r--r--media/java/android/media/MediaFile.java522
-rw-r--r--media/java/android/media/MediaScanner.java111
-rw-r--r--media/java/android/media/ThumbnailUtils.java22
-rw-r--r--media/tests/MediaFrameworkTest/AndroidTest.xml27
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java133
-rw-r--r--packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java20
9 files changed, 472 insertions, 378 deletions
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 5867a9c8890e..3bfb1c55fed6 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -437,6 +437,12 @@ public abstract class ContentResolver {
*/
public static final String ANY_CURSOR_ITEM_TYPE = "vnd.android.cursor.item/*";
+ /**
+ * Default MIME type for files whose type is otherwise unknown.
+ * @hide
+ */
+ public static final String MIME_TYPE_DEFAULT = "application/octet-stream";
+
/** @hide */
@UnsupportedAppUsage
public static final int SYNC_ERROR_SYNC_ALREADY_IN_PROGRESS = 1;
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index 3a3d9ea0b44f..1c8029caab70 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -23,6 +23,7 @@ import static android.system.OsConstants.S_ISREG;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.ContentResolver;
import android.provider.DocumentsContract.Document;
import android.system.ErrnoException;
import android.system.Os;
@@ -1057,7 +1058,7 @@ public class FileUtils {
}
if (mimeTypeFromExt == null) {
- mimeTypeFromExt = "application/octet-stream";
+ mimeTypeFromExt = ContentResolver.MIME_TYPE_DEFAULT;
}
final String extFromMimeType = MimeTypeMap.getSingleton().getExtensionFromMimeType(
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index 0c6f832ff33a..b33a5c4ffb7d 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -74,10 +74,6 @@ public abstract class FileSystemProvider extends DocumentsProvider {
private Handler mHandler;
- private static final String MIMETYPE_JPEG = "image/jpeg";
- private static final String MIMETYPE_JPG = "image/jpg";
- private static final String MIMETYPE_OCTET_STREAM = "application/octet-stream";
-
protected abstract File getFileForDocId(String docId, boolean visible)
throws FileNotFoundException;
@@ -433,7 +429,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
return mime;
}
}
- return MIMETYPE_OCTET_STREAM;
+ return ContentResolver.MIME_TYPE_DEFAULT;
}
}
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 3b9b6dd6d889..710b503d97fd 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -16,115 +16,41 @@
package android.media;
+import static android.content.ContentResolver.MIME_TYPE_DEFAULT;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
-import android.media.DecoderCapabilities;
-import android.media.DecoderCapabilities.VideoDecoder;
-import android.media.DecoderCapabilities.AudioDecoder;
import android.mtp.MtpConstants;
-import com.android.internal.util.Preconditions;
+
+import libcore.net.MimeUtils;
+
import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
/**
* MediaScanner helper class.
+ * <p>
+ * This heavily relies upon extension to MIME type mappings which are maintained
+ * in {@link MimeUtils}, to ensure consistency across the OS.
+ * <p>
+ * When adding a new file type, first add the MIME type mapping to
+ * {@link MimeUtils}, and then add the MTP format mapping here.
*
- * {@hide}
+ * @hide
*/
public class MediaFile {
- // Audio file types
- public static final int FILE_TYPE_MP3 = 1;
- public static final int FILE_TYPE_M4A = 2;
- public static final int FILE_TYPE_WAV = 3;
- public static final int FILE_TYPE_AMR = 4;
- public static final int FILE_TYPE_AWB = 5;
- public static final int FILE_TYPE_WMA = 6;
- public static final int FILE_TYPE_OGG = 7;
- public static final int FILE_TYPE_AAC = 8;
- public static final int FILE_TYPE_MKA = 9;
- public static final int FILE_TYPE_FLAC = 10;
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
- private static final int FIRST_AUDIO_FILE_TYPE = FILE_TYPE_MP3;
+ private static final int FIRST_AUDIO_FILE_TYPE = 1;
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
- private static final int LAST_AUDIO_FILE_TYPE = FILE_TYPE_FLAC;
-
- // MIDI file types
- public static final int FILE_TYPE_MID = 11;
- public static final int FILE_TYPE_SMF = 12;
- public static final int FILE_TYPE_IMY = 13;
- private static final int FIRST_MIDI_FILE_TYPE = FILE_TYPE_MID;
- private static final int LAST_MIDI_FILE_TYPE = FILE_TYPE_IMY;
-
- // Video file types
- public static final int FILE_TYPE_MP4 = 21;
- public static final int FILE_TYPE_M4V = 22;
- public static final int FILE_TYPE_3GPP = 23;
- public static final int FILE_TYPE_3GPP2 = 24;
- public static final int FILE_TYPE_WMV = 25;
- public static final int FILE_TYPE_ASF = 26;
- public static final int FILE_TYPE_MKV = 27;
- public static final int FILE_TYPE_MP2TS = 28;
- public static final int FILE_TYPE_AVI = 29;
- public static final int FILE_TYPE_WEBM = 30;
- private static final int FIRST_VIDEO_FILE_TYPE = FILE_TYPE_MP4;
- private static final int LAST_VIDEO_FILE_TYPE = FILE_TYPE_WEBM;
-
- // More video file types
- public static final int FILE_TYPE_MP2PS = 200;
- public static final int FILE_TYPE_QT = 201;
- private static final int FIRST_VIDEO_FILE_TYPE2 = FILE_TYPE_MP2PS;
- private static final int LAST_VIDEO_FILE_TYPE2 = FILE_TYPE_QT;
-
- // Image file types
- public static final int FILE_TYPE_JPEG = 31;
- public static final int FILE_TYPE_GIF = 32;
- public static final int FILE_TYPE_PNG = 33;
- public static final int FILE_TYPE_BMP = 34;
- public static final int FILE_TYPE_WBMP = 35;
- public static final int FILE_TYPE_WEBP = 36;
- public static final int FILE_TYPE_HEIF = 37;
- private static final int FIRST_IMAGE_FILE_TYPE = FILE_TYPE_JPEG;
- private static final int LAST_IMAGE_FILE_TYPE = FILE_TYPE_HEIF;
-
- // Raw image file types
- public static final int FILE_TYPE_DNG = 300;
- public static final int FILE_TYPE_CR2 = 301;
- public static final int FILE_TYPE_NEF = 302;
- public static final int FILE_TYPE_NRW = 303;
- public static final int FILE_TYPE_ARW = 304;
- public static final int FILE_TYPE_RW2 = 305;
- public static final int FILE_TYPE_ORF = 306;
- public static final int FILE_TYPE_RAF = 307;
- public static final int FILE_TYPE_PEF = 308;
- public static final int FILE_TYPE_SRW = 309;
- private static final int FIRST_RAW_IMAGE_FILE_TYPE = FILE_TYPE_DNG;
- private static final int LAST_RAW_IMAGE_FILE_TYPE = FILE_TYPE_SRW;
-
- // Playlist file types
- public static final int FILE_TYPE_M3U = 41;
- public static final int FILE_TYPE_PLS = 42;
- public static final int FILE_TYPE_WPL = 43;
- public static final int FILE_TYPE_HTTPLIVE = 44;
-
- private static final int FIRST_PLAYLIST_FILE_TYPE = FILE_TYPE_M3U;
- private static final int LAST_PLAYLIST_FILE_TYPE = FILE_TYPE_HTTPLIVE;
-
- // Drm file types
- public static final int FILE_TYPE_FL = 51;
- private static final int FIRST_DRM_FILE_TYPE = FILE_TYPE_FL;
- private static final int LAST_DRM_FILE_TYPE = FILE_TYPE_FL;
-
- // Other popular file types
- public static final int FILE_TYPE_TEXT = 100;
- public static final int FILE_TYPE_HTML = 101;
- public static final int FILE_TYPE_PDF = 102;
- public static final int FILE_TYPE_XML = 103;
- public static final int FILE_TYPE_MS_WORD = 104;
- public static final int FILE_TYPE_MS_EXCEL = 105;
- public static final int FILE_TYPE_MS_POWERPOINT = 106;
- public static final int FILE_TYPE_ZIP = 107;
+ private static final int LAST_AUDIO_FILE_TYPE = 10;
+ /** @deprecated file types no longer exist */
+ @Deprecated
public static class MediaFileType {
@UnsupportedAppUsage
public final int fileType;
@@ -137,214 +63,178 @@ public class MediaFile {
}
}
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
- private static final HashMap<String, MediaFileType> sFileTypeMap
- = new HashMap<String, MediaFileType>();
- private static final HashMap<String, Integer> sMimeTypeMap
- = new HashMap<String, Integer>();
- // maps file extension to MTP format code
+ private static final HashMap<String, MediaFileType> sFileTypeMap = new HashMap<>();
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
- private static final HashMap<String, Integer> sFileTypeToFormatMap
- = new HashMap<String, Integer>();
+ private static final HashMap<String, Integer> sFileTypeToFormatMap = new HashMap<>();
+
// maps mime type to MTP format code
@UnsupportedAppUsage
- private static final HashMap<String, Integer> sMimeTypeToFormatMap
- = new HashMap<String, Integer>();
+ private static final HashMap<String, Integer> sMimeTypeToFormatMap = new HashMap<>();
// maps MTP format code to mime type
@UnsupportedAppUsage
- private static final HashMap<Integer, String> sFormatToMimeTypeMap
- = new HashMap<Integer, String>();
+ private static final HashMap<Integer, String> sFormatToMimeTypeMap = new HashMap<>();
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
static void addFileType(String extension, int fileType, String mimeType) {
- sFileTypeMap.put(extension, new MediaFileType(fileType, mimeType));
- sMimeTypeMap.put(mimeType, Integer.valueOf(fileType));
}
- private static void addFileType(String extension, int fileType, String mimeType,
- int mtpFormatCode, boolean primaryType) {
- addFileType(extension, fileType, mimeType);
- sFileTypeToFormatMap.put(extension, Integer.valueOf(mtpFormatCode));
- sMimeTypeToFormatMap.put(mimeType, Integer.valueOf(mtpFormatCode));
- if (primaryType) {
- Preconditions.checkArgument(!sFormatToMimeTypeMap.containsKey(mtpFormatCode));
- sFormatToMimeTypeMap.put(mtpFormatCode, mimeType);
+ private static void addFileType(int mtpFormatCode, @NonNull String mimeType) {
+ if (!sMimeTypeToFormatMap.containsKey(mimeType)) {
+ sMimeTypeToFormatMap.put(mimeType, Integer.valueOf(mtpFormatCode));
}
- }
-
- private static boolean isWMAEnabled() {
- List<AudioDecoder> decoders = DecoderCapabilities.getAudioDecoders();
- int count = decoders.size();
- for (int i = 0; i < count; i++) {
- AudioDecoder decoder = decoders.get(i);
- if (decoder == AudioDecoder.AUDIO_DECODER_WMA) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean isWMVEnabled() {
- List<VideoDecoder> decoders = DecoderCapabilities.getVideoDecoders();
- int count = decoders.size();
- for (int i = 0; i < count; i++) {
- VideoDecoder decoder = decoders.get(i);
- if (decoder == VideoDecoder.VIDEO_DECODER_WMV) {
- return true;
- }
+ if (!sFormatToMimeTypeMap.containsKey(mtpFormatCode)) {
+ sFormatToMimeTypeMap.put(mtpFormatCode, mimeType);
}
- return false;
}
static {
- addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg", MtpConstants.FORMAT_MP3, true);
- addFileType("MPGA", FILE_TYPE_MP3, "audio/mpeg", MtpConstants.FORMAT_MP3, false);
- addFileType("M4A", FILE_TYPE_M4A, "audio/mp4", MtpConstants.FORMAT_MPEG, false);
- addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav", MtpConstants.FORMAT_WAV, true);
- addFileType("AMR", FILE_TYPE_AMR, "audio/amr");
- addFileType("AWB", FILE_TYPE_AWB, "audio/amr-wb");
- if (isWMAEnabled()) {
- addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma", MtpConstants.FORMAT_WMA, true);
- }
- addFileType("OGG", FILE_TYPE_OGG, "audio/ogg", MtpConstants.FORMAT_OGG, false);
- addFileType("OGG", FILE_TYPE_OGG, "application/ogg", MtpConstants.FORMAT_OGG, true);
- addFileType("OGA", FILE_TYPE_OGG, "application/ogg", MtpConstants.FORMAT_OGG, false);
- addFileType("AAC", FILE_TYPE_AAC, "audio/aac", MtpConstants.FORMAT_AAC, true);
- addFileType("AAC", FILE_TYPE_AAC, "audio/aac-adts", MtpConstants.FORMAT_AAC, false);
- addFileType("MKA", FILE_TYPE_MKA, "audio/x-matroska");
-
- addFileType("MID", FILE_TYPE_MID, "audio/midi");
- addFileType("MIDI", FILE_TYPE_MID, "audio/midi");
- addFileType("XMF", FILE_TYPE_MID, "audio/midi");
- addFileType("RTTTL", FILE_TYPE_MID, "audio/midi");
- addFileType("SMF", FILE_TYPE_SMF, "audio/sp-midi");
- addFileType("IMY", FILE_TYPE_IMY, "audio/imelody");
- addFileType("RTX", FILE_TYPE_MID, "audio/midi");
- addFileType("OTA", FILE_TYPE_MID, "audio/midi");
- addFileType("MXMF", FILE_TYPE_MID, "audio/midi");
-
- addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG, true);
- addFileType("MPG", FILE_TYPE_MP4, "video/mpeg", MtpConstants.FORMAT_MPEG, false);
- addFileType("MP4", FILE_TYPE_MP4, "video/mp4", MtpConstants.FORMAT_MPEG, false);
- addFileType("M4V", FILE_TYPE_M4V, "video/mp4", MtpConstants.FORMAT_MPEG, false);
- addFileType("MOV", FILE_TYPE_QT, "video/quicktime", MtpConstants.FORMAT_MPEG, false);
-
- addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp", MtpConstants.FORMAT_3GP_CONTAINER, true);
- addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp", MtpConstants.FORMAT_3GP_CONTAINER, false);
- addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2", MtpConstants.FORMAT_3GP_CONTAINER, false);
- addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2", MtpConstants.FORMAT_3GP_CONTAINER, false);
- addFileType("MKV", FILE_TYPE_MKV, "video/x-matroska");
- addFileType("WEBM", FILE_TYPE_WEBM, "video/webm");
- addFileType("TS", FILE_TYPE_MP2TS, "video/mp2ts");
- addFileType("AVI", FILE_TYPE_AVI, "video/avi");
-
- if (isWMVEnabled()) {
- addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv", MtpConstants.FORMAT_WMV, true);
- addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf");
- }
-
- addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg", MtpConstants.FORMAT_EXIF_JPEG, true);
- addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg", MtpConstants.FORMAT_EXIF_JPEG, false);
- addFileType("GIF", FILE_TYPE_GIF, "image/gif", MtpConstants.FORMAT_GIF, true);
- addFileType("PNG", FILE_TYPE_PNG, "image/png", MtpConstants.FORMAT_PNG, true);
- addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp", MtpConstants.FORMAT_BMP, true);
- addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp", MtpConstants.FORMAT_DEFINED, false);
- addFileType("WEBP", FILE_TYPE_WEBP, "image/webp", MtpConstants.FORMAT_DEFINED, false);
- addFileType("HEIC", FILE_TYPE_HEIF, "image/heif", MtpConstants.FORMAT_HEIF, true);
- addFileType("HEIF", FILE_TYPE_HEIF, "image/heif", MtpConstants.FORMAT_HEIF, false);
-
- addFileType("DNG", FILE_TYPE_DNG, "image/x-adobe-dng", MtpConstants.FORMAT_DNG, true);
- addFileType("CR2", FILE_TYPE_CR2, "image/x-canon-cr2", MtpConstants.FORMAT_TIFF, false);
- addFileType("NEF", FILE_TYPE_NEF, "image/x-nikon-nef", MtpConstants.FORMAT_TIFF_EP, false);
- addFileType("NRW", FILE_TYPE_NRW, "image/x-nikon-nrw", MtpConstants.FORMAT_TIFF, false);
- addFileType("ARW", FILE_TYPE_ARW, "image/x-sony-arw", MtpConstants.FORMAT_TIFF, false);
- addFileType("RW2", FILE_TYPE_RW2, "image/x-panasonic-rw2", MtpConstants.FORMAT_TIFF, false);
- addFileType("ORF", FILE_TYPE_ORF, "image/x-olympus-orf", MtpConstants.FORMAT_TIFF, false);
- addFileType("RAF", FILE_TYPE_RAF, "image/x-fuji-raf", MtpConstants.FORMAT_DEFINED, false);
- addFileType("PEF", FILE_TYPE_PEF, "image/x-pentax-pef", MtpConstants.FORMAT_TIFF, false);
- addFileType("SRW", FILE_TYPE_SRW, "image/x-samsung-srw", MtpConstants.FORMAT_TIFF, false);
-
- addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl", MtpConstants.FORMAT_M3U_PLAYLIST, true);
- addFileType("M3U", FILE_TYPE_M3U, "application/x-mpegurl", MtpConstants.FORMAT_M3U_PLAYLIST, false);
- addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls", MtpConstants.FORMAT_PLS_PLAYLIST, true);
- addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl", MtpConstants.FORMAT_WPL_PLAYLIST, true);
- addFileType("M3U8", FILE_TYPE_HTTPLIVE, "application/vnd.apple.mpegurl");
- addFileType("M3U8", FILE_TYPE_HTTPLIVE, "audio/mpegurl");
- addFileType("M3U8", FILE_TYPE_HTTPLIVE, "audio/x-mpegurl");
-
- addFileType("FL", FILE_TYPE_FL, "application/x-android-drm-fl");
-
- addFileType("TXT", FILE_TYPE_TEXT, "text/plain", MtpConstants.FORMAT_TEXT, true);
- addFileType("HTM", FILE_TYPE_HTML, "text/html", MtpConstants.FORMAT_HTML, true);
- addFileType("HTML", FILE_TYPE_HTML, "text/html", MtpConstants.FORMAT_HTML, false);
- addFileType("PDF", FILE_TYPE_PDF, "application/pdf");
- addFileType("DOC", FILE_TYPE_MS_WORD, "application/msword", MtpConstants.FORMAT_MS_WORD_DOCUMENT, true);
- addFileType("XLS", FILE_TYPE_MS_EXCEL, "application/vnd.ms-excel", MtpConstants.FORMAT_MS_EXCEL_SPREADSHEET, true);
- addFileType("PPT", FILE_TYPE_MS_POWERPOINT, "application/vnd.ms-powerpoint", MtpConstants.FORMAT_MS_POWERPOINT_PRESENTATION, true);
- addFileType("FLAC", FILE_TYPE_FLAC, "audio/flac", MtpConstants.FORMAT_FLAC, true);
- addFileType("ZIP", FILE_TYPE_ZIP, "application/zip");
- addFileType("MPG", FILE_TYPE_MP2PS, "video/mp2p");
- addFileType("MPEG", FILE_TYPE_MP2PS, "video/mp2p");
+ addFileType(MtpConstants.FORMAT_MP3, "audio/mpeg");
+ addFileType(MtpConstants.FORMAT_WAV, "audio/x-wav");
+ addFileType(MtpConstants.FORMAT_WMA, "audio/x-ms-wma");
+ addFileType(MtpConstants.FORMAT_OGG, "audio/ogg");
+ addFileType(MtpConstants.FORMAT_AAC, "audio/aac");
+ addFileType(MtpConstants.FORMAT_FLAC, "audio/flac");
+ addFileType(MtpConstants.FORMAT_AIFF, "audio/x-aiff");
+ addFileType(MtpConstants.FORMAT_MP2, "audio/mpeg");
+
+ addFileType(MtpConstants.FORMAT_MPEG, "video/mpeg");
+ addFileType(MtpConstants.FORMAT_MP4_CONTAINER, "video/mp4");
+ addFileType(MtpConstants.FORMAT_3GP_CONTAINER, "video/3gpp");
+ addFileType(MtpConstants.FORMAT_3GP_CONTAINER, "video/3gpp2");
+ addFileType(MtpConstants.FORMAT_AVI, "video/avi");
+ addFileType(MtpConstants.FORMAT_WMV, "video/x-ms-wmv");
+ addFileType(MtpConstants.FORMAT_ASF, "video/x-ms-asf");
+
+ addFileType(MtpConstants.FORMAT_EXIF_JPEG, "image/jpeg");
+ addFileType(MtpConstants.FORMAT_GIF, "image/gif");
+ addFileType(MtpConstants.FORMAT_PNG, "image/png");
+ addFileType(MtpConstants.FORMAT_BMP, "image/x-ms-bmp");
+ addFileType(MtpConstants.FORMAT_HEIF, "image/heif");
+ addFileType(MtpConstants.FORMAT_DNG, "image/x-adobe-dng");
+ addFileType(MtpConstants.FORMAT_TIFF, "image/tiff");
+ addFileType(MtpConstants.FORMAT_TIFF, "image/x-canon-cr2");
+ addFileType(MtpConstants.FORMAT_TIFF, "image/x-nikon-nrw");
+ addFileType(MtpConstants.FORMAT_TIFF, "image/x-sony-arw");
+ addFileType(MtpConstants.FORMAT_TIFF, "image/x-panasonic-rw2");
+ addFileType(MtpConstants.FORMAT_TIFF, "image/x-olympus-orf");
+ addFileType(MtpConstants.FORMAT_TIFF, "image/x-pentax-pef");
+ addFileType(MtpConstants.FORMAT_TIFF, "image/x-samsung-srw");
+ addFileType(MtpConstants.FORMAT_TIFF_EP, "image/tiff");
+ addFileType(MtpConstants.FORMAT_TIFF_EP, "image/x-nikon-nef");
+ addFileType(MtpConstants.FORMAT_JP2, "image/jp2");
+ addFileType(MtpConstants.FORMAT_JPX, "image/jpx");
+
+ addFileType(MtpConstants.FORMAT_M3U_PLAYLIST, "audio/x-mpegurl");
+ addFileType(MtpConstants.FORMAT_PLS_PLAYLIST, "audio/x-scpls");
+ addFileType(MtpConstants.FORMAT_WPL_PLAYLIST, "application/vnd.ms-wpl");
+ addFileType(MtpConstants.FORMAT_ASX_PLAYLIST, "video/x-ms-asf");
+
+ addFileType(MtpConstants.FORMAT_TEXT, "text/plain");
+ addFileType(MtpConstants.FORMAT_HTML, "text/html");
+ addFileType(MtpConstants.FORMAT_XML_DOCUMENT, "text/xml");
+
+ addFileType(MtpConstants.FORMAT_MS_WORD_DOCUMENT,
+ "application/msword");
+ addFileType(MtpConstants.FORMAT_MS_WORD_DOCUMENT,
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
+ addFileType(MtpConstants.FORMAT_MS_EXCEL_SPREADSHEET,
+ "application/vnd.ms-excel");
+ addFileType(MtpConstants.FORMAT_MS_EXCEL_SPREADSHEET,
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ addFileType(MtpConstants.FORMAT_MS_POWERPOINT_PRESENTATION,
+ "application/vnd.ms-powerpoint");
+ addFileType(MtpConstants.FORMAT_MS_POWERPOINT_PRESENTATION,
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation");
}
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
public static boolean isAudioFileType(int fileType) {
- return ((fileType >= FIRST_AUDIO_FILE_TYPE &&
- fileType <= LAST_AUDIO_FILE_TYPE) ||
- (fileType >= FIRST_MIDI_FILE_TYPE &&
- fileType <= LAST_MIDI_FILE_TYPE));
+ return false;
}
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
public static boolean isVideoFileType(int fileType) {
- return (fileType >= FIRST_VIDEO_FILE_TYPE &&
- fileType <= LAST_VIDEO_FILE_TYPE)
- || (fileType >= FIRST_VIDEO_FILE_TYPE2 &&
- fileType <= LAST_VIDEO_FILE_TYPE2);
+ return false;
}
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
public static boolean isImageFileType(int fileType) {
- return (fileType >= FIRST_IMAGE_FILE_TYPE &&
- fileType <= LAST_IMAGE_FILE_TYPE)
- || (fileType >= FIRST_RAW_IMAGE_FILE_TYPE &&
- fileType <= LAST_RAW_IMAGE_FILE_TYPE);
- }
-
- public static boolean isRawImageFileType(int fileType) {
- return (fileType >= FIRST_RAW_IMAGE_FILE_TYPE &&
- fileType <= LAST_RAW_IMAGE_FILE_TYPE);
+ return false;
}
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
public static boolean isPlayListFileType(int fileType) {
- return (fileType >= FIRST_PLAYLIST_FILE_TYPE &&
- fileType <= LAST_PLAYLIST_FILE_TYPE);
+ return false;
}
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
public static boolean isDrmFileType(int fileType) {
- return (fileType >= FIRST_DRM_FILE_TYPE &&
- fileType <= LAST_DRM_FILE_TYPE);
+ return false;
}
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
public static MediaFileType getFileType(String path) {
- int lastDot = path.lastIndexOf('.');
- if (lastDot < 0)
- return null;
- return sFileTypeMap.get(path.substring(lastDot + 1).toUpperCase(Locale.ROOT));
+ return null;
+ }
+
+ public static boolean isExifMimeType(@Nullable String mimeType) {
+ // For simplicity, assume that all image files might have EXIF data
+ return isImageMimeType(mimeType);
+ }
+
+ public static boolean isAudioMimeType(@Nullable String mimeType) {
+ return normalizeMimeType(mimeType).startsWith("audio/");
+ }
+
+ public static boolean isVideoMimeType(@Nullable String mimeType) {
+ return normalizeMimeType(mimeType).startsWith("video/");
+ }
+
+ public static boolean isImageMimeType(@Nullable String mimeType) {
+ return normalizeMimeType(mimeType).startsWith("image/");
}
- public static boolean isMimeTypeMedia(String mimeType) {
- int fileType = getFileTypeForMimeType(mimeType);
- return isAudioFileType(fileType) || isVideoFileType(fileType)
- || isImageFileType(fileType) || isPlayListFileType(fileType);
+ public static boolean isPlayListMimeType(@Nullable String mimeType) {
+ switch (normalizeMimeType(mimeType)) {
+ case "application/vnd.ms-wpl":
+ case "audio/x-mpegurl":
+ case "audio/mpegurl":
+ case "application/x-mpegurl":
+ case "application/vnd.apple.mpegurl":
+ case "video/x-ms-asf":
+ case "audio/x-scpls":
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public static boolean isDrmMimeType(@Nullable String mimeType) {
+ return normalizeMimeType(mimeType).equals("application/x-android-drm-fl");
}
// generates a title based on file name
@UnsupportedAppUsage
- public static String getFileTitle(String path) {
+ public static @NonNull String getFileTitle(@NonNull String path) {
// extract file name after last slash
int lastSlash = path.lastIndexOf('/');
if (lastSlash >= 0) {
@@ -361,37 +251,111 @@ public class MediaFile {
return path;
}
+ public static @Nullable String getFileExtension(@Nullable String path) {
+ if (path == null) {
+ return null;
+ }
+ int lastDot = path.lastIndexOf('.');
+ if (lastDot >= 0) {
+ return path.substring(lastDot + 1);
+ } else {
+ return null;
+ }
+ }
+
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
public static int getFileTypeForMimeType(String mimeType) {
- Integer value = sMimeTypeMap.get(mimeType);
- return (value == null ? 0 : value.intValue());
+ return 0;
+ }
+
+ /**
+ * Find the best MIME type for the given item. Prefers mappings from file
+ * extensions, since they're more accurate than format codes.
+ */
+ public static @NonNull String getMimeType(@Nullable String path, int formatCode) {
+ // First look for extension mapping
+ String mimeType = getMimeTypeForFile(path);
+ if (!MIME_TYPE_DEFAULT.equals(mimeType)) {
+ return mimeType;
+ }
+
+ // Otherwise look for format mapping
+ return getMimeTypeForFormatCode(formatCode);
}
@UnsupportedAppUsage
- public static String getMimeTypeForFile(String path) {
- MediaFileType mediaFileType = getFileType(path);
- return (mediaFileType == null ? null : mediaFileType.mimeType);
+ public static @NonNull String getMimeTypeForFile(@Nullable String path) {
+ final String mimeType = MimeUtils.guessMimeTypeFromExtension(getFileExtension(path));
+ return (mimeType != null) ? mimeType : MIME_TYPE_DEFAULT;
}
- public static int getFormatCode(String fileName, String mimeType) {
- if (mimeType != null) {
- Integer value = sMimeTypeToFormatMap.get(mimeType);
- if (value != null) {
- return value.intValue();
- }
+ public static @NonNull String getMimeTypeForFormatCode(int formatCode) {
+ final String mimeType = sFormatToMimeTypeMap.get(formatCode);
+ return (mimeType != null) ? mimeType : MIME_TYPE_DEFAULT;
+ }
+
+ /**
+ * Find the best MTP format code mapping for the given item. Prefers
+ * mappings from MIME types, since they're more accurate than file
+ * extensions.
+ */
+ public static int getFormatCode(@Nullable String path, @Nullable String mimeType) {
+ // First look for MIME type mapping
+ int formatCode = getFormatCodeForMimeType(mimeType);
+ if (formatCode != MtpConstants.FORMAT_UNDEFINED) {
+ return formatCode;
}
- int lastDot = fileName.lastIndexOf('.');
- if (lastDot > 0) {
- String extension = fileName.substring(lastDot + 1).toUpperCase(Locale.ROOT);
- Integer value = sFileTypeToFormatMap.get(extension);
- if (value != null) {
- return value.intValue();
- }
+
+ // Otherwise look for extension mapping
+ return getFormatCodeForFile(path);
+ }
+
+ public static int getFormatCodeForFile(@Nullable String path) {
+ return getFormatCodeForMimeType(getMimeTypeForFile(path));
+ }
+
+ public static int getFormatCodeForMimeType(@Nullable String mimeType) {
+ if (mimeType == null) {
+ return MtpConstants.FORMAT_UNDEFINED;
+ }
+
+ // First look for direct mapping
+ Integer value = sMimeTypeToFormatMap.get(mimeType);
+ if (value != null) {
+ return value.intValue();
+ }
+
+ // Otherwise look for indirect mapping
+ mimeType = normalizeMimeType(mimeType);
+ value = sMimeTypeToFormatMap.get(mimeType);
+ if (value != null) {
+ return value.intValue();
+ } else if (mimeType.startsWith("audio/")) {
+ return MtpConstants.FORMAT_UNDEFINED_AUDIO;
+ } else if (mimeType.startsWith("video/")) {
+ return MtpConstants.FORMAT_UNDEFINED_VIDEO;
+ } else if (mimeType.startsWith("image/")) {
+ return MtpConstants.FORMAT_DEFINED;
+ } else {
+ return MtpConstants.FORMAT_UNDEFINED;
}
- return MtpConstants.FORMAT_UNDEFINED;
}
- public static String getMimeTypeForFormatCode(int formatCode) {
- return sFormatToMimeTypeMap.get(formatCode);
+ /**
+ * Normalize the given MIME type by bouncing through a default file
+ * extension, if defined. This handles cases like "application/x-flac" to
+ * ".flac" to "audio/flac".
+ */
+ private static @NonNull String normalizeMimeType(@Nullable String mimeType) {
+ final String extension = MimeUtils.guessExtensionFromMimeType(mimeType);
+ if (extension != null) {
+ final String extensionMimeType = MimeUtils.guessMimeTypeFromExtension(extension);
+ if ( extensionMimeType != null) {
+ return extensionMimeType;
+ }
+ }
+ return (mimeType != null) ? mimeType : MIME_TYPE_DEFAULT;
}
}
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index dcacb925b25b..0ff2d8f6b6ec 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -502,6 +502,8 @@ public class MediaScanner implements AutoCloseable {
private String mGenre;
@UnsupportedAppUsage
private String mMimeType;
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
private int mFileType;
private int mTrack;
@@ -531,7 +533,6 @@ public class MediaScanner implements AutoCloseable {
public FileEntry beginFile(String path, String mimeType, long lastModified,
long fileSize, boolean isDirectory, boolean noMedia) {
mMimeType = mimeType;
- mFileType = 0;
mFileSize = fileSize;
mIsDrm = false;
mScanSuccess = true;
@@ -542,24 +543,13 @@ public class MediaScanner implements AutoCloseable {
}
mNoMedia = noMedia;
- // 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 (mMimeType == null) {
+ mMimeType = MediaFile.getMimeTypeForFile(path);
}
- if (isDrmEnabled() && MediaFile.isDrmFileType(mFileType)) {
- mFileType = getFileTypeFromDrm(path);
+ if (isDrmEnabled() && MediaFile.isDrmMimeType(mMimeType)) {
+ getMimeTypeFromDrm(path);
}
}
@@ -578,7 +568,7 @@ public class MediaScanner implements AutoCloseable {
entry.mLastModifiedChanged = true;
}
- if (mProcessPlaylists && MediaFile.isPlayListFileType(mFileType)) {
+ if (mProcessPlaylists && MediaFile.isPlayListMimeType(mMimeType)) {
mPlayLists.add(entry);
// we don't process playlists in the main scan, so return null
return null;
@@ -659,9 +649,9 @@ public class MediaScanner implements AutoCloseable {
if (noMedia) {
result = endFile(entry, false, false, false, false, false);
} else {
- boolean isaudio = MediaFile.isAudioFileType(mFileType);
- boolean isvideo = MediaFile.isVideoFileType(mFileType);
- boolean isimage = MediaFile.isImageFileType(mFileType);
+ boolean isaudio = MediaFile.isAudioMimeType(mMimeType);
+ boolean isvideo = MediaFile.isVideoMimeType(mMimeType);
+ boolean isimage = MediaFile.isImageMimeType(mMimeType);
if (isaudio || isvideo || isimage) {
path = Environment.maybeTranslateEmulatedPathToInternal(new File(path))
@@ -878,7 +868,6 @@ public class MediaScanner implements AutoCloseable {
return;
}
mMimeType = mimeType;
- mFileType = MediaFile.getFileTypeForMimeType(mimeType);
}
/**
@@ -906,7 +895,7 @@ public class MediaScanner implements AutoCloseable {
}
if (!mNoMedia) {
- if (MediaFile.isVideoFileType(mFileType)) {
+ if (MediaFile.isVideoMimeType(mMimeType)) {
map.put(Video.Media.ARTIST, (mArtist != null && mArtist.length() > 0
? mArtist : MediaStore.UNKNOWN_STRING));
map.put(Video.Media.ALBUM, (mAlbum != null && mAlbum.length() > 0
@@ -918,9 +907,9 @@ public class MediaScanner implements AutoCloseable {
if (mDate > 0) {
map.put(Video.Media.DATE_TAKEN, mDate);
}
- } else if (MediaFile.isImageFileType(mFileType)) {
+ } else if (MediaFile.isImageMimeType(mMimeType)) {
// FIXME - add DESCRIPTION
- } else if (mScanSuccess && MediaFile.isAudioFileType(mFileType)) {
+ } else if (mScanSuccess && MediaFile.isAudioMimeType(mMimeType)) {
map.put(Audio.Media.ARTIST, (mArtist != null && mArtist.length() > 0) ?
mArtist : MediaStore.UNKNOWN_STRING);
map.put(Audio.Media.ALBUM_ARTIST, (mAlbumArtist != null &&
@@ -982,7 +971,7 @@ public class MediaScanner implements AutoCloseable {
}
}
long rowId = entry.mRowId;
- if (MediaFile.isAudioFileType(mFileType) && (rowId == 0 || mMtpObjectHandle != 0)) {
+ if (MediaFile.isAudioMimeType(mMimeType) && (rowId == 0 || mMtpObjectHandle != 0)) {
// Only set these for new entries. For existing entries, they
// may have been modified later, and we want to keep the current
// values so that custom ringtones still show up in the ringtone
@@ -992,9 +981,7 @@ public class MediaScanner implements AutoCloseable {
values.put(Audio.Media.IS_ALARM, alarms);
values.put(Audio.Media.IS_MUSIC, music);
values.put(Audio.Media.IS_PODCAST, podcasts);
- } else if ((mFileType == MediaFile.FILE_TYPE_JPEG
- || mFileType == MediaFile.FILE_TYPE_HEIF
- || MediaFile.isRawImageFileType(mFileType)) && !mNoMedia) {
+ } else if (MediaFile.isExifMimeType(mMimeType) && !mNoMedia) {
ExifInterface exif = null;
try {
exif = new ExifInterface(entry.mPath);
@@ -1050,16 +1037,16 @@ public class MediaScanner implements AutoCloseable {
int mediaType = FileColumns.MEDIA_TYPE_NONE;
MediaInserter inserter = mMediaInserter;
if (mScanSuccess && !mNoMedia) {
- if (MediaFile.isVideoFileType(mFileType)) {
+ if (MediaFile.isVideoMimeType(mMimeType)) {
tableUri = mVideoUri;
mediaType = FileColumns.MEDIA_TYPE_VIDEO;
- } else if (MediaFile.isImageFileType(mFileType)) {
+ } else if (MediaFile.isImageMimeType(mMimeType)) {
tableUri = mImagesUri;
mediaType = FileColumns.MEDIA_TYPE_IMAGE;
- } else if (MediaFile.isAudioFileType(mFileType)) {
+ } else if (MediaFile.isAudioMimeType(mMimeType)) {
tableUri = mAudioUri;
mediaType = FileColumns.MEDIA_TYPE_AUDIO;
- } else if (MediaFile.isPlayListFileType(mFileType)) {
+ } else if (MediaFile.isPlayListMimeType(mMimeType)) {
tableUri = mPlaylistsUri;
mediaType = FileColumns.MEDIA_TYPE_PLAYLIST;
}
@@ -1176,13 +1163,15 @@ public class MediaScanner implements AutoCloseable {
Settings.System.putInt(cr, settingSetIndicatorName(settingName), 1);
}
+ /** @deprecated file types no longer exist */
+ @Deprecated
@UnsupportedAppUsage
private int getFileTypeFromDrm(String path) {
- if (!isDrmEnabled()) {
- return 0;
- }
+ return 0;
+ }
- int resultFileType = 0;
+ private void getMimeTypeFromDrm(String path) {
+ mMimeType = null;
if (mDrmManagerClient == null) {
mDrmManagerClient = new DrmManagerClient(mContext);
@@ -1190,13 +1179,12 @@ public class MediaScanner implements AutoCloseable {
if (mDrmManagerClient.canHandle(path, null)) {
mIsDrm = true;
- String drmMimetype = mDrmManagerClient.getOriginalMimeType(path);
- if (drmMimetype != null) {
- mMimeType = drmMimetype;
- resultFileType = MediaFile.getFileTypeForMimeType(drmMimetype);
- }
+ mMimeType = mDrmManagerClient.getOriginalMimeType(path);
+ }
+
+ if (mMimeType == null) {
+ mMimeType = ContentResolver.MIME_TYPE_DEFAULT;
}
- return resultFileType;
}
}; // end of anonymous MediaScannerClient instance
@@ -1305,10 +1293,8 @@ public class MediaScanner implements AutoCloseable {
// modified by the user.
// The user can delete them in the media player instead.
// instead, clear the path and lastModified fields in the row
- MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
- int fileType = (mediaFileType == null ? 0 : mediaFileType.fileType);
-
- if (!MediaFile.isPlayListFileType(fileType)) {
+ String mimeType = MediaFile.getMimeTypeForFile(path);
+ if (!MediaFile.isPlayListMimeType(mimeType)) {
deleter.delete(rowId);
if (path.toLowerCase(Locale.US).endsWith("/.nomedia")) {
deleter.flush();
@@ -1556,14 +1542,13 @@ public class MediaScanner implements AutoCloseable {
}
public void scanMtpFile(String path, int objectHandle, int format) {
- MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
- int fileType = (mediaFileType == null ? 0 : mediaFileType.fileType);
+ String mimeType = MediaFile.getMimeType(path, format);
File file = new File(path);
long lastModifiedSeconds = file.lastModified() / 1000;
- if (!MediaFile.isAudioFileType(fileType) && !MediaFile.isVideoFileType(fileType) &&
- !MediaFile.isImageFileType(fileType) && !MediaFile.isPlayListFileType(fileType) &&
- !MediaFile.isDrmFileType(fileType)) {
+ if (!MediaFile.isAudioMimeType(mimeType) && !MediaFile.isVideoMimeType(mimeType) &&
+ !MediaFile.isImageMimeType(mimeType) && !MediaFile.isPlayListMimeType(mimeType) &&
+ !MediaFile.isDrmMimeType(mimeType)) {
// no need to use the media scanner, but we need to update last modified and file size
ContentValues values = new ContentValues();
@@ -1582,7 +1567,7 @@ public class MediaScanner implements AutoCloseable {
mMtpObjectHandle = objectHandle;
Cursor fileList = null;
try {
- if (MediaFile.isPlayListFileType(fileType)) {
+ if (MediaFile.isPlayListMimeType(mimeType)) {
// build file cache so we can look up tracks in the playlist
prescan(null, true);
@@ -1597,7 +1582,7 @@ public class MediaScanner implements AutoCloseable {
prescan(path, false);
// always scan the file, so we can return the content://media Uri for existing files
- mClient.doScanFile(path, mediaFileType.mimeType, lastModifiedSeconds, file.length(),
+ mClient.doScanFile(path, mimeType, lastModifiedSeconds, file.length(),
(format == MtpConstants.FORMAT_ASSOCIATION), true, isNoMediaPath(path));
}
} catch (RemoteException e) {
@@ -1911,15 +1896,17 @@ public class MediaScanner implements AutoCloseable {
}
String playListDirectory = path.substring(0, lastSlash + 1);
- MediaFile.MediaFileType mediaFileType = MediaFile.getFileType(path);
- int fileType = (mediaFileType == null ? 0 : mediaFileType.fileType);
-
- if (fileType == MediaFile.FILE_TYPE_M3U) {
- processM3uPlayList(path, playListDirectory, membersUri, values, fileList);
- } else if (fileType == MediaFile.FILE_TYPE_PLS) {
- processPlsPlayList(path, playListDirectory, membersUri, values, fileList);
- } else if (fileType == MediaFile.FILE_TYPE_WPL) {
- processWplPlayList(path, playListDirectory, membersUri, values, fileList);
+ String mimeType = MediaFile.getMimeTypeForFile(path);
+ switch (mimeType) {
+ case "application/vnd.ms-wpl":
+ processWplPlayList(path, playListDirectory, membersUri, values, fileList);
+ break;
+ case "audio/x-mpegurl":
+ processM3uPlayList(path, playListDirectory, membersUri, values, fileList);
+ break;
+ case "audio/x-scpls":
+ processPlsPlayList(path, playListDirectory, membersUri, values, fileList);
+ break;
}
}
diff --git a/media/java/android/media/ThumbnailUtils.java b/media/java/android/media/ThumbnailUtils.java
index 07ab06934eb3..4cc86fdce2f2 100644
--- a/media/java/android/media/ThumbnailUtils.java
+++ b/media/java/android/media/ThumbnailUtils.java
@@ -23,15 +23,13 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
-import android.media.MediaMetadataRetriever;
-import android.media.MediaFile.MediaFileType;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.provider.MediaStore.Images;
import android.util.Log;
-import java.io.FileInputStream;
import java.io.FileDescriptor;
+import java.io.FileInputStream;
import java.io.IOException;
/**
@@ -94,15 +92,15 @@ public class ThumbnailUtils {
: MAX_NUM_PIXELS_MICRO_THUMBNAIL;
SizedThumbnailBitmap sizedThumbnailBitmap = new SizedThumbnailBitmap();
Bitmap bitmap = null;
- MediaFileType fileType = MediaFile.getFileType(filePath);
- if (fileType != null) {
- if (fileType.fileType == MediaFile.FILE_TYPE_JPEG
- || MediaFile.isRawImageFileType(fileType.fileType)) {
- createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
- bitmap = sizedThumbnailBitmap.mBitmap;
- } else if (fileType.fileType == MediaFile.FILE_TYPE_HEIF) {
- bitmap = createThumbnailFromMetadataRetriever(filePath, targetSize, maxPixels);
- }
+ String mimeType = MediaFile.getMimeTypeForFile(filePath);
+ if (mimeType.equals("image/heif")
+ || mimeType.equals("image/heif-sequence")
+ || mimeType.equals("image/heic")
+ || mimeType.equals("image/heic-sequence")) {
+ bitmap = createThumbnailFromMetadataRetriever(filePath, targetSize, maxPixels);
+ } else if (MediaFile.isExifMimeType(mimeType)) {
+ createThumbnailFromEXIF(filePath, targetSize, maxPixels, sizedThumbnailBitmap);
+ bitmap = sizedThumbnailBitmap.mBitmap;
}
if (bitmap == null) {
diff --git a/media/tests/MediaFrameworkTest/AndroidTest.xml b/media/tests/MediaFrameworkTest/AndroidTest.xml
new file mode 100644
index 000000000000..204959ff2749
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/AndroidTest.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<configuration description="Runs Media Framework Tests">
+ <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+ <option name="test-file-name" value="mediaframeworktest.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="MediaFrameworkTest" />
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.mediaframeworktest" />
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
new file mode 100644
index 000000000000..feac63d40710
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaFileTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.unit;
+
+import static android.media.MediaFile.getFormatCode;
+import static android.media.MediaFile.getMimeType;
+import static android.media.MediaFile.isAudioMimeType;
+import static android.media.MediaFile.isImageMimeType;
+import static android.media.MediaFile.isPlayListMimeType;
+import static android.media.MediaFile.isVideoMimeType;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.mtp.MtpConstants;
+import android.support.test.runner.AndroidJUnit4;
+
+import libcore.net.MimeUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+public class MediaFileTest {
+ @Test
+ public void testCommon() throws Exception {
+ assertConsistent("FOO.TXT", "text/plain", MtpConstants.FORMAT_TEXT);
+ assertConsistent("FOO.XML", "text/xml", MtpConstants.FORMAT_XML_DOCUMENT);
+ assertConsistent("FOO.HTML", "text/html", MtpConstants.FORMAT_HTML);
+ }
+
+ @Test
+ public void testAudio() throws Exception {
+ assertTrue(isAudioMimeType("audio/flac"));
+ assertTrue(isAudioMimeType("application/x-flac"));
+ assertFalse(isAudioMimeType("video/mpeg"));
+
+ assertConsistent("FOO.MP3", "audio/mpeg", MtpConstants.FORMAT_MP3);
+ assertConsistent("FOO.AAC", "audio/aac", MtpConstants.FORMAT_AAC);
+ assertConsistent("FOO.OGG", "audio/ogg", MtpConstants.FORMAT_OGG);
+ assertConsistent("FOO.FLAC", "audio/flac", MtpConstants.FORMAT_FLAC);
+ }
+
+ @Test
+ public void testVideo() throws Exception {
+ assertTrue(isVideoMimeType("video/x-msvideo"));
+ assertFalse(isVideoMimeType("audio/mpeg"));
+
+ assertConsistent("FOO.AVI", "video/avi", MtpConstants.FORMAT_AVI);
+ assertConsistent("FOO.MP4", "video/mp4", MtpConstants.FORMAT_MP4_CONTAINER);
+ assertConsistent("FOO.3GP", "video/3gpp", MtpConstants.FORMAT_3GP_CONTAINER);
+ }
+
+ @Test
+ public void testImage() throws Exception {
+ assertTrue(isImageMimeType("image/jpeg"));
+ assertTrue(isImageMimeType("image/heif"));
+ assertTrue(isImageMimeType("image/webp"));
+ assertFalse(isImageMimeType("video/webm"));
+
+ assertConsistent("FOO.JPG", "image/jpeg", MtpConstants.FORMAT_EXIF_JPEG);
+ assertConsistent("FOO.PNG", "image/png", MtpConstants.FORMAT_PNG);
+ assertConsistent("FOO.HEIF", "image/heif", MtpConstants.FORMAT_HEIF);
+ assertConsistent("FOO.DNG", "image/x-adobe-dng", MtpConstants.FORMAT_DNG);
+ assertConsistent("FOO.TIFF", "image/tiff", MtpConstants.FORMAT_TIFF);
+ }
+
+ @Test
+ public void testPlayList() throws Exception {
+ assertTrue(isPlayListMimeType(MimeUtils.guessMimeTypeFromExtension("pls")));
+ assertTrue(isPlayListMimeType(MimeUtils.guessMimeTypeFromExtension("wpl")));
+ assertTrue(isPlayListMimeType(MimeUtils.guessMimeTypeFromExtension("m3u")));
+ assertTrue(isPlayListMimeType(MimeUtils.guessMimeTypeFromExtension("m3u8")));
+ assertTrue(isPlayListMimeType(MimeUtils.guessMimeTypeFromExtension("asf")));
+ }
+
+ @Test
+ public void testImageRaw() throws Exception {
+ // We trust MIME types before filenames
+ assertHexEquals(MtpConstants.FORMAT_TIFF, getFormatCode("FOO.CR2", "image/x-canon-cr2"));
+ // We trust filenames before format codes
+ assertEquals("image/x-canon-cr2", getMimeType("FOO.CR2", MtpConstants.FORMAT_TIFF));
+ }
+
+ @Test
+ public void testConfusing() throws Exception {
+ // We trust MIME types before filenames
+ assertHexEquals(MtpConstants.FORMAT_MP3, getFormatCode("foo.avi", "audio/mpeg"));
+ // We trust filenames before format codes
+ assertEquals("video/avi", getMimeType("foo.avi", MtpConstants.FORMAT_MP3));
+ }
+
+ @Test
+ public void testUnknown() throws Exception {
+ assertHexEquals(MtpConstants.FORMAT_UNDEFINED,
+ getFormatCode("foo.example", "application/x-example"));
+ assertHexEquals(MtpConstants.FORMAT_UNDEFINED_AUDIO,
+ getFormatCode("foo.example", "audio/x-example"));
+ assertHexEquals(MtpConstants.FORMAT_UNDEFINED_VIDEO,
+ getFormatCode("foo.example", "video/x-example"));
+ assertHexEquals(MtpConstants.FORMAT_DEFINED,
+ getFormatCode("foo.example", "image/x-example"));
+ }
+
+ private static void assertConsistent(String path, String mimeType, int formatCode) {
+ assertHexEquals(formatCode, getFormatCode(path, null));
+ assertHexEquals(formatCode, getFormatCode(null, mimeType));
+ assertHexEquals(formatCode, getFormatCode(path, mimeType));
+
+ assertEquals(mimeType, getMimeType(path, MtpConstants.FORMAT_UNDEFINED));
+ assertEquals(mimeType, getMimeType(null, formatCode));
+ assertEquals(mimeType, getMimeType(path, formatCode));
+ }
+
+ private static void assertHexEquals(int expected, int actual) {
+ assertEquals(Integer.toHexString(expected), Integer.toHexString(actual));
+ }
+}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index f243b51d6769..59c205aebe18 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -851,25 +851,7 @@ class MtpDatabase {
return DocumentsContract.Document.MIME_TYPE_DIR;
}
- final String formatCodeMimeType = MediaFile.getMimeTypeForFormatCode(info.getFormat());
- final String mediaFileMimeType = MediaFile.getMimeTypeForFile(info.getName());
-
- // Format code can be mapped with multiple mime types, e.g. FORMAT_MPEG is mapped with
- // audio/mp4 and video/mp4.
- // As file extension contains more information than format code, returns mime type obtained
- // from file extension if it is consistent with format code.
- if (mediaFileMimeType != null &&
- MediaFile.getFormatCode("", mediaFileMimeType) == info.getFormat()) {
- return mediaFileMimeType;
- }
- if (formatCodeMimeType != null) {
- return formatCodeMimeType;
- }
- if (mediaFileMimeType != null) {
- return mediaFileMimeType;
- }
- // We don't know the file type.
- return "application/octet-stream";
+ return MediaFile.getMimeType(info.getName(), info.getFormat());
}
private static int getRootFlags(int[] operationsSupported) {