blob: 5722cb0130265b42218d4f2118fae001ba8cb86d [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,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900234 MtpObjectFormat format,
235 MtpObjectHandle parent,
236 MtpStorageID storage,
237 uint64_t size,
238 time_t modified) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400239 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,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900252 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,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900264 MtpObjectFormat format,
265 MtpObjectHandle parent) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400266 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,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900284 MtpObjectFormat format,
285 MtpObjectHandle parent) {
Mike Lockwood7a047c82010-08-02 10:52:20 -0400286 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,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900367 MtpObjectProperty property,
368 MtpDataPacket& packet) {
369 static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
370 "Casting MtpObjectHandle to jint loses a value");
371 static_assert(sizeof(jint) >= sizeof(MtpObjectProperty),
372 "Casting MtpObjectProperty to jint loses a value");
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400373 JNIEnv* env = AndroidRuntime::getJNIEnv();
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900374 jobject list = env->CallObjectMethod(
375 mDatabase,
376 method_getObjectPropertyList,
377 static_cast<jint>(handle),
378 0,
379 static_cast<jint>(property),
380 0,
381 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400382 MtpResponseCode result = env->GetIntField(list, field_mResult);
383 int count = env->GetIntField(list, field_mCount);
384 if (result == MTP_RESPONSE_OK && count != 1)
385 result = MTP_RESPONSE_GENERAL_ERROR;
386
387 if (result == MTP_RESPONSE_OK) {
388 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
389 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
390 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
391 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
392 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
393
394 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
395 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
396 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
397 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
398
399 int type = dataTypes[0];
400 jlong longValue = (longValues ? longValues[0] : 0);
401
402 // special case date properties, which are strings to MTP
403 // but stored internally as a uint64
404 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
405 char date[20];
406 formatDateTime(longValue, date, sizeof(date));
407 packet.putString(date);
408 goto out;
409 }
410 // release date is stored internally as just the year
411 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
412 char date[20];
Mark Salyzynaeb75fc2014-03-20 12:09:01 -0700413 snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400414 packet.putString(date);
415 goto out;
416 }
417
418 switch (type) {
419 case MTP_TYPE_INT8:
420 packet.putInt8(longValue);
421 break;
422 case MTP_TYPE_UINT8:
423 packet.putUInt8(longValue);
424 break;
425 case MTP_TYPE_INT16:
426 packet.putInt16(longValue);
427 break;
428 case MTP_TYPE_UINT16:
429 packet.putUInt16(longValue);
430 break;
431 case MTP_TYPE_INT32:
432 packet.putInt32(longValue);
433 break;
434 case MTP_TYPE_UINT32:
435 packet.putUInt32(longValue);
436 break;
437 case MTP_TYPE_INT64:
438 packet.putInt64(longValue);
439 break;
440 case MTP_TYPE_UINT64:
441 packet.putUInt64(longValue);
442 break;
443 case MTP_TYPE_INT128:
444 packet.putInt128(longValue);
445 break;
446 case MTP_TYPE_UINT128:
447 packet.putInt128(longValue);
448 break;
449 case MTP_TYPE_STR:
450 {
451 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200452 const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400453 if (stringValue) {
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400454 packet.putString(str);
455 env->ReleaseStringUTFChars(stringValue, str);
456 } else {
457 packet.putEmptyString();
458 }
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200459 env->DeleteLocalRef(stringValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400460 break;
461 }
462 default:
Steve Block3762c312012-01-06 19:20:56 +0000463 ALOGE("unsupported type in getObjectPropertyValue\n");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400464 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
465 }
466out:
467 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
468 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
469 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
470 if (longValues)
471 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
472
473 env->DeleteLocalRef(objectHandlesArray);
474 env->DeleteLocalRef(propertyCodesArray);
475 env->DeleteLocalRef(dataTypesArray);
476 if (longValuesArray)
477 env->DeleteLocalRef(longValuesArray);
478 if (stringValuesArray)
479 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400480 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400481
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400482 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400483 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400484 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400485}
486
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800487static bool readLongValue(int type, MtpDataPacket& packet, jlong& longValue) {
488 switch (type) {
489 case MTP_TYPE_INT8: {
490 int8_t temp;
491 if (!packet.getInt8(temp)) return false;
492 longValue = temp;
493 break;
494 }
495 case MTP_TYPE_UINT8: {
496 uint8_t temp;
497 if (!packet.getUInt8(temp)) return false;
498 longValue = temp;
499 break;
500 }
501 case MTP_TYPE_INT16: {
502 int16_t temp;
503 if (!packet.getInt16(temp)) return false;
504 longValue = temp;
505 break;
506 }
507 case MTP_TYPE_UINT16: {
508 uint16_t temp;
509 if (!packet.getUInt16(temp)) return false;
510 longValue = temp;
511 break;
512 }
513 case MTP_TYPE_INT32: {
514 int32_t temp;
515 if (!packet.getInt32(temp)) return false;
516 longValue = temp;
517 break;
518 }
519 case MTP_TYPE_UINT32: {
520 uint32_t temp;
521 if (!packet.getUInt32(temp)) return false;
522 longValue = temp;
523 break;
524 }
525 case MTP_TYPE_INT64: {
526 int64_t temp;
527 if (!packet.getInt64(temp)) return false;
528 longValue = temp;
529 break;
530 }
531 case MTP_TYPE_UINT64: {
532 uint64_t temp;
533 if (!packet.getUInt64(temp)) return false;
534 longValue = temp;
535 break;
536 }
537 default:
538 ALOGE("unsupported type in readLongValue");
539 return false;
540 }
541 return true;
542}
543
Mike Lockwood828d19d2010-08-10 15:20:35 -0400544MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900545 MtpObjectProperty property,
546 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400547 int type;
548
549 if (!getObjectPropertyInfo(property, type))
550 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
551
552 JNIEnv* env = AndroidRuntime::getJNIEnv();
553 jlong longValue = 0;
554 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800555 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400556
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800557 if (type == MTP_TYPE_STR) {
558 MtpStringBuffer buffer;
559 if (!packet.getString(buffer)) goto fail;
560 stringValue = env->NewStringUTF((const char *)buffer);
561 } else {
562 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400563 }
564
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800565 result = env->CallIntMethod(mDatabase, method_setObjectProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400566 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400567 if (stringValue)
568 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400569
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800570fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400571 checkAndClearExceptionFromCallback(env, __FUNCTION__);
572 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400573}
574
575MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900576 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400577 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood56c85242014-03-07 13:29:08 -0800578
579 if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) {
580 // special case - implemented here instead of Java
581 packet.putUInt8((uint8_t)env->GetIntField(mDatabase, field_batteryLevel));
582 return MTP_RESPONSE_OK;
583 } else {
584 int type;
585
586 if (!getDevicePropertyInfo(property, type))
587 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
588
589 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
590 (jint)property, mLongBuffer, mStringBuffer);
591 if (result != MTP_RESPONSE_OK) {
592 checkAndClearExceptionFromCallback(env, __FUNCTION__);
593 return result;
594 }
595
596 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
597 jlong longValue = longValues[0];
598 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
599
600 switch (type) {
601 case MTP_TYPE_INT8:
602 packet.putInt8(longValue);
603 break;
604 case MTP_TYPE_UINT8:
605 packet.putUInt8(longValue);
606 break;
607 case MTP_TYPE_INT16:
608 packet.putInt16(longValue);
609 break;
610 case MTP_TYPE_UINT16:
611 packet.putUInt16(longValue);
612 break;
613 case MTP_TYPE_INT32:
614 packet.putInt32(longValue);
615 break;
616 case MTP_TYPE_UINT32:
617 packet.putUInt32(longValue);
618 break;
619 case MTP_TYPE_INT64:
620 packet.putInt64(longValue);
621 break;
622 case MTP_TYPE_UINT64:
623 packet.putUInt64(longValue);
624 break;
625 case MTP_TYPE_INT128:
626 packet.putInt128(longValue);
627 break;
628 case MTP_TYPE_UINT128:
629 packet.putInt128(longValue);
630 break;
631 case MTP_TYPE_STR:
632 {
633 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
634 packet.putString(str);
635 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
636 break;
637 }
638 default:
639 ALOGE("unsupported type in getDevicePropertyValue\n");
640 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
641 }
642
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400643 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood56c85242014-03-07 13:29:08 -0800644 return MTP_RESPONSE_OK;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400645 }
Mike Lockwood828d19d2010-08-10 15:20:35 -0400646}
647
648MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900649 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400650 int type;
651
652 if (!getDevicePropertyInfo(property, type))
653 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
654
655 JNIEnv* env = AndroidRuntime::getJNIEnv();
656 jlong longValue = 0;
657 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800658 MtpResponseCode result = MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400659
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800660 if (type == MTP_TYPE_STR) {
661 MtpStringBuffer buffer;
662 if (!packet.getString(buffer)) goto fail;
663 stringValue = env->NewStringUTF((const char *)buffer);
664 } else {
665 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400666 }
667
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800668 result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400669 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400670 if (stringValue)
671 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400672
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800673fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400674 checkAndClearExceptionFromCallback(env, __FUNCTION__);
675 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400676}
677
Mark Salyzynaeb75fc2014-03-20 12:09:01 -0700678MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
Mike Lockwood828d19d2010-08-10 15:20:35 -0400679 return -1;
680}
681
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400682MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900683 uint32_t format, uint32_t property,
684 int groupCode, int depth,
685 MtpDataPacket& packet) {
686 static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
687 "Casting MtpObjectHandle to jint loses a value");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400688 JNIEnv* env = AndroidRuntime::getJNIEnv();
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900689 jobject list = env->CallObjectMethod(
690 mDatabase,
691 method_getObjectPropertyList,
692 static_cast<jint>(handle),
693 static_cast<jint>(format),
694 static_cast<jint>(property),
695 static_cast<jint>(groupCode),
696 static_cast<jint>(depth));
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500697 checkAndClearExceptionFromCallback(env, __FUNCTION__);
698 if (!list)
699 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400700 int count = env->GetIntField(list, field_mCount);
701 MtpResponseCode result = env->GetIntField(list, field_mResult);
702
703 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400704 if (count > 0) {
705 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
706 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
707 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
708 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
709 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
710
711 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
712 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
713 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
714 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
715
716 for (int i = 0; i < count; i++) {
717 packet.putUInt32(objectHandles[i]);
718 packet.putUInt16(propertyCodes[i]);
719 int type = dataTypes[i];
720 packet.putUInt16(type);
721
722 switch (type) {
723 case MTP_TYPE_INT8:
724 packet.putInt8(longValues[i]);
725 break;
726 case MTP_TYPE_UINT8:
727 packet.putUInt8(longValues[i]);
728 break;
729 case MTP_TYPE_INT16:
730 packet.putInt16(longValues[i]);
731 break;
732 case MTP_TYPE_UINT16:
733 packet.putUInt16(longValues[i]);
734 break;
735 case MTP_TYPE_INT32:
736 packet.putInt32(longValues[i]);
737 break;
738 case MTP_TYPE_UINT32:
739 packet.putUInt32(longValues[i]);
740 break;
741 case MTP_TYPE_INT64:
742 packet.putInt64(longValues[i]);
743 break;
744 case MTP_TYPE_UINT64:
745 packet.putUInt64(longValues[i]);
746 break;
747 case MTP_TYPE_INT128:
748 packet.putInt128(longValues[i]);
749 break;
750 case MTP_TYPE_UINT128:
751 packet.putUInt128(longValues[i]);
752 break;
753 case MTP_TYPE_STR: {
754 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
Mike Lockwood2711e492010-12-11 11:24:37 -0800755 const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400756 if (valueStr) {
757 packet.putString(valueStr);
758 env->ReleaseStringUTFChars(value, valueStr);
759 } else {
760 packet.putEmptyString();
761 }
762 env->DeleteLocalRef(value);
763 break;
764 }
765 default:
Steve Block3762c312012-01-06 19:20:56 +0000766 ALOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400767 break;
768 }
769 }
770
771 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
772 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
773 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
774 if (longValues)
775 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
776
777 env->DeleteLocalRef(objectHandlesArray);
778 env->DeleteLocalRef(propertyCodesArray);
779 env->DeleteLocalRef(dataTypesArray);
780 if (longValuesArray)
781 env->DeleteLocalRef(longValuesArray);
782 if (stringValuesArray)
783 env->DeleteLocalRef(stringValuesArray);
784 }
785
786 env->DeleteLocalRef(list);
787 checkAndClearExceptionFromCallback(env, __FUNCTION__);
788 return result;
789}
790
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800791static void foreachentry(ExifEntry *entry, void* /* user */) {
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800792 char buf[1024];
793 ALOGI("entry %x, format %d, size %d: %s",
794 entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
795}
796
797static void foreachcontent(ExifContent *content, void *user) {
798 ALOGI("content %d", exif_content_get_ifd(content));
799 exif_content_foreach_entry(content, foreachentry, user);
800}
801
802static long getLongFromExifEntry(ExifEntry *e) {
803 ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
804 return exif_get_long(e->data, o);
805}
806
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400807MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900808 MtpObjectInfo& info) {
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700809 MtpString path;
810 int64_t length;
811 MtpObjectFormat format;
812
813 MtpResponseCode result = getObjectFilePath(handle, path, length, format);
814 if (result != MTP_RESPONSE_OK) {
815 return result;
816 }
817 info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400818
819 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700820 if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
821 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400822 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700823 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400824
825 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700826 info.mStorageID = intValues[0];
827 info.mFormat = intValues[1];
828 info.mParent = intValues[2];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400829 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
830
831 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood1341f1e2013-04-01 10:52:47 -0700832 info.mDateCreated = longValues[0];
833 info.mDateModified = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400834 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
835
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800836 if ((false)) {
837 info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
838 MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
839 MTP_ASSOCIATION_TYPE_UNDEFINED);
840 }
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700841 info.mAssociationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400842
843 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Dan Albert66987492014-11-20 11:41:21 -0800844 MtpString temp(reinterpret_cast<char16_t*>(str));
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700845 info.mName = strdup((const char *)temp);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400846 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
847
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700848 // read EXIF data for thumbnail information
Jaesung Chung8409c062016-01-19 10:48:30 +0900849 switch (info.mFormat) {
850 case MTP_FORMAT_EXIF_JPEG:
851 case MTP_FORMAT_JFIF: {
852 ExifData *exifdata = exif_data_new_from_file(path);
853 if (exifdata) {
854 if ((false)) {
855 exif_data_foreach_content(exifdata, foreachcontent, NULL);
856 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800857
Jaesung Chung8409c062016-01-19 10:48:30 +0900858 ExifEntry *w = exif_content_get_entry(
859 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
860 ExifEntry *h = exif_content_get_entry(
861 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
862 info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
863 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
864 info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
865 info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
866 exif_data_unref(exifdata);
867 }
868 break;
869 }
870
871 // Except DNG, all supported RAW image formats are not defined in PTP 1.2 specification.
872 // Most of RAW image formats are based on TIFF or TIFF/EP. To render Fuji's RAF format,
873 // it checks MTP_FORMAT_DEFINED case since it's designed as a custom format.
874 case MTP_FORMAT_DNG:
875 case MTP_FORMAT_TIFF:
876 case MTP_FORMAT_TIFF_EP:
877 case MTP_FORMAT_DEFINED: {
878 std::unique_ptr<FileStream> stream(new FileStream(path));
879 piex::PreviewImageData image_data;
880 if (!GetExifFromRawImage(stream.get(), path, image_data)) {
881 // Couldn't parse EXIF data from a image file via piex.
882 break;
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800883 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800884
Jaesung Chung8409c062016-01-19 10:48:30 +0900885 info.mThumbCompressedSize = image_data.thumbnail_length;
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800886 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
Jaesung Chung8409c062016-01-19 10:48:30 +0900887 info.mImagePixWidth = image_data.full_width;
888 info.mImagePixHeight = image_data.full_height;
889
890 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700891 }
892 }
893
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400894 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400895 return MTP_RESPONSE_OK;
896}
897
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700898void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
899 MtpString path;
900 int64_t length;
901 MtpObjectFormat format;
902 void* result = NULL;
903 outThumbSize = 0;
904
Jaesung Chung8409c062016-01-19 10:48:30 +0900905 if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
906 switch (format) {
907 case MTP_FORMAT_EXIF_JPEG:
908 case MTP_FORMAT_JFIF: {
909 ExifData *exifdata = exif_data_new_from_file(path);
910 if (exifdata) {
911 if (exifdata->data) {
912 result = malloc(exifdata->size);
913 if (result) {
914 memcpy(result, exifdata->data, exifdata->size);
915 outThumbSize = exifdata->size;
916 }
917 }
918 exif_data_unref(exifdata);
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800919 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900920 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700921 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900922
923 // See the above comment on getObjectInfo() method.
924 case MTP_FORMAT_DNG:
925 case MTP_FORMAT_TIFF:
926 case MTP_FORMAT_TIFF_EP:
927 case MTP_FORMAT_DEFINED: {
928 std::unique_ptr<FileStream> stream(new FileStream(path));
929 piex::PreviewImageData image_data;
930 if (!GetExifFromRawImage(stream.get(), path, image_data)) {
931 // Couldn't parse EXIF data from a image file via piex.
932 break;
933 }
934
935 if (image_data.thumbnail_length == 0) {
936 // No thumbnail.
937 break;
938 }
939
940 result = malloc(image_data.thumbnail_length);
941 if (result) {
942 piex::Error err = stream.get()->GetData(
943 image_data.thumbnail_offset,
944 image_data.thumbnail_length,
945 (std::uint8_t *)result);
946 if (err == piex::Error::kOk) {
947 outThumbSize = image_data.thumbnail_length;
948 } else {
949 free(result);
950 }
951 }
952 break;
953 }
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700954 }
955 }
956
957 return result;
958}
959
Mike Lockwood59c777a2010-08-02 10:37:41 -0400960MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900961 MtpString& outFilePath,
962 int64_t& outFileLength,
963 MtpObjectFormat& outFormat) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400964 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400965 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400966 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400967 if (result != MTP_RESPONSE_OK) {
968 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400969 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400970 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400971
972 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Dan Albert66987492014-11-20 11:41:21 -0800973 outFilePath.setTo(reinterpret_cast<char16_t*>(str),
974 strlen16(reinterpret_cast<char16_t*>(str)));
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400975 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
976
977 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800978 outFileLength = longValues[0];
979 outFormat = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400980 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700981
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400982 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400983 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400984}
985
Mike Lockwood59c777a2010-08-02 10:37:41 -0400986MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400987 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400988 MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
989
990 checkAndClearExceptionFromCallback(env, __FUNCTION__);
991 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400992}
993
994struct PropertyTableEntry {
995 MtpObjectProperty property;
996 int type;
997};
998
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400999static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001000 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
1001 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
1002 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
1003 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
1004 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
1005 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
1006 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
1007 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
1008 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -04001009 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
1010 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
1011 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
1012 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
1013 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
1014 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
1015 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
1016 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
1017 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
1018 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
1019 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwood71827742015-01-23 10:50:08 -08001020 { MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_TYPE_UINT32 },
1021 { MTP_PROPERTY_BITRATE_TYPE, MTP_TYPE_UINT16 },
1022 { MTP_PROPERTY_AUDIO_BITRATE, MTP_TYPE_UINT32 },
1023 { MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_TYPE_UINT16 },
1024 { MTP_PROPERTY_SAMPLE_RATE, MTP_TYPE_UINT32 },
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001025};
1026
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001027static const PropertyTableEntry kDevicePropertyTable[] = {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001028 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
1029 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
1030 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
Mike Lockwood56c85242014-03-07 13:29:08 -08001031 { MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001032};
1033
1034bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
1035 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
1036 const PropertyTableEntry* entry = kObjectPropertyTable;
1037 for (int i = 0; i < count; i++, entry++) {
1038 if (entry->property == property) {
1039 type = entry->type;
1040 return true;
1041 }
1042 }
1043 return false;
1044}
1045
1046bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
1047 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
1048 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001049 for (int i = 0; i < count; i++, entry++) {
1050 if (entry->property == property) {
1051 type = entry->type;
1052 return true;
1053 }
1054 }
1055 return false;
1056}
1057
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001058MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
1059 JNIEnv* env = AndroidRuntime::getJNIEnv();
1060 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
1061 (jint)handle);
1062 if (!array)
1063 return NULL;
1064 MtpObjectHandleList* list = new MtpObjectHandleList();
1065 jint* handles = env->GetIntArrayElements(array, 0);
1066 jsize length = env->GetArrayLength(array);
1067 for (int i = 0; i < length; i++)
1068 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001069 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -04001070 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001071
1072 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1073 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001074}
1075
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001076MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001077 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001078 JNIEnv* env = AndroidRuntime::getJNIEnv();
1079 int count = references->size();
1080 jintArray array = env->NewIntArray(count);
1081 if (!array) {
Steve Block3762c312012-01-06 19:20:56 +00001082 ALOGE("out of memory in setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001083 return false;
1084 }
1085 jint* handles = env->GetIntArrayElements(array, 0);
1086 for (int i = 0; i < count; i++)
1087 handles[i] = (*references)[i];
1088 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001089 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001090 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -04001091 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001092
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001093 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1094 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001095}
1096
Mike Lockwood828d19d2010-08-10 15:20:35 -04001097MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001098 MtpObjectFormat format) {
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001099 static const int channelEnum[] = {
1100 1, // mono
1101 2, // stereo
1102 3, // 2.1
1103 4, // 3
1104 5, // 3.1
1105 6, // 4
1106 7, // 4.1
1107 8, // 5
1108 9, // 5.1
1109 };
1110 static const int bitrateEnum[] = {
1111 1, // fixed rate
1112 2, // variable rate
1113 };
1114
Mike Lockwood828d19d2010-08-10 15:20:35 -04001115 MtpProperty* result = NULL;
1116 switch (property) {
1117 case MTP_PROPERTY_OBJECT_FORMAT:
Mike Lockwood9b5e9c42010-12-07 18:53:50 -08001118 // use format as default value
1119 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
1120 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001121 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001122 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001123 result = new MtpProperty(property, MTP_TYPE_UINT16);
1124 break;
1125 case MTP_PROPERTY_STORAGE_ID:
1126 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001127 case MTP_PROPERTY_DURATION:
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001128 case MTP_PROPERTY_AUDIO_WAVE_CODEC:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001129 result = new MtpProperty(property, MTP_TYPE_UINT32);
1130 break;
1131 case MTP_PROPERTY_OBJECT_SIZE:
1132 result = new MtpProperty(property, MTP_TYPE_UINT64);
1133 break;
1134 case MTP_PROPERTY_PERSISTENT_UID:
1135 result = new MtpProperty(property, MTP_TYPE_UINT128);
1136 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001137 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001138 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001139 case MTP_PROPERTY_ARTIST:
1140 case MTP_PROPERTY_ALBUM_NAME:
1141 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001142 case MTP_PROPERTY_GENRE:
1143 case MTP_PROPERTY_COMPOSER:
1144 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001145 result = new MtpProperty(property, MTP_TYPE_STR);
1146 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -05001147 case MTP_PROPERTY_DATE_MODIFIED:
1148 case MTP_PROPERTY_DATE_ADDED:
1149 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
1150 result = new MtpProperty(property, MTP_TYPE_STR);
1151 result->setFormDateTime();
1152 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -04001153 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -04001154 // We allow renaming files and folders
1155 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -04001156 break;
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001157 case MTP_PROPERTY_BITRATE_TYPE:
1158 result = new MtpProperty(property, MTP_TYPE_UINT16);
1159 result->setFormEnum(bitrateEnum, sizeof(bitrateEnum)/sizeof(bitrateEnum[0]));
1160 break;
1161 case MTP_PROPERTY_AUDIO_BITRATE:
1162 result = new MtpProperty(property, MTP_TYPE_UINT32);
1163 result->setFormRange(1, 1536000, 1);
1164 break;
1165 case MTP_PROPERTY_NUMBER_OF_CHANNELS:
1166 result = new MtpProperty(property, MTP_TYPE_UINT16);
1167 result->setFormEnum(channelEnum, sizeof(channelEnum)/sizeof(channelEnum[0]));
1168 break;
1169 case MTP_PROPERTY_SAMPLE_RATE:
1170 result = new MtpProperty(property, MTP_TYPE_UINT32);
1171 result->setFormRange(8000, 48000, 1);
1172 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001173 }
1174
1175 return result;
1176}
1177
1178MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001179 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001180 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001181 bool writable = false;
1182
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001183 switch (property) {
1184 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
1185 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001186 writable = true;
1187 // fall through
Mike Lockwood56c85242014-03-07 13:29:08 -08001188 case MTP_DEVICE_PROPERTY_IMAGE_SIZE: {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001189 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001190
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001191 // get current value
Mike Lockwooda2a21282010-09-25 21:21:05 -04001192 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
1193 (jint)property, mLongBuffer, mStringBuffer);
1194 if (ret == MTP_RESPONSE_OK) {
1195 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
1196 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001197 // for read-only properties it is safe to assume current value is default value
1198 if (!writable)
1199 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001200 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
1201 } else {
Steve Block3762c312012-01-06 19:20:56 +00001202 ALOGE("unable to read device property, response: %04X", ret);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001203 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001204 break;
Mike Lockwood56c85242014-03-07 13:29:08 -08001205 }
1206 case MTP_DEVICE_PROPERTY_BATTERY_LEVEL:
1207 result = new MtpProperty(property, MTP_TYPE_UINT8);
1208 result->setFormRange(0, env->GetIntField(mDatabase, field_batteryScale), 1);
1209 result->mCurrentValue.u.u8 = (uint8_t)env->GetIntField(mDatabase, field_batteryLevel);
1210 break;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001211 }
1212
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001213 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001214 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001215}
1216
Mike Lockwood2837eef2010-08-31 16:25:12 -04001217void MyMtpDatabase::sessionStarted() {
1218 JNIEnv* env = AndroidRuntime::getJNIEnv();
1219 env->CallVoidMethod(mDatabase, method_sessionStarted);
1220 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1221}
1222
1223void MyMtpDatabase::sessionEnded() {
1224 JNIEnv* env = AndroidRuntime::getJNIEnv();
1225 env->CallVoidMethod(mDatabase, method_sessionEnded);
1226 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1227}
1228
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001229// ----------------------------------------------------------------------------
1230
1231static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001232android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001233{
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001234 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
Ashok Bhate2e59322013-12-17 19:04:19 +00001235 env->SetLongField(thiz, field_context, (jlong)database);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001236 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1237}
1238
1239static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001240android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001241{
Ashok Bhate2e59322013-12-17 19:04:19 +00001242 MyMtpDatabase* database = (MyMtpDatabase *)env->GetLongField(thiz, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001243 database->cleanup(env);
1244 delete database;
Ashok Bhate2e59322013-12-17 19:04:19 +00001245 env->SetLongField(thiz, field_context, 0);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001246 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1247}
1248
Mike Lockwood31599912010-11-15 13:43:30 -05001249static jstring
Mark Salyzynaeb75fc2014-03-20 12:09:01 -07001250android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001251{
Mike Lockwood31599912010-11-15 13:43:30 -05001252 char date[20];
1253 formatDateTime(seconds, date, sizeof(date));
1254 return env->NewStringUTF(date);
Mike Lockwood31599912010-11-15 13:43:30 -05001255}
1256
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001257// ----------------------------------------------------------------------------
1258
Daniel Micay76f6a862015-09-19 17:31:01 -04001259static const JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001260 {"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
1261 {"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001262};
1263
Daniel Micay76f6a862015-09-19 17:31:01 -04001264static const JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001265 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001266 (void *)android_mtp_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001267};
1268
Mike Lockwood0cd01362010-12-30 11:54:33 -05001269int register_android_mtp_MtpDatabase(JNIEnv *env)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001270{
1271 jclass clazz;
1272
Mike Lockwood0cd01362010-12-30 11:54:33 -05001273 clazz = env->FindClass("android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001274 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001275 ALOGE("Can't find android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001276 return -1;
1277 }
Mike Lockwoodd815f792010-07-12 08:49:01 -04001278 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1279 if (method_beginSendObject == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001280 ALOGE("Can't find beginSendObject");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001281 return -1;
1282 }
Mike Lockwood7a0bd172011-01-18 11:06:19 -08001283 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001284 if (method_endSendObject == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001285 ALOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001286 return -1;
1287 }
1288 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1289 if (method_getObjectList == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001290 ALOGE("Can't find getObjectList");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001291 return -1;
1292 }
Mike Lockwood7a047c82010-08-02 10:52:20 -04001293 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
1294 if (method_getNumObjects == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001295 ALOGE("Can't find getNumObjects");
Mike Lockwood7a047c82010-08-02 10:52:20 -04001296 return -1;
1297 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001298 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
1299 if (method_getSupportedPlaybackFormats == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001300 ALOGE("Can't find getSupportedPlaybackFormats");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001301 return -1;
1302 }
1303 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
1304 if (method_getSupportedCaptureFormats == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001305 ALOGE("Can't find getSupportedCaptureFormats");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001306 return -1;
1307 }
1308 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
1309 if (method_getSupportedObjectProperties == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001310 ALOGE("Can't find getSupportedObjectProperties");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001311 return -1;
1312 }
1313 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
1314 if (method_getSupportedDeviceProperties == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001315 ALOGE("Can't find getSupportedDeviceProperties");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001316 return -1;
1317 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001318 method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
1319 if (method_setObjectProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001320 ALOGE("Can't find setObjectProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001321 return -1;
1322 }
1323 method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
1324 if (method_getDeviceProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001325 ALOGE("Can't find getDeviceProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001326 return -1;
1327 }
1328 method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
1329 if (method_setDeviceProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001330 ALOGE("Can't find setDeviceProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001331 return -1;
1332 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001333 method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001334 "(IIIII)Landroid/mtp/MtpPropertyList;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001335 if (method_getObjectPropertyList == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001336 ALOGE("Can't find getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001337 return -1;
1338 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001339 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1340 if (method_getObjectInfo == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001341 ALOGE("Can't find getObjectInfo");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001342 return -1;
1343 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001344 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001345 if (method_getObjectFilePath == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001346 ALOGE("Can't find getObjectFilePath");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001347 return -1;
1348 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001349 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001350 if (method_deleteFile == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001351 ALOGE("Can't find deleteFile");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001352 return -1;
1353 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001354 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
1355 if (method_getObjectReferences == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001356 ALOGE("Can't find getObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001357 return -1;
1358 }
1359 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
1360 if (method_setObjectReferences == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001361 ALOGE("Can't find setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001362 return -1;
1363 }
Mike Lockwood2837eef2010-08-31 16:25:12 -04001364 method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
1365 if (method_sessionStarted == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001366 ALOGE("Can't find sessionStarted");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001367 return -1;
1368 }
1369 method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
1370 if (method_sessionEnded == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001371 ALOGE("Can't find sessionEnded");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001372 return -1;
1373 }
1374
Ashok Bhate2e59322013-12-17 19:04:19 +00001375 field_context = env->GetFieldID(clazz, "mNativeContext", "J");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001376 if (field_context == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001377 ALOGE("Can't find MtpDatabase.mNativeContext");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001378 return -1;
1379 }
Mike Lockwood56c85242014-03-07 13:29:08 -08001380 field_batteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");
1381 if (field_batteryLevel == NULL) {
1382 ALOGE("Can't find MtpDatabase.mBatteryLevel");
1383 return -1;
1384 }
1385 field_batteryScale = env->GetFieldID(clazz, "mBatteryScale", "I");
1386 if (field_batteryScale == NULL) {
1387 ALOGE("Can't find MtpDatabase.mBatteryScale");
1388 return -1;
1389 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001390
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001391 // now set up fields for MtpPropertyList class
Mike Lockwood0cd01362010-12-30 11:54:33 -05001392 clazz = env->FindClass("android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001393 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001394 ALOGE("Can't find android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001395 return -1;
1396 }
1397 field_mCount = env->GetFieldID(clazz, "mCount", "I");
1398 if (field_mCount == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001399 ALOGE("Can't find MtpPropertyList.mCount");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001400 return -1;
1401 }
1402 field_mResult = env->GetFieldID(clazz, "mResult", "I");
1403 if (field_mResult == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001404 ALOGE("Can't find MtpPropertyList.mResult");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001405 return -1;
1406 }
1407 field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1408 if (field_mObjectHandles == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001409 ALOGE("Can't find MtpPropertyList.mObjectHandles");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001410 return -1;
1411 }
1412 field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1413 if (field_mPropertyCodes == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001414 ALOGE("Can't find MtpPropertyList.mPropertyCodes");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001415 return -1;
1416 }
1417 field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1418 if (field_mDataTypes == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001419 ALOGE("Can't find MtpPropertyList.mDataTypes");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001420 return -1;
1421 }
1422 field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1423 if (field_mLongValues == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001424 ALOGE("Can't find MtpPropertyList.mLongValues");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001425 return -1;
1426 }
1427 field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1428 if (field_mStringValues == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001429 ALOGE("Can't find MtpPropertyList.mStringValues");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001430 return -1;
1431 }
1432
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001433 if (AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001434 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001435 return -1;
1436
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001437 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001438 "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001439}