MtpDatabase.java revision 44bc17c6b517aef35a390c81b5aa79c4f284f744
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 170cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodpackage android.mtp; 18d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 19d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.Context; 20d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodimport android.content.ContentValues; 21d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.IContentProvider; 222837eefc5459427138c080d445bb491c75630163Mike Lockwoodimport android.content.Intent; 23775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwoodimport android.content.SharedPreferences; 24d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.database.Cursor; 2559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodimport android.database.sqlite.SQLiteDatabase; 260cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodimport android.media.MediaScanner; 27d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.net.Uri; 282b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwoodimport android.os.Environment; 29d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException; 30a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwoodimport android.provider.MediaStore; 319a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.Audio; 323b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwoodimport android.provider.MediaStore.Files; 33ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.Images; 34ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.MediaColumns; 35d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log; 36ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.Display; 37ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.WindowManager; 38d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 395ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwoodimport java.io.File; 407d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport java.util.HashMap; 415ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood 42d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/** 43d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide} 44d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */ 45d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic class MtpDatabase { 46d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 47d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String TAG = "MtpDatabase"; 48d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 492837eefc5459427138c080d445bb491c75630163Mike Lockwood private final Context mContext; 50d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final IContentProvider mMediaProvider; 51d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final String mVolumeName; 52d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final Uri mObjectsUri; 53b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private final String mMediaStoragePath; // path to primary storage 54b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>(); 55d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 567d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // cached property groups for single properties 577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByProperty 587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood = new HashMap<Integer, MtpPropertyGroup>(); 597d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 607d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // cached property groups for all properties for a given format 617d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByFormat 627d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood = new HashMap<Integer, MtpPropertyGroup>(); 637d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 642837eefc5459427138c080d445bb491c75630163Mike Lockwood // true if the database has been modified in the current MTP session 652837eefc5459427138c080d445bb491c75630163Mike Lockwood private boolean mDatabaseModified; 662837eefc5459427138c080d445bb491c75630163Mike Lockwood 67775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // SharedPreferences for writable MTP device properties 68775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood private SharedPreferences mDeviceProperties; 6959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1; 7059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 71d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] ID_PROJECTION = new String[] { 723b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 73d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 746a6a3aff17e057eeb1457ac4d04ab4b5e8f53abeMike Lockwood private static final String[] PATH_PROJECTION = new String[] { 755ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood Files.FileColumns._ID, // 0 765ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood Files.FileColumns.DATA, // 1 775ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood }; 78365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood private static final String[] PATH_SIZE_FORMAT_PROJECTION = new String[] { 793b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 803b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.DATA, // 1 813b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.SIZE, // 2 82365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood Files.FileColumns.FORMAT, // 3 83d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 84d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] OBJECT_INFO_PROJECTION = new String[] { 853b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 86b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Files.FileColumns.STORAGE_ID, // 1 873b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.FORMAT, // 2 883b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.PARENT, // 3 89b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Files.FileColumns.DATA, // 4 90b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Files.FileColumns.SIZE, // 5 91b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Files.FileColumns.DATE_MODIFIED, // 6 92d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 933b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood private static final String ID_WHERE = Files.FileColumns._ID + "=?"; 94bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood private static final String PATH_WHERE = Files.FileColumns.DATA + "=?"; 953b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?"; 96d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " 973b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood + Files.FileColumns.FORMAT + "=?"; 98b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private static final String PARENT_STORAGE_WHERE = PARENT_WHERE + " AND " 99b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood + Files.FileColumns.STORAGE_ID + "=?"; 100b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private static final String PARENT_STORAGE_FORMAT_WHERE = PARENT_STORAGE_WHERE + " AND " 101b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood + Files.FileColumns.FORMAT + "=?"; 102d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 103d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private final MediaScanner mMediaScanner; 104d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 105d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood static { 106d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood System.loadLibrary("media_jni"); 107d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 108d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 10901788562f26f213f63c14483fd3977e23b8314abMike Lockwood public MtpDatabase(Context context, String volumeName, String storagePath) { 110d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood native_setup(); 111d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 1122837eefc5459427138c080d445bb491c75630163Mike Lockwood mContext = context; 113d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mMediaProvider = context.getContentResolver().acquireProvider("media"); 114d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mVolumeName = volumeName; 11501788562f26f213f63c14483fd3977e23b8314abMike Lockwood mMediaStoragePath = storagePath; 1168490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood mObjectsUri = Files.getMtpObjectsUri(volumeName); 117d815f79766984fce499e147ecbacc01914683f74Mike Lockwood mMediaScanner = new MediaScanner(context); 118775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood initDeviceProperties(context); 119d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 120d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 121d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood @Override 122dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood protected void finalize() throws Throwable { 123dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood try { 124dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood native_finalize(); 125dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood } finally { 126dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood super.finalize(); 127dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood } 128d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 129d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 130b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood public void addStorage(MtpStorage storage) { 131b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood mStorageMap.put(storage.getPath(), storage); 132b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 133b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood 134b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood public void removeStorage(MtpStorage storage) { 135b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood mStorageMap.remove(storage.getPath()); 136b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 137b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood 138775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood private void initDeviceProperties(Context context) { 139775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood final String devicePropertiesName = "device-properties"; 140775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood mDeviceProperties = context.getSharedPreferences(devicePropertiesName, Context.MODE_PRIVATE); 141775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood File databaseFile = context.getDatabasePath(devicePropertiesName); 142775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood 143775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (databaseFile.exists()) { 144775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // for backward compatibility - read device properties from sqlite database 145775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // and migrate them to shared prefs 146775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood SQLiteDatabase db = null; 147775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood Cursor c = null; 148775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood try { 149775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood db = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null); 150775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (db != null) { 151775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood c = db.query("properties", new String[] { "_id", "code", "value" }, 152775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood null, null, null, null, null); 153775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (c != null) { 154775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood SharedPreferences.Editor e = mDeviceProperties.edit(); 155775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood while (c.moveToNext()) { 156775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood String name = c.getString(1); 157775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood String value = c.getString(2); 158775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood e.putString(name, value); 159775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } 160775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood e.commit(); 161775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } 162775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } 163775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } catch (Exception e) { 164775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood Log.e(TAG, "failed to migrate device properties", e); 165775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } finally { 166775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (c != null) c.close(); 167775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (db != null) db.close(); 168775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } 169775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood databaseFile.delete(); 17059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 17159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 17259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 173d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private int beginSendObject(String path, int format, int parent, 174b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood int storageId, long size, long modified) { 175bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood // first make sure the object does not exist 176bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood if (path != null) { 177bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood Cursor c = null; 178bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood try { 179bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE, 180bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood new String[] { path }, null); 181bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood if (c != null && c.getCount() > 0) { 182bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood Log.w(TAG, "file already exists in beginSendObject: " + path); 183bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood return -1; 184bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } 185bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } catch (RemoteException e) { 186bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood Log.e(TAG, "RemoteException in beginSendObject", e); 187bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } finally { 188bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood if (c != null) { 189bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood c.close(); 190bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } 191bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } 192bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } 193bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood 1942837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 195d815f79766984fce499e147ecbacc01914683f74Mike Lockwood ContentValues values = new ContentValues(); 1963b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.DATA, path); 1973b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.FORMAT, format); 1983b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.PARENT, parent); 199b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood values.put(Files.FileColumns.STORAGE_ID, storageId); 2003b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.SIZE, size); 2013b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.DATE_MODIFIED, modified); 202d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 203d815f79766984fce499e147ecbacc01914683f74Mike Lockwood try { 204d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Uri uri = mMediaProvider.insert(mObjectsUri, values); 205d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (uri != null) { 206d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return Integer.parseInt(uri.getPathSegments().get(2)); 207d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 208d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 209d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 210d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } catch (RemoteException e) { 211d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Log.e(TAG, "RemoteException in beginSendObject", e); 212d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 213d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 214d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 215d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 2167a0bd17bceaf3efc3732e30c538fae420d3b742cMike Lockwood private void endSendObject(String path, int handle, int format, boolean succeeded) { 217d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (succeeded) { 2189a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // handle abstract playlists separately 2199a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // they do not exist in the file system so don't use the media scanner here 2205367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) { 2219a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // extract name from path 2229a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood String name = path; 2239a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int lastSlash = name.lastIndexOf('/'); 2249a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (lastSlash >= 0) { 2259a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood name = name.substring(lastSlash + 1); 2269a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 2278cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood // strip trailing ".pla" from the name 2288cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood if (name.endsWith(".pla")) { 2298cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood name = name.substring(0, name.length() - 4); 2308cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood } 2319a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 2329a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues values = new ContentValues(1); 2339a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(Audio.Playlists.DATA, path); 2349a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(Audio.Playlists.NAME, name); 2350b58c19840c577c8d8fd8aa5315676d61b78ba0fMike Lockwood values.put(Files.FileColumns.FORMAT, format); 2368ed67acf38ccdfdb89553ed58620a135f2100e10Mike Lockwood values.put(Files.FileColumns.DATE_MODIFIED, System.currentTimeMillis() / 1000); 2379a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle); 2389a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 2399a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values); 2409a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 2419a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in endSendObject", e); 2429a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 2439a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } else { 244c37255d5d0fd9e0ec02b0d7cb5c4b235e200d367Mike Lockwood mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); 2459a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 246d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 247d815f79766984fce499e147ecbacc01914683f74Mike Lockwood deleteFile(handle); 248d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 249d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 250d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 251b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException { 252b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood if (storageID != 0) { 253b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood if (format != 0) { 254b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood return mMediaProvider.query(mObjectsUri, ID_PROJECTION, 255b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood PARENT_STORAGE_FORMAT_WHERE, 256b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood new String[] { Integer.toString(parent), Integer.toString(storageID), 257b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Integer.toString(format) }, null); 258b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } else { 259b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood return mMediaProvider.query(mObjectsUri, ID_PROJECTION, 260b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood PARENT_STORAGE_WHERE, new String[] 261b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood { Integer.toString(parent), Integer.toString(storageID) }, null); 262b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 263b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } else { 264d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (format != 0) { 265b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood return mMediaProvider.query(mObjectsUri, ID_PROJECTION, 266d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood PARENT_FORMAT_WHERE, 267d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood new String[] { Integer.toString(parent), Integer.toString(format) }, 268d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood null); 269d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } else { 270b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood return mMediaProvider.query(mObjectsUri, ID_PROJECTION, 271d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood PARENT_WHERE, new String[] { Integer.toString(parent) }, null); 272d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 273b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 274b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 275b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood 276b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private int[] getObjectList(int storageID, int format, int parent) { 277b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Cursor c = null; 278b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood try { 279b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood c = createObjectQuery(storageID, format, parent); 280d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c == null) { 281d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 282d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 283d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int count = c.getCount(); 284d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (count > 0) { 285d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int[] result = new int[count]; 286d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood for (int i = 0; i < count; i++) { 287d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.moveToNext(); 288d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood result[i] = c.getInt(0); 289d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 290d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return result; 291d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 292d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 293d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 294d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 295d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 296d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 297d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 298d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 299d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 300d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 301d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 3027a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood private int getNumObjects(int storageID, int format, int parent) { 3037a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Cursor c = null; 3047a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood try { 305b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood c = createObjectQuery(storageID, format, parent); 3067a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 3077a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return c.getCount(); 3087a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 3097a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } catch (RemoteException e) { 3107a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Log.e(TAG, "RemoteException in getNumObjects", e); 3117a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } finally { 3127a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 3137a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c.close(); 3147a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 3157a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 3167a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return -1; 3177a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 3187a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood 3194b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedPlaybackFormats() { 3204b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood return new int[] { 321e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood // allow transfering arbitrary files 322e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood MtpConstants.FORMAT_UNDEFINED, 32312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood 324792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood MtpConstants.FORMAT_ASSOCIATION, 32512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_TEXT, 32612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_HTML, 32712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_WAV, 32812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_MP3, 32912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_MPEG, 33012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_EXIF_JPEG, 33112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_TIFF_EP, 33212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_GIF, 33312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_JFIF, 33412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_PNG, 33512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_TIFF, 33612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_WMA, 33712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_OGG, 33812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_AAC, 33912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_MP4_CONTAINER, 34012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_MP2, 34112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_3GP_CONTAINER, 342792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST, 34312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_WPL_PLAYLIST, 34412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_M3U_PLAYLIST, 34512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_PLS_PLAYLIST, 34612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_XML_DOCUMENT, 347f9f223edb408cdc9fd946dc099a86857079a639fGlenn Kasten MtpConstants.FORMAT_FLAC, 3484b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood }; 3494b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 3504b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 3514b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedCaptureFormats() { 3524b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood // no capture formats yet 3534b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood return null; 3544b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 3554b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 356ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood static final int[] FILE_PROPERTIES = { 357ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES 358ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // and IMAGE_PROPERTIES below 3595367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 3605367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 361d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 3625367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 3635367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 364d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 3655367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 366d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 367d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood MtpConstants.PROPERTY_NAME, 368ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 369ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood }; 370ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 371ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood static final int[] AUDIO_PROPERTIES = { 372ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // NOTE must match FILE_PROPERTIES above 373ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 374ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 375ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 376ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 377ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 378ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 379ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 380ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 381ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_NAME, 382ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DISPLAY_NAME, 383ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 384ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 385ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // audio specific properties 386ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ARTIST, 387ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ALBUM_NAME, 388ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ALBUM_ARTIST, 389ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_TRACK, 390ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE, 391ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DURATION, 392ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_GENRE, 393ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_COMPOSER, 394ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood }; 395ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 396ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood static final int[] VIDEO_PROPERTIES = { 397ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // NOTE must match FILE_PROPERTIES above 398ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 399ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 400ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 401ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 402ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 403ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 404ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 405ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 406ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_NAME, 407ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DISPLAY_NAME, 408ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 409ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 410ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // video specific properties 411ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ARTIST, 412ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ALBUM_NAME, 413ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DURATION, 414ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DESCRIPTION, 415ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood }; 416ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 417ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood static final int[] IMAGE_PROPERTIES = { 418ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // NOTE must match FILE_PROPERTIES above 419ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 420ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 421ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 422ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 423ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 424ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 425ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 426ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 427ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_NAME, 428ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DISPLAY_NAME, 429ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 430ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 431ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // image specific properties 432ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DESCRIPTION, 433ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood }; 434ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 4357d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood static final int[] ALL_PROPERTIES = { 4367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // NOTE must match FILE_PROPERTIES above 4377d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 4387d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 4397d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 4407d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 4417d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 4427d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 4437d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 4447d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 4457d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_NAME, 4467d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_DISPLAY_NAME, 4477d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 4487d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 4497d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // image specific properties 4507d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_DESCRIPTION, 4517d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 4527d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // audio specific properties 4537d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_ARTIST, 4547d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_ALBUM_NAME, 4557d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_ALBUM_ARTIST, 4567d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_TRACK, 4577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE, 4587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_DURATION, 4597d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_GENRE, 4607d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_COMPOSER, 4617d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 4627d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // video specific properties 4637d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_ARTIST, 4647d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_ALBUM_NAME, 4657d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_DURATION, 4667d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_DESCRIPTION, 4677d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 4687d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // image specific properties 4697d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpConstants.PROPERTY_DESCRIPTION, 4707d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood }; 4717d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 472ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood private int[] getSupportedObjectProperties(int format) { 473ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood switch (format) { 474ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_MP3: 475ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_WAV: 476ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_WMA: 477ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_OGG: 478ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_AAC: 479ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood return AUDIO_PROPERTIES; 480ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_MPEG: 481ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_3GP_CONTAINER: 482ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_WMV: 483ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood return VIDEO_PROPERTIES; 484ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_EXIF_JPEG: 485ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_GIF: 486ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_PNG: 487ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_BMP: 488ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood return IMAGE_PROPERTIES; 4897d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood case 0: 4907d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood return ALL_PROPERTIES; 491ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood default: 492ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood return FILE_PROPERTIES; 493ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood } 4944b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 4954b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 4964b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedDeviceProperties() { 49759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return new int[] { 49859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, 49959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, 500ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE, 50159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood }; 5024b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 5034b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 504e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 5057d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private MtpPropertyList getObjectPropertyList(long handle, int format, long property, 506e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood int groupCode, int depth) { 507e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // FIXME - implement group support 508e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (groupCode != 0) { 509e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED); 5105ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood } 5115ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood 5127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpPropertyGroup propertyGroup; 5137d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (property == 0xFFFFFFFFL) { 5147d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood propertyGroup = mPropertyGroupsByFormat.get(format); 5157d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (propertyGroup == null) { 5167d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int[] propertyList = getSupportedObjectProperties(format); 5177d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList); 5187d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mPropertyGroupsByFormat.put(new Integer(format), propertyGroup); 519e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 5207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 5217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood propertyGroup = mPropertyGroupsByProperty.get(property); 5227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood if (propertyGroup == null) { 5237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int[] propertyList = new int[] { (int)property }; 5247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList); 5257d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup); 526e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 527e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 5287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 529b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood return propertyGroup.getPropertyList((int)handle, format, depth); 530e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 531e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 532e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood private int renameFile(int handle, String newName) { 533e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood Cursor c = null; 534e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 535e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // first compute current path 536e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood String path = null; 537e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood String[] whereArgs = new String[] { Integer.toString(handle) }; 538e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood try { 539e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null); 540e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (c != null && c.moveToNext()) { 5411c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood path = c.getString(1); 542e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 543e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } catch (RemoteException e) { 544e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood Log.e(TAG, "RemoteException in getObjectFilePath", e); 545e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 546e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } finally { 547e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (c != null) { 548e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood c.close(); 549b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 550b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 551e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (path == null) { 552e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 553e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 554e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 555e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // now rename the file. make sure this succeeds before updating database 556e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood File oldFile = new File(path); 557e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood int lastSlash = path.lastIndexOf('/'); 558e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (lastSlash <= 1) { 559e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 560e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 561e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood String newPath = path.substring(0, lastSlash + 1) + newName; 562e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood File newFile = new File(newPath); 563e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood boolean success = oldFile.renameTo(newFile); 564e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (!success) { 565f26a586c86b097f975e26fe526ead564ad011bd0Mike Lockwood Log.w(TAG, "renaming "+ path + " to " + newPath + " failed"); 566e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 567e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 568e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 569e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // finally update database 570e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood ContentValues values = new ContentValues(); 571e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood values.put(Files.FileColumns.DATA, newPath); 572e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood int updated = 0; 573e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood try { 574e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // note - we are relying on a special case in MediaProvider.update() to update 575e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // the paths for all children in the case where this is a directory. 576e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood updated = mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs); 577e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } catch (RemoteException e) { 578e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood Log.e(TAG, "RemoteException in mMediaProvider.update", e); 579e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 580e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (updated == 0) { 581e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood Log.e(TAG, "Unable to update path for " + path + " to " + newPath); 582e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // this shouldn't happen, but if it does we need to rename the file to its original name 583e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood newFile.renameTo(oldFile); 584e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 585e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 586e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 587e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_OK; 588d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 589d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 59059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int setObjectProperty(int handle, int property, 59159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood long intValue, String stringValue) { 5925ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood switch (property) { 5935ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood case MtpConstants.PROPERTY_OBJECT_FILE_NAME: 5945ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood return renameFile(handle, stringValue); 5955ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood 5965ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood default: 5975ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 5985ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood } 59959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 60059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 60159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) { 60259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood switch (property) { 60359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER: 60459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME: 605775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // writable string properties kept in shared preferences 606775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood String value = mDeviceProperties.getString(Integer.toString(property), ""); 607775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood int length = value.length(); 608775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (length > 255) { 609775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood length = 255; 61059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 611775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood value.getChars(0, length, outStringValue, 0); 612775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood outStringValue[length] = 0; 613775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood return MtpConstants.RESPONSE_OK; 61459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 615ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE: 616ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood // use screen size as max image size 617ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood Display display = ((WindowManager)mContext.getSystemService( 618ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood Context.WINDOW_SERVICE)).getDefaultDisplay(); 61944bc17c6b517aef35a390c81b5aa79c4f284f744Dianne Hackborn int width = display.getMaximumSizeDimension(); 62044bc17c6b517aef35a390c81b5aa79c4f284f744Dianne Hackborn int height = display.getMaximumSizeDimension(); 621ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood String imageSize = Integer.toString(width) + "x" + Integer.toString(height); 622ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood imageSize.getChars(0, imageSize.length(), outStringValue, 0); 623ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood outStringValue[imageSize.length()] = 0; 624ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood return MtpConstants.RESPONSE_OK; 625ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood 626ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood default: 627ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 628ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood } 62959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 63059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 63159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int setDeviceProperty(int property, long intValue, String stringValue) { 63259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood switch (property) { 63359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER: 63459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME: 635775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // writable string properties kept in shared prefs 636775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood SharedPreferences.Editor e = mDeviceProperties.edit(); 637775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood e.putString(Integer.toString(property), stringValue); 638775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood return (e.commit() ? MtpConstants.RESPONSE_OK 639775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood : MtpConstants.RESPONSE_GENERAL_ERROR); 64059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 64159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 64259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 64359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 64459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 645d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private boolean getObjectInfo(int handle, int[] outStorageFormatParent, 646d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood char[] outName, long[] outSizeModified) { 647d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 648d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 649d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, 650d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 651d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 652b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood outStorageFormatParent[0] = c.getInt(1); 653d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[1] = c.getInt(2); 654d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[2] = c.getInt(3); 655d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 656d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // extract name from path 657b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood String path = c.getString(4); 658d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int lastSlash = path.lastIndexOf('/'); 659d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int start = (lastSlash >= 0 ? lastSlash + 1 : 0); 660d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int end = path.length(); 661d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (end - start > 255) { 662d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood end = start + 255; 663d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 664d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(start, end, outName, 0); 665d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outName[end - start] = 0; 666d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 667b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood outSizeModified[0] = c.getLong(5); 668b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood outSizeModified[1] = c.getLong(6); 669d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return true; 670d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 671d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 6722b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood Log.e(TAG, "RemoteException in getObjectInfo", e); 673d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 674d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 675d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 676d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 677d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 678d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return false; 679d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 680d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 681365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) { 68201788562f26f213f63c14483fd3977e23b8314abMike Lockwood if (handle == 0) { 68301788562f26f213f63c14483fd3977e23b8314abMike Lockwood // special case root directory 68401788562f26f213f63c14483fd3977e23b8314abMike Lockwood mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0); 68501788562f26f213f63c14483fd3977e23b8314abMike Lockwood outFilePath[mMediaStoragePath.length()] = 0; 686365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood outFileLengthFormat[0] = 0; 687365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood outFileLengthFormat[1] = MtpConstants.FORMAT_ASSOCIATION; 68801788562f26f213f63c14483fd3977e23b8314abMike Lockwood return MtpConstants.RESPONSE_OK; 68901788562f26f213f63c14483fd3977e23b8314abMike Lockwood } 690d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 691d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 692365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION, 693d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 694d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 6951c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood String path = c.getString(1); 696d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(0, path.length(), outFilePath, 0); 697d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outFilePath[path.length()] = 0; 698365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood outFileLengthFormat[0] = c.getLong(2); 699365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood outFileLengthFormat[1] = c.getLong(3); 7005367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 70159c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 7025367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 703d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 704d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 705d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectFilePath", e); 7065367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 707d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 708d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 709d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 710d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 711d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 712d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 713d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 71459c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood private int deleteFile(int handle) { 7152837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 71655f808cff9913a00164120a422af6ca45db5072bMike Lockwood String path = null; 71755f808cff9913a00164120a422af6ca45db5072bMike Lockwood int format = 0; 71855f808cff9913a00164120a422af6ca45db5072bMike Lockwood 71955f808cff9913a00164120a422af6ca45db5072bMike Lockwood Cursor c = null; 720d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 72155f808cff9913a00164120a422af6ca45db5072bMike Lockwood c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION, 72255f808cff9913a00164120a422af6ca45db5072bMike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 72355f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (c != null && c.moveToNext()) { 72455f808cff9913a00164120a422af6ca45db5072bMike Lockwood // don't convert to media path here, since we will be matching 72555f808cff9913a00164120a422af6ca45db5072bMike Lockwood // against paths in the database matching /data/media 72655f808cff9913a00164120a422af6ca45db5072bMike Lockwood path = c.getString(1); 72755f808cff9913a00164120a422af6ca45db5072bMike Lockwood format = c.getInt(3); 72855f808cff9913a00164120a422af6ca45db5072bMike Lockwood } else { 72955f808cff9913a00164120a422af6ca45db5072bMike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 73055f808cff9913a00164120a422af6ca45db5072bMike Lockwood } 73155f808cff9913a00164120a422af6ca45db5072bMike Lockwood 73255f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (path == null || format == 0) { 73355f808cff9913a00164120a422af6ca45db5072bMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 73455f808cff9913a00164120a422af6ca45db5072bMike Lockwood } 73555f808cff9913a00164120a422af6ca45db5072bMike Lockwood 73655f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (format == MtpConstants.FORMAT_ASSOCIATION) { 73755f808cff9913a00164120a422af6ca45db5072bMike Lockwood // recursive case - delete all children first 73855f808cff9913a00164120a422af6ca45db5072bMike Lockwood Uri uri = Files.getMtpObjectsUri(mVolumeName); 73955f808cff9913a00164120a422af6ca45db5072bMike Lockwood int count = mMediaProvider.delete(uri, "_data LIKE ?", 74055f808cff9913a00164120a422af6ca45db5072bMike Lockwood new String[] { path + "/%"}); 74155f808cff9913a00164120a422af6ca45db5072bMike Lockwood } 74255f808cff9913a00164120a422af6ca45db5072bMike Lockwood 74355f808cff9913a00164120a422af6ca45db5072bMike Lockwood Uri uri = Files.getMtpObjectsUri(mVolumeName, handle); 74455f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (mMediaProvider.delete(uri, null, null) > 0) { 7455367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 74659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 7475367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 74859c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } 749d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 750d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in deleteFile", e); 7515367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 75255f808cff9913a00164120a422af6ca45db5072bMike Lockwood } finally { 75355f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (c != null) { 75455f808cff9913a00164120a422af6ca45db5072bMike Lockwood c.close(); 75555f808cff9913a00164120a422af6ca45db5072bMike Lockwood } 756d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 757d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 758d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 7599a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood private int[] getObjectReferences(int handle) { 7608490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood Uri uri = Files.getMtpReferencesUri(mVolumeName, handle); 7619a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Cursor c = null; 7629a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 7639a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null); 7649a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (c == null) { 7659a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return null; 7669a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 7679a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int count = c.getCount(); 7689a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (count > 0) { 7699a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int[] result = new int[count]; 7709a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood for (int i = 0; i < count; i++) { 7719a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c.moveToNext(); 7729a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood result[i] = c.getInt(0); 7739a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 7749a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return result; 7759a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 7769a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 7779a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 7789a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } finally { 7799a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (c != null) { 7809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c.close(); 7819a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 7829a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 7839a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return null; 7849a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 7859a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 7869a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood private int setObjectReferences(int handle, int[] references) { 7872837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 7888490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood Uri uri = Files.getMtpReferencesUri(mVolumeName, handle); 7899a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int count = references.length; 7909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues[] valuesList = new ContentValues[count]; 7919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood for (int i = 0; i < count; i++) { 7929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues values = new ContentValues(); 7933b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns._ID, references[i]); 7949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood valuesList[i] = values; 7959a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 7969a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 7977adfd1896c17d734440962c9f8dbe4aad48bcb49Mike Lockwood if (mMediaProvider.bulkInsert(uri, valuesList) > 0) { 7985367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 7999a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 8009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 8019a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in setObjectReferences", e); 8029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 8035367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 8049a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 8059a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 8062837eefc5459427138c080d445bb491c75630163Mike Lockwood private void sessionStarted() { 8072837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = false; 8082837eefc5459427138c080d445bb491c75630163Mike Lockwood } 8092837eefc5459427138c080d445bb491c75630163Mike Lockwood 8102837eefc5459427138c080d445bb491c75630163Mike Lockwood private void sessionEnded() { 8112837eefc5459427138c080d445bb491c75630163Mike Lockwood if (mDatabaseModified) { 812a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwood mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END)); 8132837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = false; 8142837eefc5459427138c080d445bb491c75630163Mike Lockwood } 8152837eefc5459427138c080d445bb491c75630163Mike Lockwood } 8162837eefc5459427138c080d445bb491c75630163Mike Lockwood 817d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // used by the JNI code 818d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int mNativeContext; 819d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 820d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_setup(); 821d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_finalize(); 822d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood} 823