Loading core/java/android/provider/MediaStore.java +38 −0 Original line number Diff line number Diff line Loading @@ -239,6 +239,44 @@ public final class MediaStore { public static final String MIME_TYPE = "mime_type"; } /** * Media provider interface used by MTP implementation. * @hide */ public static final class MtpObjects { public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object"); } public static final Uri getContentUri(String volumeName, long objectId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object/" + objectId); } /** * Fields for master table for all media files. * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED. */ public interface ObjectColumns extends MediaColumns { /** * The MTP format code of the file * <P>Type: INTEGER</P> */ public static final String FORMAT = "format"; /** * The index of the parent directory of the file * <P>Type: INTEGER</P> */ public static final String PARENT = "parent"; } } /** * This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended * to be accessed elsewhere. Loading media/java/android/media/MediaFile.java +57 −26 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.ContentValues; import android.provider.MediaStore.Audio; import android.provider.MediaStore.Images; import android.provider.MediaStore.Video; import android.provider.Mtp; import android.media.DecoderCapabilities; import android.media.DecoderCapabilities.VideoDecoder; import android.media.DecoderCapabilities.AudioDecoder; Loading Loading @@ -100,11 +101,24 @@ public class MediaFile { = new HashMap<String, MediaFileType>(); private static HashMap<String, Integer> sMimeTypeMap = new HashMap<String, Integer>(); // maps file extension to MTP format code private static HashMap<String, Integer> sFileTypeToFormatMap = new HashMap<String, Integer>(); // maps mime type to MTP format code private static HashMap<String, Integer> sMimeTypeToFormatMap = new HashMap<String, Integer>(); static void addFileType(String extension, int fileType, String mimeType) { sFileTypeMap.put(extension, new MediaFileType(fileType, mimeType)); sMimeTypeMap.put(mimeType, Integer.valueOf(fileType)); } static void addFileType(String extension, int fileType, String mimeType, int mtpFormatCode) { addFileType(extension, fileType, mimeType); sFileTypeToFormatMap.put(extension, Integer.valueOf(mtpFormatCode)); sMimeTypeToFormatMap.put(mimeType, Integer.valueOf(mtpFormatCode)); } private static boolean isWMAEnabled() { List<AudioDecoder> decoders = DecoderCapabilities.getAudioDecoders(); for (AudioDecoder decoder: decoders) { Loading @@ -126,17 +140,17 @@ public class MediaFile { } static { addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg"); addFileType("M4A", FILE_TYPE_M4A, "audio/mp4"); addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav"); addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg", Mtp.Object.FORMAT_MP3); addFileType("M4A", FILE_TYPE_M4A, "audio/mp4", Mtp.Object.FORMAT_MPEG); addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav", Mtp.Object.FORMAT_WAV); 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"); addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma", Mtp.Object.FORMAT_WMA); } addFileType("OGG", FILE_TYPE_OGG, "application/ogg"); addFileType("OGA", FILE_TYPE_OGG, "application/ogg"); addFileType("AAC", FILE_TYPE_AAC, "audio/aac"); addFileType("OGG", FILE_TYPE_OGG, "application/ogg", Mtp.Object.FORMAT_OGG); addFileType("OGA", FILE_TYPE_OGG, "application/ogg", Mtp.Object.FORMAT_OGG); addFileType("AAC", FILE_TYPE_AAC, "audio/aac", Mtp.Object.FORMAT_AAC); addFileType("MKA", FILE_TYPE_MKA, "audio/x-matroska"); addFileType("MID", FILE_TYPE_MID, "audio/midi"); Loading @@ -148,32 +162,32 @@ public class MediaFile { addFileType("RTX", FILE_TYPE_MID, "audio/midi"); addFileType("OTA", FILE_TYPE_MID, "audio/midi"); addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg"); addFileType("MP4", FILE_TYPE_MP4, "video/mp4"); addFileType("M4V", FILE_TYPE_M4V, "video/mp4"); addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp"); addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp"); addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2"); addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2"); addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg", Mtp.Object.FORMAT_MPEG); addFileType("MP4", FILE_TYPE_MP4, "video/mp4", Mtp.Object.FORMAT_MPEG); addFileType("M4V", FILE_TYPE_M4V, "video/mp4", Mtp.Object.FORMAT_MPEG); addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp", Mtp.Object.FORMAT_3GP_CONTAINER); addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp", Mtp.Object.FORMAT_3GP_CONTAINER); addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2", Mtp.Object.FORMAT_3GP_CONTAINER); addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2", Mtp.Object.FORMAT_3GP_CONTAINER); addFileType("MKV", FILE_TYPE_MKV, "video/x-matroska"); addFileType("WEBM", FILE_TYPE_MKV, "video/x-matroska"); addFileType("TS", FILE_TYPE_MP2TS, "video/mp2ts"); if (isWMVEnabled()) { addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv"); addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv", Mtp.Object.FORMAT_WMV); addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf"); } addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg"); addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg"); addFileType("GIF", FILE_TYPE_GIF, "image/gif"); addFileType("PNG", FILE_TYPE_PNG, "image/png"); addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp"); addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg", Mtp.Object.FORMAT_EXIF_JPEG); addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg", Mtp.Object.FORMAT_EXIF_JPEG); addFileType("GIF", FILE_TYPE_GIF, "image/gif", Mtp.Object.FORMAT_GIF); addFileType("PNG", FILE_TYPE_PNG, "image/png", Mtp.Object.FORMAT_PNG); addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp", Mtp.Object.FORMAT_BMP); addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp"); addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl"); addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls"); addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl"); addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl", Mtp.Object.FORMAT_M3U_PLAYLIST); addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls", Mtp.Object.FORMAT_PLS_PLAYLIST); addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl", Mtp.Object.FORMAT_WPL_PLAYLIST); // compute file extensions list for native Media Scanner StringBuilder builder = new StringBuilder(); Loading Loading @@ -222,4 +236,21 @@ public class MediaFile { return (value == null ? 0 : value.intValue()); } public static int getFormatCode(String fileName, String mimeType) { if (mimeType != null) { Integer value = sMimeTypeToFormatMap.get(mimeType); if (value != null) { return value.intValue(); } } int lastDot = fileName.lastIndexOf('.'); if (lastDot > 0) { String extension = fileName.substring(lastDot + 1); Integer value = sFileTypeToFormatMap.get(extension); if (value != null) { return value.intValue(); } } return Mtp.Object.FORMAT_UNDEFINED; } } media/java/android/media/MtpDatabase.java 0 → 100644 +223 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 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 android.media; import android.content.Context; import android.content.IContentProvider; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; import android.provider.MediaStore.MtpObjects; import android.util.Log; /** * {@hide} */ public class MtpDatabase { private static final String TAG = "MtpDatabase"; private final IContentProvider mMediaProvider; private final String mVolumeName; private final Uri mObjectsUri; private static final String[] ID_PROJECTION = new String[] { MtpObjects.ObjectColumns._ID, // 0 }; private static final String[] PATH_SIZE_PROJECTION = new String[] { MtpObjects.ObjectColumns._ID, // 0 MtpObjects.ObjectColumns.DATA, // 1 MtpObjects.ObjectColumns.SIZE, // 2 }; private static final String[] OBJECT_INFO_PROJECTION = new String[] { MtpObjects.ObjectColumns._ID, // 0 MtpObjects.ObjectColumns.DATA, // 1 MtpObjects.ObjectColumns.FORMAT, // 2 MtpObjects.ObjectColumns.PARENT, // 3 MtpObjects.ObjectColumns.SIZE, // 4 MtpObjects.ObjectColumns.DATE_MODIFIED, // 5 }; private static final String ID_WHERE = MtpObjects.ObjectColumns._ID + "=?"; private static final String PATH_WHERE = MtpObjects.ObjectColumns.DATA + "=?"; private static final String PARENT_WHERE = MtpObjects.ObjectColumns.PARENT + "=?"; private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " + MtpObjects.ObjectColumns.FORMAT + "=?"; static { System.loadLibrary("media_jni"); } public MtpDatabase(Context context, String volumeName) { native_setup(); mMediaProvider = context.getContentResolver().acquireProvider("media"); mVolumeName = volumeName; mObjectsUri = MtpObjects.getContentUri(volumeName); } @Override protected void finalize() { native_finalize(); } // called from native code private int getObjectHandle(String path) { Log.d(TAG, "getObjectHandle " + path); Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE, new String[] { path }, null); if (c != null && c.moveToNext()) { return c.getInt(0); } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectHandle", e); } finally { if (c != null) { c.close(); } } return 0; } private int addFile(String path, int format, int parent, int storage, long size, long modified) { Log.d(TAG, "addFile " + path); return 0; } private int[] getObjectList(int storageID, int format, int parent) { // we can ignore storageID until we support multiple storages Log.d(TAG, "getObjectList parent: " + parent); Cursor c = null; try { if (format != 0) { c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_FORMAT_WHERE, new String[] { Integer.toString(parent), Integer.toString(format) }, null); } else { c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE, new String[] { Integer.toString(parent) }, null); } if (c == null) { Log.d(TAG, "null cursor"); return null; } int count = c.getCount(); if (count > 0) { int[] result = new int[count]; for (int i = 0; i < count; i++) { c.moveToNext(); result[i] = c.getInt(0); } Log.d(TAG, "returning " + result); return result; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectList", e); } finally { if (c != null) { c.close(); } } return null; } private int getObjectProperty(int handle, int property, long[] outIntValue, char[] outStringValue) { Log.d(TAG, "getObjectProperty: " + property); return 0; } private boolean getObjectInfo(int handle, int[] outStorageFormatParent, char[] outName, long[] outSizeModified) { Log.d(TAG, "getObjectInfo: " + handle); Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, ID_WHERE, new String[] { Integer.toString(handle) }, null); if (c != null && c.moveToNext()) { outStorageFormatParent[0] = 0x00010001; outStorageFormatParent[1] = c.getInt(2); outStorageFormatParent[2] = c.getInt(3); // extract name from path String path = c.getString(1); int lastSlash = path.lastIndexOf('/'); int start = (lastSlash >= 0 ? lastSlash + 1 : 0); int end = path.length(); if (end - start > 255) { end = start + 255; } path.getChars(start, end, outName, 0); outName[end - start] = 0; outSizeModified[0] = c.getLong(4); outSizeModified[1] = c.getLong(5); return true; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectProperty", e); } finally { if (c != null) { c.close(); } } return false; } private boolean getObjectFilePath(int handle, char[] outFilePath, long[] outFileLength) { Log.d(TAG, "getObjectFilePath: " + handle); Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, PATH_SIZE_PROJECTION, ID_WHERE, new String[] { Integer.toString(handle) }, null); if (c != null && c.moveToNext()) { String path = c.getString(1); path.getChars(0, path.length(), outFilePath, 0); outFilePath[path.length()] = 0; outFileLength[0] = c.getLong(2); return true; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectFilePath", e); } finally { if (c != null) { c.close(); } } return false; } private boolean deleteFile(int handle) { Log.d(TAG, "deleteFile: " + handle); Uri uri = MtpObjects.getContentUri(mVolumeName, handle); try { return (mMediaProvider.delete(uri, null, null) == 1); } catch (RemoteException e) { Log.e(TAG, "RemoteException in deleteFile", e); return false; } } // used by the JNI code private int mNativeContext; private native final void native_setup(); private native final void native_finalize(); } media/java/android/media/MtpServer.java +3 −3 Original line number Diff line number Diff line Loading @@ -30,8 +30,8 @@ public class MtpServer { System.loadLibrary("media_jni"); } public MtpServer(String storagePath, String databasePath) { native_setup(storagePath, databasePath); public MtpServer(MtpDatabase database, String storagePath) { native_setup(database, storagePath); } @Override Loading @@ -50,7 +50,7 @@ public class MtpServer { // used by the JNI code private int mNativeContext; private native final void native_setup(String storagePath, String databasePath); private native final void native_setup(MtpDatabase database, String storagePath); private native final void native_finalize(); private native final void native_start(); private native final void native_stop(); Loading media/jni/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ LOCAL_SRC_FILES:= \ android_media_AmrInputStream.cpp \ android_media_MtpClient.cpp \ android_media_MtpCursor.cpp \ android_media_MtpDatabase.cpp \ android_media_MtpServer.cpp \ LOCAL_SHARED_LIBRARIES := \ Loading Loading
core/java/android/provider/MediaStore.java +38 −0 Original line number Diff line number Diff line Loading @@ -239,6 +239,44 @@ public final class MediaStore { public static final String MIME_TYPE = "mime_type"; } /** * Media provider interface used by MTP implementation. * @hide */ public static final class MtpObjects { public static Uri getContentUri(String volumeName) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object"); } public static final Uri getContentUri(String volumeName, long objectId) { return Uri.parse(CONTENT_AUTHORITY_SLASH + volumeName + "/object/" + objectId); } /** * Fields for master table for all media files. * Table also contains MediaColumns._ID, DATA, SIZE and DATE_MODIFIED. */ public interface ObjectColumns extends MediaColumns { /** * The MTP format code of the file * <P>Type: INTEGER</P> */ public static final String FORMAT = "format"; /** * The index of the parent directory of the file * <P>Type: INTEGER</P> */ public static final String PARENT = "parent"; } } /** * This class is used internally by Images.Thumbnails and Video.Thumbnails, it's not intended * to be accessed elsewhere. Loading
media/java/android/media/MediaFile.java +57 −26 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.ContentValues; import android.provider.MediaStore.Audio; import android.provider.MediaStore.Images; import android.provider.MediaStore.Video; import android.provider.Mtp; import android.media.DecoderCapabilities; import android.media.DecoderCapabilities.VideoDecoder; import android.media.DecoderCapabilities.AudioDecoder; Loading Loading @@ -100,11 +101,24 @@ public class MediaFile { = new HashMap<String, MediaFileType>(); private static HashMap<String, Integer> sMimeTypeMap = new HashMap<String, Integer>(); // maps file extension to MTP format code private static HashMap<String, Integer> sFileTypeToFormatMap = new HashMap<String, Integer>(); // maps mime type to MTP format code private static HashMap<String, Integer> sMimeTypeToFormatMap = new HashMap<String, Integer>(); static void addFileType(String extension, int fileType, String mimeType) { sFileTypeMap.put(extension, new MediaFileType(fileType, mimeType)); sMimeTypeMap.put(mimeType, Integer.valueOf(fileType)); } static void addFileType(String extension, int fileType, String mimeType, int mtpFormatCode) { addFileType(extension, fileType, mimeType); sFileTypeToFormatMap.put(extension, Integer.valueOf(mtpFormatCode)); sMimeTypeToFormatMap.put(mimeType, Integer.valueOf(mtpFormatCode)); } private static boolean isWMAEnabled() { List<AudioDecoder> decoders = DecoderCapabilities.getAudioDecoders(); for (AudioDecoder decoder: decoders) { Loading @@ -126,17 +140,17 @@ public class MediaFile { } static { addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg"); addFileType("M4A", FILE_TYPE_M4A, "audio/mp4"); addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav"); addFileType("MP3", FILE_TYPE_MP3, "audio/mpeg", Mtp.Object.FORMAT_MP3); addFileType("M4A", FILE_TYPE_M4A, "audio/mp4", Mtp.Object.FORMAT_MPEG); addFileType("WAV", FILE_TYPE_WAV, "audio/x-wav", Mtp.Object.FORMAT_WAV); 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"); addFileType("WMA", FILE_TYPE_WMA, "audio/x-ms-wma", Mtp.Object.FORMAT_WMA); } addFileType("OGG", FILE_TYPE_OGG, "application/ogg"); addFileType("OGA", FILE_TYPE_OGG, "application/ogg"); addFileType("AAC", FILE_TYPE_AAC, "audio/aac"); addFileType("OGG", FILE_TYPE_OGG, "application/ogg", Mtp.Object.FORMAT_OGG); addFileType("OGA", FILE_TYPE_OGG, "application/ogg", Mtp.Object.FORMAT_OGG); addFileType("AAC", FILE_TYPE_AAC, "audio/aac", Mtp.Object.FORMAT_AAC); addFileType("MKA", FILE_TYPE_MKA, "audio/x-matroska"); addFileType("MID", FILE_TYPE_MID, "audio/midi"); Loading @@ -148,32 +162,32 @@ public class MediaFile { addFileType("RTX", FILE_TYPE_MID, "audio/midi"); addFileType("OTA", FILE_TYPE_MID, "audio/midi"); addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg"); addFileType("MP4", FILE_TYPE_MP4, "video/mp4"); addFileType("M4V", FILE_TYPE_M4V, "video/mp4"); addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp"); addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp"); addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2"); addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2"); addFileType("MPEG", FILE_TYPE_MP4, "video/mpeg", Mtp.Object.FORMAT_MPEG); addFileType("MP4", FILE_TYPE_MP4, "video/mp4", Mtp.Object.FORMAT_MPEG); addFileType("M4V", FILE_TYPE_M4V, "video/mp4", Mtp.Object.FORMAT_MPEG); addFileType("3GP", FILE_TYPE_3GPP, "video/3gpp", Mtp.Object.FORMAT_3GP_CONTAINER); addFileType("3GPP", FILE_TYPE_3GPP, "video/3gpp", Mtp.Object.FORMAT_3GP_CONTAINER); addFileType("3G2", FILE_TYPE_3GPP2, "video/3gpp2", Mtp.Object.FORMAT_3GP_CONTAINER); addFileType("3GPP2", FILE_TYPE_3GPP2, "video/3gpp2", Mtp.Object.FORMAT_3GP_CONTAINER); addFileType("MKV", FILE_TYPE_MKV, "video/x-matroska"); addFileType("WEBM", FILE_TYPE_MKV, "video/x-matroska"); addFileType("TS", FILE_TYPE_MP2TS, "video/mp2ts"); if (isWMVEnabled()) { addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv"); addFileType("WMV", FILE_TYPE_WMV, "video/x-ms-wmv", Mtp.Object.FORMAT_WMV); addFileType("ASF", FILE_TYPE_ASF, "video/x-ms-asf"); } addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg"); addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg"); addFileType("GIF", FILE_TYPE_GIF, "image/gif"); addFileType("PNG", FILE_TYPE_PNG, "image/png"); addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp"); addFileType("JPG", FILE_TYPE_JPEG, "image/jpeg", Mtp.Object.FORMAT_EXIF_JPEG); addFileType("JPEG", FILE_TYPE_JPEG, "image/jpeg", Mtp.Object.FORMAT_EXIF_JPEG); addFileType("GIF", FILE_TYPE_GIF, "image/gif", Mtp.Object.FORMAT_GIF); addFileType("PNG", FILE_TYPE_PNG, "image/png", Mtp.Object.FORMAT_PNG); addFileType("BMP", FILE_TYPE_BMP, "image/x-ms-bmp", Mtp.Object.FORMAT_BMP); addFileType("WBMP", FILE_TYPE_WBMP, "image/vnd.wap.wbmp"); addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl"); addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls"); addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl"); addFileType("M3U", FILE_TYPE_M3U, "audio/x-mpegurl", Mtp.Object.FORMAT_M3U_PLAYLIST); addFileType("PLS", FILE_TYPE_PLS, "audio/x-scpls", Mtp.Object.FORMAT_PLS_PLAYLIST); addFileType("WPL", FILE_TYPE_WPL, "application/vnd.ms-wpl", Mtp.Object.FORMAT_WPL_PLAYLIST); // compute file extensions list for native Media Scanner StringBuilder builder = new StringBuilder(); Loading Loading @@ -222,4 +236,21 @@ public class MediaFile { return (value == null ? 0 : value.intValue()); } public static int getFormatCode(String fileName, String mimeType) { if (mimeType != null) { Integer value = sMimeTypeToFormatMap.get(mimeType); if (value != null) { return value.intValue(); } } int lastDot = fileName.lastIndexOf('.'); if (lastDot > 0) { String extension = fileName.substring(lastDot + 1); Integer value = sFileTypeToFormatMap.get(extension); if (value != null) { return value.intValue(); } } return Mtp.Object.FORMAT_UNDEFINED; } }
media/java/android/media/MtpDatabase.java 0 → 100644 +223 −0 Original line number Diff line number Diff line /* * Copyright (C) 2010 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 android.media; import android.content.Context; import android.content.IContentProvider; import android.database.Cursor; import android.net.Uri; import android.os.RemoteException; import android.provider.MediaStore.MtpObjects; import android.util.Log; /** * {@hide} */ public class MtpDatabase { private static final String TAG = "MtpDatabase"; private final IContentProvider mMediaProvider; private final String mVolumeName; private final Uri mObjectsUri; private static final String[] ID_PROJECTION = new String[] { MtpObjects.ObjectColumns._ID, // 0 }; private static final String[] PATH_SIZE_PROJECTION = new String[] { MtpObjects.ObjectColumns._ID, // 0 MtpObjects.ObjectColumns.DATA, // 1 MtpObjects.ObjectColumns.SIZE, // 2 }; private static final String[] OBJECT_INFO_PROJECTION = new String[] { MtpObjects.ObjectColumns._ID, // 0 MtpObjects.ObjectColumns.DATA, // 1 MtpObjects.ObjectColumns.FORMAT, // 2 MtpObjects.ObjectColumns.PARENT, // 3 MtpObjects.ObjectColumns.SIZE, // 4 MtpObjects.ObjectColumns.DATE_MODIFIED, // 5 }; private static final String ID_WHERE = MtpObjects.ObjectColumns._ID + "=?"; private static final String PATH_WHERE = MtpObjects.ObjectColumns.DATA + "=?"; private static final String PARENT_WHERE = MtpObjects.ObjectColumns.PARENT + "=?"; private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " + MtpObjects.ObjectColumns.FORMAT + "=?"; static { System.loadLibrary("media_jni"); } public MtpDatabase(Context context, String volumeName) { native_setup(); mMediaProvider = context.getContentResolver().acquireProvider("media"); mVolumeName = volumeName; mObjectsUri = MtpObjects.getContentUri(volumeName); } @Override protected void finalize() { native_finalize(); } // called from native code private int getObjectHandle(String path) { Log.d(TAG, "getObjectHandle " + path); Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE, new String[] { path }, null); if (c != null && c.moveToNext()) { return c.getInt(0); } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectHandle", e); } finally { if (c != null) { c.close(); } } return 0; } private int addFile(String path, int format, int parent, int storage, long size, long modified) { Log.d(TAG, "addFile " + path); return 0; } private int[] getObjectList(int storageID, int format, int parent) { // we can ignore storageID until we support multiple storages Log.d(TAG, "getObjectList parent: " + parent); Cursor c = null; try { if (format != 0) { c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_FORMAT_WHERE, new String[] { Integer.toString(parent), Integer.toString(format) }, null); } else { c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE, new String[] { Integer.toString(parent) }, null); } if (c == null) { Log.d(TAG, "null cursor"); return null; } int count = c.getCount(); if (count > 0) { int[] result = new int[count]; for (int i = 0; i < count; i++) { c.moveToNext(); result[i] = c.getInt(0); } Log.d(TAG, "returning " + result); return result; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectList", e); } finally { if (c != null) { c.close(); } } return null; } private int getObjectProperty(int handle, int property, long[] outIntValue, char[] outStringValue) { Log.d(TAG, "getObjectProperty: " + property); return 0; } private boolean getObjectInfo(int handle, int[] outStorageFormatParent, char[] outName, long[] outSizeModified) { Log.d(TAG, "getObjectInfo: " + handle); Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, ID_WHERE, new String[] { Integer.toString(handle) }, null); if (c != null && c.moveToNext()) { outStorageFormatParent[0] = 0x00010001; outStorageFormatParent[1] = c.getInt(2); outStorageFormatParent[2] = c.getInt(3); // extract name from path String path = c.getString(1); int lastSlash = path.lastIndexOf('/'); int start = (lastSlash >= 0 ? lastSlash + 1 : 0); int end = path.length(); if (end - start > 255) { end = start + 255; } path.getChars(start, end, outName, 0); outName[end - start] = 0; outSizeModified[0] = c.getLong(4); outSizeModified[1] = c.getLong(5); return true; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectProperty", e); } finally { if (c != null) { c.close(); } } return false; } private boolean getObjectFilePath(int handle, char[] outFilePath, long[] outFileLength) { Log.d(TAG, "getObjectFilePath: " + handle); Cursor c = null; try { c = mMediaProvider.query(mObjectsUri, PATH_SIZE_PROJECTION, ID_WHERE, new String[] { Integer.toString(handle) }, null); if (c != null && c.moveToNext()) { String path = c.getString(1); path.getChars(0, path.length(), outFilePath, 0); outFilePath[path.length()] = 0; outFileLength[0] = c.getLong(2); return true; } } catch (RemoteException e) { Log.e(TAG, "RemoteException in getObjectFilePath", e); } finally { if (c != null) { c.close(); } } return false; } private boolean deleteFile(int handle) { Log.d(TAG, "deleteFile: " + handle); Uri uri = MtpObjects.getContentUri(mVolumeName, handle); try { return (mMediaProvider.delete(uri, null, null) == 1); } catch (RemoteException e) { Log.e(TAG, "RemoteException in deleteFile", e); return false; } } // used by the JNI code private int mNativeContext; private native final void native_setup(); private native final void native_finalize(); }
media/java/android/media/MtpServer.java +3 −3 Original line number Diff line number Diff line Loading @@ -30,8 +30,8 @@ public class MtpServer { System.loadLibrary("media_jni"); } public MtpServer(String storagePath, String databasePath) { native_setup(storagePath, databasePath); public MtpServer(MtpDatabase database, String storagePath) { native_setup(database, storagePath); } @Override Loading @@ -50,7 +50,7 @@ public class MtpServer { // used by the JNI code private int mNativeContext; private native final void native_setup(String storagePath, String databasePath); private native final void native_setup(MtpDatabase database, String storagePath); private native final void native_finalize(); private native final void native_start(); private native final void native_stop(); Loading
media/jni/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -15,6 +15,7 @@ LOCAL_SRC_FILES:= \ android_media_AmrInputStream.cpp \ android_media_MtpClient.cpp \ android_media_MtpCursor.cpp \ android_media_MtpDatabase.cpp \ android_media_MtpServer.cpp \ LOCAL_SHARED_LIBRARIES := \ Loading