blob: 556f2c7706484c83371d88838107729eb630e2ae [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
Jaesung Chung8409c062016-01-19 10:48:30 +090020#include "android_media_Utils.h"
21#include "mtp.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040022#include "MtpDatabase.h"
23#include "MtpDataPacket.h"
Mike Lockwood9df53fae2011-04-21 17:05:55 -070024#include "MtpObjectInfo.h"
Mike Lockwood828d19d2010-08-10 15:20:35 -040025#include "MtpProperty.h"
Mike Lockwood59e3f0d2010-09-02 14:57:30 -040026#include "MtpStringBuffer.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040027#include "MtpUtils.h"
Jaesung Chung8409c062016-01-19 10:48:30 +090028
29#include "src/piex_types.h"
30#include "src/piex.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040031
Mike Lockwoodc89f2222011-04-24 18:40:17 -070032extern "C" {
Marco Nelissen3cd393c2014-01-10 10:39:27 -080033#include "libexif/exif-content.h"
34#include "libexif/exif-data.h"
35#include "libexif/exif-tag.h"
36#include "libexif/exif-utils.h"
Mike Lockwoodc89f2222011-04-24 18:40:17 -070037}
38
Jaesung Chung8409c062016-01-19 10:48:30 +090039#include <android_runtime/AndroidRuntime.h>
40#include <android_runtime/Log.h>
41#include <jni.h>
42#include <JNIHelp.h>
43#include <nativehelper/ScopedLocalRef.h>
44
45#include <assert.h>
46#include <fcntl.h>
47#include <inttypes.h>
48#include <limits.h>
49#include <stdio.h>
50#include <unistd.h>
51
Mike Lockwoodd21eac92010-07-03 00:44:05 -040052using namespace android;
53
54// ----------------------------------------------------------------------------
55
Mike Lockwoodd815f792010-07-12 08:49:01 -040056static jmethodID method_beginSendObject;
57static jmethodID method_endSendObject;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040058static jmethodID method_getObjectList;
Mike Lockwood7a047c82010-08-02 10:52:20 -040059static jmethodID method_getNumObjects;
Mike Lockwood4b322ce2010-08-10 07:37:50 -040060static jmethodID method_getSupportedPlaybackFormats;
61static jmethodID method_getSupportedCaptureFormats;
62static jmethodID method_getSupportedObjectProperties;
63static jmethodID method_getSupportedDeviceProperties;
Mike Lockwood828d19d2010-08-10 15:20:35 -040064static jmethodID method_setObjectProperty;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -040065static jmethodID method_getDeviceProperty;
66static jmethodID method_setDeviceProperty;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040067static jmethodID method_getObjectPropertyList;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040068static jmethodID method_getObjectInfo;
69static jmethodID method_getObjectFilePath;
70static jmethodID method_deleteFile;
Mike Lockwood9a2046f2010-08-03 15:30:09 -040071static jmethodID method_getObjectReferences;
72static jmethodID method_setObjectReferences;
Mike Lockwood2837eef2010-08-31 16:25:12 -040073static jmethodID method_sessionStarted;
74static jmethodID method_sessionEnded;
75
Mike Lockwoodd21eac92010-07-03 00:44:05 -040076static jfieldID field_context;
Mike Lockwood56c85242014-03-07 13:29:08 -080077static jfieldID field_batteryLevel;
78static jfieldID field_batteryScale;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040079
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040080// MtpPropertyList fields
81static jfieldID field_mCount;
82static jfieldID field_mResult;
83static jfieldID field_mObjectHandles;
84static jfieldID field_mPropertyCodes;
85static jfieldID field_mDataTypes;
86static jfieldID field_mLongValues;
87static jfieldID field_mStringValues;
88
89
Mike Lockwoodd21eac92010-07-03 00:44:05 -040090MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
Ashok Bhate2e59322013-12-17 19:04:19 +000091 return (MtpDatabase *)env->GetLongField(database, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -040092}
93
94// ----------------------------------------------------------------------------
95
96class MyMtpDatabase : public MtpDatabase {
97private:
98 jobject mDatabase;
99 jintArray mIntBuffer;
100 jlongArray mLongBuffer;
101 jcharArray mStringBuffer;
102
103public:
104 MyMtpDatabase(JNIEnv *env, jobject client);
105 virtual ~MyMtpDatabase();
106 void cleanup(JNIEnv *env);
107
Mike Lockwoodd815f792010-07-12 08:49:01 -0400108 virtual MtpObjectHandle beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400109 MtpObjectFormat format,
110 MtpObjectHandle parent,
111 MtpStorageID storage,
112 uint64_t size,
113 time_t modified);
114
Mike Lockwoodd815f792010-07-12 08:49:01 -0400115 virtual void endSendObject(const char* path,
116 MtpObjectHandle handle,
117 MtpObjectFormat format,
118 bool succeeded);
119
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400120 virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
121 MtpObjectFormat format,
122 MtpObjectHandle parent);
123
Mike Lockwood7a047c82010-08-02 10:52:20 -0400124 virtual int getNumObjects(MtpStorageID storageID,
125 MtpObjectFormat format,
126 MtpObjectHandle parent);
127
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400128 // callee should delete[] the results from these
129 // results can be NULL
130 virtual MtpObjectFormatList* getSupportedPlaybackFormats();
131 virtual MtpObjectFormatList* getSupportedCaptureFormats();
132 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
133 virtual MtpDevicePropertyList* getSupportedDeviceProperties();
134
Mike Lockwood828d19d2010-08-10 15:20:35 -0400135 virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400136 MtpObjectProperty property,
137 MtpDataPacket& packet);
138
Mike Lockwood828d19d2010-08-10 15:20:35 -0400139 virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
140 MtpObjectProperty property,
141 MtpDataPacket& packet);
142
143 virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
144 MtpDataPacket& packet);
145
146 virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
147 MtpDataPacket& packet);
148
149 virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
150
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400151 virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500152 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400153 int groupCode, int depth,
154 MtpDataPacket& packet);
155
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400156 virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700157 MtpObjectInfo& info);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400158
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700159 virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
160
Mike Lockwood59c777a2010-08-02 10:37:41 -0400161 virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800162 MtpString& outFilePath,
163 int64_t& outFileLength,
164 MtpObjectFormat& outFormat);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400165 virtual MtpResponseCode deleteFile(MtpObjectHandle handle);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400166
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400167 bool getObjectPropertyInfo(MtpObjectProperty property, int& type);
168 bool getDevicePropertyInfo(MtpDeviceProperty property, int& type);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400169
170 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
171
172 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
173 MtpObjectHandleList* references);
Mike Lockwood828d19d2010-08-10 15:20:35 -0400174
175 virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
176 MtpObjectFormat format);
177
178 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400179
180 virtual void sessionStarted();
181
182 virtual void sessionEnded();
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400183};
184
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400185// ----------------------------------------------------------------------------
186
187static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
188 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +0000189 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400190 LOGE_EX(env);
191 env->ExceptionClear();
192 }
193}
194
195// ----------------------------------------------------------------------------
196
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400197MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
198 : mDatabase(env->NewGlobalRef(client)),
199 mIntBuffer(NULL),
200 mLongBuffer(NULL),
201 mStringBuffer(NULL)
202{
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400203 // create buffers for out arguments
204 // we don't need to be thread-safe so this is OK
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700205 jintArray intArray = env->NewIntArray(3);
206 if (!intArray) {
207 return; // Already threw.
208 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400209 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700210 jlongArray longArray = env->NewLongArray(2);
211 if (!longArray) {
212 return; // Already threw.
213 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400214 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
Mike Lockwood63ffd782014-09-24 10:55:19 -0700215 // Needs to be long enough to hold a file path for getObjectFilePath()
216 jcharArray charArray = env->NewCharArray(PATH_MAX + 1);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700217 if (!charArray) {
218 return; // Already threw.
219 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400220 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400221}
222
223void MyMtpDatabase::cleanup(JNIEnv *env) {
224 env->DeleteGlobalRef(mDatabase);
225 env->DeleteGlobalRef(mIntBuffer);
226 env->DeleteGlobalRef(mLongBuffer);
227 env->DeleteGlobalRef(mStringBuffer);
228}
229
230MyMtpDatabase::~MyMtpDatabase() {
231}
232
Mike Lockwoodd815f792010-07-12 08:49:01 -0400233MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400234 MtpObjectFormat format,
235 MtpObjectHandle parent,
236 MtpStorageID storage,
237 uint64_t size,
238 time_t modified) {
239 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400240 jstring pathStr = env->NewStringUTF(path);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400241 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
Mike Lockwood88394712010-09-27 10:01:00 -0400242 pathStr, (jint)format, (jint)parent, (jint)storage,
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400243 (jlong)size, (jlong)modified);
244
Mike Lockwood88394712010-09-27 10:01:00 -0400245 if (pathStr)
246 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400247 checkAndClearExceptionFromCallback(env, __FUNCTION__);
248 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400249}
250
Mike Lockwoodd815f792010-07-12 08:49:01 -0400251void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
Mike Lockwood7a0bd172011-01-18 11:06:19 -0800252 MtpObjectFormat format, bool succeeded) {
Mike Lockwoodd815f792010-07-12 08:49:01 -0400253 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400254 jstring pathStr = env->NewStringUTF(path);
255 env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
Mike Lockwood7a0bd172011-01-18 11:06:19 -0800256 (jint)handle, (jint)format, (jboolean)succeeded);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400257
Mike Lockwood88394712010-09-27 10:01:00 -0400258 if (pathStr)
259 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400260 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400261}
262
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400263MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
264 MtpObjectFormat format,
265 MtpObjectHandle parent) {
266 JNIEnv* env = AndroidRuntime::getJNIEnv();
267 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
268 (jint)storageID, (jint)format, (jint)parent);
269 if (!array)
270 return NULL;
271 MtpObjectHandleList* list = new MtpObjectHandleList();
272 jint* handles = env->GetIntArrayElements(array, 0);
273 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400274 for (int i = 0; i < length; i++)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400275 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400276 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400277 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400278
279 checkAndClearExceptionFromCallback(env, __FUNCTION__);
280 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400281}
282
Mike Lockwood7a047c82010-08-02 10:52:20 -0400283int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
284 MtpObjectFormat format,
285 MtpObjectHandle parent) {
286 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400287 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400288 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400289
290 checkAndClearExceptionFromCallback(env, __FUNCTION__);
291 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400292}
293
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400294MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
295 JNIEnv* env = AndroidRuntime::getJNIEnv();
296 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
297 method_getSupportedPlaybackFormats);
298 if (!array)
299 return NULL;
300 MtpObjectFormatList* list = new MtpObjectFormatList();
301 jint* formats = env->GetIntArrayElements(array, 0);
302 jsize length = env->GetArrayLength(array);
303 for (int i = 0; i < length; i++)
304 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400305 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400306 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400307
308 checkAndClearExceptionFromCallback(env, __FUNCTION__);
309 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400310}
311
312MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
313 JNIEnv* env = AndroidRuntime::getJNIEnv();
314 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
315 method_getSupportedCaptureFormats);
316 if (!array)
317 return NULL;
318 MtpObjectFormatList* list = new MtpObjectFormatList();
319 jint* formats = env->GetIntArrayElements(array, 0);
320 jsize length = env->GetArrayLength(array);
321 for (int i = 0; i < length; i++)
322 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400323 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400324 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400325
326 checkAndClearExceptionFromCallback(env, __FUNCTION__);
327 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400328}
329
330MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
331 JNIEnv* env = AndroidRuntime::getJNIEnv();
332 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
333 method_getSupportedObjectProperties, (jint)format);
334 if (!array)
335 return NULL;
336 MtpObjectPropertyList* list = new MtpObjectPropertyList();
337 jint* properties = env->GetIntArrayElements(array, 0);
338 jsize length = env->GetArrayLength(array);
339 for (int i = 0; i < length; i++)
340 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400341 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400342 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400343
344 checkAndClearExceptionFromCallback(env, __FUNCTION__);
345 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400346}
347
348MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
349 JNIEnv* env = AndroidRuntime::getJNIEnv();
350 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
351 method_getSupportedDeviceProperties);
352 if (!array)
353 return NULL;
354 MtpDevicePropertyList* list = new MtpDevicePropertyList();
355 jint* properties = env->GetIntArrayElements(array, 0);
356 jsize length = env->GetArrayLength(array);
357 for (int i = 0; i < length; i++)
358 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400359 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400360 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400361
362 checkAndClearExceptionFromCallback(env, __FUNCTION__);
363 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400364}
365
Mike Lockwood828d19d2010-08-10 15:20:35 -0400366MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400367 MtpObjectProperty property,
368 MtpDataPacket& packet) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400369 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400370 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500371 (jlong)handle, 0, (jlong)property, 0, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400372 MtpResponseCode result = env->GetIntField(list, field_mResult);
373 int count = env->GetIntField(list, field_mCount);
374 if (result == MTP_RESPONSE_OK && count != 1)
375 result = MTP_RESPONSE_GENERAL_ERROR;
376
377 if (result == MTP_RESPONSE_OK) {
378 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
379 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
380 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
381 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
382 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
383
384 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
385 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
386 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
387 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
388
389 int type = dataTypes[0];
390 jlong longValue = (longValues ? longValues[0] : 0);
391
392 // special case date properties, which are strings to MTP
393 // but stored internally as a uint64
394 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
395 char date[20];
396 formatDateTime(longValue, date, sizeof(date));
397 packet.putString(date);
398 goto out;
399 }
400 // release date is stored internally as just the year
401 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
402 char date[20];
Mark Salyzynaeb75fc2014-03-20 12:09:01 -0700403 snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400404 packet.putString(date);
405 goto out;
406 }
407
408 switch (type) {
409 case MTP_TYPE_INT8:
410 packet.putInt8(longValue);
411 break;
412 case MTP_TYPE_UINT8:
413 packet.putUInt8(longValue);
414 break;
415 case MTP_TYPE_INT16:
416 packet.putInt16(longValue);
417 break;
418 case MTP_TYPE_UINT16:
419 packet.putUInt16(longValue);
420 break;
421 case MTP_TYPE_INT32:
422 packet.putInt32(longValue);
423 break;
424 case MTP_TYPE_UINT32:
425 packet.putUInt32(longValue);
426 break;
427 case MTP_TYPE_INT64:
428 packet.putInt64(longValue);
429 break;
430 case MTP_TYPE_UINT64:
431 packet.putUInt64(longValue);
432 break;
433 case MTP_TYPE_INT128:
434 packet.putInt128(longValue);
435 break;
436 case MTP_TYPE_UINT128:
437 packet.putInt128(longValue);
438 break;
439 case MTP_TYPE_STR:
440 {
441 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200442 const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400443 if (stringValue) {
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400444 packet.putString(str);
445 env->ReleaseStringUTFChars(stringValue, str);
446 } else {
447 packet.putEmptyString();
448 }
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200449 env->DeleteLocalRef(stringValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400450 break;
451 }
452 default:
Steve Block3762c312012-01-06 19:20:56 +0000453 ALOGE("unsupported type in getObjectPropertyValue\n");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400454 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
455 }
456out:
457 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
458 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
459 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
460 if (longValues)
461 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
462
463 env->DeleteLocalRef(objectHandlesArray);
464 env->DeleteLocalRef(propertyCodesArray);
465 env->DeleteLocalRef(dataTypesArray);
466 if (longValuesArray)
467 env->DeleteLocalRef(longValuesArray);
468 if (stringValuesArray)
469 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400470 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400471
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400472 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400473 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400474 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400475}
476
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800477static bool readLongValue(int type, MtpDataPacket& packet, jlong& longValue) {
478 switch (type) {
479 case MTP_TYPE_INT8: {
480 int8_t temp;
481 if (!packet.getInt8(temp)) return false;
482 longValue = temp;
483 break;
484 }
485 case MTP_TYPE_UINT8: {
486 uint8_t temp;
487 if (!packet.getUInt8(temp)) return false;
488 longValue = temp;
489 break;
490 }
491 case MTP_TYPE_INT16: {
492 int16_t temp;
493 if (!packet.getInt16(temp)) return false;
494 longValue = temp;
495 break;
496 }
497 case MTP_TYPE_UINT16: {
498 uint16_t temp;
499 if (!packet.getUInt16(temp)) return false;
500 longValue = temp;
501 break;
502 }
503 case MTP_TYPE_INT32: {
504 int32_t temp;
505 if (!packet.getInt32(temp)) return false;
506 longValue = temp;
507 break;
508 }
509 case MTP_TYPE_UINT32: {
510 uint32_t temp;
511 if (!packet.getUInt32(temp)) return false;
512 longValue = temp;
513 break;
514 }
515 case MTP_TYPE_INT64: {
516 int64_t temp;
517 if (!packet.getInt64(temp)) return false;
518 longValue = temp;
519 break;
520 }
521 case MTP_TYPE_UINT64: {
522 uint64_t temp;
523 if (!packet.getUInt64(temp)) return false;
524 longValue = temp;
525 break;
526 }
527 default:
528 ALOGE("unsupported type in readLongValue");
529 return false;
530 }
531 return true;
532}
533
Mike Lockwood828d19d2010-08-10 15:20:35 -0400534MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
535 MtpObjectProperty property,
536 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400537 int type;
538
539 if (!getObjectPropertyInfo(property, type))
540 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
541
542 JNIEnv* env = AndroidRuntime::getJNIEnv();
543 jlong longValue = 0;
544 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800545 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400546
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800547 if (type == MTP_TYPE_STR) {
548 MtpStringBuffer buffer;
549 if (!packet.getString(buffer)) goto fail;
550 stringValue = env->NewStringUTF((const char *)buffer);
551 } else {
552 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400553 }
554
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800555 result = env->CallIntMethod(mDatabase, method_setObjectProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400556 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400557 if (stringValue)
558 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400559
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800560fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400561 checkAndClearExceptionFromCallback(env, __FUNCTION__);
562 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400563}
564
565MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
566 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400567 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood56c85242014-03-07 13:29:08 -0800568
569 if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) {
570 // special case - implemented here instead of Java
571 packet.putUInt8((uint8_t)env->GetIntField(mDatabase, field_batteryLevel));
572 return MTP_RESPONSE_OK;
573 } else {
574 int type;
575
576 if (!getDevicePropertyInfo(property, type))
577 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
578
579 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
580 (jint)property, mLongBuffer, mStringBuffer);
581 if (result != MTP_RESPONSE_OK) {
582 checkAndClearExceptionFromCallback(env, __FUNCTION__);
583 return result;
584 }
585
586 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
587 jlong longValue = longValues[0];
588 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
589
590 switch (type) {
591 case MTP_TYPE_INT8:
592 packet.putInt8(longValue);
593 break;
594 case MTP_TYPE_UINT8:
595 packet.putUInt8(longValue);
596 break;
597 case MTP_TYPE_INT16:
598 packet.putInt16(longValue);
599 break;
600 case MTP_TYPE_UINT16:
601 packet.putUInt16(longValue);
602 break;
603 case MTP_TYPE_INT32:
604 packet.putInt32(longValue);
605 break;
606 case MTP_TYPE_UINT32:
607 packet.putUInt32(longValue);
608 break;
609 case MTP_TYPE_INT64:
610 packet.putInt64(longValue);
611 break;
612 case MTP_TYPE_UINT64:
613 packet.putUInt64(longValue);
614 break;
615 case MTP_TYPE_INT128:
616 packet.putInt128(longValue);
617 break;
618 case MTP_TYPE_UINT128:
619 packet.putInt128(longValue);
620 break;
621 case MTP_TYPE_STR:
622 {
623 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
624 packet.putString(str);
625 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
626 break;
627 }
628 default:
629 ALOGE("unsupported type in getDevicePropertyValue\n");
630 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
631 }
632
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400633 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood56c85242014-03-07 13:29:08 -0800634 return MTP_RESPONSE_OK;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400635 }
Mike Lockwood828d19d2010-08-10 15:20:35 -0400636}
637
638MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
639 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400640 int type;
641
642 if (!getDevicePropertyInfo(property, type))
643 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
644
645 JNIEnv* env = AndroidRuntime::getJNIEnv();
646 jlong longValue = 0;
647 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800648 MtpResponseCode result = MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400649
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800650 if (type == MTP_TYPE_STR) {
651 MtpStringBuffer buffer;
652 if (!packet.getString(buffer)) goto fail;
653 stringValue = env->NewStringUTF((const char *)buffer);
654 } else {
655 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400656 }
657
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800658 result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400659 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400660 if (stringValue)
661 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400662
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800663fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400664 checkAndClearExceptionFromCallback(env, __FUNCTION__);
665 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400666}
667
Mark Salyzynaeb75fc2014-03-20 12:09:01 -0700668MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
Mike Lockwood828d19d2010-08-10 15:20:35 -0400669 return -1;
670}
671
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400672MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500673 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400674 int groupCode, int depth,
675 MtpDataPacket& packet) {
676 JNIEnv* env = AndroidRuntime::getJNIEnv();
677 jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500678 (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
679 checkAndClearExceptionFromCallback(env, __FUNCTION__);
680 if (!list)
681 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400682 int count = env->GetIntField(list, field_mCount);
683 MtpResponseCode result = env->GetIntField(list, field_mResult);
684
685 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400686 if (count > 0) {
687 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
688 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
689 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
690 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
691 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
692
693 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
694 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
695 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
696 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
697
698 for (int i = 0; i < count; i++) {
699 packet.putUInt32(objectHandles[i]);
700 packet.putUInt16(propertyCodes[i]);
701 int type = dataTypes[i];
702 packet.putUInt16(type);
703
704 switch (type) {
705 case MTP_TYPE_INT8:
706 packet.putInt8(longValues[i]);
707 break;
708 case MTP_TYPE_UINT8:
709 packet.putUInt8(longValues[i]);
710 break;
711 case MTP_TYPE_INT16:
712 packet.putInt16(longValues[i]);
713 break;
714 case MTP_TYPE_UINT16:
715 packet.putUInt16(longValues[i]);
716 break;
717 case MTP_TYPE_INT32:
718 packet.putInt32(longValues[i]);
719 break;
720 case MTP_TYPE_UINT32:
721 packet.putUInt32(longValues[i]);
722 break;
723 case MTP_TYPE_INT64:
724 packet.putInt64(longValues[i]);
725 break;
726 case MTP_TYPE_UINT64:
727 packet.putUInt64(longValues[i]);
728 break;
729 case MTP_TYPE_INT128:
730 packet.putInt128(longValues[i]);
731 break;
732 case MTP_TYPE_UINT128:
733 packet.putUInt128(longValues[i]);
734 break;
735 case MTP_TYPE_STR: {
736 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
Mike Lockwood2711e492010-12-11 11:24:37 -0800737 const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400738 if (valueStr) {
739 packet.putString(valueStr);
740 env->ReleaseStringUTFChars(value, valueStr);
741 } else {
742 packet.putEmptyString();
743 }
744 env->DeleteLocalRef(value);
745 break;
746 }
747 default:
Steve Block3762c312012-01-06 19:20:56 +0000748 ALOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400749 break;
750 }
751 }
752
753 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
754 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
755 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
756 if (longValues)
757 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
758
759 env->DeleteLocalRef(objectHandlesArray);
760 env->DeleteLocalRef(propertyCodesArray);
761 env->DeleteLocalRef(dataTypesArray);
762 if (longValuesArray)
763 env->DeleteLocalRef(longValuesArray);
764 if (stringValuesArray)
765 env->DeleteLocalRef(stringValuesArray);
766 }
767
768 env->DeleteLocalRef(list);
769 checkAndClearExceptionFromCallback(env, __FUNCTION__);
770 return result;
771}
772
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800773static void foreachentry(ExifEntry *entry, void* /* user */) {
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800774 char buf[1024];
775 ALOGI("entry %x, format %d, size %d: %s",
776 entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
777}
778
779static void foreachcontent(ExifContent *content, void *user) {
780 ALOGI("content %d", exif_content_get_ifd(content));
781 exif_content_foreach_entry(content, foreachentry, user);
782}
783
784static long getLongFromExifEntry(ExifEntry *e) {
785 ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
786 return exif_get_long(e->data, o);
787}
788
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400789MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700790 MtpObjectInfo& info) {
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700791 MtpString path;
792 int64_t length;
793 MtpObjectFormat format;
794
795 MtpResponseCode result = getObjectFilePath(handle, path, length, format);
796 if (result != MTP_RESPONSE_OK) {
797 return result;
798 }
799 info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400800
801 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700802 if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
803 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400804 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700805 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400806
807 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700808 info.mStorageID = intValues[0];
809 info.mFormat = intValues[1];
810 info.mParent = intValues[2];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400811 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
812
813 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood1341f1e2013-04-01 10:52:47 -0700814 info.mDateCreated = longValues[0];
815 info.mDateModified = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400816 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
817
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800818 if ((false)) {
819 info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
820 MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
821 MTP_ASSOCIATION_TYPE_UNDEFINED);
822 }
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700823 info.mAssociationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400824
825 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Dan Albert66987492014-11-20 11:41:21 -0800826 MtpString temp(reinterpret_cast<char16_t*>(str));
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700827 info.mName = strdup((const char *)temp);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400828 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
829
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700830 // read EXIF data for thumbnail information
Jaesung Chung8409c062016-01-19 10:48:30 +0900831 switch (info.mFormat) {
832 case MTP_FORMAT_EXIF_JPEG:
833 case MTP_FORMAT_JFIF: {
834 ExifData *exifdata = exif_data_new_from_file(path);
835 if (exifdata) {
836 if ((false)) {
837 exif_data_foreach_content(exifdata, foreachcontent, NULL);
838 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800839
Jaesung Chung8409c062016-01-19 10:48:30 +0900840 ExifEntry *w = exif_content_get_entry(
841 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
842 ExifEntry *h = exif_content_get_entry(
843 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
844 info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
845 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
846 info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
847 info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
848 exif_data_unref(exifdata);
849 }
850 break;
851 }
852
853 // Except DNG, all supported RAW image formats are not defined in PTP 1.2 specification.
854 // Most of RAW image formats are based on TIFF or TIFF/EP. To render Fuji's RAF format,
855 // it checks MTP_FORMAT_DEFINED case since it's designed as a custom format.
856 case MTP_FORMAT_DNG:
857 case MTP_FORMAT_TIFF:
858 case MTP_FORMAT_TIFF_EP:
859 case MTP_FORMAT_DEFINED: {
860 std::unique_ptr<FileStream> stream(new FileStream(path));
861 piex::PreviewImageData image_data;
862 if (!GetExifFromRawImage(stream.get(), path, image_data)) {
863 // Couldn't parse EXIF data from a image file via piex.
864 break;
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800865 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800866
Jaesung Chung8409c062016-01-19 10:48:30 +0900867 info.mThumbCompressedSize = image_data.thumbnail_length;
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800868 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
Jaesung Chung8409c062016-01-19 10:48:30 +0900869 info.mImagePixWidth = image_data.full_width;
870 info.mImagePixHeight = image_data.full_height;
871
872 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700873 }
874 }
875
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400876 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400877 return MTP_RESPONSE_OK;
878}
879
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700880void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
881 MtpString path;
882 int64_t length;
883 MtpObjectFormat format;
884 void* result = NULL;
885 outThumbSize = 0;
886
Jaesung Chung8409c062016-01-19 10:48:30 +0900887 if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
888 switch (format) {
889 case MTP_FORMAT_EXIF_JPEG:
890 case MTP_FORMAT_JFIF: {
891 ExifData *exifdata = exif_data_new_from_file(path);
892 if (exifdata) {
893 if (exifdata->data) {
894 result = malloc(exifdata->size);
895 if (result) {
896 memcpy(result, exifdata->data, exifdata->size);
897 outThumbSize = exifdata->size;
898 }
899 }
900 exif_data_unref(exifdata);
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800901 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900902 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700903 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900904
905 // See the above comment on getObjectInfo() method.
906 case MTP_FORMAT_DNG:
907 case MTP_FORMAT_TIFF:
908 case MTP_FORMAT_TIFF_EP:
909 case MTP_FORMAT_DEFINED: {
910 std::unique_ptr<FileStream> stream(new FileStream(path));
911 piex::PreviewImageData image_data;
912 if (!GetExifFromRawImage(stream.get(), path, image_data)) {
913 // Couldn't parse EXIF data from a image file via piex.
914 break;
915 }
916
917 if (image_data.thumbnail_length == 0) {
918 // No thumbnail.
919 break;
920 }
921
922 result = malloc(image_data.thumbnail_length);
923 if (result) {
924 piex::Error err = stream.get()->GetData(
925 image_data.thumbnail_offset,
926 image_data.thumbnail_length,
927 (std::uint8_t *)result);
928 if (err == piex::Error::kOk) {
929 outThumbSize = image_data.thumbnail_length;
930 } else {
931 free(result);
932 }
933 }
934 break;
935 }
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700936 }
937 }
938
939 return result;
940}
941
Mike Lockwood59c777a2010-08-02 10:37:41 -0400942MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800943 MtpString& outFilePath,
944 int64_t& outFileLength,
945 MtpObjectFormat& outFormat) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400946 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400947 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400948 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400949 if (result != MTP_RESPONSE_OK) {
950 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400951 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400952 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400953
954 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Dan Albert66987492014-11-20 11:41:21 -0800955 outFilePath.setTo(reinterpret_cast<char16_t*>(str),
956 strlen16(reinterpret_cast<char16_t*>(str)));
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400957 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
958
959 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800960 outFileLength = longValues[0];
961 outFormat = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400962 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700963
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400964 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400965 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400966}
967
Mike Lockwood59c777a2010-08-02 10:37:41 -0400968MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400969 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400970 MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
971
972 checkAndClearExceptionFromCallback(env, __FUNCTION__);
973 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400974}
975
976struct PropertyTableEntry {
977 MtpObjectProperty property;
978 int type;
979};
980
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400981static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -0400982 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
983 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
984 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
985 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
986 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
987 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
988 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
989 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
990 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -0400991 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
992 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
993 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
994 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
995 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
996 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
997 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
998 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
999 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
1000 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
1001 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwood71827742015-01-23 10:50:08 -08001002 { MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_TYPE_UINT32 },
1003 { MTP_PROPERTY_BITRATE_TYPE, MTP_TYPE_UINT16 },
1004 { MTP_PROPERTY_AUDIO_BITRATE, MTP_TYPE_UINT32 },
1005 { MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_TYPE_UINT16 },
1006 { MTP_PROPERTY_SAMPLE_RATE, MTP_TYPE_UINT32 },
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001007};
1008
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001009static const PropertyTableEntry kDevicePropertyTable[] = {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001010 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
1011 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
1012 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
Mike Lockwood56c85242014-03-07 13:29:08 -08001013 { MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001014};
1015
1016bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
1017 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
1018 const PropertyTableEntry* entry = kObjectPropertyTable;
1019 for (int i = 0; i < count; i++, entry++) {
1020 if (entry->property == property) {
1021 type = entry->type;
1022 return true;
1023 }
1024 }
1025 return false;
1026}
1027
1028bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
1029 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
1030 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001031 for (int i = 0; i < count; i++, entry++) {
1032 if (entry->property == property) {
1033 type = entry->type;
1034 return true;
1035 }
1036 }
1037 return false;
1038}
1039
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001040MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
1041 JNIEnv* env = AndroidRuntime::getJNIEnv();
1042 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
1043 (jint)handle);
1044 if (!array)
1045 return NULL;
1046 MtpObjectHandleList* list = new MtpObjectHandleList();
1047 jint* handles = env->GetIntArrayElements(array, 0);
1048 jsize length = env->GetArrayLength(array);
1049 for (int i = 0; i < length; i++)
1050 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001051 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -04001052 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001053
1054 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1055 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001056}
1057
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001058MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
1059 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001060 JNIEnv* env = AndroidRuntime::getJNIEnv();
1061 int count = references->size();
1062 jintArray array = env->NewIntArray(count);
1063 if (!array) {
Steve Block3762c312012-01-06 19:20:56 +00001064 ALOGE("out of memory in setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001065 return false;
1066 }
1067 jint* handles = env->GetIntArrayElements(array, 0);
1068 for (int i = 0; i < count; i++)
1069 handles[i] = (*references)[i];
1070 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001071 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001072 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -04001073 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001074
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001075 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1076 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001077}
1078
Mike Lockwood828d19d2010-08-10 15:20:35 -04001079MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
1080 MtpObjectFormat format) {
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001081 static const int channelEnum[] = {
1082 1, // mono
1083 2, // stereo
1084 3, // 2.1
1085 4, // 3
1086 5, // 3.1
1087 6, // 4
1088 7, // 4.1
1089 8, // 5
1090 9, // 5.1
1091 };
1092 static const int bitrateEnum[] = {
1093 1, // fixed rate
1094 2, // variable rate
1095 };
1096
Mike Lockwood828d19d2010-08-10 15:20:35 -04001097 MtpProperty* result = NULL;
1098 switch (property) {
1099 case MTP_PROPERTY_OBJECT_FORMAT:
Mike Lockwood9b5e9c42010-12-07 18:53:50 -08001100 // use format as default value
1101 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
1102 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001103 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001104 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001105 result = new MtpProperty(property, MTP_TYPE_UINT16);
1106 break;
1107 case MTP_PROPERTY_STORAGE_ID:
1108 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001109 case MTP_PROPERTY_DURATION:
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001110 case MTP_PROPERTY_AUDIO_WAVE_CODEC:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001111 result = new MtpProperty(property, MTP_TYPE_UINT32);
1112 break;
1113 case MTP_PROPERTY_OBJECT_SIZE:
1114 result = new MtpProperty(property, MTP_TYPE_UINT64);
1115 break;
1116 case MTP_PROPERTY_PERSISTENT_UID:
1117 result = new MtpProperty(property, MTP_TYPE_UINT128);
1118 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001119 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001120 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001121 case MTP_PROPERTY_ARTIST:
1122 case MTP_PROPERTY_ALBUM_NAME:
1123 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001124 case MTP_PROPERTY_GENRE:
1125 case MTP_PROPERTY_COMPOSER:
1126 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001127 result = new MtpProperty(property, MTP_TYPE_STR);
1128 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -05001129 case MTP_PROPERTY_DATE_MODIFIED:
1130 case MTP_PROPERTY_DATE_ADDED:
1131 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
1132 result = new MtpProperty(property, MTP_TYPE_STR);
1133 result->setFormDateTime();
1134 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -04001135 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -04001136 // We allow renaming files and folders
1137 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -04001138 break;
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001139 case MTP_PROPERTY_BITRATE_TYPE:
1140 result = new MtpProperty(property, MTP_TYPE_UINT16);
1141 result->setFormEnum(bitrateEnum, sizeof(bitrateEnum)/sizeof(bitrateEnum[0]));
1142 break;
1143 case MTP_PROPERTY_AUDIO_BITRATE:
1144 result = new MtpProperty(property, MTP_TYPE_UINT32);
1145 result->setFormRange(1, 1536000, 1);
1146 break;
1147 case MTP_PROPERTY_NUMBER_OF_CHANNELS:
1148 result = new MtpProperty(property, MTP_TYPE_UINT16);
1149 result->setFormEnum(channelEnum, sizeof(channelEnum)/sizeof(channelEnum[0]));
1150 break;
1151 case MTP_PROPERTY_SAMPLE_RATE:
1152 result = new MtpProperty(property, MTP_TYPE_UINT32);
1153 result->setFormRange(8000, 48000, 1);
1154 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001155 }
1156
1157 return result;
1158}
1159
1160MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001161 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001162 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001163 bool writable = false;
1164
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001165 switch (property) {
1166 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
1167 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001168 writable = true;
1169 // fall through
Mike Lockwood56c85242014-03-07 13:29:08 -08001170 case MTP_DEVICE_PROPERTY_IMAGE_SIZE: {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001171 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001172
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001173 // get current value
Mike Lockwooda2a21282010-09-25 21:21:05 -04001174 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
1175 (jint)property, mLongBuffer, mStringBuffer);
1176 if (ret == MTP_RESPONSE_OK) {
1177 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
1178 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001179 // for read-only properties it is safe to assume current value is default value
1180 if (!writable)
1181 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001182 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
1183 } else {
Steve Block3762c312012-01-06 19:20:56 +00001184 ALOGE("unable to read device property, response: %04X", ret);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001185 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001186 break;
Mike Lockwood56c85242014-03-07 13:29:08 -08001187 }
1188 case MTP_DEVICE_PROPERTY_BATTERY_LEVEL:
1189 result = new MtpProperty(property, MTP_TYPE_UINT8);
1190 result->setFormRange(0, env->GetIntField(mDatabase, field_batteryScale), 1);
1191 result->mCurrentValue.u.u8 = (uint8_t)env->GetIntField(mDatabase, field_batteryLevel);
1192 break;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001193 }
1194
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001195 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001196 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001197}
1198
Mike Lockwood2837eef2010-08-31 16:25:12 -04001199void MyMtpDatabase::sessionStarted() {
1200 JNIEnv* env = AndroidRuntime::getJNIEnv();
1201 env->CallVoidMethod(mDatabase, method_sessionStarted);
1202 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1203}
1204
1205void MyMtpDatabase::sessionEnded() {
1206 JNIEnv* env = AndroidRuntime::getJNIEnv();
1207 env->CallVoidMethod(mDatabase, method_sessionEnded);
1208 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1209}
1210
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001211// ----------------------------------------------------------------------------
1212
1213static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001214android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001215{
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001216 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
Ashok Bhate2e59322013-12-17 19:04:19 +00001217 env->SetLongField(thiz, field_context, (jlong)database);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001218 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1219}
1220
1221static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001222android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001223{
Ashok Bhate2e59322013-12-17 19:04:19 +00001224 MyMtpDatabase* database = (MyMtpDatabase *)env->GetLongField(thiz, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001225 database->cleanup(env);
1226 delete database;
Ashok Bhate2e59322013-12-17 19:04:19 +00001227 env->SetLongField(thiz, field_context, 0);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001228 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1229}
1230
Mike Lockwood31599912010-11-15 13:43:30 -05001231static jstring
Mark Salyzynaeb75fc2014-03-20 12:09:01 -07001232android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001233{
Mike Lockwood31599912010-11-15 13:43:30 -05001234 char date[20];
1235 formatDateTime(seconds, date, sizeof(date));
1236 return env->NewStringUTF(date);
Mike Lockwood31599912010-11-15 13:43:30 -05001237}
1238
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001239// ----------------------------------------------------------------------------
1240
Daniel Micay76f6a862015-09-19 17:31:01 -04001241static const JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001242 {"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
1243 {"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001244};
1245
Daniel Micay76f6a862015-09-19 17:31:01 -04001246static const JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001247 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001248 (void *)android_mtp_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001249};
1250
Mike Lockwood0cd01362010-12-30 11:54:33 -05001251int register_android_mtp_MtpDatabase(JNIEnv *env)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001252{
1253 jclass clazz;
1254
Mike Lockwood0cd01362010-12-30 11:54:33 -05001255 clazz = env->FindClass("android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001256 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001257 ALOGE("Can't find android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001258 return -1;
1259 }
Mike Lockwoodd815f792010-07-12 08:49:01 -04001260 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1261 if (method_beginSendObject == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001262 ALOGE("Can't find beginSendObject");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001263 return -1;
1264 }
Mike Lockwood7a0bd172011-01-18 11:06:19 -08001265 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001266 if (method_endSendObject == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001267 ALOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001268 return -1;
1269 }
1270 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1271 if (method_getObjectList == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001272 ALOGE("Can't find getObjectList");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001273 return -1;
1274 }
Mike Lockwood7a047c82010-08-02 10:52:20 -04001275 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
1276 if (method_getNumObjects == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001277 ALOGE("Can't find getNumObjects");
Mike Lockwood7a047c82010-08-02 10:52:20 -04001278 return -1;
1279 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001280 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
1281 if (method_getSupportedPlaybackFormats == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001282 ALOGE("Can't find getSupportedPlaybackFormats");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001283 return -1;
1284 }
1285 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
1286 if (method_getSupportedCaptureFormats == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001287 ALOGE("Can't find getSupportedCaptureFormats");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001288 return -1;
1289 }
1290 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
1291 if (method_getSupportedObjectProperties == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001292 ALOGE("Can't find getSupportedObjectProperties");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001293 return -1;
1294 }
1295 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
1296 if (method_getSupportedDeviceProperties == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001297 ALOGE("Can't find getSupportedDeviceProperties");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001298 return -1;
1299 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001300 method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
1301 if (method_setObjectProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001302 ALOGE("Can't find setObjectProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001303 return -1;
1304 }
1305 method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
1306 if (method_getDeviceProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001307 ALOGE("Can't find getDeviceProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001308 return -1;
1309 }
1310 method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
1311 if (method_setDeviceProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001312 ALOGE("Can't find setDeviceProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001313 return -1;
1314 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001315 method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001316 "(JIJII)Landroid/mtp/MtpPropertyList;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001317 if (method_getObjectPropertyList == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001318 ALOGE("Can't find getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001319 return -1;
1320 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001321 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1322 if (method_getObjectInfo == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001323 ALOGE("Can't find getObjectInfo");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001324 return -1;
1325 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001326 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001327 if (method_getObjectFilePath == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001328 ALOGE("Can't find getObjectFilePath");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001329 return -1;
1330 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001331 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001332 if (method_deleteFile == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001333 ALOGE("Can't find deleteFile");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001334 return -1;
1335 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001336 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
1337 if (method_getObjectReferences == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001338 ALOGE("Can't find getObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001339 return -1;
1340 }
1341 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
1342 if (method_setObjectReferences == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001343 ALOGE("Can't find setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001344 return -1;
1345 }
Mike Lockwood2837eef2010-08-31 16:25:12 -04001346 method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
1347 if (method_sessionStarted == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001348 ALOGE("Can't find sessionStarted");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001349 return -1;
1350 }
1351 method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
1352 if (method_sessionEnded == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001353 ALOGE("Can't find sessionEnded");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001354 return -1;
1355 }
1356
Ashok Bhate2e59322013-12-17 19:04:19 +00001357 field_context = env->GetFieldID(clazz, "mNativeContext", "J");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001358 if (field_context == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001359 ALOGE("Can't find MtpDatabase.mNativeContext");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001360 return -1;
1361 }
Mike Lockwood56c85242014-03-07 13:29:08 -08001362 field_batteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");
1363 if (field_batteryLevel == NULL) {
1364 ALOGE("Can't find MtpDatabase.mBatteryLevel");
1365 return -1;
1366 }
1367 field_batteryScale = env->GetFieldID(clazz, "mBatteryScale", "I");
1368 if (field_batteryScale == NULL) {
1369 ALOGE("Can't find MtpDatabase.mBatteryScale");
1370 return -1;
1371 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001372
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001373 // now set up fields for MtpPropertyList class
Mike Lockwood0cd01362010-12-30 11:54:33 -05001374 clazz = env->FindClass("android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001375 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001376 ALOGE("Can't find android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001377 return -1;
1378 }
1379 field_mCount = env->GetFieldID(clazz, "mCount", "I");
1380 if (field_mCount == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001381 ALOGE("Can't find MtpPropertyList.mCount");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001382 return -1;
1383 }
1384 field_mResult = env->GetFieldID(clazz, "mResult", "I");
1385 if (field_mResult == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001386 ALOGE("Can't find MtpPropertyList.mResult");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001387 return -1;
1388 }
1389 field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1390 if (field_mObjectHandles == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001391 ALOGE("Can't find MtpPropertyList.mObjectHandles");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001392 return -1;
1393 }
1394 field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1395 if (field_mPropertyCodes == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001396 ALOGE("Can't find MtpPropertyList.mPropertyCodes");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001397 return -1;
1398 }
1399 field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1400 if (field_mDataTypes == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001401 ALOGE("Can't find MtpPropertyList.mDataTypes");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001402 return -1;
1403 }
1404 field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1405 if (field_mLongValues == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001406 ALOGE("Can't find MtpPropertyList.mLongValues");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001407 return -1;
1408 }
1409 field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1410 if (field_mStringValues == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001411 ALOGE("Can't find MtpPropertyList.mStringValues");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001412 return -1;
1413 }
1414
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001415 if (AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001416 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001417 return -1;
1418
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001419 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001420 "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001421}