blob: 8f9b8a2b0c6e4830fe9b26b9091844ed10683c14 [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 Lockwood59e3f0d2010-09-02 14:57:30 -040033#include "MtpStringBuffer.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040034#include "MtpUtils.h"
35#include "mtp.h"
36
37using namespace android;
38
39// ----------------------------------------------------------------------------
40
Mike Lockwoodd815f792010-07-12 08:49:01 -040041static jmethodID method_beginSendObject;
42static jmethodID method_endSendObject;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040043static jmethodID method_getObjectList;
Mike Lockwood7a047c82010-08-02 10:52:20 -040044static jmethodID method_getNumObjects;
Mike Lockwood4b322ce2010-08-10 07:37:50 -040045static jmethodID method_getSupportedPlaybackFormats;
46static jmethodID method_getSupportedCaptureFormats;
47static jmethodID method_getSupportedObjectProperties;
48static jmethodID method_getSupportedDeviceProperties;
Mike Lockwood828d19d2010-08-10 15:20:35 -040049static jmethodID method_setObjectProperty;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -040050static jmethodID method_getDeviceProperty;
51static jmethodID method_setDeviceProperty;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040052static jmethodID method_getObjectPropertyList;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040053static jmethodID method_getObjectInfo;
54static jmethodID method_getObjectFilePath;
55static jmethodID method_deleteFile;
Mike Lockwood9a2046f2010-08-03 15:30:09 -040056static jmethodID method_getObjectReferences;
57static jmethodID method_setObjectReferences;
Mike Lockwood2837eef2010-08-31 16:25:12 -040058static jmethodID method_sessionStarted;
59static jmethodID method_sessionEnded;
60
Mike Lockwoodd21eac92010-07-03 00:44:05 -040061static jfieldID field_context;
62
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040063// MtpPropertyList fields
64static jfieldID field_mCount;
65static jfieldID field_mResult;
66static jfieldID field_mObjectHandles;
67static jfieldID field_mPropertyCodes;
68static jfieldID field_mDataTypes;
69static jfieldID field_mLongValues;
70static jfieldID field_mStringValues;
71
72
Mike Lockwoodd21eac92010-07-03 00:44:05 -040073MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
74 return (MtpDatabase *)env->GetIntField(database, field_context);
75}
76
Mike Lockwoodff164a72010-07-15 15:01:17 -040077#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -040078// ----------------------------------------------------------------------------
79
80class MyMtpDatabase : public MtpDatabase {
81private:
82 jobject mDatabase;
83 jintArray mIntBuffer;
84 jlongArray mLongBuffer;
85 jcharArray mStringBuffer;
86
87public:
88 MyMtpDatabase(JNIEnv *env, jobject client);
89 virtual ~MyMtpDatabase();
90 void cleanup(JNIEnv *env);
91
Mike Lockwoodd815f792010-07-12 08:49:01 -040092 virtual MtpObjectHandle beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -040093 MtpObjectFormat format,
94 MtpObjectHandle parent,
95 MtpStorageID storage,
96 uint64_t size,
97 time_t modified);
98
Mike Lockwoodd815f792010-07-12 08:49:01 -040099 virtual void endSendObject(const char* path,
100 MtpObjectHandle handle,
101 MtpObjectFormat format,
Mike Lockwood413577d2010-11-16 17:38:43 -0500102 int64_t actualSize,
Mike Lockwoodd815f792010-07-12 08:49:01 -0400103 bool succeeded);
104
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400105 virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
106 MtpObjectFormat format,
107 MtpObjectHandle parent);
108
Mike Lockwood7a047c82010-08-02 10:52:20 -0400109 virtual int getNumObjects(MtpStorageID storageID,
110 MtpObjectFormat format,
111 MtpObjectHandle parent);
112
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400113 // callee should delete[] the results from these
114 // results can be NULL
115 virtual MtpObjectFormatList* getSupportedPlaybackFormats();
116 virtual MtpObjectFormatList* getSupportedCaptureFormats();
117 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
118 virtual MtpDevicePropertyList* getSupportedDeviceProperties();
119
Mike Lockwood828d19d2010-08-10 15:20:35 -0400120 virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400121 MtpObjectProperty property,
122 MtpDataPacket& packet);
123
Mike Lockwood828d19d2010-08-10 15:20:35 -0400124 virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
125 MtpObjectProperty property,
126 MtpDataPacket& packet);
127
128 virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
129 MtpDataPacket& packet);
130
131 virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
132 MtpDataPacket& packet);
133
134 virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
135
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400136 virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500137 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400138 int groupCode, int depth,
139 MtpDataPacket& packet);
140
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400141 virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
142 MtpDataPacket& packet);
143
Mike Lockwood59c777a2010-08-02 10:37:41 -0400144 virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800145 MtpString& outFilePath,
146 int64_t& outFileLength,
147 MtpObjectFormat& outFormat);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400148 virtual MtpResponseCode deleteFile(MtpObjectHandle handle);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400149
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400150 bool getObjectPropertyInfo(MtpObjectProperty property, int& type);
151 bool getDevicePropertyInfo(MtpDeviceProperty property, int& type);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400152
153 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
154
155 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
156 MtpObjectHandleList* references);
Mike Lockwood828d19d2010-08-10 15:20:35 -0400157
158 virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
159 MtpObjectFormat format);
160
161 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400162
163 virtual void sessionStarted();
164
165 virtual void sessionEnded();
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400166};
167
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400168// ----------------------------------------------------------------------------
169
170static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
171 if (env->ExceptionCheck()) {
172 LOGE("An exception was thrown by callback '%s'.", methodName);
173 LOGE_EX(env);
174 env->ExceptionClear();
175 }
176}
177
178// ----------------------------------------------------------------------------
179
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400180MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
181 : mDatabase(env->NewGlobalRef(client)),
182 mIntBuffer(NULL),
183 mLongBuffer(NULL),
184 mStringBuffer(NULL)
185{
186 jintArray intArray;
187 jlongArray longArray;
188 jcharArray charArray;
189
190 // create buffers for out arguments
191 // we don't need to be thread-safe so this is OK
192 intArray = env->NewIntArray(3);
193 if (!intArray)
194 goto out_of_memory;
195 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
196 longArray = env->NewLongArray(2);
197 if (!longArray)
198 goto out_of_memory;
199 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
200 charArray = env->NewCharArray(256);
201 if (!charArray)
202 goto out_of_memory;
203 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
204 return;
205
206out_of_memory:
207 env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), NULL);
208}
209
210void MyMtpDatabase::cleanup(JNIEnv *env) {
211 env->DeleteGlobalRef(mDatabase);
212 env->DeleteGlobalRef(mIntBuffer);
213 env->DeleteGlobalRef(mLongBuffer);
214 env->DeleteGlobalRef(mStringBuffer);
215}
216
217MyMtpDatabase::~MyMtpDatabase() {
218}
219
Mike Lockwoodd815f792010-07-12 08:49:01 -0400220MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400221 MtpObjectFormat format,
222 MtpObjectHandle parent,
223 MtpStorageID storage,
224 uint64_t size,
225 time_t modified) {
226 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400227 jstring pathStr = env->NewStringUTF(path);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400228 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
Mike Lockwood88394712010-09-27 10:01:00 -0400229 pathStr, (jint)format, (jint)parent, (jint)storage,
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400230 (jlong)size, (jlong)modified);
231
Mike Lockwood88394712010-09-27 10:01:00 -0400232 if (pathStr)
233 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400234 checkAndClearExceptionFromCallback(env, __FUNCTION__);
235 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400236}
237
Mike Lockwoodd815f792010-07-12 08:49:01 -0400238void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
Mike Lockwood413577d2010-11-16 17:38:43 -0500239 MtpObjectFormat format, int64_t actualSize, bool succeeded) {
Mike Lockwoodd815f792010-07-12 08:49:01 -0400240 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400241 jstring pathStr = env->NewStringUTF(path);
242 env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
Mike Lockwood413577d2010-11-16 17:38:43 -0500243 (jint)handle, (jint)format, (jlong)actualSize, (jboolean)succeeded);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400244
Mike Lockwood88394712010-09-27 10:01:00 -0400245 if (pathStr)
246 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400247 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400248}
249
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400250MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
251 MtpObjectFormat format,
252 MtpObjectHandle parent) {
253 JNIEnv* env = AndroidRuntime::getJNIEnv();
254 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
255 (jint)storageID, (jint)format, (jint)parent);
256 if (!array)
257 return NULL;
258 MtpObjectHandleList* list = new MtpObjectHandleList();
259 jint* handles = env->GetIntArrayElements(array, 0);
260 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400261 for (int i = 0; i < length; i++)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400262 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400263 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400264 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400265
266 checkAndClearExceptionFromCallback(env, __FUNCTION__);
267 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400268}
269
Mike Lockwood7a047c82010-08-02 10:52:20 -0400270int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
271 MtpObjectFormat format,
272 MtpObjectHandle parent) {
273 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400274 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400275 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400276
277 checkAndClearExceptionFromCallback(env, __FUNCTION__);
278 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400279}
280
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400281MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
282 JNIEnv* env = AndroidRuntime::getJNIEnv();
283 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
284 method_getSupportedPlaybackFormats);
285 if (!array)
286 return NULL;
287 MtpObjectFormatList* list = new MtpObjectFormatList();
288 jint* formats = env->GetIntArrayElements(array, 0);
289 jsize length = env->GetArrayLength(array);
290 for (int i = 0; i < length; i++)
291 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400292 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400293 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400294
295 checkAndClearExceptionFromCallback(env, __FUNCTION__);
296 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400297}
298
299MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
300 JNIEnv* env = AndroidRuntime::getJNIEnv();
301 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
302 method_getSupportedCaptureFormats);
303 if (!array)
304 return NULL;
305 MtpObjectFormatList* list = new MtpObjectFormatList();
306 jint* formats = env->GetIntArrayElements(array, 0);
307 jsize length = env->GetArrayLength(array);
308 for (int i = 0; i < length; i++)
309 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400310 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400311 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400312
313 checkAndClearExceptionFromCallback(env, __FUNCTION__);
314 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400315}
316
317MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
318 JNIEnv* env = AndroidRuntime::getJNIEnv();
319 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
320 method_getSupportedObjectProperties, (jint)format);
321 if (!array)
322 return NULL;
323 MtpObjectPropertyList* list = new MtpObjectPropertyList();
324 jint* properties = env->GetIntArrayElements(array, 0);
325 jsize length = env->GetArrayLength(array);
326 for (int i = 0; i < length; i++)
327 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400328 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400329 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400330
331 checkAndClearExceptionFromCallback(env, __FUNCTION__);
332 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400333}
334
335MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
336 JNIEnv* env = AndroidRuntime::getJNIEnv();
337 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
338 method_getSupportedDeviceProperties);
339 if (!array)
340 return NULL;
341 MtpDevicePropertyList* list = new MtpDevicePropertyList();
342 jint* properties = env->GetIntArrayElements(array, 0);
343 jsize length = env->GetArrayLength(array);
344 for (int i = 0; i < length; i++)
345 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400346 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400347 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400348
349 checkAndClearExceptionFromCallback(env, __FUNCTION__);
350 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400351}
352
Mike Lockwood828d19d2010-08-10 15:20:35 -0400353MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400354 MtpObjectProperty property,
355 MtpDataPacket& packet) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400356 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400357 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500358 (jlong)handle, 0, (jlong)property, 0, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400359 MtpResponseCode result = env->GetIntField(list, field_mResult);
360 int count = env->GetIntField(list, field_mCount);
361 if (result == MTP_RESPONSE_OK && count != 1)
362 result = MTP_RESPONSE_GENERAL_ERROR;
363
364 if (result == MTP_RESPONSE_OK) {
365 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
366 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
367 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
368 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
369 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
370
371 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
372 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
373 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
374 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
375
376 int type = dataTypes[0];
377 jlong longValue = (longValues ? longValues[0] : 0);
378
379 // special case date properties, which are strings to MTP
380 // but stored internally as a uint64
381 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
382 char date[20];
383 formatDateTime(longValue, date, sizeof(date));
384 packet.putString(date);
385 goto out;
386 }
387 // release date is stored internally as just the year
388 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
389 char date[20];
390 snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
391 packet.putString(date);
392 goto out;
393 }
394
395 switch (type) {
396 case MTP_TYPE_INT8:
397 packet.putInt8(longValue);
398 break;
399 case MTP_TYPE_UINT8:
400 packet.putUInt8(longValue);
401 break;
402 case MTP_TYPE_INT16:
403 packet.putInt16(longValue);
404 break;
405 case MTP_TYPE_UINT16:
406 packet.putUInt16(longValue);
407 break;
408 case MTP_TYPE_INT32:
409 packet.putInt32(longValue);
410 break;
411 case MTP_TYPE_UINT32:
412 packet.putUInt32(longValue);
413 break;
414 case MTP_TYPE_INT64:
415 packet.putInt64(longValue);
416 break;
417 case MTP_TYPE_UINT64:
418 packet.putUInt64(longValue);
419 break;
420 case MTP_TYPE_INT128:
421 packet.putInt128(longValue);
422 break;
423 case MTP_TYPE_UINT128:
424 packet.putInt128(longValue);
425 break;
426 case MTP_TYPE_STR:
427 {
428 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
429 if (stringValue) {
430 const char* str = env->GetStringUTFChars(stringValue, NULL);
431 packet.putString(str);
432 env->ReleaseStringUTFChars(stringValue, str);
433 } else {
434 packet.putEmptyString();
435 }
436 break;
437 }
438 default:
439 LOGE("unsupported type in getObjectPropertyValue\n");
440 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
441 }
442out:
443 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
444 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
445 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
446 if (longValues)
447 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
448
449 env->DeleteLocalRef(objectHandlesArray);
450 env->DeleteLocalRef(propertyCodesArray);
451 env->DeleteLocalRef(dataTypesArray);
452 if (longValuesArray)
453 env->DeleteLocalRef(longValuesArray);
454 if (stringValuesArray)
455 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400456 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400457
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400458 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400459 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400460 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400461}
462
Mike Lockwood828d19d2010-08-10 15:20:35 -0400463MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
464 MtpObjectProperty property,
465 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400466 int type;
467
468 if (!getObjectPropertyInfo(property, type))
469 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
470
471 JNIEnv* env = AndroidRuntime::getJNIEnv();
472 jlong longValue = 0;
473 jstring stringValue = NULL;
474
475 switch (type) {
476 case MTP_TYPE_INT8:
477 longValue = packet.getInt8();
478 break;
479 case MTP_TYPE_UINT8:
480 longValue = packet.getUInt8();
481 break;
482 case MTP_TYPE_INT16:
483 longValue = packet.getInt16();
484 break;
485 case MTP_TYPE_UINT16:
486 longValue = packet.getUInt16();
487 break;
488 case MTP_TYPE_INT32:
489 longValue = packet.getInt32();
490 break;
491 case MTP_TYPE_UINT32:
492 longValue = packet.getUInt32();
493 break;
494 case MTP_TYPE_INT64:
495 longValue = packet.getInt64();
496 break;
497 case MTP_TYPE_UINT64:
498 longValue = packet.getUInt64();
499 break;
500 case MTP_TYPE_STR:
501 {
502 MtpStringBuffer buffer;
503 packet.getString(buffer);
504 stringValue = env->NewStringUTF((const char *)buffer);
505 break;
506 }
507 default:
508 LOGE("unsupported type in getObjectPropertyValue\n");
509 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
510 }
511
512 jint result = env->CallIntMethod(mDatabase, method_setObjectProperty,
513 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400514 if (stringValue)
515 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400516
517 checkAndClearExceptionFromCallback(env, __FUNCTION__);
518 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400519}
520
521MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
522 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400523 int type;
524
525 if (!getDevicePropertyInfo(property, type))
526 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
527
528 JNIEnv* env = AndroidRuntime::getJNIEnv();
529 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
530 (jint)property, mLongBuffer, mStringBuffer);
531 if (result != MTP_RESPONSE_OK) {
532 checkAndClearExceptionFromCallback(env, __FUNCTION__);
533 return result;
534 }
535
536 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
537 jlong longValue = longValues[0];
538 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
539
540 switch (type) {
541 case MTP_TYPE_INT8:
542 packet.putInt8(longValue);
543 break;
544 case MTP_TYPE_UINT8:
545 packet.putUInt8(longValue);
546 break;
547 case MTP_TYPE_INT16:
548 packet.putInt16(longValue);
549 break;
550 case MTP_TYPE_UINT16:
551 packet.putUInt16(longValue);
552 break;
553 case MTP_TYPE_INT32:
554 packet.putInt32(longValue);
555 break;
556 case MTP_TYPE_UINT32:
557 packet.putUInt32(longValue);
558 break;
559 case MTP_TYPE_INT64:
560 packet.putInt64(longValue);
561 break;
562 case MTP_TYPE_UINT64:
563 packet.putUInt64(longValue);
564 break;
565 case MTP_TYPE_INT128:
566 packet.putInt128(longValue);
567 break;
568 case MTP_TYPE_UINT128:
569 packet.putInt128(longValue);
570 break;
571 case MTP_TYPE_STR:
572 {
573 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
574 packet.putString(str);
575 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
576 break;
577 }
578 default:
579 LOGE("unsupported type in getDevicePropertyValue\n");
580 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
581 }
582
583 checkAndClearExceptionFromCallback(env, __FUNCTION__);
584 return MTP_RESPONSE_OK;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400585}
586
587MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
588 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400589 int type;
590
591 if (!getDevicePropertyInfo(property, type))
592 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
593
594 JNIEnv* env = AndroidRuntime::getJNIEnv();
595 jlong longValue = 0;
596 jstring stringValue = NULL;
597
598 switch (type) {
599 case MTP_TYPE_INT8:
600 longValue = packet.getInt8();
601 break;
602 case MTP_TYPE_UINT8:
603 longValue = packet.getUInt8();
604 break;
605 case MTP_TYPE_INT16:
606 longValue = packet.getInt16();
607 break;
608 case MTP_TYPE_UINT16:
609 longValue = packet.getUInt16();
610 break;
611 case MTP_TYPE_INT32:
612 longValue = packet.getInt32();
613 break;
614 case MTP_TYPE_UINT32:
615 longValue = packet.getUInt32();
616 break;
617 case MTP_TYPE_INT64:
618 longValue = packet.getInt64();
619 break;
620 case MTP_TYPE_UINT64:
621 longValue = packet.getUInt64();
622 break;
623 case MTP_TYPE_STR:
624 {
625 MtpStringBuffer buffer;
626 packet.getString(buffer);
627 stringValue = env->NewStringUTF((const char *)buffer);
628 break;
629 }
630 default:
631 LOGE("unsupported type in setDevicePropertyValue\n");
632 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
633 }
634
635 jint result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
636 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400637 if (stringValue)
638 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400639
640 checkAndClearExceptionFromCallback(env, __FUNCTION__);
641 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400642}
643
644MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
645 return -1;
646}
647
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400648MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500649 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400650 int groupCode, int depth,
651 MtpDataPacket& packet) {
652 JNIEnv* env = AndroidRuntime::getJNIEnv();
653 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500654 (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
655 checkAndClearExceptionFromCallback(env, __FUNCTION__);
656 if (!list)
657 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400658 int count = env->GetIntField(list, field_mCount);
659 MtpResponseCode result = env->GetIntField(list, field_mResult);
660
661 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400662 if (count > 0) {
663 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
664 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
665 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
666 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
667 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
668
669 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
670 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
671 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
672 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
673
674 for (int i = 0; i < count; i++) {
675 packet.putUInt32(objectHandles[i]);
676 packet.putUInt16(propertyCodes[i]);
677 int type = dataTypes[i];
678 packet.putUInt16(type);
679
680 switch (type) {
681 case MTP_TYPE_INT8:
682 packet.putInt8(longValues[i]);
683 break;
684 case MTP_TYPE_UINT8:
685 packet.putUInt8(longValues[i]);
686 break;
687 case MTP_TYPE_INT16:
688 packet.putInt16(longValues[i]);
689 break;
690 case MTP_TYPE_UINT16:
691 packet.putUInt16(longValues[i]);
692 break;
693 case MTP_TYPE_INT32:
694 packet.putInt32(longValues[i]);
695 break;
696 case MTP_TYPE_UINT32:
697 packet.putUInt32(longValues[i]);
698 break;
699 case MTP_TYPE_INT64:
700 packet.putInt64(longValues[i]);
701 break;
702 case MTP_TYPE_UINT64:
703 packet.putUInt64(longValues[i]);
704 break;
705 case MTP_TYPE_INT128:
706 packet.putInt128(longValues[i]);
707 break;
708 case MTP_TYPE_UINT128:
709 packet.putUInt128(longValues[i]);
710 break;
711 case MTP_TYPE_STR: {
712 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
Mike Lockwood2711e492010-12-11 11:24:37 -0800713 const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400714 if (valueStr) {
715 packet.putString(valueStr);
716 env->ReleaseStringUTFChars(value, valueStr);
717 } else {
718 packet.putEmptyString();
719 }
720 env->DeleteLocalRef(value);
721 break;
722 }
723 default:
724 LOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
725 break;
726 }
727 }
728
729 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
730 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
731 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
732 if (longValues)
733 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
734
735 env->DeleteLocalRef(objectHandlesArray);
736 env->DeleteLocalRef(propertyCodesArray);
737 env->DeleteLocalRef(dataTypesArray);
738 if (longValuesArray)
739 env->DeleteLocalRef(longValuesArray);
740 if (stringValuesArray)
741 env->DeleteLocalRef(stringValuesArray);
742 }
743
744 env->DeleteLocalRef(list);
745 checkAndClearExceptionFromCallback(env, __FUNCTION__);
746 return result;
747}
748
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400749MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
750 MtpDataPacket& packet) {
751 char date[20];
752
753 JNIEnv* env = AndroidRuntime::getJNIEnv();
754 jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
755 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
756 if (!result)
757 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
758
759 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
760 MtpStorageID storageID = intValues[0];
761 MtpObjectFormat format = intValues[1];
762 MtpObjectHandle parent = intValues[2];
763 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
764
765 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
766 uint64_t size = longValues[0];
767 uint64_t modified = longValues[1];
768 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
769
Mike Lockwood828d19d2010-08-10 15:20:35 -0400770// int associationType = (format == MTP_FORMAT_ASSOCIATION ?
771// MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
772// MTP_ASSOCIATION_TYPE_UNDEFINED);
773 int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400774
775 packet.putUInt32(storageID);
776 packet.putUInt16(format);
777 packet.putUInt16(0); // protection status
778 packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
779 packet.putUInt16(0); // thumb format
780 packet.putUInt32(0); // thumb compressed size
781 packet.putUInt32(0); // thumb pix width
782 packet.putUInt32(0); // thumb pix height
783 packet.putUInt32(0); // image pix width
784 packet.putUInt32(0); // image pix height
785 packet.putUInt32(0); // image bit depth
786 packet.putUInt32(parent);
787 packet.putUInt16(associationType);
788 packet.putUInt32(0); // association desc
789 packet.putUInt32(0); // sequence number
790
791 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
792 packet.putString(str); // file name
793 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
794
795 packet.putEmptyString();
796 formatDateTime(modified, date, sizeof(date));
797 packet.putString(date); // date modified
798 packet.putEmptyString(); // keywords
799
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400800 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400801 return MTP_RESPONSE_OK;
802}
803
Mike Lockwood59c777a2010-08-02 10:37:41 -0400804MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800805 MtpString& outFilePath,
806 int64_t& outFileLength,
807 MtpObjectFormat& outFormat) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400808 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400809 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400810 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400811 if (result != MTP_RESPONSE_OK) {
812 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400813 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400814 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400815
816 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800817 outFilePath.setTo(str, strlen16(str));
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400818 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
819
820 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800821 outFileLength = longValues[0];
822 outFormat = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400823 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
824
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400825 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400826 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400827}
828
Mike Lockwood59c777a2010-08-02 10:37:41 -0400829MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400830 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400831 MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
832
833 checkAndClearExceptionFromCallback(env, __FUNCTION__);
834 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400835}
836
837struct PropertyTableEntry {
838 MtpObjectProperty property;
839 int type;
840};
841
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400842static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400843 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
844 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
845 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
846 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
847 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
848 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
849 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
850 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
851 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -0400852 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
853 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
854 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
855 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
856 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
857 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
858 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
859 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
860 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
861 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
862 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400863};
864
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400865static const PropertyTableEntry kDevicePropertyTable[] = {
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800866 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
867 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
868 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400869};
870
871bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
872 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
873 const PropertyTableEntry* entry = kObjectPropertyTable;
874 for (int i = 0; i < count; i++, entry++) {
875 if (entry->property == property) {
876 type = entry->type;
877 return true;
878 }
879 }
880 return false;
881}
882
883bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
884 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
885 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400886 for (int i = 0; i < count; i++, entry++) {
887 if (entry->property == property) {
888 type = entry->type;
889 return true;
890 }
891 }
892 return false;
893}
894
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400895MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
896 JNIEnv* env = AndroidRuntime::getJNIEnv();
897 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
898 (jint)handle);
899 if (!array)
900 return NULL;
901 MtpObjectHandleList* list = new MtpObjectHandleList();
902 jint* handles = env->GetIntArrayElements(array, 0);
903 jsize length = env->GetArrayLength(array);
904 for (int i = 0; i < length; i++)
905 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400906 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400907 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400908
909 checkAndClearExceptionFromCallback(env, __FUNCTION__);
910 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400911}
912
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400913MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
914 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400915 JNIEnv* env = AndroidRuntime::getJNIEnv();
916 int count = references->size();
917 jintArray array = env->NewIntArray(count);
918 if (!array) {
919 LOGE("out of memory in setObjectReferences");
920 return false;
921 }
922 jint* handles = env->GetIntArrayElements(array, 0);
923 for (int i = 0; i < count; i++)
924 handles[i] = (*references)[i];
925 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400926 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400927 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -0400928 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400929
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400930 checkAndClearExceptionFromCallback(env, __FUNCTION__);
931 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400932}
933
Mike Lockwood828d19d2010-08-10 15:20:35 -0400934MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
935 MtpObjectFormat format) {
936 MtpProperty* result = NULL;
937 switch (property) {
938 case MTP_PROPERTY_OBJECT_FORMAT:
Mike Lockwood9b5e9c42010-12-07 18:53:50 -0800939 // use format as default value
940 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
941 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400942 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400943 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400944 result = new MtpProperty(property, MTP_TYPE_UINT16);
945 break;
946 case MTP_PROPERTY_STORAGE_ID:
947 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400948 case MTP_PROPERTY_DURATION:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400949 result = new MtpProperty(property, MTP_TYPE_UINT32);
950 break;
951 case MTP_PROPERTY_OBJECT_SIZE:
952 result = new MtpProperty(property, MTP_TYPE_UINT64);
953 break;
954 case MTP_PROPERTY_PERSISTENT_UID:
955 result = new MtpProperty(property, MTP_TYPE_UINT128);
956 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400957 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400958 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400959 case MTP_PROPERTY_ARTIST:
960 case MTP_PROPERTY_ALBUM_NAME:
961 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400962 case MTP_PROPERTY_GENRE:
963 case MTP_PROPERTY_COMPOSER:
964 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400965 result = new MtpProperty(property, MTP_TYPE_STR);
966 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -0500967 case MTP_PROPERTY_DATE_MODIFIED:
968 case MTP_PROPERTY_DATE_ADDED:
969 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
970 result = new MtpProperty(property, MTP_TYPE_STR);
971 result->setFormDateTime();
972 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -0400973 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -0400974 // We allow renaming files and folders
975 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -0400976 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400977 }
978
979 return result;
980}
981
982MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800983 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400984 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800985 bool writable = false;
986
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400987 switch (property) {
988 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
989 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800990 writable = true;
991 // fall through
992 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
993 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -0400994
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800995 // get current value
Mike Lockwooda2a21282010-09-25 21:21:05 -0400996 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
997 (jint)property, mLongBuffer, mStringBuffer);
998 if (ret == MTP_RESPONSE_OK) {
999 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
1000 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001001 // for read-only properties it is safe to assume current value is default value
1002 if (!writable)
1003 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001004 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
1005 } else {
1006 LOGE("unable to read device property, response: %04X", ret);
1007 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001008 break;
1009 }
1010
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001011 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001012 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001013}
1014
Mike Lockwood2837eef2010-08-31 16:25:12 -04001015void MyMtpDatabase::sessionStarted() {
1016 JNIEnv* env = AndroidRuntime::getJNIEnv();
1017 env->CallVoidMethod(mDatabase, method_sessionStarted);
1018 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1019}
1020
1021void MyMtpDatabase::sessionEnded() {
1022 JNIEnv* env = AndroidRuntime::getJNIEnv();
1023 env->CallVoidMethod(mDatabase, method_sessionEnded);
1024 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1025}
1026
Mike Lockwoodff164a72010-07-15 15:01:17 -04001027#endif // HAVE_ANDROID_OS
1028
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001029// ----------------------------------------------------------------------------
1030
1031static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001032android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001033{
Mike Lockwoodff164a72010-07-15 15:01:17 -04001034#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001035 LOGD("setup\n");
1036 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
1037 env->SetIntField(thiz, field_context, (int)database);
1038 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -04001039#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001040}
1041
1042static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001043android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001044{
Mike Lockwoodff164a72010-07-15 15:01:17 -04001045#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001046 LOGD("finalize\n");
1047 MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
1048 database->cleanup(env);
1049 delete database;
1050 env->SetIntField(thiz, field_context, 0);
1051 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -04001052#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001053}
1054
Mike Lockwood31599912010-11-15 13:43:30 -05001055static jstring
Mike Lockwood0cd01362010-12-30 11:54:33 -05001056android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001057{
1058#ifdef HAVE_ANDROID_OS
1059 char date[20];
1060 formatDateTime(seconds, date, sizeof(date));
1061 return env->NewStringUTF(date);
1062#else
1063 return NULL;
1064#endif
1065}
1066
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001067// ----------------------------------------------------------------------------
1068
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001069static JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001070 {"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
1071 {"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001072};
1073
1074static JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001075 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001076 (void *)android_mtp_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001077};
1078
Mike Lockwood0cd01362010-12-30 11:54:33 -05001079static const char* const kClassPathName = "android/mtp/MtpDatabase";
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001080
Mike Lockwood0cd01362010-12-30 11:54:33 -05001081int register_android_mtp_MtpDatabase(JNIEnv *env)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001082{
1083 jclass clazz;
1084
Mike Lockwood0cd01362010-12-30 11:54:33 -05001085 LOGD("register_android_mtp_MtpDatabase\n");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001086
Mike Lockwood0cd01362010-12-30 11:54:33 -05001087 clazz = env->FindClass("android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001088 if (clazz == NULL) {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001089 LOGE("Can't find android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001090 return -1;
1091 }
Mike Lockwoodd815f792010-07-12 08:49:01 -04001092 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1093 if (method_beginSendObject == NULL) {
1094 LOGE("Can't find beginSendObject");
1095 return -1;
1096 }
Mike Lockwood413577d2010-11-16 17:38:43 -05001097 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIJZ)V");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001098 if (method_endSendObject == NULL) {
1099 LOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001100 return -1;
1101 }
1102 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1103 if (method_getObjectList == NULL) {
1104 LOGE("Can't find getObjectList");
1105 return -1;
1106 }
Mike Lockwood7a047c82010-08-02 10:52:20 -04001107 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
1108 if (method_getNumObjects == NULL) {
1109 LOGE("Can't find getNumObjects");
1110 return -1;
1111 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001112 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
1113 if (method_getSupportedPlaybackFormats == NULL) {
1114 LOGE("Can't find getSupportedPlaybackFormats");
1115 return -1;
1116 }
1117 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
1118 if (method_getSupportedCaptureFormats == NULL) {
1119 LOGE("Can't find getSupportedCaptureFormats");
1120 return -1;
1121 }
1122 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
1123 if (method_getSupportedObjectProperties == NULL) {
1124 LOGE("Can't find getSupportedObjectProperties");
1125 return -1;
1126 }
1127 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
1128 if (method_getSupportedDeviceProperties == NULL) {
1129 LOGE("Can't find getSupportedDeviceProperties");
1130 return -1;
1131 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001132 method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
1133 if (method_setObjectProperty == NULL) {
1134 LOGE("Can't find setObjectProperty");
1135 return -1;
1136 }
1137 method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
1138 if (method_getDeviceProperty == NULL) {
1139 LOGE("Can't find getDeviceProperty");
1140 return -1;
1141 }
1142 method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
1143 if (method_setDeviceProperty == NULL) {
1144 LOGE("Can't find setDeviceProperty");
1145 return -1;
1146 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001147 method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001148 "(JIJII)Landroid/mtp/MtpPropertyList;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001149 if (method_getObjectPropertyList == NULL) {
1150 LOGE("Can't find getObjectPropertyList");
1151 return -1;
1152 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001153 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1154 if (method_getObjectInfo == NULL) {
1155 LOGE("Can't find getObjectInfo");
1156 return -1;
1157 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001158 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001159 if (method_getObjectFilePath == NULL) {
1160 LOGE("Can't find getObjectFilePath");
1161 return -1;
1162 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001163 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001164 if (method_deleteFile == NULL) {
1165 LOGE("Can't find deleteFile");
1166 return -1;
1167 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001168 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
1169 if (method_getObjectReferences == NULL) {
1170 LOGE("Can't find getObjectReferences");
1171 return -1;
1172 }
1173 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
1174 if (method_setObjectReferences == NULL) {
1175 LOGE("Can't find setObjectReferences");
1176 return -1;
1177 }
Mike Lockwood2837eef2010-08-31 16:25:12 -04001178 method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
1179 if (method_sessionStarted == NULL) {
1180 LOGE("Can't find sessionStarted");
1181 return -1;
1182 }
1183 method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
1184 if (method_sessionEnded == NULL) {
1185 LOGE("Can't find sessionEnded");
1186 return -1;
1187 }
1188
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001189 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
1190 if (field_context == NULL) {
1191 LOGE("Can't find MtpDatabase.mNativeContext");
1192 return -1;
1193 }
1194
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001195 // now set up fields for MtpPropertyList class
Mike Lockwood0cd01362010-12-30 11:54:33 -05001196 clazz = env->FindClass("android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001197 if (clazz == NULL) {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001198 LOGE("Can't find android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001199 return -1;
1200 }
1201 field_mCount = env->GetFieldID(clazz, "mCount", "I");
1202 if (field_mCount == NULL) {
1203 LOGE("Can't find MtpPropertyList.mCount");
1204 return -1;
1205 }
1206 field_mResult = env->GetFieldID(clazz, "mResult", "I");
1207 if (field_mResult == NULL) {
1208 LOGE("Can't find MtpPropertyList.mResult");
1209 return -1;
1210 }
1211 field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1212 if (field_mObjectHandles == NULL) {
1213 LOGE("Can't find MtpPropertyList.mObjectHandles");
1214 return -1;
1215 }
1216 field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1217 if (field_mPropertyCodes == NULL) {
1218 LOGE("Can't find MtpPropertyList.mPropertyCodes");
1219 return -1;
1220 }
1221 field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1222 if (field_mDataTypes == NULL) {
1223 LOGE("Can't find MtpPropertyList.mDataTypes");
1224 return -1;
1225 }
1226 field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1227 if (field_mLongValues == NULL) {
1228 LOGE("Can't find MtpPropertyList.mLongValues");
1229 return -1;
1230 }
1231 field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1232 if (field_mStringValues == NULL) {
1233 LOGE("Can't find MtpPropertyList.mStringValues");
1234 return -1;
1235 }
1236
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001237 if (AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001238 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001239 return -1;
1240
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001241 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001242 "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001243}