diff options
author | Mike Lockwood <lockwood@android.com> | 2011-04-05 10:21:27 -0400 |
---|---|---|
committer | Mike Lockwood <lockwood@android.com> | 2011-05-04 10:41:20 -0400 |
commit | d3e4290c0442b6dcf24bcf642f4fc26d12d8e7aa (patch) | |
tree | 4604a25cd5f0617b9667f7b2d03ab56d57e13207 /media/java | |
parent | 10fbba21e4827a1582d97aa99e4e8d772ce04920 (diff) | |
download | frameworks_base-d3e4290c0442b6dcf24bcf642f4fc26d12d8e7aa.zip frameworks_base-d3e4290c0442b6dcf24bcf642f4fc26d12d8e7aa.tar.gz frameworks_base-d3e4290c0442b6dcf24bcf642f4fc26d12d8e7aa.tar.bz2 |
DO NOT MERGE MTP and media provider support for multiple storage devices:
- MTP support for multiple storage units
- Add storage_id column to media database for MTP storage ID
- Add framework resource for defining mount points and user visible descriptions
for multiple volumes
- Clean up locking in MtpServer JNI code
Change-Id: I53d501fd4891ebe27408135fb598027e06b7e495
Signed-off-by: Mike Lockwood <lockwood@android.com>
Diffstat (limited to 'media/java')
-rw-r--r-- | media/java/android/mtp/MtpDatabase.java | 78 | ||||
-rw-r--r-- | media/java/android/mtp/MtpPropertyGroup.java | 11 | ||||
-rw-r--r-- | media/java/android/mtp/MtpServer.java | 20 | ||||
-rw-r--r-- | media/java/android/mtp/MtpStorage.java | 89 |
4 files changed, 152 insertions, 46 deletions
diff --git a/media/java/android/mtp/MtpDatabase.java b/media/java/android/mtp/MtpDatabase.java index b4a4689..b900671 100644 --- a/media/java/android/mtp/MtpDatabase.java +++ b/media/java/android/mtp/MtpDatabase.java @@ -50,7 +50,8 @@ public class MtpDatabase { private final IContentProvider mMediaProvider; private final String mVolumeName; private final Uri mObjectsUri; - private final String mMediaStoragePath; + private final String mMediaStoragePath; // path to primary storage + private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>(); // cached property groups for single properties private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByProperty @@ -67,9 +68,6 @@ public class MtpDatabase { private SharedPreferences mDeviceProperties; private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1; - // FIXME - this should be passed in via the constructor - private final int mStorageID = 0x00010001; - private static final String[] ID_PROJECTION = new String[] { Files.FileColumns._ID, // 0 }; @@ -85,17 +83,22 @@ public class MtpDatabase { }; private static final String[] OBJECT_INFO_PROJECTION = new String[] { Files.FileColumns._ID, // 0 - Files.FileColumns.DATA, // 1 + Files.FileColumns.STORAGE_ID, // 1 Files.FileColumns.FORMAT, // 2 Files.FileColumns.PARENT, // 3 - Files.FileColumns.SIZE, // 4 - Files.FileColumns.DATE_MODIFIED, // 5 + Files.FileColumns.DATA, // 4 + Files.FileColumns.SIZE, // 5 + Files.FileColumns.DATE_MODIFIED, // 6 }; private static final String ID_WHERE = Files.FileColumns._ID + "=?"; private static final String PATH_WHERE = Files.FileColumns.DATA + "=?"; private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?"; private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " + Files.FileColumns.FORMAT + "=?"; + private static final String PARENT_STORAGE_WHERE = PARENT_WHERE + " AND " + + Files.FileColumns.STORAGE_ID + "=?"; + private static final String PARENT_STORAGE_FORMAT_WHERE = PARENT_STORAGE_WHERE + " AND " + + Files.FileColumns.FORMAT + "=?"; private final MediaScanner mMediaScanner; @@ -124,6 +127,14 @@ public class MtpDatabase { } } + public void addStorage(MtpStorage storage) { + mStorageMap.put(storage.getPath(), storage); + } + + public void removeStorage(MtpStorage storage) { + mStorageMap.remove(storage.getPath()); + } + private void initDeviceProperties(Context context) { final String devicePropertiesName = "device-properties"; mDeviceProperties = context.getSharedPreferences(devicePropertiesName, Context.MODE_PRIVATE); @@ -160,7 +171,7 @@ public class MtpDatabase { } private int beginSendObject(String path, int format, int parent, - int storage, long size, long modified) { + int storageId, long size, long modified) { // first make sure the object does not exist if (path != null) { Cursor c = null; @@ -185,7 +196,7 @@ public class MtpDatabase { values.put(Files.FileColumns.DATA, path); values.put(Files.FileColumns.FORMAT, format); values.put(Files.FileColumns.PARENT, parent); - // storage is ignored for now + values.put(Files.FileColumns.STORAGE_ID, storageId); values.put(Files.FileColumns.SIZE, size); values.put(Files.FileColumns.DATE_MODIFIED, modified); @@ -237,19 +248,35 @@ public class MtpDatabase { } } - private int[] getObjectList(int storageID, int format, int parent) { - // we can ignore storageID until we support multiple storages - Cursor c = null; - try { + private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException { + if (storageID != 0) { + if (format != 0) { + return mMediaProvider.query(mObjectsUri, ID_PROJECTION, + PARENT_STORAGE_FORMAT_WHERE, + new String[] { Integer.toString(parent), Integer.toString(storageID), + Integer.toString(format) }, null); + } else { + return mMediaProvider.query(mObjectsUri, ID_PROJECTION, + PARENT_STORAGE_WHERE, new String[] + { Integer.toString(parent), Integer.toString(storageID) }, null); + } + } else { if (format != 0) { - c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, + return mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_FORMAT_WHERE, new String[] { Integer.toString(parent), Integer.toString(format) }, null); } else { - c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, + return mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE, new String[] { Integer.toString(parent) }, null); } + } + } + + private int[] getObjectList(int storageID, int format, int parent) { + Cursor c = null; + try { + c = createObjectQuery(storageID, format, parent); if (c == null) { return null; } @@ -273,18 +300,9 @@ public class MtpDatabase { } private int getNumObjects(int storageID, int format, int parent) { - // we can ignore storageID until we support multiple storages 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); - } + c = createObjectQuery(storageID, format, parent); if (c != null) { return c.getCount(); } @@ -508,7 +526,7 @@ public class MtpDatabase { } } - return propertyGroup.getPropertyList((int)handle, format, depth, mStorageID); + return propertyGroup.getPropertyList((int)handle, format, depth); } private int renameFile(int handle, String newName) { @@ -631,12 +649,12 @@ public class MtpDatabase { c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, ID_WHERE, new String[] { Integer.toString(handle) }, null); if (c != null && c.moveToNext()) { - outStorageFormatParent[0] = mStorageID; + outStorageFormatParent[0] = c.getInt(1); outStorageFormatParent[1] = c.getInt(2); outStorageFormatParent[2] = c.getInt(3); // extract name from path - String path = c.getString(1); + String path = c.getString(4); int lastSlash = path.lastIndexOf('/'); int start = (lastSlash >= 0 ? lastSlash + 1 : 0); int end = path.length(); @@ -646,8 +664,8 @@ public class MtpDatabase { path.getChars(start, end, outName, 0); outName[end - start] = 0; - outSizeModified[0] = c.getLong(4); - outSizeModified[1] = c.getLong(5); + outSizeModified[0] = c.getLong(5); + outSizeModified[1] = c.getLong(6); return true; } } catch (RemoteException e) { diff --git a/media/java/android/mtp/MtpPropertyGroup.java b/media/java/android/mtp/MtpPropertyGroup.java index fceedd2..b75b11a 100644 --- a/media/java/android/mtp/MtpPropertyGroup.java +++ b/media/java/android/mtp/MtpPropertyGroup.java @@ -93,7 +93,7 @@ class MtpPropertyGroup { switch (code) { case MtpConstants.PROPERTY_STORAGE_ID: - // no query needed until we support multiple storage units + column = Files.FileColumns.STORAGE_ID; type = MtpConstants.TYPE_UINT32; break; case MtpConstants.PROPERTY_OBJECT_FORMAT: @@ -134,6 +134,7 @@ class MtpPropertyGroup { break; case MtpConstants.PROPERTY_PERSISTENT_UID: // PUID is concatenation of storageID and object handle + column = Files.FileColumns.STORAGE_ID; type = MtpConstants.TYPE_UINT128; break; case MtpConstants.PROPERTY_DURATION: @@ -280,7 +281,7 @@ class MtpPropertyGroup { return path.substring(start, end); } - MtpPropertyList getPropertyList(int handle, int format, int depth, int storageID) { + MtpPropertyList getPropertyList(int handle, int format, int depth) { //Log.d(TAG, "getPropertyList handle: " + handle + " format: " + format + " depth: " + depth); if (depth > 1) { // we only support depth 0 and 1 @@ -348,10 +349,6 @@ class MtpPropertyGroup { // handle some special cases switch (propertyCode) { - case MtpConstants.PROPERTY_STORAGE_ID: - result.append(handle, propertyCode, MtpConstants.TYPE_UINT32, - storageID); - break; case MtpConstants.PROPERTY_PROTECTION_STATUS: // protection status is always 0 result.append(handle, propertyCode, MtpConstants.TYPE_UINT16, 0); @@ -398,7 +395,7 @@ class MtpPropertyGroup { break; case MtpConstants.PROPERTY_PERSISTENT_UID: // PUID is concatenation of storageID and object handle - long puid = storageID; + long puid = c.getLong(column); puid <<= 32; puid += handle; result.append(handle, propertyCode, MtpConstants.TYPE_UINT128, puid); diff --git a/media/java/android/mtp/MtpServer.java b/media/java/android/mtp/MtpServer.java index 006fa6d..c065ca8 100644 --- a/media/java/android/mtp/MtpServer.java +++ b/media/java/android/mtp/MtpServer.java @@ -33,8 +33,8 @@ public class MtpServer { System.loadLibrary("media_jni"); } - public MtpServer(MtpDatabase database, String storagePath, long reserveSpace) { - native_setup(database, storagePath, reserveSpace); + public MtpServer(MtpDatabase database) { + native_setup(database); } public void start() { @@ -65,18 +65,20 @@ public class MtpServer { native_set_ptp_mode(usePtp); } - // Used to disable MTP by removing all storage units. - // This is done to disable access to file transfer when the device is locked. - public void setLocked(boolean locked) { - native_set_locked(locked); + public void addStorage(MtpStorage storage) { + native_add_storage(storage); } - private native final void native_setup(MtpDatabase database, String storagePath, - long reserveSpace); + public void removeStorage(MtpStorage storage) { + native_remove_storage(storage.getStorageId()); + } + + private native final void native_setup(MtpDatabase database); private native final void native_start(); private native final void native_stop(); private native final void native_send_object_added(int handle); private native final void native_send_object_removed(int handle); private native final void native_set_ptp_mode(boolean usePtp); - private native final void native_set_locked(boolean locked); + private native final void native_add_storage(MtpStorage storage); + private native final void native_remove_storage(int storageId); } diff --git a/media/java/android/mtp/MtpStorage.java b/media/java/android/mtp/MtpStorage.java new file mode 100644 index 0000000..33146e7 --- /dev/null +++ b/media/java/android/mtp/MtpStorage.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2011 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.mtp; + +/** + * This class represents a storage unit on an MTP device. + * Used only for MTP support in USB responder mode. + * MtpStorageInfo is used in MTP host mode + * + * @hide + */ +public class MtpStorage { + + private final int mStorageId; + private final String mPath; + private final String mDescription; + private final long mReserveSpace; + + public MtpStorage(int id, String path, String description, long reserveSpace) { + mStorageId = id; + mPath = path; + mDescription = description; + mReserveSpace = reserveSpace; + } + + /** + * Returns the storage ID for the storage unit + * + * @return the storage ID + */ + public final int getStorageId() { + return mStorageId; + } + + /** + * Generates a storage ID for storage of given index. + * Index 0 is for primary external storage + * + * @return the storage ID + */ + public static int getStorageId(int index) { + // storage ID is 0x00010001 for primary storage, + // then 0x00020001, 0x00030001, etc. for secondary storages + return ((index + 1) << 16) + 1; + } + + /** + * Returns the file path for the storage unit's storage in the file system + * + * @return the storage file path + */ + public final String getPath() { + return mPath; + } + + /** + * Returns the description string for the storage unit + * + * @return the storage unit description + */ + public final String getDescription() { + return mDescription; + } + + /** + * Returns the amount of space to reserve on the storage file system. + * This can be set to a non-zero value to prevent MTP from filling up the entire storage. + * + * @return the storage unit description + */ + public final long getReserveSpace() { + return mReserveSpace; + } + +} |