MtpDatabase.java revision 7a047c89862febf63ce1bb5873179c7a2ff8d9d3
1d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/* 2d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 3d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * 4d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 5d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * you may not use this file except in compliance with the License. 6d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * You may obtain a copy of the License at 7d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * 8d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 9d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * 10d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Unless required by applicable law or agreed to in writing, software 11d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 12d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * See the License for the specific language governing permissions and 14d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * limitations under the License. 15d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */ 16d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 17d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpackage android.media; 18d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 19d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.Context; 20d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodimport android.content.ContentValues; 21d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.IContentProvider; 22d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.database.Cursor; 23d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.net.Uri; 24d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException; 25d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.provider.MediaStore.MtpObjects; 26d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log; 27d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 28d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/** 29d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide} 30d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */ 31d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic class MtpDatabase { 32d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 33d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String TAG = "MtpDatabase"; 34d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 35d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final IContentProvider mMediaProvider; 36d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final String mVolumeName; 37d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final Uri mObjectsUri; 38d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 39b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // FIXME - this should be passed in via the constructor 40b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private final int mStorageID = 0x00010001; 41b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 42d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] ID_PROJECTION = new String[] { 43d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns._ID, // 0 44d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 45d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] PATH_SIZE_PROJECTION = new String[] { 46d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns._ID, // 0 47d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.DATA, // 1 48d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.SIZE, // 2 49d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 50d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] OBJECT_INFO_PROJECTION = new String[] { 51d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns._ID, // 0 52d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.DATA, // 1 53d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.FORMAT, // 2 54d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.PARENT, // 3 55d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.SIZE, // 4 56d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.DATE_MODIFIED, // 5 57d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 58d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String ID_WHERE = MtpObjects.ObjectColumns._ID + "=?"; 59d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String PATH_WHERE = MtpObjects.ObjectColumns.DATA + "=?"; 60d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String PARENT_WHERE = MtpObjects.ObjectColumns.PARENT + "=?"; 61d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " 62d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood + MtpObjects.ObjectColumns.FORMAT + "=?"; 63d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 64d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private final MediaScanner mMediaScanner; 65d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 66b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // MTP property codes 67b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_STORAGE_ID = 0xDC01; 68b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_OBJECT_FORMAT = 0xDC02; 69b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_OBJECT_SIZE = 0xDC04; 70b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_OBJECT_FILE_NAME = 0xDC07; 71b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_DATE_MODIFIED = 0xDC09; 72b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_PARENT_OBJECT = 0xDC0B; 73b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 74b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // MTP response codes 75b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_RESPONSE_OK = 0x2001; 76b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_RESPONSE_GENERAL_ERROR = 0x2002; 77b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_RESPONSE_INVALID_OBJECT_HANDLE = 0x2009; 78b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED = 0xA80A; 79b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 80d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood static { 81d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood System.loadLibrary("media_jni"); 82d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 83d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 84d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood public MtpDatabase(Context context, String volumeName) { 85d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood native_setup(); 86d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 87d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mMediaProvider = context.getContentResolver().acquireProvider("media"); 88d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mVolumeName = volumeName; 89d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mObjectsUri = MtpObjects.getContentUri(volumeName); 90d815f79766984fce499e147ecbacc01914683f74Mike Lockwood mMediaScanner = new MediaScanner(context); 91d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 92d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 93d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood @Override 94d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood protected void finalize() { 95d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood native_finalize(); 96d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 97d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 98d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private int beginSendObject(String path, int format, int parent, 99d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int storage, long size, long modified) { 100d815f79766984fce499e147ecbacc01914683f74Mike Lockwood ContentValues values = new ContentValues(); 101d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.DATA, path); 102d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.FORMAT, format); 103d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.PARENT, parent); 104d815f79766984fce499e147ecbacc01914683f74Mike Lockwood // storage is ignored for now 105d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.SIZE, size); 106d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.DATE_MODIFIED, modified); 107d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 108d815f79766984fce499e147ecbacc01914683f74Mike Lockwood try { 109d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Uri uri = mMediaProvider.insert(mObjectsUri, values); 110d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (uri != null) { 111d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return Integer.parseInt(uri.getPathSegments().get(2)); 112d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 113d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 114d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 115d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } catch (RemoteException e) { 116d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Log.e(TAG, "RemoteException in beginSendObject", e); 117d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 118d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 119d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 120d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 121d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private void endSendObject(String path, int handle, int format, boolean succeeded) { 122d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (succeeded) { 123d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Uri uri = mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); 124d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 125d815f79766984fce499e147ecbacc01914683f74Mike Lockwood deleteFile(handle); 126d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 127d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 128d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 129d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int[] getObjectList(int storageID, int format, int parent) { 130d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // we can ignore storageID until we support multiple storages 131d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectList parent: " + parent); 132d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 133d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 134d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (format != 0) { 135d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 136d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood PARENT_FORMAT_WHERE, 137d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood new String[] { Integer.toString(parent), Integer.toString(format) }, 138d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood null); 139d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } else { 140d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 141d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood PARENT_WHERE, new String[] { Integer.toString(parent) }, null); 142d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 143d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c == null) { 144d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "null cursor"); 145d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 146d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 147d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int count = c.getCount(); 148d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (count > 0) { 149d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int[] result = new int[count]; 150d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood for (int i = 0; i < count; i++) { 151d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.moveToNext(); 152d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood result[i] = c.getInt(0); 153d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 154d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "returning " + result); 155d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return result; 156d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 157d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 158d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 159d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 160d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 161d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 162d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 163d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 164d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 165d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 166d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 1677a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood private int getNumObjects(int storageID, int format, int parent) { 1687a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood // we can ignore storageID until we support multiple storages 1697a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Log.d(TAG, "getObjectList parent: " + parent); 1707a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Cursor c = null; 1717a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood try { 1727a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (format != 0) { 1737a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 1747a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood PARENT_FORMAT_WHERE, 1757a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood new String[] { Integer.toString(parent), Integer.toString(format) }, 1767a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood null); 1777a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } else { 1787a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 1797a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood PARENT_WHERE, new String[] { Integer.toString(parent) }, null); 1807a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 1817a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 1827a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return c.getCount(); 1837a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 1847a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } catch (RemoteException e) { 1857a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Log.e(TAG, "RemoteException in getNumObjects", e); 1867a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } finally { 1877a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 1887a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c.close(); 1897a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 1907a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 1917a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return -1; 1927a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 1937a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood 194d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int getObjectProperty(int handle, int property, 195d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood long[] outIntValue, char[] outStringValue) { 196d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectProperty: " + property); 197b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood String column = null; 198b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood boolean isString = false; 199b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 200b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood switch (property) { 201b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_STORAGE_ID: 202b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outIntValue[0] = mStorageID; 203b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_OK; 204b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_OBJECT_FORMAT: 205b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.FORMAT; 206b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 207b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_OBJECT_SIZE: 208b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.SIZE; 209b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 210b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_OBJECT_FILE_NAME: 211b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.DATA; 212b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood isString = true; 213b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 214b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_DATE_MODIFIED: 215b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.DATE_MODIFIED; 216b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 217b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_PARENT_OBJECT: 218b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.PARENT; 219b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 220b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood default: 221b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 222b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 223b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 224b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood Cursor c = null; 225b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood try { 226b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // for now we are only reading properties from the "objects" table 227b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood c = mMediaProvider.query(mObjectsUri, 228b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood new String [] { MtpObjects.ObjectColumns._ID, column }, 229b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 230b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (c != null && c.moveToNext()) { 231b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (isString) { 232b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood String value = c.getString(1); 233b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int start = 0; 234b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 235b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (property == MTP_PROPERTY_OBJECT_FILE_NAME) { 236b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // extract name from full path 237b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int lastSlash = value.lastIndexOf('/'); 238b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (lastSlash >= 0) { 239b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood start = lastSlash + 1; 240b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 241b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 242b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int end = value.length(); 243b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (end - start > 255) { 244b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood end = start + 255; 245b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 246b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood value.getChars(start, end, outStringValue, 0); 247b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outStringValue[end - start] = 0; 248b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } else { 249b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outIntValue[0] = c.getLong(1); 250b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 251b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_OK; 252b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 253b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } catch (Exception e) { 254b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 255b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } finally { 256b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (c != null) { 257b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood c.close(); 258b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 259b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 260b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // query failed if we get here 261b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 262d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 263d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 264d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private boolean getObjectInfo(int handle, int[] outStorageFormatParent, 265d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood char[] outName, long[] outSizeModified) { 266d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectInfo: " + handle); 267d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 268d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 269d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, 270d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 271d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 272b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outStorageFormatParent[0] = mStorageID; 273d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[1] = c.getInt(2); 274d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[2] = c.getInt(3); 275d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 276d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // extract name from path 277d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood String path = c.getString(1); 278d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int lastSlash = path.lastIndexOf('/'); 279d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int start = (lastSlash >= 0 ? lastSlash + 1 : 0); 280d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int end = path.length(); 281d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (end - start > 255) { 282d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood end = start + 255; 283d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 284d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(start, end, outName, 0); 285d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outName[end - start] = 0; 286d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 287d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outSizeModified[0] = c.getLong(4); 288d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outSizeModified[1] = c.getLong(5); 289d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return true; 290d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 291d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 292d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectProperty", e); 293d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 294d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 295d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 296d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 297d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 298d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return false; 299d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 300d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 30159c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLength) { 302d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectFilePath: " + handle); 303d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 304d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 305d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, PATH_SIZE_PROJECTION, 306d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 307d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 308d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood String path = c.getString(1); 309d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(0, path.length(), outFilePath, 0); 310d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outFilePath[path.length()] = 0; 311d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outFileLength[0] = c.getLong(2); 31259c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_OK; 31359c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 31459c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 315d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 316d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 317d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectFilePath", e); 31859c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 319d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 320d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 321d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 322d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 323d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 324d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 325d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 32659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood private int deleteFile(int handle) { 327d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "deleteFile: " + handle); 328d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Uri uri = MtpObjects.getContentUri(mVolumeName, handle); 329d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 33059c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood if (mMediaProvider.delete(uri, null, null) == 1) { 33159c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_OK; 33259c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 33359c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 33459c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } 335d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 336d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in deleteFile", e); 33759c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 338d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 339d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 340d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 341d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // used by the JNI code 342d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int mNativeContext; 343d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 344d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_setup(); 345d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_finalize(); 346d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood} 347