MtpDatabase.java revision e2e59326f13cf291bf5b37989390fd2a55a94f0c
1d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/*
2d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Copyright (C) 2010 The Android Open Source Project
3d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
4d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
5d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * you may not use this file except in compliance with the License.
6d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * You may obtain a copy of the License at
7d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
8d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
9d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
10d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Unless required by applicable law or agreed to in writing, software
11d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
12d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * See the License for the specific language governing permissions and
14d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * limitations under the License.
15d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */
16d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
170cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodpackage android.mtp;
18d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
19d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.Context;
20d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodimport android.content.ContentValues;
21d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.IContentProvider;
222837eefc5459427138c080d445bb491c75630163Mike Lockwoodimport android.content.Intent;
23775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwoodimport android.content.SharedPreferences;
24d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.database.Cursor;
2559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodimport android.database.sqlite.SQLiteDatabase;
260cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodimport android.media.MediaScanner;
27d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.net.Uri;
282b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwoodimport android.os.Environment;
29d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException;
30a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwoodimport android.provider.MediaStore;
319a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.Audio;
323b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwoodimport android.provider.MediaStore.Files;
33ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.Images;
34ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.MediaColumns;
35d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log;
36ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.Display;
37ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.WindowManager;
38d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
395ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwoodimport java.io.File;
407d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport java.util.HashMap;
41fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.chaimport java.util.Locale;
425ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
43d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/**
44d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide}
45d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */
46d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic class MtpDatabase {
47d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
48d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String TAG = "MtpDatabase";
49d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
502837eefc5459427138c080d445bb491c75630163Mike Lockwood    private final Context mContext;
5135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn    private final String mPackageName;
52d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final IContentProvider mMediaProvider;
53d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final String mVolumeName;
54d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private final Uri mObjectsUri;
5573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    // path to primary storage
5673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    private final String mMediaStoragePath;
5773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    // if not null, restrict all queries to these subdirectories
5873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    private final String[] mSubDirectories;
5973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    // where clause for restricting queries to files in mSubDirectories
6073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    private String mSubDirectoriesWhere;
6173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    // where arguments for restricting queries to files in mSubDirectories
6273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    private String[] mSubDirectoriesWhereArgs;
6373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
64b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>();
65d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
667d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    // cached property groups for single properties
677d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByProperty
687d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            = new HashMap<Integer, MtpPropertyGroup>();
697d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
707d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    // cached property groups for all properties for a given format
717d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByFormat
727d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            = new HashMap<Integer, MtpPropertyGroup>();
737d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
742837eefc5459427138c080d445bb491c75630163Mike Lockwood    // true if the database has been modified in the current MTP session
752837eefc5459427138c080d445bb491c75630163Mike Lockwood    private boolean mDatabaseModified;
762837eefc5459427138c080d445bb491c75630163Mike Lockwood
77775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood    // SharedPreferences for writable MTP device properties
78775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood    private SharedPreferences mDeviceProperties;
7959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1;
8059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
81d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String[] ID_PROJECTION = new String[] {
823b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
83d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
846a6a3aff17e057eeb1457ac4d04ab4b5e8f53abeMike Lockwood    private static final String[] PATH_PROJECTION = new String[] {
855ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            Files.FileColumns._ID, // 0
865ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            Files.FileColumns.DATA, // 1
875ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood    };
88f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    private static final String[] PATH_FORMAT_PROJECTION = new String[] {
893b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
903b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.DATA, // 1
91f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood            Files.FileColumns.FORMAT, // 2
92d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
93d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private static final String[] OBJECT_INFO_PROJECTION = new String[] {
943b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns._ID, // 0
95b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            Files.FileColumns.STORAGE_ID, // 1
963b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.FORMAT, // 2
973b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            Files.FileColumns.PARENT, // 3
98b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            Files.FileColumns.DATA, // 4
991341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood            Files.FileColumns.DATE_ADDED, // 5
1001341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood            Files.FileColumns.DATE_MODIFIED, // 6
101d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    };
1023b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood    private static final String ID_WHERE = Files.FileColumns._ID + "=?";
103bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood    private static final String PATH_WHERE = Files.FileColumns.DATA + "=?";
1046acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood
1056acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String STORAGE_WHERE = Files.FileColumns.STORAGE_ID + "=?";
10658e6831ccb54b33a914115e88ebb67e720615fb8Mike Lockwood    private static final String FORMAT_WHERE = Files.FileColumns.FORMAT + "=?";
10758e6831ccb54b33a914115e88ebb67e720615fb8Mike Lockwood    private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?";
1086acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String STORAGE_FORMAT_WHERE = STORAGE_WHERE + " AND "
109b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                                            + Files.FileColumns.FORMAT + "=?";
1106acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String STORAGE_PARENT_WHERE = STORAGE_WHERE + " AND "
1116acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                                            + Files.FileColumns.PARENT + "=?";
1126acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String FORMAT_PARENT_WHERE = FORMAT_WHERE + " AND "
1136acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                                            + Files.FileColumns.PARENT + "=?";
1146acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood    private static final String STORAGE_FORMAT_PARENT_WHERE = STORAGE_FORMAT_WHERE + " AND "
1156acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                                            + Files.FileColumns.PARENT + "=?";
116d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
117d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    private final MediaScanner mMediaScanner;
118d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
119d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    static {
120d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        System.loadLibrary("media_jni");
121d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
122d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
12373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    public MtpDatabase(Context context, String volumeName, String storagePath,
12473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            String[] subDirectories) {
125d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        native_setup();
126d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1272837eefc5459427138c080d445bb491c75630163Mike Lockwood        mContext = context;
12835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        mPackageName = context.getPackageName();
129d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mMediaProvider = context.getContentResolver().acquireProvider("media");
130d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mVolumeName = volumeName;
13101788562f26f213f63c14483fd3977e23b8314abMike Lockwood        mMediaStoragePath = storagePath;
1328490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        mObjectsUri = Files.getMtpObjectsUri(volumeName);
133d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        mMediaScanner = new MediaScanner(context);
134fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha
13573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        mSubDirectories = subDirectories;
13673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        if (subDirectories != null) {
13773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            // Compute "where" string for restricting queries to subdirectories
13873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            StringBuilder builder = new StringBuilder();
13973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            builder.append("(");
14073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            int count = subDirectories.length;
14173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            for (int i = 0; i < count; i++) {
14273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                builder.append(Files.FileColumns.DATA + "=? OR "
14373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        + Files.FileColumns.DATA + " LIKE ?");
14473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                if (i != count - 1) {
14573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    builder.append(" OR ");
14673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                }
14773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            }
14873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            builder.append(")");
14973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            mSubDirectoriesWhere = builder.toString();
15073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
15173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            // Compute "where" arguments for restricting queries to subdirectories
15273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            mSubDirectoriesWhereArgs = new String[count * 2];
15373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            for (int i = 0, j = 0; i < count; i++) {
15473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                String path = subDirectories[i];
15573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                mSubDirectoriesWhereArgs[j++] = path;
15673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                mSubDirectoriesWhereArgs[j++] = path + "/%";
15773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            }
15873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        }
15973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
160fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha        // Set locale to MediaScanner.
161fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha        Locale locale = context.getResources().getConfiguration().locale;
162fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha        if (locale != null) {
163fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha            String language = locale.getLanguage();
164fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha            String country = locale.getCountry();
165fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha            if (language != null) {
166fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                if (country != null) {
167fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                    mMediaScanner.setLocale(language + "_" + country);
168fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                } else {
169fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                    mMediaScanner.setLocale(language);
170fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha                }
171fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha            }
172fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha        }
173775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        initDeviceProperties(context);
174d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
175d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
176d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    @Override
177dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood    protected void finalize() throws Throwable {
178dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        try {
179dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood            native_finalize();
180dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        } finally {
181dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood            super.finalize();
182dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood        }
183d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
184d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
185b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    public void addStorage(MtpStorage storage) {
186b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        mStorageMap.put(storage.getPath(), storage);
187b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    }
188b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood
189b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    public void removeStorage(MtpStorage storage) {
190b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        mStorageMap.remove(storage.getPath());
191b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    }
192b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood
193775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood    private void initDeviceProperties(Context context) {
194775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        final String devicePropertiesName = "device-properties";
195775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        mDeviceProperties = context.getSharedPreferences(devicePropertiesName, Context.MODE_PRIVATE);
196775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        File databaseFile = context.getDatabasePath(devicePropertiesName);
197775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood
198775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood        if (databaseFile.exists()) {
199775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            // for backward compatibility - read device properties from sqlite database
200775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            // and migrate them to shared prefs
201775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            SQLiteDatabase db = null;
202775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            Cursor c = null;
203775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            try {
204775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                db = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null);
205775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                if (db != null) {
206775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                    c = db.query("properties", new String[] { "_id", "code", "value" },
207775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                            null, null, null, null, null);
208775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                    if (c != null) {
209775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        SharedPreferences.Editor e = mDeviceProperties.edit();
210775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        while (c.moveToNext()) {
211775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                            String name = c.getString(1);
212775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                            String value = c.getString(2);
213775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                            e.putString(name, value);
214775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        }
215775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        e.commit();
216775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                    }
217775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                }
218775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            } catch (Exception e) {
219775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                Log.e(TAG, "failed to migrate device properties", e);
220775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            } finally {
221775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                if (c != null) c.close();
222775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                if (db != null) db.close();
223775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood            }
2243ed02535fdc3c752346c40b57962905b7072e693jangwon.lee            context.deleteDatabase(devicePropertiesName);
22559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
22659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
22759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
22873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    // check to see if the path is contained in one of our storage subdirectories
22973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    // returns true if we have no special subdirectories
23073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    private boolean inStorageSubDirectory(String path) {
23173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        if (mSubDirectories == null) return true;
23273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        if (path == null) return false;
23373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
23473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        boolean allowed = false;
23573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        int pathLength = path.length();
23673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        for (int i = 0; i < mSubDirectories.length && !allowed; i++) {
23773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            String subdir = mSubDirectories[i];
23873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            int subdirLength = subdir.length();
23973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            if (subdirLength < pathLength &&
24073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    path.charAt(subdirLength) == '/' &&
24173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    path.startsWith(subdir)) {
24273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                allowed = true;
24373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            }
24473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        }
24573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        return allowed;
24673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    }
24773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
24873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    // check to see if the path matches one of our storage subdirectories
24973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    // returns true if we have no special subdirectories
25073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    private boolean isStorageSubDirectory(String path) {
25173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    if (mSubDirectories == null) return false;
25273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        for (int i = 0; i < mSubDirectories.length; i++) {
25373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            if (path.equals(mSubDirectories[i])) {
25473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                return true;
25573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            }
25673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        }
25773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        return false;
25873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood    }
25973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
260d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    private int beginSendObject(String path, int format, int parent,
261b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                         int storageId, long size, long modified) {
26273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        // if mSubDirectories is not null, do not allow copying files to any other locations
26373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        if (!inStorageSubDirectory(path)) return -1;
26473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
26573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        // make sure the object does not exist
266bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood        if (path != null) {
267bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            Cursor c = null;
268bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            try {
26935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                c = mMediaProvider.query(mPackageName, mObjectsUri, ID_PROJECTION, PATH_WHERE,
27075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown                        new String[] { path }, null, null);
271bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                if (c != null && c.getCount() > 0) {
272bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    Log.w(TAG, "file already exists in beginSendObject: " + path);
273bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    return -1;
274bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                }
275bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            } catch (RemoteException e) {
276bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                Log.e(TAG, "RemoteException in beginSendObject", e);
277bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            } finally {
278bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                if (c != null) {
279bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                    c.close();
280bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood                }
281bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood            }
282bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood        }
283bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood
2842837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
285d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        ContentValues values = new ContentValues();
2863b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.DATA, path);
2873b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.FORMAT, format);
2883b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.PARENT, parent);
289b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        values.put(Files.FileColumns.STORAGE_ID, storageId);
2903b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.SIZE, size);
2913b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood        values.put(Files.FileColumns.DATE_MODIFIED, modified);
292d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
293d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        try {
29435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            Uri uri = mMediaProvider.insert(mPackageName, mObjectsUri, values);
295d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            if (uri != null) {
296d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                return Integer.parseInt(uri.getPathSegments().get(2));
297d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            } else {
298d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                return -1;
299d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            }
300d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        } catch (RemoteException e) {
301d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            Log.e(TAG, "RemoteException in beginSendObject", e);
302d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            return -1;
303d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        }
304d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    }
305d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
3067a0bd17bceaf3efc3732e30c538fae420d3b742cMike Lockwood    private void endSendObject(String path, int handle, int format, boolean succeeded) {
307d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        if (succeeded) {
3089a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            // handle abstract playlists separately
3099a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            // they do not exist in the file system so don't use the media scanner here
3105367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) {
3119a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                // extract name from path
3129a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                String name = path;
3139a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                int lastSlash = name.lastIndexOf('/');
3149a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                if (lastSlash >= 0) {
3159a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    name = name.substring(lastSlash + 1);
3169a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
3178cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                // strip trailing ".pla" from the name
3188cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                if (name.endsWith(".pla")) {
3198cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                    name = name.substring(0, name.length() - 4);
3208cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood                }
3219a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
3229a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                ContentValues values = new ContentValues(1);
3239a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(Audio.Playlists.DATA, path);
3249a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(Audio.Playlists.NAME, name);
3250b58c19840c577c8d8fd8aa5315676d61b78ba0fMike Lockwood                values.put(Files.FileColumns.FORMAT, format);
3268ed67acf38ccdfdb89553ed58620a135f2100e10Mike Lockwood                values.put(Files.FileColumns.DATE_MODIFIED, System.currentTimeMillis() / 1000);
3279a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle);
3289a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                try {
32935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    Uri uri = mMediaProvider.insert(mPackageName,
33035654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                            Audio.Playlists.EXTERNAL_CONTENT_URI, values);
3319a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                } catch (RemoteException e) {
3329a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    Log.e(TAG, "RemoteException in endSendObject", e);
3339a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
3349a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            } else {
335c37255d5d0fd9e0ec02b0d7cb5c4b235e200d367Mike Lockwood                mMediaScanner.scanMtpFile(path, mVolumeName, handle, format);
3369a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
337d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        } else {
338d815f79766984fce499e147ecbacc01914683f74Mike Lockwood            deleteFile(handle);
339d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        }
340d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
341d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
342b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException {
34373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        String where;
34473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        String[] whereArgs;
34573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
3466acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood        if (storageID == 0xFFFFFFFF) {
3476acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood            // query all stores
3486acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood            if (format == 0) {
3496acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                // query all formats
3506acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0) {
3516acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // query all objects
35273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    where = null;
35373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    whereArgs = null;
35473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                } else {
35573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    if (parent == 0xFFFFFFFF) {
35673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        // all objects in root of store
35773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        parent = 0;
35873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    }
35973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    where = PARENT_WHERE;
36073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    whereArgs = new String[] { Integer.toString(parent) };
3616acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
362b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            } else {
3636acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                // query specific format
3646acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0) {
3656acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // query all objects
36673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    where = FORMAT_WHERE;
36773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    whereArgs = new String[] { Integer.toString(format) };
36873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                } else {
36973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    if (parent == 0xFFFFFFFF) {
37073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        // all objects in root of store
37173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        parent = 0;
37273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    }
37373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    where = FORMAT_PARENT_WHERE;
37473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    whereArgs = new String[] { Integer.toString(format),
37573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                                               Integer.toString(parent) };
3766acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
377b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            }
378b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        } else {
3796acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood            // query specific store
3806acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood            if (format == 0) {
3816acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                // query all formats
3826acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0) {
3836acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // query all objects
38473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    where = STORAGE_WHERE;
38573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    whereArgs = new String[] { Integer.toString(storageID) };
38673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                } else {
38773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    if (parent == 0xFFFFFFFF) {
38873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        // all objects in root of store
38973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        parent = 0;
39073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    }
39173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    where = STORAGE_PARENT_WHERE;
39273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    whereArgs = new String[] { Integer.toString(storageID),
39373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                                               Integer.toString(parent) };
3946acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
395d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            } else {
3966acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                // query specific format
3976acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                if (parent == 0) {
3986acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                    // query all objects
39973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    where = STORAGE_FORMAT_WHERE;
40073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    whereArgs = new String[] {  Integer.toString(storageID),
40173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                                                Integer.toString(format) };
40273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                } else {
40373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    if (parent == 0xFFFFFFFF) {
40473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        // all objects in root of store
40573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        parent = 0;
40673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    }
40773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    where = STORAGE_FORMAT_PARENT_WHERE;
40873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    whereArgs = new String[] { Integer.toString(storageID),
40973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                                               Integer.toString(format),
41073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                                               Integer.toString(parent) };
4116acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
41273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            }
41373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        }
41473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
41573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        // if we are restricting queries to mSubDirectories, we need to add the restriction
41673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        // onto our "where" arguments
41773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        if (mSubDirectoriesWhere != null) {
41873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            if (where == null) {
41973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                where = mSubDirectoriesWhere;
42073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                whereArgs = mSubDirectoriesWhereArgs;
42173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            } else {
42273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                where = where + " AND " + mSubDirectoriesWhere;
42373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
42473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                // create new array to hold whereArgs and mSubDirectoriesWhereArgs
42573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                String[] newWhereArgs =
42673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                        new String[whereArgs.length + mSubDirectoriesWhereArgs.length];
42773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                int i, j;
42873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                for (i = 0; i < whereArgs.length; i++) {
42973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    newWhereArgs[i] = whereArgs[i];
4306acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood                }
43173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                for (j = 0; j < mSubDirectoriesWhereArgs.length; i++, j++) {
43273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                    newWhereArgs[i] = mSubDirectoriesWhereArgs[j];
43373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                }
43473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                whereArgs = newWhereArgs;
435d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
436b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        }
43773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
43835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn        return mMediaProvider.query(mPackageName, mObjectsUri, ID_PROJECTION, where,
43935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                whereArgs, null, null);
440b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    }
441b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood
442b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood    private int[] getObjectList(int storageID, int format, int parent) {
443b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        Cursor c = null;
444b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        try {
445b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            c = createObjectQuery(storageID, format, parent);
446d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c == null) {
447d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return null;
448d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
449d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            int count = c.getCount();
450d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (count > 0) {
451d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int[] result = new int[count];
452d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                for (int i = 0; i < count; i++) {
453d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    c.moveToNext();
454d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    result[i] = c.getInt(0);
455d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                }
456d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return result;
457d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
458d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
459d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in getObjectList", e);
460d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
461d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
462d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
463d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
464d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
465d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return null;
466d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
467d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
4687a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    private int getNumObjects(int storageID, int format, int parent) {
4697a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        Cursor c = null;
4707a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        try {
471b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood            c = createObjectQuery(storageID, format, parent);
4727a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (c != null) {
4737a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                return c.getCount();
4747a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
4757a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        } catch (RemoteException e) {
4767a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            Log.e(TAG, "RemoteException in getNumObjects", e);
4777a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        } finally {
4787a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            if (c != null) {
4797a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                c.close();
4807a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood            }
4817a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        }
4827a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        return -1;
4837a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    }
4847a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood
4854b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedPlaybackFormats() {
4864b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return new int[] {
487e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood            // allow transfering arbitrary files
488e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood            MtpConstants.FORMAT_UNDEFINED,
48912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood
490792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood            MtpConstants.FORMAT_ASSOCIATION,
49112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TEXT,
49212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_HTML,
49312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WAV,
49412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP3,
49512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MPEG,
49612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_EXIF_JPEG,
49712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TIFF_EP,
498240582eabee56d55751b85e220811d48fabe839abo huang            MtpConstants.FORMAT_BMP,
49912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_GIF,
50012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_JFIF,
50112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_PNG,
50212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_TIFF,
50312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WMA,
50412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_OGG,
50512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_AAC,
50612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP4_CONTAINER,
50712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_MP2,
50812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_3GP_CONTAINER,
509792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood            MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST,
51012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_WPL_PLAYLIST,
51112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_M3U_PLAYLIST,
51212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_PLS_PLAYLIST,
51312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood            MtpConstants.FORMAT_XML_DOCUMENT,
514f9f223edb408cdc9fd946dc099a86857079a639fGlenn Kasten            MtpConstants.FORMAT_FLAC,
5154b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        };
5164b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
5174b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
5184b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedCaptureFormats() {
5194b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        // no capture formats yet
5204b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return null;
5214b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
5224b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
523ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] FILE_PROPERTIES = {
524ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES
525ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // and IMAGE_PROPERTIES below
5265367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
5275367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
528d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
5295367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
5305367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
531d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
5325367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
533d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
534d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood            MtpConstants.PROPERTY_NAME,
535ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
536ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
537ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
538ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] AUDIO_PROPERTIES = {
539ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
540ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
541ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
542ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
543ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
544ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
545ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
546ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
547ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
548ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
549ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
550ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
551ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
552ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // audio specific properties
553ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ARTIST,
554ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
555ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_ARTIST,
556ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_TRACK,
557ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
558ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DURATION,
559ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_GENRE,
560ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_COMPOSER,
561ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
562ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
563ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] VIDEO_PROPERTIES = {
564ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
565ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
566ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
567ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
568ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
569ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
570ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
571ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
572ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
573ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
574ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
575ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
576ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
577ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // video specific properties
578ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ARTIST,
579ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
580ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DURATION,
581ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
582ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
583ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
584ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    static final int[] IMAGE_PROPERTIES = {
585ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // NOTE must match FILE_PROPERTIES above
586ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
587ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
588ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
589ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
590ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
591ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
592ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
593ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
594ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_NAME,
595ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
596ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
597ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
598ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            // image specific properties
599ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
600ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    };
601ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood
6027d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    static final int[] ALL_PROPERTIES = {
6037d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // NOTE must match FILE_PROPERTIES above
6047d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_STORAGE_ID,
6057d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FORMAT,
6067d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PROTECTION_STATUS,
6077d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_SIZE,
6087d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_OBJECT_FILE_NAME,
6097d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DATE_MODIFIED,
6107d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PARENT_OBJECT,
6117d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_PERSISTENT_UID,
6127d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_NAME,
6137d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DISPLAY_NAME,
6147d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DATE_ADDED,
6157d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
6167d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // image specific properties
6177d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
6187d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
6197d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // audio specific properties
6207d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ARTIST,
6217d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
6227d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_ARTIST,
6237d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_TRACK,
6247d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE,
6257d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DURATION,
6267d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_GENRE,
6277d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_COMPOSER,
6287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
6297d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // video specific properties
6307d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ARTIST,
6317d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_ALBUM_NAME,
6327d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DURATION,
6337d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
6347d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
6357d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            // image specific properties
6367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            MtpConstants.PROPERTY_DESCRIPTION,
6377d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    };
6387d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
639ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    private int[] getSupportedObjectProperties(int format) {
640ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        switch (format) {
641ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_MP3:
642ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WAV:
643ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WMA:
644ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_OGG:
645ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_AAC:
646ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return AUDIO_PROPERTIES;
647ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_MPEG:
648ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_3GP_CONTAINER:
649ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_WMV:
650ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return VIDEO_PROPERTIES;
651ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_EXIF_JPEG:
652ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_GIF:
653ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_PNG:
654ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            case MtpConstants.FORMAT_BMP:
655ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return IMAGE_PROPERTIES;
6567d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood            case 0:
6577d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                return ALL_PROPERTIES;
658ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood            default:
659ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood                return FILE_PROPERTIES;
660ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        }
6614b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
6624b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
6634b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    private int[] getSupportedDeviceProperties() {
66459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return new int[] {
66559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,
66659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,
667ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE,
66859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        };
6694b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
6704b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
671e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
6727d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    private MtpPropertyList getObjectPropertyList(long handle, int format, long property,
673e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        int groupCode, int depth) {
674e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // FIXME - implement group support
675e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (groupCode != 0) {
676e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED);
6775ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
6785ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
6797d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        MtpPropertyGroup propertyGroup;
6807d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        if (property == 0xFFFFFFFFL) {
6817d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             propertyGroup = mPropertyGroupsByFormat.get(format);
6827d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             if (propertyGroup == null) {
6837d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                int[] propertyList = getSupportedObjectProperties(format);
68435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mPackageName,
68535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        mVolumeName, propertyList);
6867d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                mPropertyGroupsByFormat.put(new Integer(format), propertyGroup);
687e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
6887d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        } else {
6897d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood              propertyGroup = mPropertyGroupsByProperty.get(property);
6907d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood             if (propertyGroup == null) {
6917d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                int[] propertyList = new int[] { (int)property };
69235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                propertyGroup = new MtpPropertyGroup(this, mMediaProvider, mPackageName,
69335654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        mVolumeName, propertyList);
6947d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                mPropertyGroupsByProperty.put(new Integer((int)property), propertyGroup);
695e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
696e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
6977d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
698b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood        return propertyGroup.getPropertyList((int)handle, format, depth);
699e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
700e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
701e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    private int renameFile(int handle, String newName) {
702e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        Cursor c = null;
703e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
704e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // first compute current path
705e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String path = null;
706e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String[] whereArgs = new String[] {  Integer.toString(handle) };
707e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
70835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            c = mMediaProvider.query(mPackageName, mObjectsUri, PATH_PROJECTION, ID_WHERE,
70935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    whereArgs, null, null);
710e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null && c.moveToNext()) {
7111c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood                path = c.getString(1);
712e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
713e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
714e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "RemoteException in getObjectFilePath", e);
715e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
716e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } finally {
717e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            if (c != null) {
718e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                c.close();
719b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood            }
720b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood        }
721e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (path == null) {
722e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
723e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
724e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
72573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        // do not allow renaming any of the special subdirectories
72673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        if (isStorageSubDirectory(path)) {
72773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED;
72873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood        }
72973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
730e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // now rename the file.  make sure this succeeds before updating database
731e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        File oldFile = new File(path);
732e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int lastSlash = path.lastIndexOf('/');
733e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (lastSlash <= 1) {
734e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
735e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
736e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        String newPath = path.substring(0, lastSlash + 1) + newName;
737e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        File newFile = new File(newPath);
738e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        boolean success = oldFile.renameTo(newFile);
739e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (!success) {
740f26a586c86b097f975e26fe526ead564ad011bd0Mike Lockwood            Log.w(TAG, "renaming "+ path + " to " + newPath + " failed");
741e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
742e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
743e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
744e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // finally update database
745e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        ContentValues values = new ContentValues();
746e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        values.put(Files.FileColumns.DATA, newPath);
747e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int updated = 0;
748e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        try {
749e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // note - we are relying on a special case in MediaProvider.update() to update
750e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // the paths for all children in the case where this is a directory.
75135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            updated = mMediaProvider.update(mPackageName, mObjectsUri, values, ID_WHERE, whereArgs);
752e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        } catch (RemoteException e) {
753e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "RemoteException in mMediaProvider.update", e);
754e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
755e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (updated == 0) {
756e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            Log.e(TAG, "Unable to update path for " + path + " to " + newPath);
757e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            // this shouldn't happen, but if it does we need to rename the file to its original name
758e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            newFile.renameTo(oldFile);
759e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
760e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
761e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
762ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen        // check if nomedia status changed
763ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen        if (newFile.isDirectory()) {
764ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen            // for directories, check if renamed from something hidden to something non-hidden
765ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen            if (oldFile.getName().startsWith(".") && !newPath.startsWith(".")) {
766ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                // directory was unhidden
767ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                try {
76835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    mMediaProvider.call(mPackageName, MediaStore.UNHIDE_CALL, newPath, null);
769ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                } catch (RemoteException e) {
770ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                    Log.e(TAG, "failed to unhide/rescan for " + newPath);
771ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                }
772ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen            }
773ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen        } else {
774ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen            // for files, check if renamed from .nomedia to something else
775ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen            if (oldFile.getName().toLowerCase(Locale.US).equals(".nomedia")
776ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                    && !newPath.toLowerCase(Locale.US).equals(".nomedia")) {
777ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                try {
77835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                    mMediaProvider.call(mPackageName, MediaStore.UNHIDE_CALL, oldFile.getParent(), null);
779ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                } catch (RemoteException e) {
780ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                    Log.e(TAG, "failed to unhide/rescan for " + newPath);
781ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                }
782ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen            }
783ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen        }
784ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen
785e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return MtpConstants.RESPONSE_OK;
786d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
787d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
78859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int setObjectProperty(int handle, int property,
78959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                            long intValue, String stringValue) {
7905ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        switch (property) {
7915ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            case MtpConstants.PROPERTY_OBJECT_FILE_NAME:
7925ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood                return renameFile(handle, stringValue);
7935ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood
7945ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            default:
7955ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood                return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
7965ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        }
79759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
79859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
79959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) {
80059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        switch (property) {
80159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
80259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
803775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                // writable string properties kept in shared preferences
804775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                String value = mDeviceProperties.getString(Integer.toString(property), "");
805775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                int length = value.length();
806775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                if (length > 255) {
807775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                    length = 255;
80859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                }
809775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                value.getChars(0, length, outStringValue, 0);
810775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                outStringValue[length] = 0;
811775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                return MtpConstants.RESPONSE_OK;
81259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
813ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE:
814ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                // use screen size as max image size
815ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                Display display = ((WindowManager)mContext.getSystemService(
816ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                        Context.WINDOW_SERVICE)).getDefaultDisplay();
81744bc17c6b517aef35a390c81b5aa79c4f284f744Dianne Hackborn                int width = display.getMaximumSizeDimension();
81844bc17c6b517aef35a390c81b5aa79c4f284f744Dianne Hackborn                int height = display.getMaximumSizeDimension();
819ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                String imageSize = Integer.toString(width) + "x" +  Integer.toString(height);
820ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                imageSize.getChars(0, imageSize.length(), outStringValue, 0);
821ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                outStringValue[imageSize.length()] = 0;
822ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                return MtpConstants.RESPONSE_OK;
823ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood
824ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            default:
825ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
826ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood        }
82759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
82859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
82959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    private int setDeviceProperty(int property, long intValue, String stringValue) {
83059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        switch (property) {
83159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
83259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
833775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                // writable string properties kept in shared prefs
834775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                SharedPreferences.Editor e = mDeviceProperties.edit();
835775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                e.putString(Integer.toString(property), stringValue);
836775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                return (e.commit() ? MtpConstants.RESPONSE_OK
837775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood                        : MtpConstants.RESPONSE_GENERAL_ERROR);
83859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
83959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
84059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
84159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
84259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
843d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private boolean getObjectInfo(int handle, int[] outStorageFormatParent,
8441341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood                        char[] outName, long[] outCreatedModified) {
845d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
846d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
84735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            c = mMediaProvider.query(mPackageName, mObjectsUri, OBJECT_INFO_PROJECTION,
84875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown                            ID_WHERE, new String[] {  Integer.toString(handle) }, null, null);
849d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null && c.moveToNext()) {
850b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                outStorageFormatParent[0] = c.getInt(1);
851d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outStorageFormatParent[1] = c.getInt(2);
852d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outStorageFormatParent[2] = c.getInt(3);
853d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
854d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                // extract name from path
855b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood                String path = c.getString(4);
856d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int lastSlash = path.lastIndexOf('/');
857d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int start = (lastSlash >= 0 ? lastSlash + 1 : 0);
858d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                int end = path.length();
859d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                if (end - start > 255) {
860d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                    end = start + 255;
861d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                }
862d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                path.getChars(start, end, outName, 0);
863d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outName[end - start] = 0;
864d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
8651341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood                outCreatedModified[0] = c.getLong(5);
8661341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood                outCreatedModified[1] = c.getLong(6);
8671341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood                // use modification date as creation date if date added is not set
8681341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood                if (outCreatedModified[0] == 0) {
8691341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood                    outCreatedModified[0] = outCreatedModified[1];
8701341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood                }
871d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                return true;
872d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
873d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
8742b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood            Log.e(TAG, "RemoteException in getObjectInfo", e);
875d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
876d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
877d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
878d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
879d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
880d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return false;
881d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
882d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
883365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood    private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) {
88401788562f26f213f63c14483fd3977e23b8314abMike Lockwood        if (handle == 0) {
88501788562f26f213f63c14483fd3977e23b8314abMike Lockwood            // special case root directory
88601788562f26f213f63c14483fd3977e23b8314abMike Lockwood            mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0);
88701788562f26f213f63c14483fd3977e23b8314abMike Lockwood            outFilePath[mMediaStoragePath.length()] = 0;
888365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            outFileLengthFormat[0] = 0;
889365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood            outFileLengthFormat[1] = MtpConstants.FORMAT_ASSOCIATION;
89001788562f26f213f63c14483fd3977e23b8314abMike Lockwood            return MtpConstants.RESPONSE_OK;
89101788562f26f213f63c14483fd3977e23b8314abMike Lockwood        }
892d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        Cursor c = null;
893d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
89435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            c = mMediaProvider.query(mPackageName, mObjectsUri, PATH_FORMAT_PROJECTION,
89575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown                            ID_WHERE, new String[] {  Integer.toString(handle) }, null, null);
896d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null && c.moveToNext()) {
8971c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood                String path = c.getString(1);
898d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                path.getChars(0, path.length(), outFilePath, 0);
899d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                outFilePath[path.length()] = 0;
900f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood                // File transfers from device to host will likely fail if the size is incorrect.
901f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood                // So to be safe, use the actual file size here.
902f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood                outFileLengthFormat[0] = new File(path).length();
903f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood                outFileLengthFormat[1] = c.getLong(2);
9045367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
90559c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            } else {
9065367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
907d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
908d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
909d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in getObjectFilePath", e);
9105367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
911d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } finally {
912d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            if (c != null) {
913d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                c.close();
914d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            }
915d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
916d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
917d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
91859c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    private int deleteFile(int handle) {
9192837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
92055f808cff9913a00164120a422af6ca45db5072bMike Lockwood        String path = null;
92155f808cff9913a00164120a422af6ca45db5072bMike Lockwood        int format = 0;
92255f808cff9913a00164120a422af6ca45db5072bMike Lockwood
92355f808cff9913a00164120a422af6ca45db5072bMike Lockwood        Cursor c = null;
924d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        try {
92535654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            c = mMediaProvider.query(mPackageName, mObjectsUri, PATH_FORMAT_PROJECTION,
92675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown                            ID_WHERE, new String[] {  Integer.toString(handle) }, null, null);
92755f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (c != null && c.moveToNext()) {
92855f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // don't convert to media path here, since we will be matching
92955f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // against paths in the database matching /data/media
93055f808cff9913a00164120a422af6ca45db5072bMike Lockwood                path = c.getString(1);
931f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood                format = c.getInt(2);
93255f808cff9913a00164120a422af6ca45db5072bMike Lockwood            } else {
93355f808cff9913a00164120a422af6ca45db5072bMike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
93455f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
93555f808cff9913a00164120a422af6ca45db5072bMike Lockwood
93655f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (path == null || format == 0) {
93755f808cff9913a00164120a422af6ca45db5072bMike Lockwood                return MtpConstants.RESPONSE_GENERAL_ERROR;
93855f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
93955f808cff9913a00164120a422af6ca45db5072bMike Lockwood
94073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            // do not allow deleting any of the special subdirectories
94173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            if (isStorageSubDirectory(path)) {
94273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood                return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED;
94373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood            }
94473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood
94555f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (format == MtpConstants.FORMAT_ASSOCIATION) {
94655f808cff9913a00164120a422af6ca45db5072bMike Lockwood                // recursive case - delete all children first
94755f808cff9913a00164120a422af6ca45db5072bMike Lockwood                Uri uri = Files.getMtpObjectsUri(mVolumeName);
94835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                int count = mMediaProvider.delete(mPackageName, uri,
9491e855d98aa979b30cee9e096cf6a1cb54df0367bMike Lockwood                    // the 'like' makes it use the index, the 'lower()' makes it correct
9501e855d98aa979b30cee9e096cf6a1cb54df0367bMike Lockwood                    // when the path contains sqlite wildcard characters
9511e855d98aa979b30cee9e096cf6a1cb54df0367bMike Lockwood                    "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)",
9521e855d98aa979b30cee9e096cf6a1cb54df0367bMike Lockwood                    new String[] { path + "/%",Integer.toString(path.length() + 1), path + "/"});
95355f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
95455f808cff9913a00164120a422af6ca45db5072bMike Lockwood
95555f808cff9913a00164120a422af6ca45db5072bMike Lockwood            Uri uri = Files.getMtpObjectsUri(mVolumeName, handle);
95635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (mMediaProvider.delete(mPackageName, uri, null, null) > 0) {
957ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                if (format != MtpConstants.FORMAT_ASSOCIATION
958ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                        && path.toLowerCase(Locale.US).endsWith("/.nomedia")) {
959ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                    try {
960ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                        String parentPath = path.substring(0, path.lastIndexOf("/"));
96135654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn                        mMediaProvider.call(mPackageName, MediaStore.UNHIDE_CALL, parentPath, null);
962ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                    } catch (RemoteException e) {
963ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                        Log.e(TAG, "failed to unhide/rescan for " + path);
964ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                    }
965ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen                }
9665367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
96759c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            } else {
9685367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE;
96959c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood            }
970d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        } catch (RemoteException e) {
971d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            Log.e(TAG, "RemoteException in deleteFile", e);
9725367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood            return MtpConstants.RESPONSE_GENERAL_ERROR;
97355f808cff9913a00164120a422af6ca45db5072bMike Lockwood        } finally {
97455f808cff9913a00164120a422af6ca45db5072bMike Lockwood            if (c != null) {
97555f808cff9913a00164120a422af6ca45db5072bMike Lockwood                c.close();
97655f808cff9913a00164120a422af6ca45db5072bMike Lockwood            }
977d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
978d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
979d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
9809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    private int[] getObjectReferences(int handle) {
9818490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
9829a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        Cursor c = null;
9839a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        try {
98435654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            c = mMediaProvider.query(mPackageName, uri, ID_PROJECTION, null, null, null, null);
9859a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (c == null) {
9869a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                return null;
9879a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
9889a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            int count = c.getCount();
9899a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (count > 0) {
9909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                int[] result = new int[count];
9919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                for (int i = 0; i < count; i++) {
9929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    c.moveToNext();
9939a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                    result[i] = c.getInt(0);
9949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                }
9959a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                return result;
9969a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
9979a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } catch (RemoteException e) {
9989a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            Log.e(TAG, "RemoteException in getObjectList", e);
9999a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } finally {
10009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            if (c != null) {
10019a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                c.close();
10029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
10039a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
10049a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        return null;
10059a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
10069a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
10079a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    private int setObjectReferences(int handle, int[] references) {
10082837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = true;
10098490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood        Uri uri = Files.getMtpReferencesUri(mVolumeName, handle);
10109a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        int count = references.length;
10119a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        ContentValues[] valuesList = new ContentValues[count];
10129a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        for (int i = 0; i < count; i++) {
10139a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            ContentValues values = new ContentValues();
10143b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood            values.put(Files.FileColumns._ID, references[i]);
10159a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            valuesList[i] = values;
10169a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
10179a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        try {
101835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn            if (mMediaProvider.bulkInsert(mPackageName, uri, valuesList) > 0) {
10195367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood                return MtpConstants.RESPONSE_OK;
10209a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            }
10219a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        } catch (RemoteException e) {
10229a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood            Log.e(TAG, "RemoteException in setObjectReferences", e);
10239a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        }
10245367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood        return MtpConstants.RESPONSE_GENERAL_ERROR;
10259a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
10269a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
10272837eefc5459427138c080d445bb491c75630163Mike Lockwood    private void sessionStarted() {
10282837eefc5459427138c080d445bb491c75630163Mike Lockwood        mDatabaseModified = false;
10292837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
10302837eefc5459427138c080d445bb491c75630163Mike Lockwood
10312837eefc5459427138c080d445bb491c75630163Mike Lockwood    private void sessionEnded() {
10322837eefc5459427138c080d445bb491c75630163Mike Lockwood        if (mDatabaseModified) {
1033a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwood            mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END));
10342837eefc5459427138c080d445bb491c75630163Mike Lockwood            mDatabaseModified = false;
10352837eefc5459427138c080d445bb491c75630163Mike Lockwood        }
10362837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
10372837eefc5459427138c080d445bb491c75630163Mike Lockwood
1038d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    // used by the JNI code
1039e2e59326f13cf291bf5b37989390fd2a55a94f0cAshok Bhat    private long mNativeContext;
1040d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1041d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private native final void native_setup();
1042d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    private native final void native_finalize();
1043d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
1044