blob: aa29de8449deba25028188260a750909815308e9 [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,
136 MtpObjectFormat format,
137 MtpObjectProperty property,
138 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,
238 MtpObjectFormat format, bool succeeded) {
239 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 Lockwoodd815f792010-07-12 08:49:01 -0400242 (jint)handle, (jint)format, (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,
357 (jint)handle, 0, (jint)property, 0, 0);
358 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,
648 MtpObjectFormat format,
649 MtpObjectProperty property,
650 int groupCode, int depth,
651 MtpDataPacket& packet) {
652 JNIEnv* env = AndroidRuntime::getJNIEnv();
653 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
654 (jint)handle, (jint)format, (jint)property, (jint)groupCode, (jint)depth);
655 int count = env->GetIntField(list, field_mCount);
656 MtpResponseCode result = env->GetIntField(list, field_mResult);
657
658 packet.putUInt32(count);
659
660 if (count > 0) {
661 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
662 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
663 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
664 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
665 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
666
667 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
668 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
669 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
670 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
671
672 for (int i = 0; i < count; i++) {
673 packet.putUInt32(objectHandles[i]);
674 packet.putUInt16(propertyCodes[i]);
675 int type = dataTypes[i];
676 packet.putUInt16(type);
677
678 switch (type) {
679 case MTP_TYPE_INT8:
680 packet.putInt8(longValues[i]);
681 break;
682 case MTP_TYPE_UINT8:
683 packet.putUInt8(longValues[i]);
684 break;
685 case MTP_TYPE_INT16:
686 packet.putInt16(longValues[i]);
687 break;
688 case MTP_TYPE_UINT16:
689 packet.putUInt16(longValues[i]);
690 break;
691 case MTP_TYPE_INT32:
692 packet.putInt32(longValues[i]);
693 break;
694 case MTP_TYPE_UINT32:
695 packet.putUInt32(longValues[i]);
696 break;
697 case MTP_TYPE_INT64:
698 packet.putInt64(longValues[i]);
699 break;
700 case MTP_TYPE_UINT64:
701 packet.putUInt64(longValues[i]);
702 break;
703 case MTP_TYPE_INT128:
704 packet.putInt128(longValues[i]);
705 break;
706 case MTP_TYPE_UINT128:
707 packet.putUInt128(longValues[i]);
708 break;
709 case MTP_TYPE_STR: {
710 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
711 const char *valueStr = env->GetStringUTFChars(value, NULL);
712 if (valueStr) {
713 packet.putString(valueStr);
714 env->ReleaseStringUTFChars(value, valueStr);
715 } else {
716 packet.putEmptyString();
717 }
718 env->DeleteLocalRef(value);
719 break;
720 }
721 default:
722 LOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
723 break;
724 }
725 }
726
727 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
728 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
729 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
730 if (longValues)
731 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
732
733 env->DeleteLocalRef(objectHandlesArray);
734 env->DeleteLocalRef(propertyCodesArray);
735 env->DeleteLocalRef(dataTypesArray);
736 if (longValuesArray)
737 env->DeleteLocalRef(longValuesArray);
738 if (stringValuesArray)
739 env->DeleteLocalRef(stringValuesArray);
740 }
741
742 env->DeleteLocalRef(list);
743 checkAndClearExceptionFromCallback(env, __FUNCTION__);
744 return result;
745}
746
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400747MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
748 MtpDataPacket& packet) {
749 char date[20];
750
751 JNIEnv* env = AndroidRuntime::getJNIEnv();
752 jboolean result = env->CallBooleanMethod(mDatabase, method_getObjectInfo,
753 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer);
754 if (!result)
755 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
756
757 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
758 MtpStorageID storageID = intValues[0];
759 MtpObjectFormat format = intValues[1];
760 MtpObjectHandle parent = intValues[2];
761 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
762
763 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
764 uint64_t size = longValues[0];
765 uint64_t modified = longValues[1];
766 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
767
Mike Lockwood828d19d2010-08-10 15:20:35 -0400768// int associationType = (format == MTP_FORMAT_ASSOCIATION ?
769// MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
770// MTP_ASSOCIATION_TYPE_UNDEFINED);
771 int associationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400772
773 packet.putUInt32(storageID);
774 packet.putUInt16(format);
775 packet.putUInt16(0); // protection status
776 packet.putUInt32((size > 0xFFFFFFFFLL ? 0xFFFFFFFF : size));
777 packet.putUInt16(0); // thumb format
778 packet.putUInt32(0); // thumb compressed size
779 packet.putUInt32(0); // thumb pix width
780 packet.putUInt32(0); // thumb pix height
781 packet.putUInt32(0); // image pix width
782 packet.putUInt32(0); // image pix height
783 packet.putUInt32(0); // image bit depth
784 packet.putUInt32(parent);
785 packet.putUInt16(associationType);
786 packet.putUInt32(0); // association desc
787 packet.putUInt32(0); // sequence number
788
789 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
790 packet.putString(str); // file name
791 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
792
793 packet.putEmptyString();
794 formatDateTime(modified, date, sizeof(date));
795 packet.putString(date); // date modified
796 packet.putEmptyString(); // keywords
797
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400798 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400799 return MTP_RESPONSE_OK;
800}
801
Mike Lockwood59c777a2010-08-02 10:37:41 -0400802MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400803 MtpString& filePath,
804 int64_t& fileLength) {
805 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);
814 filePath.setTo(str, strlen16(str));
815 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
816
817 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
818 fileLength = longValues[0];
819 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
820
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400821 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400822 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400823}
824
Mike Lockwood59c777a2010-08-02 10:37:41 -0400825MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400826 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400827 MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
828
829 checkAndClearExceptionFromCallback(env, __FUNCTION__);
830 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400831}
832
833struct PropertyTableEntry {
834 MtpObjectProperty property;
835 int type;
836};
837
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400838static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400839 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
840 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
841 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
842 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
843 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
844 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
845 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
846 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
847 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -0400848 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
849 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
850 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
851 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
852 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
853 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
854 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
855 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
856 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
857 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
858 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400859};
860
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400861static const PropertyTableEntry kDevicePropertyTable[] = {
862 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
863 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
864};
865
866bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
867 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
868 const PropertyTableEntry* entry = kObjectPropertyTable;
869 for (int i = 0; i < count; i++, entry++) {
870 if (entry->property == property) {
871 type = entry->type;
872 return true;
873 }
874 }
875 return false;
876}
877
878bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
879 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
880 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400881 for (int i = 0; i < count; i++, entry++) {
882 if (entry->property == property) {
883 type = entry->type;
884 return true;
885 }
886 }
887 return false;
888}
889
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400890MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
891 JNIEnv* env = AndroidRuntime::getJNIEnv();
892 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
893 (jint)handle);
894 if (!array)
895 return NULL;
896 MtpObjectHandleList* list = new MtpObjectHandleList();
897 jint* handles = env->GetIntArrayElements(array, 0);
898 jsize length = env->GetArrayLength(array);
899 for (int i = 0; i < length; i++)
900 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400901 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400902 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400903
904 checkAndClearExceptionFromCallback(env, __FUNCTION__);
905 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400906}
907
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400908MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
909 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400910 JNIEnv* env = AndroidRuntime::getJNIEnv();
911 int count = references->size();
912 jintArray array = env->NewIntArray(count);
913 if (!array) {
914 LOGE("out of memory in setObjectReferences");
915 return false;
916 }
917 jint* handles = env->GetIntArrayElements(array, 0);
918 for (int i = 0; i < count; i++)
919 handles[i] = (*references)[i];
920 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400921 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400922 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -0400923 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400924
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400925 checkAndClearExceptionFromCallback(env, __FUNCTION__);
926 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400927}
928
Mike Lockwood828d19d2010-08-10 15:20:35 -0400929MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
930 MtpObjectFormat format) {
931 MtpProperty* result = NULL;
932 switch (property) {
933 case MTP_PROPERTY_OBJECT_FORMAT:
934 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400935 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400936 result = new MtpProperty(property, MTP_TYPE_UINT16);
937 break;
938 case MTP_PROPERTY_STORAGE_ID:
939 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400940 case MTP_PROPERTY_DURATION:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400941 result = new MtpProperty(property, MTP_TYPE_UINT32);
942 break;
943 case MTP_PROPERTY_OBJECT_SIZE:
944 result = new MtpProperty(property, MTP_TYPE_UINT64);
945 break;
946 case MTP_PROPERTY_PERSISTENT_UID:
947 result = new MtpProperty(property, MTP_TYPE_UINT128);
948 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400949 case MTP_PROPERTY_NAME:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400950 case MTP_PROPERTY_DATE_MODIFIED:
Mike Lockwoodae078f72010-09-26 12:35:51 -0400951 case MTP_PROPERTY_DISPLAY_NAME:
952 case MTP_PROPERTY_DATE_ADDED:
953 case MTP_PROPERTY_ARTIST:
954 case MTP_PROPERTY_ALBUM_NAME:
955 case MTP_PROPERTY_ALBUM_ARTIST:
956 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
957 case MTP_PROPERTY_GENRE:
958 case MTP_PROPERTY_COMPOSER:
959 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -0400960 result = new MtpProperty(property, MTP_TYPE_STR);
961 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -0400962 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -0400963 // We allow renaming files and folders
964 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -0400965 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400966 }
967
968 return result;
969}
970
971MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400972 MtpProperty* result = NULL;
973 switch (property) {
974 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
975 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
Mike Lockwooda2a21282010-09-25 21:21:05 -0400976 {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400977 // writeable string properties
978 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwooda2a21282010-09-25 21:21:05 -0400979
980 // set current value
981 JNIEnv* env = AndroidRuntime::getJNIEnv();
982 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
983 (jint)property, mLongBuffer, mStringBuffer);
984 if (ret == MTP_RESPONSE_OK) {
985 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
986 result->setCurrentValue(str);
987 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
988 } else {
989 LOGE("unable to read device property, response: %04X", ret);
990 }
991
992 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400993 break;
Mike Lockwooda2a21282010-09-25 21:21:05 -0400994 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400995 }
996
997 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400998}
999
Mike Lockwood2837eef2010-08-31 16:25:12 -04001000void MyMtpDatabase::sessionStarted() {
1001 JNIEnv* env = AndroidRuntime::getJNIEnv();
1002 env->CallVoidMethod(mDatabase, method_sessionStarted);
1003 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1004}
1005
1006void MyMtpDatabase::sessionEnded() {
1007 JNIEnv* env = AndroidRuntime::getJNIEnv();
1008 env->CallVoidMethod(mDatabase, method_sessionEnded);
1009 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1010}
1011
Mike Lockwoodff164a72010-07-15 15:01:17 -04001012#endif // HAVE_ANDROID_OS
1013
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001014// ----------------------------------------------------------------------------
1015
1016static void
1017android_media_MtpDatabase_setup(JNIEnv *env, jobject thiz)
1018{
Mike Lockwoodff164a72010-07-15 15:01:17 -04001019#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001020 LOGD("setup\n");
1021 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
1022 env->SetIntField(thiz, field_context, (int)database);
1023 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -04001024#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001025}
1026
1027static void
1028android_media_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
1029{
Mike Lockwoodff164a72010-07-15 15:01:17 -04001030#ifdef HAVE_ANDROID_OS
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001031 LOGD("finalize\n");
1032 MyMtpDatabase* database = (MyMtpDatabase *)env->GetIntField(thiz, field_context);
1033 database->cleanup(env);
1034 delete database;
1035 env->SetIntField(thiz, field_context, 0);
1036 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodff164a72010-07-15 15:01:17 -04001037#endif
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001038}
1039
1040// ----------------------------------------------------------------------------
1041
1042static JNINativeMethod gMethods[] = {
1043 {"native_setup", "()V", (void *)android_media_MtpDatabase_setup},
1044 {"native_finalize", "()V", (void *)android_media_MtpDatabase_finalize},
1045};
1046
1047static const char* const kClassPathName = "android/media/MtpDatabase";
1048
1049int register_android_media_MtpDatabase(JNIEnv *env)
1050{
1051 jclass clazz;
1052
1053 LOGD("register_android_media_MtpDatabase\n");
1054
1055 clazz = env->FindClass("android/media/MtpDatabase");
1056 if (clazz == NULL) {
1057 LOGE("Can't find android/media/MtpDatabase");
1058 return -1;
1059 }
Mike Lockwoodd815f792010-07-12 08:49:01 -04001060 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1061 if (method_beginSendObject == NULL) {
1062 LOGE("Can't find beginSendObject");
1063 return -1;
1064 }
1065 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
1066 if (method_endSendObject == NULL) {
1067 LOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001068 return -1;
1069 }
1070 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1071 if (method_getObjectList == NULL) {
1072 LOGE("Can't find getObjectList");
1073 return -1;
1074 }
Mike Lockwood7a047c82010-08-02 10:52:20 -04001075 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
1076 if (method_getNumObjects == NULL) {
1077 LOGE("Can't find getNumObjects");
1078 return -1;
1079 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001080 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
1081 if (method_getSupportedPlaybackFormats == NULL) {
1082 LOGE("Can't find getSupportedPlaybackFormats");
1083 return -1;
1084 }
1085 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
1086 if (method_getSupportedCaptureFormats == NULL) {
1087 LOGE("Can't find getSupportedCaptureFormats");
1088 return -1;
1089 }
1090 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
1091 if (method_getSupportedObjectProperties == NULL) {
1092 LOGE("Can't find getSupportedObjectProperties");
1093 return -1;
1094 }
1095 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
1096 if (method_getSupportedDeviceProperties == NULL) {
1097 LOGE("Can't find getSupportedDeviceProperties");
1098 return -1;
1099 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001100 method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
1101 if (method_setObjectProperty == NULL) {
1102 LOGE("Can't find setObjectProperty");
1103 return -1;
1104 }
1105 method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
1106 if (method_getDeviceProperty == NULL) {
1107 LOGE("Can't find getDeviceProperty");
1108 return -1;
1109 }
1110 method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
1111 if (method_setDeviceProperty == NULL) {
1112 LOGE("Can't find setDeviceProperty");
1113 return -1;
1114 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001115 method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
1116 "(IIIII)Landroid/media/MtpPropertyList;");
1117 if (method_getObjectPropertyList == NULL) {
1118 LOGE("Can't find getObjectPropertyList");
1119 return -1;
1120 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001121 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1122 if (method_getObjectInfo == NULL) {
1123 LOGE("Can't find getObjectInfo");
1124 return -1;
1125 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001126 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001127 if (method_getObjectFilePath == NULL) {
1128 LOGE("Can't find getObjectFilePath");
1129 return -1;
1130 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001131 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001132 if (method_deleteFile == NULL) {
1133 LOGE("Can't find deleteFile");
1134 return -1;
1135 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001136 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
1137 if (method_getObjectReferences == NULL) {
1138 LOGE("Can't find getObjectReferences");
1139 return -1;
1140 }
1141 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
1142 if (method_setObjectReferences == NULL) {
1143 LOGE("Can't find setObjectReferences");
1144 return -1;
1145 }
Mike Lockwood2837eef2010-08-31 16:25:12 -04001146 method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
1147 if (method_sessionStarted == NULL) {
1148 LOGE("Can't find sessionStarted");
1149 return -1;
1150 }
1151 method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
1152 if (method_sessionEnded == NULL) {
1153 LOGE("Can't find sessionEnded");
1154 return -1;
1155 }
1156
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001157 field_context = env->GetFieldID(clazz, "mNativeContext", "I");
1158 if (field_context == NULL) {
1159 LOGE("Can't find MtpDatabase.mNativeContext");
1160 return -1;
1161 }
1162
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001163 // now set up fields for MtpPropertyList class
1164 clazz = env->FindClass("android/media/MtpPropertyList");
1165 if (clazz == NULL) {
1166 LOGE("Can't find android/media/MtpPropertyList");
1167 return -1;
1168 }
1169 field_mCount = env->GetFieldID(clazz, "mCount", "I");
1170 if (field_mCount == NULL) {
1171 LOGE("Can't find MtpPropertyList.mCount");
1172 return -1;
1173 }
1174 field_mResult = env->GetFieldID(clazz, "mResult", "I");
1175 if (field_mResult == NULL) {
1176 LOGE("Can't find MtpPropertyList.mResult");
1177 return -1;
1178 }
1179 field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1180 if (field_mObjectHandles == NULL) {
1181 LOGE("Can't find MtpPropertyList.mObjectHandles");
1182 return -1;
1183 }
1184 field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1185 if (field_mPropertyCodes == NULL) {
1186 LOGE("Can't find MtpPropertyList.mPropertyCodes");
1187 return -1;
1188 }
1189 field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1190 if (field_mDataTypes == NULL) {
1191 LOGE("Can't find MtpPropertyList.mDataTypes");
1192 return -1;
1193 }
1194 field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1195 if (field_mLongValues == NULL) {
1196 LOGE("Can't find MtpPropertyList.mLongValues");
1197 return -1;
1198 }
1199 field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1200 if (field_mStringValues == NULL) {
1201 LOGE("Can't find MtpPropertyList.mStringValues");
1202 return -1;
1203 }
1204
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001205 return AndroidRuntime::registerNativeMethods(env,
1206 "android/media/MtpDatabase", gMethods, NELEM(gMethods));
1207}