MtpDatabase.java revision 9a2046fb5ceeee4d5334274cbff15f1058bb3244
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 17d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpackage android.media; 18d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 19d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.Context; 20d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodimport android.content.ContentValues; 21d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.content.IContentProvider; 22d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.database.Cursor; 23d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.net.Uri; 24d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.os.RemoteException; 259a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.Audio; 269a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.MediaStore.MediaColumns; 27d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.provider.MediaStore.MtpObjects; 289a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodimport android.provider.Mtp; 29d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodimport android.util.Log; 30d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 31d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/** 32d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * {@hide} 33d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */ 34d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic class MtpDatabase { 35d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 36d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String TAG = "MtpDatabase"; 37d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 38d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final IContentProvider mMediaProvider; 39d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final String mVolumeName; 40d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private final Uri mObjectsUri; 41d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 42b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // FIXME - this should be passed in via the constructor 43b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private final int mStorageID = 0x00010001; 44b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 45d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] ID_PROJECTION = new String[] { 46d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns._ID, // 0 47d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 48d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] PATH_SIZE_PROJECTION = new String[] { 49d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns._ID, // 0 50d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.DATA, // 1 51d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.SIZE, // 2 52d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 53d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String[] OBJECT_INFO_PROJECTION = new String[] { 54d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns._ID, // 0 55d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.DATA, // 1 56d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.FORMAT, // 2 57d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.PARENT, // 3 58d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.SIZE, // 4 59d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood MtpObjects.ObjectColumns.DATE_MODIFIED, // 5 60d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood }; 61d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String ID_WHERE = MtpObjects.ObjectColumns._ID + "=?"; 62d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String PATH_WHERE = MtpObjects.ObjectColumns.DATA + "=?"; 63d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String PARENT_WHERE = MtpObjects.ObjectColumns.PARENT + "=?"; 64d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private static final String PARENT_FORMAT_WHERE = PARENT_WHERE + " AND " 65d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood + MtpObjects.ObjectColumns.FORMAT + "=?"; 66d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 67d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private final MediaScanner mMediaScanner; 68d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 69b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // MTP property codes 70b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_STORAGE_ID = 0xDC01; 71b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_OBJECT_FORMAT = 0xDC02; 72b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_OBJECT_SIZE = 0xDC04; 73b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_OBJECT_FILE_NAME = 0xDC07; 74b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_DATE_MODIFIED = 0xDC09; 75b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_PROPERTY_PARENT_OBJECT = 0xDC0B; 76b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 77b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // MTP response codes 78b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_RESPONSE_OK = 0x2001; 79b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_RESPONSE_GENERAL_ERROR = 0x2002; 80b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_RESPONSE_INVALID_OBJECT_HANDLE = 0x2009; 81b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood private static final int MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED = 0xA80A; 82b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 83d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood static { 84d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood System.loadLibrary("media_jni"); 85d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 86d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 87d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood public MtpDatabase(Context context, String volumeName) { 88d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood native_setup(); 89d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 90d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mMediaProvider = context.getContentResolver().acquireProvider("media"); 91d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mVolumeName = volumeName; 92d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood mObjectsUri = MtpObjects.getContentUri(volumeName); 93d815f79766984fce499e147ecbacc01914683f74Mike Lockwood mMediaScanner = new MediaScanner(context); 94d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 95d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 96d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood @Override 97d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood protected void finalize() { 98d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood native_finalize(); 99d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 100d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 101d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private int beginSendObject(String path, int format, int parent, 102d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int storage, long size, long modified) { 103d815f79766984fce499e147ecbacc01914683f74Mike Lockwood ContentValues values = new ContentValues(); 104d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.DATA, path); 105d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.FORMAT, format); 106d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.PARENT, parent); 107d815f79766984fce499e147ecbacc01914683f74Mike Lockwood // storage is ignored for now 108d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.SIZE, size); 109d815f79766984fce499e147ecbacc01914683f74Mike Lockwood values.put(MtpObjects.ObjectColumns.DATE_MODIFIED, modified); 110d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 111d815f79766984fce499e147ecbacc01914683f74Mike Lockwood try { 112d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Uri uri = mMediaProvider.insert(mObjectsUri, values); 113d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (uri != null) { 114d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return Integer.parseInt(uri.getPathSegments().get(2)); 115d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 116d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 117d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 118d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } catch (RemoteException e) { 119d815f79766984fce499e147ecbacc01914683f74Mike Lockwood Log.e(TAG, "RemoteException in beginSendObject", e); 120d815f79766984fce499e147ecbacc01914683f74Mike Lockwood return -1; 121d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 122d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 123d815f79766984fce499e147ecbacc01914683f74Mike Lockwood 124d815f79766984fce499e147ecbacc01914683f74Mike Lockwood private void endSendObject(String path, int handle, int format, boolean succeeded) { 125d815f79766984fce499e147ecbacc01914683f74Mike Lockwood if (succeeded) { 1269a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // handle abstract playlists separately 1279a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // they do not exist in the file system so don't use the media scanner here 1289a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (format == Mtp.Object.FORMAT_ABSTRACT_AV_PLAYLIST) { 1299a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // Strip Windows Media Player file extension 1309a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (path.endsWith(".pla")) { 1319a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood path = path.substring(0, path.length() - 4); 1329a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 1339a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 1349a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood // extract name from path 1359a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood String name = path; 1369a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int lastSlash = name.lastIndexOf('/'); 1379a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (lastSlash >= 0) { 1389a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood name = name.substring(lastSlash + 1); 1399a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 1409a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 1419a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues values = new ContentValues(1); 1429a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(Audio.Playlists.DATA, path); 1439a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(Audio.Playlists.NAME, name); 1449a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(MediaColumns.MEDIA_SCANNER_NEW_OBJECT_ID, handle); 1459a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 1469a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Uri uri = mMediaProvider.insert(Audio.Playlists.EXTERNAL_CONTENT_URI, values); 1479a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 1489a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in endSendObject", e); 1499a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 1509a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } else { 1519a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Uri uri = mMediaScanner.scanMtpFile(path, mVolumeName, handle, format); 1529a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 153d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } else { 154d815f79766984fce499e147ecbacc01914683f74Mike Lockwood deleteFile(handle); 155d815f79766984fce499e147ecbacc01914683f74Mike Lockwood } 156d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 157d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 158d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int[] getObjectList(int storageID, int format, int parent) { 159d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // we can ignore storageID until we support multiple storages 160d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectList parent: " + parent); 161d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 162d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 163d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (format != 0) { 164d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 165d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood PARENT_FORMAT_WHERE, 166d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood new String[] { Integer.toString(parent), Integer.toString(format) }, 167d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood null); 168d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } else { 169d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 170d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood PARENT_WHERE, new String[] { Integer.toString(parent) }, null); 171d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 172d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c == null) { 173d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "null cursor"); 174d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 175d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 176d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int count = c.getCount(); 177d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (count > 0) { 178d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int[] result = new int[count]; 179d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood for (int i = 0; i < count; i++) { 180d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.moveToNext(); 181d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood result[i] = c.getInt(0); 182d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 183d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "returning " + result); 184d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return result; 185d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 186d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 187d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 188d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 189d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 190d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 191d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 192d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 193d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return null; 194d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 195d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 1967a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood private int getNumObjects(int storageID, int format, int parent) { 1977a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood // we can ignore storageID until we support multiple storages 1987a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Log.d(TAG, "getObjectList parent: " + parent); 1997a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Cursor c = null; 2007a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood try { 2017a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (format != 0) { 2027a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 2037a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood PARENT_FORMAT_WHERE, 2047a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood new String[] { Integer.toString(parent), Integer.toString(format) }, 2057a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood null); 2067a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } else { 2077a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c = mMediaProvider.query(mObjectsUri, ID_PROJECTION, 2087a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood PARENT_WHERE, new String[] { Integer.toString(parent) }, null); 2097a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2107a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 2117a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return c.getCount(); 2127a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2137a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } catch (RemoteException e) { 2147a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood Log.e(TAG, "RemoteException in getNumObjects", e); 2157a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } finally { 2167a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood if (c != null) { 2177a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood c.close(); 2187a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2197a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2207a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood return -1; 2217a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood } 2227a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood 223d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int getObjectProperty(int handle, int property, 224d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood long[] outIntValue, char[] outStringValue) { 225d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectProperty: " + property); 226b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood String column = null; 227b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood boolean isString = false; 228b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 229b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood switch (property) { 230b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_STORAGE_ID: 231b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outIntValue[0] = mStorageID; 232b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_OK; 233b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_OBJECT_FORMAT: 234b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.FORMAT; 235b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 236b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_OBJECT_SIZE: 237b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.SIZE; 238b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 239b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_OBJECT_FILE_NAME: 240b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.DATA; 241b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood isString = true; 242b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 243b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_DATE_MODIFIED: 244b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.DATE_MODIFIED; 245b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 246b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood case MTP_PROPERTY_PARENT_OBJECT: 247b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood column = MtpObjects.ObjectColumns.PARENT; 248b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood break; 249b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood default: 250b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED; 251b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 252b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 253b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood Cursor c = null; 254b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood try { 255b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // for now we are only reading properties from the "objects" table 256b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood c = mMediaProvider.query(mObjectsUri, 257b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood new String [] { MtpObjects.ObjectColumns._ID, column }, 258b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 259b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (c != null && c.moveToNext()) { 260b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (isString) { 261b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood String value = c.getString(1); 262b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int start = 0; 263b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood 264b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (property == MTP_PROPERTY_OBJECT_FILE_NAME) { 265b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // extract name from full path 266b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int lastSlash = value.lastIndexOf('/'); 267b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (lastSlash >= 0) { 268b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood start = lastSlash + 1; 269b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 270b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 271b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood int end = value.length(); 272b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (end - start > 255) { 273b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood end = start + 255; 274b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 275b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood value.getChars(start, end, outStringValue, 0); 276b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outStringValue[end - start] = 0; 277b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } else { 278b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outIntValue[0] = c.getLong(1); 279b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 280b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_OK; 281b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 282b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } catch (Exception e) { 283b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 284b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } finally { 285b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood if (c != null) { 286b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood c.close(); 287b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 288b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood } 289b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood // query failed if we get here 290b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 291d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 292d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 293d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private boolean getObjectInfo(int handle, int[] outStorageFormatParent, 294d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood char[] outName, long[] outSizeModified) { 295d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectInfo: " + handle); 296d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 297d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 298d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, OBJECT_INFO_PROJECTION, 299d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 300d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 301b2cada9034436b4ea4bac218da7a1e29460d15b2Mike Lockwood outStorageFormatParent[0] = mStorageID; 302d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[1] = c.getInt(2); 303d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outStorageFormatParent[2] = c.getInt(3); 304d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 305d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // extract name from path 306d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood String path = c.getString(1); 307d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int lastSlash = path.lastIndexOf('/'); 308d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int start = (lastSlash >= 0 ? lastSlash + 1 : 0); 309d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood int end = path.length(); 310d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (end - start > 255) { 311d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood end = start + 255; 312d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 313d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(start, end, outName, 0); 314d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outName[end - start] = 0; 315d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 316d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outSizeModified[0] = c.getLong(4); 317d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outSizeModified[1] = c.getLong(5); 318d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return true; 319d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 320d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 321d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectProperty", e); 322d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 323d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 324d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 325d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 326d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 327d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood return false; 328d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 329d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 33059c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood private int getObjectFilePath(int handle, char[] outFilePath, long[] outFileLength) { 331d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "getObjectFilePath: " + handle); 332d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Cursor c = null; 333d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 334d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c = mMediaProvider.query(mObjectsUri, PATH_SIZE_PROJECTION, 335d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood ID_WHERE, new String[] { Integer.toString(handle) }, null); 336d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null && c.moveToNext()) { 337d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood String path = c.getString(1); 338d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood path.getChars(0, path.length(), outFilePath, 0); 339d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outFilePath[path.length()] = 0; 340d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood outFileLength[0] = c.getLong(2); 34159c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_OK; 34259c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 34359c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 344d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 345d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 346d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in getObjectFilePath", e); 34759c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 348d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } finally { 349d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood if (c != null) { 350d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood c.close(); 351d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 352d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 353d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 354d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 35559c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood private int deleteFile(int handle) { 356d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.d(TAG, "deleteFile: " + handle); 357d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Uri uri = MtpObjects.getContentUri(mVolumeName, handle); 358d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood try { 35959c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood if (mMediaProvider.delete(uri, null, null) == 1) { 36059c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_OK; 36159c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } else { 36259c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_INVALID_OBJECT_HANDLE; 36359c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood } 364d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } catch (RemoteException e) { 365d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood Log.e(TAG, "RemoteException in deleteFile", e); 36659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 367d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 368d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood } 369d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 3709a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood private int[] getObjectReferences(int handle) { 3719a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.d(TAG, "getObjectReferences for: " + handle); 3729a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Uri uri = MtpObjects.getReferencesUri(mVolumeName, handle); 3739a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Cursor c = null; 3749a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 3759a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c = mMediaProvider.query(uri, ID_PROJECTION, null, null, null); 3769a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (c == null) { 3779a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return null; 3789a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 3799a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int count = c.getCount(); 3809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (count > 0) { 3819a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int[] result = new int[count]; 3829a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood for (int i = 0; i < count; i++) { 3839a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c.moveToNext(); 3849a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood result[i] = c.getInt(0); 3859a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 3869a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return result; 3879a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 3889a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 3899a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in getObjectList", e); 3909a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } finally { 3919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (c != null) { 3929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood c.close(); 3939a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 3949a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 3959a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return null; 3969a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 3979a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 3989a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood private int setObjectReferences(int handle, int[] references) { 3999a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Uri uri = MtpObjects.getReferencesUri(mVolumeName, handle); 4009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood int count = references.length; 4019a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues[] valuesList = new ContentValues[count]; 4029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood for (int i = 0; i < count; i++) { 4039a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood ContentValues values = new ContentValues(); 4049a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood values.put(MtpObjects.ObjectColumns._ID, references[i]); 4059a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood valuesList[i] = values; 4069a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 4079a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood try { 4089a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood if (count == mMediaProvider.bulkInsert(uri, valuesList)) { 4099a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return MTP_RESPONSE_OK; 4109a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 4119a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } catch (RemoteException e) { 4129a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood Log.e(TAG, "RemoteException in setObjectReferences", e); 4139a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 4149a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood return MTP_RESPONSE_GENERAL_ERROR; 4159a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood } 4169a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood 417d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood // used by the JNI code 418d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private int mNativeContext; 419d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood 420d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_setup(); 421d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood private native final void native_finalize(); 422d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood} 423