blob: 5b874cd826788e188462b6f36bd81051c3af4a89 [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>
Steven Moreland2279b252017-07-19 09:50:45 -070042#include <nativehelper/JNIHelp.h>
Jaesung Chung8409c062016-01-19 10:48:30 +090043#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;
Jerry Zhang13bb2f42016-12-14 15:39:29 -080079static jfieldID field_deviceType;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040080
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040081// MtpPropertyList fields
82static jfieldID field_mCount;
83static jfieldID field_mResult;
84static jfieldID field_mObjectHandles;
85static jfieldID field_mPropertyCodes;
86static jfieldID field_mDataTypes;
87static jfieldID field_mLongValues;
88static jfieldID field_mStringValues;
89
90
Mike Lockwoodd21eac92010-07-03 00:44:05 -040091MtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
Ashok Bhate2e59322013-12-17 19:04:19 +000092 return (MtpDatabase *)env->GetLongField(database, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -040093}
94
95// ----------------------------------------------------------------------------
96
97class MyMtpDatabase : public MtpDatabase {
98private:
99 jobject mDatabase;
100 jintArray mIntBuffer;
101 jlongArray mLongBuffer;
102 jcharArray mStringBuffer;
103
104public:
105 MyMtpDatabase(JNIEnv *env, jobject client);
106 virtual ~MyMtpDatabase();
107 void cleanup(JNIEnv *env);
108
Mike Lockwoodd815f792010-07-12 08:49:01 -0400109 virtual MtpObjectHandle beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400110 MtpObjectFormat format,
111 MtpObjectHandle parent,
112 MtpStorageID storage,
113 uint64_t size,
114 time_t modified);
115
Mike Lockwoodd815f792010-07-12 08:49:01 -0400116 virtual void endSendObject(const char* path,
117 MtpObjectHandle handle,
118 MtpObjectFormat format,
119 bool succeeded);
120
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400121 virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
122 MtpObjectFormat format,
123 MtpObjectHandle parent);
124
Mike Lockwood7a047c82010-08-02 10:52:20 -0400125 virtual int getNumObjects(MtpStorageID storageID,
126 MtpObjectFormat format,
127 MtpObjectHandle parent);
128
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400129 // callee should delete[] the results from these
130 // results can be NULL
131 virtual MtpObjectFormatList* getSupportedPlaybackFormats();
132 virtual MtpObjectFormatList* getSupportedCaptureFormats();
133 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
134 virtual MtpDevicePropertyList* getSupportedDeviceProperties();
135
Mike Lockwood828d19d2010-08-10 15:20:35 -0400136 virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400137 MtpObjectProperty property,
138 MtpDataPacket& packet);
139
Mike Lockwood828d19d2010-08-10 15:20:35 -0400140 virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
141 MtpObjectProperty property,
142 MtpDataPacket& packet);
143
144 virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
145 MtpDataPacket& packet);
146
147 virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
148 MtpDataPacket& packet);
149
150 virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
151
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400152 virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500153 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400154 int groupCode, int depth,
155 MtpDataPacket& packet);
156
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400157 virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700158 MtpObjectInfo& info);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400159
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700160 virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
161
Mike Lockwood59c777a2010-08-02 10:37:41 -0400162 virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800163 MtpString& outFilePath,
164 int64_t& outFileLength,
165 MtpObjectFormat& outFormat);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400166 virtual MtpResponseCode deleteFile(MtpObjectHandle handle);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400167
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400168 bool getObjectPropertyInfo(MtpObjectProperty property, int& type);
169 bool getDevicePropertyInfo(MtpDeviceProperty property, int& type);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400170
171 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
172
173 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
174 MtpObjectHandleList* references);
Mike Lockwood828d19d2010-08-10 15:20:35 -0400175
176 virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
177 MtpObjectFormat format);
178
179 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400180
181 virtual void sessionStarted();
182
183 virtual void sessionEnded();
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400184};
185
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400186// ----------------------------------------------------------------------------
187
188static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
189 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +0000190 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400191 LOGE_EX(env);
192 env->ExceptionClear();
193 }
194}
195
196// ----------------------------------------------------------------------------
197
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400198MyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
199 : mDatabase(env->NewGlobalRef(client)),
200 mIntBuffer(NULL),
201 mLongBuffer(NULL),
202 mStringBuffer(NULL)
203{
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400204 // create buffers for out arguments
205 // we don't need to be thread-safe so this is OK
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700206 jintArray intArray = env->NewIntArray(3);
207 if (!intArray) {
208 return; // Already threw.
209 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400210 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700211 jlongArray longArray = env->NewLongArray(2);
212 if (!longArray) {
213 return; // Already threw.
214 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400215 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
Mike Lockwood63ffd782014-09-24 10:55:19 -0700216 // Needs to be long enough to hold a file path for getObjectFilePath()
217 jcharArray charArray = env->NewCharArray(PATH_MAX + 1);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700218 if (!charArray) {
219 return; // Already threw.
220 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400221 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400222}
223
224void MyMtpDatabase::cleanup(JNIEnv *env) {
225 env->DeleteGlobalRef(mDatabase);
226 env->DeleteGlobalRef(mIntBuffer);
227 env->DeleteGlobalRef(mLongBuffer);
228 env->DeleteGlobalRef(mStringBuffer);
229}
230
231MyMtpDatabase::~MyMtpDatabase() {
232}
233
Mike Lockwoodd815f792010-07-12 08:49:01 -0400234MtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900235 MtpObjectFormat format,
236 MtpObjectHandle parent,
237 MtpStorageID storage,
238 uint64_t size,
239 time_t modified) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400240 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400241 jstring pathStr = env->NewStringUTF(path);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400242 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
Mike Lockwood88394712010-09-27 10:01:00 -0400243 pathStr, (jint)format, (jint)parent, (jint)storage,
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400244 (jlong)size, (jlong)modified);
245
Mike Lockwood88394712010-09-27 10:01:00 -0400246 if (pathStr)
247 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400248 checkAndClearExceptionFromCallback(env, __FUNCTION__);
249 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400250}
251
Mike Lockwoodd815f792010-07-12 08:49:01 -0400252void MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900253 MtpObjectFormat format, bool succeeded) {
Mike Lockwoodd815f792010-07-12 08:49:01 -0400254 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400255 jstring pathStr = env->NewStringUTF(path);
256 env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
Mike Lockwood7a0bd172011-01-18 11:06:19 -0800257 (jint)handle, (jint)format, (jboolean)succeeded);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400258
Mike Lockwood88394712010-09-27 10:01:00 -0400259 if (pathStr)
260 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400261 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400262}
263
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400264MtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900265 MtpObjectFormat format,
266 MtpObjectHandle parent) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400267 JNIEnv* env = AndroidRuntime::getJNIEnv();
268 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
269 (jint)storageID, (jint)format, (jint)parent);
270 if (!array)
271 return NULL;
272 MtpObjectHandleList* list = new MtpObjectHandleList();
273 jint* handles = env->GetIntArrayElements(array, 0);
274 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400275 for (int i = 0; i < length; i++)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400276 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400277 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400278 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400279
280 checkAndClearExceptionFromCallback(env, __FUNCTION__);
281 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400282}
283
Mike Lockwood7a047c82010-08-02 10:52:20 -0400284int MyMtpDatabase::getNumObjects(MtpStorageID storageID,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900285 MtpObjectFormat format,
286 MtpObjectHandle parent) {
Mike Lockwood7a047c82010-08-02 10:52:20 -0400287 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400288 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400289 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400290
291 checkAndClearExceptionFromCallback(env, __FUNCTION__);
292 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400293}
294
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400295MtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
296 JNIEnv* env = AndroidRuntime::getJNIEnv();
297 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
298 method_getSupportedPlaybackFormats);
299 if (!array)
300 return NULL;
301 MtpObjectFormatList* list = new MtpObjectFormatList();
302 jint* formats = env->GetIntArrayElements(array, 0);
303 jsize length = env->GetArrayLength(array);
304 for (int i = 0; i < length; i++)
305 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400306 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400307 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400308
309 checkAndClearExceptionFromCallback(env, __FUNCTION__);
310 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400311}
312
313MtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
314 JNIEnv* env = AndroidRuntime::getJNIEnv();
315 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
316 method_getSupportedCaptureFormats);
317 if (!array)
318 return NULL;
319 MtpObjectFormatList* list = new MtpObjectFormatList();
320 jint* formats = env->GetIntArrayElements(array, 0);
321 jsize length = env->GetArrayLength(array);
322 for (int i = 0; i < length; i++)
323 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400324 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400325 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400326
327 checkAndClearExceptionFromCallback(env, __FUNCTION__);
328 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400329}
330
331MtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
332 JNIEnv* env = AndroidRuntime::getJNIEnv();
333 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
334 method_getSupportedObjectProperties, (jint)format);
335 if (!array)
336 return NULL;
337 MtpObjectPropertyList* list = new MtpObjectPropertyList();
338 jint* properties = env->GetIntArrayElements(array, 0);
339 jsize length = env->GetArrayLength(array);
340 for (int i = 0; i < length; i++)
341 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400342 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400343 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400344
345 checkAndClearExceptionFromCallback(env, __FUNCTION__);
346 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400347}
348
349MtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
350 JNIEnv* env = AndroidRuntime::getJNIEnv();
351 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
352 method_getSupportedDeviceProperties);
353 if (!array)
354 return NULL;
355 MtpDevicePropertyList* list = new MtpDevicePropertyList();
356 jint* properties = env->GetIntArrayElements(array, 0);
357 jsize length = env->GetArrayLength(array);
358 for (int i = 0; i < length; i++)
359 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400360 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400361 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400362
363 checkAndClearExceptionFromCallback(env, __FUNCTION__);
364 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400365}
366
Mike Lockwood828d19d2010-08-10 15:20:35 -0400367MtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900368 MtpObjectProperty property,
369 MtpDataPacket& packet) {
370 static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
371 "Casting MtpObjectHandle to jint loses a value");
372 static_assert(sizeof(jint) >= sizeof(MtpObjectProperty),
373 "Casting MtpObjectProperty to jint loses a value");
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400374 JNIEnv* env = AndroidRuntime::getJNIEnv();
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900375 jobject list = env->CallObjectMethod(
376 mDatabase,
377 method_getObjectPropertyList,
378 static_cast<jint>(handle),
379 0,
380 static_cast<jint>(property),
381 0,
382 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400383 MtpResponseCode result = env->GetIntField(list, field_mResult);
384 int count = env->GetIntField(list, field_mCount);
385 if (result == MTP_RESPONSE_OK && count != 1)
386 result = MTP_RESPONSE_GENERAL_ERROR;
387
388 if (result == MTP_RESPONSE_OK) {
389 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
390 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
391 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
392 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
393 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
394
395 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
396 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
397 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
398 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
399
400 int type = dataTypes[0];
401 jlong longValue = (longValues ? longValues[0] : 0);
402
403 // special case date properties, which are strings to MTP
404 // but stored internally as a uint64
405 if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
406 char date[20];
407 formatDateTime(longValue, date, sizeof(date));
408 packet.putString(date);
409 goto out;
410 }
411 // release date is stored internally as just the year
412 if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
413 char date[20];
Mark Salyzynaeb75fc2014-03-20 12:09:01 -0700414 snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400415 packet.putString(date);
416 goto out;
417 }
418
419 switch (type) {
420 case MTP_TYPE_INT8:
421 packet.putInt8(longValue);
422 break;
423 case MTP_TYPE_UINT8:
424 packet.putUInt8(longValue);
425 break;
426 case MTP_TYPE_INT16:
427 packet.putInt16(longValue);
428 break;
429 case MTP_TYPE_UINT16:
430 packet.putUInt16(longValue);
431 break;
432 case MTP_TYPE_INT32:
433 packet.putInt32(longValue);
434 break;
435 case MTP_TYPE_UINT32:
436 packet.putUInt32(longValue);
437 break;
438 case MTP_TYPE_INT64:
439 packet.putInt64(longValue);
440 break;
441 case MTP_TYPE_UINT64:
442 packet.putUInt64(longValue);
443 break;
444 case MTP_TYPE_INT128:
445 packet.putInt128(longValue);
446 break;
447 case MTP_TYPE_UINT128:
Wanwu Peng8937f1a2016-03-02 18:16:46 +0800448 packet.putUInt128(longValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400449 break;
450 case MTP_TYPE_STR:
451 {
452 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200453 const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400454 if (stringValue) {
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400455 packet.putString(str);
456 env->ReleaseStringUTFChars(stringValue, str);
457 } else {
458 packet.putEmptyString();
459 }
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200460 env->DeleteLocalRef(stringValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400461 break;
462 }
463 default:
Steve Block3762c312012-01-06 19:20:56 +0000464 ALOGE("unsupported type in getObjectPropertyValue\n");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400465 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
466 }
467out:
468 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
469 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
470 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
471 if (longValues)
472 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
473
474 env->DeleteLocalRef(objectHandlesArray);
475 env->DeleteLocalRef(propertyCodesArray);
476 env->DeleteLocalRef(dataTypesArray);
477 if (longValuesArray)
478 env->DeleteLocalRef(longValuesArray);
479 if (stringValuesArray)
480 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400481 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400482
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400483 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400484 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400485 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400486}
487
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800488static bool readLongValue(int type, MtpDataPacket& packet, jlong& longValue) {
489 switch (type) {
490 case MTP_TYPE_INT8: {
491 int8_t temp;
492 if (!packet.getInt8(temp)) return false;
493 longValue = temp;
494 break;
495 }
496 case MTP_TYPE_UINT8: {
497 uint8_t temp;
498 if (!packet.getUInt8(temp)) return false;
499 longValue = temp;
500 break;
501 }
502 case MTP_TYPE_INT16: {
503 int16_t temp;
504 if (!packet.getInt16(temp)) return false;
505 longValue = temp;
506 break;
507 }
508 case MTP_TYPE_UINT16: {
509 uint16_t temp;
510 if (!packet.getUInt16(temp)) return false;
511 longValue = temp;
512 break;
513 }
514 case MTP_TYPE_INT32: {
515 int32_t temp;
516 if (!packet.getInt32(temp)) return false;
517 longValue = temp;
518 break;
519 }
520 case MTP_TYPE_UINT32: {
521 uint32_t temp;
522 if (!packet.getUInt32(temp)) return false;
523 longValue = temp;
524 break;
525 }
526 case MTP_TYPE_INT64: {
527 int64_t temp;
528 if (!packet.getInt64(temp)) return false;
529 longValue = temp;
530 break;
531 }
532 case MTP_TYPE_UINT64: {
533 uint64_t temp;
534 if (!packet.getUInt64(temp)) return false;
535 longValue = temp;
536 break;
537 }
538 default:
539 ALOGE("unsupported type in readLongValue");
540 return false;
541 }
542 return true;
543}
544
Mike Lockwood828d19d2010-08-10 15:20:35 -0400545MtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900546 MtpObjectProperty property,
547 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400548 int type;
549
550 if (!getObjectPropertyInfo(property, type))
551 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
552
553 JNIEnv* env = AndroidRuntime::getJNIEnv();
554 jlong longValue = 0;
555 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800556 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400557
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800558 if (type == MTP_TYPE_STR) {
559 MtpStringBuffer buffer;
560 if (!packet.getString(buffer)) goto fail;
561 stringValue = env->NewStringUTF((const char *)buffer);
562 } else {
563 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400564 }
565
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800566 result = env->CallIntMethod(mDatabase, method_setObjectProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400567 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400568 if (stringValue)
569 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400570
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800571fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400572 checkAndClearExceptionFromCallback(env, __FUNCTION__);
573 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400574}
575
576MtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900577 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400578 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood56c85242014-03-07 13:29:08 -0800579
580 if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) {
581 // special case - implemented here instead of Java
582 packet.putUInt8((uint8_t)env->GetIntField(mDatabase, field_batteryLevel));
583 return MTP_RESPONSE_OK;
584 } else {
585 int type;
586
587 if (!getDevicePropertyInfo(property, type))
588 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
589
590 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
591 (jint)property, mLongBuffer, mStringBuffer);
592 if (result != MTP_RESPONSE_OK) {
593 checkAndClearExceptionFromCallback(env, __FUNCTION__);
594 return result;
595 }
596
597 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
598 jlong longValue = longValues[0];
599 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
600
601 switch (type) {
602 case MTP_TYPE_INT8:
603 packet.putInt8(longValue);
604 break;
605 case MTP_TYPE_UINT8:
606 packet.putUInt8(longValue);
607 break;
608 case MTP_TYPE_INT16:
609 packet.putInt16(longValue);
610 break;
611 case MTP_TYPE_UINT16:
612 packet.putUInt16(longValue);
613 break;
614 case MTP_TYPE_INT32:
615 packet.putInt32(longValue);
616 break;
617 case MTP_TYPE_UINT32:
618 packet.putUInt32(longValue);
619 break;
620 case MTP_TYPE_INT64:
621 packet.putInt64(longValue);
622 break;
623 case MTP_TYPE_UINT64:
624 packet.putUInt64(longValue);
625 break;
626 case MTP_TYPE_INT128:
627 packet.putInt128(longValue);
628 break;
629 case MTP_TYPE_UINT128:
630 packet.putInt128(longValue);
631 break;
632 case MTP_TYPE_STR:
633 {
634 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
635 packet.putString(str);
636 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
637 break;
638 }
639 default:
640 ALOGE("unsupported type in getDevicePropertyValue\n");
641 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
642 }
643
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400644 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood56c85242014-03-07 13:29:08 -0800645 return MTP_RESPONSE_OK;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400646 }
Mike Lockwood828d19d2010-08-10 15:20:35 -0400647}
648
649MtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900650 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400651 int type;
652
653 if (!getDevicePropertyInfo(property, type))
654 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
655
656 JNIEnv* env = AndroidRuntime::getJNIEnv();
657 jlong longValue = 0;
658 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800659 MtpResponseCode result = MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400660
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800661 if (type == MTP_TYPE_STR) {
662 MtpStringBuffer buffer;
663 if (!packet.getString(buffer)) goto fail;
664 stringValue = env->NewStringUTF((const char *)buffer);
665 } else {
666 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400667 }
668
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800669 result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400670 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400671 if (stringValue)
672 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400673
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800674fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400675 checkAndClearExceptionFromCallback(env, __FUNCTION__);
676 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400677}
678
Mark Salyzynaeb75fc2014-03-20 12:09:01 -0700679MtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
Mike Lockwood828d19d2010-08-10 15:20:35 -0400680 return -1;
681}
682
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400683MtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900684 uint32_t format, uint32_t property,
685 int groupCode, int depth,
686 MtpDataPacket& packet) {
687 static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
688 "Casting MtpObjectHandle to jint loses a value");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400689 JNIEnv* env = AndroidRuntime::getJNIEnv();
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900690 jobject list = env->CallObjectMethod(
691 mDatabase,
692 method_getObjectPropertyList,
693 static_cast<jint>(handle),
694 static_cast<jint>(format),
695 static_cast<jint>(property),
696 static_cast<jint>(groupCode),
697 static_cast<jint>(depth));
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500698 checkAndClearExceptionFromCallback(env, __FUNCTION__);
699 if (!list)
700 return MTP_RESPONSE_GENERAL_ERROR;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400701 int count = env->GetIntField(list, field_mCount);
702 MtpResponseCode result = env->GetIntField(list, field_mResult);
703
704 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400705 if (count > 0) {
706 jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
707 jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
708 jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
709 jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
710 jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
711
712 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
713 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
714 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
715 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
716
717 for (int i = 0; i < count; i++) {
718 packet.putUInt32(objectHandles[i]);
719 packet.putUInt16(propertyCodes[i]);
720 int type = dataTypes[i];
721 packet.putUInt16(type);
722
723 switch (type) {
724 case MTP_TYPE_INT8:
725 packet.putInt8(longValues[i]);
726 break;
727 case MTP_TYPE_UINT8:
728 packet.putUInt8(longValues[i]);
729 break;
730 case MTP_TYPE_INT16:
731 packet.putInt16(longValues[i]);
732 break;
733 case MTP_TYPE_UINT16:
734 packet.putUInt16(longValues[i]);
735 break;
736 case MTP_TYPE_INT32:
737 packet.putInt32(longValues[i]);
738 break;
739 case MTP_TYPE_UINT32:
740 packet.putUInt32(longValues[i]);
741 break;
742 case MTP_TYPE_INT64:
743 packet.putInt64(longValues[i]);
744 break;
745 case MTP_TYPE_UINT64:
746 packet.putUInt64(longValues[i]);
747 break;
748 case MTP_TYPE_INT128:
749 packet.putInt128(longValues[i]);
750 break;
751 case MTP_TYPE_UINT128:
752 packet.putUInt128(longValues[i]);
753 break;
754 case MTP_TYPE_STR: {
755 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
Mike Lockwood2711e492010-12-11 11:24:37 -0800756 const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400757 if (valueStr) {
758 packet.putString(valueStr);
759 env->ReleaseStringUTFChars(value, valueStr);
760 } else {
761 packet.putEmptyString();
762 }
763 env->DeleteLocalRef(value);
764 break;
765 }
766 default:
Steve Block3762c312012-01-06 19:20:56 +0000767 ALOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400768 break;
769 }
770 }
771
772 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
773 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
774 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
775 if (longValues)
776 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
777
778 env->DeleteLocalRef(objectHandlesArray);
779 env->DeleteLocalRef(propertyCodesArray);
780 env->DeleteLocalRef(dataTypesArray);
781 if (longValuesArray)
782 env->DeleteLocalRef(longValuesArray);
783 if (stringValuesArray)
784 env->DeleteLocalRef(stringValuesArray);
785 }
786
787 env->DeleteLocalRef(list);
788 checkAndClearExceptionFromCallback(env, __FUNCTION__);
789 return result;
790}
791
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800792static void foreachentry(ExifEntry *entry, void* /* user */) {
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800793 char buf[1024];
794 ALOGI("entry %x, format %d, size %d: %s",
795 entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
796}
797
798static void foreachcontent(ExifContent *content, void *user) {
799 ALOGI("content %d", exif_content_get_ifd(content));
800 exif_content_foreach_entry(content, foreachentry, user);
801}
802
803static long getLongFromExifEntry(ExifEntry *e) {
804 ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
805 return exif_get_long(e->data, o);
806}
807
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400808MtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900809 MtpObjectInfo& info) {
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700810 MtpString path;
811 int64_t length;
812 MtpObjectFormat format;
813
814 MtpResponseCode result = getObjectFilePath(handle, path, length, format);
815 if (result != MTP_RESPONSE_OK) {
816 return result;
817 }
818 info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400819
820 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700821 if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
822 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400823 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700824 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400825
826 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700827 info.mStorageID = intValues[0];
828 info.mFormat = intValues[1];
829 info.mParent = intValues[2];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400830 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
831
832 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood1341f1e2013-04-01 10:52:47 -0700833 info.mDateCreated = longValues[0];
834 info.mDateModified = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400835 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
836
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800837 if ((false)) {
838 info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
839 MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
840 MTP_ASSOCIATION_TYPE_UNDEFINED);
841 }
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700842 info.mAssociationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400843
844 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Dan Albert66987492014-11-20 11:41:21 -0800845 MtpString temp(reinterpret_cast<char16_t*>(str));
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700846 info.mName = strdup((const char *)temp);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400847 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
848
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700849 // read EXIF data for thumbnail information
Jaesung Chung8409c062016-01-19 10:48:30 +0900850 switch (info.mFormat) {
851 case MTP_FORMAT_EXIF_JPEG:
Chong Zhang6e18cce2017-08-16 11:57:02 -0700852 case MTP_FORMAT_HEIF:
Jaesung Chung8409c062016-01-19 10:48:30 +0900853 case MTP_FORMAT_JFIF: {
854 ExifData *exifdata = exif_data_new_from_file(path);
855 if (exifdata) {
856 if ((false)) {
857 exif_data_foreach_content(exifdata, foreachcontent, NULL);
858 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800859
Jaesung Chung8409c062016-01-19 10:48:30 +0900860 ExifEntry *w = exif_content_get_entry(
861 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
862 ExifEntry *h = exif_content_get_entry(
863 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
864 info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
865 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
866 info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
867 info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
868 exif_data_unref(exifdata);
869 }
870 break;
871 }
872
873 // Except DNG, all supported RAW image formats are not defined in PTP 1.2 specification.
874 // Most of RAW image formats are based on TIFF or TIFF/EP. To render Fuji's RAF format,
875 // it checks MTP_FORMAT_DEFINED case since it's designed as a custom format.
876 case MTP_FORMAT_DNG:
877 case MTP_FORMAT_TIFF:
878 case MTP_FORMAT_TIFF_EP:
879 case MTP_FORMAT_DEFINED: {
880 std::unique_ptr<FileStream> stream(new FileStream(path));
881 piex::PreviewImageData image_data;
882 if (!GetExifFromRawImage(stream.get(), path, image_data)) {
883 // Couldn't parse EXIF data from a image file via piex.
884 break;
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800885 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800886
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900887 info.mThumbCompressedSize = image_data.thumbnail.length;
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800888 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
Jaesung Chung8409c062016-01-19 10:48:30 +0900889 info.mImagePixWidth = image_data.full_width;
890 info.mImagePixHeight = image_data.full_height;
891
892 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700893 }
894 }
895
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400896 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400897 return MTP_RESPONSE_OK;
898}
899
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700900void* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
901 MtpString path;
902 int64_t length;
903 MtpObjectFormat format;
904 void* result = NULL;
905 outThumbSize = 0;
906
Jaesung Chung8409c062016-01-19 10:48:30 +0900907 if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
908 switch (format) {
909 case MTP_FORMAT_EXIF_JPEG:
Chong Zhang6e18cce2017-08-16 11:57:02 -0700910 case MTP_FORMAT_HEIF:
Jaesung Chung8409c062016-01-19 10:48:30 +0900911 case MTP_FORMAT_JFIF: {
912 ExifData *exifdata = exif_data_new_from_file(path);
913 if (exifdata) {
914 if (exifdata->data) {
915 result = malloc(exifdata->size);
916 if (result) {
917 memcpy(result, exifdata->data, exifdata->size);
918 outThumbSize = exifdata->size;
919 }
920 }
921 exif_data_unref(exifdata);
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800922 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900923 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700924 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900925
926 // See the above comment on getObjectInfo() method.
927 case MTP_FORMAT_DNG:
928 case MTP_FORMAT_TIFF:
929 case MTP_FORMAT_TIFF_EP:
930 case MTP_FORMAT_DEFINED: {
931 std::unique_ptr<FileStream> stream(new FileStream(path));
932 piex::PreviewImageData image_data;
933 if (!GetExifFromRawImage(stream.get(), path, image_data)) {
934 // Couldn't parse EXIF data from a image file via piex.
935 break;
936 }
937
Jaesung Chung742e89f2016-04-13 14:13:10 +0900938 if (image_data.thumbnail.length == 0
Insun Kang82c2ce12016-04-19 17:56:10 +0900939 || image_data.thumbnail.format != ::piex::Image::kJpegCompressed) {
Jaesung Chung742e89f2016-04-13 14:13:10 +0900940 // No thumbnail or non jpeg thumbnail.
Jaesung Chung8409c062016-01-19 10:48:30 +0900941 break;
942 }
943
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900944 result = malloc(image_data.thumbnail.length);
Jaesung Chung8409c062016-01-19 10:48:30 +0900945 if (result) {
946 piex::Error err = stream.get()->GetData(
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900947 image_data.thumbnail.offset,
948 image_data.thumbnail.length,
Jaesung Chung8409c062016-01-19 10:48:30 +0900949 (std::uint8_t *)result);
950 if (err == piex::Error::kOk) {
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900951 outThumbSize = image_data.thumbnail.length;
Jaesung Chung8409c062016-01-19 10:48:30 +0900952 } else {
953 free(result);
954 }
955 }
956 break;
957 }
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700958 }
959 }
960
961 return result;
962}
963
Mike Lockwood59c777a2010-08-02 10:37:41 -0400964MtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900965 MtpString& outFilePath,
966 int64_t& outFileLength,
967 MtpObjectFormat& outFormat) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400968 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400969 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400970 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400971 if (result != MTP_RESPONSE_OK) {
972 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400973 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400974 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400975
976 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Dan Albert66987492014-11-20 11:41:21 -0800977 outFilePath.setTo(reinterpret_cast<char16_t*>(str),
978 strlen16(reinterpret_cast<char16_t*>(str)));
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400979 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
980
981 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800982 outFileLength = longValues[0];
983 outFormat = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400984 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700985
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400986 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400987 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400988}
989
Mike Lockwood59c777a2010-08-02 10:37:41 -0400990MtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400991 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400992 MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
993
994 checkAndClearExceptionFromCallback(env, __FUNCTION__);
995 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400996}
997
998struct PropertyTableEntry {
999 MtpObjectProperty property;
1000 int type;
1001};
1002
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001003static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001004 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
1005 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
1006 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
1007 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
1008 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
1009 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
1010 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
1011 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
1012 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -04001013 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
1014 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
1015 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
1016 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
1017 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
1018 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
1019 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
1020 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
1021 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
1022 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
1023 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwood71827742015-01-23 10:50:08 -08001024 { MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_TYPE_UINT32 },
1025 { MTP_PROPERTY_BITRATE_TYPE, MTP_TYPE_UINT16 },
1026 { MTP_PROPERTY_AUDIO_BITRATE, MTP_TYPE_UINT32 },
1027 { MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_TYPE_UINT16 },
1028 { MTP_PROPERTY_SAMPLE_RATE, MTP_TYPE_UINT32 },
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001029};
1030
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001031static const PropertyTableEntry kDevicePropertyTable[] = {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001032 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
1033 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
1034 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
Mike Lockwood56c85242014-03-07 13:29:08 -08001035 { MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
Jerry Zhang13bb2f42016-12-14 15:39:29 -08001036 { MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE, MTP_TYPE_UINT32 },
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001037};
1038
1039bool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
1040 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
1041 const PropertyTableEntry* entry = kObjectPropertyTable;
1042 for (int i = 0; i < count; i++, entry++) {
1043 if (entry->property == property) {
1044 type = entry->type;
1045 return true;
1046 }
1047 }
1048 return false;
1049}
1050
1051bool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
1052 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
1053 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001054 for (int i = 0; i < count; i++, entry++) {
1055 if (entry->property == property) {
1056 type = entry->type;
1057 return true;
1058 }
1059 }
1060 return false;
1061}
1062
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001063MtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
1064 JNIEnv* env = AndroidRuntime::getJNIEnv();
1065 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
1066 (jint)handle);
1067 if (!array)
1068 return NULL;
1069 MtpObjectHandleList* list = new MtpObjectHandleList();
1070 jint* handles = env->GetIntArrayElements(array, 0);
1071 jsize length = env->GetArrayLength(array);
1072 for (int i = 0; i < length; i++)
1073 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001074 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -04001075 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001076
1077 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1078 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001079}
1080
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001081MtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001082 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001083 JNIEnv* env = AndroidRuntime::getJNIEnv();
1084 int count = references->size();
1085 jintArray array = env->NewIntArray(count);
1086 if (!array) {
Steve Block3762c312012-01-06 19:20:56 +00001087 ALOGE("out of memory in setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001088 return false;
1089 }
1090 jint* handles = env->GetIntArrayElements(array, 0);
1091 for (int i = 0; i < count; i++)
1092 handles[i] = (*references)[i];
1093 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001094 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001095 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -04001096 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001097
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001098 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1099 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001100}
1101
Mike Lockwood828d19d2010-08-10 15:20:35 -04001102MtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001103 MtpObjectFormat format) {
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001104 static const int channelEnum[] = {
1105 1, // mono
1106 2, // stereo
1107 3, // 2.1
1108 4, // 3
1109 5, // 3.1
1110 6, // 4
1111 7, // 4.1
1112 8, // 5
1113 9, // 5.1
1114 };
1115 static const int bitrateEnum[] = {
1116 1, // fixed rate
1117 2, // variable rate
1118 };
1119
Mike Lockwood828d19d2010-08-10 15:20:35 -04001120 MtpProperty* result = NULL;
1121 switch (property) {
1122 case MTP_PROPERTY_OBJECT_FORMAT:
Mike Lockwood9b5e9c42010-12-07 18:53:50 -08001123 // use format as default value
1124 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
1125 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001126 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001127 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001128 result = new MtpProperty(property, MTP_TYPE_UINT16);
1129 break;
1130 case MTP_PROPERTY_STORAGE_ID:
1131 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001132 case MTP_PROPERTY_DURATION:
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001133 case MTP_PROPERTY_AUDIO_WAVE_CODEC:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001134 result = new MtpProperty(property, MTP_TYPE_UINT32);
1135 break;
1136 case MTP_PROPERTY_OBJECT_SIZE:
1137 result = new MtpProperty(property, MTP_TYPE_UINT64);
1138 break;
1139 case MTP_PROPERTY_PERSISTENT_UID:
1140 result = new MtpProperty(property, MTP_TYPE_UINT128);
1141 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001142 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001143 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001144 case MTP_PROPERTY_ARTIST:
1145 case MTP_PROPERTY_ALBUM_NAME:
1146 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001147 case MTP_PROPERTY_GENRE:
1148 case MTP_PROPERTY_COMPOSER:
1149 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001150 result = new MtpProperty(property, MTP_TYPE_STR);
1151 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -05001152 case MTP_PROPERTY_DATE_MODIFIED:
1153 case MTP_PROPERTY_DATE_ADDED:
1154 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
1155 result = new MtpProperty(property, MTP_TYPE_STR);
1156 result->setFormDateTime();
1157 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -04001158 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -04001159 // We allow renaming files and folders
1160 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -04001161 break;
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001162 case MTP_PROPERTY_BITRATE_TYPE:
1163 result = new MtpProperty(property, MTP_TYPE_UINT16);
1164 result->setFormEnum(bitrateEnum, sizeof(bitrateEnum)/sizeof(bitrateEnum[0]));
1165 break;
1166 case MTP_PROPERTY_AUDIO_BITRATE:
1167 result = new MtpProperty(property, MTP_TYPE_UINT32);
1168 result->setFormRange(1, 1536000, 1);
1169 break;
1170 case MTP_PROPERTY_NUMBER_OF_CHANNELS:
1171 result = new MtpProperty(property, MTP_TYPE_UINT16);
1172 result->setFormEnum(channelEnum, sizeof(channelEnum)/sizeof(channelEnum[0]));
1173 break;
1174 case MTP_PROPERTY_SAMPLE_RATE:
1175 result = new MtpProperty(property, MTP_TYPE_UINT32);
1176 result->setFormRange(8000, 48000, 1);
1177 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001178 }
1179
1180 return result;
1181}
1182
1183MtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001184 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001185 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001186 bool writable = false;
1187
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001188 switch (property) {
1189 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
1190 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001191 writable = true;
1192 // fall through
Mike Lockwood56c85242014-03-07 13:29:08 -08001193 case MTP_DEVICE_PROPERTY_IMAGE_SIZE: {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001194 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001195
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001196 // get current value
Mike Lockwooda2a21282010-09-25 21:21:05 -04001197 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
1198 (jint)property, mLongBuffer, mStringBuffer);
1199 if (ret == MTP_RESPONSE_OK) {
1200 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
1201 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001202 // for read-only properties it is safe to assume current value is default value
1203 if (!writable)
1204 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001205 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
1206 } else {
Steve Block3762c312012-01-06 19:20:56 +00001207 ALOGE("unable to read device property, response: %04X", ret);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001208 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001209 break;
Mike Lockwood56c85242014-03-07 13:29:08 -08001210 }
1211 case MTP_DEVICE_PROPERTY_BATTERY_LEVEL:
1212 result = new MtpProperty(property, MTP_TYPE_UINT8);
1213 result->setFormRange(0, env->GetIntField(mDatabase, field_batteryScale), 1);
1214 result->mCurrentValue.u.u8 = (uint8_t)env->GetIntField(mDatabase, field_batteryLevel);
1215 break;
Jerry Zhang13bb2f42016-12-14 15:39:29 -08001216 case MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE:
1217 result = new MtpProperty(property, MTP_TYPE_UINT32);
1218 result->mCurrentValue.u.u32 = (uint32_t)env->GetIntField(mDatabase, field_deviceType);
1219 break;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001220 }
1221
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001222 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001223 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001224}
1225
Mike Lockwood2837eef2010-08-31 16:25:12 -04001226void MyMtpDatabase::sessionStarted() {
1227 JNIEnv* env = AndroidRuntime::getJNIEnv();
1228 env->CallVoidMethod(mDatabase, method_sessionStarted);
1229 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1230}
1231
1232void MyMtpDatabase::sessionEnded() {
1233 JNIEnv* env = AndroidRuntime::getJNIEnv();
1234 env->CallVoidMethod(mDatabase, method_sessionEnded);
1235 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1236}
1237
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001238// ----------------------------------------------------------------------------
1239
1240static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001241android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001242{
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001243 MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
Ashok Bhate2e59322013-12-17 19:04:19 +00001244 env->SetLongField(thiz, field_context, (jlong)database);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001245 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1246}
1247
1248static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001249android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001250{
Ashok Bhate2e59322013-12-17 19:04:19 +00001251 MyMtpDatabase* database = (MyMtpDatabase *)env->GetLongField(thiz, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001252 database->cleanup(env);
1253 delete database;
Ashok Bhate2e59322013-12-17 19:04:19 +00001254 env->SetLongField(thiz, field_context, 0);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001255 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1256}
1257
Mike Lockwood31599912010-11-15 13:43:30 -05001258static jstring
Mark Salyzynaeb75fc2014-03-20 12:09:01 -07001259android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001260{
Mike Lockwood31599912010-11-15 13:43:30 -05001261 char date[20];
1262 formatDateTime(seconds, date, sizeof(date));
1263 return env->NewStringUTF(date);
Mike Lockwood31599912010-11-15 13:43:30 -05001264}
1265
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001266// ----------------------------------------------------------------------------
1267
Daniel Micay76f6a862015-09-19 17:31:01 -04001268static const JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001269 {"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
1270 {"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001271};
1272
Daniel Micay76f6a862015-09-19 17:31:01 -04001273static const JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001274 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001275 (void *)android_mtp_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001276};
1277
Mike Lockwood0cd01362010-12-30 11:54:33 -05001278int register_android_mtp_MtpDatabase(JNIEnv *env)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001279{
1280 jclass clazz;
1281
Mike Lockwood0cd01362010-12-30 11:54:33 -05001282 clazz = env->FindClass("android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001283 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001284 ALOGE("Can't find android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001285 return -1;
1286 }
Mike Lockwoodd815f792010-07-12 08:49:01 -04001287 method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1288 if (method_beginSendObject == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001289 ALOGE("Can't find beginSendObject");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001290 return -1;
1291 }
Mike Lockwood7a0bd172011-01-18 11:06:19 -08001292 method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
Mike Lockwoodd815f792010-07-12 08:49:01 -04001293 if (method_endSendObject == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001294 ALOGE("Can't find endSendObject");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001295 return -1;
1296 }
1297 method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1298 if (method_getObjectList == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001299 ALOGE("Can't find getObjectList");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001300 return -1;
1301 }
Mike Lockwood7a047c82010-08-02 10:52:20 -04001302 method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
1303 if (method_getNumObjects == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001304 ALOGE("Can't find getNumObjects");
Mike Lockwood7a047c82010-08-02 10:52:20 -04001305 return -1;
1306 }
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001307 method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
1308 if (method_getSupportedPlaybackFormats == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001309 ALOGE("Can't find getSupportedPlaybackFormats");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001310 return -1;
1311 }
1312 method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
1313 if (method_getSupportedCaptureFormats == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001314 ALOGE("Can't find getSupportedCaptureFormats");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001315 return -1;
1316 }
1317 method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
1318 if (method_getSupportedObjectProperties == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001319 ALOGE("Can't find getSupportedObjectProperties");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001320 return -1;
1321 }
1322 method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
1323 if (method_getSupportedDeviceProperties == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001324 ALOGE("Can't find getSupportedDeviceProperties");
Mike Lockwood4b322ce2010-08-10 07:37:50 -04001325 return -1;
1326 }
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001327 method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
1328 if (method_setObjectProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001329 ALOGE("Can't find setObjectProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001330 return -1;
1331 }
1332 method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
1333 if (method_getDeviceProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001334 ALOGE("Can't find getDeviceProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001335 return -1;
1336 }
1337 method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
1338 if (method_setDeviceProperty == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001339 ALOGE("Can't find setDeviceProperty");
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001340 return -1;
1341 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001342 method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001343 "(IIIII)Landroid/mtp/MtpPropertyList;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001344 if (method_getObjectPropertyList == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001345 ALOGE("Can't find getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001346 return -1;
1347 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001348 method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1349 if (method_getObjectInfo == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001350 ALOGE("Can't find getObjectInfo");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001351 return -1;
1352 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001353 method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001354 if (method_getObjectFilePath == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001355 ALOGE("Can't find getObjectFilePath");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001356 return -1;
1357 }
Mike Lockwood59c777a2010-08-02 10:37:41 -04001358 method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001359 if (method_deleteFile == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001360 ALOGE("Can't find deleteFile");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001361 return -1;
1362 }
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001363 method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
1364 if (method_getObjectReferences == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001365 ALOGE("Can't find getObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001366 return -1;
1367 }
1368 method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
1369 if (method_setObjectReferences == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001370 ALOGE("Can't find setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001371 return -1;
1372 }
Mike Lockwood2837eef2010-08-31 16:25:12 -04001373 method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
1374 if (method_sessionStarted == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001375 ALOGE("Can't find sessionStarted");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001376 return -1;
1377 }
1378 method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
1379 if (method_sessionEnded == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001380 ALOGE("Can't find sessionEnded");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001381 return -1;
1382 }
1383
Ashok Bhate2e59322013-12-17 19:04:19 +00001384 field_context = env->GetFieldID(clazz, "mNativeContext", "J");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001385 if (field_context == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001386 ALOGE("Can't find MtpDatabase.mNativeContext");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001387 return -1;
1388 }
Mike Lockwood56c85242014-03-07 13:29:08 -08001389 field_batteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");
1390 if (field_batteryLevel == NULL) {
1391 ALOGE("Can't find MtpDatabase.mBatteryLevel");
1392 return -1;
1393 }
1394 field_batteryScale = env->GetFieldID(clazz, "mBatteryScale", "I");
1395 if (field_batteryScale == NULL) {
1396 ALOGE("Can't find MtpDatabase.mBatteryScale");
1397 return -1;
1398 }
Jerry Zhang13bb2f42016-12-14 15:39:29 -08001399 field_deviceType = env->GetFieldID(clazz, "mDeviceType", "I");
1400 if (field_deviceType == NULL) {
1401 ALOGE("Can't find MtpDatabase.mDeviceType");
1402 return -1;
1403 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001404
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001405 // now set up fields for MtpPropertyList class
Mike Lockwood0cd01362010-12-30 11:54:33 -05001406 clazz = env->FindClass("android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001407 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001408 ALOGE("Can't find android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001409 return -1;
1410 }
1411 field_mCount = env->GetFieldID(clazz, "mCount", "I");
1412 if (field_mCount == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001413 ALOGE("Can't find MtpPropertyList.mCount");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001414 return -1;
1415 }
1416 field_mResult = env->GetFieldID(clazz, "mResult", "I");
1417 if (field_mResult == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001418 ALOGE("Can't find MtpPropertyList.mResult");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001419 return -1;
1420 }
1421 field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1422 if (field_mObjectHandles == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001423 ALOGE("Can't find MtpPropertyList.mObjectHandles");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001424 return -1;
1425 }
1426 field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1427 if (field_mPropertyCodes == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001428 ALOGE("Can't find MtpPropertyList.mPropertyCodes");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001429 return -1;
1430 }
1431 field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1432 if (field_mDataTypes == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001433 ALOGE("Can't find MtpPropertyList.mDataTypes");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001434 return -1;
1435 }
1436 field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1437 if (field_mLongValues == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001438 ALOGE("Can't find MtpPropertyList.mLongValues");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001439 return -1;
1440 }
1441 field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1442 if (field_mStringValues == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001443 ALOGE("Can't find MtpPropertyList.mStringValues");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001444 return -1;
1445 }
1446
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001447 if (AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001448 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001449 return -1;
1450
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001451 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001452 "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001453}