MtpDatabase.java revision fe464a76d8fc858be971dbb5e67b1d22fd925347
1d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/*
2d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Copyright (C) 2010 The Android Open Source Project
3d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
4d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
5d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * you may not use this file except in compliance with the License.
6d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * You may obtain a copy of the License at
7d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
8d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
9d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
10d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Unless required by applicable law or agreed to in writing, software
11d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
12d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * See the License for the specific language governing permissions and
14d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * limitations under the License.
15d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */
16d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
170cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodpackage android.mtp;
18d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
19d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.Context;
20d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodimport android.content.ContentValues;
21d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.IContentProvider;
222837eefc5459427138c080d445bb491c75630163Mike Lockwoodimport android.content.Intent;
23775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwoodimport android.content.SharedPreferences;
24d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.database.Cursor;
2559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodimport android.database.sqlite.SQLiteDatabase;
260cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodimport android.media.MediaScanner;
27d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.net.Uri;
282b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwoodimport android.os.Environment;
29d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException;
30a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwoodimport android.provider.MediaStore;
319a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.Audio;
323b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwoodimport android.provider.MediaStore.Files;
33ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.Images;
34ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.MediaColumns;
35d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log;
36ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.Display;
37ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.WindowManager;
38d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
395ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwoodimport java.io.File;
407d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport java.util.HashMap;
41fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.chaimport java.util.Locale;
425ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
43d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/**
44d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide}
45d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */
46d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic class MtpDatabase {
47d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
48d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String TAG = "MtpDatabase";
49d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
502837eefc5459427138c080d445bb491c75630163Mike Lockwood    private final Context mContext;
51d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final IContentProvider mMediaProvider;
52d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final String mVolumeName;
53d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final Uri mObjectsUri;
54b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    private final String mMediaStoragePath; // path to primary storage
55b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>();
56d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    // cached property groups for single properties
587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByProperty
597d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            = new HashMap<Integer, MtpPropertyGroup>();
607d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
617d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    // cached property groups for all properties for a given format
627d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByFormat
637d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            = new HashMap<Integer, MtpPropertyGroup>();
647d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
652837eefc5459427138c080d445bb491c75630163Mike Lockwood    // true if the database has been modified in the current MTP session
662837eefc5459427138c080d445bb491c75630163Mike Lockwood    private boolean mDatabaseModified;
672837eefc5459427138c080d445bb491c75630163Mike Lockwood
68775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood    // SharedPreferences for writable MTP device properties
69775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood    private SharedPreferences mDeviceProperties;
7059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1;
7159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
72d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String[] ID_PROJECTION = new String[] {
733b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
74d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
756a6a3aff17e057eeb1457ac4d04ab4b5e8f53abeMike Lockwood    private static final String[] PATH_PROJECTION = new String[] {
765ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            Files.FileColumns._ID, // 0
775ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            Files.FileColumns.DATA, // 1
785ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood    };
79365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood    private static final String[] PATH_SIZE_FORMAT_PROJECTION = new String[] {
803b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
813b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.DATA, // 1
823b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.SIZE, // 2
83365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            Files.FileColumns.FORMAT, // 3
84d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
85d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String[] OBJECT_INFO_PROJECTION = new String[] {
863b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
87b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            Files.FileColumns.STORAGE_ID, // 1
883b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.FORMAT, // 2
893b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.PARENT, // 3
90b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            Files.FileColumns.DATA, // 4
91b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            Files.FileColumns.SIZE, // 5
92b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            Files.FileColumns.DATE_MODIFIED, // 6
93d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
943b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood    private static final String ID_WHERE = Files.FileColumns._ID + "=?";
95bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood    private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
966acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood
976acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String STORAGE_WHERE = Files.FileColumns.STORAGE_ID + "=?";
986acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String FORMAT_WHERE = Files.FileColumns.PARENT + "=?";
996acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String PARENT_WHERE = Files.FileColumns.FORMAT + "=?";
1006acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String STORAGE_FORMAT_WHERE = STORAGE_WHERE + " AND "
101b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                                            + Files.FileColumns.FORMAT + "=?";
1026acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String STORAGE_PARENT_WHERE = STORAGE_WHERE + " AND "
1036acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                                            + Files.FileColumns.PARENT + "=?";
1046acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String FORMAT_PARENT_WHERE = FORMAT_WHERE + " AND "
1056acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                                            + Files.FileColumns.PARENT + "=?";
1066acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String STORAGE_FORMAT_PARENT_WHERE = STORAGE_FORMAT_WHERE + " AND "
1076acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                                            + Files.FileColumns.PARENT + "=?";
108d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
109d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    private final MediaScanner mMediaScanner;
110d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
111d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    static {
112d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        System.loadLibrary("media_jni");
113d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
114d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
11501788562f26f213f63c14483fd3977e23b8314abMike Lockwood    public MtpDatabase(Context context, String volumeName, String storagePath) {
116d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        native_setup();
117d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1182837eefc5459427138c080d445bb491c75630163Mike Lockwood        mContext = context;
119d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mMediaProvider = context.getContentResolver().acquireProvider("media");
120d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mVolumeName = volumeName;
12101788562f26f213f63c14483fd3977e23b8314abMike Lockwood        mMediaStoragePath = storagePath;
1228490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        mObjectsUri = Files.getMtpObjectsUri(volumeName);
123d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        mMediaScanner = new MediaScanner(context);
124fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha
125fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha        // Set locale to MediaScanner.
126fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha        Locale locale = context.getResources().getConfiguration().locale;
127fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha        if (locale != null) {
128fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha            String language = locale.getLanguage();
129fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha            String country = locale.getCountry();
130fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha            if (language != null) {
131fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                if (country != null) {
132fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                    mMediaScanner.setLocale(language + "_" + country);
133fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                } else {
134fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                    mMediaScanner.setLocale(language);
135fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                }
136fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha            }
137fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha        }
138775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        initDeviceProperties(context);
139d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
140d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
141d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    @Override
142dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood    protected void finalize() throws Throwable {
143dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        try {
144dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood            native_finalize();
145dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        } finally {
146dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood            super.finalize();
147dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        }
148d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
149d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
150b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    public void addStorage(MtpStorage storage) {
151b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        mStorageMap.put(storage.getPath(), storage);
152b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    }
153b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood
154b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    public void removeStorage(MtpStorage storage) {
155b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        mStorageMap.remove(storage.getPath());
156b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    }
157b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood
158775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood    private void initDeviceProperties(Context context) {
159775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        final String devicePropertiesName = "device-properties";
160775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        mDeviceProperties = context.getSharedPreferences(devicePropertiesName, Context.MODE_PRIVATE);
161775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        File databaseFile = context.getDatabasePath(devicePropertiesName);
162775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood
163775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        if (databaseFile.exists()) {
164775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            // for backward compatibility - read device properties from sqlite database
165775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            // and migrate them to shared prefs
166775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            SQLiteDatabase db = null;
167775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            Cursor c = null;
168775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            try {
169775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                db = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
170775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                if (db != null) {
171775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                    c = db.query("properties", new String[] { "_id", "code", "value" },
172775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                            null, null, null, null, null);
173775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                    if (c != null) {
174775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        SharedPreferences.Editor e = mDeviceProperties.edit();
175775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        while (c.moveToNext()) {
176775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                            String name = c.getString(1);
177775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                            String value = c.getString(2);
178775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                            e.putString(name, value);
179775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        }
180775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        e.commit();
181775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                    }
182775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                }
183775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            } catch (Exception e) {
184775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                Log.e(TAG, "failed to migrate device properties", e);
185775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            } finally {
186775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                if (c != null) c.close();
187775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                if (db != null) db.close();
188775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            }
189775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            databaseFile.delete();
19059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
19159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
19259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
193d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    private int beginSendObject(String path, int format, int parent,
194b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                         int storageId, long size, long modified) {
195bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood        // first make sure the object does not exist
196bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood        if (path != null) {
197bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            Cursor c = null;
198bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            try {
199bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE,
200bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                        new String[] { path }, null);
201bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                if (c != null && c.getCount() > 0) {
202bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    Log.w(TAG, "file already exists in beginSendObject: " + path);
203bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    return -1;
204bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                }
205bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            } catch (RemoteException e) {
206bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                Log.e(TAG, "RemoteException in beginSendObject", e);
207bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            } finally {
208bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                if (c != null) {
209bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    c.close();
210bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                }
211bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            }
212bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood        }
213bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood
2142837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
215d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        ContentValues values = new ContentValues();
2163b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.DATA, path);
2173b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.FORMAT, format);
2183b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.PARENT, parent);
219b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        values.put(Files.FileColumns.STORAGE_ID, storageId);
2203b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.SIZE, size);
2213b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.DATE_MODIFIED, modified);
222d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
223d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        try {
224d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            Uri uri = mMediaProvider.insert(mObjectsUri, values);
225d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            if (uri != null) {
226d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                return Integer.parseInt(uri.getPathSegments().get(2));
227d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            } else {
228d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                return -1;
229d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            }
230d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        } catch (RemoteException e) {
231d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            Log.e(TAG, "RemoteException in beginSendObject", e);
232d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            return -1;
233d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        }
234d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    }
235d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
2367a0bd17bceaf3efc3732e30c538fae420d3b742cMike Lockwood    private void endSendObject(String path, int handle, int format, boolean succeeded) {
237d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        if (succeeded) {
2389a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            // handle abstract playlists separately
2399a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            // they do not exist in the file system so don't use the media scanner here
2405367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) {
2419a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                // extract name from path
2429a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                String name = path;
2439a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                int lastSlash = name.lastIndexOf('/');
2449a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                if (lastSlash >= 0) {
2459a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    name = name.substring(lastSlash + 1);
2469a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
2478cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                // strip trailing ".pla" from the name
2488cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                if (name.endsWith(".pla")) {
2498cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                    name = name.substring(0, name.length() - 4);
2508cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                }
2519a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
2529a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                ContentValues values = new ContentValues(1);
2539a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(Audio.Playlists.DATA, path);
2549a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(Audio.Playlists.NAME, name);
2550b58c19840c577c8d8fd8aa5315676d61b78ba0fMike Lockwood                values.put(Files.FileColumns.FORMAT, format);
2568ed67acf38ccdfdb89553ed58620a135f2100e10Mike Lockwood                values.put(Files.FileColumns.DATE_MODIFIED, System.currentTimeMillis() / 1000);
2579a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle);
2589a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                try {
2599a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values);
2609a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                } catch (RemoteException e) {
2619a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    Log.e(TAG, "RemoteException in endSendObject", e);
2629a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
2639a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            } else {
264c37255d5d0fd9e0ec02b0d7cb5c4b235e200d367Mike Lockwood                mMediaScanner.scanMtpFile(path, mVolumeName, handle, format);
2659a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
266d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        } else {
267d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            deleteFile(handle);
268d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        }
269d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
270d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
271b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException {
2726acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood        if (storageID == 0xFFFFFFFF) {
2736acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood            // query all stores
2746acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood            if (format == 0) {
2756acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                // query all formats
2766acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0) {
2776acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // query all objects
2786acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    return mMediaProvider.query(mObjectsUri, ID_PROJECTION, null, null, null);
2796acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
2806acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0xFFFFFFFF) {
2816acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // all objects in root of store
2826acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    parent = 0;
2836acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
2846acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                return mMediaProvider.query(mObjectsUri, ID_PROJECTION, PARENT_WHERE,
2856acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                        new String[] { Integer.toString(parent) }, null);
286b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            } else {
2876acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                // query specific format
2886acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0) {
2896acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // query all objects
2906acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_WHERE,
2916acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                            new String[] { Integer.toString(format) }, null);
2926acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
2936acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0xFFFFFFFF) {
2946acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // all objects in root of store
2956acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    parent = 0;
2966acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
2976acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                return mMediaProvider.query(mObjectsUri, ID_PROJECTION, FORMAT_PARENT_WHERE,
2986acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                        new String[] { Integer.toString(format), Integer.toString(parent) }, null);
299b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            }
300b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        } else {
3016acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood            // query specific store
3026acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood            if (format == 0) {
3036acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                // query all formats
3046acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0) {
3056acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // query all objects
3066acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_WHERE,
3076acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                            new String[] { Integer.toString(storageID) }, null);
3086acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
3096acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0xFFFFFFFF) {
3106acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // all objects in root of store
3116acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    parent = 0;
3126acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
3136acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_PARENT_WHERE,
3146acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                        new String[] { Integer.toString(storageID), Integer.toString(parent) },
3156acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                        null);
316d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            } else {
3176acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                // query specific format
3186acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0) {
3196acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // query all objects
3206acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_WHERE,
3216acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                            new String[] {  Integer.toString(storageID), Integer.toString(format) },
3226acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                            null);
3236acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
3246acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0xFFFFFFFF) {
3256acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // all objects in root of store
3266acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    parent = 0;
3276acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
3286acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                return mMediaProvider.query(mObjectsUri, ID_PROJECTION, STORAGE_FORMAT_PARENT_WHERE,
3296acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                        new String[] { Integer.toString(storageID),
3306acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                                       Integer.toString(format),
3316acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                                       Integer.toString(parent) },
3326acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                        null);
333d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
334b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        }
335b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    }
336b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood
337b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    private int[] getObjectList(int storageID, int format, int parent) {
338b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        Cursor c = null;
339b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        try {
340b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            c = createObjectQuery(storageID, format, parent);
341d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c == null) {
342d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return null;
343d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
344d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            int count = c.getCount();
345d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (count > 0) {
346d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int[] result = new int[count];
347d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                for (int i = 0; i < count; i++) {
348d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    c.moveToNext();
349d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    result[i] = c.getInt(0);
350d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                }
351d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return result;
352d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
353d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
354d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in getObjectList", e);
355d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
356d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
357d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
358d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
359d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
360d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return null;
361d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
362d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
3637a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    private int getNumObjects(int storageID, int format, int parent) {
3647a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        Cursor c = null;
3657a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        try {
366b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            c = createObjectQuery(storageID, format, parent);
3677a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (c != null) {
3687a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                return c.getCount();
3697a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
3707a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        } catch (RemoteException e) {
3717a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            Log.e(TAG, "RemoteException in getNumObjects", e);
3727a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        } finally {
3737a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (c != null) {
3747a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                c.close();
3757a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
3767a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        }
3777a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        return -1;
3787a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    }
3797a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood
3804b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedPlaybackFormats() {
3814b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return new int[] {
382e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood            // allow transfering arbitrary files
383e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood            MtpConstants.FORMAT_UNDEFINED,
38412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood
385792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood            MtpConstants.FORMAT_ASSOCIATION,
38612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TEXT,
38712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_HTML,
38812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WAV,
38912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP3,
39012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MPEG,
39112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_EXIF_JPEG,
39212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TIFF_EP,
39312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_GIF,
39412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_JFIF,
39512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_PNG,
39612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TIFF,
39712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WMA,
39812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_OGG,
39912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_AAC,
40012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP4_CONTAINER,
40112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP2,
40212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_3GP_CONTAINER,
403792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood            MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
40412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WPL_PLAYLIST,
40512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_M3U_PLAYLIST,
40612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_PLS_PLAYLIST,
40712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_XML_DOCUMENT,
408f9f223edb408cdc9fd946dc099a86857079a639fGlenn Kasten            MtpConstants.FORMAT_FLAC,
4094b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        };
4104b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
4114b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
4124b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedCaptureFormats() {
4134b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        // no capture formats yet
4144b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return null;
4154b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
4164b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
417ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] FILE_PROPERTIES = {
418ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
419ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // and IMAGE_PROPERTIES below
4205367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
4215367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
422d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
4235367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
4245367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
425d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
4265367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
427d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
428d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_NAME,
429ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
430ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
431ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
432ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] AUDIO_PROPERTIES = {
433ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
434ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
435ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
436ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
437ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
438ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
439ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
440ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
441ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
442ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
443ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
444ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
445ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
446ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // audio specific properties
447ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ARTIST,
448ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
449ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_ARTIST,
450ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_TRACK,
451ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
452ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DURATION,
453ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_GENRE,
454ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_COMPOSER,
455ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
456ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
457ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] VIDEO_PROPERTIES = {
458ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
459ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
460ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
461ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
462ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
463ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
464ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
465ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
466ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
467ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
468ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
469ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
470ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
471ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // video specific properties
472ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ARTIST,
473ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
474ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DURATION,
475ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
476ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
477ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
478ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] IMAGE_PROPERTIES = {
479ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
480ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
481ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
482ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
483ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
484ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
485ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
486ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
487ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
488ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
489ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
490ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
491ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
492ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // image specific properties
493ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
494ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
495ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
4967d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    static final int[] ALL_PROPERTIES = {
4977d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // NOTE must match FILE_PROPERTIES above
4987d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
4997d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
5007d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
5017d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
5027d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
5037d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
5047d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
5057d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
5067d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_NAME,
5077d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
5087d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
5097d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
5107d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // image specific properties
5117d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
5127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
5137d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // audio specific properties
5147d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ARTIST,
5157d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
5167d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_ARTIST,
5177d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_TRACK,
5187d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
5197d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DURATION,
5207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_GENRE,
5217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_COMPOSER,
5227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
5237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // video specific properties
5247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ARTIST,
5257d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
5267d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DURATION,
5277d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
5287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
5297d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // image specific properties
5307d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
5317d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    };
5327d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
533ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    private int[] getSupportedObjectProperties(int format) {
534ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        switch (format) {
535ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_MP3:
536ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WAV:
537ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WMA:
538ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_OGG:
539ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_AAC:
540ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return AUDIO_PROPERTIES;
541ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_MPEG:
542ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_3GP_CONTAINER:
543ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WMV:
544ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return VIDEO_PROPERTIES;
545ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_EXIF_JPEG:
546ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_GIF:
547ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_PNG:
548ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_BMP:
549ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return IMAGE_PROPERTIES;
5507d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            case 0:
5517d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                return ALL_PROPERTIES;
552ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            default:
553ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return FILE_PROPERTIES;
554ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
5554b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
5564b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
5574b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedDeviceProperties() {
55859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return new int[] {
55959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
56059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
561ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
56259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        };
5634b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
5644b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
565e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
5667d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private MtpPropertyList getObjectPropertyList(long handle, int format, long property,
567e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        int groupCode, int depth) {
568e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // FIXME - implement group support
569e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (groupCode != 0) {
570e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED);
5715ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
5725ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
5737d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        MtpPropertyGroup propertyGroup;
5747d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        if (property == 0xFFFFFFFFL) {
5757d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             propertyGroup = mPropertyGroupsByFormat.get(format);
5767d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             if (propertyGroup == null) {
5777d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                int[] propertyList = getSupportedObjectProperties(format);
5787d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList);
5797d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                mPropertyGroupsByFormat.put(new Integer(format), propertyGroup);
580e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
5817d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        } else {
5827d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood              propertyGroup = mPropertyGroupsByProperty.get(property);
5837d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             if (propertyGroup == null) {
5847d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                int[] propertyList = new int[] { (int)property };
5857d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList);
5867d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup);
587e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
588e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
5897d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
590b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        return propertyGroup.getPropertyList((int)handle, format, depth);
591e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
592e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
593e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    private int renameFile(int handle, String newName) {
594e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        Cursor c = null;
595e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
596e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // first compute current path
597e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String path = null;
598e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String[] whereArgs = new String[] {  Integer.toString(handle) };
599e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
600e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null);
601e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null && c.moveToNext()) {
6021c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood                path = c.getString(1);
603e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
604e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
605e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "RemoteException in getObjectFilePath", e);
606e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
607e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } finally {
608e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null) {
609e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                c.close();
610b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood            }
611b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood        }
612e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (path == null) {
613e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
614e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
615e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
616e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // now rename the file.  make sure this succeeds before updating database
617e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        File oldFile = new File(path);
618e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int lastSlash = path.lastIndexOf('/');
619e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (lastSlash <= 1) {
620e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
621e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
622e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String newPath = path.substring(0, lastSlash + 1) + newName;
623e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        File newFile = new File(newPath);
624e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        boolean success = oldFile.renameTo(newFile);
625e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (!success) {
626f26a586c86b097f975e26fe526ead564ad011bd0Mike Lockwood            Log.w(TAG, "renaming "+ path + " to " + newPath + " failed");
627e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
628e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
629e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
630e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // finally update database
631e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        ContentValues values = new ContentValues();
632e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        values.put(Files.FileColumns.DATA, newPath);
633e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int updated = 0;
634e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
635e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // note - we are relying on a special case in MediaProvider.update() to update
636e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // the paths for all children in the case where this is a directory.
637e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            updated = mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
638e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
639e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "RemoteException in mMediaProvider.update", e);
640e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
641e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (updated == 0) {
642e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "Unable to update path for " + path + " to " + newPath);
643e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // this shouldn't happen, but if it does we need to rename the file to its original name
644e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            newFile.renameTo(oldFile);
645e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
646e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
647e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
648e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return MtpConstants.RESPONSE_OK;
649d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
650d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
65159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int setObjectProperty(int handle, int property,
65259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                            long intValue, String stringValue) {
6535ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        switch (property) {
6545ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
6555ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood                return renameFile(handle, stringValue);
6565ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
6575ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            default:
6585ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood                return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
6595ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
66059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
66159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
66259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
66359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        switch (property) {
66459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
66559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
666775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                // writable string properties kept in shared preferences
667775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                String value = mDeviceProperties.getString(Integer.toString(property), "");
668775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                int length = value.length();
669775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                if (length > 255) {
670775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                    length = 255;
67159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                }
672775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                value.getChars(0, length, outStringValue, 0);
673775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                outStringValue[length] = 0;
674775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                return MtpConstants.RESPONSE_OK;
67559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
676ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
677ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                // use screen size as max image size
678ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                Display display = ((WindowManager)mContext.getSystemService(
679ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                        Context.WINDOW_SERVICE)).getDefaultDisplay();
68044bc17c6b517aef35a390c81b5aa79c4f284f744Dianne Hackborn                int width = display.getMaximumSizeDimension();
68144bc17c6b517aef35a390c81b5aa79c4f284f744Dianne Hackborn                int height = display.getMaximumSizeDimension();
682ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                String imageSize = Integer.toString(width) + "x" +  Integer.toString(height);
683ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
684ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                outStringValue[imageSize.length()] = 0;
685ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                return MtpConstants.RESPONSE_OK;
686ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood
687ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            default:
688ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
689ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood        }
69059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
69159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
69259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int setDeviceProperty(int property, long intValue, String stringValue) {
69359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        switch (property) {
69459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
69559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
696775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                // writable string properties kept in shared prefs
697775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                SharedPreferences.Editor e = mDeviceProperties.edit();
698775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                e.putString(Integer.toString(property), stringValue);
699775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                return (e.commit() ? MtpConstants.RESPONSE_OK
700775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        : MtpConstants.RESPONSE_GENERAL_ERROR);
70159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
70259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
70359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
70459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
70559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
706d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
707d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                        char[] outName, long[] outSizeModified) {
708d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
709d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
710d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION,
711d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
712d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null && c.moveToNext()) {
713b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                outStorageFormatParent[0] = c.getInt(1);
714d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outStorageFormatParent[1] = c.getInt(2);
715d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outStorageFormatParent[2] = c.getInt(3);
716d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
717d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                // extract name from path
718b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                String path = c.getString(4);
719d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int lastSlash = path.lastIndexOf('/');
720d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int start = (lastSlash >= 0 ? lastSlash + 1 : 0);
721d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int end = path.length();
722d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                if (end - start > 255) {
723d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    end = start + 255;
724d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                }
725d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                path.getChars(start, end, outName, 0);
726d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outName[end - start] = 0;
727d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
728b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                outSizeModified[0] = c.getLong(5);
729b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                outSizeModified[1] = c.getLong(6);
730d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return true;
731d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
732d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
7332b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood            Log.e(TAG, "RemoteException in getObjectInfo", e);
734d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
735d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
736d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
737d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
738d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
739d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return false;
740d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
741d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
742365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood    private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) {
74301788562f26f213f63c14483fd3977e23b8314abMike Lockwood        if (handle == 0) {
74401788562f26f213f63c14483fd3977e23b8314abMike Lockwood            // special case root directory
74501788562f26f213f63c14483fd3977e23b8314abMike Lockwood            mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0);
74601788562f26f213f63c14483fd3977e23b8314abMike Lockwood            outFilePath[mMediaStoragePath.length()] = 0;
747365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            outFileLengthFormat[0] = 0;
748365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            outFileLengthFormat[1] = MtpConstants.FORMAT_ASSOCIATION;
74901788562f26f213f63c14483fd3977e23b8314abMike Lockwood            return MtpConstants.RESPONSE_OK;
75001788562f26f213f63c14483fd3977e23b8314abMike Lockwood        }
751d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
752d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
753365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
754d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
755d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null && c.moveToNext()) {
7561c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood                String path = c.getString(1);
757d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                path.getChars(0, path.length(), outFilePath, 0);
758d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outFilePath[path.length()] = 0;
759365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                outFileLengthFormat[0] = c.getLong(2);
760365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                outFileLengthFormat[1] = c.getLong(3);
7615367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
76259c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            } else {
7635367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
764d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
765d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
766d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in getObjectFilePath", e);
7675367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
768d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
769d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
770d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
771d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
772d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
773d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
774d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
77559c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    private int deleteFile(int handle) {
7762837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
77755f808cff9913a00164120a422af6ca45db5072bMike Lockwood        String path = null;
77855f808cff9913a00164120a422af6ca45db5072bMike Lockwood        int format = 0;
77955f808cff9913a00164120a422af6ca45db5072bMike Lockwood
78055f808cff9913a00164120a422af6ca45db5072bMike Lockwood        Cursor c = null;
781d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
78255f808cff9913a00164120a422af6ca45db5072bMike Lockwood            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
78355f808cff9913a00164120a422af6ca45db5072bMike Lockwood                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
78455f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (c != null && c.moveToNext()) {
78555f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // don't convert to media path here, since we will be matching
78655f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // against paths in the database matching /data/media
78755f808cff9913a00164120a422af6ca45db5072bMike Lockwood                path = c.getString(1);
78855f808cff9913a00164120a422af6ca45db5072bMike Lockwood                format = c.getInt(3);
78955f808cff9913a00164120a422af6ca45db5072bMike Lockwood            } else {
79055f808cff9913a00164120a422af6ca45db5072bMike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
79155f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
79255f808cff9913a00164120a422af6ca45db5072bMike Lockwood
79355f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (path == null || format == 0) {
79455f808cff9913a00164120a422af6ca45db5072bMike Lockwood                return MtpConstants.RESPONSE_GENERAL_ERROR;
79555f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
79655f808cff9913a00164120a422af6ca45db5072bMike Lockwood
79755f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (format == MtpConstants.FORMAT_ASSOCIATION) {
79855f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // recursive case - delete all children first
79955f808cff9913a00164120a422af6ca45db5072bMike Lockwood                Uri uri = Files.getMtpObjectsUri(mVolumeName);
80055f808cff9913a00164120a422af6ca45db5072bMike Lockwood                int count = mMediaProvider.delete(uri, "_data LIKE ?",
80155f808cff9913a00164120a422af6ca45db5072bMike Lockwood                        new String[] { path + "/%"});
80255f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
80355f808cff9913a00164120a422af6ca45db5072bMike Lockwood
80455f808cff9913a00164120a422af6ca45db5072bMike Lockwood            Uri uri = Files.getMtpObjectsUri(mVolumeName, handle);
80555f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (mMediaProvider.delete(uri, null, null) > 0) {
8065367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
80759c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            } else {
8085367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
80959c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            }
810d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
811d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in deleteFile", e);
8125367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
81355f808cff9913a00164120a422af6ca45db5072bMike Lockwood        } finally {
81455f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (c != null) {
81555f808cff9913a00164120a422af6ca45db5072bMike Lockwood                c.close();
81655f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
817d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
818d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
819d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
8209a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    private int[] getObjectReferences(int handle) {
8218490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
8229a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        Cursor c = null;
8239a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        try {
8249a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null);
8259a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (c == null) {
8269a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                return null;
8279a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
8289a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            int count = c.getCount();
8299a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (count > 0) {
8309a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                int[] result = new int[count];
8319a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                for (int i = 0; i < count; i++) {
8329a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    c.moveToNext();
8339a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    result[i] = c.getInt(0);
8349a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
8359a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                return result;
8369a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
8379a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } catch (RemoteException e) {
8389a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            Log.e(TAG, "RemoteException in getObjectList", e);
8399a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } finally {
8409a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (c != null) {
8419a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                c.close();
8429a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
8439a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
8449a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        return null;
8459a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
8469a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
8479a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    private int setObjectReferences(int handle, int[] references) {
8482837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
8498490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
8509a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        int count = references.length;
8519a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        ContentValues[] valuesList = new ContentValues[count];
8529a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        for (int i = 0; i < count; i++) {
8539a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            ContentValues values = new ContentValues();
8543b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            values.put(Files.FileColumns._ID, references[i]);
8559a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            valuesList[i] = values;
8569a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
8579a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        try {
8587adfd1896c17d734440962c9f8dbe4aad48bcb49Mike Lockwood            if (mMediaProvider.bulkInsert(uri, valuesList) > 0) {
8595367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
8609a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
8619a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } catch (RemoteException e) {
8629a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            Log.e(TAG, "RemoteException in setObjectReferences", e);
8639a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
8645367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood        return MtpConstants.RESPONSE_GENERAL_ERROR;
8659a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
8669a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
8672837eefc5459427138c080d445bb491c75630163Mike Lockwood    private void sessionStarted() {
8682837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = false;
8692837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
8702837eefc5459427138c080d445bb491c75630163Mike Lockwood
8712837eefc5459427138c080d445bb491c75630163Mike Lockwood    private void sessionEnded() {
8722837eefc5459427138c080d445bb491c75630163Mike Lockwood        if (mDatabaseModified) {
873a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwood            mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END));
8742837eefc5459427138c080d445bb491c75630163Mike Lockwood            mDatabaseModified = false;
8752837eefc5459427138c080d445bb491c75630163Mike Lockwood        }
8762837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
8772837eefc5459427138c080d445bb491c75630163Mike Lockwood
878d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    // used by the JNI code
879d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private int mNativeContext;
880d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
881d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private native final void native_setup();
882d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private native final void native_finalize();
883d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
884