blob: fc7d86ec9081a48f06446e6bb0345224b4db748a [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 Lockwoodd21eac92010-07-03 00:44:05 -0400145 MtpString& filePath,
146 int64_t& fileLength);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400147 virtual MtpResponseCode deleteFile(MtpObjectHandle handle);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400148
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400149 bool getObjectPropertyInfo(MtpObjectProperty property, int& type);
150 bool getDevicePropertyInfo(MtpDeviceProperty property, int& type);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400151
152 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
153
154 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
155 MtpObjectHandleList* references);
Mike Lockwood828d19d2010-08-10 15:20:35 -0400156
157 virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
158 MtpObjectFormat format);
159
160 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400161
162 virtual void sessionStarted();
163
164 virtual void sessionEnded();
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400165};
166
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400167// ----------------------------------------------------------------------------
168
169static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
170 if (env->ExceptionCheck()) {
171 LOGE("An exception was thrown by callback '%s'.", methodName);
172 LOGE_EX(env);
173 env->ExceptionClear();
174 }
175}
176
177// ----------------------------------------------------------------------------
178
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400179MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
180 : mDatabase(env->NewGlobalRef(client)),
181 mIntBuffer(NULL),
182 mLongBuffer(NULL),
183 mStringBuffer(NULL)
184{
185 jintArray intArray;
186 jlongArray longArray;
187 jcharArray charArray;
188
189 // create buffers for out arguments
190 // we don't need to be thread-safe so this is OK
191 intArray = env->NewIntArray(3);
192 if (!intArray)
193 goto out_of_memory;
194 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
195 longArray = env->NewLongArray(2);
196 if (!longArray)
197 goto out_of_memory;
198 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
199 charArray = env->NewCharArray(256);
200 if (!charArray)
201 goto out_of_memory;
202 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
203 return;
204
205out_of_memory:
206 env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"), NULL);
207}
208
209void MyMtpDatabase::cleanup(JNIEnv *env) {
210 env->DeleteGlobalRef(mDatabase);
211 env->DeleteGlobalRef(mIntBuffer);
212 env->DeleteGlobalRef(mLongBuffer);
213 env->DeleteGlobalRef(mStringBuffer);
214}
215
216MyMtpDatabase::~MyMtpDatabase() {
217}
218
Mike Lockwoodd815f792010-07-12 08:49:01 -0400219MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400220 MtpObjectFormat format,
221 MtpObjectHandle parent,
222 MtpStorageID storage,
223 uint64_t size,
224 time_t modified) {
225 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400226 jstring pathStr = env->NewStringUTF(path);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400227 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
Mike Lockwood88394712010-09-27 10:01:00 -0400228 pathStr, (jint)format, (jint)parent, (jint)storage,
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400229 (jlong)size, (jlong)modified);
230
Mike Lockwood88394712010-09-27 10:01:00 -0400231 if (pathStr)
232 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400233 checkAndClearExceptionFromCallback(env, __FUNCTION__);
234 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400235}
236
Mike Lockwoodd815f792010-07-12 08:49:01 -0400237void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
Mike Lockwood413577d2010-11-16 17:38:43 -0500238 MtpObjectFormat format, int64_t actualSize, bool succeeded) {
Mike Lockwoodd815f792010-07-12 08:49:01 -0400239 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400240 jstring pathStr = env->NewStringUTF(path);
241 env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
Mike Lockwood413577d2010-11-16 17:38:43 -0500242 (jint)handle, (jint)format, (jlong)actualSize, (jboolean)succeeded);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400243
Mike Lockwood88394712010-09-27 10:01:00 -0400244 if (pathStr)
245 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400246 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400247}
248
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400249MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
250 MtpObjectFormat format,
251 MtpObjectHandle parent) {
252 JNIEnv* env = AndroidRuntime::getJNIEnv();
253 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
254 (jint)storageID, (jint)format, (jint)parent);
255 if (!array)
256 return NULL;
257 MtpObjectHandleList* list = new MtpObjectHandleList();
258 jint* handles = env->GetIntArrayElements(array, 0);
259 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400260 for (int i = 0; i < length; i++)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400261 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400262 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400263 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400264
265 checkAndClearExceptionFromCallback(env, __FUNCTION__);
266 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400267}
268
Mike Lockwood7a047c82010-08-02 10:52:20 -0400269int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
270 MtpObjectFormat format,
271 MtpObjectHandle parent) {
272 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400273 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400274 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400275
276 checkAndClearExceptionFromCallback(env, __FUNCTION__);
277 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400278}
279
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400280MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
281 JNIEnv* env = AndroidRuntime::getJNIEnv();
282 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
283 method_getSupportedPlaybackFormats);
284 if (!array)
285 return NULL;
286 MtpObjectFormatList* list = new MtpObjectFormatList();
287 jint* formats = env->GetIntArrayElements(array, 0);
288 jsize length = env->GetArrayLength(array);
289 for (int i = 0; i < length; i++)
290 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400291 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400292 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400293
294 checkAndClearExceptionFromCallback(env, __FUNCTION__);
295 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400296}
297
298MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
299 JNIEnv* env = AndroidRuntime::getJNIEnv();
300 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
301 method_getSupportedCaptureFormats);
302 if (!array)
303 return NULL;
304 MtpObjectFormatList* list = new MtpObjectFormatList();
305 jint* formats = env->GetIntArrayElements(array, 0);
306 jsize length = env->GetArrayLength(array);
307 for (int i = 0; i < length; i++)
308 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400309 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400310 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400311
312 checkAndClearExceptionFromCallback(env, __FUNCTION__);
313 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400314}
315
316MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
317 JNIEnv* env = AndroidRuntime::getJNIEnv();
318 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
319 method_getSupportedObjectProperties, (jint)format);
320 if (!array)
321 return NULL;
322 MtpObjectPropertyList* list = new MtpObjectPropertyList();
323 jint* properties = env->GetIntArrayElements(array, 0);
324 jsize length = env->GetArrayLength(array);
325 for (int i = 0; i < length; i++)
326 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400327 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400328 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400329
330 checkAndClearExceptionFromCallback(env, __FUNCTION__);
331 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400332}
333
334MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
335 JNIEnv* env = AndroidRuntime::getJNIEnv();
336 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
337 method_getSupportedDeviceProperties);
338 if (!array)
339 return NULL;
340 MtpDevicePropertyList* list = new MtpDevicePropertyList();
341 jint* properties = env->GetIntArrayElements(array, 0);
342 jsize length = env->GetArrayLength(array);
343 for (int i = 0; i < length; i++)
344 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400345 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400346 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400347
348 checkAndClearExceptionFromCallback(env, __FUNCTION__);
349 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400350}
351
Mike Lockwood828d19d2010-08-10 15:20:35 -0400352MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400353 MtpObjectProperty property,
354 MtpDataPacket& packet) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400355 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400356 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500357 (jlong)handle, 0, (jlong)property, 0, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400358 MtpResponseCode result = env->GetIntField(list, field_mResult);
359 int count = env->GetIntField(list, field_mCount);
360 if (result == MTP_RESPONSE_OK && count != 1)
361 result = MTP_RESPONSE_GENERAL_ERROR;
362
363 if (result == MTP_RESPONSE_OK) {
364 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
365 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
366 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
367 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
368 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
369
370 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
371 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
372 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
373 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
374
375 int type = dataTypes[0];
376 jlong longValue = (longValues ? longValues[0] : 0);
377
378 // special case date properties, which are strings to MTP
379 // but stored internally as a uint64
380 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
381 char date[20];
382 formatDateTime(longValue, date, sizeof(date));
383 packet.putString(date);
384 goto out;
385 }
386 // release date is stored internally as just the year
387 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
388 char date[20];
389 snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
390 packet.putString(date);
391 goto out;
392 }
393
394 switch (type) {
395 case MTP_TYPE_INT8:
396 packet.putInt8(longValue);
397 break;
398 case MTP_TYPE_UINT8:
399 packet.putUInt8(longValue);
400 break;
401 case MTP_TYPE_INT16:
402 packet.putInt16(longValue);
403 break;
404 case MTP_TYPE_UINT16:
405 packet.putUInt16(longValue);
406 break;
407 case MTP_TYPE_INT32:
408 packet.putInt32(longValue);
409 break;
410 case MTP_TYPE_UINT32:
411 packet.putUInt32(longValue);
412 break;
413 case MTP_TYPE_INT64:
414 packet.putInt64(longValue);
415 break;
416 case MTP_TYPE_UINT64:
417 packet.putUInt64(longValue);
418 break;
419 case MTP_TYPE_INT128:
420 packet.putInt128(longValue);
421 break;
422 case MTP_TYPE_UINT128:
423 packet.putInt128(longValue);
424 break;
425 case MTP_TYPE_STR:
426 {
427 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
428 if (stringValue) {
429 const char* str = env->GetStringUTFChars(stringValue, NULL);
430 packet.putString(str);
431 env->ReleaseStringUTFChars(stringValue, str);
432 } else {
433 packet.putEmptyString();
434 }
435 break;
436 }
437 default:
438 LOGE("unsupported type in getObjectPropertyValue\n");
439 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
440 }
441out:
442 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
443 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
444 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
445 if (longValues)
446 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
447
448 env->DeleteLocalRef(objectHandlesArray);
449 env->DeleteLocalRef(propertyCodesArray);
450 env->DeleteLocalRef(dataTypesArray);
451 if (longValuesArray)
452 env->DeleteLocalRef(longValuesArray);
453 if (stringValuesArray)
454 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400455 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400456
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400457 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400458 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400459 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400460}
461
Mike Lockwood828d19d2010-08-10 15:20:35 -0400462MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
463 MtpObjectProperty property,
464 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400465 int type;
466
467 if (!getObjectPropertyInfo(property, type))
468 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
469
470 JNIEnv* env = AndroidRuntime::getJNIEnv();
471 jlong longValue = 0;
472 jstring stringValue = NULL;
473
474 switch (type) {
475 case MTP_TYPE_INT8:
476 longValue = packet.getInt8();
477 break;
478 case MTP_TYPE_UINT8:
479 longValue = packet.getUInt8();
480 break;
481 case MTP_TYPE_INT16:
482 longValue = packet.getInt16();
483 break;
484 case MTP_TYPE_UINT16:
485 longValue = packet.getUInt16();
486 break;
487 case MTP_TYPE_INT32:
488 longValue = packet.getInt32();
489 break;
490 case MTP_TYPE_UINT32:
491 longValue = packet.getUInt32();
492 break;
493 case MTP_TYPE_INT64:
494 longValue = packet.getInt64();
495 break;
496 case MTP_TYPE_UINT64:
497 longValue = packet.getUInt64();
498 break;
499 case MTP_TYPE_STR:
500 {
501 MtpStringBuffer buffer;
502 packet.getString(buffer);
503 stringValue = env->NewStringUTF((const char *)buffer);
504 break;
505 }
506 default:
507 LOGE("unsupported type in getObjectPropertyValue\n");
508 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
509 }
510
511 jint result = env->CallIntMethod(mDatabase, method_setObjectProperty,
512 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400513 if (stringValue)
514 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400515
516 checkAndClearExceptionFromCallback(env, __FUNCTION__);
517 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400518}
519
520MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
521 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400522 int type;
523
524 if (!getDevicePropertyInfo(property, type))
525 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
526
527 JNIEnv* env = AndroidRuntime::getJNIEnv();
528 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
529 (jint)property, mLongBuffer, mStringBuffer);
530 if (result != MTP_RESPONSE_OK) {
531 checkAndClearExceptionFromCallback(env, __FUNCTION__);
532 return result;
533 }
534
535 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
536 jlong longValue = longValues[0];
537 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
538
539 switch (type) {
540 case MTP_TYPE_INT8:
541 packet.putInt8(longValue);
542 break;
543 case MTP_TYPE_UINT8:
544 packet.putUInt8(longValue);
545 break;
546 case MTP_TYPE_INT16:
547 packet.putInt16(longValue);
548 break;
549 case MTP_TYPE_UINT16:
550 packet.putUInt16(longValue);
551 break;
552 case MTP_TYPE_INT32:
553 packet.putInt32(longValue);
554 break;
555 case MTP_TYPE_UINT32:
556 packet.putUInt32(longValue);
557 break;
558 case MTP_TYPE_INT64:
559 packet.putInt64(longValue);
560 break;
561 case MTP_TYPE_UINT64:
562 packet.putUInt64(longValue);
563 break;
564 case MTP_TYPE_INT128:
565 packet.putInt128(longValue);
566 break;
567 case MTP_TYPE_UINT128:
568 packet.putInt128(longValue);
569 break;
570 case MTP_TYPE_STR:
571 {
572 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
573 packet.putString(str);
574 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
575 break;
576 }
577 default:
578 LOGE("unsupported type in getDevicePropertyValue\n");
579 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
580 }
581
582 checkAndClearExceptionFromCallback(env, __FUNCTION__);
583 return MTP_RESPONSE_OK;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400584}
585
586MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
587 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400588 int type;
589
590 if (!getDevicePropertyInfo(property, type))
591 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
592
593 JNIEnv* env = AndroidRuntime::getJNIEnv();
594 jlong longValue = 0;
595 jstring stringValue = NULL;
596
597 switch (type) {
598 case MTP_TYPE_INT8:
599 longValue = packet.getInt8();
600 break;
601 case MTP_TYPE_UINT8:
602 longValue = packet.getUInt8();
603 break;
604 case MTP_TYPE_INT16:
605 longValue = packet.getInt16();
606 break;
607 case MTP_TYPE_UINT16:
608 longValue = packet.getUInt16();
609 break;
610 case MTP_TYPE_INT32:
611 longValue = packet.getInt32();
612 break;
613 case MTP_TYPE_UINT32:
614 longValue = packet.getUInt32();
615 break;
616 case MTP_TYPE_INT64:
617 longValue = packet.getInt64();
618 break;
619 case MTP_TYPE_UINT64:
620 longValue = packet.getUInt64();
621 break;
622 case MTP_TYPE_STR:
623 {
624 MtpStringBuffer buffer;
625 packet.getString(buffer);
626 stringValue = env->NewStringUTF((const char *)buffer);
627 break;
628 }
629 default:
630 LOGE("unsupported type in setDevicePropertyValue\n");
631 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
632 }
633
634 jint result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
635 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400636 if (stringValue)
637 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400638
639 checkAndClearExceptionFromCallback(env, __FUNCTION__);
640 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400641}
642
643MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
644 return -1;
645}
646
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400647MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500648 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400649 int groupCode, int depth,
650 MtpDataPacket& packet) {
651 JNIEnv* env = AndroidRuntime::getJNIEnv();
652 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500653 (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
654 checkAndClearExceptionFromCallback(env, __FUNCTION__);
655 if (!list)
656 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400657 int count = env->GetIntField(list, field_mCount);
658 MtpResponseCode result = env->GetIntField(list, field_mResult);
659
660 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400661 if (count > 0) {
662 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
663 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
664 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
665 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
666 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
667
668 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
669 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
670 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
671 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
672
673 for (int i = 0; i < count; i++) {
674 packet.putUInt32(objectHandles[i]);
675 packet.putUInt16(propertyCodes[i]);
676 int type = dataTypes[i];
677 packet.putUInt16(type);
678
679 switch (type) {
680 case MTP_TYPE_INT8:
681 packet.putInt8(longValues[i]);
682 break;
683 case MTP_TYPE_UINT8:
684 packet.putUInt8(longValues[i]);
685 break;
686 case MTP_TYPE_INT16:
687 packet.putInt16(longValues[i]);
688 break;
689 case MTP_TYPE_UINT16:
690 packet.putUInt16(longValues[i]);
691 break;
692 case MTP_TYPE_INT32:
693 packet.putInt32(longValues[i]);
694 break;
695 case MTP_TYPE_UINT32:
696 packet.putUInt32(longValues[i]);
697 break;
698 case MTP_TYPE_INT64:
699 packet.putInt64(longValues[i]);
700 break;
701 case MTP_TYPE_UINT64:
702 packet.putUInt64(longValues[i]);
703 break;
704 case MTP_TYPE_INT128:
705 packet.putInt128(longValues[i]);
706 break;
707 case MTP_TYPE_UINT128:
708 packet.putUInt128(longValues[i]);
709 break;
710 case MTP_TYPE_STR: {
711 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
712 const char *valueStr = env->GetStringUTFChars(value, NULL);
713 if (valueStr) {
714 packet.putString(valueStr);
715 env->ReleaseStringUTFChars(value, valueStr);
716 } else {
717 packet.putEmptyString();
718 }
719 env->DeleteLocalRef(value);
720 break;
721 }
722 default:
723 LOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
724 break;
725 }
726 }
727
728 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
729 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
730 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
731 if (longValues)
732 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
733
734 env->DeleteLocalRef(objectHandlesArray);
735 env->DeleteLocalRef(propertyCodesArray);
736 env->DeleteLocalRef(dataTypesArray);
737 if (longValuesArray)
738 env->DeleteLocalRef(longValuesArray);
739 if (stringValuesArray)
740 env->DeleteLocalRef(stringValuesArray);
741 }
742
743 env->DeleteLocalRef(list);
744 checkAndClearExceptionFromCallback(env, __FUNCTION__);
745 return result;
746}
747
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400748MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
749 MtpDataPacket& packet) {
750 char date[20];
751
752 JNIEnv* env = AndroidRuntime::getJNIEnv();
753 jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
754 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
755 if (!result)
756 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
757
758 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
759 MtpStorageID storageID = intValues[0];
760 MtpObjectFormat format = intValues[1];
761 MtpObjectHandle parent = intValues[2];
762 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
763
764 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
765 uint64_t size = longValues[0];
766 uint64_t modified = longValues[1];
767 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
768
Mike Lockwood828d19d2010-08-10 15:20:35 -0400769// int associationType = (format == MTP_FORMAT_ASSOCIATION ?
770// MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
771// MTP_ASSOCIATION_TYPE_UNDEFINED);
772 int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400773
774 packet.putUInt32(storageID);
775 packet.putUInt16(format);
776 packet.putUInt16(0); // protection status
777 packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
778 packet.putUInt16(0); // thumb format
779 packet.putUInt32(0); // thumb compressed size
780 packet.putUInt32(0); // thumb pix width
781 packet.putUInt32(0); // thumb pix height
782 packet.putUInt32(0); // image pix width
783 packet.putUInt32(0); // image pix height
784 packet.putUInt32(0); // image bit depth
785 packet.putUInt32(parent);
786 packet.putUInt16(associationType);
787 packet.putUInt32(0); // association desc
788 packet.putUInt32(0); // sequence number
789
790 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
791 packet.putString(str); // file name
792 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
793
794 packet.putEmptyString();
795 formatDateTime(modified, date, sizeof(date));
796 packet.putString(date); // date modified
797 packet.putEmptyString(); // keywords
798
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400799 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400800 return MTP_RESPONSE_OK;
801}
802
Mike Lockwood59c777a2010-08-02 10:37:41 -0400803MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400804 MtpString& filePath,
805 int64_t& fileLength) {
806 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400807 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400808 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400809 if (result != MTP_RESPONSE_OK) {
810 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400811 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400812 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400813
814 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
815 filePath.setTo(str, strlen16(str));
816 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
817
818 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
819 fileLength = longValues[0];
820 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
821
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400822 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400823 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400824}
825
Mike Lockwood59c777a2010-08-02 10:37:41 -0400826MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400827 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400828 MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
829
830 checkAndClearExceptionFromCallback(env, __FUNCTION__);
831 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400832}
833
834struct PropertyTableEntry {
835 MtpObjectProperty property;
836 int type;
837};
838
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400839static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400840 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
841 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
842 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
843 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
844 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
845 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
846 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
847 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
848 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -0400849 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
850 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
851 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
852 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
853 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
854 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
855 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
856 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
857 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
858 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
859 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400860};
861
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400862static const PropertyTableEntry kDevicePropertyTable[] = {
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800863 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
864 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
865 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400866};
867
868bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
869 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
870 const PropertyTableEntry* entry = kObjectPropertyTable;
871 for (int i = 0; i < count; i++, entry++) {
872 if (entry->property == property) {
873 type = entry->type;
874 return true;
875 }
876 }
877 return false;
878}
879
880bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
881 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
882 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400883 for (int i = 0; i < count; i++, entry++) {
884 if (entry->property == property) {
885 type = entry->type;
886 return true;
887 }
888 }
889 return false;
890}
891
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400892MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
893 JNIEnv* env = AndroidRuntime::getJNIEnv();
894 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
895 (jint)handle);
896 if (!array)
897 return NULL;
898 MtpObjectHandleList* list = new MtpObjectHandleList();
899 jint* handles = env->GetIntArrayElements(array, 0);
900 jsize length = env->GetArrayLength(array);
901 for (int i = 0; i < length; i++)
902 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400903 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400904 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400905
906 checkAndClearExceptionFromCallback(env, __FUNCTION__);
907 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400908}
909
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400910MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
911 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400912 JNIEnv* env = AndroidRuntime::getJNIEnv();
913 int count = references->size();
914 jintArray array = env->NewIntArray(count);
915 if (!array) {
916 LOGE("out of memory in setObjectReferences");
917 return false;
918 }
919 jint* handles = env->GetIntArrayElements(array, 0);
920 for (int i = 0; i < count; i++)
921 handles[i] = (*references)[i];
922 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400923 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400924 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -0400925 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400926
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400927 checkAndClearExceptionFromCallback(env, __FUNCTION__);
928 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400929}
930
Mike Lockwood828d19d2010-08-10 15:20:35 -0400931MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
932 MtpObjectFormat format) {
933 MtpProperty* result = NULL;
934 switch (property) {
935 case MTP_PROPERTY_OBJECT_FORMAT:
936 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400937 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400938 result = new MtpProperty(property, MTP_TYPE_UINT16);
939 break;
940 case MTP_PROPERTY_STORAGE_ID:
941 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400942 case MTP_PROPERTY_DURATION:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400943 result = new MtpProperty(property, MTP_TYPE_UINT32);
944 break;
945 case MTP_PROPERTY_OBJECT_SIZE:
946 result = new MtpProperty(property, MTP_TYPE_UINT64);
947 break;
948 case MTP_PROPERTY_PERSISTENT_UID:
949 result = new MtpProperty(property, MTP_TYPE_UINT128);
950 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400951 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400952 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400953 case MTP_PROPERTY_ARTIST:
954 case MTP_PROPERTY_ALBUM_NAME:
955 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400956 case MTP_PROPERTY_GENRE:
957 case MTP_PROPERTY_COMPOSER:
958 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400959 result = new MtpProperty(property, MTP_TYPE_STR);
960 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -0500961 case MTP_PROPERTY_DATE_MODIFIED:
962 case MTP_PROPERTY_DATE_ADDED:
963 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
964 result = new MtpProperty(property, MTP_TYPE_STR);
965 result->setFormDateTime();
966 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -0400967 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -0400968 // We allow renaming files and folders
969 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -0400970 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400971 }
972
973 return result;
974}
975
976MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800977 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400978 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800979 bool writable = false;
980
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400981 switch (property) {
982 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
983 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800984 writable = true;
985 // fall through
986 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
987 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -0400988
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800989 // get current value
Mike Lockwooda2a21282010-09-25 21:21:05 -0400990 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
991 (jint)property, mLongBuffer, mStringBuffer);
992 if (ret == MTP_RESPONSE_OK) {
993 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
994 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800995 // for read-only properties it is safe to assume current value is default value
996 if (!writable)
997 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -0400998 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
999 } else {
1000 LOGE("unable to read device property, response: %04X", ret);
1001 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001002 break;
1003 }
1004
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001005 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001006 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001007}
1008
Mike Lockwood2837eef2010-08-31 16:25:12 -04001009void MyMtpDatabase::sessionStarted() {
1010 JNIEnv* env = AndroidRuntime::getJNIEnv();
1011 env->CallVoidMethod(mDatabase, method_sessionStarted);
1012 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1013}
1014
1015void MyMtpDatabase::sessionEnded() {
1016 JNIEnv* env = AndroidRuntime::getJNIEnv();
1017 env->CallVoidMethod(mDatabase, method_sessionEnded);
1018 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1019}
1020
Mike Lockwoodff164a72010-07-15 15:01:17 -04001021#endif // HAVE_ANDROID_OS
1022
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001023// ----------------------------------------------------------------------------
1024
1025static void
1026android_media_MtpDatabase_setup(JNIEnv *env, jobject thiz)
1027{
Mike Lockwoodff164a72010-07-15 15:01:17 -04001028#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001029 LOGD("setup\n");
1030 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
1031 env->SetIntField(thiz, field_context, (int)database);
1032 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -04001033#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001034}
1035
1036static void
1037android_media_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
1038{
Mike Lockwoodff164a72010-07-15 15:01:17 -04001039#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001040 LOGD("finalize\n");
1041 MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
1042 database->cleanup(env);
1043 delete database;
1044 env->SetIntField(thiz, field_context, 0);
1045 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -04001046#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001047}
1048
Mike Lockwood31599912010-11-15 13:43:30 -05001049static jstring
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001050android_media_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001051{
1052#ifdef HAVE_ANDROID_OS
1053 char date[20];
1054 formatDateTime(seconds, date, sizeof(date));
1055 return env->NewStringUTF(date);
1056#else
1057 return NULL;
1058#endif
1059}
1060
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001061// ----------------------------------------------------------------------------
1062
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001063static JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001064 {"native_setup", "()V", (void *)android_media_MtpDatabase_setup},
1065 {"native_finalize", "()V", (void *)android_media_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001066};
1067
1068static JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001069 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001070 (void *)android_media_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001071};
1072
1073static const char* const kClassPathName = "android/media/MtpDatabase";
1074
1075int register_android_media_MtpDatabase(JNIEnv *env)
1076{
1077 jclass clazz;
1078
1079 LOGD("register_android_media_MtpDatabase\n");
1080
1081 clazz = env->FindClass("android/media/MtpDatabase");
1082 if (clazz == NULL) {
1083 LOGE("Can't find android/media/MtpDatabase");
1084 return -1;
1085 }
Mike Lockwoodd815f792010-07-12 08:49:01 -04001086 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1087 if (method_beginSendObject == NULL) {
1088 LOGE("Can't find beginSendObject");
1089 return -1;
1090 }
Mike Lockwood413577d2010-11-16 17:38:43 -05001091 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIJZ)V");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001092 if (method_endSendObject == NULL) {
1093 LOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001094 return -1;
1095 }
1096 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1097 if (method_getObjectList == NULL) {
1098 LOGE("Can't find getObjectList");
1099 return -1;
1100 }
Mike Lockwood7a047c82010-08-02 10:52:20 -04001101 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
1102 if (method_getNumObjects == NULL) {
1103 LOGE("Can't find getNumObjects");
1104 return -1;
1105 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001106 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
1107 if (method_getSupportedPlaybackFormats == NULL) {
1108 LOGE("Can't find getSupportedPlaybackFormats");
1109 return -1;
1110 }
1111 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
1112 if (method_getSupportedCaptureFormats == NULL) {
1113 LOGE("Can't find getSupportedCaptureFormats");
1114 return -1;
1115 }
1116 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
1117 if (method_getSupportedObjectProperties == NULL) {
1118 LOGE("Can't find getSupportedObjectProperties");
1119 return -1;
1120 }
1121 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
1122 if (method_getSupportedDeviceProperties == NULL) {
1123 LOGE("Can't find getSupportedDeviceProperties");
1124 return -1;
1125 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001126 method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
1127 if (method_setObjectProperty == NULL) {
1128 LOGE("Can't find setObjectProperty");
1129 return -1;
1130 }
1131 method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
1132 if (method_getDeviceProperty == NULL) {
1133 LOGE("Can't find getDeviceProperty");
1134 return -1;
1135 }
1136 method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
1137 if (method_setDeviceProperty == NULL) {
1138 LOGE("Can't find setDeviceProperty");
1139 return -1;
1140 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001141 method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001142 "(JIJII)Landroid/media/MtpPropertyList;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001143 if (method_getObjectPropertyList == NULL) {
1144 LOGE("Can't find getObjectPropertyList");
1145 return -1;
1146 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001147 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1148 if (method_getObjectInfo == NULL) {
1149 LOGE("Can't find getObjectInfo");
1150 return -1;
1151 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001152 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001153 if (method_getObjectFilePath == NULL) {
1154 LOGE("Can't find getObjectFilePath");
1155 return -1;
1156 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001157 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001158 if (method_deleteFile == NULL) {
1159 LOGE("Can't find deleteFile");
1160 return -1;
1161 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001162 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
1163 if (method_getObjectReferences == NULL) {
1164 LOGE("Can't find getObjectReferences");
1165 return -1;
1166 }
1167 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
1168 if (method_setObjectReferences == NULL) {
1169 LOGE("Can't find setObjectReferences");
1170 return -1;
1171 }
Mike Lockwood2837eef2010-08-31 16:25:12 -04001172 method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
1173 if (method_sessionStarted == NULL) {
1174 LOGE("Can't find sessionStarted");
1175 return -1;
1176 }
1177 method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
1178 if (method_sessionEnded == NULL) {
1179 LOGE("Can't find sessionEnded");
1180 return -1;
1181 }
1182
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001183 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
1184 if (field_context == NULL) {
1185 LOGE("Can't find MtpDatabase.mNativeContext");
1186 return -1;
1187 }
1188
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001189 // now set up fields for MtpPropertyList class
1190 clazz = env->FindClass("android/media/MtpPropertyList");
1191 if (clazz == NULL) {
1192 LOGE("Can't find android/media/MtpPropertyList");
1193 return -1;
1194 }
1195 field_mCount = env->GetFieldID(clazz, "mCount", "I");
1196 if (field_mCount == NULL) {
1197 LOGE("Can't find MtpPropertyList.mCount");
1198 return -1;
1199 }
1200 field_mResult = env->GetFieldID(clazz, "mResult", "I");
1201 if (field_mResult == NULL) {
1202 LOGE("Can't find MtpPropertyList.mResult");
1203 return -1;
1204 }
1205 field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1206 if (field_mObjectHandles == NULL) {
1207 LOGE("Can't find MtpPropertyList.mObjectHandles");
1208 return -1;
1209 }
1210 field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1211 if (field_mPropertyCodes == NULL) {
1212 LOGE("Can't find MtpPropertyList.mPropertyCodes");
1213 return -1;
1214 }
1215 field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1216 if (field_mDataTypes == NULL) {
1217 LOGE("Can't find MtpPropertyList.mDataTypes");
1218 return -1;
1219 }
1220 field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1221 if (field_mLongValues == NULL) {
1222 LOGE("Can't find MtpPropertyList.mLongValues");
1223 return -1;
1224 }
1225 field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1226 if (field_mStringValues == NULL) {
1227 LOGE("Can't find MtpPropertyList.mStringValues");
1228 return -1;
1229 }
1230
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001231 if (AndroidRuntime::registerNativeMethods(env,
1232 "android/media/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
1233 return -1;
1234
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001235 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001236 "android/media/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001237}