blob: 4ef3a9ff8a77c1ef527f7431240a0435a4cbd5cf [file] [log] [blame]
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "MtpDatabaseJNI"
18#include "utils/Log.h"
19
20#include <stdio.h>
21#include <assert.h>
22#include <limits.h>
23#include <unistd.h>
24#include <fcntl.h>
25
26#include "jni.h"
27#include "JNIHelp.h"
28#include "android_runtime/AndroidRuntime.h"
29
30#include "MtpDatabase.h"
31#include "MtpDataPacket.h"
Mike Lockwood828d19d2010-08-10 15:20:35 -040032#include "MtpProperty.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040033#include "MtpUtils.h"
34#include "mtp.h"
35
36using namespace android;
37
38// ----------------------------------------------------------------------------
39
Mike Lockwoodd815f792010-07-12 08:49:01 -040040static jmethodID method_beginSendObject;
41static jmethodID method_endSendObject;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040042static jmethodID method_getObjectList;
Mike Lockwood7a047c82010-08-02 10:52:20 -040043static jmethodID method_getNumObjects;
Mike Lockwood4b322ce2010-08-10 07:37:50 -040044static jmethodID method_getSupportedPlaybackFormats;
45static jmethodID method_getSupportedCaptureFormats;
46static jmethodID method_getSupportedObjectProperties;
47static jmethodID method_getSupportedDeviceProperties;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040048static jmethodID method_getObjectProperty;
Mike Lockwood828d19d2010-08-10 15:20:35 -040049static jmethodID method_setObjectProperty;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040050static jmethodID method_getObjectInfo;
51static jmethodID method_getObjectFilePath;
52static jmethodID method_deleteFile;
Mike Lockwood9a2046f2010-08-03 15:30:09 -040053static jmethodID method_getObjectReferences;
54static jmethodID method_setObjectReferences;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040055static jfieldID field_context;
56
57MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
58 return (MtpDatabase *)env->GetIntField(database, field_context);
59}
60
Mike Lockwoodff164a72010-07-15 15:01:17 -040061#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -040062// ----------------------------------------------------------------------------
63
64class MyMtpDatabase : public MtpDatabase {
65private:
66 jobject mDatabase;
67 jintArray mIntBuffer;
68 jlongArray mLongBuffer;
69 jcharArray mStringBuffer;
70
71public:
72 MyMtpDatabase(JNIEnv *env, jobject client);
73 virtual ~MyMtpDatabase();
74 void cleanup(JNIEnv *env);
75
Mike Lockwoodd815f792010-07-12 08:49:01 -040076 virtual MtpObjectHandle beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -040077 MtpObjectFormat format,
78 MtpObjectHandle parent,
79 MtpStorageID storage,
80 uint64_t size,
81 time_t modified);
82
Mike Lockwoodd815f792010-07-12 08:49:01 -040083 virtual void endSendObject(const char* path,
84 MtpObjectHandle handle,
85 MtpObjectFormat format,
86 bool succeeded);
87
Mike Lockwoodd21eac92010-07-03 00:44:05 -040088 virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
89 MtpObjectFormat format,
90 MtpObjectHandle parent);
91
Mike Lockwood7a047c82010-08-02 10:52:20 -040092 virtual int getNumObjects(MtpStorageID storageID,
93 MtpObjectFormat format,
94 MtpObjectHandle parent);
95
Mike Lockwood4b322ce2010-08-10 07:37:50 -040096 // callee should delete[] the results from these
97 // results can be NULL
98 virtual MtpObjectFormatList* getSupportedPlaybackFormats();
99 virtual MtpObjectFormatList* getSupportedCaptureFormats();
100 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
101 virtual MtpDevicePropertyList* getSupportedDeviceProperties();
102
Mike Lockwood828d19d2010-08-10 15:20:35 -0400103 virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400104 MtpObjectProperty property,
105 MtpDataPacket& packet);
106
Mike Lockwood828d19d2010-08-10 15:20:35 -0400107 virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
108 MtpObjectProperty property,
109 MtpDataPacket& packet);
110
111 virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
112 MtpDataPacket& packet);
113
114 virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
115 MtpDataPacket& packet);
116
117 virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
118
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400119 virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
120 MtpDataPacket& packet);
121
Mike Lockwood59c777a2010-08-02 10:37:41 -0400122 virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400123 MtpString& filePath,
124 int64_t& fileLength);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400125 virtual MtpResponseCode deleteFile(MtpObjectHandle handle);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400126
127 bool getPropertyInfo(MtpObjectProperty property, int& type);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400128
129 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
130
131 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
132 MtpObjectHandleList* references);
Mike Lockwood828d19d2010-08-10 15:20:35 -0400133
134 virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
135 MtpObjectFormat format);
136
137 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400138};
139
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400140// ----------------------------------------------------------------------------
141
142static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
143 if (env->ExceptionCheck()) {
144 LOGE("An exception was thrown by callback '%s'.", methodName);
145 LOGE_EX(env);
146 env->ExceptionClear();
147 }
148}
149
150// ----------------------------------------------------------------------------
151
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400152MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
153 : mDatabase(env->NewGlobalRef(client)),
154 mIntBuffer(NULL),
155 mLongBuffer(NULL),
156 mStringBuffer(NULL)
157{
158 jintArray intArray;
159 jlongArray longArray;
160 jcharArray charArray;
161
162 // create buffers for out arguments
163 // we don't need to be thread-safe so this is OK
164 intArray = env->NewIntArray(3);
165 if (!intArray)
166 goto out_of_memory;
167 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
168 longArray = env->NewLongArray(2);
169 if (!longArray)
170 goto out_of_memory;
171 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
172 charArray = env->NewCharArray(256);
173 if (!charArray)
174 goto out_of_memory;
175 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
176 return;
177
178out_of_memory:
179 env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), NULL);
180}
181
182void MyMtpDatabase::cleanup(JNIEnv *env) {
183 env->DeleteGlobalRef(mDatabase);
184 env->DeleteGlobalRef(mIntBuffer);
185 env->DeleteGlobalRef(mLongBuffer);
186 env->DeleteGlobalRef(mStringBuffer);
187}
188
189MyMtpDatabase::~MyMtpDatabase() {
190}
191
Mike Lockwoodd815f792010-07-12 08:49:01 -0400192MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400193 MtpObjectFormat format,
194 MtpObjectHandle parent,
195 MtpStorageID storage,
196 uint64_t size,
197 time_t modified) {
198 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400199 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
200 env->NewStringUTF(path), (jint)format, (jint)parent, (jint)storage,
201 (jlong)size, (jlong)modified);
202
203 checkAndClearExceptionFromCallback(env, __FUNCTION__);
204 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400205}
206
Mike Lockwoodd815f792010-07-12 08:49:01 -0400207void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
208 MtpObjectFormat format, bool succeeded) {
209 JNIEnv* env = AndroidRuntime::getJNIEnv();
210 env->CallVoidMethod(mDatabase, method_endSendObject, env->NewStringUTF(path),
211 (jint)handle, (jint)format, (jboolean)succeeded);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400212
213 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400214}
215
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400216MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
217 MtpObjectFormat format,
218 MtpObjectHandle parent) {
219 JNIEnv* env = AndroidRuntime::getJNIEnv();
220 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
221 (jint)storageID, (jint)format, (jint)parent);
222 if (!array)
223 return NULL;
224 MtpObjectHandleList* list = new MtpObjectHandleList();
225 jint* handles = env->GetIntArrayElements(array, 0);
226 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400227 for (int i = 0; i < length; i++)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400228 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400229 env->ReleaseIntArrayElements(array, handles, 0);
230
231 checkAndClearExceptionFromCallback(env, __FUNCTION__);
232 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400233}
234
Mike Lockwood7a047c82010-08-02 10:52:20 -0400235int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
236 MtpObjectFormat format,
237 MtpObjectHandle parent) {
238 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400239 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400240 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400241
242 checkAndClearExceptionFromCallback(env, __FUNCTION__);
243 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400244}
245
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400246MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
247 JNIEnv* env = AndroidRuntime::getJNIEnv();
248 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
249 method_getSupportedPlaybackFormats);
250 if (!array)
251 return NULL;
252 MtpObjectFormatList* list = new MtpObjectFormatList();
253 jint* formats = env->GetIntArrayElements(array, 0);
254 jsize length = env->GetArrayLength(array);
255 for (int i = 0; i < length; i++)
256 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400257 env->ReleaseIntArrayElements(array, formats, 0);
258
259 checkAndClearExceptionFromCallback(env, __FUNCTION__);
260 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400261}
262
263MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
264 JNIEnv* env = AndroidRuntime::getJNIEnv();
265 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
266 method_getSupportedCaptureFormats);
267 if (!array)
268 return NULL;
269 MtpObjectFormatList* list = new MtpObjectFormatList();
270 jint* formats = env->GetIntArrayElements(array, 0);
271 jsize length = env->GetArrayLength(array);
272 for (int i = 0; i < length; i++)
273 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400274 env->ReleaseIntArrayElements(array, formats, 0);
275
276 checkAndClearExceptionFromCallback(env, __FUNCTION__);
277 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400278}
279
280MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
281 JNIEnv* env = AndroidRuntime::getJNIEnv();
282 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
283 method_getSupportedObjectProperties, (jint)format);
284 if (!array)
285 return NULL;
286 MtpObjectPropertyList* list = new MtpObjectPropertyList();
287 jint* properties = env->GetIntArrayElements(array, 0);
288 jsize length = env->GetArrayLength(array);
289 for (int i = 0; i < length; i++)
290 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400291 env->ReleaseIntArrayElements(array, properties, 0);
292
293 checkAndClearExceptionFromCallback(env, __FUNCTION__);
294 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400295}
296
297MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
298 JNIEnv* env = AndroidRuntime::getJNIEnv();
299 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
300 method_getSupportedDeviceProperties);
301 if (!array)
302 return NULL;
303 MtpDevicePropertyList* list = new MtpDevicePropertyList();
304 jint* properties = env->GetIntArrayElements(array, 0);
305 jsize length = env->GetArrayLength(array);
306 for (int i = 0; i < length; i++)
307 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400308 env->ReleaseIntArrayElements(array, properties, 0);
309
310 checkAndClearExceptionFromCallback(env, __FUNCTION__);
311 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400312}
313
Mike Lockwood828d19d2010-08-10 15:20:35 -0400314MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400315 MtpObjectProperty property,
316 MtpDataPacket& packet) {
317 int type;
318
319 if (!getPropertyInfo(property, type))
320 return MTP_RESPONSE_INVALID_OBJECT_PROP_CODE;
321
322 JNIEnv* env = AndroidRuntime::getJNIEnv();
323 jint result = env->CallIntMethod(mDatabase, method_getObjectProperty,
324 (jint)handle, (jint)property, mLongBuffer, mStringBuffer);
325 if (result != MTP_RESPONSE_OK)
326 return result;
327
328 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
329 jlong longValue = longValues[0];
330 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
331
Mike Lockwood828d19d2010-08-10 15:20:35 -0400332 // special case MTP_PROPERTY_DATE_MODIFIED, which is a string to MTP
333 // but stored internally as a uint64
334 if (property == MTP_PROPERTY_DATE_MODIFIED) {
335 char date[20];
336 formatDateTime(longValue, date, sizeof(date));
337 packet.putString(date);
338 return MTP_RESPONSE_OK;
339 }
340
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400341 switch (type) {
342 case MTP_TYPE_INT8:
343 packet.putInt8(longValue);
344 break;
345 case MTP_TYPE_UINT8:
346 packet.putUInt8(longValue);
347 break;
348 case MTP_TYPE_INT16:
349 packet.putInt16(longValue);
350 break;
351 case MTP_TYPE_UINT16:
352 packet.putUInt16(longValue);
353 break;
354 case MTP_TYPE_INT32:
355 packet.putInt32(longValue);
356 break;
357 case MTP_TYPE_UINT32:
358 packet.putUInt32(longValue);
359 break;
360 case MTP_TYPE_INT64:
361 packet.putInt64(longValue);
362 break;
363 case MTP_TYPE_UINT64:
364 packet.putUInt64(longValue);
365 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400366 case MTP_TYPE_INT128:
367 packet.putInt128(longValue);
368 break;
369 case MTP_TYPE_UINT128:
370 packet.putInt128(longValue);
371 break;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400372 case MTP_TYPE_STR:
373 {
374 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
375 packet.putString(str);
376 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
377 break;
378 }
379 default:
380 LOGE("unsupported object type\n");
381 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
382 }
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400383
384 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400385 return MTP_RESPONSE_OK;
386}
387
Mike Lockwood828d19d2010-08-10 15:20:35 -0400388MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
389 MtpObjectProperty property,
390 MtpDataPacket& packet) {
391 return -1;
392}
393
394MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
395 MtpDataPacket& packet) {
396 return -1;
397}
398
399MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
400 MtpDataPacket& packet) {
401 return -1;
402}
403
404MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
405 return -1;
406}
407
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400408MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
409 MtpDataPacket& packet) {
410 char date[20];
411
412 JNIEnv* env = AndroidRuntime::getJNIEnv();
413 jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
414 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
415 if (!result)
416 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
417
418 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
419 MtpStorageID storageID = intValues[0];
420 MtpObjectFormat format = intValues[1];
421 MtpObjectHandle parent = intValues[2];
422 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
423
424 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
425 uint64_t size = longValues[0];
426 uint64_t modified = longValues[1];
427 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
428
Mike Lockwood828d19d2010-08-10 15:20:35 -0400429// int associationType = (format == MTP_FORMAT_ASSOCIATION ?
430// MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
431// MTP_ASSOCIATION_TYPE_UNDEFINED);
432 int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400433
434 packet.putUInt32(storageID);
435 packet.putUInt16(format);
436 packet.putUInt16(0); // protection status
437 packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
438 packet.putUInt16(0); // thumb format
439 packet.putUInt32(0); // thumb compressed size
440 packet.putUInt32(0); // thumb pix width
441 packet.putUInt32(0); // thumb pix height
442 packet.putUInt32(0); // image pix width
443 packet.putUInt32(0); // image pix height
444 packet.putUInt32(0); // image bit depth
445 packet.putUInt32(parent);
446 packet.putUInt16(associationType);
447 packet.putUInt32(0); // association desc
448 packet.putUInt32(0); // sequence number
449
450 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
451 packet.putString(str); // file name
452 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
453
454 packet.putEmptyString();
455 formatDateTime(modified, date, sizeof(date));
456 packet.putString(date); // date modified
457 packet.putEmptyString(); // keywords
458
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400459 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400460 return MTP_RESPONSE_OK;
461}
462
Mike Lockwood59c777a2010-08-02 10:37:41 -0400463MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400464 MtpString& filePath,
465 int64_t& fileLength) {
466 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400467 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400468 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400469 if (result != MTP_RESPONSE_OK)
470 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400471
472 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
473 filePath.setTo(str, strlen16(str));
474 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
475
476 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
477 fileLength = longValues[0];
478 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
479
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400480 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400481 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400482}
483
Mike Lockwood59c777a2010-08-02 10:37:41 -0400484MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400485 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400486 MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
487
488 checkAndClearExceptionFromCallback(env, __FUNCTION__);
489 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400490}
491
492struct PropertyTableEntry {
493 MtpObjectProperty property;
494 int type;
495};
496
497static const PropertyTableEntry kPropertyTable[] = {
498 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
499 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
Mike Lockwoodc642e8a2010-08-09 14:17:52 -0400500 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400501 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
502 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
503 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
504};
505
506bool MyMtpDatabase::getPropertyInfo(MtpObjectProperty property, int& type) {
507 int count = sizeof(kPropertyTable) / sizeof(kPropertyTable[0]);
508 const PropertyTableEntry* entry = kPropertyTable;
509 for (int i = 0; i < count; i++, entry++) {
510 if (entry->property == property) {
511 type = entry->type;
512 return true;
513 }
514 }
515 return false;
516}
517
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400518MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
519 JNIEnv* env = AndroidRuntime::getJNIEnv();
520 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
521 (jint)handle);
522 if (!array)
523 return NULL;
524 MtpObjectHandleList* list = new MtpObjectHandleList();
525 jint* handles = env->GetIntArrayElements(array, 0);
526 jsize length = env->GetArrayLength(array);
527 for (int i = 0; i < length; i++)
528 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400529 env->ReleaseIntArrayElements(array, handles, 0);
530
531 checkAndClearExceptionFromCallback(env, __FUNCTION__);
532 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400533}
534
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400535MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
536 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400537 JNIEnv* env = AndroidRuntime::getJNIEnv();
538 int count = references->size();
539 jintArray array = env->NewIntArray(count);
540 if (!array) {
541 LOGE("out of memory in setObjectReferences");
542 return false;
543 }
544 jint* handles = env->GetIntArrayElements(array, 0);
545 for (int i = 0; i < count; i++)
546 handles[i] = (*references)[i];
547 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400548 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400549 (jint)handle, array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400550
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400551 checkAndClearExceptionFromCallback(env, __FUNCTION__);
552 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400553}
554
Mike Lockwood828d19d2010-08-10 15:20:35 -0400555MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
556 MtpObjectFormat format) {
557 MtpProperty* result = NULL;
558 switch (property) {
559 case MTP_PROPERTY_OBJECT_FORMAT:
560 case MTP_PROPERTY_PROTECTION_STATUS:
561 result = new MtpProperty(property, MTP_TYPE_UINT16);
562 break;
563 case MTP_PROPERTY_STORAGE_ID:
564 case MTP_PROPERTY_PARENT_OBJECT:
565 result = new MtpProperty(property, MTP_TYPE_UINT32);
566 break;
567 case MTP_PROPERTY_OBJECT_SIZE:
568 result = new MtpProperty(property, MTP_TYPE_UINT64);
569 break;
570 case MTP_PROPERTY_PERSISTENT_UID:
571 result = new MtpProperty(property, MTP_TYPE_UINT128);
572 break;
573 case MTP_PROPERTY_OBJECT_FILE_NAME:
574 case MTP_PROPERTY_DATE_MODIFIED:
575 result = new MtpProperty(property, MTP_TYPE_STR);
576 break;
577 }
578
579 return result;
580}
581
582MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
583 return NULL;
584}
585
Mike Lockwoodff164a72010-07-15 15:01:17 -0400586#endif // HAVE_ANDROID_OS
587
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400588// ----------------------------------------------------------------------------
589
590static void
591android_media_MtpDatabase_setup(JNIEnv *env, jobject thiz)
592{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400593#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400594 LOGD("setup\n");
595 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
596 env->SetIntField(thiz, field_context, (int)database);
597 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400598#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400599}
600
601static void
602android_media_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
603{
Mike Lockwoodff164a72010-07-15 15:01:17 -0400604#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400605 LOGD("finalize\n");
606 MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
607 database->cleanup(env);
608 delete database;
609 env->SetIntField(thiz, field_context, 0);
610 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -0400611#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400612}
613
614// ----------------------------------------------------------------------------
615
616static JNINativeMethod gMethods[] = {
617 {"native_setup", "()V", (void *)android_media_MtpDatabase_setup},
618 {"native_finalize", "()V", (void *)android_media_MtpDatabase_finalize},
619};
620
621static const char* const kClassPathName = "android/media/MtpDatabase";
622
623int register_android_media_MtpDatabase(JNIEnv *env)
624{
625 jclass clazz;
626
627 LOGD("register_android_media_MtpDatabase\n");
628
629 clazz = env->FindClass("android/media/MtpDatabase");
630 if (clazz == NULL) {
631 LOGE("Can't find android/media/MtpDatabase");
632 return -1;
633 }
Mike Lockwoodd815f792010-07-12 08:49:01 -0400634 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
635 if (method_beginSendObject == NULL) {
636 LOGE("Can't find beginSendObject");
637 return -1;
638 }
639 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
640 if (method_endSendObject == NULL) {
641 LOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400642 return -1;
643 }
644 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
645 if (method_getObjectList == NULL) {
646 LOGE("Can't find getObjectList");
647 return -1;
648 }
Mike Lockwood7a047c82010-08-02 10:52:20 -0400649 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
650 if (method_getNumObjects == NULL) {
651 LOGE("Can't find getNumObjects");
652 return -1;
653 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400654 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
655 if (method_getSupportedPlaybackFormats == NULL) {
656 LOGE("Can't find getSupportedPlaybackFormats");
657 return -1;
658 }
659 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
660 if (method_getSupportedCaptureFormats == NULL) {
661 LOGE("Can't find getSupportedCaptureFormats");
662 return -1;
663 }
664 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
665 if (method_getSupportedObjectProperties == NULL) {
666 LOGE("Can't find getSupportedObjectProperties");
667 return -1;
668 }
669 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
670 if (method_getSupportedDeviceProperties == NULL) {
671 LOGE("Can't find getSupportedDeviceProperties");
672 return -1;
673 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400674 method_getObjectProperty = env->GetMethodID(clazz, "getObjectProperty", "(II[J[C)I");
675 if (method_getObjectProperty == NULL) {
676 LOGE("Can't find getObjectProperty");
677 return -1;
678 }
679 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
680 if (method_getObjectInfo == NULL) {
681 LOGE("Can't find getObjectInfo");
682 return -1;
683 }
Mike Lockwood59c777a2010-08-02 10:37:41 -0400684 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400685 if (method_getObjectFilePath == NULL) {
686 LOGE("Can't find getObjectFilePath");
687 return -1;
688 }
Mike Lockwood59c777a2010-08-02 10:37:41 -0400689 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400690 if (method_deleteFile == NULL) {
691 LOGE("Can't find deleteFile");
692 return -1;
693 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400694 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
695 if (method_getObjectReferences == NULL) {
696 LOGE("Can't find getObjectReferences");
697 return -1;
698 }
699 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
700 if (method_setObjectReferences == NULL) {
701 LOGE("Can't find setObjectReferences");
702 return -1;
703 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400704 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
705 if (field_context == NULL) {
706 LOGE("Can't find MtpDatabase.mNativeContext");
707 return -1;
708 }
709
710 return AndroidRuntime::registerNativeMethods(env,
711 "android/media/MtpDatabase", gMethods, NELEM(gMethods));
712}