MtpDatabase.java revision 8ed67acf38ccdfdb89553ed58620a135f2100e10
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;
23d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.database.Cursor;
2459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodimport android.database.sqlite.SQLiteDatabase;
250cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodimport android.media.MediaScanner;
26d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.net.Uri;
272b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwoodimport android.os.Environment;
28d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException;
29a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwoodimport android.provider.MediaStore;
309a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.Audio;
313b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwoodimport android.provider.MediaStore.Files;
32ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.Images;
33ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.MediaColumns;
34d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log;
35ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.Display;
36ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.WindowManager;
37d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
385ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwoodimport java.io.File;
397d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport java.util.HashMap;
405ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
41d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/**
42d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide}
43d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */
44d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic class MtpDatabase {
45d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
46d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String TAG = "MtpDatabase";
47d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
482837eefc5459427138c080d445bb491c75630163Mike Lockwood    private final Context mContext;
49d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final IContentProvider mMediaProvider;
50d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final String mVolumeName;
51d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final Uri mObjectsUri;
5201788562f26f213f63c14483fd3977e23b8314abMike Lockwood    private final String mMediaStoragePath;
53d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
547d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    // cached property groups for single properties
557d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByProperty
567d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            = new HashMap<Integer, MtpPropertyGroup>();
577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    // cached property groups for all properties for a given format
597d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByFormat
607d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            = new HashMap<Integer, MtpPropertyGroup>();
617d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
622837eefc5459427138c080d445bb491c75630163Mike Lockwood    // true if the database has been modified in the current MTP session
632837eefc5459427138c080d445bb491c75630163Mike Lockwood    private boolean mDatabaseModified;
642837eefc5459427138c080d445bb491c75630163Mike Lockwood
6559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    // database for writable MTP device properties
6659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private SQLiteDatabase mDevicePropDb;
6759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1;
6859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
69b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood    // FIXME - this should be passed in via the constructor
70b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood    private final int mStorageID = 0x00010001;
71b2cada9034436b4ea4bac218da7a1e29460d15b2Mike 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
873b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.DATA, // 1
883b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.FORMAT, // 2
893b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.PARENT, // 3
903b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.SIZE, // 4
913b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.DATE_MODIFIED, // 5
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 + "=?";
98d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
9959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private static final String[] DEVICE_PROPERTY_PROJECTION = new String[] { "_id", "value" };
10059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private  static final String DEVICE_PROPERTY_WHERE = "code=?";
10159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
102d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    private final MediaScanner mMediaScanner;
103d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
104d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    static {
105d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        System.loadLibrary("media_jni");
106d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
107d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
10801788562f26f213f63c14483fd3977e23b8314abMike Lockwood    public MtpDatabase(Context context, String volumeName, String storagePath) {
109d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        native_setup();
110d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1112837eefc5459427138c080d445bb491c75630163Mike Lockwood        mContext = context;
112d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mMediaProvider = context.getContentResolver().acquireProvider("media");
113d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mVolumeName = volumeName;
11401788562f26f213f63c14483fd3977e23b8314abMike Lockwood        mMediaStoragePath = storagePath;
1158490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        mObjectsUri = Files.getMtpObjectsUri(volumeName);
116d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        mMediaScanner = new MediaScanner(context);
11759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        openDevicePropertiesDatabase(context);
118d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
119d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
120d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    @Override
121dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood    protected void finalize() throws Throwable {
122dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        try {
123dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood            native_finalize();
124dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        } finally {
125dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood            super.finalize();
126dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        }
127d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
128d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
12959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private void openDevicePropertiesDatabase(Context context) {
13059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        mDevicePropDb = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
13159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        int version = mDevicePropDb.getVersion();
13259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
13359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        // initialize if necessary
13459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        if (version != DEVICE_PROPERTIES_DATABASE_VERSION) {
13559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            mDevicePropDb.execSQL("CREATE TABLE properties (" +
13659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    "_id INTEGER PRIMARY KEY AUTOINCREMENT," +
13759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    "code INTEGER UNIQUE ON CONFLICT REPLACE," +
13859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    "value TEXT" +
13959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    ");");
14059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            mDevicePropDb.execSQL("CREATE INDEX property_index ON properties (code);");
14159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            mDevicePropDb.setVersion(DEVICE_PROPERTIES_DATABASE_VERSION);
14259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
14359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
14459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
145d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    private int beginSendObject(String path, int format, int parent,
146d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                         int storage, long size, long modified) {
147bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood        // first make sure the object does not exist
148bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood        if (path != null) {
149bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            Cursor c = null;
150bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            try {
151bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE,
152bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                        new String[] { path }, null);
153bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                if (c != null && c.getCount() > 0) {
154bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    Log.w(TAG, "file already exists in beginSendObject: " + path);
155bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    return -1;
156bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                }
157bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            } catch (RemoteException e) {
158bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                Log.e(TAG, "RemoteException in beginSendObject", e);
159bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            } finally {
160bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                if (c != null) {
161bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    c.close();
162bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                }
163bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            }
164bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood        }
165bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood
1662837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
167d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        ContentValues values = new ContentValues();
1683b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.DATA, path);
1693b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.FORMAT, format);
1703b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.PARENT, parent);
171d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        // storage is ignored for now
1723b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.SIZE, size);
1733b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.DATE_MODIFIED, modified);
174d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
175d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        try {
176d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            Uri uri = mMediaProvider.insert(mObjectsUri, values);
177d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            if (uri != null) {
178d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                return Integer.parseInt(uri.getPathSegments().get(2));
179d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            } else {
180d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                return -1;
181d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            }
182d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        } catch (RemoteException e) {
183d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            Log.e(TAG, "RemoteException in beginSendObject", e);
184d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            return -1;
185d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        }
186d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    }
187d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
1887a0bd17bceaf3efc3732e30c538fae420d3b742cMike Lockwood    private void endSendObject(String path, int handle, int format, boolean succeeded) {
189d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        if (succeeded) {
1909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            // handle abstract playlists separately
1919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            // they do not exist in the file system so don't use the media scanner here
1925367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) {
1939a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                // extract name from path
1949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                String name = path;
1959a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                int lastSlash = name.lastIndexOf('/');
1969a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                if (lastSlash >= 0) {
1979a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    name = name.substring(lastSlash + 1);
1989a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
1998cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                // strip trailing ".pla" from the name
2008cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                if (name.endsWith(".pla")) {
2018cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                    name = name.substring(0, name.length() - 4);
2028cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                }
2039a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
2049a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                ContentValues values = new ContentValues(1);
2059a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(Audio.Playlists.DATA, path);
2069a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(Audio.Playlists.NAME, name);
2070b58c19840c577c8d8fd8aa5315676d61b78ba0fMike Lockwood                values.put(Files.FileColumns.FORMAT, format);
2088ed67acf38ccdfdb89553ed58620a135f2100e10Mike Lockwood                values.put(Files.FileColumns.DATE_MODIFIED, System.currentTimeMillis() / 1000);
2099a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle);
2109a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                try {
2119a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values);
2129a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                } catch (RemoteException e) {
2139a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    Log.e(TAG, "RemoteException in endSendObject", e);
2149a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
2159a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            } else {
216c37255d5d0fd9e0ec02b0d7cb5c4b235e200d367Mike Lockwood                mMediaScanner.scanMtpFile(path, mVolumeName, handle, format);
2179a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
218d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        } else {
219d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            deleteFile(handle);
220d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        }
221d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
222d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
223d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private int[] getObjectList(int storageID, int format, int parent) {
224d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        // we can ignore storageID until we support multiple storages
225d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Log.d(TAG, "getObjectList parent: " + parent);
226d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
227d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
228d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (format != 0) {
229d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
230d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            PARENT_FORMAT_WHERE,
231d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            new String[] { Integer.toString(parent), Integer.toString(format) },
232d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                             null);
233d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            } else {
234d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
235d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
236d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
237d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c == null) {
238d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                Log.d(TAG, "null cursor");
239d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return null;
240d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
241d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            int count = c.getCount();
242d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (count > 0) {
243d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int[] result = new int[count];
244d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                for (int i = 0; i < count; i++) {
245d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    c.moveToNext();
246d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    result[i] = c.getInt(0);
247d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                }
248d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                Log.d(TAG, "returning " + result);
249d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return result;
250d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
251d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
252d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in getObjectList", e);
253d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
254d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
255d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
256d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
257d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
258d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return null;
259d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
260d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
2617a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    private int getNumObjects(int storageID, int format, int parent) {
2627a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        // we can ignore storageID until we support multiple storages
2637a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        Log.d(TAG, "getObjectList parent: " + parent);
2647a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        Cursor c = null;
2657a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        try {
2667a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (format != 0) {
2677a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
2687a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                            PARENT_FORMAT_WHERE,
2697a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                            new String[] { Integer.toString(parent), Integer.toString(format) },
2707a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                             null);
2717a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            } else {
2727a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                c = mMediaProvider.query(mObjectsUri, ID_PROJECTION,
2737a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                            PARENT_WHERE, new String[] { Integer.toString(parent) }, null);
2747a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
2757a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (c != null) {
2767a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                return c.getCount();
2777a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
2787a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        } catch (RemoteException e) {
2797a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            Log.e(TAG, "RemoteException in getNumObjects", e);
2807a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        } finally {
2817a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (c != null) {
2827a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                c.close();
2837a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
2847a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        }
2857a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        return -1;
2867a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    }
2877a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood
2884b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedPlaybackFormats() {
2894b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return new int[] {
290e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood            // allow transfering arbitrary files
291e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood            MtpConstants.FORMAT_UNDEFINED,
29212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood
293792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood            MtpConstants.FORMAT_ASSOCIATION,
29412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TEXT,
29512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_HTML,
29612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WAV,
29712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP3,
29812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MPEG,
29912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_EXIF_JPEG,
30012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TIFF_EP,
30112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_GIF,
30212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_JFIF,
30312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_PNG,
30412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TIFF,
30512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WMA,
30612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_OGG,
30712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_AAC,
30812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP4_CONTAINER,
30912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP2,
31012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_3GP_CONTAINER,
311792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood            MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
31212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WPL_PLAYLIST,
31312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_M3U_PLAYLIST,
31412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_PLS_PLAYLIST,
31512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_XML_DOCUMENT,
3164b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        };
3174b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
3184b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
3194b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedCaptureFormats() {
3204b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        // no capture formats yet
3214b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return null;
3224b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
3234b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
324ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] FILE_PROPERTIES = {
325ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
326ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // and IMAGE_PROPERTIES below
3275367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
3285367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
329d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
3305367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
3315367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
332d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
3335367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
334d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
335d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_NAME,
336ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
337ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
338ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
339ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] AUDIO_PROPERTIES = {
340ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
341ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
342ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
343ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
344ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
345ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
346ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
347ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
348ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
349ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
350ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
351ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
352ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
353ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // audio specific properties
354ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ARTIST,
355ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
356ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_ARTIST,
357ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_TRACK,
358ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
359ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DURATION,
360ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_GENRE,
361ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_COMPOSER,
362ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
363ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
364ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] VIDEO_PROPERTIES = {
365ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
366ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
367ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
368ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
369ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
370ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
371ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
372ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
373ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
374ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
375ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
376ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
377ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
378ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // video specific properties
379ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ARTIST,
380ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
381ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DURATION,
382ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
383ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
384ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
385ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] IMAGE_PROPERTIES = {
386ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
387ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
388ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
389ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
390ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
391ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
392ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
393ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
394ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
395ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
396ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
397ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
398ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
399ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // image specific properties
400ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
401ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
402ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
4037d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    static final int[] ALL_PROPERTIES = {
4047d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // NOTE must match FILE_PROPERTIES above
4057d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
4067d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
4077d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
4087d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
4097d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
4107d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
4117d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
4127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
4137d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_NAME,
4147d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
4157d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
4167d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
4177d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // image specific properties
4187d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
4197d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
4207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // audio specific properties
4217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ARTIST,
4227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
4237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_ARTIST,
4247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_TRACK,
4257d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
4267d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DURATION,
4277d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_GENRE,
4287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_COMPOSER,
4297d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
4307d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // video specific properties
4317d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ARTIST,
4327d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
4337d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DURATION,
4347d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
4357d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
4367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // image specific properties
4377d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
4387d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    };
4397d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
440ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    private int[] getSupportedObjectProperties(int format) {
441ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        switch (format) {
442ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_MP3:
443ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WAV:
444ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WMA:
445ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_OGG:
446ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_AAC:
447ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return AUDIO_PROPERTIES;
448ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_MPEG:
449ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_3GP_CONTAINER:
450ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WMV:
451ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return VIDEO_PROPERTIES;
452ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_EXIF_JPEG:
453ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_GIF:
454ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_PNG:
455ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_BMP:
456ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return IMAGE_PROPERTIES;
4577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            case 0:
4587d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                return ALL_PROPERTIES;
459ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            default:
460ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return FILE_PROPERTIES;
461ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
4624b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
4634b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
4644b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedDeviceProperties() {
46559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return new int[] {
46659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
46759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
468ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
46959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        };
4704b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
4714b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
472e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
4737d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private MtpPropertyList getObjectPropertyList(long handle, int format, long property,
474e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        int groupCode, int depth) {
475e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // FIXME - implement group support
476e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (groupCode != 0) {
477e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED);
4785ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
4795ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
4807d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        MtpPropertyGroup propertyGroup;
4817d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        if (property == 0xFFFFFFFFL) {
4827d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             propertyGroup = mPropertyGroupsByFormat.get(format);
4837d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             if (propertyGroup == null) {
4847d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                int[] propertyList = getSupportedObjectProperties(format);
4857d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList);
4867d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                mPropertyGroupsByFormat.put(new Integer(format), propertyGroup);
487e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
4887d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        } else {
4897d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood              propertyGroup = mPropertyGroupsByProperty.get(property);
4907d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             if (propertyGroup == null) {
4917d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                int[] propertyList = new int[] { (int)property };
4927d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mVolumeName, propertyList);
4937d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup);
494e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
495e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
4967d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
4977d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        return propertyGroup.getPropertyList((int)handle, format, depth, mStorageID);
498e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
499e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
500e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    private int renameFile(int handle, String newName) {
501e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        Cursor c = null;
502e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
503e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // first compute current path
504e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String path = null;
505e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String[] whereArgs = new String[] {  Integer.toString(handle) };
506e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
507e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, whereArgs, null);
508e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null && c.moveToNext()) {
5091c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood                path = c.getString(1);
510e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
511e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
512e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "RemoteException in getObjectFilePath", e);
513e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
514e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } finally {
515e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null) {
516e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                c.close();
517b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood            }
518b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood        }
519e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (path == null) {
520e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
521e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
522e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
523e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // now rename the file.  make sure this succeeds before updating database
524e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        File oldFile = new File(path);
525e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int lastSlash = path.lastIndexOf('/');
526e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (lastSlash <= 1) {
527e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
528e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
529e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String newPath = path.substring(0, lastSlash + 1) + newName;
530e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        File newFile = new File(newPath);
531e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        boolean success = oldFile.renameTo(newFile);
532e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        Log.d(TAG, "renaming "+ path + " to " + newPath + (success ? " succeeded" : " failed"));
533e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (!success) {
534e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
535e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
536e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
537e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // finally update database
538e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        ContentValues values = new ContentValues();
539e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        values.put(Files.FileColumns.DATA, newPath);
540e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int updated = 0;
541e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
542e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // note - we are relying on a special case in MediaProvider.update() to update
543e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // the paths for all children in the case where this is a directory.
544e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            updated = mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs);
545e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
546e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "RemoteException in mMediaProvider.update", e);
547e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
548e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (updated == 0) {
549e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "Unable to update path for " + path + " to " + newPath);
550e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // this shouldn't happen, but if it does we need to rename the file to its original name
551e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            newFile.renameTo(oldFile);
552e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
553e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
554e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
555e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return MtpConstants.RESPONSE_OK;
556d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
557d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
55859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int setObjectProperty(int handle, int property,
55959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                            long intValue, String stringValue) {
56059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        Log.d(TAG, "setObjectProperty: " + property);
5615ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
5625ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        switch (property) {
5635ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
5645ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood                return renameFile(handle, stringValue);
5655ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
5665ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            default:
5675ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood                return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
5685ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
56959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
57059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
57159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
57259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        Log.d(TAG, "getDeviceProperty: " + property);
57359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
57459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        switch (property) {
57559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
57659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
57759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                // writable string properties kept in our device property database
57859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                Cursor c = null;
57959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                try {
58059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    c = mDevicePropDb.query("properties", DEVICE_PROPERTY_PROJECTION,
58159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        DEVICE_PROPERTY_WHERE, new String[] {  Integer.toString(property) },
58259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        null, null, null);
58359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
58459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    if (c != null && c.moveToNext()) {
58559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        String value = c.getString(1);
58659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        int length = value.length();
58759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        if (length > 255) {
58859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                            length = 255;
58959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        }
59059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        value.getChars(0, length, outStringValue, 0);
59159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        outStringValue[length] = 0;
59259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    } else {
59359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        outStringValue[0] = 0;
59459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    }
59559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    return MtpConstants.RESPONSE_OK;
59659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                } finally {
59759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    if (c != null) {
59859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                        c.close();
59959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    }
60059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                }
60159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
602ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
603ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                // use screen size as max image size
604ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                Display display = ((WindowManager)mContext.getSystemService(
605ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                        Context.WINDOW_SERVICE)).getDefaultDisplay();
606ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                int width = display.getWidth();
607ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                int height = display.getHeight();
608ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                String imageSize = Integer.toString(width) + "x" +  Integer.toString(height);
609ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
610ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                outStringValue[imageSize.length()] = 0;
611ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                return MtpConstants.RESPONSE_OK;
612ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood
613ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            default:
614ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
615ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood        }
61659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
61759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
61859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int setDeviceProperty(int property, long intValue, String stringValue) {
61959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        Log.d(TAG, "setDeviceProperty: " + property + " : " + stringValue);
62059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
62159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        switch (property) {
62259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
62359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
62459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                // writable string properties kept in our device property database
62559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                try {
62659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    ContentValues values = new ContentValues();
62759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    values.put("code", property);
62859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    values.put("value", stringValue);
62959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    mDevicePropDb.insert("properties", "code", values);
63059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    return MtpConstants.RESPONSE_OK;
63159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                } catch (Exception e) {
63259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                    return MtpConstants.RESPONSE_GENERAL_ERROR;
63359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                }
63459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
63559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
63659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
63759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
63859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
639d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
640d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                        char[] outName, long[] outSizeModified) {
641d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Log.d(TAG, "getObjectInfo: " + handle);
642d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
643d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
644d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION,
645d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
646d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null && c.moveToNext()) {
647b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood                outStorageFormatParent[0] = mStorageID;
648d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outStorageFormatParent[1] = c.getInt(2);
649d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outStorageFormatParent[2] = c.getInt(3);
650d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
651d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                // extract name from path
652d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                String path = c.getString(1);
653d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int lastSlash = path.lastIndexOf('/');
654d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int start = (lastSlash >= 0 ? lastSlash + 1 : 0);
655d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int end = path.length();
656d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                if (end - start > 255) {
657d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    end = start + 255;
658d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                }
659d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                path.getChars(start, end, outName, 0);
660d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outName[end - start] = 0;
661d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
662d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outSizeModified[0] = c.getLong(4);
663d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outSizeModified[1] = c.getLong(5);
664d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return true;
665d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
666d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
6672b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood            Log.e(TAG, "RemoteException in getObjectInfo", e);
668d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
669d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
670d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
671d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
672d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
673d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return false;
674d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
675d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
676365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood    private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) {
677d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Log.d(TAG, "getObjectFilePath: " + handle);
67801788562f26f213f63c14483fd3977e23b8314abMike Lockwood        if (handle == 0) {
67901788562f26f213f63c14483fd3977e23b8314abMike Lockwood            // special case root directory
68001788562f26f213f63c14483fd3977e23b8314abMike Lockwood            mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0);
68101788562f26f213f63c14483fd3977e23b8314abMike Lockwood            outFilePath[mMediaStoragePath.length()] = 0;
682365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            outFileLengthFormat[0] = 0;
683365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            outFileLengthFormat[1] = MtpConstants.FORMAT_ASSOCIATION;
68401788562f26f213f63c14483fd3977e23b8314abMike Lockwood            return MtpConstants.RESPONSE_OK;
68501788562f26f213f63c14483fd3977e23b8314abMike Lockwood        }
686d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
687d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
688365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
689d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
690d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null && c.moveToNext()) {
6911c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood                String path = c.getString(1);
692d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                path.getChars(0, path.length(), outFilePath, 0);
693d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outFilePath[path.length()] = 0;
694365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                outFileLengthFormat[0] = c.getLong(2);
695365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                outFileLengthFormat[1] = c.getLong(3);
6965367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
69759c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            } else {
6985367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
699d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
700d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
701d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in getObjectFilePath", e);
7025367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
703d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
704d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
705d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
706d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
707d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
708d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
709d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
71059c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    private int deleteFile(int handle) {
711d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Log.d(TAG, "deleteFile: " + handle);
7122837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
71355f808cff9913a00164120a422af6ca45db5072bMike Lockwood        String path = null;
71455f808cff9913a00164120a422af6ca45db5072bMike Lockwood        int format = 0;
71555f808cff9913a00164120a422af6ca45db5072bMike Lockwood
71655f808cff9913a00164120a422af6ca45db5072bMike Lockwood        Cursor c = null;
717d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
71855f808cff9913a00164120a422af6ca45db5072bMike Lockwood            c = mMediaProvider.query(mObjectsUri, PATH_SIZE_FORMAT_PROJECTION,
71955f808cff9913a00164120a422af6ca45db5072bMike Lockwood                            ID_WHERE, new String[] {  Integer.toString(handle) }, null);
72055f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (c != null && c.moveToNext()) {
72155f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // don't convert to media path here, since we will be matching
72255f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // against paths in the database matching /data/media
72355f808cff9913a00164120a422af6ca45db5072bMike Lockwood                path = c.getString(1);
72455f808cff9913a00164120a422af6ca45db5072bMike Lockwood                format = c.getInt(3);
72555f808cff9913a00164120a422af6ca45db5072bMike Lockwood            } else {
72655f808cff9913a00164120a422af6ca45db5072bMike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
72755f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
72855f808cff9913a00164120a422af6ca45db5072bMike Lockwood
72955f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (path == null || format == 0) {
73055f808cff9913a00164120a422af6ca45db5072bMike Lockwood                return MtpConstants.RESPONSE_GENERAL_ERROR;
73155f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
73255f808cff9913a00164120a422af6ca45db5072bMike Lockwood
73355f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (format == MtpConstants.FORMAT_ASSOCIATION) {
73455f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // recursive case - delete all children first
73555f808cff9913a00164120a422af6ca45db5072bMike Lockwood                Uri uri = Files.getMtpObjectsUri(mVolumeName);
73655f808cff9913a00164120a422af6ca45db5072bMike Lockwood                int count = mMediaProvider.delete(uri, "_data LIKE ?",
73755f808cff9913a00164120a422af6ca45db5072bMike Lockwood                        new String[] { path + "/%"});
73855f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
73955f808cff9913a00164120a422af6ca45db5072bMike Lockwood
74055f808cff9913a00164120a422af6ca45db5072bMike Lockwood            Uri uri = Files.getMtpObjectsUri(mVolumeName, handle);
74155f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (mMediaProvider.delete(uri, null, null) > 0) {
7425367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
74359c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            } else {
7445367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
74559c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            }
746d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
747d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in deleteFile", e);
7485367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
74955f808cff9913a00164120a422af6ca45db5072bMike Lockwood        } finally {
75055f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (c != null) {
75155f808cff9913a00164120a422af6ca45db5072bMike Lockwood                c.close();
75255f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
753d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
754d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
755d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
7569a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    private int[] getObjectReferences(int handle) {
7579a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        Log.d(TAG, "getObjectReferences for: " + handle);
7588490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
7599a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        Cursor c = null;
7609a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        try {
7619a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null);
7629a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (c == null) {
7639a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                return null;
7649a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
7659a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            int count = c.getCount();
7669a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (count > 0) {
7679a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                int[] result = new int[count];
7689a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                for (int i = 0; i < count; i++) {
7699a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    c.moveToNext();
7709a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    result[i] = c.getInt(0);
7719a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
7729a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                return result;
7739a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
7749a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } catch (RemoteException e) {
7759a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            Log.e(TAG, "RemoteException in getObjectList", e);
7769a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } finally {
7779a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (c != null) {
7789a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                c.close();
7799a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
7809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
7819a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        return null;
7829a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
7839a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
7849a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    private int setObjectReferences(int handle, int[] references) {
7852837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
7868490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
7879a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        int count = references.length;
7889a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        ContentValues[] valuesList = new ContentValues[count];
7899a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        for (int i = 0; i < count; i++) {
7909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            ContentValues values = new ContentValues();
7913b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            values.put(Files.FileColumns._ID, references[i]);
7929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            valuesList[i] = values;
7939a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
7949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        try {
7957adfd1896c17d734440962c9f8dbe4aad48bcb49Mike Lockwood            if (mMediaProvider.bulkInsert(uri, valuesList) > 0) {
7965367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
7979a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
7989a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } catch (RemoteException e) {
7999a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            Log.e(TAG, "RemoteException in setObjectReferences", e);
8009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
8015367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood        return MtpConstants.RESPONSE_GENERAL_ERROR;
8029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
8039a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
8042837eefc5459427138c080d445bb491c75630163Mike Lockwood    private void sessionStarted() {
8052837eefc5459427138c080d445bb491c75630163Mike Lockwood        Log.d(TAG, "sessionStarted");
8062837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = false;
8072837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
8082837eefc5459427138c080d445bb491c75630163Mike Lockwood
8092837eefc5459427138c080d445bb491c75630163Mike Lockwood    private void sessionEnded() {
8102837eefc5459427138c080d445bb491c75630163Mike Lockwood        Log.d(TAG, "sessionEnded");
8112837eefc5459427138c080d445bb491c75630163Mike Lockwood        if (mDatabaseModified) {
8122837eefc5459427138c080d445bb491c75630163Mike Lockwood            Log.d(TAG, "sending ACTION_MTP_SESSION_END");
813a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwood            mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END));
8142837eefc5459427138c080d445bb491c75630163Mike Lockwood            mDatabaseModified = false;
8152837eefc5459427138c080d445bb491c75630163Mike Lockwood        }
8162837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
8172837eefc5459427138c080d445bb491c75630163Mike Lockwood
818d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    // used by the JNI code
819d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private int mNativeContext;
820d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
821d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private native final void native_setup();
822d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private native final void native_finalize();
823d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
824