MtpDatabase.java revision 8490e66f57506d4e4b05e7c987c7ca34295843e6
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; 222837eefc5459427138c080d445bb491c75630163Mike Lockwoodimport android.content.Intent; 23d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.database.Cursor; 2459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodimport android.database.sqlite.SQLiteDatabase; 25d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.net.Uri; 26d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException; 279a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.Audio; 289a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.MediaColumns; 293b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwoodimport android.provider.MediaStore.Files; 302837eefc5459427138c080d445bb491c75630163Mike Lockwoodimport android.provider.Mtp; 31d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log; 32d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 33d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/** 34d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide} 35d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */ 36d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic class MtpDatabase { 37d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 38d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String TAG = "MtpDatabase"; 39d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 402837eefc5459427138c080d445bb491c75630163Mike Lockwood private final Context mContext; 41d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final IContentProvider mMediaProvider; 42d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final String mVolumeName; 43d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final Uri mObjectsUri; 44d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 452837eefc5459427138c080d445bb491c75630163Mike Lockwood // true if the database has been modified in the current MTP session 462837eefc5459427138c080d445bb491c75630163Mike Lockwood private boolean mDatabaseModified; 472837eefc5459427138c080d445bb491c75630163Mike Lockwood 4859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood // database for writable MTP device properties 4959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private SQLiteDatabase mDevicePropDb; 5059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1; 5159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 52b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // FIXME - this should be passed in via the constructor 53b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private final int mStorageID = 0x00010001; 54b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 55d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] ID_PROJECTION = new String[] { 563b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 57d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 58d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] PATH_SIZE_PROJECTION = new String[] { 593b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 603b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.DATA, // 1 613b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.SIZE, // 2 62d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 63d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] OBJECT_INFO_PROJECTION = new String[] { 643b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 653b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.DATA, // 1 663b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.FORMAT, // 2 673b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.PARENT, // 3 683b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.SIZE, // 4 693b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.DATE_MODIFIED, // 5 70d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 713b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood private static final String ID_WHERE = Files.FileColumns._ID + "=?"; 723b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood private static final String PATH_WHERE = Files.FileColumns.DATA + "=?"; 733b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?"; 74d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " 753b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood + Files.FileColumns.FORMAT + "=?"; 76d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 7759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" }; 7859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private static final String DEVICE_PROPERTY_WHERE = "code=?"; 7959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 80d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private final MediaScanner mMediaScanner; 81d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 82d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood static { 83d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood System.loadLibrary("media_jni"); 84d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 85d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 86d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood public MtpDatabase(Context context, String volumeName) { 87d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood native_setup(); 88d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 892837eefc5459427138c080d445bb491c75630163Mike Lockwood mContext = context; 90d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mMediaProvider = context.getContentResolver().acquireProvider("media"); 91d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mVolumeName = volumeName; 928490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood mObjectsUri = Files.getMtpObjectsUri(volumeName); 93d815f79766984fce499e147ecbacc01914683f74Mike Lockwood mMediaScanner = new MediaScanner(context); 9459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood openDevicePropertiesDatabase(context); 95d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 96d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 97d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood @Override 98dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood protected void finalize() throws Throwable { 99dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood try { 100dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood native_finalize(); 101dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood } finally { 102dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood super.finalize(); 103dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood } 104d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 105d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 10659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private void openDevicePropertiesDatabase(Context context) { 10759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null); 10859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood int version = mDevicePropDb.getVersion(); 10959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 11059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood // initialize if necessary 11159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood if (version != DEVICE_PROPERTIES_DATABASE_VERSION) { 11259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood mDevicePropDb.execSQL("CREATE TABLE properties (" + 11359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood "_id INTEGER PRIMARY KEY AUTOINCREMENT," + 11459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood "code INTEGER UNIQUE ON CONFLICT REPLACE," + 11559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood "value TEXT" + 11659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood ");"); 11759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood mDevicePropDb.execSQL("CREATE INDEX property_index ON properties (code);"); 11859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood mDevicePropDb.setVersion(DEVICE_PROPERTIES_DATABASE_VERSION); 11959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 12059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 12159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 122d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private int beginSendObject(String path, int format, int parent, 123d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int storage, long size, long modified) { 1242837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 125d815f79766984fce499e147ecbacc01914683f74Mike Lockwood ContentValues values = new ContentValues(); 1263b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.DATA, path); 1273b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.FORMAT, format); 1283b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.PARENT, parent); 129d815f79766984fce499e147ecbacc01914683f74Mike Lockwood // storage is ignored for now 1303b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.SIZE, size); 1313b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.DATE_MODIFIED, modified); 132d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 133d815f79766984fce499e147ecbacc01914683f74Mike Lockwood try { 134d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Uri uri = mMediaProvider.insert(mObjectsUri, values); 135d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (uri != null) { 136d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return Integer.parseInt(uri.getPathSegments().get(2)); 137d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 138d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 139d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 140d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } catch (RemoteException e) { 141d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Log.e(TAG, "RemoteException in beginSendObject", e); 142d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 143d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 144d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 145d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 146d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private void endSendObject(String path, int handle, int format, boolean succeeded) { 147d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (succeeded) { 1489a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // handle abstract playlists separately 1499a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // they do not exist in the file system so don't use the media scanner here 1505367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) { 1519a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // Strip Windows Media Player file extension 1529a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (path.endsWith(".pla")) { 1539a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood path = path.substring(0, path.length() - 4); 1549a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 1559a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 1569a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // extract name from path 1579a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood String name = path; 1589a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int lastSlash = name.lastIndexOf('/'); 1599a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (lastSlash >= 0) { 1609a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood name = name.substring(lastSlash + 1); 1619a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 1629a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 1639a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues values = new ContentValues(1); 1649a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(Audio.Playlists.DATA, path); 1659a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(Audio.Playlists.NAME, name); 1669a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle); 1679a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 1689a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values); 1699a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 1709a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in endSendObject", e); 1719a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 1729a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } else { 1739a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Uri uri = mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); 1749a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 175d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 176d815f79766984fce499e147ecbacc01914683f74Mike Lockwood deleteFile(handle); 177d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 178d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 179d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 180d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int[] getObjectList(int storageID, int format, int parent) { 181d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // we can ignore storageID until we support multiple storages 182d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectList parent: " + parent); 183d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 184d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 185d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (format != 0) { 186d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 187d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood PARENT_FORMAT_WHERE, 188d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood new String[] { Integer.toString(parent), Integer.toString(format) }, 189d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood null); 190d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } else { 191d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 192d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood PARENT_WHERE, new String[] { Integer.toString(parent) }, null); 193d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 194d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c == null) { 195d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "null cursor"); 196d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 197d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 198d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int count = c.getCount(); 199d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (count > 0) { 200d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int[] result = new int[count]; 201d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood for (int i = 0; i < count; i++) { 202d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.moveToNext(); 203d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood result[i] = c.getInt(0); 204d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 205d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "returning " + result); 206d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return result; 207d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 208d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 209d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 210d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 211d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 212d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 213d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 214d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 215d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 216d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 217d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 2187a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood private int getNumObjects(int storageID, int format, int parent) { 2197a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood // we can ignore storageID until we support multiple storages 2207a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Log.d(TAG, "getObjectList parent: " + parent); 2217a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Cursor c = null; 2227a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood try { 2237a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (format != 0) { 2247a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 2257a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood PARENT_FORMAT_WHERE, 2267a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood new String[] { Integer.toString(parent), Integer.toString(format) }, 2277a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood null); 2287a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } else { 2297a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 2307a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood PARENT_WHERE, new String[] { Integer.toString(parent) }, null); 2317a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2327a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 2337a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return c.getCount(); 2347a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2357a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } catch (RemoteException e) { 2367a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Log.e(TAG, "RemoteException in getNumObjects", e); 2377a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } finally { 2387a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 2397a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c.close(); 2407a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2417a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2427a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return -1; 2437a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2447a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood 2454b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedPlaybackFormats() { 2464b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood return new int[] { 247e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood // allow transfering arbitrary files 248e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood MtpConstants.FORMAT_UNDEFINED, 249792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood MtpConstants.FORMAT_ASSOCIATION, 250792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST, 2514b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood }; 2524b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 2534b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 2544b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedCaptureFormats() { 2554b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood // no capture formats yet 2564b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood return null; 2574b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 2584b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 2594b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedObjectProperties(int handle) { 2604b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood return new int[] { 2615367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 2625367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 2635367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 2645367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 2655367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 2664b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood }; 2674b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 2684b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 2694b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedDeviceProperties() { 27059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return new int[] { 27159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, 27259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, 27359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood }; 2744b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 2754b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 276d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int getObjectProperty(int handle, int property, 277d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood long[] outIntValue, char[] outStringValue) { 278d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectProperty: " + property); 279b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood String column = null; 280b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood boolean isString = false; 281b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 282b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood switch (property) { 2835367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood case MtpConstants.PROPERTY_STORAGE_ID: 284b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outIntValue[0] = mStorageID; 2855367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 2865367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood case MtpConstants.PROPERTY_OBJECT_FORMAT: 2873b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood column = Files.FileColumns.FORMAT; 288b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 2895367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood case MtpConstants.PROPERTY_PROTECTION_STATUS: 290828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood // protection status is always 0 291828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood outIntValue[0] = 0; 2925367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 2935367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood case MtpConstants.PROPERTY_OBJECT_SIZE: 2943b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood column = Files.FileColumns.SIZE; 295b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 2965367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood case MtpConstants.PROPERTY_OBJECT_FILE_NAME: 2973b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood column = Files.FileColumns.DATA; 298b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood isString = true; 299b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 3005367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood case MtpConstants.PROPERTY_DATE_MODIFIED: 3013b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood column = Files.FileColumns.DATE_MODIFIED; 302b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 3035367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood case MtpConstants.PROPERTY_PARENT_OBJECT: 3043b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood column = Files.FileColumns.PARENT; 305b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 3065367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood case MtpConstants.PROPERTY_PERSISTENT_UID: 307828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood // PUID is concatenation of storageID and object handle 308828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood long puid = mStorageID; 309828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood puid <<= 32; 310828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood puid += handle; 311828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood outIntValue[0] = puid; 3125367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 313b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood default: 3145367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 315b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 316b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 317b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood Cursor c = null; 318b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood try { 319b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // for now we are only reading properties from the "objects" table 320b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood c = mMediaProvider.query(mObjectsUri, 3213b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood new String [] { Files.FileColumns._ID, column }, 322b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 323b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (c != null && c.moveToNext()) { 324b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (isString) { 325b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood String value = c.getString(1); 326b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int start = 0; 327b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 3285367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood if (property == MtpConstants.PROPERTY_OBJECT_FILE_NAME) { 329b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // extract name from full path 330b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int lastSlash = value.lastIndexOf('/'); 331b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (lastSlash >= 0) { 332b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood start = lastSlash + 1; 333b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 334b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 335b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int end = value.length(); 336b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (end - start > 255) { 337b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood end = start + 255; 338b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 339b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood value.getChars(start, end, outStringValue, 0); 340b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outStringValue[end - start] = 0; 341b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } else { 342b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outIntValue[0] = c.getLong(1); 343b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 3445367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 345b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 346b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } catch (Exception e) { 3475367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 348b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } finally { 349b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (c != null) { 350b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood c.close(); 351b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 352b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 353b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // query failed if we get here 3545367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 355d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 356d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 35759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int setObjectProperty(int handle, int property, 35859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood long intValue, String stringValue) { 35959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood Log.d(TAG, "setObjectProperty: " + property); 36059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 36159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 36259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 36359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) { 36459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood Log.d(TAG, "getDeviceProperty: " + property); 36559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 36659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood switch (property) { 36759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER: 36859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME: 36959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood // writable string properties kept in our device property database 37059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood Cursor c = null; 37159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood try { 37259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood c = mDevicePropDb.query("properties", DEVICE_PROPERTY_PROJECTION, 37359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood DEVICE_PROPERTY_WHERE, new String[] { Integer.toString(property) }, 37459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood null, null, null); 37559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 37659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood if (c != null && c.moveToNext()) { 37759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood String value = c.getString(1); 37859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood int length = value.length(); 37959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood if (length > 255) { 38059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood length = 255; 38159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 38259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood value.getChars(0, length, outStringValue, 0); 38359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood outStringValue[length] = 0; 38459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } else { 38559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood outStringValue[0] = 0; 38659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 38759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return MtpConstants.RESPONSE_OK; 38859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } finally { 38959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood if (c != null) { 39059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood c.close(); 39159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 39259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 39359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 39459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 39559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 39659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 39759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 39859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int setDeviceProperty(int property, long intValue, String stringValue) { 39959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood Log.d(TAG, "setDeviceProperty: " + property + " : " + stringValue); 40059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 40159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood switch (property) { 40259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER: 40359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME: 40459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood // writable string properties kept in our device property database 40559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood try { 40659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood ContentValues values = new ContentValues(); 40759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood values.put("code", property); 40859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood values.put("value", stringValue); 40959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood mDevicePropDb.insert("properties", "code", values); 41059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return MtpConstants.RESPONSE_OK; 41159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } catch (Exception e) { 41259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 41359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 41459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 41559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 41659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 41759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 41859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 419d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private boolean getObjectInfo(int handle, int[] outStorageFormatParent, 420d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood char[] outName, long[] outSizeModified) { 421d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectInfo: " + handle); 422d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 423d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 424d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, 425d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 426d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 427b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outStorageFormatParent[0] = mStorageID; 428d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[1] = c.getInt(2); 429d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[2] = c.getInt(3); 430d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 431d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // extract name from path 432d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood String path = c.getString(1); 433d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int lastSlash = path.lastIndexOf('/'); 434d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int start = (lastSlash >= 0 ? lastSlash + 1 : 0); 435d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int end = path.length(); 436d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (end - start > 255) { 437d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood end = start + 255; 438d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 439d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(start, end, outName, 0); 440d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outName[end - start] = 0; 441d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 442d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outSizeModified[0] = c.getLong(4); 443d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outSizeModified[1] = c.getLong(5); 444d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return true; 445d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 446d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 447d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectProperty", e); 448d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 449d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 450d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 451d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 452d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 453d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return false; 454d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 455d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 45659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLength) { 457d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectFilePath: " + handle); 458d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 459d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 460d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, PATH_SIZE_PROJECTION, 461d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 462d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 463d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood String path = c.getString(1); 464d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(0, path.length(), outFilePath, 0); 465d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outFilePath[path.length()] = 0; 466d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outFileLength[0] = c.getLong(2); 4675367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 46859c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 4695367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 470d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 471d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 472d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectFilePath", e); 4735367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 474d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 475d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 476d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 477d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 478d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 479d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 480d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 48159c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood private int deleteFile(int handle) { 482d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "deleteFile: " + handle); 4832837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 4848490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood Uri uri = Files.getMtpObjectsUri(mVolumeName, handle); 485d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 48659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood if (mMediaProvider.delete(uri, null, null) == 1) { 4875367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 48859c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 4895367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 49059c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } 491d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 492d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in deleteFile", e); 4935367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 494d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 495d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 496d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 4979a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood private int[] getObjectReferences(int handle) { 4989a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.d(TAG, "getObjectReferences for: " + handle); 4998490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood Uri uri = Files.getMtpReferencesUri(mVolumeName, handle); 5009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Cursor c = null; 5019a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 5029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null); 5039a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (c == null) { 5049a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return null; 5059a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5069a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int count = c.getCount(); 5079a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (count > 0) { 5089a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int[] result = new int[count]; 5099a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood for (int i = 0; i < count; i++) { 5109a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c.moveToNext(); 5119a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood result[i] = c.getInt(0); 5129a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5139a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return result; 5149a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5159a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 5169a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 5179a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } finally { 5189a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (c != null) { 5199a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c.close(); 5209a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5219a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5229a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return null; 5239a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5249a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 5259a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood private int setObjectReferences(int handle, int[] references) { 5262837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 5278490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood Uri uri = Files.getMtpReferencesUri(mVolumeName, handle); 5289a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int count = references.length; 5299a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues[] valuesList = new ContentValues[count]; 5309a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood for (int i = 0; i < count; i++) { 5319a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues values = new ContentValues(); 5323b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns._ID, references[i]); 5339a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood valuesList[i] = values; 5349a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5359a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 5369a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (count == mMediaProvider.bulkInsert(uri, valuesList)) { 5375367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 5389a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5399a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 5409a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in setObjectReferences", e); 5419a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5425367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 5439a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 5449a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 5452837eefc5459427138c080d445bb491c75630163Mike Lockwood private void sessionStarted() { 5462837eefc5459427138c080d445bb491c75630163Mike Lockwood Log.d(TAG, "sessionStarted"); 5472837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = false; 5482837eefc5459427138c080d445bb491c75630163Mike Lockwood } 5492837eefc5459427138c080d445bb491c75630163Mike Lockwood 5502837eefc5459427138c080d445bb491c75630163Mike Lockwood private void sessionEnded() { 5512837eefc5459427138c080d445bb491c75630163Mike Lockwood Log.d(TAG, "sessionEnded"); 5522837eefc5459427138c080d445bb491c75630163Mike Lockwood if (mDatabaseModified) { 5532837eefc5459427138c080d445bb491c75630163Mike Lockwood Log.d(TAG, "sending ACTION_MTP_SESSION_END"); 5542837eefc5459427138c080d445bb491c75630163Mike Lockwood mContext.sendBroadcast(new Intent(Mtp.ACTION_MTP_SESSION_END)); 5552837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = false; 5562837eefc5459427138c080d445bb491c75630163Mike Lockwood } 5572837eefc5459427138c080d445bb491c75630163Mike Lockwood } 5582837eefc5459427138c080d445bb491c75630163Mike Lockwood 559d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // used by the JNI code 560d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int mNativeContext; 561d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 562d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_setup(); 563d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_finalize(); 564d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood} 565