blob: 06708da4bae34a4d72dda019a4ebef39782878a7 [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,
102 bool succeeded);
103
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400104 virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
105 MtpObjectFormat format,
106 MtpObjectHandle parent);
107
Mike Lockwood7a047c82010-08-02 10:52:20 -0400108 virtual int getNumObjects(MtpStorageID storageID,
109 MtpObjectFormat format,
110 MtpObjectHandle parent);
111
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400112 // callee should delete[] the results from these
113 // results can be NULL
114 virtual MtpObjectFormatList* getSupportedPlaybackFormats();
115 virtual MtpObjectFormatList* getSupportedCaptureFormats();
116 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
117 virtual MtpDevicePropertyList* getSupportedDeviceProperties();
118
Mike Lockwood828d19d2010-08-10 15:20:35 -0400119 virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400120 MtpObjectProperty property,
121 MtpDataPacket& packet);
122
Mike Lockwood828d19d2010-08-10 15:20:35 -0400123 virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
124 MtpObjectProperty property,
125 MtpDataPacket& packet);
126
127 virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
128 MtpDataPacket& packet);
129
130 virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
131 MtpDataPacket& packet);
132
133 virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
134
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400135 virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500136 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400137 int groupCode, int depth,
138 MtpDataPacket& packet);
139
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400140 virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
141 MtpDataPacket& packet);
142
Mike Lockwood59c777a2010-08-02 10:37:41 -0400143 virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800144 MtpString& outFilePath,
145 int64_t& outFileLength,
146 MtpObjectFormat& outFormat);
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{
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400185 // create buffers for out arguments
186 // we don't need to be thread-safe so this is OK
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700187 jintArray intArray = env->NewIntArray(3);
188 if (!intArray) {
189 return; // Already threw.
190 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400191 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700192 jlongArray longArray = env->NewLongArray(2);
193 if (!longArray) {
194 return; // Already threw.
195 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400196 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700197 jcharArray charArray = env->NewCharArray(256);
198 if (!charArray) {
199 return; // Already threw.
200 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400201 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400202}
203
204void MyMtpDatabase::cleanup(JNIEnv *env) {
205 env->DeleteGlobalRef(mDatabase);
206 env->DeleteGlobalRef(mIntBuffer);
207 env->DeleteGlobalRef(mLongBuffer);
208 env->DeleteGlobalRef(mStringBuffer);
209}
210
211MyMtpDatabase::~MyMtpDatabase() {
212}
213
Mike Lockwoodd815f792010-07-12 08:49:01 -0400214MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400215 MtpObjectFormat format,
216 MtpObjectHandle parent,
217 MtpStorageID storage,
218 uint64_t size,
219 time_t modified) {
220 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400221 jstring pathStr = env->NewStringUTF(path);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400222 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
Mike Lockwood88394712010-09-27 10:01:00 -0400223 pathStr, (jint)format, (jint)parent, (jint)storage,
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400224 (jlong)size, (jlong)modified);
225
Mike Lockwood88394712010-09-27 10:01:00 -0400226 if (pathStr)
227 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400228 checkAndClearExceptionFromCallback(env, __FUNCTION__);
229 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400230}
231
Mike Lockwoodd815f792010-07-12 08:49:01 -0400232void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
Mike Lockwood7a0bd172011-01-18 11:06:19 -0800233 MtpObjectFormat format, bool succeeded) {
Mike Lockwoodd815f792010-07-12 08:49:01 -0400234 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400235 jstring pathStr = env->NewStringUTF(path);
236 env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
Mike Lockwood7a0bd172011-01-18 11:06:19 -0800237 (jint)handle, (jint)format, (jboolean)succeeded);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400238
Mike Lockwood88394712010-09-27 10:01:00 -0400239 if (pathStr)
240 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400241 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400242}
243
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400244MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
245 MtpObjectFormat format,
246 MtpObjectHandle parent) {
247 JNIEnv* env = AndroidRuntime::getJNIEnv();
248 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
249 (jint)storageID, (jint)format, (jint)parent);
250 if (!array)
251 return NULL;
252 MtpObjectHandleList* list = new MtpObjectHandleList();
253 jint* handles = env->GetIntArrayElements(array, 0);
254 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400255 for (int i = 0; i < length; i++)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400256 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400257 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400258 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400259
260 checkAndClearExceptionFromCallback(env, __FUNCTION__);
261 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400262}
263
Mike Lockwood7a047c82010-08-02 10:52:20 -0400264int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
265 MtpObjectFormat format,
266 MtpObjectHandle parent) {
267 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400268 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400269 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400270
271 checkAndClearExceptionFromCallback(env, __FUNCTION__);
272 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400273}
274
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400275MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
276 JNIEnv* env = AndroidRuntime::getJNIEnv();
277 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
278 method_getSupportedPlaybackFormats);
279 if (!array)
280 return NULL;
281 MtpObjectFormatList* list = new MtpObjectFormatList();
282 jint* formats = env->GetIntArrayElements(array, 0);
283 jsize length = env->GetArrayLength(array);
284 for (int i = 0; i < length; i++)
285 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400286 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400287 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400288
289 checkAndClearExceptionFromCallback(env, __FUNCTION__);
290 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400291}
292
293MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
294 JNIEnv* env = AndroidRuntime::getJNIEnv();
295 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
296 method_getSupportedCaptureFormats);
297 if (!array)
298 return NULL;
299 MtpObjectFormatList* list = new MtpObjectFormatList();
300 jint* formats = env->GetIntArrayElements(array, 0);
301 jsize length = env->GetArrayLength(array);
302 for (int i = 0; i < length; i++)
303 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400304 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400305 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400306
307 checkAndClearExceptionFromCallback(env, __FUNCTION__);
308 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400309}
310
311MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
312 JNIEnv* env = AndroidRuntime::getJNIEnv();
313 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
314 method_getSupportedObjectProperties, (jint)format);
315 if (!array)
316 return NULL;
317 MtpObjectPropertyList* list = new MtpObjectPropertyList();
318 jint* properties = env->GetIntArrayElements(array, 0);
319 jsize length = env->GetArrayLength(array);
320 for (int i = 0; i < length; i++)
321 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400322 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400323 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400324
325 checkAndClearExceptionFromCallback(env, __FUNCTION__);
326 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400327}
328
329MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
330 JNIEnv* env = AndroidRuntime::getJNIEnv();
331 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
332 method_getSupportedDeviceProperties);
333 if (!array)
334 return NULL;
335 MtpDevicePropertyList* list = new MtpDevicePropertyList();
336 jint* properties = env->GetIntArrayElements(array, 0);
337 jsize length = env->GetArrayLength(array);
338 for (int i = 0; i < length; i++)
339 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400340 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400341 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400342
343 checkAndClearExceptionFromCallback(env, __FUNCTION__);
344 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400345}
346
Mike Lockwood828d19d2010-08-10 15:20:35 -0400347MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400348 MtpObjectProperty property,
349 MtpDataPacket& packet) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400350 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400351 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500352 (jlong)handle, 0, (jlong)property, 0, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400353 MtpResponseCode result = env->GetIntField(list, field_mResult);
354 int count = env->GetIntField(list, field_mCount);
355 if (result == MTP_RESPONSE_OK && count != 1)
356 result = MTP_RESPONSE_GENERAL_ERROR;
357
358 if (result == MTP_RESPONSE_OK) {
359 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
360 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
361 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
362 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
363 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
364
365 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
366 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
367 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
368 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
369
370 int type = dataTypes[0];
371 jlong longValue = (longValues ? longValues[0] : 0);
372
373 // special case date properties, which are strings to MTP
374 // but stored internally as a uint64
375 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
376 char date[20];
377 formatDateTime(longValue, date, sizeof(date));
378 packet.putString(date);
379 goto out;
380 }
381 // release date is stored internally as just the year
382 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
383 char date[20];
384 snprintf(date, sizeof(date), "%04lld0101T000000", longValue);
385 packet.putString(date);
386 goto out;
387 }
388
389 switch (type) {
390 case MTP_TYPE_INT8:
391 packet.putInt8(longValue);
392 break;
393 case MTP_TYPE_UINT8:
394 packet.putUInt8(longValue);
395 break;
396 case MTP_TYPE_INT16:
397 packet.putInt16(longValue);
398 break;
399 case MTP_TYPE_UINT16:
400 packet.putUInt16(longValue);
401 break;
402 case MTP_TYPE_INT32:
403 packet.putInt32(longValue);
404 break;
405 case MTP_TYPE_UINT32:
406 packet.putUInt32(longValue);
407 break;
408 case MTP_TYPE_INT64:
409 packet.putInt64(longValue);
410 break;
411 case MTP_TYPE_UINT64:
412 packet.putUInt64(longValue);
413 break;
414 case MTP_TYPE_INT128:
415 packet.putInt128(longValue);
416 break;
417 case MTP_TYPE_UINT128:
418 packet.putInt128(longValue);
419 break;
420 case MTP_TYPE_STR:
421 {
422 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
423 if (stringValue) {
424 const char* str = env->GetStringUTFChars(stringValue, NULL);
James Dong39774722011-04-06 11:57:48 -0700425 if (str == NULL) {
426 return MTP_RESPONSE_GENERAL_ERROR;
427 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400428 packet.putString(str);
429 env->ReleaseStringUTFChars(stringValue, str);
430 } else {
431 packet.putEmptyString();
432 }
433 break;
434 }
435 default:
436 LOGE("unsupported type in getObjectPropertyValue\n");
437 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
438 }
439out:
440 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
441 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
442 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
443 if (longValues)
444 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
445
446 env->DeleteLocalRef(objectHandlesArray);
447 env->DeleteLocalRef(propertyCodesArray);
448 env->DeleteLocalRef(dataTypesArray);
449 if (longValuesArray)
450 env->DeleteLocalRef(longValuesArray);
451 if (stringValuesArray)
452 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400453 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400454
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400455 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400456 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400457 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400458}
459
Mike Lockwood828d19d2010-08-10 15:20:35 -0400460MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
461 MtpObjectProperty property,
462 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400463 int type;
464
465 if (!getObjectPropertyInfo(property, type))
466 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
467
468 JNIEnv* env = AndroidRuntime::getJNIEnv();
469 jlong longValue = 0;
470 jstring stringValue = NULL;
471
472 switch (type) {
473 case MTP_TYPE_INT8:
474 longValue = packet.getInt8();
475 break;
476 case MTP_TYPE_UINT8:
477 longValue = packet.getUInt8();
478 break;
479 case MTP_TYPE_INT16:
480 longValue = packet.getInt16();
481 break;
482 case MTP_TYPE_UINT16:
483 longValue = packet.getUInt16();
484 break;
485 case MTP_TYPE_INT32:
486 longValue = packet.getInt32();
487 break;
488 case MTP_TYPE_UINT32:
489 longValue = packet.getUInt32();
490 break;
491 case MTP_TYPE_INT64:
492 longValue = packet.getInt64();
493 break;
494 case MTP_TYPE_UINT64:
495 longValue = packet.getUInt64();
496 break;
497 case MTP_TYPE_STR:
498 {
499 MtpStringBuffer buffer;
500 packet.getString(buffer);
501 stringValue = env->NewStringUTF((const char *)buffer);
502 break;
503 }
504 default:
505 LOGE("unsupported type in getObjectPropertyValue\n");
506 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
507 }
508
509 jint result = env->CallIntMethod(mDatabase, method_setObjectProperty,
510 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400511 if (stringValue)
512 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400513
514 checkAndClearExceptionFromCallback(env, __FUNCTION__);
515 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400516}
517
518MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
519 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400520 int type;
521
522 if (!getDevicePropertyInfo(property, type))
523 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
524
525 JNIEnv* env = AndroidRuntime::getJNIEnv();
526 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
527 (jint)property, mLongBuffer, mStringBuffer);
528 if (result != MTP_RESPONSE_OK) {
529 checkAndClearExceptionFromCallback(env, __FUNCTION__);
530 return result;
531 }
532
533 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
534 jlong longValue = longValues[0];
535 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
536
537 switch (type) {
538 case MTP_TYPE_INT8:
539 packet.putInt8(longValue);
540 break;
541 case MTP_TYPE_UINT8:
542 packet.putUInt8(longValue);
543 break;
544 case MTP_TYPE_INT16:
545 packet.putInt16(longValue);
546 break;
547 case MTP_TYPE_UINT16:
548 packet.putUInt16(longValue);
549 break;
550 case MTP_TYPE_INT32:
551 packet.putInt32(longValue);
552 break;
553 case MTP_TYPE_UINT32:
554 packet.putUInt32(longValue);
555 break;
556 case MTP_TYPE_INT64:
557 packet.putInt64(longValue);
558 break;
559 case MTP_TYPE_UINT64:
560 packet.putUInt64(longValue);
561 break;
562 case MTP_TYPE_INT128:
563 packet.putInt128(longValue);
564 break;
565 case MTP_TYPE_UINT128:
566 packet.putInt128(longValue);
567 break;
568 case MTP_TYPE_STR:
569 {
570 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
571 packet.putString(str);
572 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
573 break;
574 }
575 default:
576 LOGE("unsupported type in getDevicePropertyValue\n");
577 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
578 }
579
580 checkAndClearExceptionFromCallback(env, __FUNCTION__);
581 return MTP_RESPONSE_OK;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400582}
583
584MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
585 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400586 int type;
587
588 if (!getDevicePropertyInfo(property, type))
589 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
590
591 JNIEnv* env = AndroidRuntime::getJNIEnv();
592 jlong longValue = 0;
593 jstring stringValue = NULL;
594
595 switch (type) {
596 case MTP_TYPE_INT8:
597 longValue = packet.getInt8();
598 break;
599 case MTP_TYPE_UINT8:
600 longValue = packet.getUInt8();
601 break;
602 case MTP_TYPE_INT16:
603 longValue = packet.getInt16();
604 break;
605 case MTP_TYPE_UINT16:
606 longValue = packet.getUInt16();
607 break;
608 case MTP_TYPE_INT32:
609 longValue = packet.getInt32();
610 break;
611 case MTP_TYPE_UINT32:
612 longValue = packet.getUInt32();
613 break;
614 case MTP_TYPE_INT64:
615 longValue = packet.getInt64();
616 break;
617 case MTP_TYPE_UINT64:
618 longValue = packet.getUInt64();
619 break;
620 case MTP_TYPE_STR:
621 {
622 MtpStringBuffer buffer;
623 packet.getString(buffer);
624 stringValue = env->NewStringUTF((const char *)buffer);
625 break;
626 }
627 default:
628 LOGE("unsupported type in setDevicePropertyValue\n");
629 return MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
630 }
631
632 jint result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
633 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400634 if (stringValue)
635 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400636
637 checkAndClearExceptionFromCallback(env, __FUNCTION__);
638 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400639}
640
641MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty property) {
642 return -1;
643}
644
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400645MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500646 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400647 int groupCode, int depth,
648 MtpDataPacket& packet) {
649 JNIEnv* env = AndroidRuntime::getJNIEnv();
650 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500651 (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
652 checkAndClearExceptionFromCallback(env, __FUNCTION__);
653 if (!list)
654 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400655 int count = env->GetIntField(list, field_mCount);
656 MtpResponseCode result = env->GetIntField(list, field_mResult);
657
658 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400659 if (count > 0) {
660 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
661 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
662 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
663 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
664 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
665
666 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
667 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
668 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
669 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
670
671 for (int i = 0; i < count; i++) {
672 packet.putUInt32(objectHandles[i]);
673 packet.putUInt16(propertyCodes[i]);
674 int type = dataTypes[i];
675 packet.putUInt16(type);
676
677 switch (type) {
678 case MTP_TYPE_INT8:
679 packet.putInt8(longValues[i]);
680 break;
681 case MTP_TYPE_UINT8:
682 packet.putUInt8(longValues[i]);
683 break;
684 case MTP_TYPE_INT16:
685 packet.putInt16(longValues[i]);
686 break;
687 case MTP_TYPE_UINT16:
688 packet.putUInt16(longValues[i]);
689 break;
690 case MTP_TYPE_INT32:
691 packet.putInt32(longValues[i]);
692 break;
693 case MTP_TYPE_UINT32:
694 packet.putUInt32(longValues[i]);
695 break;
696 case MTP_TYPE_INT64:
697 packet.putInt64(longValues[i]);
698 break;
699 case MTP_TYPE_UINT64:
700 packet.putUInt64(longValues[i]);
701 break;
702 case MTP_TYPE_INT128:
703 packet.putInt128(longValues[i]);
704 break;
705 case MTP_TYPE_UINT128:
706 packet.putUInt128(longValues[i]);
707 break;
708 case MTP_TYPE_STR: {
709 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
Mike Lockwood2711e492010-12-11 11:24:37 -0800710 const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400711 if (valueStr) {
712 packet.putString(valueStr);
713 env->ReleaseStringUTFChars(value, valueStr);
714 } else {
715 packet.putEmptyString();
716 }
717 env->DeleteLocalRef(value);
718 break;
719 }
720 default:
721 LOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
722 break;
723 }
724 }
725
726 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
727 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
728 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
729 if (longValues)
730 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
731
732 env->DeleteLocalRef(objectHandlesArray);
733 env->DeleteLocalRef(propertyCodesArray);
734 env->DeleteLocalRef(dataTypesArray);
735 if (longValuesArray)
736 env->DeleteLocalRef(longValuesArray);
737 if (stringValuesArray)
738 env->DeleteLocalRef(stringValuesArray);
739 }
740
741 env->DeleteLocalRef(list);
742 checkAndClearExceptionFromCallback(env, __FUNCTION__);
743 return result;
744}
745
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400746MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
747 MtpDataPacket& packet) {
748 char date[20];
749
750 JNIEnv* env = AndroidRuntime::getJNIEnv();
751 jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
752 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
753 if (!result)
754 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
755
756 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
757 MtpStorageID storageID = intValues[0];
758 MtpObjectFormat format = intValues[1];
759 MtpObjectHandle parent = intValues[2];
760 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
761
762 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
763 uint64_t size = longValues[0];
764 uint64_t modified = longValues[1];
765 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
766
Mike Lockwood828d19d2010-08-10 15:20:35 -0400767// int associationType = (format == MTP_FORMAT_ASSOCIATION ?
768// MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
769// MTP_ASSOCIATION_TYPE_UNDEFINED);
770 int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400771
772 packet.putUInt32(storageID);
773 packet.putUInt16(format);
774 packet.putUInt16(0); // protection status
775 packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
776 packet.putUInt16(0); // thumb format
777 packet.putUInt32(0); // thumb compressed size
778 packet.putUInt32(0); // thumb pix width
779 packet.putUInt32(0); // thumb pix height
780 packet.putUInt32(0); // image pix width
781 packet.putUInt32(0); // image pix height
782 packet.putUInt32(0); // image bit depth
783 packet.putUInt32(parent);
784 packet.putUInt16(associationType);
785 packet.putUInt32(0); // association desc
786 packet.putUInt32(0); // sequence number
787
788 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
789 packet.putString(str); // file name
790 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
791
792 packet.putEmptyString();
793 formatDateTime(modified, date, sizeof(date));
794 packet.putString(date); // date modified
795 packet.putEmptyString(); // keywords
796
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400797 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400798 return MTP_RESPONSE_OK;
799}
800
Mike Lockwood59c777a2010-08-02 10:37:41 -0400801MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800802 MtpString& outFilePath,
803 int64_t& outFileLength,
804 MtpObjectFormat& outFormat) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400805 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400806 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400807 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400808 if (result != MTP_RESPONSE_OK) {
809 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400810 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400811 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400812
813 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800814 outFilePath.setTo(str, strlen16(str));
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400815 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
816
817 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800818 outFileLength = longValues[0];
819 outFormat = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400820 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700821
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:
Mike Lockwood9b5e9c42010-12-07 18:53:50 -0800936 // use format as default value
937 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
938 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400939 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400940 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400941 result = new MtpProperty(property, MTP_TYPE_UINT16);
942 break;
943 case MTP_PROPERTY_STORAGE_ID:
944 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400945 case MTP_PROPERTY_DURATION:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400946 result = new MtpProperty(property, MTP_TYPE_UINT32);
947 break;
948 case MTP_PROPERTY_OBJECT_SIZE:
949 result = new MtpProperty(property, MTP_TYPE_UINT64);
950 break;
951 case MTP_PROPERTY_PERSISTENT_UID:
952 result = new MtpProperty(property, MTP_TYPE_UINT128);
953 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400954 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400955 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400956 case MTP_PROPERTY_ARTIST:
957 case MTP_PROPERTY_ALBUM_NAME:
958 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400959 case MTP_PROPERTY_GENRE:
960 case MTP_PROPERTY_COMPOSER:
961 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400962 result = new MtpProperty(property, MTP_TYPE_STR);
963 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -0500964 case MTP_PROPERTY_DATE_MODIFIED:
965 case MTP_PROPERTY_DATE_ADDED:
966 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
967 result = new MtpProperty(property, MTP_TYPE_STR);
968 result->setFormDateTime();
969 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -0400970 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -0400971 // We allow renaming files and folders
972 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -0400973 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400974 }
975
976 return result;
977}
978
979MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800980 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400981 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800982 bool writable = false;
983
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400984 switch (property) {
985 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
986 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800987 writable = true;
988 // fall through
989 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
990 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -0400991
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800992 // get current value
Mike Lockwooda2a21282010-09-25 21:21:05 -0400993 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
994 (jint)property, mLongBuffer, mStringBuffer);
995 if (ret == MTP_RESPONSE_OK) {
996 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
997 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800998 // for read-only properties it is safe to assume current value is default value
999 if (!writable)
1000 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001001 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
1002 } else {
1003 LOGE("unable to read device property, response: %04X", ret);
1004 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001005 break;
1006 }
1007
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001008 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001009 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001010}
1011
Mike Lockwood2837eef2010-08-31 16:25:12 -04001012void MyMtpDatabase::sessionStarted() {
1013 JNIEnv* env = AndroidRuntime::getJNIEnv();
1014 env->CallVoidMethod(mDatabase, method_sessionStarted);
1015 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1016}
1017
1018void MyMtpDatabase::sessionEnded() {
1019 JNIEnv* env = AndroidRuntime::getJNIEnv();
1020 env->CallVoidMethod(mDatabase, method_sessionEnded);
1021 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1022}
1023
Mike Lockwoodff164a72010-07-15 15:01:17 -04001024#endif // HAVE_ANDROID_OS
1025
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001026// ----------------------------------------------------------------------------
1027
1028static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001029android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001030{
Mike Lockwoodff164a72010-07-15 15:01:17 -04001031#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001032 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
1033 env->SetIntField(thiz, field_context, (int)database);
1034 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -04001035#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001036}
1037
1038static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001039android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001040{
Mike Lockwoodff164a72010-07-15 15:01:17 -04001041#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001042 MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
1043 database->cleanup(env);
1044 delete database;
1045 env->SetIntField(thiz, field_context, 0);
1046 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -04001047#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001048}
1049
Mike Lockwood31599912010-11-15 13:43:30 -05001050static jstring
Mike Lockwood0cd01362010-12-30 11:54:33 -05001051android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject thiz, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001052{
1053#ifdef HAVE_ANDROID_OS
1054 char date[20];
1055 formatDateTime(seconds, date, sizeof(date));
1056 return env->NewStringUTF(date);
1057#else
1058 return NULL;
1059#endif
1060}
1061
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001062// ----------------------------------------------------------------------------
1063
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001064static JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001065 {"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
1066 {"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001067};
1068
1069static JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001070 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001071 (void *)android_mtp_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001072};
1073
Mike Lockwood0cd01362010-12-30 11:54:33 -05001074static const char* const kClassPathName = "android/mtp/MtpDatabase";
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001075
Mike Lockwood0cd01362010-12-30 11:54:33 -05001076int register_android_mtp_MtpDatabase(JNIEnv *env)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001077{
1078 jclass clazz;
1079
Mike Lockwood0cd01362010-12-30 11:54:33 -05001080 clazz = env->FindClass("android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001081 if (clazz == NULL) {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001082 LOGE("Can't find android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001083 return -1;
1084 }
Mike Lockwoodd815f792010-07-12 08:49:01 -04001085 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1086 if (method_beginSendObject == NULL) {
1087 LOGE("Can't find beginSendObject");
1088 return -1;
1089 }
Mike Lockwood7a0bd172011-01-18 11:06:19 -08001090 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001091 if (method_endSendObject == NULL) {
1092 LOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001093 return -1;
1094 }
1095 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1096 if (method_getObjectList == NULL) {
1097 LOGE("Can't find getObjectList");
1098 return -1;
1099 }
Mike Lockwood7a047c82010-08-02 10:52:20 -04001100 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
1101 if (method_getNumObjects == NULL) {
1102 LOGE("Can't find getNumObjects");
1103 return -1;
1104 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001105 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
1106 if (method_getSupportedPlaybackFormats == NULL) {
1107 LOGE("Can't find getSupportedPlaybackFormats");
1108 return -1;
1109 }
1110 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
1111 if (method_getSupportedCaptureFormats == NULL) {
1112 LOGE("Can't find getSupportedCaptureFormats");
1113 return -1;
1114 }
1115 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
1116 if (method_getSupportedObjectProperties == NULL) {
1117 LOGE("Can't find getSupportedObjectProperties");
1118 return -1;
1119 }
1120 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
1121 if (method_getSupportedDeviceProperties == NULL) {
1122 LOGE("Can't find getSupportedDeviceProperties");
1123 return -1;
1124 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001125 method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
1126 if (method_setObjectProperty == NULL) {
1127 LOGE("Can't find setObjectProperty");
1128 return -1;
1129 }
1130 method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
1131 if (method_getDeviceProperty == NULL) {
1132 LOGE("Can't find getDeviceProperty");
1133 return -1;
1134 }
1135 method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
1136 if (method_setDeviceProperty == NULL) {
1137 LOGE("Can't find setDeviceProperty");
1138 return -1;
1139 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001140 method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001141 "(JIJII)Landroid/mtp/MtpPropertyList;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001142 if (method_getObjectPropertyList == NULL) {
1143 LOGE("Can't find getObjectPropertyList");
1144 return -1;
1145 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001146 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1147 if (method_getObjectInfo == NULL) {
1148 LOGE("Can't find getObjectInfo");
1149 return -1;
1150 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001151 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001152 if (method_getObjectFilePath == NULL) {
1153 LOGE("Can't find getObjectFilePath");
1154 return -1;
1155 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001156 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001157 if (method_deleteFile == NULL) {
1158 LOGE("Can't find deleteFile");
1159 return -1;
1160 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001161 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
1162 if (method_getObjectReferences == NULL) {
1163 LOGE("Can't find getObjectReferences");
1164 return -1;
1165 }
1166 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
1167 if (method_setObjectReferences == NULL) {
1168 LOGE("Can't find setObjectReferences");
1169 return -1;
1170 }
Mike Lockwood2837eef2010-08-31 16:25:12 -04001171 method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
1172 if (method_sessionStarted == NULL) {
1173 LOGE("Can't find sessionStarted");
1174 return -1;
1175 }
1176 method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
1177 if (method_sessionEnded == NULL) {
1178 LOGE("Can't find sessionEnded");
1179 return -1;
1180 }
1181
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001182 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
1183 if (field_context == NULL) {
1184 LOGE("Can't find MtpDatabase.mNativeContext");
1185 return -1;
1186 }
1187
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001188 // now set up fields for MtpPropertyList class
Mike Lockwood0cd01362010-12-30 11:54:33 -05001189 clazz = env->FindClass("android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001190 if (clazz == NULL) {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001191 LOGE("Can't find android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001192 return -1;
1193 }
1194 field_mCount = env->GetFieldID(clazz, "mCount", "I");
1195 if (field_mCount == NULL) {
1196 LOGE("Can't find MtpPropertyList.mCount");
1197 return -1;
1198 }
1199 field_mResult = env->GetFieldID(clazz, "mResult", "I");
1200 if (field_mResult == NULL) {
1201 LOGE("Can't find MtpPropertyList.mResult");
1202 return -1;
1203 }
1204 field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1205 if (field_mObjectHandles == NULL) {
1206 LOGE("Can't find MtpPropertyList.mObjectHandles");
1207 return -1;
1208 }
1209 field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1210 if (field_mPropertyCodes == NULL) {
1211 LOGE("Can't find MtpPropertyList.mPropertyCodes");
1212 return -1;
1213 }
1214 field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1215 if (field_mDataTypes == NULL) {
1216 LOGE("Can't find MtpPropertyList.mDataTypes");
1217 return -1;
1218 }
1219 field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1220 if (field_mLongValues == NULL) {
1221 LOGE("Can't find MtpPropertyList.mLongValues");
1222 return -1;
1223 }
1224 field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1225 if (field_mStringValues == NULL) {
1226 LOGE("Can't find MtpPropertyList.mStringValues");
1227 return -1;
1228 }
1229
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001230 if (AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001231 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001232 return -1;
1233
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001234 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001235 "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001236}