blob: b8e850a32bbbcea4076ffe3aaa675ddfe49a9dbd [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
Mike Lockwoodd21eac92010-07-03 00:44:05 -040020#include <assert.h>
Mike Lockwoodd21eac92010-07-03 00:44:05 -040021#include <fcntl.h>
Mark Salyzynaeb75fc2014-03-20 12:09:01 -070022#include <inttypes.h>
23#include <limits.h>
24#include <stdio.h>
25#include <unistd.h>
Mike Lockwoodd21eac92010-07-03 00:44:05 -040026
27#include "jni.h"
28#include "JNIHelp.h"
29#include "android_runtime/AndroidRuntime.h"
Ruben Brunk87eac992013-09-09 17:44:59 -070030#include "android_runtime/Log.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040031
32#include "MtpDatabase.h"
33#include "MtpDataPacket.h"
Mike Lockwood9df53fae2011-04-21 17:05:55 -070034#include "MtpObjectInfo.h"
Mike Lockwood828d19d2010-08-10 15:20:35 -040035#include "MtpProperty.h"
Mike Lockwood59e3f0d2010-09-02 14:57:30 -040036#include "MtpStringBuffer.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040037#include "MtpUtils.h"
38#include "mtp.h"
39
Mike Lockwoodc89f2222011-04-24 18:40:17 -070040extern "C" {
Marco Nelissen3cd393c2014-01-10 10:39:27 -080041#include "libexif/exif-content.h"
42#include "libexif/exif-data.h"
43#include "libexif/exif-tag.h"
44#include "libexif/exif-utils.h"
Mike Lockwoodc89f2222011-04-24 18:40:17 -070045}
46
Mike Lockwoodd21eac92010-07-03 00:44:05 -040047using namespace android;
48
49// ----------------------------------------------------------------------------
50
Mike Lockwoodd815f792010-07-12 08:49:01 -040051static jmethodID method_beginSendObject;
52static jmethodID method_endSendObject;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040053static jmethodID method_getObjectList;
Mike Lockwood7a047c82010-08-02 10:52:20 -040054static jmethodID method_getNumObjects;
Mike Lockwood4b322ce2010-08-10 07:37:50 -040055static jmethodID method_getSupportedPlaybackFormats;
56static jmethodID method_getSupportedCaptureFormats;
57static jmethodID method_getSupportedObjectProperties;
58static jmethodID method_getSupportedDeviceProperties;
Mike Lockwood828d19d2010-08-10 15:20:35 -040059static jmethodID method_setObjectProperty;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -040060static jmethodID method_getDeviceProperty;
61static jmethodID method_setDeviceProperty;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040062static jmethodID method_getObjectPropertyList;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040063static jmethodID method_getObjectInfo;
64static jmethodID method_getObjectFilePath;
65static jmethodID method_deleteFile;
Mike Lockwood9a2046f2010-08-03 15:30:09 -040066static jmethodID method_getObjectReferences;
67static jmethodID method_setObjectReferences;
Mike Lockwood2837eef2010-08-31 16:25:12 -040068static jmethodID method_sessionStarted;
69static jmethodID method_sessionEnded;
70
Mike Lockwoodd21eac92010-07-03 00:44:05 -040071static jfieldID field_context;
Mike Lockwood56c85242014-03-07 13:29:08 -080072static jfieldID field_batteryLevel;
73static jfieldID field_batteryScale;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040074
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040075// MtpPropertyList fields
76static jfieldID field_mCount;
77static jfieldID field_mResult;
78static jfieldID field_mObjectHandles;
79static jfieldID field_mPropertyCodes;
80static jfieldID field_mDataTypes;
81static jfieldID field_mLongValues;
82static jfieldID field_mStringValues;
83
84
Mike Lockwoodd21eac92010-07-03 00:44:05 -040085MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
Ashok Bhate2e59322013-12-17 19:04:19 +000086 return (MtpDatabase *)env->GetLongField(database, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -040087}
88
89// ----------------------------------------------------------------------------
90
91class MyMtpDatabase : public MtpDatabase {
92private:
93 jobject mDatabase;
94 jintArray mIntBuffer;
95 jlongArray mLongBuffer;
96 jcharArray mStringBuffer;
97
98public:
99 MyMtpDatabase(JNIEnv *env, jobject client);
100 virtual ~MyMtpDatabase();
101 void cleanup(JNIEnv *env);
102
Mike Lockwoodd815f792010-07-12 08:49:01 -0400103 virtual MtpObjectHandle beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400104 MtpObjectFormat format,
105 MtpObjectHandle parent,
106 MtpStorageID storage,
107 uint64_t size,
108 time_t modified);
109
Mike Lockwoodd815f792010-07-12 08:49:01 -0400110 virtual void endSendObject(const char* path,
111 MtpObjectHandle handle,
112 MtpObjectFormat format,
113 bool succeeded);
114
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400115 virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
116 MtpObjectFormat format,
117 MtpObjectHandle parent);
118
Mike Lockwood7a047c82010-08-02 10:52:20 -0400119 virtual int getNumObjects(MtpStorageID storageID,
120 MtpObjectFormat format,
121 MtpObjectHandle parent);
122
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400123 // callee should delete[] the results from these
124 // results can be NULL
125 virtual MtpObjectFormatList* getSupportedPlaybackFormats();
126 virtual MtpObjectFormatList* getSupportedCaptureFormats();
127 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
128 virtual MtpDevicePropertyList* getSupportedDeviceProperties();
129
Mike Lockwood828d19d2010-08-10 15:20:35 -0400130 virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400131 MtpObjectProperty property,
132 MtpDataPacket& packet);
133
Mike Lockwood828d19d2010-08-10 15:20:35 -0400134 virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
135 MtpObjectProperty property,
136 MtpDataPacket& packet);
137
138 virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
139 MtpDataPacket& packet);
140
141 virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
142 MtpDataPacket& packet);
143
144 virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
145
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400146 virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500147 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400148 int groupCode, int depth,
149 MtpDataPacket& packet);
150
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400151 virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700152 MtpObjectInfo& info);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400153
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700154 virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
155
Mike Lockwood59c777a2010-08-02 10:37:41 -0400156 virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800157 MtpString& outFilePath,
158 int64_t& outFileLength,
159 MtpObjectFormat& outFormat);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400160 virtual MtpResponseCode deleteFile(MtpObjectHandle handle);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400161
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400162 bool getObjectPropertyInfo(MtpObjectProperty property, int& type);
163 bool getDevicePropertyInfo(MtpDeviceProperty property, int& type);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400164
165 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
166
167 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
168 MtpObjectHandleList* references);
Mike Lockwood828d19d2010-08-10 15:20:35 -0400169
170 virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
171 MtpObjectFormat format);
172
173 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400174
175 virtual void sessionStarted();
176
177 virtual void sessionEnded();
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400178};
179
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400180// ----------------------------------------------------------------------------
181
182static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
183 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +0000184 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400185 LOGE_EX(env);
186 env->ExceptionClear();
187 }
188}
189
190// ----------------------------------------------------------------------------
191
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400192MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
193 : mDatabase(env->NewGlobalRef(client)),
194 mIntBuffer(NULL),
195 mLongBuffer(NULL),
196 mStringBuffer(NULL)
197{
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400198 // create buffers for out arguments
199 // we don't need to be thread-safe so this is OK
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700200 jintArray intArray = env->NewIntArray(3);
201 if (!intArray) {
202 return; // Already threw.
203 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400204 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700205 jlongArray longArray = env->NewLongArray(2);
206 if (!longArray) {
207 return; // Already threw.
208 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400209 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
Mike Lockwood63ffd782014-09-24 10:55:19 -0700210 // Needs to be long enough to hold a file path for getObjectFilePath()
211 jcharArray charArray = env->NewCharArray(PATH_MAX + 1);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700212 if (!charArray) {
213 return; // Already threw.
214 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400215 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400216}
217
218void MyMtpDatabase::cleanup(JNIEnv *env) {
219 env->DeleteGlobalRef(mDatabase);
220 env->DeleteGlobalRef(mIntBuffer);
221 env->DeleteGlobalRef(mLongBuffer);
222 env->DeleteGlobalRef(mStringBuffer);
223}
224
225MyMtpDatabase::~MyMtpDatabase() {
226}
227
Mike Lockwoodd815f792010-07-12 08:49:01 -0400228MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400229 MtpObjectFormat format,
230 MtpObjectHandle parent,
231 MtpStorageID storage,
232 uint64_t size,
233 time_t modified) {
234 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400235 jstring pathStr = env->NewStringUTF(path);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400236 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
Mike Lockwood88394712010-09-27 10:01:00 -0400237 pathStr, (jint)format, (jint)parent, (jint)storage,
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400238 (jlong)size, (jlong)modified);
239
Mike Lockwood88394712010-09-27 10:01:00 -0400240 if (pathStr)
241 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400242 checkAndClearExceptionFromCallback(env, __FUNCTION__);
243 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400244}
245
Mike Lockwoodd815f792010-07-12 08:49:01 -0400246void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
Mike Lockwood7a0bd172011-01-18 11:06:19 -0800247 MtpObjectFormat format, bool succeeded) {
Mike Lockwoodd815f792010-07-12 08:49:01 -0400248 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400249 jstring pathStr = env->NewStringUTF(path);
250 env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
Mike Lockwood7a0bd172011-01-18 11:06:19 -0800251 (jint)handle, (jint)format, (jboolean)succeeded);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400252
Mike Lockwood88394712010-09-27 10:01:00 -0400253 if (pathStr)
254 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400255 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400256}
257
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400258MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
259 MtpObjectFormat format,
260 MtpObjectHandle parent) {
261 JNIEnv* env = AndroidRuntime::getJNIEnv();
262 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
263 (jint)storageID, (jint)format, (jint)parent);
264 if (!array)
265 return NULL;
266 MtpObjectHandleList* list = new MtpObjectHandleList();
267 jint* handles = env->GetIntArrayElements(array, 0);
268 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400269 for (int i = 0; i < length; i++)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400270 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400271 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400272 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400273
274 checkAndClearExceptionFromCallback(env, __FUNCTION__);
275 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400276}
277
Mike Lockwood7a047c82010-08-02 10:52:20 -0400278int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
279 MtpObjectFormat format,
280 MtpObjectHandle parent) {
281 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400282 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400283 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400284
285 checkAndClearExceptionFromCallback(env, __FUNCTION__);
286 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400287}
288
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400289MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
290 JNIEnv* env = AndroidRuntime::getJNIEnv();
291 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
292 method_getSupportedPlaybackFormats);
293 if (!array)
294 return NULL;
295 MtpObjectFormatList* list = new MtpObjectFormatList();
296 jint* formats = env->GetIntArrayElements(array, 0);
297 jsize length = env->GetArrayLength(array);
298 for (int i = 0; i < length; i++)
299 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400300 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400301 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400302
303 checkAndClearExceptionFromCallback(env, __FUNCTION__);
304 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400305}
306
307MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
308 JNIEnv* env = AndroidRuntime::getJNIEnv();
309 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
310 method_getSupportedCaptureFormats);
311 if (!array)
312 return NULL;
313 MtpObjectFormatList* list = new MtpObjectFormatList();
314 jint* formats = env->GetIntArrayElements(array, 0);
315 jsize length = env->GetArrayLength(array);
316 for (int i = 0; i < length; i++)
317 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400318 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400319 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400320
321 checkAndClearExceptionFromCallback(env, __FUNCTION__);
322 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400323}
324
325MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
326 JNIEnv* env = AndroidRuntime::getJNIEnv();
327 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
328 method_getSupportedObjectProperties, (jint)format);
329 if (!array)
330 return NULL;
331 MtpObjectPropertyList* list = new MtpObjectPropertyList();
332 jint* properties = env->GetIntArrayElements(array, 0);
333 jsize length = env->GetArrayLength(array);
334 for (int i = 0; i < length; i++)
335 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400336 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400337 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400338
339 checkAndClearExceptionFromCallback(env, __FUNCTION__);
340 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400341}
342
343MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
344 JNIEnv* env = AndroidRuntime::getJNIEnv();
345 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
346 method_getSupportedDeviceProperties);
347 if (!array)
348 return NULL;
349 MtpDevicePropertyList* list = new MtpDevicePropertyList();
350 jint* properties = env->GetIntArrayElements(array, 0);
351 jsize length = env->GetArrayLength(array);
352 for (int i = 0; i < length; i++)
353 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400354 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400355 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400356
357 checkAndClearExceptionFromCallback(env, __FUNCTION__);
358 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400359}
360
Mike Lockwood828d19d2010-08-10 15:20:35 -0400361MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400362 MtpObjectProperty property,
363 MtpDataPacket& packet) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400364 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400365 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500366 (jlong)handle, 0, (jlong)property, 0, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400367 MtpResponseCode result = env->GetIntField(list, field_mResult);
368 int count = env->GetIntField(list, field_mCount);
369 if (result == MTP_RESPONSE_OK && count != 1)
370 result = MTP_RESPONSE_GENERAL_ERROR;
371
372 if (result == MTP_RESPONSE_OK) {
373 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
374 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
375 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
376 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
377 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
378
379 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
380 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
381 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
382 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
383
384 int type = dataTypes[0];
385 jlong longValue = (longValues ? longValues[0] : 0);
386
387 // special case date properties, which are strings to MTP
388 // but stored internally as a uint64
389 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
390 char date[20];
391 formatDateTime(longValue, date, sizeof(date));
392 packet.putString(date);
393 goto out;
394 }
395 // release date is stored internally as just the year
396 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
397 char date[20];
Mark Salyzynaeb75fc2014-03-20 12:09:01 -0700398 snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400399 packet.putString(date);
400 goto out;
401 }
402
403 switch (type) {
404 case MTP_TYPE_INT8:
405 packet.putInt8(longValue);
406 break;
407 case MTP_TYPE_UINT8:
408 packet.putUInt8(longValue);
409 break;
410 case MTP_TYPE_INT16:
411 packet.putInt16(longValue);
412 break;
413 case MTP_TYPE_UINT16:
414 packet.putUInt16(longValue);
415 break;
416 case MTP_TYPE_INT32:
417 packet.putInt32(longValue);
418 break;
419 case MTP_TYPE_UINT32:
420 packet.putUInt32(longValue);
421 break;
422 case MTP_TYPE_INT64:
423 packet.putInt64(longValue);
424 break;
425 case MTP_TYPE_UINT64:
426 packet.putUInt64(longValue);
427 break;
428 case MTP_TYPE_INT128:
429 packet.putInt128(longValue);
430 break;
431 case MTP_TYPE_UINT128:
432 packet.putInt128(longValue);
433 break;
434 case MTP_TYPE_STR:
435 {
436 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200437 const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400438 if (stringValue) {
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400439 packet.putString(str);
440 env->ReleaseStringUTFChars(stringValue, str);
441 } else {
442 packet.putEmptyString();
443 }
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200444 env->DeleteLocalRef(stringValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400445 break;
446 }
447 default:
Steve Block3762c312012-01-06 19:20:56 +0000448 ALOGE("unsupported type in getObjectPropertyValue\n");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400449 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
450 }
451out:
452 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
453 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
454 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
455 if (longValues)
456 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
457
458 env->DeleteLocalRef(objectHandlesArray);
459 env->DeleteLocalRef(propertyCodesArray);
460 env->DeleteLocalRef(dataTypesArray);
461 if (longValuesArray)
462 env->DeleteLocalRef(longValuesArray);
463 if (stringValuesArray)
464 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400465 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400466
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400467 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400468 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400469 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400470}
471
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800472static bool readLongValue(int type, MtpDataPacket& packet, jlong& longValue) {
473 switch (type) {
474 case MTP_TYPE_INT8: {
475 int8_t temp;
476 if (!packet.getInt8(temp)) return false;
477 longValue = temp;
478 break;
479 }
480 case MTP_TYPE_UINT8: {
481 uint8_t temp;
482 if (!packet.getUInt8(temp)) return false;
483 longValue = temp;
484 break;
485 }
486 case MTP_TYPE_INT16: {
487 int16_t temp;
488 if (!packet.getInt16(temp)) return false;
489 longValue = temp;
490 break;
491 }
492 case MTP_TYPE_UINT16: {
493 uint16_t temp;
494 if (!packet.getUInt16(temp)) return false;
495 longValue = temp;
496 break;
497 }
498 case MTP_TYPE_INT32: {
499 int32_t temp;
500 if (!packet.getInt32(temp)) return false;
501 longValue = temp;
502 break;
503 }
504 case MTP_TYPE_UINT32: {
505 uint32_t temp;
506 if (!packet.getUInt32(temp)) return false;
507 longValue = temp;
508 break;
509 }
510 case MTP_TYPE_INT64: {
511 int64_t temp;
512 if (!packet.getInt64(temp)) return false;
513 longValue = temp;
514 break;
515 }
516 case MTP_TYPE_UINT64: {
517 uint64_t temp;
518 if (!packet.getUInt64(temp)) return false;
519 longValue = temp;
520 break;
521 }
522 default:
523 ALOGE("unsupported type in readLongValue");
524 return false;
525 }
526 return true;
527}
528
Mike Lockwood828d19d2010-08-10 15:20:35 -0400529MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
530 MtpObjectProperty property,
531 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400532 int type;
533
534 if (!getObjectPropertyInfo(property, type))
535 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
536
537 JNIEnv* env = AndroidRuntime::getJNIEnv();
538 jlong longValue = 0;
539 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800540 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400541
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800542 if (type == MTP_TYPE_STR) {
543 MtpStringBuffer buffer;
544 if (!packet.getString(buffer)) goto fail;
545 stringValue = env->NewStringUTF((const char *)buffer);
546 } else {
547 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400548 }
549
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800550 result = env->CallIntMethod(mDatabase, method_setObjectProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400551 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400552 if (stringValue)
553 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400554
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800555fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400556 checkAndClearExceptionFromCallback(env, __FUNCTION__);
557 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400558}
559
560MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
561 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400562 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood56c85242014-03-07 13:29:08 -0800563
564 if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) {
565 // special case - implemented here instead of Java
566 packet.putUInt8((uint8_t)env->GetIntField(mDatabase, field_batteryLevel));
567 return MTP_RESPONSE_OK;
568 } else {
569 int type;
570
571 if (!getDevicePropertyInfo(property, type))
572 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
573
574 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
575 (jint)property, mLongBuffer, mStringBuffer);
576 if (result != MTP_RESPONSE_OK) {
577 checkAndClearExceptionFromCallback(env, __FUNCTION__);
578 return result;
579 }
580
581 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
582 jlong longValue = longValues[0];
583 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
584
585 switch (type) {
586 case MTP_TYPE_INT8:
587 packet.putInt8(longValue);
588 break;
589 case MTP_TYPE_UINT8:
590 packet.putUInt8(longValue);
591 break;
592 case MTP_TYPE_INT16:
593 packet.putInt16(longValue);
594 break;
595 case MTP_TYPE_UINT16:
596 packet.putUInt16(longValue);
597 break;
598 case MTP_TYPE_INT32:
599 packet.putInt32(longValue);
600 break;
601 case MTP_TYPE_UINT32:
602 packet.putUInt32(longValue);
603 break;
604 case MTP_TYPE_INT64:
605 packet.putInt64(longValue);
606 break;
607 case MTP_TYPE_UINT64:
608 packet.putUInt64(longValue);
609 break;
610 case MTP_TYPE_INT128:
611 packet.putInt128(longValue);
612 break;
613 case MTP_TYPE_UINT128:
614 packet.putInt128(longValue);
615 break;
616 case MTP_TYPE_STR:
617 {
618 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
619 packet.putString(str);
620 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
621 break;
622 }
623 default:
624 ALOGE("unsupported type in getDevicePropertyValue\n");
625 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
626 }
627
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400628 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood56c85242014-03-07 13:29:08 -0800629 return MTP_RESPONSE_OK;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400630 }
Mike Lockwood828d19d2010-08-10 15:20:35 -0400631}
632
633MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
634 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400635 int type;
636
637 if (!getDevicePropertyInfo(property, type))
638 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
639
640 JNIEnv* env = AndroidRuntime::getJNIEnv();
641 jlong longValue = 0;
642 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800643 MtpResponseCode result = MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400644
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800645 if (type == MTP_TYPE_STR) {
646 MtpStringBuffer buffer;
647 if (!packet.getString(buffer)) goto fail;
648 stringValue = env->NewStringUTF((const char *)buffer);
649 } else {
650 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400651 }
652
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800653 result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400654 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400655 if (stringValue)
656 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400657
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800658fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400659 checkAndClearExceptionFromCallback(env, __FUNCTION__);
660 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400661}
662
Mark Salyzynaeb75fc2014-03-20 12:09:01 -0700663MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
Mike Lockwood828d19d2010-08-10 15:20:35 -0400664 return -1;
665}
666
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400667MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500668 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400669 int groupCode, int depth,
670 MtpDataPacket& packet) {
671 JNIEnv* env = AndroidRuntime::getJNIEnv();
672 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500673 (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
674 checkAndClearExceptionFromCallback(env, __FUNCTION__);
675 if (!list)
676 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400677 int count = env->GetIntField(list, field_mCount);
678 MtpResponseCode result = env->GetIntField(list, field_mResult);
679
680 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400681 if (count > 0) {
682 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
683 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
684 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
685 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
686 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
687
688 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
689 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
690 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
691 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
692
693 for (int i = 0; i < count; i++) {
694 packet.putUInt32(objectHandles[i]);
695 packet.putUInt16(propertyCodes[i]);
696 int type = dataTypes[i];
697 packet.putUInt16(type);
698
699 switch (type) {
700 case MTP_TYPE_INT8:
701 packet.putInt8(longValues[i]);
702 break;
703 case MTP_TYPE_UINT8:
704 packet.putUInt8(longValues[i]);
705 break;
706 case MTP_TYPE_INT16:
707 packet.putInt16(longValues[i]);
708 break;
709 case MTP_TYPE_UINT16:
710 packet.putUInt16(longValues[i]);
711 break;
712 case MTP_TYPE_INT32:
713 packet.putInt32(longValues[i]);
714 break;
715 case MTP_TYPE_UINT32:
716 packet.putUInt32(longValues[i]);
717 break;
718 case MTP_TYPE_INT64:
719 packet.putInt64(longValues[i]);
720 break;
721 case MTP_TYPE_UINT64:
722 packet.putUInt64(longValues[i]);
723 break;
724 case MTP_TYPE_INT128:
725 packet.putInt128(longValues[i]);
726 break;
727 case MTP_TYPE_UINT128:
728 packet.putUInt128(longValues[i]);
729 break;
730 case MTP_TYPE_STR: {
731 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
Mike Lockwood2711e492010-12-11 11:24:37 -0800732 const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400733 if (valueStr) {
734 packet.putString(valueStr);
735 env->ReleaseStringUTFChars(value, valueStr);
736 } else {
737 packet.putEmptyString();
738 }
739 env->DeleteLocalRef(value);
740 break;
741 }
742 default:
Steve Block3762c312012-01-06 19:20:56 +0000743 ALOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400744 break;
745 }
746 }
747
748 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
749 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
750 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
751 if (longValues)
752 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
753
754 env->DeleteLocalRef(objectHandlesArray);
755 env->DeleteLocalRef(propertyCodesArray);
756 env->DeleteLocalRef(dataTypesArray);
757 if (longValuesArray)
758 env->DeleteLocalRef(longValuesArray);
759 if (stringValuesArray)
760 env->DeleteLocalRef(stringValuesArray);
761 }
762
763 env->DeleteLocalRef(list);
764 checkAndClearExceptionFromCallback(env, __FUNCTION__);
765 return result;
766}
767
Mike Lockwood63ffd782014-09-24 10:55:19 -0700768static void foreachentry(ExifEntry *entry, void * /*user*/) {
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800769 char buf[1024];
770 ALOGI("entry %x, format %d, size %d: %s",
771 entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
772}
773
774static void foreachcontent(ExifContent *content, void *user) {
775 ALOGI("content %d", exif_content_get_ifd(content));
776 exif_content_foreach_entry(content, foreachentry, user);
777}
778
779static long getLongFromExifEntry(ExifEntry *e) {
780 ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
781 return exif_get_long(e->data, o);
782}
783
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400784MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700785 MtpObjectInfo& info) {
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700786 char date[20];
787 MtpString path;
788 int64_t length;
789 MtpObjectFormat format;
790
791 MtpResponseCode result = getObjectFilePath(handle, path, length, format);
792 if (result != MTP_RESPONSE_OK) {
793 return result;
794 }
795 info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400796
797 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700798 if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
799 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400800 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700801 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400802
803 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700804 info.mStorageID = intValues[0];
805 info.mFormat = intValues[1];
806 info.mParent = intValues[2];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400807 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
808
809 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood1341f1e2013-04-01 10:52:47 -0700810 info.mDateCreated = longValues[0];
811 info.mDateModified = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400812 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
813
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700814// info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
Mike Lockwood828d19d2010-08-10 15:20:35 -0400815// MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
816// MTP_ASSOCIATION_TYPE_UNDEFINED);
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700817 info.mAssociationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400818
819 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700820 MtpString temp(str);
821 info.mName = strdup((const char *)temp);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400822 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
823
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700824 // read EXIF data for thumbnail information
825 if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800826
827 ExifData *exifdata = exif_data_new_from_file(path);
828 if (exifdata) {
829 //exif_data_foreach_content(exifdata, foreachcontent, NULL);
830
831 // XXX get this from exif, or parse jpeg header instead?
832 ExifEntry *w = exif_content_get_entry(
833 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
834 ExifEntry *h = exif_content_get_entry(
835 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
836 info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
837 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
Marco Nelissen0937eed2014-01-22 15:10:57 -0800838 info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
839 info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800840 exif_data_unref(exifdata);
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700841 }
842 }
843
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400844 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400845 return MTP_RESPONSE_OK;
846}
847
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700848void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
849 MtpString path;
850 int64_t length;
851 MtpObjectFormat format;
852 void* result = NULL;
853 outThumbSize = 0;
854
855 if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK
856 && (format == MTP_FORMAT_EXIF_JPEG || format == MTP_FORMAT_JFIF)) {
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800857
858 ExifData *exifdata = exif_data_new_from_file(path);
859 if (exifdata) {
860 if (exifdata->data) {
861 result = malloc(exifdata->size);
862 if (result) {
863 memcpy(result, exifdata->data, exifdata->size);
Mike Lockwoodc4367722014-04-21 08:49:30 -0700864 outThumbSize = exifdata->size;
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800865 }
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700866 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800867 exif_data_unref(exifdata);
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700868 }
869 }
870
871 return result;
872}
873
Mike Lockwood59c777a2010-08-02 10:37:41 -0400874MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800875 MtpString& outFilePath,
876 int64_t& outFileLength,
877 MtpObjectFormat& outFormat) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400878 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400879 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400880 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400881 if (result != MTP_RESPONSE_OK) {
882 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400883 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400884 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400885
886 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800887 outFilePath.setTo(str, strlen16(str));
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400888 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
889
890 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800891 outFileLength = longValues[0];
892 outFormat = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400893 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700894
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400895 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400896 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400897}
898
Mike Lockwood59c777a2010-08-02 10:37:41 -0400899MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400900 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400901 MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
902
903 checkAndClearExceptionFromCallback(env, __FUNCTION__);
904 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400905}
906
907struct PropertyTableEntry {
908 MtpObjectProperty property;
909 int type;
910};
911
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400912static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400913 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
914 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
915 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
916 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
917 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
918 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
919 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
920 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
921 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -0400922 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
923 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
924 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
925 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
926 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
927 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
928 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
929 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
930 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
931 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
932 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400933};
934
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400935static const PropertyTableEntry kDevicePropertyTable[] = {
Mike Lockwoodea93fa12010-12-07 10:41:35 -0800936 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
937 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
938 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
Mike Lockwood56c85242014-03-07 13:29:08 -0800939 { MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400940};
941
942bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
943 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
944 const PropertyTableEntry* entry = kObjectPropertyTable;
945 for (int i = 0; i < count; i++, entry++) {
946 if (entry->property == property) {
947 type = entry->type;
948 return true;
949 }
950 }
951 return false;
952}
953
954bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
955 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
956 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400957 for (int i = 0; i < count; i++, entry++) {
958 if (entry->property == property) {
959 type = entry->type;
960 return true;
961 }
962 }
963 return false;
964}
965
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400966MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
967 JNIEnv* env = AndroidRuntime::getJNIEnv();
968 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
969 (jint)handle);
970 if (!array)
971 return NULL;
972 MtpObjectHandleList* list = new MtpObjectHandleList();
973 jint* handles = env->GetIntArrayElements(array, 0);
974 jsize length = env->GetArrayLength(array);
975 for (int i = 0; i < length; i++)
976 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400977 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400978 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400979
980 checkAndClearExceptionFromCallback(env, __FUNCTION__);
981 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400982}
983
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400984MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
985 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400986 JNIEnv* env = AndroidRuntime::getJNIEnv();
987 int count = references->size();
988 jintArray array = env->NewIntArray(count);
989 if (!array) {
Steve Block3762c312012-01-06 19:20:56 +0000990 ALOGE("out of memory in setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400991 return false;
992 }
993 jint* handles = env->GetIntArrayElements(array, 0);
994 for (int i = 0; i < count; i++)
995 handles[i] = (*references)[i];
996 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400997 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400998 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -0400999 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001000
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001001 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1002 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001003}
1004
Mike Lockwood828d19d2010-08-10 15:20:35 -04001005MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
1006 MtpObjectFormat format) {
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001007 static const int channelEnum[] = {
1008 1, // mono
1009 2, // stereo
1010 3, // 2.1
1011 4, // 3
1012 5, // 3.1
1013 6, // 4
1014 7, // 4.1
1015 8, // 5
1016 9, // 5.1
1017 };
1018 static const int bitrateEnum[] = {
1019 1, // fixed rate
1020 2, // variable rate
1021 };
1022
Mike Lockwood828d19d2010-08-10 15:20:35 -04001023 MtpProperty* result = NULL;
1024 switch (property) {
1025 case MTP_PROPERTY_OBJECT_FORMAT:
Mike Lockwood9b5e9c42010-12-07 18:53:50 -08001026 // use format as default value
1027 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
1028 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001029 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001030 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001031 result = new MtpProperty(property, MTP_TYPE_UINT16);
1032 break;
1033 case MTP_PROPERTY_STORAGE_ID:
1034 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001035 case MTP_PROPERTY_DURATION:
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001036 case MTP_PROPERTY_AUDIO_WAVE_CODEC:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001037 result = new MtpProperty(property, MTP_TYPE_UINT32);
1038 break;
1039 case MTP_PROPERTY_OBJECT_SIZE:
1040 result = new MtpProperty(property, MTP_TYPE_UINT64);
1041 break;
1042 case MTP_PROPERTY_PERSISTENT_UID:
1043 result = new MtpProperty(property, MTP_TYPE_UINT128);
1044 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001045 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001046 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001047 case MTP_PROPERTY_ARTIST:
1048 case MTP_PROPERTY_ALBUM_NAME:
1049 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001050 case MTP_PROPERTY_GENRE:
1051 case MTP_PROPERTY_COMPOSER:
1052 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001053 result = new MtpProperty(property, MTP_TYPE_STR);
1054 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -05001055 case MTP_PROPERTY_DATE_MODIFIED:
1056 case MTP_PROPERTY_DATE_ADDED:
1057 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
1058 result = new MtpProperty(property, MTP_TYPE_STR);
1059 result->setFormDateTime();
1060 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -04001061 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -04001062 // We allow renaming files and folders
1063 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -04001064 break;
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001065 case MTP_PROPERTY_BITRATE_TYPE:
1066 result = new MtpProperty(property, MTP_TYPE_UINT16);
1067 result->setFormEnum(bitrateEnum, sizeof(bitrateEnum)/sizeof(bitrateEnum[0]));
1068 break;
1069 case MTP_PROPERTY_AUDIO_BITRATE:
1070 result = new MtpProperty(property, MTP_TYPE_UINT32);
1071 result->setFormRange(1, 1536000, 1);
1072 break;
1073 case MTP_PROPERTY_NUMBER_OF_CHANNELS:
1074 result = new MtpProperty(property, MTP_TYPE_UINT16);
1075 result->setFormEnum(channelEnum, sizeof(channelEnum)/sizeof(channelEnum[0]));
1076 break;
1077 case MTP_PROPERTY_SAMPLE_RATE:
1078 result = new MtpProperty(property, MTP_TYPE_UINT32);
1079 result->setFormRange(8000, 48000, 1);
1080 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001081 }
1082
1083 return result;
1084}
1085
1086MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001087 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001088 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001089 bool writable = false;
1090
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001091 switch (property) {
1092 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
1093 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001094 writable = true;
1095 // fall through
Mike Lockwood56c85242014-03-07 13:29:08 -08001096 case MTP_DEVICE_PROPERTY_IMAGE_SIZE: {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001097 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001098
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001099 // get current value
Mike Lockwooda2a21282010-09-25 21:21:05 -04001100 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
1101 (jint)property, mLongBuffer, mStringBuffer);
1102 if (ret == MTP_RESPONSE_OK) {
1103 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
1104 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001105 // for read-only properties it is safe to assume current value is default value
1106 if (!writable)
1107 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001108 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
1109 } else {
Steve Block3762c312012-01-06 19:20:56 +00001110 ALOGE("unable to read device property, response: %04X", ret);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001111 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001112 break;
Mike Lockwood56c85242014-03-07 13:29:08 -08001113 }
1114 case MTP_DEVICE_PROPERTY_BATTERY_LEVEL:
1115 result = new MtpProperty(property, MTP_TYPE_UINT8);
1116 result->setFormRange(0, env->GetIntField(mDatabase, field_batteryScale), 1);
1117 result->mCurrentValue.u.u8 = (uint8_t)env->GetIntField(mDatabase, field_batteryLevel);
1118 break;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001119 }
1120
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001121 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001122 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001123}
1124
Mike Lockwood2837eef2010-08-31 16:25:12 -04001125void MyMtpDatabase::sessionStarted() {
1126 JNIEnv* env = AndroidRuntime::getJNIEnv();
1127 env->CallVoidMethod(mDatabase, method_sessionStarted);
1128 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1129}
1130
1131void MyMtpDatabase::sessionEnded() {
1132 JNIEnv* env = AndroidRuntime::getJNIEnv();
1133 env->CallVoidMethod(mDatabase, method_sessionEnded);
1134 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1135}
1136
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001137// ----------------------------------------------------------------------------
1138
1139static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001140android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001141{
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001142 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
Ashok Bhate2e59322013-12-17 19:04:19 +00001143 env->SetLongField(thiz, field_context, (jlong)database);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001144 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1145}
1146
1147static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001148android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001149{
Ashok Bhate2e59322013-12-17 19:04:19 +00001150 MyMtpDatabase* database = (MyMtpDatabase *)env->GetLongField(thiz, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001151 database->cleanup(env);
1152 delete database;
Ashok Bhate2e59322013-12-17 19:04:19 +00001153 env->SetLongField(thiz, field_context, 0);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001154 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1155}
1156
Mike Lockwood31599912010-11-15 13:43:30 -05001157static jstring
Mark Salyzynaeb75fc2014-03-20 12:09:01 -07001158android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001159{
Mike Lockwood31599912010-11-15 13:43:30 -05001160 char date[20];
1161 formatDateTime(seconds, date, sizeof(date));
1162 return env->NewStringUTF(date);
Mike Lockwood31599912010-11-15 13:43:30 -05001163}
1164
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001165// ----------------------------------------------------------------------------
1166
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001167static JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001168 {"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
1169 {"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001170};
1171
1172static JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001173 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001174 (void *)android_mtp_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001175};
1176
Mike Lockwood0cd01362010-12-30 11:54:33 -05001177static const char* const kClassPathName = "android/mtp/MtpDatabase";
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001178
Mike Lockwood0cd01362010-12-30 11:54:33 -05001179int register_android_mtp_MtpDatabase(JNIEnv *env)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001180{
1181 jclass clazz;
1182
Mike Lockwood0cd01362010-12-30 11:54:33 -05001183 clazz = env->FindClass("android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001184 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001185 ALOGE("Can't find android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001186 return -1;
1187 }
Mike Lockwoodd815f792010-07-12 08:49:01 -04001188 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1189 if (method_beginSendObject == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001190 ALOGE("Can't find beginSendObject");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001191 return -1;
1192 }
Mike Lockwood7a0bd172011-01-18 11:06:19 -08001193 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001194 if (method_endSendObject == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001195 ALOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001196 return -1;
1197 }
1198 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1199 if (method_getObjectList == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001200 ALOGE("Can't find getObjectList");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001201 return -1;
1202 }
Mike Lockwood7a047c82010-08-02 10:52:20 -04001203 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
1204 if (method_getNumObjects == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001205 ALOGE("Can't find getNumObjects");
Mike Lockwood7a047c82010-08-02 10:52:20 -04001206 return -1;
1207 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001208 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
1209 if (method_getSupportedPlaybackFormats == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001210 ALOGE("Can't find getSupportedPlaybackFormats");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001211 return -1;
1212 }
1213 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
1214 if (method_getSupportedCaptureFormats == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001215 ALOGE("Can't find getSupportedCaptureFormats");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001216 return -1;
1217 }
1218 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
1219 if (method_getSupportedObjectProperties == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001220 ALOGE("Can't find getSupportedObjectProperties");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001221 return -1;
1222 }
1223 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
1224 if (method_getSupportedDeviceProperties == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001225 ALOGE("Can't find getSupportedDeviceProperties");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001226 return -1;
1227 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001228 method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
1229 if (method_setObjectProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001230 ALOGE("Can't find setObjectProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001231 return -1;
1232 }
1233 method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
1234 if (method_getDeviceProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001235 ALOGE("Can't find getDeviceProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001236 return -1;
1237 }
1238 method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
1239 if (method_setDeviceProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001240 ALOGE("Can't find setDeviceProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001241 return -1;
1242 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001243 method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001244 "(JIJII)Landroid/mtp/MtpPropertyList;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001245 if (method_getObjectPropertyList == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001246 ALOGE("Can't find getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001247 return -1;
1248 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001249 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1250 if (method_getObjectInfo == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001251 ALOGE("Can't find getObjectInfo");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001252 return -1;
1253 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001254 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001255 if (method_getObjectFilePath == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001256 ALOGE("Can't find getObjectFilePath");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001257 return -1;
1258 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001259 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001260 if (method_deleteFile == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001261 ALOGE("Can't find deleteFile");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001262 return -1;
1263 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001264 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
1265 if (method_getObjectReferences == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001266 ALOGE("Can't find getObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001267 return -1;
1268 }
1269 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
1270 if (method_setObjectReferences == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001271 ALOGE("Can't find setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001272 return -1;
1273 }
Mike Lockwood2837eef2010-08-31 16:25:12 -04001274 method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
1275 if (method_sessionStarted == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001276 ALOGE("Can't find sessionStarted");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001277 return -1;
1278 }
1279 method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
1280 if (method_sessionEnded == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001281 ALOGE("Can't find sessionEnded");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001282 return -1;
1283 }
1284
Ashok Bhate2e59322013-12-17 19:04:19 +00001285 field_context = env->GetFieldID(clazz, "mNativeContext", "J");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001286 if (field_context == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001287 ALOGE("Can't find MtpDatabase.mNativeContext");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001288 return -1;
1289 }
Mike Lockwood56c85242014-03-07 13:29:08 -08001290 field_batteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");
1291 if (field_batteryLevel == NULL) {
1292 ALOGE("Can't find MtpDatabase.mBatteryLevel");
1293 return -1;
1294 }
1295 field_batteryScale = env->GetFieldID(clazz, "mBatteryScale", "I");
1296 if (field_batteryScale == NULL) {
1297 ALOGE("Can't find MtpDatabase.mBatteryScale");
1298 return -1;
1299 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001300
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001301 // now set up fields for MtpPropertyList class
Mike Lockwood0cd01362010-12-30 11:54:33 -05001302 clazz = env->FindClass("android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001303 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001304 ALOGE("Can't find android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001305 return -1;
1306 }
1307 field_mCount = env->GetFieldID(clazz, "mCount", "I");
1308 if (field_mCount == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001309 ALOGE("Can't find MtpPropertyList.mCount");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001310 return -1;
1311 }
1312 field_mResult = env->GetFieldID(clazz, "mResult", "I");
1313 if (field_mResult == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001314 ALOGE("Can't find MtpPropertyList.mResult");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001315 return -1;
1316 }
1317 field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1318 if (field_mObjectHandles == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001319 ALOGE("Can't find MtpPropertyList.mObjectHandles");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001320 return -1;
1321 }
1322 field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1323 if (field_mPropertyCodes == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001324 ALOGE("Can't find MtpPropertyList.mPropertyCodes");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001325 return -1;
1326 }
1327 field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1328 if (field_mDataTypes == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001329 ALOGE("Can't find MtpPropertyList.mDataTypes");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001330 return -1;
1331 }
1332 field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1333 if (field_mLongValues == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001334 ALOGE("Can't find MtpPropertyList.mLongValues");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001335 return -1;
1336 }
1337 field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1338 if (field_mStringValues == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001339 ALOGE("Can't find MtpPropertyList.mStringValues");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001340 return -1;
1341 }
1342
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001343 if (AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001344 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001345 return -1;
1346
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001347 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001348 "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001349}