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