MtpDatabase.java revision a31560598af25d5116effc2a6af0d9be12a0628d
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;
262b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwoodimport android.os.Environment;
27d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException;
28a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwoodimport android.provider.MediaStore;
299a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.Audio;
303b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwoodimport android.provider.MediaStore.Files;
31ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.Images;
32ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.MediaColumns;
33d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log;
34d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
355ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwoodimport java.io.File;
365ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
37d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/**
38d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide}
39d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */
40d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic class MtpDatabase {
41d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
42d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String TAG = "MtpDatabase";
43d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
442837eefc5459427138c080d445bb491c75630163Mike Lockwood    private final Context mContext;
45d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final IContentProvider mMediaProvider;
46d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final String mVolumeName;
47d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final Uri mObjectsUri;
4801788562f26f213f63c14483fd3977e23b8314abMike Lockwood    private final String mMediaStoragePath;
492b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood    private final String mExternalStoragePath;
50d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
512837eefc5459427138c080d445bb491c75630163Mike Lockwood    // true if the database has been modified in the current MTP session
522837eefc5459427138c080d445bb491c75630163Mike Lockwood    private boolean mDatabaseModified;
532837eefc5459427138c080d445bb491c75630163Mike Lockwood
5459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    // database for writable MTP device properties
5559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private SQLiteDatabase mDevicePropDb;
5659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1;
5759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
58b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood    // FIXME - this should be passed in via the constructor
59b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood    private final int mStorageID = 0x00010001;
60b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood
61d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String[] ID_PROJECTION = new String[] {
623b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
63d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
646a6a3aff17e057eeb1457ac4d04ab4b5e8f53abeMike Lockwood    private static final String[] PATH_PROJECTION = new String[] {
655ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            Files.FileColumns._ID, // 0
665ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            Files.FileColumns.DATA, // 1
675ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood    };
68d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String[] PATH_SIZE_PROJECTION = new String[] {
693b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
703b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.DATA, // 1
713b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.SIZE, // 2
72d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
73d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String[] OBJECT_INFO_PROJECTION = new String[] {
743b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
753b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.DATA, // 1
763b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.FORMAT, // 2
773b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.PARENT, // 3
783b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.SIZE, // 4
793b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.DATE_MODIFIED, // 5
80d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
813b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood    private static final String ID_WHERE = Files.FileColumns._ID + "=?";
823b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood    private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
83d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND "
843b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood                                            + Files.FileColumns.FORMAT + "=?";
85d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
8659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" };
8759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private  static final String DEVICE_PROPERTY_WHERE = "code=?";
8859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
89d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    private final MediaScanner mMediaScanner;
90d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
91d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    static {
92d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        System.loadLibrary("media_jni");
93d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
94d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
9501788562f26f213f63c14483fd3977e23b8314abMike Lockwood    public MtpDatabase(Context context, String volumeName, String storagePath) {
96d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        native_setup();
97d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
982837eefc5459427138c080d445bb491c75630163Mike Lockwood        mContext = context;
99d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mMediaProvider = context.getContentResolver().acquireProvider("media");
100d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mVolumeName = volumeName;
10101788562f26f213f63c14483fd3977e23b8314abMike Lockwood        mMediaStoragePath = storagePath;
1022b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood        mExternalStoragePath = Environment.getExternalStorageDirectory().getAbsolutePath();
1038490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        mObjectsUri = Files.getMtpObjectsUri(volumeName);
104d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        mMediaScanner = new MediaScanner(context);
10559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        openDevicePropertiesDatabase(context);
106d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
107d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
108d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    @Override
109dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood    protected void finalize() throws Throwable {
110dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        try {
111dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood            native_finalize();
112dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        } finally {
113dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood            super.finalize();
114dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        }
115d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
116d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1172b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood    private String externalToMediaPath(String path) {
1182b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood        // convert external storage path to media path
1192b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood        if (path != null && mMediaStoragePath != null
1202b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood                && mExternalStoragePath != null
1212b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood                && path.startsWith(mExternalStoragePath)) {
1222b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood            path = mMediaStoragePath + path.substring(mExternalStoragePath.length());
1232b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood        }
1242b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood        return path;
1252b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood    }
1262b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood
12759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private void openDevicePropertiesDatabase(Context context) {
12859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
12959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        int version = mDevicePropDb.getVersion();
13059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
13159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        // initialize if necessary
13259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        if (version != DEVICE_PROPERTIES_DATABASE_VERSION) {
13359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            mDevicePropDb.execSQL("CREATE TABLE properties (" +
13459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
13559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    "code INTEGER UNIQUE ON CONFLICT REPLACE," +
13659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    "value TEXT" +
13759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    ");");
13859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            mDevicePropDb.execSQL("CREATE INDEX property_index ON properties (code);");
13959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            mDevicePropDb.setVersion(DEVICE_PROPERTIES_DATABASE_VERSION);
14059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
14159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
14259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
143d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    private int beginSendObject(String path, int format, int parent,
144d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                         int storage, long size, long modified) {
1452837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
146d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        ContentValues values = new ContentValues();
1473b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.DATA, path);
1483b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.FORMAT, format);
1493b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.PARENT, parent);
150d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        // storage is ignored for now
1513b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.SIZE, size);
1523b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.DATE_MODIFIED, modified);
153d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
154d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        try {
155d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            Uri uri = mMediaProvider.insert(mObjectsUri, values);
156d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            if (uri != null) {
157d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                return Integer.parseInt(uri.getPathSegments().get(2));
158d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            } else {
159d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                return -1;
160d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            }
161d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        } catch (RemoteException e) {
162d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            Log.e(TAG, "RemoteException in beginSendObject", e);
163d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            return -1;
164d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        }
165d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    }
166d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
167413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood    private void endSendObject(String path, int handle, int format, long actualSize, boolean succeeded) {
168d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        if (succeeded) {
1699a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            // handle abstract playlists separately
1709a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            // they do not exist in the file system so don't use the media scanner here
1715367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) {
1729a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                // Strip Windows Media Player file extension
1739a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                if (path.endsWith(".pla")) {
1749a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    path = path.substring(0, path.length() - 4);
1759a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
1769a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
1779a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                // extract name from path
1789a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                String name = path;
1799a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                int lastSlash = name.lastIndexOf('/');
1809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                if (lastSlash >= 0) {
1819a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    name = name.substring(lastSlash + 1);
1829a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
1839a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
1849a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                ContentValues values = new ContentValues(1);
1859a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(Audio.Playlists.DATA, path);
1869a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(Audio.Playlists.NAME, name);
1870b58c19840c577c8d8fd8aa5315676d61b78ba0fMike Lockwood                values.put(Files.FileColumns.FORMAT, format);
1889a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle);
1899a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                try {
1909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values);
1919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                } catch (RemoteException e) {
1929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    Log.e(TAG, "RemoteException in endSendObject", e);
1939a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
1949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            } else {
195413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                if (actualSize >= 0) {
196413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                    // update size if necessary
197413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                    ContentValues values = new ContentValues();
198413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                    values.put(Files.FileColumns.SIZE, actualSize);
199413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                    try {
200413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                        String[] whereArgs = new String[] {  Integer.toString(handle) };
201413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                        mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
202413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                    } catch (RemoteException e) {
203413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                        Log.e(TAG, "RemoteException in mMediaProvider.update", e);
204413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                    }
205413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood                }
206413577d8600413bb1dca3730d4ccf20892b929b4Mike Lockwood
207c37255d5d0fd9e0ec02b0d7cb5c4b235e200d367Mike Lockwood                mMediaScanner.scanMtpFile(path, mVolumeName, handle, format);
2089a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
209d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        } else {
210d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            deleteFile(handle);
211d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        }
212d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
213d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
214d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private int[] getObjectList(int storageID, int format, int parent) {
215d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        // we can ignore storageID until we support multiple storages
216d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Log.d(TAG, "getObjectList parent: " + parent);
217d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
218d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
219d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (format != 0) {
220d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
221d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            PARENT_FORMAT_WHERE,
222d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            new String[] { Integer.toString(parent), Integer.toString(format) },
223d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                             null);
224d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            } else {
225d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
226d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
227d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
228d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c == null) {
229d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                Log.d(TAG, "null cursor");
230d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return null;
231d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
232d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            int count = c.getCount();
233d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (count > 0) {
234d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int[] result = new int[count];
235d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                for (int i = 0; i < count; i++) {
236d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    c.moveToNext();
237d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    result[i] = c.getInt(0);
238d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                }
239d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                Log.d(TAG, "returning " + result);
240d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return result;
241d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
242d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
243d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in getObjectList", e);
244d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
245d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
246d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
247d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
248d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
249d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return null;
250d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
251d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
2527a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    private int getNumObjects(int storageID, int format, int parent) {
2537a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        // we can ignore storageID until we support multiple storages
2547a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        Log.d(TAG, "getObjectList parent: " + parent);
2557a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        Cursor c = null;
2567a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        try {
2577a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (format != 0) {
2587a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
2597a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                            PARENT_FORMAT_WHERE,
2607a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                            new String[] { Integer.toString(parent), Integer.toString(format) },
2617a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                             null);
2627a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            } else {
2637a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
2647a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
2657a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
2667a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (c != null) {
2677a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                return c.getCount();
2687a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
2697a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        } catch (RemoteException e) {
2707a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            Log.e(TAG, "RemoteException in getNumObjects", e);
2717a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        } finally {
2727a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (c != null) {
2737a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                c.close();
2747a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
2757a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        }
2767a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        return -1;
2777a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    }
2787a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood
2794b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedPlaybackFormats() {
2804b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return new int[] {
281e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood            // allow transfering arbitrary files
282e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood            MtpConstants.FORMAT_UNDEFINED,
28312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood
284792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood            MtpConstants.FORMAT_ASSOCIATION,
28512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TEXT,
28612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_HTML,
28712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WAV,
28812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP3,
28912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MPEG,
29012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_EXIF_JPEG,
29112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TIFF_EP,
29212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_GIF,
29312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_JFIF,
29412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_PNG,
29512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TIFF,
29612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WMA,
29712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_OGG,
29812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_AAC,
29912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP4_CONTAINER,
30012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP2,
30112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_3GP_CONTAINER,
302792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood            MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
30312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WPL_PLAYLIST,
30412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_M3U_PLAYLIST,
30512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_PLS_PLAYLIST,
30612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_XML_DOCUMENT,
3074b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        };
3084b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
3094b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
3104b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedCaptureFormats() {
3114b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        // no capture formats yet
3124b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return null;
3134b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
3144b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
315ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] FILE_PROPERTIES = {
316ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
317ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // and IMAGE_PROPERTIES below
3185367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
3195367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
320d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
3215367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
3225367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
323d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
3245367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
325d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
326d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_NAME,
327ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
328ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
329ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
330ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] AUDIO_PROPERTIES = {
331ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
332ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
333ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
334ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
335ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
336ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
337ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
338ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
339ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
340ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
341ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
342ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
343ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
344ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // audio specific properties
345ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ARTIST,
346ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
347ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_ARTIST,
348ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_TRACK,
349ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
350ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DURATION,
351ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_GENRE,
352ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_COMPOSER,
353ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
354ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
355ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] VIDEO_PROPERTIES = {
356ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
357ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
358ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
359ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
360ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
361ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
362ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
363ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
364ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
365ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
366ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
367ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
368ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
369ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // video specific properties
370ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ARTIST,
371ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
372ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DURATION,
373ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
374ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
375ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
376ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] IMAGE_PROPERTIES = {
377ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
378ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
379ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
380ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
381ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
382ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
383ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
384ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
385ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
386ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
387ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
388ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
389ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
390ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // image specific properties
391ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
392ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
393ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
394ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    private int[] getSupportedObjectProperties(int format) {
395ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        switch (format) {
396ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_MP3:
397ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WAV:
398ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WMA:
399ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_OGG:
400ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_AAC:
401ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return AUDIO_PROPERTIES;
402ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_MPEG:
403ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_3GP_CONTAINER:
404ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WMV:
405ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return VIDEO_PROPERTIES;
406ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_EXIF_JPEG:
407ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_GIF:
408ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_PNG:
409ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_BMP:
410ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return IMAGE_PROPERTIES;
411ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            default:
412ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return FILE_PROPERTIES;
413ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
4144b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
4154b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
4164b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedDeviceProperties() {
41759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return new int[] {
41859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
41959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
42059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        };
4214b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
4224b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
423ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    private String queryString(int id, String column) {
424ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        Cursor c = null;
425ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        try {
426ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // for now we are only reading properties from the "objects" table
427ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            c = mMediaProvider.query(mObjectsUri,
428ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                            new String [] { Files.FileColumns._ID, column },
429ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                            ID_WHERE, new String[] { Integer.toString(id) }, null);
430ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            if (c != null && c.moveToNext()) {
431ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return c.getString(1);
432ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            } else {
433ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return "";
434ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            }
435ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        } catch (Exception e) {
436ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            return null;
437ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        } finally {
438ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            if (c != null) {
439ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                c.close();
440ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            }
441ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
442ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    }
443ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
444e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    private String queryAudio(int id, String column) {
445e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        Cursor c = null;
446e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
447e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            c = mMediaProvider.query(Audio.Media.getContentUri(mVolumeName),
448e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            new String [] { Files.FileColumns._ID, column },
449e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            ID_WHERE, new String[] { Integer.toString(id) }, null);
450e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null && c.moveToNext()) {
451e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                return c.getString(1);
452e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            } else {
453e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                return "";
454e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
455e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (Exception e) {
456e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return null;
457e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } finally {
458e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null) {
459e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                c.close();
460e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
461e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
462e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
463e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
464ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    private String queryGenre(int id) {
465ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        Cursor c = null;
466ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        try {
467ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            Uri uri = Audio.Genres.getContentUriForAudioId(mVolumeName, id);
468ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            c = mMediaProvider.query(uri,
469ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                            new String [] { Files.FileColumns._ID, Audio.GenresColumns.NAME },
470ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                            null, null, null);
471ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            if (c != null && c.moveToNext()) {
472ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return c.getString(1);
473ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            } else {
474ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return "";
475ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            }
476ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        } catch (Exception e) {
477ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            Log.e(TAG, "queryGenre exception", e);
478ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            return null;
479ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        } finally {
480ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            if (c != null) {
481ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                c.close();
482ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            }
483ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
484ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    }
485ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
486e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    private Long queryLong(int id, String column) {
487ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        Cursor c = null;
488ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        try {
489ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // for now we are only reading properties from the "objects" table
490ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            c = mMediaProvider.query(mObjectsUri,
491ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                            new String [] { Files.FileColumns._ID, column },
492ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                            ID_WHERE, new String[] { Integer.toString(id) }, null);
493ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            if (c != null && c.moveToNext()) {
494e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                return new Long(c.getLong(1));
495ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            }
496ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        } catch (Exception e) {
497ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        } finally {
498ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            if (c != null) {
499ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                c.close();
500ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            }
501ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
502e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return null;
503ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    }
504ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
505ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    private String nameFromPath(String path) {
506ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        // extract name from full path
507ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        int start = 0;
508ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        int lastSlash = path.lastIndexOf('/');
509ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        if (lastSlash >= 0) {
510ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            start = lastSlash + 1;
511ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
512ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        int end = path.length();
513ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        if (end - start > 255) {
514ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            end = start + 255;
515ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
516ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        return path.substring(start, end);
517ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    }
518ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
519e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    private MtpPropertyList getObjectPropertyList(int handle, int format, int property,
520e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        int groupCode, int depth) {
521e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // FIXME - implement group support
522e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // For now we only support a single property at a time
523e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (groupCode != 0) {
524e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED);
5255ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
526e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (depth > 1) {
527e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_DEPTH_UNSUPPORTED);
5285ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
5295ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
530b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood        String column = null;
531e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int type = MtpConstants.TYPE_UNDEFINED;
532b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood
533e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood         switch (property) {
5345367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            case MtpConstants.PROPERTY_STORAGE_ID:
535e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                // no query needed until we support multiple storage units
536e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                // for now it is always mStorageID
537e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_UINT32;
538e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
539e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood             case MtpConstants.PROPERTY_OBJECT_FORMAT:
5403b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood                column = Files.FileColumns.FORMAT;
541e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_UINT16;
542b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood                break;
5435367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            case MtpConstants.PROPERTY_PROTECTION_STATUS:
544828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                // protection status is always 0
545e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_UINT16;
546e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
5475367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            case MtpConstants.PROPERTY_OBJECT_SIZE:
5483b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood                column = Files.FileColumns.SIZE;
549e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_UINT64;
550b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood                break;
5515367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
552e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                column = Files.FileColumns.DATA;
553e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
554e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
555ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_NAME:
556e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                column = MediaColumns.TITLE;
557e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
558e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
5595367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            case MtpConstants.PROPERTY_DATE_MODIFIED:
5603b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood                column = Files.FileColumns.DATE_MODIFIED;
561e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
562b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood                break;
563ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_DATE_ADDED:
564ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                column = Files.FileColumns.DATE_ADDED;
565e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
566ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
567ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE:
568ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                column = Audio.AudioColumns.YEAR;
569e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
570ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
5715367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            case MtpConstants.PROPERTY_PARENT_OBJECT:
5723b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood                column = Files.FileColumns.PARENT;
573e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_UINT32;
574b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood                break;
5755367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            case MtpConstants.PROPERTY_PERSISTENT_UID:
576828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                // PUID is concatenation of storageID and object handle
577e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_UINT128;
578e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
579ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_DURATION:
580ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                column = Audio.AudioColumns.DURATION;
581e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_UINT32;
582ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
583ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_TRACK:
584e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                column = Audio.AudioColumns.TRACK;
585e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_UINT16;
586e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
587ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_DISPLAY_NAME:
588ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                column = MediaColumns.DISPLAY_NAME;
589e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
590ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
591ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_ARTIST:
592e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
593ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
594ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_ALBUM_NAME:
595e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
596ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
597ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_ALBUM_ARTIST:
598ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                column = Audio.AudioColumns.ALBUM_ARTIST;
599e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
600ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
601ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_GENRE:
602e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                // genre requires a special query
603e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
604e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
605ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_COMPOSER:
606ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                column = Audio.AudioColumns.COMPOSER;
607e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
608ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
609ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.PROPERTY_DESCRIPTION:
610ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                column = Images.ImageColumns.DESCRIPTION;
611e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                type = MtpConstants.TYPE_STR;
612ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                break;
613b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood            default:
614e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                return new MtpPropertyList(0, MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED);
615b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood        }
616b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood
617e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        Cursor c = null;
618e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
619e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (column != null) {
620e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                c = mMediaProvider.query(mObjectsUri,
621e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        new String [] { Files.FileColumns._ID, column },
622e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // depth 0: single record, depth 1: immediate children
623e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        (depth == 0 ? ID_WHERE : PARENT_WHERE),
624e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        new String[] { Integer.toString(handle) }, null);
625e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                if (c == null) {
626e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    return new MtpPropertyList(0, MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
627e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                }
628e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            } else if (depth == 1) {
629e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                c = mMediaProvider.query(mObjectsUri,
630e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        new String [] { Files.FileColumns._ID },
631e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        PARENT_WHERE, new String[] { Integer.toString(handle) }, null);
632e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                if (c == null) {
633e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    return new MtpPropertyList(0, MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
634e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                }
635b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood            }
636e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
637e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            int count = (c == null ? 1 : c.getCount());
638e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            MtpPropertyList result = new MtpPropertyList(count, MtpConstants.RESPONSE_OK);
639e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
640e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            for (int index = 0; index < count; index++) {
641e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                if (c != null) {
642e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    c.moveToNext();
643e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                }
644e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                if (depth == 1) {
645e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    handle = (int)c.getLong(0);
646e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                }
647e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
648e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                switch (property) {
649e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    // handle special cases here
650e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_STORAGE_ID:
651e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        result.setProperty(index, handle, property, MtpConstants.TYPE_UINT32,
652e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                                mStorageID);
653e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
654e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_PROTECTION_STATUS:
655e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // protection status is always 0
656e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        result.setProperty(index, handle, property, MtpConstants.TYPE_UINT16, 0);
657e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
658e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
659e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // special case - need to extract file name from full path
660e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        String value = c.getString(1);
661e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        if (value != null) {
662e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            result.setProperty(index, handle, property, nameFromPath(value));
663e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        } else {
664e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
665e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        }
666e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
667e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_NAME:
668e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // first try title
669e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        String name = c.getString(1);
670e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // then try name
671e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        if (name == null) {
672e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            name = queryString(handle, Audio.PlaylistsColumns.NAME);
673e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        }
674e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // if title and name fail, extract name from full path
675e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        if (name == null) {
676e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            name = queryString(handle, Files.FileColumns.DATA);
677e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            if (name != null) {
678e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                                name = nameFromPath(name);
679e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            }
680e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        }
681e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        if (name != null) {
682e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            result.setProperty(index, handle, property, name);
683e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        } else {
684e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
685e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        }
686e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
687e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_DATE_MODIFIED:
688e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_DATE_ADDED:
689e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // convert from seconds to DateTime
6903159991e586f9e243f60d65a9554828328b00521Mike Lockwood                        result.setProperty(index, handle, property, format_date_time(c.getInt(1)));
691e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
692e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE:
693e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // release date is stored internally as just the year
694e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        int year = c.getInt(1);
695e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        String dateTime = Integer.toString(year) + "0101T000000";
696e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        result.setProperty(index, handle, property, dateTime);
697e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
698e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_PERSISTENT_UID:
699e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        // PUID is concatenation of storageID and object handle
700e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        long puid = mStorageID;
701e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        puid <<= 32;
702e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        puid += handle;
703e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        result.setProperty(index, handle, property, MtpConstants.TYPE_UINT128, puid);
704e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
705e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_TRACK:
706e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        result.setProperty(index, handle, property, MtpConstants.TYPE_UINT16,
707e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                                    c.getInt(1) % 1000);
708e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
709e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_ARTIST:
710e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        result.setProperty(index, handle, property, queryAudio(handle, Audio.AudioColumns.ARTIST));
711e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
712e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_ALBUM_NAME:
713e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        result.setProperty(index, handle, property, queryAudio(handle, Audio.AudioColumns.ALBUM));
714e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
715e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    case MtpConstants.PROPERTY_GENRE:
716e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        String genre = queryGenre(handle);
717e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        if (genre != null) {
718e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            result.setProperty(index, handle, property, genre);
719e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        } else {
720e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            result.setResult(MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE);
721e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        }
722e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        break;
723e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    default:
724e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        if (type == MtpConstants.TYPE_STR) {
725e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            result.setProperty(index, handle, property, c.getString(1));
726e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        } else {
727e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                            result.setProperty(index, handle, property, type, c.getLong(1));
728e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        }
729e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                }
730e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
731e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
732e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return result;
733e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
734e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return new MtpPropertyList(0, MtpConstants.RESPONSE_GENERAL_ERROR);
735e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } finally {
736e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null) {
737e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                c.close();
738e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
739e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
740e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // impossible to get here, so no return statement
741e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
742e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
743e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    private int renameFile(int handle, String newName) {
744e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        Cursor c = null;
745e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
746e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // first compute current path
747e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String path = null;
748e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String[] whereArgs = new String[] {  Integer.toString(handle) };
749e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
750e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null);
751e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null && c.moveToNext()) {
752e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                path = externalToMediaPath(c.getString(1));
753e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
754e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
755e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "RemoteException in getObjectFilePath", e);
756e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
757e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } finally {
758e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null) {
759e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                c.close();
760b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood            }
761b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood        }
762e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (path == null) {
763e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
764e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
765e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
766e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // now rename the file.  make sure this succeeds before updating database
767e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        File oldFile = new File(path);
768e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int lastSlash = path.lastIndexOf('/');
769e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (lastSlash <= 1) {
770e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
771e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
772e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String newPath = path.substring(0, lastSlash + 1) + newName;
773e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        File newFile = new File(newPath);
774e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        boolean success = oldFile.renameTo(newFile);
775e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        Log.d(TAG, "renaming "+ path + " to " + newPath + (success ? " succeeded" : " failed"));
776e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (!success) {
777e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
778e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
779e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
780e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // finally update database
781e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        ContentValues values = new ContentValues();
782e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        values.put(Files.FileColumns.DATA, newPath);
783e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int updated = 0;
784e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
785e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // note - we are relying on a special case in MediaProvider.update() to update
786e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // the paths for all children in the case where this is a directory.
787e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            updated = mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
788e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
789e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "RemoteException in mMediaProvider.update", e);
790e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
791e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (updated == 0) {
792e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "Unable to update path for " + path + " to " + newPath);
793e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // this shouldn't happen, but if it does we need to rename the file to its original name
794e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            newFile.renameTo(oldFile);
795e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
796e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
797e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
798e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return MtpConstants.RESPONSE_OK;
799d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
800d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
80159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int setObjectProperty(int handle, int property,
80259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                            long intValue, String stringValue) {
80359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        Log.d(TAG, "setObjectProperty: " + property);
8045ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
8055ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        switch (property) {
8065ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
8075ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood                return renameFile(handle, stringValue);
8085ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
8095ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            default:
8105ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood                return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
8115ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
81259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
81359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
81459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
81559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        Log.d(TAG, "getDeviceProperty: " + property);
81659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
81759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        switch (property) {
81859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
81959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
82059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                // writable string properties kept in our device property database
82159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                Cursor c = null;
82259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                try {
82359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    c = mDevicePropDb.query("properties", DEVICE_PROPERTY_PROJECTION,
82459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        DEVICE_PROPERTY_WHERE, new String[] {  Integer.toString(property) },
82559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        null, null, null);
82659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
82759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    if (c != null && c.moveToNext()) {
82859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        String value = c.getString(1);
82959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        int length = value.length();
83059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        if (length > 255) {
83159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                            length = 255;
83259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        }
83359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        value.getChars(0, length, outStringValue, 0);
83459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        outStringValue[length] = 0;
83559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    } else {
83659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        outStringValue[0] = 0;
83759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    }
83859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    return MtpConstants.RESPONSE_OK;
83959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                } finally {
84059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    if (c != null) {
84159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        c.close();
84259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    }
84359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                }
84459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
84559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
84659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
84759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
84859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
84959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int setDeviceProperty(int property, long intValue, String stringValue) {
85059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        Log.d(TAG, "setDeviceProperty: " + property + " : " + stringValue);
85159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
85259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        switch (property) {
85359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
85459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
85559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                // writable string properties kept in our device property database
85659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                try {
85759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    ContentValues values = new ContentValues();
85859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    values.put("code", property);
85959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    values.put("value", stringValue);
86059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    mDevicePropDb.insert("properties", "code", values);
86159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    return MtpConstants.RESPONSE_OK;
86259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                } catch (Exception e) {
86359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    return MtpConstants.RESPONSE_GENERAL_ERROR;
86459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                }
86559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
86659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
86759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
86859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
86959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
870d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
871d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                        char[] outName, long[] outSizeModified) {
872d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Log.d(TAG, "getObjectInfo: " + handle);
873d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
874d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
875d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION,
876d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
877d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null && c.moveToNext()) {
878b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood                outStorageFormatParent[0] = mStorageID;
879d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outStorageFormatParent[1] = c.getInt(2);
880d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outStorageFormatParent[2] = c.getInt(3);
881d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
882d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                // extract name from path
883d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                String path = c.getString(1);
884d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int lastSlash = path.lastIndexOf('/');
885d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int start = (lastSlash >= 0 ? lastSlash + 1 : 0);
886d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int end = path.length();
887d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                if (end - start > 255) {
888d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    end = start + 255;
889d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                }
890d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                path.getChars(start, end, outName, 0);
891d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outName[end - start] = 0;
892d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
893d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outSizeModified[0] = c.getLong(4);
894d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outSizeModified[1] = c.getLong(5);
895d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return true;
896d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
897d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
8982b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood            Log.e(TAG, "RemoteException in getObjectInfo", e);
899d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
900d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
901d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
902d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
903d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
904d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return false;
905d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
906d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
90759c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLength) {
908d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Log.d(TAG, "getObjectFilePath: " + handle);
90901788562f26f213f63c14483fd3977e23b8314abMike Lockwood        if (handle == 0) {
91001788562f26f213f63c14483fd3977e23b8314abMike Lockwood            // special case root directory
91101788562f26f213f63c14483fd3977e23b8314abMike Lockwood            mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0);
91201788562f26f213f63c14483fd3977e23b8314abMike Lockwood            outFilePath[mMediaStoragePath.length()] = 0;
91301788562f26f213f63c14483fd3977e23b8314abMike Lockwood            outFileLength[0] = 0;
91401788562f26f213f63c14483fd3977e23b8314abMike Lockwood            return MtpConstants.RESPONSE_OK;
91501788562f26f213f63c14483fd3977e23b8314abMike Lockwood        }
916d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
917d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
918d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_PROJECTION,
919d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
920d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null && c.moveToNext()) {
9212b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood                String path = externalToMediaPath(c.getString(1));
922d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                path.getChars(0, path.length(), outFilePath, 0);
923d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outFilePath[path.length()] = 0;
924d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outFileLength[0] = c.getLong(2);
9255367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
92659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            } else {
9275367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
928d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
929d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
930d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in getObjectFilePath", e);
9315367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
932d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
933d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
934d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
935d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
936d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
937d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
938d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
939ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood    private int deleteRecursive(int handle) throws RemoteException {
940ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood        int[] children = getObjectList(0 /* storageID */, 0 /* format */, handle);
941ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood        Uri uri = Files.getMtpObjectsUri(mVolumeName, handle);
942ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood        // delete parent first, to avoid potential infinite recursion
943ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood        int count = mMediaProvider.delete(uri, null, null);
944ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood        if (count == 1) {
945ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood            if (children != null) {
946ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood                for (int i = 0; i < children.length; i++) {
947ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood                    count += deleteRecursive(children[i]);
948ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood                }
949ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood            }
950ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood        }
951ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood        return count;
952ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood    }
953ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood
95459c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    private int deleteFile(int handle) {
955d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Log.d(TAG, "deleteFile: " + handle);
9562837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
957d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
958ccb6e961941c607208ed9ac44db2dc9a9649b218Mike Lockwood            if (deleteRecursive(handle) > 0) {
9595367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
96059c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            } else {
9615367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
96259c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            }
963d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
964d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in deleteFile", e);
9655367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
966d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
967d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
968d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
9699a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    private int[] getObjectReferences(int handle) {
9709a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        Log.d(TAG, "getObjectReferences for: " + handle);
9718490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
9729a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        Cursor c = null;
9739a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        try {
9749a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null);
9759a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (c == null) {
9769a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                return null;
9779a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
9789a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            int count = c.getCount();
9799a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (count > 0) {
9809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                int[] result = new int[count];
9819a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                for (int i = 0; i < count; i++) {
9829a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    c.moveToNext();
9839a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    result[i] = c.getInt(0);
9849a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
9859a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                return result;
9869a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
9879a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } catch (RemoteException e) {
9889a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            Log.e(TAG, "RemoteException in getObjectList", e);
9899a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } finally {
9909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (c != null) {
9919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                c.close();
9929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
9939a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
9949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        return null;
9959a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
9969a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
9979a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    private int setObjectReferences(int handle, int[] references) {
9982837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
9998490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
10009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        int count = references.length;
10019a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        ContentValues[] valuesList = new ContentValues[count];
10029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        for (int i = 0; i < count; i++) {
10039a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            ContentValues values = new ContentValues();
10043b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            values.put(Files.FileColumns._ID, references[i]);
10059a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            valuesList[i] = values;
10069a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
10079a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        try {
10089a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (count == mMediaProvider.bulkInsert(uri, valuesList)) {
10095367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
10109a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
10119a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } catch (RemoteException e) {
10129a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            Log.e(TAG, "RemoteException in setObjectReferences", e);
10139a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
10145367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood        return MtpConstants.RESPONSE_GENERAL_ERROR;
10159a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
10169a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
10172837eefc5459427138c080d445bb491c75630163Mike Lockwood    private void sessionStarted() {
10182837eefc5459427138c080d445bb491c75630163Mike Lockwood        Log.d(TAG, "sessionStarted");
10192837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = false;
10202837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
10212837eefc5459427138c080d445bb491c75630163Mike Lockwood
10222837eefc5459427138c080d445bb491c75630163Mike Lockwood    private void sessionEnded() {
10232837eefc5459427138c080d445bb491c75630163Mike Lockwood        Log.d(TAG, "sessionEnded");
10242837eefc5459427138c080d445bb491c75630163Mike Lockwood        if (mDatabaseModified) {
10252837eefc5459427138c080d445bb491c75630163Mike Lockwood            Log.d(TAG, "sending ACTION_MTP_SESSION_END");
1026a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwood            mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END));
10272837eefc5459427138c080d445bb491c75630163Mike Lockwood            mDatabaseModified = false;
10282837eefc5459427138c080d445bb491c75630163Mike Lockwood        }
10292837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
10302837eefc5459427138c080d445bb491c75630163Mike Lockwood
1031d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    // used by the JNI code
1032d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private int mNativeContext;
1033d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1034d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private native final void native_setup();
1035d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private native final void native_finalize();
10363159991e586f9e243f60d65a9554828328b00521Mike Lockwood    private native String format_date_time(long seconds);
1037d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
1038