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 1956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwoodimport android.content.BroadcastReceiver; 2060cfad80bdf61db436643927337c2fb30186e99dJeff Sharkeyimport android.content.ContentProviderClient; 21d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodimport android.content.ContentValues; 2260cfad80bdf61db436643927337c2fb30186e99dJeff Sharkeyimport android.content.Context; 232837eefc5459427138c080d445bb491c75630163Mike Lockwoodimport android.content.Intent; 2456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwoodimport android.content.IntentFilter; 25775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwoodimport android.content.SharedPreferences; 26d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.database.Cursor; 2759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodimport android.database.sqlite.SQLiteDatabase; 280cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodimport android.media.MediaScanner; 29d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.net.Uri; 3056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwoodimport android.os.BatteryManager; 31d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException; 3213bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhangimport android.os.SystemProperties; 33a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwoodimport android.provider.MediaStore; 349a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.Audio; 353b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwoodimport android.provider.MediaStore.Files; 36ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwoodimport android.provider.MediaStore.MediaColumns; 37d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log; 38ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.Display; 39ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwoodimport android.view.WindowManager; 40d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 4160cfad80bdf61db436643927337c2fb30186e99dJeff Sharkeyimport dalvik.system.CloseGuard; 4260cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey 435ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwoodimport java.io.File; 445f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissenimport java.io.IOException; 457d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwoodimport java.util.HashMap; 46fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.chaimport java.util.Locale; 4760cfad80bdf61db436643927337c2fb30186e99dJeff Sharkeyimport java.util.concurrent.atomic.AtomicBoolean; 485ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood 49d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/** 50d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide} 51d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */ 5260cfad80bdf61db436643927337c2fb30186e99dJeff Sharkeypublic class MtpDatabase implements AutoCloseable { 53d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String TAG = "MtpDatabase"; 54d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 552837eefc5459427138c080d445bb491c75630163Mike Lockwood private final Context mContext; 5635654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn private final String mPackageName; 5760cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey private final ContentProviderClient mMediaProvider; 58d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final String mVolumeName; 59d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final Uri mObjectsUri; 6060cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey private final MediaScanner mMediaScanner; 6160cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey 6260cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey private final AtomicBoolean mClosed = new AtomicBoolean(); 6360cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey private final CloseGuard mCloseGuard = CloseGuard.get(); 6460cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey 6573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // path to primary storage 6673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood private final String mMediaStoragePath; 6773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // if not null, restrict all queries to these subdirectories 6873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood private final String[] mSubDirectories; 6973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // where clause for restricting queries to files in mSubDirectories 7073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood private String mSubDirectoriesWhere; 7173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // where arguments for restricting queries to files in mSubDirectories 7273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood private String[] mSubDirectoriesWhereArgs; 7373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 74b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private final HashMap<String, MtpStorage> mStorageMap = new HashMap<String, MtpStorage>(); 75d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 767d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // cached property groups for single properties 777d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByProperty 787d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood = new HashMap<Integer, MtpPropertyGroup>(); 797d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 807d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood // cached property groups for all properties for a given format 817d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood private final HashMap<Integer, MtpPropertyGroup> mPropertyGroupsByFormat 827d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood = new HashMap<Integer, MtpPropertyGroup>(); 837d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 842837eefc5459427138c080d445bb491c75630163Mike Lockwood // true if the database has been modified in the current MTP session 852837eefc5459427138c080d445bb491c75630163Mike Lockwood private boolean mDatabaseModified; 862837eefc5459427138c080d445bb491c75630163Mike Lockwood 87775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // SharedPreferences for writable MTP device properties 88775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood private SharedPreferences mDeviceProperties; 8959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private static final int DEVICE_PROPERTIES_DATABASE_VERSION = 1; 9059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 91d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] ID_PROJECTION = new String[] { 923b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 93d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 946a6a3aff17e057eeb1457ac4d04ab4b5e8f53abeMike Lockwood private static final String[] PATH_PROJECTION = new String[] { 955ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood Files.FileColumns._ID, // 0 965ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood Files.FileColumns.DATA, // 1 975ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood }; 9871827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood private static final String[] FORMAT_PROJECTION = new String[] { 9971827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood Files.FileColumns._ID, // 0 10071827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood Files.FileColumns.FORMAT, // 1 10171827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood }; 102f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood private static final String[] PATH_FORMAT_PROJECTION = new String[] { 1033b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 1043b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.DATA, // 1 105f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood Files.FileColumns.FORMAT, // 2 106d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 107d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] OBJECT_INFO_PROJECTION = new String[] { 1083b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns._ID, // 0 109b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Files.FileColumns.STORAGE_ID, // 1 1103b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.FORMAT, // 2 1113b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood Files.FileColumns.PARENT, // 3 112b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Files.FileColumns.DATA, // 4 1131341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood Files.FileColumns.DATE_ADDED, // 5 1141341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood Files.FileColumns.DATE_MODIFIED, // 6 115d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 1163b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood private static final String ID_WHERE = Files.FileColumns._ID + "=?"; 117bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood private static final String PATH_WHERE = Files.FileColumns.DATA + "=?"; 1186acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood 1196acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood private static final String STORAGE_WHERE = Files.FileColumns.STORAGE_ID + "=?"; 12058e6831ccb54b33a914115e88ebb67e720615fb8Mike Lockwood private static final String FORMAT_WHERE = Files.FileColumns.FORMAT + "=?"; 12158e6831ccb54b33a914115e88ebb67e720615fb8Mike Lockwood private static final String PARENT_WHERE = Files.FileColumns.PARENT + "=?"; 1226acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood private static final String STORAGE_FORMAT_WHERE = STORAGE_WHERE + " AND " 123b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood + Files.FileColumns.FORMAT + "=?"; 1246acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood private static final String STORAGE_PARENT_WHERE = STORAGE_WHERE + " AND " 1256acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood + Files.FileColumns.PARENT + "=?"; 1266acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood private static final String FORMAT_PARENT_WHERE = FORMAT_WHERE + " AND " 1276acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood + Files.FileColumns.PARENT + "=?"; 1286acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood private static final String STORAGE_FORMAT_PARENT_WHERE = STORAGE_FORMAT_WHERE + " AND " 1296acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood + Files.FileColumns.PARENT + "=?"; 130d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 13156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood private MtpServer mServer; 13256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood 13356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood // read from native code 13456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood private int mBatteryLevel; 13556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood private int mBatteryScale; 136d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 13713bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhang private int mDeviceType; 13813bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhang 139d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood static { 140d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood System.loadLibrary("media_jni"); 141d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 142d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 14356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood private BroadcastReceiver mBatteryReceiver = new BroadcastReceiver() { 14456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood @Override 14556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood public void onReceive(Context context, Intent intent) { 14656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood String action = intent.getAction(); 14756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood if (action.equals(Intent.ACTION_BATTERY_CHANGED)) { 14856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood mBatteryScale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 0); 14956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood int newLevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0); 15056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood if (newLevel != mBatteryLevel) { 15156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood mBatteryLevel = newLevel; 15256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood if (mServer != null) { 15356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood // send device property changed event 15456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood mServer.sendDevicePropertyChanged( 15556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL); 15656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood } 15756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood } 15856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood } 15956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood } 16056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood }; 16156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood 16273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood public MtpDatabase(Context context, String volumeName, String storagePath, 16373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood String[] subDirectories) { 164d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood native_setup(); 165d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 1662837eefc5459427138c080d445bb491c75630163Mike Lockwood mContext = context; 16735654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mPackageName = context.getPackageName(); 16860cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mMediaProvider = context.getContentResolver() 16960cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey .acquireContentProviderClient(MediaStore.AUTHORITY); 170d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mVolumeName = volumeName; 17101788562f26f213f63c14483fd3977e23b8314abMike Lockwood mMediaStoragePath = storagePath; 1728490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood mObjectsUri = Files.getMtpObjectsUri(volumeName); 17360cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mMediaScanner = new MediaScanner(context, mVolumeName); 174fe464a76d8fc858be971dbb5e67b1d22fd925347dujin.cha 17573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood mSubDirectories = subDirectories; 17673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (subDirectories != null) { 17773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // Compute "where" string for restricting queries to subdirectories 17873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood StringBuilder builder = new StringBuilder(); 17973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood builder.append("("); 18073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood int count = subDirectories.length; 18173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood for (int i = 0; i < count; i++) { 18273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood builder.append(Files.FileColumns.DATA + "=? OR " 18373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood + Files.FileColumns.DATA + " LIKE ?"); 18473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (i != count - 1) { 18573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood builder.append(" OR "); 18673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 18773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 18873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood builder.append(")"); 18973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood mSubDirectoriesWhere = builder.toString(); 19073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 19173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // Compute "where" arguments for restricting queries to subdirectories 19273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood mSubDirectoriesWhereArgs = new String[count * 2]; 19373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood for (int i = 0, j = 0; i < count; i++) { 19473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood String path = subDirectories[i]; 19573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood mSubDirectoriesWhereArgs[j++] = path; 19673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood mSubDirectoriesWhereArgs[j++] = path + "/%"; 19773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 19873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 19973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 200775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood initDeviceProperties(context); 20113bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhang mDeviceType = SystemProperties.getInt("sys.usb.mtp.device_type", 0); 20260cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey 20360cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mCloseGuard.open("close"); 204d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 205d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 20656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood public void setServer(MtpServer server) { 20756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood mServer = server; 20856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood 2091632fae376eb460cf992e543b13c8690b71fe8d5Marco Nelissen // always unregister before registering 2101632fae376eb460cf992e543b13c8690b71fe8d5Marco Nelissen try { 2111632fae376eb460cf992e543b13c8690b71fe8d5Marco Nelissen mContext.unregisterReceiver(mBatteryReceiver); 2121632fae376eb460cf992e543b13c8690b71fe8d5Marco Nelissen } catch (IllegalArgumentException e) { 2131632fae376eb460cf992e543b13c8690b71fe8d5Marco Nelissen // wasn't previously registered, ignore 2141632fae376eb460cf992e543b13c8690b71fe8d5Marco Nelissen } 2151632fae376eb460cf992e543b13c8690b71fe8d5Marco Nelissen 21656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood // register for battery notifications when we are connected 21756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood if (server != null) { 21856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood mContext.registerReceiver(mBatteryReceiver, 21956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); 22056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood } 22156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood } 22256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood 223d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood @Override 22460cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey public void close() { 22560cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mCloseGuard.close(); 22660cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey if (mClosed.compareAndSet(false, true)) { 22760cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mMediaScanner.close(); 22860cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mMediaProvider.close(); 22960cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey native_finalize(); 23060cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey } 23160cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey } 23260cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey 23360cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey @Override 234dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood protected void finalize() throws Throwable { 235dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood try { 23660cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mCloseGuard.warnIfOpen(); 23760cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey close(); 238dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood } finally { 239dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood super.finalize(); 240dbead321daf2c16dc74e182bec591b278cfccb2cMike Lockwood } 241d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 242d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 243b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood public void addStorage(MtpStorage storage) { 244b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood mStorageMap.put(storage.getPath(), storage); 245b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 246b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood 247b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood public void removeStorage(MtpStorage storage) { 248b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood mStorageMap.remove(storage.getPath()); 249b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 250b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood 251775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood private void initDeviceProperties(Context context) { 252775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood final String devicePropertiesName = "device-properties"; 253775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood mDeviceProperties = context.getSharedPreferences(devicePropertiesName, Context.MODE_PRIVATE); 254775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood File databaseFile = context.getDatabasePath(devicePropertiesName); 255775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood 256775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (databaseFile.exists()) { 257775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // for backward compatibility - read device properties from sqlite database 258775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // and migrate them to shared prefs 259775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood SQLiteDatabase db = null; 260775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood Cursor c = null; 261775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood try { 262775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood db = context.openOrCreateDatabase("device-properties", Context.MODE_PRIVATE, null); 263775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (db != null) { 264775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood c = db.query("properties", new String[] { "_id", "code", "value" }, 265775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood null, null, null, null, null); 266775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (c != null) { 267775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood SharedPreferences.Editor e = mDeviceProperties.edit(); 268775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood while (c.moveToNext()) { 269775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood String name = c.getString(1); 270775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood String value = c.getString(2); 271775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood e.putString(name, value); 272775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } 273775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood e.commit(); 274775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } 275775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } 276775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } catch (Exception e) { 277775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood Log.e(TAG, "failed to migrate device properties", e); 278775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } finally { 279775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (c != null) c.close(); 280775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (db != null) db.close(); 281775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood } 2823ed02535fdc3c752346c40b57962905b7072e693jangwon.lee context.deleteDatabase(devicePropertiesName); 28359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 28459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 28559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 28673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // check to see if the path is contained in one of our storage subdirectories 28773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // returns true if we have no special subdirectories 28873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood private boolean inStorageSubDirectory(String path) { 28973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (mSubDirectories == null) return true; 29073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (path == null) return false; 29173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 29273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood boolean allowed = false; 29373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood int pathLength = path.length(); 29473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood for (int i = 0; i < mSubDirectories.length && !allowed; i++) { 29573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood String subdir = mSubDirectories[i]; 29673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood int subdirLength = subdir.length(); 29773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (subdirLength < pathLength && 29873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood path.charAt(subdirLength) == '/' && 29973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood path.startsWith(subdir)) { 30073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood allowed = true; 30173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 30273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 30373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood return allowed; 30473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 30573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 30673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // check to see if the path matches one of our storage subdirectories 30773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // returns true if we have no special subdirectories 30873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood private boolean isStorageSubDirectory(String path) { 30973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (mSubDirectories == null) return false; 31073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood for (int i = 0; i < mSubDirectories.length; i++) { 31173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (path.equals(mSubDirectories[i])) { 31273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood return true; 31373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 31473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 31573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood return false; 31673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 31773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 3185f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen // returns true if the path is in the storage root 3195f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen private boolean inStorageRoot(String path) { 3205f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen try { 3215f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen File f = new File(path); 3225f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen String canonical = f.getCanonicalPath(); 323c1fda12823bfac1c2180beddc3f733ea0311b37dMarco Nelissen for (String root: mStorageMap.keySet()) { 324c1fda12823bfac1c2180beddc3f733ea0311b37dMarco Nelissen if (canonical.startsWith(root)) { 325c1fda12823bfac1c2180beddc3f733ea0311b37dMarco Nelissen return true; 326c1fda12823bfac1c2180beddc3f733ea0311b37dMarco Nelissen } 3275f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen } 3285f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen } catch (IOException e) { 3295f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen // ignore 3305f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen } 3315f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen return false; 3325f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen } 3335f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen 334d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private int beginSendObject(String path, int format, int parent, 335b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood int storageId, long size, long modified) { 3365f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen // if the path is outside of the storage root, do not allow access 3375f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen if (!inStorageRoot(path)) { 3385f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen Log.e(TAG, "attempt to put file outside of storage area: " + path); 3395f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen return -1; 3405f411696a62b7f0fb95ba3519aa127c09f155eedMarco Nelissen } 34173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // if mSubDirectories is not null, do not allow copying files to any other locations 34273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (!inStorageSubDirectory(path)) return -1; 34373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 34473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // make sure the object does not exist 345bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood if (path != null) { 346bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood Cursor c = null; 347bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood try { 34860cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, PATH_WHERE, 34975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown new String[] { path }, null, null); 350bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood if (c != null && c.getCount() > 0) { 351bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood Log.w(TAG, "file already exists in beginSendObject: " + path); 352bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood return -1; 353bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } 354bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } catch (RemoteException e) { 355bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood Log.e(TAG, "RemoteException in beginSendObject", e); 356bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } finally { 357bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood if (c != null) { 358bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood c.close(); 359bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } 360bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } 361bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood } 362bafca214eaf326441e5157d645b2ee7fe8c7d1abMike Lockwood 3632837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 364d815f79766984fce499e147ecbacc01914683f74Mike Lockwood ContentValues values = new ContentValues(); 3653b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.DATA, path); 3663b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.FORMAT, format); 3673b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.PARENT, parent); 368b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood values.put(Files.FileColumns.STORAGE_ID, storageId); 3693b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.SIZE, size); 3703b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns.DATE_MODIFIED, modified); 371d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 372d815f79766984fce499e147ecbacc01914683f74Mike Lockwood try { 37360cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey Uri uri = mMediaProvider.insert(mObjectsUri, values); 374d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (uri != null) { 375d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return Integer.parseInt(uri.getPathSegments().get(2)); 376d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 377d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 378d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 379d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } catch (RemoteException e) { 380d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Log.e(TAG, "RemoteException in beginSendObject", e); 381d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 382d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 383d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 384d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 3857a0bd17bceaf3efc3732e30c538fae420d3b742cMike Lockwood private void endSendObject(String path, int handle, int format, boolean succeeded) { 386d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (succeeded) { 3879a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // handle abstract playlists separately 3889a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // they do not exist in the file system so don't use the media scanner here 3895367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood if (format == MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST) { 3909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // extract name from path 3919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood String name = path; 3929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int lastSlash = name.lastIndexOf('/'); 3939a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (lastSlash >= 0) { 3949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood name = name.substring(lastSlash + 1); 3959a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 3968cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood // strip trailing ".pla" from the name 3978cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood if (name.endsWith(".pla")) { 3988cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood name = name.substring(0, name.length() - 4); 3998cc6eb1e4c708fb4398292ba30aa80ad5770d7ceMike Lockwood } 4009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 4019a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues values = new ContentValues(1); 4029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(Audio.Playlists.DATA, path); 4039a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(Audio.Playlists.NAME, name); 4040b58c19840c577c8d8fd8aa5315676d61b78ba0fMike Lockwood values.put(Files.FileColumns.FORMAT, format); 4058ed67acf38ccdfdb89553ed58620a135f2100e10Mike Lockwood values.put(Files.FileColumns.DATE_MODIFIED, System.currentTimeMillis() / 1000); 4069a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle); 4079a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 40860cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey Uri uri = mMediaProvider.insert( 40935654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn Audio.Playlists.EXTERNAL_CONTENT_URI, values); 4109a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 4119a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in endSendObject", e); 4129a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 4139a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } else { 41460cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mMediaScanner.scanMtpFile(path, handle, format); 4159a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 416d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 417d815f79766984fce499e147ecbacc01914683f74Mike Lockwood deleteFile(handle); 418d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 419d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 420d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 421b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private Cursor createObjectQuery(int storageID, int format, int parent) throws RemoteException { 42273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood String where; 42373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood String[] whereArgs; 42473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 4256acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood if (storageID == 0xFFFFFFFF) { 4266acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query all stores 4276acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood if (format == 0) { 4286acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query all formats 4296acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood if (parent == 0) { 4306acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query all objects 43173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = null; 43273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = null; 43373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } else { 43473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (parent == 0xFFFFFFFF) { 43573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // all objects in root of store 43673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood parent = 0; 43773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 43873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = PARENT_WHERE; 43973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = new String[] { Integer.toString(parent) }; 4406acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood } 441b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } else { 4426acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query specific format 4436acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood if (parent == 0) { 4446acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query all objects 44573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = FORMAT_WHERE; 44673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = new String[] { Integer.toString(format) }; 44773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } else { 44873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (parent == 0xFFFFFFFF) { 44973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // all objects in root of store 45073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood parent = 0; 45173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 45273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = FORMAT_PARENT_WHERE; 45373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = new String[] { Integer.toString(format), 45473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood Integer.toString(parent) }; 4556acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood } 456b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 457b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } else { 4586acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query specific store 4596acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood if (format == 0) { 4606acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query all formats 4616acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood if (parent == 0) { 4626acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query all objects 46373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = STORAGE_WHERE; 46473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = new String[] { Integer.toString(storageID) }; 46573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } else { 46673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (parent == 0xFFFFFFFF) { 46773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // all objects in root of store 46873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood parent = 0; 46973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 47073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = STORAGE_PARENT_WHERE; 47173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = new String[] { Integer.toString(storageID), 47273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood Integer.toString(parent) }; 4736acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood } 474d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } else { 4756acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query specific format 4766acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood if (parent == 0) { 4776acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood // query all objects 47873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = STORAGE_FORMAT_WHERE; 47973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = new String[] { Integer.toString(storageID), 48073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood Integer.toString(format) }; 48173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } else { 48273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (parent == 0xFFFFFFFF) { 48373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // all objects in root of store 48473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood parent = 0; 48573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 48673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = STORAGE_FORMAT_PARENT_WHERE; 48773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = new String[] { Integer.toString(storageID), 48873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood Integer.toString(format), 48973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood Integer.toString(parent) }; 4906acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood } 49173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 49273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 49373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 49473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // if we are restricting queries to mSubDirectories, we need to add the restriction 49573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // onto our "where" arguments 49673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (mSubDirectoriesWhere != null) { 49773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (where == null) { 49873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = mSubDirectoriesWhere; 49973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = mSubDirectoriesWhereArgs; 50073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } else { 50173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood where = where + " AND " + mSubDirectoriesWhere; 50273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 50373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // create new array to hold whereArgs and mSubDirectoriesWhereArgs 50473e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood String[] newWhereArgs = 50573e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood new String[whereArgs.length + mSubDirectoriesWhereArgs.length]; 50673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood int i, j; 50773e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood for (i = 0; i < whereArgs.length; i++) { 50873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood newWhereArgs[i] = whereArgs[i]; 5096acc90fc216530f0a5bbf7339066af9b415cbb02Mike Lockwood } 51073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood for (j = 0; j < mSubDirectoriesWhereArgs.length; i++, j++) { 51173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood newWhereArgs[i] = mSubDirectoriesWhereArgs[j]; 51273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 51373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood whereArgs = newWhereArgs; 514d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 515b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 51673e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 51760cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey return mMediaProvider.query(mObjectsUri, ID_PROJECTION, where, 51835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn whereArgs, null, null); 519b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood } 520b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood 521b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood private int[] getObjectList(int storageID, int format, int parent) { 522b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood Cursor c = null; 523b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood try { 524b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood c = createObjectQuery(storageID, format, parent); 525d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c == null) { 526d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 527d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 528d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int count = c.getCount(); 529d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (count > 0) { 530d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int[] result = new int[count]; 531d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood for (int i = 0; i < count; i++) { 532d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.moveToNext(); 533d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood result[i] = c.getInt(0); 534d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 535d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return result; 536d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 537d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 538d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 539d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 540d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 541d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 542d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 543d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 544d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 545d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 546d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 5477a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood private int getNumObjects(int storageID, int format, int parent) { 5487a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Cursor c = null; 5497a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood try { 550b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood c = createObjectQuery(storageID, format, parent); 5517a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 5527a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return c.getCount(); 5537a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 5547a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } catch (RemoteException e) { 5557a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Log.e(TAG, "RemoteException in getNumObjects", e); 5567a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } finally { 5577a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 5587a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c.close(); 5597a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 5607a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 5617a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return -1; 5627a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 5637a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood 5644b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedPlaybackFormats() { 5654b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood return new int[] { 566e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood // allow transfering arbitrary files 567e521169ff5dc6cbe1762bd7a049d95b56cc657eeMike Lockwood MtpConstants.FORMAT_UNDEFINED, 56812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood 569792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood MtpConstants.FORMAT_ASSOCIATION, 57012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_TEXT, 57112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_HTML, 57212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_WAV, 57312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_MP3, 57412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_MPEG, 57512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_EXIF_JPEG, 57612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_TIFF_EP, 577240582eabee56d55751b85e220811d48fabe839abo huang MtpConstants.FORMAT_BMP, 57812b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_GIF, 57912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_JFIF, 58012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_PNG, 58112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_TIFF, 58212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_WMA, 58312b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_OGG, 58412b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_AAC, 58512b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_MP4_CONTAINER, 58612b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_MP2, 58712b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_3GP_CONTAINER, 588792ec849e5bc27c090c62f578846b888fa43e0d6Mike Lockwood MtpConstants.FORMAT_ABSTRACT_AV_PLAYLIST, 58912b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_WPL_PLAYLIST, 59012b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_M3U_PLAYLIST, 59112b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_PLS_PLAYLIST, 59212b8a99fc1d4acc427307a4a924bf33745410260Mike Lockwood MtpConstants.FORMAT_XML_DOCUMENT, 593f9f223edb408cdc9fd946dc099a86857079a639fGlenn Kasten MtpConstants.FORMAT_FLAC, 5945a8b9627c7fdacc94791fb3024386739f8cf9a56Jaesung Chung MtpConstants.FORMAT_DNG, 5954b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood }; 5964b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 5974b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 5984b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedCaptureFormats() { 5994b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood // no capture formats yet 6004b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood return null; 6014b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 6024b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 603ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood static final int[] FILE_PROPERTIES = { 604ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // NOTE must match beginning of AUDIO_PROPERTIES, VIDEO_PROPERTIES 605ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // and IMAGE_PROPERTIES below 6065367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 6075367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 608d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 6095367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 6105367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 611d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 6125367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 613d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 614d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood MtpConstants.PROPERTY_NAME, 61571827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood MtpConstants.PROPERTY_DISPLAY_NAME, 616ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 617ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood }; 618ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 619ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood static final int[] AUDIO_PROPERTIES = { 620ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // NOTE must match FILE_PROPERTIES above 621ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 622ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 623ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 624ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 625ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 626ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 627ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 628ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 629ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_NAME, 630ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DISPLAY_NAME, 631ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 632ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 633ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // audio specific properties 634ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ARTIST, 635ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ALBUM_NAME, 636ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ALBUM_ARTIST, 637ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_TRACK, 638ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ORIGINAL_RELEASE_DATE, 639ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DURATION, 640ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_GENRE, 641ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_COMPOSER, 64292b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood MtpConstants.PROPERTY_AUDIO_WAVE_CODEC, 64392b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood MtpConstants.PROPERTY_BITRATE_TYPE, 64492b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood MtpConstants.PROPERTY_AUDIO_BITRATE, 64592b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood MtpConstants.PROPERTY_NUMBER_OF_CHANNELS, 64692b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood MtpConstants.PROPERTY_SAMPLE_RATE, 647ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood }; 648ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 649ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood static final int[] VIDEO_PROPERTIES = { 650ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // NOTE must match FILE_PROPERTIES above 651ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 652ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 653ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 654ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 655ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 656ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 657ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 658ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 659ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_NAME, 660ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DISPLAY_NAME, 661ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 662ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 663ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // video specific properties 664ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ARTIST, 665ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_ALBUM_NAME, 666ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DURATION, 667ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DESCRIPTION, 668ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood }; 669ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 670ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood static final int[] IMAGE_PROPERTIES = { 671ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // NOTE must match FILE_PROPERTIES above 672ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_STORAGE_ID, 673ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FORMAT, 674ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PROTECTION_STATUS, 675ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_SIZE, 676ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_OBJECT_FILE_NAME, 677ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_MODIFIED, 678ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PARENT_OBJECT, 679ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_PERSISTENT_UID, 680ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_NAME, 681ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DISPLAY_NAME, 682ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DATE_ADDED, 683ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 684ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood // image specific properties 685ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood MtpConstants.PROPERTY_DESCRIPTION, 686ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood }; 687ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood 688ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood private int[] getSupportedObjectProperties(int format) { 689ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood switch (format) { 690ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_MP3: 691ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_WAV: 692ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_WMA: 693ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_OGG: 694ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_AAC: 695ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood return AUDIO_PROPERTIES; 696ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_MPEG: 697ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_3GP_CONTAINER: 698ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_WMV: 699ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood return VIDEO_PROPERTIES; 700ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_EXIF_JPEG: 701ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_GIF: 702ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_PNG: 703ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood case MtpConstants.FORMAT_BMP: 7045a8b9627c7fdacc94791fb3024386739f8cf9a56Jaesung Chung case MtpConstants.FORMAT_DNG: 705ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood return IMAGE_PROPERTIES; 706ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood default: 707ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood return FILE_PROPERTIES; 708ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood } 7094b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 7104b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 7114b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood private int[] getSupportedDeviceProperties() { 71259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return new int[] { 71359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, 71459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, 715ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE, 71656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood MtpConstants.DEVICE_PROPERTY_BATTERY_LEVEL, 71713bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhang MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE, 71859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood }; 7194b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood } 7204b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood 721486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono private MtpPropertyList getObjectPropertyList(int handle, int format, int property, 722e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood int groupCode, int depth) { 723e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // FIXME - implement group support 724e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (groupCode != 0) { 725e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return new MtpPropertyList(0, MtpConstants.RESPONSE_SPECIFICATION_BY_GROUP_UNSUPPORTED); 7265ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood } 7275ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood 7287d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood MtpPropertyGroup propertyGroup; 729486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono if (property == 0xffffffff) { 730486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono if (format == 0 && handle != 0 && handle != 0xffffffff) { 73171827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood // return properties based on the object's format 732486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono format = getObjectFormat(handle); 73371827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood } 734486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono propertyGroup = mPropertyGroupsByFormat.get(format); 735486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono if (propertyGroup == null) { 7367d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood int[] propertyList = getSupportedObjectProperties(format); 73760cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey propertyGroup = new MtpPropertyGroup(this, mMediaProvider, 73835654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn mVolumeName, propertyList); 739486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono mPropertyGroupsByFormat.put(format, propertyGroup); 740e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 7417d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood } else { 742486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono propertyGroup = mPropertyGroupsByProperty.get(property); 743486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono if (propertyGroup == null) { 744486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono final int[] propertyList = new int[] { property }; 745486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono propertyGroup = new MtpPropertyGroup( 746486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono this, mMediaProvider, mVolumeName, propertyList); 747486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono mPropertyGroupsByProperty.put(property, propertyGroup); 748e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 749e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 7507d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood 751486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono return propertyGroup.getPropertyList(handle, format, depth); 752e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 753e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 754e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood private int renameFile(int handle, String newName) { 755e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood Cursor c = null; 756e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 757e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // first compute current path 758e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood String path = null; 759e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood String[] whereArgs = new String[] { Integer.toString(handle) }; 760e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood try { 76160cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey c = mMediaProvider.query(mObjectsUri, PATH_PROJECTION, ID_WHERE, 76235654b61e8fe7bc85afcb076ddbb590d51c5865fDianne Hackborn whereArgs, null, null); 763e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (c != null && c.moveToNext()) { 7641c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood path = c.getString(1); 765e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 766e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } catch (RemoteException e) { 767e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood Log.e(TAG, "RemoteException in getObjectFilePath", e); 768e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 769e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } finally { 770e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (c != null) { 771e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood c.close(); 772b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 773b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 774e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (path == null) { 775e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 776e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 777e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 77873e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // do not allow renaming any of the special subdirectories 77973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (isStorageSubDirectory(path)) { 78073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED; 78173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 78273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 783e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // now rename the file. make sure this succeeds before updating database 784e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood File oldFile = new File(path); 785e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood int lastSlash = path.lastIndexOf('/'); 786e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (lastSlash <= 1) { 787e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 788e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 789e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood String newPath = path.substring(0, lastSlash + 1) + newName; 790e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood File newFile = new File(newPath); 791e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood boolean success = oldFile.renameTo(newFile); 792e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (!success) { 793f26a586c86b097f975e26fe526ead564ad011bd0Mike Lockwood Log.w(TAG, "renaming "+ path + " to " + newPath + " failed"); 794e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 795e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 796e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 797e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // finally update database 798e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood ContentValues values = new ContentValues(); 799e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood values.put(Files.FileColumns.DATA, newPath); 800e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood int updated = 0; 801e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood try { 802e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // note - we are relying on a special case in MediaProvider.update() to update 803e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // the paths for all children in the case where this is a directory. 80460cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey updated = mMediaProvider.update(mObjectsUri, values, ID_WHERE, whereArgs); 805e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } catch (RemoteException e) { 806e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood Log.e(TAG, "RemoteException in mMediaProvider.update", e); 807e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 808e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood if (updated == 0) { 809e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood Log.e(TAG, "Unable to update path for " + path + " to " + newPath); 810e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood // this shouldn't happen, but if it does we need to rename the file to its original name 811e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood newFile.renameTo(oldFile); 812e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 813e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood } 814e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood 815ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen // check if nomedia status changed 816ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen if (newFile.isDirectory()) { 817ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen // for directories, check if renamed from something hidden to something non-hidden 818ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen if (oldFile.getName().startsWith(".") && !newPath.startsWith(".")) { 819ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen // directory was unhidden 820ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen try { 82160cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mMediaProvider.call(MediaStore.UNHIDE_CALL, newPath, null); 822ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } catch (RemoteException e) { 823ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen Log.e(TAG, "failed to unhide/rescan for " + newPath); 824ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } 825ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } 826ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } else { 827ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen // for files, check if renamed from .nomedia to something else 828ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen if (oldFile.getName().toLowerCase(Locale.US).equals(".nomedia") 829ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen && !newPath.toLowerCase(Locale.US).equals(".nomedia")) { 830ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen try { 83160cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mMediaProvider.call(MediaStore.UNHIDE_CALL, oldFile.getParent(), null); 832ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } catch (RemoteException e) { 833ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen Log.e(TAG, "failed to unhide/rescan for " + newPath); 834ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } 835ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } 836ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } 837ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen 838e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood return MtpConstants.RESPONSE_OK; 839d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 840d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 84159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int setObjectProperty(int handle, int property, 84259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood long intValue, String stringValue) { 8435ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood switch (property) { 8445ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood case MtpConstants.PROPERTY_OBJECT_FILE_NAME: 8455ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood return renameFile(handle, stringValue); 8465ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood 8475ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood default: 8485ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood return MtpConstants.RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 8495ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood } 85059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 85159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 85259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int getDeviceProperty(int property, long[] outIntValue, char[] outStringValue) { 85359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood switch (property) { 85459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER: 85559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME: 856775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // writable string properties kept in shared preferences 857775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood String value = mDeviceProperties.getString(Integer.toString(property), ""); 858775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood int length = value.length(); 859775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood if (length > 255) { 860775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood length = 255; 86159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 862775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood value.getChars(0, length, outStringValue, 0); 863775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood outStringValue[length] = 0; 864775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood return MtpConstants.RESPONSE_OK; 86559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 866ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood case MtpConstants.DEVICE_PROPERTY_IMAGE_SIZE: 867ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood // use screen size as max image size 868ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood Display display = ((WindowManager)mContext.getSystemService( 869ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood Context.WINDOW_SERVICE)).getDefaultDisplay(); 87044bc17c6b517aef35a390c81b5aa79c4f284f744Dianne Hackborn int width = display.getMaximumSizeDimension(); 87144bc17c6b517aef35a390c81b5aa79c4f284f744Dianne Hackborn int height = display.getMaximumSizeDimension(); 872ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood String imageSize = Integer.toString(width) + "x" + Integer.toString(height); 873ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood imageSize.getChars(0, imageSize.length(), outStringValue, 0); 874ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood outStringValue[imageSize.length()] = 0; 875ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood return MtpConstants.RESPONSE_OK; 876ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood 87713bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhang case MtpConstants.DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE: 87813bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhang outIntValue[0] = mDeviceType; 87913bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhang return MtpConstants.RESPONSE_OK; 88013bb2f4ddadcfee8e82a0eea3cb76a2448bb2ccbJerry Zhang 88156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood // DEVICE_PROPERTY_BATTERY_LEVEL is implemented in the JNI code 88256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood 883ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood default: 884ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 885ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood } 88659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 88759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 88859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood private int setDeviceProperty(int property, long intValue, String stringValue) { 88959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood switch (property) { 89059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER: 89159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood case MtpConstants.DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME: 892775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood // writable string properties kept in shared prefs 893775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood SharedPreferences.Editor e = mDeviceProperties.edit(); 894775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood e.putString(Integer.toString(property), stringValue); 895775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood return (e.commit() ? MtpConstants.RESPONSE_OK 896775de951a8d4f4fe58c849efd9ef7b92c4ade907Mike Lockwood : MtpConstants.RESPONSE_GENERAL_ERROR); 89759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 89859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 89959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood return MtpConstants.RESPONSE_DEVICE_PROP_NOT_SUPPORTED; 90059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood } 90159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood 902d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private boolean getObjectInfo(int handle, int[] outStorageFormatParent, 9031341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood char[] outName, long[] outCreatedModified) { 904d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 905d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 90660cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, 90775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown ID_WHERE, new String[] { Integer.toString(handle) }, null, null); 908d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 909b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood outStorageFormatParent[0] = c.getInt(1); 910d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[1] = c.getInt(2); 911d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[2] = c.getInt(3); 912d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 913d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // extract name from path 914b239b683765f63d79e74b8ba2a8cc2855f236536Mike Lockwood String path = c.getString(4); 915d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int lastSlash = path.lastIndexOf('/'); 916d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int start = (lastSlash >= 0 ? lastSlash + 1 : 0); 917d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int end = path.length(); 918d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (end - start > 255) { 919d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood end = start + 255; 920d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 921d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(start, end, outName, 0); 922d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outName[end - start] = 0; 923d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 9241341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood outCreatedModified[0] = c.getLong(5); 9251341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood outCreatedModified[1] = c.getLong(6); 9261341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood // use modification date as creation date if date added is not set 9271341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood if (outCreatedModified[0] == 0) { 9281341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood outCreatedModified[0] = outCreatedModified[1]; 9291341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood } 930d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return true; 931d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 932d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 9332b5f9ad1eaf0d6daaca5cf3761434a09309902bbMike Lockwood Log.e(TAG, "RemoteException in getObjectInfo", e); 934d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 935d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 936d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 937d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 938d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 939d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return false; 940d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 941d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 942365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLengthFormat) { 94301788562f26f213f63c14483fd3977e23b8314abMike Lockwood if (handle == 0) { 94401788562f26f213f63c14483fd3977e23b8314abMike Lockwood // special case root directory 94501788562f26f213f63c14483fd3977e23b8314abMike Lockwood mMediaStoragePath.getChars(0, mMediaStoragePath.length(), outFilePath, 0); 94601788562f26f213f63c14483fd3977e23b8314abMike Lockwood outFilePath[mMediaStoragePath.length()] = 0; 947365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood outFileLengthFormat[0] = 0; 948365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood outFileLengthFormat[1] = MtpConstants.FORMAT_ASSOCIATION; 94901788562f26f213f63c14483fd3977e23b8314abMike Lockwood return MtpConstants.RESPONSE_OK; 95001788562f26f213f63c14483fd3977e23b8314abMike Lockwood } 951d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 952d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 95360cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey c = mMediaProvider.query(mObjectsUri, PATH_FORMAT_PROJECTION, 95475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown ID_WHERE, new String[] { Integer.toString(handle) }, null, null); 955d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 9561c4e88d0b0a8deede0415183739478b5ebc12bfdMike Lockwood String path = c.getString(1); 957d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(0, path.length(), outFilePath, 0); 958d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outFilePath[path.length()] = 0; 959f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood // File transfers from device to host will likely fail if the size is incorrect. 960f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood // So to be safe, use the actual file size here. 961f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood outFileLengthFormat[0] = new File(path).length(); 962f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood outFileLengthFormat[1] = c.getLong(2); 9635367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 96459c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 9655367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 966d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 967d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 968d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectFilePath", e); 9695367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 970d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 971d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 972d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 973d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 974d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 975d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 976d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 97771827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood private int getObjectFormat(int handle) { 97871827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood Cursor c = null; 97971827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood try { 98060cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey c = mMediaProvider.query(mObjectsUri, FORMAT_PROJECTION, 981486ad2e73c1c24c0585d414b18bd623c54ac1547Daichi Hirono ID_WHERE, new String[] { Integer.toString(handle) }, null, null); 98271827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood if (c != null && c.moveToNext()) { 98371827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood return c.getInt(1); 98471827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood } else { 98571827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood return -1; 98671827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood } 98771827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood } catch (RemoteException e) { 98871827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood Log.e(TAG, "RemoteException in getObjectFilePath", e); 98971827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood return -1; 99071827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood } finally { 99171827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood if (c != null) { 99271827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood c.close(); 99371827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood } 99471827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood } 99571827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood } 99671827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood 99759c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood private int deleteFile(int handle) { 9982837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 99955f808cff9913a00164120a422af6ca45db5072bMike Lockwood String path = null; 100055f808cff9913a00164120a422af6ca45db5072bMike Lockwood int format = 0; 100155f808cff9913a00164120a422af6ca45db5072bMike Lockwood 100255f808cff9913a00164120a422af6ca45db5072bMike Lockwood Cursor c = null; 1003d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 100460cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey c = mMediaProvider.query(mObjectsUri, PATH_FORMAT_PROJECTION, 100575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown ID_WHERE, new String[] { Integer.toString(handle) }, null, null); 100655f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (c != null && c.moveToNext()) { 100755f808cff9913a00164120a422af6ca45db5072bMike Lockwood // don't convert to media path here, since we will be matching 100855f808cff9913a00164120a422af6ca45db5072bMike Lockwood // against paths in the database matching /data/media 100955f808cff9913a00164120a422af6ca45db5072bMike Lockwood path = c.getString(1); 1010f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood format = c.getInt(2); 101155f808cff9913a00164120a422af6ca45db5072bMike Lockwood } else { 101255f808cff9913a00164120a422af6ca45db5072bMike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 101355f808cff9913a00164120a422af6ca45db5072bMike Lockwood } 101455f808cff9913a00164120a422af6ca45db5072bMike Lockwood 101555f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (path == null || format == 0) { 101655f808cff9913a00164120a422af6ca45db5072bMike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 101755f808cff9913a00164120a422af6ca45db5072bMike Lockwood } 101855f808cff9913a00164120a422af6ca45db5072bMike Lockwood 101973e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood // do not allow deleting any of the special subdirectories 102073e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood if (isStorageSubDirectory(path)) { 102173e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood return MtpConstants.RESPONSE_OBJECT_WRITE_PROTECTED; 102273e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood } 102373e56d935e7c9b8a06e4781c4995e407e118f93dMike Lockwood 102455f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (format == MtpConstants.FORMAT_ASSOCIATION) { 102555f808cff9913a00164120a422af6ca45db5072bMike Lockwood // recursive case - delete all children first 102655f808cff9913a00164120a422af6ca45db5072bMike Lockwood Uri uri = Files.getMtpObjectsUri(mVolumeName); 102760cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey int count = mMediaProvider.delete(uri, 10281e855d98aa979b30cee9e096cf6a1cb54df0367bMike Lockwood // the 'like' makes it use the index, the 'lower()' makes it correct 10291e855d98aa979b30cee9e096cf6a1cb54df0367bMike Lockwood // when the path contains sqlite wildcard characters 10301e855d98aa979b30cee9e096cf6a1cb54df0367bMike Lockwood "_data LIKE ?1 AND lower(substr(_data,1,?2))=lower(?3)", 10311e855d98aa979b30cee9e096cf6a1cb54df0367bMike Lockwood new String[] { path + "/%",Integer.toString(path.length() + 1), path + "/"}); 103255f808cff9913a00164120a422af6ca45db5072bMike Lockwood } 103355f808cff9913a00164120a422af6ca45db5072bMike Lockwood 103455f808cff9913a00164120a422af6ca45db5072bMike Lockwood Uri uri = Files.getMtpObjectsUri(mVolumeName, handle); 103560cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey if (mMediaProvider.delete(uri, null, null) > 0) { 1036ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen if (format != MtpConstants.FORMAT_ASSOCIATION 1037ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen && path.toLowerCase(Locale.US).endsWith("/.nomedia")) { 1038ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen try { 1039ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen String parentPath = path.substring(0, path.lastIndexOf("/")); 104060cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey mMediaProvider.call(MediaStore.UNHIDE_CALL, parentPath, null); 1041ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } catch (RemoteException e) { 1042ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen Log.e(TAG, "failed to unhide/rescan for " + path); 1043ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } 1044ca78f3d9aff78c35bc065b0c35a0b3c917f56435Marco Nelissen } 10455367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 104659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 10475367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_INVALID_OBJECT_HANDLE; 104859c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } 1049d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 1050d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in deleteFile", e); 10515367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 105255f808cff9913a00164120a422af6ca45db5072bMike Lockwood } finally { 105355f808cff9913a00164120a422af6ca45db5072bMike Lockwood if (c != null) { 105455f808cff9913a00164120a422af6ca45db5072bMike Lockwood c.close(); 105555f808cff9913a00164120a422af6ca45db5072bMike Lockwood } 1056d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 1057d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 1058d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 10599a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood private int[] getObjectReferences(int handle) { 10608490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood Uri uri = Files.getMtpReferencesUri(mVolumeName, handle); 10619a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Cursor c = null; 10629a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 106360cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null, null); 10649a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (c == null) { 10659a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return null; 10669a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 10679a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int count = c.getCount(); 10689a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (count > 0) { 10699a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int[] result = new int[count]; 10709a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood for (int i = 0; i < count; i++) { 10719a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c.moveToNext(); 10729a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood result[i] = c.getInt(0); 10739a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 10749a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return result; 10759a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 10769a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 10779a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 10789a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } finally { 10799a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (c != null) { 10809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c.close(); 10819a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 10829a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 10839a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return null; 10849a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 10859a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 10869a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood private int setObjectReferences(int handle, int[] references) { 10872837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = true; 10888490e66f57506d4e4b05e7c987c7ca34295843e6Mike Lockwood Uri uri = Files.getMtpReferencesUri(mVolumeName, handle); 10899a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int count = references.length; 10909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues[] valuesList = new ContentValues[count]; 10919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood for (int i = 0; i < count; i++) { 10929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues values = new ContentValues(); 10933b2a62e5b35ea5f8da9d9bee52f75c9c2ebb4eceMike Lockwood values.put(Files.FileColumns._ID, references[i]); 10949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood valuesList[i] = values; 10959a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 10969a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 109760cfad80bdf61db436643927337c2fb30186e99dJeff Sharkey if (mMediaProvider.bulkInsert(uri, valuesList) > 0) { 10985367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_OK; 10999a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 11009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 11019a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in setObjectReferences", e); 11029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 11035367ab6aab2a61aaf534b18576dcdd0bca1b9681Mike Lockwood return MtpConstants.RESPONSE_GENERAL_ERROR; 11049a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 11059a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 11062837eefc5459427138c080d445bb491c75630163Mike Lockwood private void sessionStarted() { 11072837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = false; 11082837eefc5459427138c080d445bb491c75630163Mike Lockwood } 11092837eefc5459427138c080d445bb491c75630163Mike Lockwood 11102837eefc5459427138c080d445bb491c75630163Mike Lockwood private void sessionEnded() { 11112837eefc5459427138c080d445bb491c75630163Mike Lockwood if (mDatabaseModified) { 1112a31560598af25d5116effc2a6af0d9be12a0628dMike Lockwood mContext.sendBroadcast(new Intent(MediaStore.ACTION_MTP_SESSION_END)); 11132837eefc5459427138c080d445bb491c75630163Mike Lockwood mDatabaseModified = false; 11142837eefc5459427138c080d445bb491c75630163Mike Lockwood } 11152837eefc5459427138c080d445bb491c75630163Mike Lockwood } 11162837eefc5459427138c080d445bb491c75630163Mike Lockwood 1117d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // used by the JNI code 1118e2e59326f13cf291bf5b37989390fd2a55a94f0cAshok Bhat private long mNativeContext; 1119d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 1120d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_setup(); 1121d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_finalize(); 1122d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood} 1123