blob: 23ef84f6ad90e52e7b7a769b1eb769189fef6ea0 [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"
Jerry Zhangf9c5c252017-08-16 18:07:51 -070022#include "IMtpDatabase.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040023#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;
Jerry Zhangf9c5c252017-08-16 18:07:51 -070058static jmethodID method_rescanFile;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040059static jmethodID method_getObjectList;
Mike Lockwood7a047c82010-08-02 10:52:20 -040060static jmethodID method_getNumObjects;
Mike Lockwood4b322ce2010-08-10 07:37:50 -040061static jmethodID method_getSupportedPlaybackFormats;
62static jmethodID method_getSupportedCaptureFormats;
63static jmethodID method_getSupportedObjectProperties;
64static jmethodID method_getSupportedDeviceProperties;
Mike Lockwood828d19d2010-08-10 15:20:35 -040065static jmethodID method_setObjectProperty;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -040066static jmethodID method_getDeviceProperty;
67static jmethodID method_setDeviceProperty;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040068static jmethodID method_getObjectPropertyList;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040069static jmethodID method_getObjectInfo;
70static jmethodID method_getObjectFilePath;
Jerry Zhangf9c5c252017-08-16 18:07:51 -070071static jmethodID method_beginDeleteObject;
72static jmethodID method_endDeleteObject;
73static jmethodID method_beginMoveObject;
74static jmethodID method_endMoveObject;
75static jmethodID method_beginCopyObject;
76static jmethodID method_endCopyObject;
Mike Lockwood9a2046f2010-08-03 15:30:09 -040077static jmethodID method_getObjectReferences;
78static jmethodID method_setObjectReferences;
Mike Lockwood2837eef2010-08-31 16:25:12 -040079
Mike Lockwoodd21eac92010-07-03 00:44:05 -040080static jfieldID field_context;
81
Jerry Zhangf9c5c252017-08-16 18:07:51 -070082// MtpPropertyList methods
83static jmethodID method_getCode;
84static jmethodID method_getCount;
85static jmethodID method_getObjectHandles;
86static jmethodID method_getPropertyCodes;
87static jmethodID method_getDataTypes;
88static jmethodID method_getLongValues;
89static jmethodID method_getStringValues;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040090
91
Jerry Zhangf9c5c252017-08-16 18:07:51 -070092IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
93 return (IMtpDatabase *)env->GetLongField(database, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -040094}
95
96// ----------------------------------------------------------------------------
97
Jerry Zhangf9c5c252017-08-16 18:07:51 -070098class MtpDatabase : public IMtpDatabase {
Mike Lockwoodd21eac92010-07-03 00:44:05 -040099private:
100 jobject mDatabase;
101 jintArray mIntBuffer;
102 jlongArray mLongBuffer;
103 jcharArray mStringBuffer;
104
105public:
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700106 MtpDatabase(JNIEnv *env, jobject client);
107 virtual ~MtpDatabase();
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400108 void cleanup(JNIEnv *env);
109
Mike Lockwoodd815f792010-07-12 08:49:01 -0400110 virtual MtpObjectHandle beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400111 MtpObjectFormat format,
112 MtpObjectHandle parent,
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700113 MtpStorageID storage);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400114
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700115 virtual void endSendObject(MtpObjectHandle handle, bool succeeded);
116
117 virtual void rescanFile(const char* path,
Mike Lockwoodd815f792010-07-12 08:49:01 -0400118 MtpObjectHandle handle,
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700119 MtpObjectFormat format);
kyle_tsob4aa69f2017-11-22 20:11:27 +0800120
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);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700166 virtual MtpResponseCode beginDeleteObject(MtpObjectHandle handle);
167 virtual void endDeleteObject(MtpObjectHandle handle, bool succeeded);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400168
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400169 bool getObjectPropertyInfo(MtpObjectProperty property, int& type);
170 bool getDevicePropertyInfo(MtpDeviceProperty property, int& type);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400171
172 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
173
174 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
175 MtpObjectHandleList* references);
Mike Lockwood828d19d2010-08-10 15:20:35 -0400176
177 virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
178 MtpObjectFormat format);
179
180 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400181
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700182 virtual MtpResponseCode beginMoveObject(MtpObjectHandle handle, MtpObjectHandle newParent,
183 MtpStorageID newStorage);
Jerry Zhang952558d2017-09-26 17:49:52 -0700184
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700185 virtual void endMoveObject(MtpObjectHandle oldParent, MtpObjectHandle newParent,
186 MtpStorageID oldStorage, MtpStorageID newStorage,
187 MtpObjectHandle handle, bool succeeded);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400188
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700189 virtual MtpResponseCode beginCopyObject(MtpObjectHandle handle, MtpObjectHandle newParent,
190 MtpStorageID newStorage);
191 virtual void endCopyObject(MtpObjectHandle handle, bool succeeded);
192
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400193};
194
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400195// ----------------------------------------------------------------------------
196
197static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
198 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +0000199 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400200 LOGE_EX(env);
201 env->ExceptionClear();
202 }
203}
204
205// ----------------------------------------------------------------------------
206
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700207MtpDatabase::MtpDatabase(JNIEnv *env, jobject client)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400208 : mDatabase(env->NewGlobalRef(client)),
209 mIntBuffer(NULL),
210 mLongBuffer(NULL),
211 mStringBuffer(NULL)
212{
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400213 // create buffers for out arguments
214 // we don't need to be thread-safe so this is OK
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700215 jintArray intArray = env->NewIntArray(3);
216 if (!intArray) {
217 return; // Already threw.
218 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400219 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700220 jlongArray longArray = env->NewLongArray(2);
221 if (!longArray) {
222 return; // Already threw.
223 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400224 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
Mike Lockwood63ffd782014-09-24 10:55:19 -0700225 // Needs to be long enough to hold a file path for getObjectFilePath()
226 jcharArray charArray = env->NewCharArray(PATH_MAX + 1);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700227 if (!charArray) {
228 return; // Already threw.
229 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400230 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400231}
232
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700233void MtpDatabase::cleanup(JNIEnv *env) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400234 env->DeleteGlobalRef(mDatabase);
235 env->DeleteGlobalRef(mIntBuffer);
236 env->DeleteGlobalRef(mLongBuffer);
237 env->DeleteGlobalRef(mStringBuffer);
238}
239
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700240MtpDatabase::~MtpDatabase() {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400241}
242
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700243MtpObjectHandle MtpDatabase::beginSendObject(const char* path,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900244 MtpObjectFormat format,
245 MtpObjectHandle parent,
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700246 MtpStorageID storage) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400247 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400248 jstring pathStr = env->NewStringUTF(path);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400249 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700250 pathStr, (jint)format, (jint)parent, (jint)storage);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400251
Mike Lockwood88394712010-09-27 10:01:00 -0400252 if (pathStr)
253 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400254 checkAndClearExceptionFromCallback(env, __FUNCTION__);
255 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400256}
257
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700258void MtpDatabase::endSendObject(MtpObjectHandle handle, bool succeeded) {
259 JNIEnv* env = AndroidRuntime::getJNIEnv();
260 env->CallVoidMethod(mDatabase, method_endSendObject, (jint)handle, (jboolean)succeeded);
261
262 checkAndClearExceptionFromCallback(env, __FUNCTION__);
263}
264
265void MtpDatabase::rescanFile(const char* path, MtpObjectHandle handle,
266 MtpObjectFormat format) {
Mike Lockwoodd815f792010-07-12 08:49:01 -0400267 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400268 jstring pathStr = env->NewStringUTF(path);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700269 env->CallVoidMethod(mDatabase, method_rescanFile, pathStr,
270 (jint)handle, (jint)format);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400271
Mike Lockwood88394712010-09-27 10:01:00 -0400272 if (pathStr)
273 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400274 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400275}
276
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700277MtpObjectHandleList* MtpDatabase::getObjectList(MtpStorageID storageID,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900278 MtpObjectFormat format,
279 MtpObjectHandle parent) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400280 JNIEnv* env = AndroidRuntime::getJNIEnv();
281 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
282 (jint)storageID, (jint)format, (jint)parent);
283 if (!array)
284 return NULL;
285 MtpObjectHandleList* list = new MtpObjectHandleList();
286 jint* handles = env->GetIntArrayElements(array, 0);
287 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400288 for (int i = 0; i < length; i++)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400289 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400290 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400291 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400292
293 checkAndClearExceptionFromCallback(env, __FUNCTION__);
294 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400295}
296
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700297int MtpDatabase::getNumObjects(MtpStorageID storageID,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900298 MtpObjectFormat format,
299 MtpObjectHandle parent) {
Mike Lockwood7a047c82010-08-02 10:52:20 -0400300 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400301 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400302 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400303
304 checkAndClearExceptionFromCallback(env, __FUNCTION__);
305 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400306}
307
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700308MtpObjectFormatList* MtpDatabase::getSupportedPlaybackFormats() {
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400309 JNIEnv* env = AndroidRuntime::getJNIEnv();
310 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
311 method_getSupportedPlaybackFormats);
312 if (!array)
313 return NULL;
314 MtpObjectFormatList* list = new MtpObjectFormatList();
315 jint* formats = env->GetIntArrayElements(array, 0);
316 jsize length = env->GetArrayLength(array);
317 for (int i = 0; i < length; i++)
318 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400319 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400320 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400321
322 checkAndClearExceptionFromCallback(env, __FUNCTION__);
323 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400324}
325
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700326MtpObjectFormatList* MtpDatabase::getSupportedCaptureFormats() {
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400327 JNIEnv* env = AndroidRuntime::getJNIEnv();
328 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
329 method_getSupportedCaptureFormats);
330 if (!array)
331 return NULL;
332 MtpObjectFormatList* list = new MtpObjectFormatList();
333 jint* formats = env->GetIntArrayElements(array, 0);
334 jsize length = env->GetArrayLength(array);
335 for (int i = 0; i < length; i++)
336 list->push(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400337 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400338 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400339
340 checkAndClearExceptionFromCallback(env, __FUNCTION__);
341 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400342}
343
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700344MtpObjectPropertyList* MtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400345 JNIEnv* env = AndroidRuntime::getJNIEnv();
346 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
347 method_getSupportedObjectProperties, (jint)format);
348 if (!array)
349 return NULL;
350 MtpObjectPropertyList* list = new MtpObjectPropertyList();
351 jint* properties = env->GetIntArrayElements(array, 0);
352 jsize length = env->GetArrayLength(array);
353 for (int i = 0; i < length; i++)
354 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400355 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400356 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400357
358 checkAndClearExceptionFromCallback(env, __FUNCTION__);
359 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400360}
361
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700362MtpDevicePropertyList* MtpDatabase::getSupportedDeviceProperties() {
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400363 JNIEnv* env = AndroidRuntime::getJNIEnv();
364 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
365 method_getSupportedDeviceProperties);
366 if (!array)
367 return NULL;
368 MtpDevicePropertyList* list = new MtpDevicePropertyList();
369 jint* properties = env->GetIntArrayElements(array, 0);
370 jsize length = env->GetArrayLength(array);
371 for (int i = 0; i < length; i++)
372 list->push(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400373 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400374 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400375
376 checkAndClearExceptionFromCallback(env, __FUNCTION__);
377 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400378}
379
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700380MtpResponseCode MtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900381 MtpObjectProperty property,
382 MtpDataPacket& packet) {
383 static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
384 "Casting MtpObjectHandle to jint loses a value");
385 static_assert(sizeof(jint) >= sizeof(MtpObjectProperty),
386 "Casting MtpObjectProperty to jint loses a value");
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400387 JNIEnv* env = AndroidRuntime::getJNIEnv();
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900388 jobject list = env->CallObjectMethod(
389 mDatabase,
390 method_getObjectPropertyList,
391 static_cast<jint>(handle),
392 0,
393 static_cast<jint>(property),
394 0,
395 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700396 MtpResponseCode result = env->CallIntMethod(list, method_getCode);
397 jint count = env->CallIntMethod(list, method_getCount);
398 if (count != 1)
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400399 result = MTP_RESPONSE_GENERAL_ERROR;
400
401 if (result == MTP_RESPONSE_OK) {
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700402 jintArray objectHandlesArray = (jintArray)env->CallObjectMethod(list, method_getObjectHandles);
403 jintArray propertyCodesArray = (jintArray)env->CallObjectMethod(list, method_getPropertyCodes);
404 jintArray dataTypesArray = (jintArray)env->CallObjectMethod(list, method_getDataTypes);
405 jlongArray longValuesArray = (jlongArray)env->CallObjectMethod(list, method_getLongValues);
406 jobjectArray stringValuesArray = (jobjectArray)env->CallObjectMethod(list, method_getStringValues);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400407
408 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
409 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
410 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700411 jlong* longValues = env->GetLongArrayElements(longValuesArray, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400412
413 int type = dataTypes[0];
414 jlong longValue = (longValues ? longValues[0] : 0);
415
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400416 switch (type) {
417 case MTP_TYPE_INT8:
418 packet.putInt8(longValue);
419 break;
420 case MTP_TYPE_UINT8:
421 packet.putUInt8(longValue);
422 break;
423 case MTP_TYPE_INT16:
424 packet.putInt16(longValue);
425 break;
426 case MTP_TYPE_UINT16:
427 packet.putUInt16(longValue);
428 break;
429 case MTP_TYPE_INT32:
430 packet.putInt32(longValue);
431 break;
432 case MTP_TYPE_UINT32:
433 packet.putUInt32(longValue);
434 break;
435 case MTP_TYPE_INT64:
436 packet.putInt64(longValue);
437 break;
438 case MTP_TYPE_UINT64:
439 packet.putUInt64(longValue);
440 break;
441 case MTP_TYPE_INT128:
442 packet.putInt128(longValue);
443 break;
444 case MTP_TYPE_UINT128:
Wanwu Peng8937f1a2016-03-02 18:16:46 +0800445 packet.putUInt128(longValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400446 break;
447 case MTP_TYPE_STR:
448 {
449 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200450 const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400451 if (stringValue) {
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400452 packet.putString(str);
453 env->ReleaseStringUTFChars(stringValue, str);
454 } else {
455 packet.putEmptyString();
456 }
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200457 env->DeleteLocalRef(stringValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400458 break;
459 }
460 default:
Steve Block3762c312012-01-06 19:20:56 +0000461 ALOGE("unsupported type in getObjectPropertyValue\n");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400462 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
463 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400464 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
465 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
466 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700467 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400468
469 env->DeleteLocalRef(objectHandlesArray);
470 env->DeleteLocalRef(propertyCodesArray);
471 env->DeleteLocalRef(dataTypesArray);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700472 env->DeleteLocalRef(longValuesArray);
473 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400474 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400475
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400476 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400477 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400478 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400479}
480
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800481static bool readLongValue(int type, MtpDataPacket& packet, jlong& longValue) {
482 switch (type) {
483 case MTP_TYPE_INT8: {
484 int8_t temp;
485 if (!packet.getInt8(temp)) return false;
486 longValue = temp;
487 break;
488 }
489 case MTP_TYPE_UINT8: {
490 uint8_t temp;
491 if (!packet.getUInt8(temp)) return false;
492 longValue = temp;
493 break;
494 }
495 case MTP_TYPE_INT16: {
496 int16_t temp;
497 if (!packet.getInt16(temp)) return false;
498 longValue = temp;
499 break;
500 }
501 case MTP_TYPE_UINT16: {
502 uint16_t temp;
503 if (!packet.getUInt16(temp)) return false;
504 longValue = temp;
505 break;
506 }
507 case MTP_TYPE_INT32: {
508 int32_t temp;
509 if (!packet.getInt32(temp)) return false;
510 longValue = temp;
511 break;
512 }
513 case MTP_TYPE_UINT32: {
514 uint32_t temp;
515 if (!packet.getUInt32(temp)) return false;
516 longValue = temp;
517 break;
518 }
519 case MTP_TYPE_INT64: {
520 int64_t temp;
521 if (!packet.getInt64(temp)) return false;
522 longValue = temp;
523 break;
524 }
525 case MTP_TYPE_UINT64: {
526 uint64_t temp;
527 if (!packet.getUInt64(temp)) return false;
528 longValue = temp;
529 break;
530 }
531 default:
532 ALOGE("unsupported type in readLongValue");
533 return false;
534 }
535 return true;
536}
537
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700538MtpResponseCode MtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900539 MtpObjectProperty property,
540 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400541 int type;
542
543 if (!getObjectPropertyInfo(property, type))
544 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
545
546 JNIEnv* env = AndroidRuntime::getJNIEnv();
547 jlong longValue = 0;
548 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800549 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400550
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800551 if (type == MTP_TYPE_STR) {
552 MtpStringBuffer buffer;
553 if (!packet.getString(buffer)) goto fail;
554 stringValue = env->NewStringUTF((const char *)buffer);
555 } else {
556 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400557 }
558
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800559 result = env->CallIntMethod(mDatabase, method_setObjectProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400560 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400561 if (stringValue)
562 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400563
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800564fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400565 checkAndClearExceptionFromCallback(env, __FUNCTION__);
566 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400567}
568
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700569MtpResponseCode MtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900570 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400571 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700572 int type;
Mike Lockwood56c85242014-03-07 13:29:08 -0800573
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700574 if (!getDevicePropertyInfo(property, type))
575 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
Mike Lockwood56c85242014-03-07 13:29:08 -0800576
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700577 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
578 (jint)property, mLongBuffer, mStringBuffer);
579 if (result != MTP_RESPONSE_OK) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400580 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700581 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400582 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700583
584 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
585 jlong longValue = longValues[0];
586 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
587
588 switch (type) {
589 case MTP_TYPE_INT8:
590 packet.putInt8(longValue);
591 break;
592 case MTP_TYPE_UINT8:
593 packet.putUInt8(longValue);
594 break;
595 case MTP_TYPE_INT16:
596 packet.putInt16(longValue);
597 break;
598 case MTP_TYPE_UINT16:
599 packet.putUInt16(longValue);
600 break;
601 case MTP_TYPE_INT32:
602 packet.putInt32(longValue);
603 break;
604 case MTP_TYPE_UINT32:
605 packet.putUInt32(longValue);
606 break;
607 case MTP_TYPE_INT64:
608 packet.putInt64(longValue);
609 break;
610 case MTP_TYPE_UINT64:
611 packet.putUInt64(longValue);
612 break;
613 case MTP_TYPE_INT128:
614 packet.putInt128(longValue);
615 break;
616 case MTP_TYPE_UINT128:
617 packet.putInt128(longValue);
618 break;
619 case MTP_TYPE_STR:
620 {
621 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
622 packet.putString(str);
623 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
624 break;
625 }
626 default:
627 ALOGE("unsupported type in getDevicePropertyValue\n");
628 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
629 }
630
631 checkAndClearExceptionFromCallback(env, __FUNCTION__);
632 return MTP_RESPONSE_OK;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400633}
634
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700635MtpResponseCode MtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900636 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400637 int type;
638
639 if (!getDevicePropertyInfo(property, type))
640 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
641
642 JNIEnv* env = AndroidRuntime::getJNIEnv();
643 jlong longValue = 0;
644 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800645 MtpResponseCode result = MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400646
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800647 if (type == MTP_TYPE_STR) {
648 MtpStringBuffer buffer;
649 if (!packet.getString(buffer)) goto fail;
650 stringValue = env->NewStringUTF((const char *)buffer);
651 } else {
652 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400653 }
654
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800655 result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400656 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400657 if (stringValue)
658 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400659
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800660fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400661 checkAndClearExceptionFromCallback(env, __FUNCTION__);
662 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400663}
664
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700665MtpResponseCode MtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
Mike Lockwood828d19d2010-08-10 15:20:35 -0400666 return -1;
667}
668
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700669MtpResponseCode MtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900670 uint32_t format, uint32_t property,
671 int groupCode, int depth,
672 MtpDataPacket& packet) {
673 static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
674 "Casting MtpObjectHandle to jint loses a value");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400675 JNIEnv* env = AndroidRuntime::getJNIEnv();
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900676 jobject list = env->CallObjectMethod(
677 mDatabase,
678 method_getObjectPropertyList,
679 static_cast<jint>(handle),
680 static_cast<jint>(format),
681 static_cast<jint>(property),
682 static_cast<jint>(groupCode),
683 static_cast<jint>(depth));
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500684 checkAndClearExceptionFromCallback(env, __FUNCTION__);
685 if (!list)
686 return MTP_RESPONSE_GENERAL_ERROR;
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700687 int count = env->CallIntMethod(list, method_getCount);
688 MtpResponseCode result = env->CallIntMethod(list, method_getCode);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400689
690 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400691 if (count > 0) {
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700692 jintArray objectHandlesArray = (jintArray)env->CallObjectMethod(list, method_getObjectHandles);
693 jintArray propertyCodesArray = (jintArray)env->CallObjectMethod(list, method_getPropertyCodes);
694 jintArray dataTypesArray = (jintArray)env->CallObjectMethod(list, method_getDataTypes);
695 jlongArray longValuesArray = (jlongArray)env->CallObjectMethod(list, method_getLongValues);
696 jobjectArray stringValuesArray = (jobjectArray)env->CallObjectMethod(list, method_getStringValues);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400697
698 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
699 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
700 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
701 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
702
703 for (int i = 0; i < count; i++) {
704 packet.putUInt32(objectHandles[i]);
705 packet.putUInt16(propertyCodes[i]);
706 int type = dataTypes[i];
707 packet.putUInt16(type);
708
709 switch (type) {
710 case MTP_TYPE_INT8:
711 packet.putInt8(longValues[i]);
712 break;
713 case MTP_TYPE_UINT8:
714 packet.putUInt8(longValues[i]);
715 break;
716 case MTP_TYPE_INT16:
717 packet.putInt16(longValues[i]);
718 break;
719 case MTP_TYPE_UINT16:
720 packet.putUInt16(longValues[i]);
721 break;
722 case MTP_TYPE_INT32:
723 packet.putInt32(longValues[i]);
724 break;
725 case MTP_TYPE_UINT32:
726 packet.putUInt32(longValues[i]);
727 break;
728 case MTP_TYPE_INT64:
729 packet.putInt64(longValues[i]);
730 break;
731 case MTP_TYPE_UINT64:
732 packet.putUInt64(longValues[i]);
733 break;
734 case MTP_TYPE_INT128:
735 packet.putInt128(longValues[i]);
736 break;
737 case MTP_TYPE_UINT128:
738 packet.putUInt128(longValues[i]);
739 break;
740 case MTP_TYPE_STR: {
741 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
Mike Lockwood2711e492010-12-11 11:24:37 -0800742 const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400743 if (valueStr) {
744 packet.putString(valueStr);
745 env->ReleaseStringUTFChars(value, valueStr);
746 } else {
747 packet.putEmptyString();
748 }
749 env->DeleteLocalRef(value);
750 break;
751 }
752 default:
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700753 ALOGE("bad or unsupported data type in MtpDatabase::getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400754 break;
755 }
756 }
757
758 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
759 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
760 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700761 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400762
763 env->DeleteLocalRef(objectHandlesArray);
764 env->DeleteLocalRef(propertyCodesArray);
765 env->DeleteLocalRef(dataTypesArray);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700766 env->DeleteLocalRef(longValuesArray);
767 env->DeleteLocalRef(stringValuesArray);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400768 }
769
770 env->DeleteLocalRef(list);
771 checkAndClearExceptionFromCallback(env, __FUNCTION__);
772 return result;
773}
774
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800775static void foreachentry(ExifEntry *entry, void* /* user */) {
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800776 char buf[1024];
777 ALOGI("entry %x, format %d, size %d: %s",
778 entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
779}
780
781static void foreachcontent(ExifContent *content, void *user) {
782 ALOGI("content %d", exif_content_get_ifd(content));
783 exif_content_foreach_entry(content, foreachentry, user);
784}
785
786static long getLongFromExifEntry(ExifEntry *e) {
787 ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
788 return exif_get_long(e->data, o);
789}
790
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700791MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900792 MtpObjectInfo& info) {
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700793 MtpString path;
794 int64_t length;
795 MtpObjectFormat format;
796
797 MtpResponseCode result = getObjectFilePath(handle, path, length, format);
798 if (result != MTP_RESPONSE_OK) {
799 return result;
800 }
801 info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400802
803 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700804 if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
805 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400806 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700807 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400808
809 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700810 info.mStorageID = intValues[0];
811 info.mFormat = intValues[1];
812 info.mParent = intValues[2];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400813 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
814
815 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood1341f1e2013-04-01 10:52:47 -0700816 info.mDateCreated = longValues[0];
817 info.mDateModified = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400818 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
819
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800820 if ((false)) {
821 info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
822 MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
823 MTP_ASSOCIATION_TYPE_UNDEFINED);
824 }
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700825 info.mAssociationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400826
827 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Dan Albert66987492014-11-20 11:41:21 -0800828 MtpString temp(reinterpret_cast<char16_t*>(str));
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700829 info.mName = strdup((const char *)temp);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400830 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
831
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700832 // read EXIF data for thumbnail information
Jaesung Chung8409c062016-01-19 10:48:30 +0900833 switch (info.mFormat) {
834 case MTP_FORMAT_EXIF_JPEG:
Chong Zhang6e18cce2017-08-16 11:57:02 -0700835 case MTP_FORMAT_HEIF:
Jaesung Chung8409c062016-01-19 10:48:30 +0900836 case MTP_FORMAT_JFIF: {
837 ExifData *exifdata = exif_data_new_from_file(path);
838 if (exifdata) {
839 if ((false)) {
840 exif_data_foreach_content(exifdata, foreachcontent, NULL);
841 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800842
Jaesung Chung8409c062016-01-19 10:48:30 +0900843 ExifEntry *w = exif_content_get_entry(
844 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
845 ExifEntry *h = exif_content_get_entry(
846 exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
847 info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
848 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
849 info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
850 info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
851 exif_data_unref(exifdata);
852 }
853 break;
854 }
855
856 // Except DNG, all supported RAW image formats are not defined in PTP 1.2 specification.
857 // Most of RAW image formats are based on TIFF or TIFF/EP. To render Fuji's RAF format,
858 // it checks MTP_FORMAT_DEFINED case since it's designed as a custom format.
859 case MTP_FORMAT_DNG:
860 case MTP_FORMAT_TIFF:
861 case MTP_FORMAT_TIFF_EP:
862 case MTP_FORMAT_DEFINED: {
863 std::unique_ptr<FileStream> stream(new FileStream(path));
864 piex::PreviewImageData image_data;
865 if (!GetExifFromRawImage(stream.get(), path, image_data)) {
866 // Couldn't parse EXIF data from a image file via piex.
867 break;
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800868 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800869
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900870 info.mThumbCompressedSize = image_data.thumbnail.length;
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800871 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
Jaesung Chung8409c062016-01-19 10:48:30 +0900872 info.mImagePixWidth = image_data.full_width;
873 info.mImagePixHeight = image_data.full_height;
874
875 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700876 }
877 }
878
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400879 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400880 return MTP_RESPONSE_OK;
881}
882
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700883void* MtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700884 MtpString path;
885 int64_t length;
886 MtpObjectFormat format;
887 void* result = NULL;
888 outThumbSize = 0;
889
Jaesung Chung8409c062016-01-19 10:48:30 +0900890 if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
891 switch (format) {
892 case MTP_FORMAT_EXIF_JPEG:
Chong Zhang6e18cce2017-08-16 11:57:02 -0700893 case MTP_FORMAT_HEIF:
Jaesung Chung8409c062016-01-19 10:48:30 +0900894 case MTP_FORMAT_JFIF: {
895 ExifData *exifdata = exif_data_new_from_file(path);
896 if (exifdata) {
897 if (exifdata->data) {
898 result = malloc(exifdata->size);
899 if (result) {
900 memcpy(result, exifdata->data, exifdata->size);
901 outThumbSize = exifdata->size;
902 }
903 }
904 exif_data_unref(exifdata);
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800905 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900906 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700907 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900908
909 // See the above comment on getObjectInfo() method.
910 case MTP_FORMAT_DNG:
911 case MTP_FORMAT_TIFF:
912 case MTP_FORMAT_TIFF_EP:
913 case MTP_FORMAT_DEFINED: {
914 std::unique_ptr<FileStream> stream(new FileStream(path));
915 piex::PreviewImageData image_data;
916 if (!GetExifFromRawImage(stream.get(), path, image_data)) {
917 // Couldn't parse EXIF data from a image file via piex.
918 break;
919 }
920
Jaesung Chung742e89f2016-04-13 14:13:10 +0900921 if (image_data.thumbnail.length == 0
Insun Kang82c2ce12016-04-19 17:56:10 +0900922 || image_data.thumbnail.format != ::piex::Image::kJpegCompressed) {
Jaesung Chung742e89f2016-04-13 14:13:10 +0900923 // No thumbnail or non jpeg thumbnail.
Jaesung Chung8409c062016-01-19 10:48:30 +0900924 break;
925 }
926
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900927 result = malloc(image_data.thumbnail.length);
Jaesung Chung8409c062016-01-19 10:48:30 +0900928 if (result) {
929 piex::Error err = stream.get()->GetData(
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900930 image_data.thumbnail.offset,
931 image_data.thumbnail.length,
Jaesung Chung8409c062016-01-19 10:48:30 +0900932 (std::uint8_t *)result);
933 if (err == piex::Error::kOk) {
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900934 outThumbSize = image_data.thumbnail.length;
Jaesung Chung8409c062016-01-19 10:48:30 +0900935 } else {
936 free(result);
Chong Zhange6b98532017-10-24 16:07:18 -0700937 result = NULL;
Jaesung Chung8409c062016-01-19 10:48:30 +0900938 }
939 }
940 break;
941 }
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700942 }
943 }
944
945 return result;
946}
947
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700948MtpResponseCode MtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900949 MtpString& outFilePath,
950 int64_t& outFileLength,
951 MtpObjectFormat& outFormat) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400952 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400953 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400954 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400955 if (result != MTP_RESPONSE_OK) {
956 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400957 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400958 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400959
960 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Dan Albert66987492014-11-20 11:41:21 -0800961 outFilePath.setTo(reinterpret_cast<char16_t*>(str),
962 strlen16(reinterpret_cast<char16_t*>(str)));
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400963 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
964
965 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800966 outFileLength = longValues[0];
967 outFormat = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400968 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700969
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400970 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400971 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400972}
973
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700974MtpResponseCode MtpDatabase::beginDeleteObject(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400975 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700976 MtpResponseCode result = env->CallIntMethod(mDatabase, method_beginDeleteObject, (jint)handle);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400977
978 checkAndClearExceptionFromCallback(env, __FUNCTION__);
979 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400980}
981
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700982void MtpDatabase::endDeleteObject(MtpObjectHandle handle, bool succeeded) {
Jerry Zhang952558d2017-09-26 17:49:52 -0700983 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700984 env->CallVoidMethod(mDatabase, method_endDeleteObject, (jint)handle, (jboolean) succeeded);
Jerry Zhang952558d2017-09-26 17:49:52 -0700985
986 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700987}
988
989MtpResponseCode MtpDatabase::beginMoveObject(MtpObjectHandle handle, MtpObjectHandle newParent,
990 MtpStorageID newStorage) {
991 JNIEnv* env = AndroidRuntime::getJNIEnv();
992 MtpResponseCode result = env->CallIntMethod(mDatabase, method_beginMoveObject,
993 (jint)handle, (jint)newParent, (jint) newStorage);
994
995 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Jerry Zhang952558d2017-09-26 17:49:52 -0700996 return result;
997}
998
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700999void MtpDatabase::endMoveObject(MtpObjectHandle oldParent, MtpObjectHandle newParent,
1000 MtpStorageID oldStorage, MtpStorageID newStorage,
1001 MtpObjectHandle handle, bool succeeded) {
1002 JNIEnv* env = AndroidRuntime::getJNIEnv();
1003 env->CallVoidMethod(mDatabase, method_endMoveObject,
1004 (jint)oldParent, (jint) newParent, (jint) oldStorage, (jint) newStorage,
1005 (jint) handle, (jboolean) succeeded);
1006
1007 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1008}
1009
1010MtpResponseCode MtpDatabase::beginCopyObject(MtpObjectHandle handle, MtpObjectHandle newParent,
1011 MtpStorageID newStorage) {
1012 JNIEnv* env = AndroidRuntime::getJNIEnv();
1013 MtpResponseCode result = env->CallIntMethod(mDatabase, method_beginCopyObject,
1014 (jint)handle, (jint)newParent, (jint) newStorage);
1015
1016 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1017 return result;
1018}
1019
1020void MtpDatabase::endCopyObject(MtpObjectHandle handle, bool succeeded) {
1021 JNIEnv* env = AndroidRuntime::getJNIEnv();
1022 env->CallVoidMethod(mDatabase, method_endCopyObject, (jint)handle, (jboolean)succeeded);
1023
1024 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1025}
1026
1027
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001028struct PropertyTableEntry {
1029 MtpObjectProperty property;
1030 int type;
1031};
1032
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001033static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001034 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
1035 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
1036 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
1037 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
1038 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
1039 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
1040 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
1041 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
1042 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -04001043 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
1044 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
1045 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
1046 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
1047 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
1048 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
1049 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
1050 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
1051 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
1052 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
1053 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwood71827742015-01-23 10:50:08 -08001054 { MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_TYPE_UINT32 },
1055 { MTP_PROPERTY_BITRATE_TYPE, MTP_TYPE_UINT16 },
1056 { MTP_PROPERTY_AUDIO_BITRATE, MTP_TYPE_UINT32 },
1057 { MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_TYPE_UINT16 },
1058 { MTP_PROPERTY_SAMPLE_RATE, MTP_TYPE_UINT32 },
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001059};
1060
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001061static const PropertyTableEntry kDevicePropertyTable[] = {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001062 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
1063 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
1064 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
Mike Lockwood56c85242014-03-07 13:29:08 -08001065 { MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
Jerry Zhang13bb2f42016-12-14 15:39:29 -08001066 { MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE, MTP_TYPE_UINT32 },
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001067};
1068
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001069bool MtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001070 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
1071 const PropertyTableEntry* entry = kObjectPropertyTable;
1072 for (int i = 0; i < count; i++, entry++) {
1073 if (entry->property == property) {
1074 type = entry->type;
1075 return true;
1076 }
1077 }
1078 return false;
1079}
1080
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001081bool MtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001082 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
1083 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001084 for (int i = 0; i < count; i++, entry++) {
1085 if (entry->property == property) {
1086 type = entry->type;
1087 return true;
1088 }
1089 }
1090 return false;
1091}
1092
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001093MtpObjectHandleList* MtpDatabase::getObjectReferences(MtpObjectHandle handle) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001094 JNIEnv* env = AndroidRuntime::getJNIEnv();
1095 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
1096 (jint)handle);
1097 if (!array)
1098 return NULL;
1099 MtpObjectHandleList* list = new MtpObjectHandleList();
1100 jint* handles = env->GetIntArrayElements(array, 0);
1101 jsize length = env->GetArrayLength(array);
1102 for (int i = 0; i < length; i++)
1103 list->push(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001104 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -04001105 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001106
1107 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1108 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001109}
1110
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001111MtpResponseCode MtpDatabase::setObjectReferences(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001112 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001113 JNIEnv* env = AndroidRuntime::getJNIEnv();
1114 int count = references->size();
1115 jintArray array = env->NewIntArray(count);
1116 if (!array) {
Steve Block3762c312012-01-06 19:20:56 +00001117 ALOGE("out of memory in setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001118 return false;
1119 }
1120 jint* handles = env->GetIntArrayElements(array, 0);
1121 for (int i = 0; i < count; i++)
1122 handles[i] = (*references)[i];
1123 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001124 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001125 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -04001126 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001127
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001128 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1129 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001130}
1131
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001132MtpProperty* MtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001133 MtpObjectFormat format) {
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001134 static const int channelEnum[] = {
1135 1, // mono
1136 2, // stereo
1137 3, // 2.1
1138 4, // 3
1139 5, // 3.1
1140 6, // 4
1141 7, // 4.1
1142 8, // 5
1143 9, // 5.1
1144 };
1145 static const int bitrateEnum[] = {
1146 1, // fixed rate
1147 2, // variable rate
1148 };
1149
Mike Lockwood828d19d2010-08-10 15:20:35 -04001150 MtpProperty* result = NULL;
1151 switch (property) {
1152 case MTP_PROPERTY_OBJECT_FORMAT:
Mike Lockwood9b5e9c42010-12-07 18:53:50 -08001153 // use format as default value
1154 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
1155 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001156 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001157 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001158 result = new MtpProperty(property, MTP_TYPE_UINT16);
1159 break;
1160 case MTP_PROPERTY_STORAGE_ID:
1161 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001162 case MTP_PROPERTY_DURATION:
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001163 case MTP_PROPERTY_AUDIO_WAVE_CODEC:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001164 result = new MtpProperty(property, MTP_TYPE_UINT32);
1165 break;
1166 case MTP_PROPERTY_OBJECT_SIZE:
1167 result = new MtpProperty(property, MTP_TYPE_UINT64);
1168 break;
1169 case MTP_PROPERTY_PERSISTENT_UID:
1170 result = new MtpProperty(property, MTP_TYPE_UINT128);
1171 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001172 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001173 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001174 case MTP_PROPERTY_ARTIST:
1175 case MTP_PROPERTY_ALBUM_NAME:
1176 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001177 case MTP_PROPERTY_GENRE:
1178 case MTP_PROPERTY_COMPOSER:
1179 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001180 result = new MtpProperty(property, MTP_TYPE_STR);
1181 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -05001182 case MTP_PROPERTY_DATE_MODIFIED:
1183 case MTP_PROPERTY_DATE_ADDED:
1184 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
1185 result = new MtpProperty(property, MTP_TYPE_STR);
1186 result->setFormDateTime();
1187 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -04001188 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -04001189 // We allow renaming files and folders
1190 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -04001191 break;
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001192 case MTP_PROPERTY_BITRATE_TYPE:
1193 result = new MtpProperty(property, MTP_TYPE_UINT16);
1194 result->setFormEnum(bitrateEnum, sizeof(bitrateEnum)/sizeof(bitrateEnum[0]));
1195 break;
1196 case MTP_PROPERTY_AUDIO_BITRATE:
1197 result = new MtpProperty(property, MTP_TYPE_UINT32);
1198 result->setFormRange(1, 1536000, 1);
1199 break;
1200 case MTP_PROPERTY_NUMBER_OF_CHANNELS:
1201 result = new MtpProperty(property, MTP_TYPE_UINT16);
1202 result->setFormEnum(channelEnum, sizeof(channelEnum)/sizeof(channelEnum[0]));
1203 break;
1204 case MTP_PROPERTY_SAMPLE_RATE:
1205 result = new MtpProperty(property, MTP_TYPE_UINT32);
1206 result->setFormRange(8000, 48000, 1);
1207 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001208 }
1209
1210 return result;
1211}
1212
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001213MtpProperty* MtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001214 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001215 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001216 bool writable = false;
1217
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001218 // get current value
1219 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
1220 (jint)property, mLongBuffer, mStringBuffer);
1221 if (ret == MTP_RESPONSE_OK) {
1222 switch (property) {
1223 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
1224 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
1225 writable = true;
1226 // fall through
1227 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
1228 {
1229 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001230 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
1231 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001232 // for read-only properties it is safe to assume current value is default value
1233 if (!writable)
1234 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001235 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001236 break;
Mike Lockwooda2a21282010-09-25 21:21:05 -04001237 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001238 case MTP_DEVICE_PROPERTY_BATTERY_LEVEL:
1239 {
1240 result = new MtpProperty(property, MTP_TYPE_UINT8);
1241 jlong* arr = env->GetLongArrayElements(mLongBuffer, 0);
1242 result->setFormRange(0, arr[1], 1);
1243 result->mCurrentValue.u.u8 = (uint8_t) arr[0];
1244 env->ReleaseLongArrayElements(mLongBuffer, arr, 0);
1245 break;
1246 }
1247 case MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE:
1248 {
1249 jlong* arr = env->GetLongArrayElements(mLongBuffer, 0);
1250 result = new MtpProperty(property, MTP_TYPE_UINT32);
1251 result->mCurrentValue.u.u32 = (uint32_t) arr[0];
1252 env->ReleaseLongArrayElements(mLongBuffer, arr, 0);
1253 break;
1254 }
1255 default:
1256 ALOGE("Unrecognized property %x", property);
Mike Lockwood56c85242014-03-07 13:29:08 -08001257 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001258 } else {
1259 ALOGE("unable to read device property, response: %04X", ret);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001260 }
1261
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001262 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001263 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001264}
1265
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001266// ----------------------------------------------------------------------------
1267
1268static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001269android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001270{
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001271 MtpDatabase* database = new MtpDatabase(env, thiz);
Ashok Bhate2e59322013-12-17 19:04:19 +00001272 env->SetLongField(thiz, field_context, (jlong)database);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001273 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1274}
1275
1276static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001277android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001278{
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001279 MtpDatabase* database = (MtpDatabase *)env->GetLongField(thiz, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001280 database->cleanup(env);
1281 delete database;
Ashok Bhate2e59322013-12-17 19:04:19 +00001282 env->SetLongField(thiz, field_context, 0);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001283 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1284}
1285
Mike Lockwood31599912010-11-15 13:43:30 -05001286static jstring
Mark Salyzynaeb75fc2014-03-20 12:09:01 -07001287android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001288{
Mike Lockwood31599912010-11-15 13:43:30 -05001289 char date[20];
1290 formatDateTime(seconds, date, sizeof(date));
1291 return env->NewStringUTF(date);
Mike Lockwood31599912010-11-15 13:43:30 -05001292}
1293
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001294// ----------------------------------------------------------------------------
1295
Daniel Micay76f6a862015-09-19 17:31:01 -04001296static const JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001297 {"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
1298 {"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001299};
1300
Daniel Micay76f6a862015-09-19 17:31:01 -04001301static const JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001302 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001303 (void *)android_mtp_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001304};
1305
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001306#define GET_METHOD_ID(name, jclass, signature) \
1307 method_##name = env->GetMethodID(jclass, #name, signature); \
1308 if (method_##name == NULL) { \
1309 ALOGE("Can't find " #name); \
1310 return -1; \
1311 } \
1312
Mike Lockwood0cd01362010-12-30 11:54:33 -05001313int register_android_mtp_MtpDatabase(JNIEnv *env)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001314{
1315 jclass clazz;
1316
Mike Lockwood0cd01362010-12-30 11:54:33 -05001317 clazz = env->FindClass("android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001318 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001319 ALOGE("Can't find android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001320 return -1;
1321 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001322 GET_METHOD_ID(beginSendObject, clazz, "(Ljava/lang/String;III)I");
1323 GET_METHOD_ID(endSendObject, clazz, "(IZ)V");
1324 GET_METHOD_ID(rescanFile, clazz, "(Ljava/lang/String;II)V");
1325 GET_METHOD_ID(getObjectList, clazz, "(III)[I");
1326 GET_METHOD_ID(getNumObjects, clazz, "(III)I");
1327 GET_METHOD_ID(getSupportedPlaybackFormats, clazz, "()[I");
1328 GET_METHOD_ID(getSupportedCaptureFormats, clazz, "()[I");
1329 GET_METHOD_ID(getSupportedObjectProperties, clazz, "(I)[I");
1330 GET_METHOD_ID(getSupportedDeviceProperties, clazz, "()[I");
1331 GET_METHOD_ID(setObjectProperty, clazz, "(IIJLjava/lang/String;)I");
1332 GET_METHOD_ID(getDeviceProperty, clazz, "(I[J[C)I");
1333 GET_METHOD_ID(setDeviceProperty, clazz, "(IJLjava/lang/String;)I");
1334 GET_METHOD_ID(getObjectPropertyList, clazz, "(IIIII)Landroid/mtp/MtpPropertyList;");
1335 GET_METHOD_ID(getObjectInfo, clazz, "(I[I[C[J)Z");
1336 GET_METHOD_ID(getObjectFilePath, clazz, "(I[C[J)I");
1337 GET_METHOD_ID(beginDeleteObject, clazz, "(I)I");
1338 GET_METHOD_ID(endDeleteObject, clazz, "(IZ)V");
1339 GET_METHOD_ID(beginMoveObject, clazz, "(III)I");
1340 GET_METHOD_ID(endMoveObject, clazz, "(IIIIIZ)V");
1341 GET_METHOD_ID(beginCopyObject, clazz, "(III)I");
1342 GET_METHOD_ID(endCopyObject, clazz, "(IZ)V");
1343 GET_METHOD_ID(getObjectReferences, clazz, "(I)[I");
1344 GET_METHOD_ID(setObjectReferences, clazz, "(I[I)I");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001345
Ashok Bhate2e59322013-12-17 19:04:19 +00001346 field_context = env->GetFieldID(clazz, "mNativeContext", "J");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001347 if (field_context == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001348 ALOGE("Can't find MtpDatabase.mNativeContext");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001349 return -1;
1350 }
1351
Mike Lockwood0cd01362010-12-30 11:54:33 -05001352 clazz = env->FindClass("android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001353 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001354 ALOGE("Can't find android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001355 return -1;
1356 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001357 GET_METHOD_ID(getCode, clazz, "()I");
1358 GET_METHOD_ID(getCount, clazz, "()I");
1359 GET_METHOD_ID(getObjectHandles, clazz, "()[I");
1360 GET_METHOD_ID(getPropertyCodes, clazz, "()[I");
1361 GET_METHOD_ID(getDataTypes, clazz, "()[I");
1362 GET_METHOD_ID(getLongValues, clazz, "()[J");
1363 GET_METHOD_ID(getStringValues, clazz, "()[Ljava/lang/String;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001364
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001365 if (AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001366 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001367 return -1;
1368
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001369 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001370 "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001371}