blob: 0a3b47b6f90108118b8b787b0a380a4be2d832bb [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"
Jerry Zhangd9f30052018-03-27 15:29:09 -070019#include "utils/String8.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040020
Jooyung Hancb1e8962019-02-21 14:18:11 +090021#include "android_media_Streams.h"
Jaesung Chung8409c062016-01-19 10:48:30 +090022#include "mtp.h"
Jerry Zhangf9c5c252017-08-16 18:07:51 -070023#include "IMtpDatabase.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040024#include "MtpDataPacket.h"
Mike Lockwood9df53fae2011-04-21 17:05:55 -070025#include "MtpObjectInfo.h"
Mike Lockwood828d19d2010-08-10 15:20:35 -040026#include "MtpProperty.h"
Mike Lockwood59e3f0d2010-09-02 14:57:30 -040027#include "MtpStringBuffer.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040028#include "MtpUtils.h"
Jaesung Chung8409c062016-01-19 10:48:30 +090029
30#include "src/piex_types.h"
31#include "src/piex.h"
Mike Lockwoodd21eac92010-07-03 00:44:05 -040032
Jaesung Chung8409c062016-01-19 10:48:30 +090033#include <android_runtime/AndroidRuntime.h>
34#include <android_runtime/Log.h>
35#include <jni.h>
Chong Zhang63f81922018-03-14 18:57:05 -070036#include <media/stagefright/NuMediaExtractor.h>
Steven Moreland2279b252017-07-19 09:50:45 -070037#include <nativehelper/JNIHelp.h>
Jaesung Chung8409c062016-01-19 10:48:30 +090038#include <nativehelper/ScopedLocalRef.h>
39
40#include <assert.h>
41#include <fcntl.h>
42#include <inttypes.h>
43#include <limits.h>
44#include <stdio.h>
45#include <unistd.h>
46
Mike Lockwoodd21eac92010-07-03 00:44:05 -040047using namespace android;
48
49// ----------------------------------------------------------------------------
50
Mike Lockwoodd815f792010-07-12 08:49:01 -040051static jmethodID method_beginSendObject;
52static jmethodID method_endSendObject;
Jerry Zhangf9c5c252017-08-16 18:07:51 -070053static jmethodID method_rescanFile;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040054static jmethodID method_getObjectList;
Mike Lockwood7a047c82010-08-02 10:52:20 -040055static jmethodID method_getNumObjects;
Mike Lockwood4b322ce2010-08-10 07:37:50 -040056static jmethodID method_getSupportedPlaybackFormats;
57static jmethodID method_getSupportedCaptureFormats;
58static jmethodID method_getSupportedObjectProperties;
59static jmethodID method_getSupportedDeviceProperties;
Mike Lockwood828d19d2010-08-10 15:20:35 -040060static jmethodID method_setObjectProperty;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -040061static jmethodID method_getDeviceProperty;
62static jmethodID method_setDeviceProperty;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040063static jmethodID method_getObjectPropertyList;
Mike Lockwoodd21eac92010-07-03 00:44:05 -040064static jmethodID method_getObjectInfo;
65static jmethodID method_getObjectFilePath;
Marco Nelissen5954d212019-06-27 15:56:32 -070066static jmethodID method_getThumbnailInfo;
67static jmethodID method_getThumbnailData;
Jerry Zhangf9c5c252017-08-16 18:07:51 -070068static jmethodID method_beginDeleteObject;
69static jmethodID method_endDeleteObject;
70static jmethodID method_beginMoveObject;
71static jmethodID method_endMoveObject;
72static jmethodID method_beginCopyObject;
73static jmethodID method_endCopyObject;
Mike Lockwood9a2046f2010-08-03 15:30:09 -040074static jmethodID method_getObjectReferences;
75static jmethodID method_setObjectReferences;
Mike Lockwood2837eef2010-08-31 16:25:12 -040076
Mike Lockwoodd21eac92010-07-03 00:44:05 -040077static jfieldID field_context;
78
Jerry Zhangf9c5c252017-08-16 18:07:51 -070079// MtpPropertyList methods
80static jmethodID method_getCode;
81static jmethodID method_getCount;
82static jmethodID method_getObjectHandles;
83static jmethodID method_getPropertyCodes;
84static jmethodID method_getDataTypes;
85static jmethodID method_getLongValues;
86static jmethodID method_getStringValues;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -040087
88
Jerry Zhangf9c5c252017-08-16 18:07:51 -070089IMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
90 return (IMtpDatabase *)env->GetLongField(database, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -040091}
92
93// ----------------------------------------------------------------------------
94
Jerry Zhangf9c5c252017-08-16 18:07:51 -070095class MtpDatabase : public IMtpDatabase {
Mike Lockwoodd21eac92010-07-03 00:44:05 -040096private:
97 jobject mDatabase;
98 jintArray mIntBuffer;
99 jlongArray mLongBuffer;
100 jcharArray mStringBuffer;
101
102public:
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700103 MtpDatabase(JNIEnv *env, jobject client);
104 virtual ~MtpDatabase();
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400105 void cleanup(JNIEnv *env);
106
Mike Lockwoodd815f792010-07-12 08:49:01 -0400107 virtual MtpObjectHandle beginSendObject(const char* path,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400108 MtpObjectFormat format,
109 MtpObjectHandle parent,
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700110 MtpStorageID storage);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400111
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700112 virtual void endSendObject(MtpObjectHandle handle, bool succeeded);
113
114 virtual void rescanFile(const char* path,
Mike Lockwoodd815f792010-07-12 08:49:01 -0400115 MtpObjectHandle handle,
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700116 MtpObjectFormat format);
kyle_tsob4aa69f2017-11-22 20:11:27 +0800117
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400118 virtual MtpObjectHandleList* getObjectList(MtpStorageID storageID,
119 MtpObjectFormat format,
120 MtpObjectHandle parent);
121
Mike Lockwood7a047c82010-08-02 10:52:20 -0400122 virtual int getNumObjects(MtpStorageID storageID,
123 MtpObjectFormat format,
124 MtpObjectHandle parent);
125
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400126 // callee should delete[] the results from these
127 // results can be NULL
128 virtual MtpObjectFormatList* getSupportedPlaybackFormats();
129 virtual MtpObjectFormatList* getSupportedCaptureFormats();
130 virtual MtpObjectPropertyList* getSupportedObjectProperties(MtpObjectFormat format);
131 virtual MtpDevicePropertyList* getSupportedDeviceProperties();
132
Mike Lockwood828d19d2010-08-10 15:20:35 -0400133 virtual MtpResponseCode getObjectPropertyValue(MtpObjectHandle handle,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400134 MtpObjectProperty property,
135 MtpDataPacket& packet);
136
Mike Lockwood828d19d2010-08-10 15:20:35 -0400137 virtual MtpResponseCode setObjectPropertyValue(MtpObjectHandle handle,
138 MtpObjectProperty property,
139 MtpDataPacket& packet);
140
141 virtual MtpResponseCode getDevicePropertyValue(MtpDeviceProperty property,
142 MtpDataPacket& packet);
143
144 virtual MtpResponseCode setDevicePropertyValue(MtpDeviceProperty property,
145 MtpDataPacket& packet);
146
147 virtual MtpResponseCode resetDeviceProperty(MtpDeviceProperty property);
148
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400149 virtual MtpResponseCode getObjectPropertyList(MtpObjectHandle handle,
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500150 uint32_t format, uint32_t property,
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400151 int groupCode, int depth,
152 MtpDataPacket& packet);
153
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400154 virtual MtpResponseCode getObjectInfo(MtpObjectHandle handle,
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700155 MtpObjectInfo& info);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400156
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700157 virtual void* getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
158
Mike Lockwood59c777a2010-08-02 10:37:41 -0400159 virtual MtpResponseCode getObjectFilePath(MtpObjectHandle handle,
Jerry Zhangd9f30052018-03-27 15:29:09 -0700160 MtpStringBuffer& outFilePath,
Mike Lockwood365e03e2010-12-08 16:08:01 -0800161 int64_t& outFileLength,
162 MtpObjectFormat& outFormat);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700163 virtual MtpResponseCode beginDeleteObject(MtpObjectHandle handle);
164 virtual void endDeleteObject(MtpObjectHandle handle, bool succeeded);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400165
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400166 bool getObjectPropertyInfo(MtpObjectProperty property, int& type);
167 bool getDevicePropertyInfo(MtpDeviceProperty property, int& type);
Mike Lockwood9a2046f2010-08-03 15:30:09 -0400168
169 virtual MtpObjectHandleList* getObjectReferences(MtpObjectHandle handle);
170
171 virtual MtpResponseCode setObjectReferences(MtpObjectHandle handle,
172 MtpObjectHandleList* references);
Mike Lockwood828d19d2010-08-10 15:20:35 -0400173
174 virtual MtpProperty* getObjectPropertyDesc(MtpObjectProperty property,
175 MtpObjectFormat format);
176
177 virtual MtpProperty* getDevicePropertyDesc(MtpDeviceProperty property);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400178
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700179 virtual MtpResponseCode beginMoveObject(MtpObjectHandle handle, MtpObjectHandle newParent,
180 MtpStorageID newStorage);
Jerry Zhang952558d2017-09-26 17:49:52 -0700181
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700182 virtual void endMoveObject(MtpObjectHandle oldParent, MtpObjectHandle newParent,
183 MtpStorageID oldStorage, MtpStorageID newStorage,
184 MtpObjectHandle handle, bool succeeded);
Mike Lockwood2837eef2010-08-31 16:25:12 -0400185
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700186 virtual MtpResponseCode beginCopyObject(MtpObjectHandle handle, MtpObjectHandle newParent,
187 MtpStorageID newStorage);
188 virtual void endCopyObject(MtpObjectHandle handle, bool succeeded);
189
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400190};
191
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400192// ----------------------------------------------------------------------------
193
194static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
195 if (env->ExceptionCheck()) {
Steve Block3762c312012-01-06 19:20:56 +0000196 ALOGE("An exception was thrown by callback '%s'.", methodName);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400197 LOGE_EX(env);
198 env->ExceptionClear();
199 }
200}
201
202// ----------------------------------------------------------------------------
203
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700204MtpDatabase::MtpDatabase(JNIEnv *env, jobject client)
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400205 : mDatabase(env->NewGlobalRef(client)),
206 mIntBuffer(NULL),
207 mLongBuffer(NULL),
208 mStringBuffer(NULL)
209{
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400210 // create buffers for out arguments
211 // we don't need to be thread-safe so this is OK
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700212 jintArray intArray = env->NewIntArray(3);
213 if (!intArray) {
214 return; // Already threw.
215 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400216 mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
Marco Nelissen5954d212019-06-27 15:56:32 -0700217 jlongArray longArray = env->NewLongArray(3);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700218 if (!longArray) {
219 return; // Already threw.
220 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400221 mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
Mike Lockwood63ffd782014-09-24 10:55:19 -0700222 // Needs to be long enough to hold a file path for getObjectFilePath()
223 jcharArray charArray = env->NewCharArray(PATH_MAX + 1);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700224 if (!charArray) {
225 return; // Already threw.
226 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400227 mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400228}
229
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700230void MtpDatabase::cleanup(JNIEnv *env) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400231 env->DeleteGlobalRef(mDatabase);
232 env->DeleteGlobalRef(mIntBuffer);
233 env->DeleteGlobalRef(mLongBuffer);
234 env->DeleteGlobalRef(mStringBuffer);
235}
236
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700237MtpDatabase::~MtpDatabase() {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400238}
239
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700240MtpObjectHandle MtpDatabase::beginSendObject(const char* path,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900241 MtpObjectFormat format,
242 MtpObjectHandle parent,
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700243 MtpStorageID storage) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400244 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400245 jstring pathStr = env->NewStringUTF(path);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400246 MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700247 pathStr, (jint)format, (jint)parent, (jint)storage);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400248
Mike Lockwood88394712010-09-27 10:01:00 -0400249 if (pathStr)
250 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400251 checkAndClearExceptionFromCallback(env, __FUNCTION__);
252 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400253}
254
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700255void MtpDatabase::endSendObject(MtpObjectHandle handle, bool succeeded) {
256 JNIEnv* env = AndroidRuntime::getJNIEnv();
257 env->CallVoidMethod(mDatabase, method_endSendObject, (jint)handle, (jboolean)succeeded);
258
259 checkAndClearExceptionFromCallback(env, __FUNCTION__);
260}
261
262void MtpDatabase::rescanFile(const char* path, MtpObjectHandle handle,
263 MtpObjectFormat format) {
Mike Lockwoodd815f792010-07-12 08:49:01 -0400264 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood88394712010-09-27 10:01:00 -0400265 jstring pathStr = env->NewStringUTF(path);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700266 env->CallVoidMethod(mDatabase, method_rescanFile, pathStr,
267 (jint)handle, (jint)format);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400268
Mike Lockwood88394712010-09-27 10:01:00 -0400269 if (pathStr)
270 env->DeleteLocalRef(pathStr);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400271 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd815f792010-07-12 08:49:01 -0400272}
273
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700274MtpObjectHandleList* MtpDatabase::getObjectList(MtpStorageID storageID,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900275 MtpObjectFormat format,
276 MtpObjectHandle parent) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400277 JNIEnv* env = AndroidRuntime::getJNIEnv();
278 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
279 (jint)storageID, (jint)format, (jint)parent);
280 if (!array)
281 return NULL;
282 MtpObjectHandleList* list = new MtpObjectHandleList();
283 jint* handles = env->GetIntArrayElements(array, 0);
284 jsize length = env->GetArrayLength(array);
Mike Lockwood7a047c82010-08-02 10:52:20 -0400285 for (int i = 0; i < length; i++)
Jerry Zhangd9f30052018-03-27 15:29:09 -0700286 list->push_back(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400287 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400288 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400289
290 checkAndClearExceptionFromCallback(env, __FUNCTION__);
291 return list;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400292}
293
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700294int MtpDatabase::getNumObjects(MtpStorageID storageID,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900295 MtpObjectFormat format,
296 MtpObjectHandle parent) {
Mike Lockwood7a047c82010-08-02 10:52:20 -0400297 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400298 int result = env->CallIntMethod(mDatabase, method_getNumObjects,
Mike Lockwood7a047c82010-08-02 10:52:20 -0400299 (jint)storageID, (jint)format, (jint)parent);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400300
301 checkAndClearExceptionFromCallback(env, __FUNCTION__);
302 return result;
Mike Lockwood7a047c82010-08-02 10:52:20 -0400303}
304
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700305MtpObjectFormatList* MtpDatabase::getSupportedPlaybackFormats() {
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400306 JNIEnv* env = AndroidRuntime::getJNIEnv();
307 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
308 method_getSupportedPlaybackFormats);
309 if (!array)
310 return NULL;
311 MtpObjectFormatList* list = new MtpObjectFormatList();
312 jint* formats = env->GetIntArrayElements(array, 0);
313 jsize length = env->GetArrayLength(array);
314 for (int i = 0; i < length; i++)
Jerry Zhangd9f30052018-03-27 15:29:09 -0700315 list->push_back(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400316 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400317 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400318
319 checkAndClearExceptionFromCallback(env, __FUNCTION__);
320 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400321}
322
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700323MtpObjectFormatList* MtpDatabase::getSupportedCaptureFormats() {
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400324 JNIEnv* env = AndroidRuntime::getJNIEnv();
325 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
326 method_getSupportedCaptureFormats);
327 if (!array)
328 return NULL;
329 MtpObjectFormatList* list = new MtpObjectFormatList();
330 jint* formats = env->GetIntArrayElements(array, 0);
331 jsize length = env->GetArrayLength(array);
332 for (int i = 0; i < length; i++)
Jerry Zhangd9f30052018-03-27 15:29:09 -0700333 list->push_back(formats[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400334 env->ReleaseIntArrayElements(array, formats, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400335 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400336
337 checkAndClearExceptionFromCallback(env, __FUNCTION__);
338 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400339}
340
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700341MtpObjectPropertyList* MtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400342 JNIEnv* env = AndroidRuntime::getJNIEnv();
343 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
344 method_getSupportedObjectProperties, (jint)format);
345 if (!array)
346 return NULL;
347 MtpObjectPropertyList* list = new MtpObjectPropertyList();
348 jint* properties = env->GetIntArrayElements(array, 0);
349 jsize length = env->GetArrayLength(array);
350 for (int i = 0; i < length; i++)
Jerry Zhangd9f30052018-03-27 15:29:09 -0700351 list->push_back(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400352 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400353 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400354
355 checkAndClearExceptionFromCallback(env, __FUNCTION__);
356 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400357}
358
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700359MtpDevicePropertyList* MtpDatabase::getSupportedDeviceProperties() {
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400360 JNIEnv* env = AndroidRuntime::getJNIEnv();
361 jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
362 method_getSupportedDeviceProperties);
363 if (!array)
364 return NULL;
365 MtpDevicePropertyList* list = new MtpDevicePropertyList();
366 jint* properties = env->GetIntArrayElements(array, 0);
367 jsize length = env->GetArrayLength(array);
368 for (int i = 0; i < length; i++)
Jerry Zhangd9f30052018-03-27 15:29:09 -0700369 list->push_back(properties[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400370 env->ReleaseIntArrayElements(array, properties, 0);
Mike Lockwood88394712010-09-27 10:01:00 -0400371 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400372
373 checkAndClearExceptionFromCallback(env, __FUNCTION__);
374 return list;
Mike Lockwood4b322ce2010-08-10 07:37:50 -0400375}
376
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700377MtpResponseCode MtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900378 MtpObjectProperty property,
379 MtpDataPacket& packet) {
380 static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
381 "Casting MtpObjectHandle to jint loses a value");
382 static_assert(sizeof(jint) >= sizeof(MtpObjectProperty),
383 "Casting MtpObjectProperty to jint loses a value");
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400384 JNIEnv* env = AndroidRuntime::getJNIEnv();
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900385 jobject list = env->CallObjectMethod(
386 mDatabase,
387 method_getObjectPropertyList,
388 static_cast<jint>(handle),
389 0,
390 static_cast<jint>(property),
391 0,
392 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700393 MtpResponseCode result = env->CallIntMethod(list, method_getCode);
394 jint count = env->CallIntMethod(list, method_getCount);
395 if (count != 1)
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400396 result = MTP_RESPONSE_GENERAL_ERROR;
397
398 if (result == MTP_RESPONSE_OK) {
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700399 jintArray objectHandlesArray = (jintArray)env->CallObjectMethod(list, method_getObjectHandles);
400 jintArray propertyCodesArray = (jintArray)env->CallObjectMethod(list, method_getPropertyCodes);
401 jintArray dataTypesArray = (jintArray)env->CallObjectMethod(list, method_getDataTypes);
402 jlongArray longValuesArray = (jlongArray)env->CallObjectMethod(list, method_getLongValues);
403 jobjectArray stringValuesArray = (jobjectArray)env->CallObjectMethod(list, method_getStringValues);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400404
405 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
406 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
407 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700408 jlong* longValues = env->GetLongArrayElements(longValuesArray, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400409
410 int type = dataTypes[0];
411 jlong longValue = (longValues ? longValues[0] : 0);
412
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400413 switch (type) {
414 case MTP_TYPE_INT8:
415 packet.putInt8(longValue);
416 break;
417 case MTP_TYPE_UINT8:
418 packet.putUInt8(longValue);
419 break;
420 case MTP_TYPE_INT16:
421 packet.putInt16(longValue);
422 break;
423 case MTP_TYPE_UINT16:
424 packet.putUInt16(longValue);
425 break;
426 case MTP_TYPE_INT32:
427 packet.putInt32(longValue);
428 break;
429 case MTP_TYPE_UINT32:
430 packet.putUInt32(longValue);
431 break;
432 case MTP_TYPE_INT64:
433 packet.putInt64(longValue);
434 break;
435 case MTP_TYPE_UINT64:
436 packet.putUInt64(longValue);
437 break;
438 case MTP_TYPE_INT128:
439 packet.putInt128(longValue);
440 break;
441 case MTP_TYPE_UINT128:
Wanwu Peng8937f1a2016-03-02 18:16:46 +0800442 packet.putUInt128(longValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400443 break;
444 case MTP_TYPE_STR:
445 {
446 jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200447 const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400448 if (stringValue) {
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400449 packet.putString(str);
450 env->ReleaseStringUTFChars(stringValue, str);
451 } else {
452 packet.putEmptyString();
453 }
Martin Blumenstingl17a24c52014-05-31 15:50:38 +0200454 env->DeleteLocalRef(stringValue);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400455 break;
456 }
457 default:
Steve Block3762c312012-01-06 19:20:56 +0000458 ALOGE("unsupported type in getObjectPropertyValue\n");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400459 result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
460 }
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400461 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
462 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
463 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700464 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400465
466 env->DeleteLocalRef(objectHandlesArray);
467 env->DeleteLocalRef(propertyCodesArray);
468 env->DeleteLocalRef(dataTypesArray);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700469 env->DeleteLocalRef(longValuesArray);
470 env->DeleteLocalRef(stringValuesArray);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400471 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400472
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400473 env->DeleteLocalRef(list);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400474 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400475 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400476}
477
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800478static bool readLongValue(int type, MtpDataPacket& packet, jlong& longValue) {
479 switch (type) {
480 case MTP_TYPE_INT8: {
481 int8_t temp;
482 if (!packet.getInt8(temp)) return false;
483 longValue = temp;
484 break;
485 }
486 case MTP_TYPE_UINT8: {
487 uint8_t temp;
488 if (!packet.getUInt8(temp)) return false;
489 longValue = temp;
490 break;
491 }
492 case MTP_TYPE_INT16: {
493 int16_t temp;
494 if (!packet.getInt16(temp)) return false;
495 longValue = temp;
496 break;
497 }
498 case MTP_TYPE_UINT16: {
499 uint16_t temp;
500 if (!packet.getUInt16(temp)) return false;
501 longValue = temp;
502 break;
503 }
504 case MTP_TYPE_INT32: {
505 int32_t temp;
506 if (!packet.getInt32(temp)) return false;
507 longValue = temp;
508 break;
509 }
510 case MTP_TYPE_UINT32: {
511 uint32_t temp;
512 if (!packet.getUInt32(temp)) return false;
513 longValue = temp;
514 break;
515 }
516 case MTP_TYPE_INT64: {
517 int64_t temp;
518 if (!packet.getInt64(temp)) return false;
519 longValue = temp;
520 break;
521 }
522 case MTP_TYPE_UINT64: {
523 uint64_t temp;
524 if (!packet.getUInt64(temp)) return false;
525 longValue = temp;
526 break;
527 }
528 default:
529 ALOGE("unsupported type in readLongValue");
530 return false;
531 }
532 return true;
533}
534
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700535MtpResponseCode MtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900536 MtpObjectProperty property,
537 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400538 int type;
539
540 if (!getObjectPropertyInfo(property, type))
541 return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
542
543 JNIEnv* env = AndroidRuntime::getJNIEnv();
544 jlong longValue = 0;
545 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800546 MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400547
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800548 if (type == MTP_TYPE_STR) {
549 MtpStringBuffer buffer;
550 if (!packet.getString(buffer)) goto fail;
551 stringValue = env->NewStringUTF((const char *)buffer);
552 } else {
553 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400554 }
555
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800556 result = env->CallIntMethod(mDatabase, method_setObjectProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400557 (jint)handle, (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400558 if (stringValue)
559 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400560
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800561fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400562 checkAndClearExceptionFromCallback(env, __FUNCTION__);
563 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400564}
565
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700566MtpResponseCode MtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900567 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400568 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700569 int type;
Mike Lockwood56c85242014-03-07 13:29:08 -0800570
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700571 if (!getDevicePropertyInfo(property, type))
572 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
Mike Lockwood56c85242014-03-07 13:29:08 -0800573
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700574 jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
575 (jint)property, mLongBuffer, mStringBuffer);
576 if (result != MTP_RESPONSE_OK) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400577 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700578 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400579 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700580
581 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
582 jlong longValue = longValues[0];
583 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
584
585 switch (type) {
586 case MTP_TYPE_INT8:
587 packet.putInt8(longValue);
588 break;
589 case MTP_TYPE_UINT8:
590 packet.putUInt8(longValue);
591 break;
592 case MTP_TYPE_INT16:
593 packet.putInt16(longValue);
594 break;
595 case MTP_TYPE_UINT16:
596 packet.putUInt16(longValue);
597 break;
598 case MTP_TYPE_INT32:
599 packet.putInt32(longValue);
600 break;
601 case MTP_TYPE_UINT32:
602 packet.putUInt32(longValue);
603 break;
604 case MTP_TYPE_INT64:
605 packet.putInt64(longValue);
606 break;
607 case MTP_TYPE_UINT64:
608 packet.putUInt64(longValue);
609 break;
610 case MTP_TYPE_INT128:
611 packet.putInt128(longValue);
612 break;
613 case MTP_TYPE_UINT128:
614 packet.putInt128(longValue);
615 break;
616 case MTP_TYPE_STR:
617 {
618 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
619 packet.putString(str);
620 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
621 break;
622 }
623 default:
624 ALOGE("unsupported type in getDevicePropertyValue\n");
625 return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
626 }
627
628 checkAndClearExceptionFromCallback(env, __FUNCTION__);
629 return MTP_RESPONSE_OK;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400630}
631
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700632MtpResponseCode MtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900633 MtpDataPacket& packet) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400634 int type;
635
636 if (!getDevicePropertyInfo(property, type))
637 return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
638
639 JNIEnv* env = AndroidRuntime::getJNIEnv();
640 jlong longValue = 0;
641 jstring stringValue = NULL;
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800642 MtpResponseCode result = MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400643
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800644 if (type == MTP_TYPE_STR) {
645 MtpStringBuffer buffer;
646 if (!packet.getString(buffer)) goto fail;
647 stringValue = env->NewStringUTF((const char *)buffer);
648 } else {
649 if (!readLongValue(type, packet, longValue)) goto fail;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400650 }
651
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800652 result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400653 (jint)property, longValue, stringValue);
Mike Lockwood88394712010-09-27 10:01:00 -0400654 if (stringValue)
655 env->DeleteLocalRef(stringValue);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400656
Mike Lockwood9c803fa2014-11-13 09:40:42 -0800657fail:
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400658 checkAndClearExceptionFromCallback(env, __FUNCTION__);
659 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -0400660}
661
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700662MtpResponseCode MtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
Mike Lockwood828d19d2010-08-10 15:20:35 -0400663 return -1;
664}
665
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700666MtpResponseCode MtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900667 uint32_t format, uint32_t property,
668 int groupCode, int depth,
669 MtpDataPacket& packet) {
670 static_assert(sizeof(jint) >= sizeof(MtpObjectHandle),
671 "Casting MtpObjectHandle to jint loses a value");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400672 JNIEnv* env = AndroidRuntime::getJNIEnv();
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900673 jobject list = env->CallObjectMethod(
674 mDatabase,
675 method_getObjectPropertyList,
676 static_cast<jint>(handle),
677 static_cast<jint>(format),
678 static_cast<jint>(property),
679 static_cast<jint>(groupCode),
680 static_cast<jint>(depth));
Mike Lockwood7d7fb632010-12-01 18:46:23 -0500681 checkAndClearExceptionFromCallback(env, __FUNCTION__);
682 if (!list)
683 return MTP_RESPONSE_GENERAL_ERROR;
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700684 int count = env->CallIntMethod(list, method_getCount);
685 MtpResponseCode result = env->CallIntMethod(list, method_getCode);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400686
687 packet.putUInt32(count);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400688 if (count > 0) {
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700689 jintArray objectHandlesArray = (jintArray)env->CallObjectMethod(list, method_getObjectHandles);
690 jintArray propertyCodesArray = (jintArray)env->CallObjectMethod(list, method_getPropertyCodes);
691 jintArray dataTypesArray = (jintArray)env->CallObjectMethod(list, method_getDataTypes);
692 jlongArray longValuesArray = (jlongArray)env->CallObjectMethod(list, method_getLongValues);
693 jobjectArray stringValuesArray = (jobjectArray)env->CallObjectMethod(list, method_getStringValues);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400694
695 jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
696 jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
697 jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
698 jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
699
700 for (int i = 0; i < count; i++) {
701 packet.putUInt32(objectHandles[i]);
702 packet.putUInt16(propertyCodes[i]);
703 int type = dataTypes[i];
704 packet.putUInt16(type);
705
George Burgess IVa8626ae2016-12-13 16:12:10 -0800706 if (type == MTP_TYPE_STR) {
707 jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
708 const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
709 if (valueStr) {
710 packet.putString(valueStr);
711 env->ReleaseStringUTFChars(value, valueStr);
712 } else {
713 packet.putEmptyString();
714 }
715 env->DeleteLocalRef(value);
716 continue;
717 }
718
719 if (!longValues) {
720 ALOGE("bad longValuesArray value in MyMtpDatabase::getObjectPropertyList");
721 continue;
722 }
723
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400724 switch (type) {
725 case MTP_TYPE_INT8:
726 packet.putInt8(longValues[i]);
727 break;
728 case MTP_TYPE_UINT8:
729 packet.putUInt8(longValues[i]);
730 break;
731 case MTP_TYPE_INT16:
732 packet.putInt16(longValues[i]);
733 break;
734 case MTP_TYPE_UINT16:
735 packet.putUInt16(longValues[i]);
736 break;
737 case MTP_TYPE_INT32:
738 packet.putInt32(longValues[i]);
739 break;
740 case MTP_TYPE_UINT32:
741 packet.putUInt32(longValues[i]);
742 break;
743 case MTP_TYPE_INT64:
744 packet.putInt64(longValues[i]);
745 break;
746 case MTP_TYPE_UINT64:
747 packet.putUInt64(longValues[i]);
748 break;
749 case MTP_TYPE_INT128:
750 packet.putInt128(longValues[i]);
751 break;
752 case MTP_TYPE_UINT128:
753 packet.putUInt128(longValues[i]);
754 break;
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400755 default:
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700756 ALOGE("bad or unsupported data type in MtpDatabase::getObjectPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400757 break;
758 }
759 }
760
761 env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
762 env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
763 env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700764 env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400765
766 env->DeleteLocalRef(objectHandlesArray);
767 env->DeleteLocalRef(propertyCodesArray);
768 env->DeleteLocalRef(dataTypesArray);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700769 env->DeleteLocalRef(longValuesArray);
770 env->DeleteLocalRef(stringValuesArray);
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -0400771 }
772
773 env->DeleteLocalRef(list);
774 checkAndClearExceptionFromCallback(env, __FUNCTION__);
775 return result;
776}
777
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700778MtpResponseCode MtpDatabase::getObjectInfo(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900779 MtpObjectInfo& info) {
Jerry Zhangd9f30052018-03-27 15:29:09 -0700780 MtpStringBuffer path;
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700781 int64_t length;
782 MtpObjectFormat format;
783
784 MtpResponseCode result = getObjectFilePath(handle, path, length, format);
785 if (result != MTP_RESPONSE_OK) {
786 return result;
787 }
788 info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400789
790 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700791 if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
792 (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400793 return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
Mike Lockwoodf6f16612012-09-12 15:50:59 -0700794 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400795
796 jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700797 info.mStorageID = intValues[0];
798 info.mFormat = intValues[1];
799 info.mParent = intValues[2];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400800 env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
801
802 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood1341f1e2013-04-01 10:52:47 -0700803 info.mDateCreated = longValues[0];
804 info.mDateModified = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400805 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
806
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800807 if ((false)) {
808 info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
809 MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
810 MTP_ASSOCIATION_TYPE_UNDEFINED);
811 }
Mike Lockwood9df53fae2011-04-21 17:05:55 -0700812 info.mAssociationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400813
814 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Jerry Zhangd9f30052018-03-27 15:29:09 -0700815 MtpStringBuffer temp(str);
816 info.mName = strdup(temp);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400817 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
818
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700819 // read EXIF data for thumbnail information
Jaesung Chung8409c062016-01-19 10:48:30 +0900820 switch (info.mFormat) {
821 case MTP_FORMAT_EXIF_JPEG:
Chong Zhang6e18cce2017-08-16 11:57:02 -0700822 case MTP_FORMAT_HEIF:
Jaesung Chung8409c062016-01-19 10:48:30 +0900823 case MTP_FORMAT_JFIF: {
Marco Nelissen5954d212019-06-27 15:56:32 -0700824 env = AndroidRuntime::getJNIEnv();
825 if (env->CallBooleanMethod(
826 mDatabase, method_getThumbnailInfo, (jint)handle, mLongBuffer)) {
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800827
Marco Nelissen5954d212019-06-27 15:56:32 -0700828 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
829 jlong size = longValues[0];
830 jlong w = longValues[1];
831 jlong h = longValues[2];
832 if (size > 0 && size <= UINT32_MAX &&
833 w > 0 && w <= UINT32_MAX &&
834 h > 0 && h <= UINT32_MAX) {
835 info.mThumbCompressedSize = size;
836 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
837 info.mImagePixWidth = w;
838 info.mImagePixHeight = h;
839 }
840 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
Jaesung Chung8409c062016-01-19 10:48:30 +0900841 }
842 break;
843 }
844
845 // Except DNG, all supported RAW image formats are not defined in PTP 1.2 specification.
846 // Most of RAW image formats are based on TIFF or TIFF/EP. To render Fuji's RAF format,
847 // it checks MTP_FORMAT_DEFINED case since it's designed as a custom format.
848 case MTP_FORMAT_DNG:
849 case MTP_FORMAT_TIFF:
850 case MTP_FORMAT_TIFF_EP:
851 case MTP_FORMAT_DEFINED: {
Jerry Zhangd9f30052018-03-27 15:29:09 -0700852 String8 temp(path);
853 std::unique_ptr<FileStream> stream(new FileStream(temp));
Jaesung Chung8409c062016-01-19 10:48:30 +0900854 piex::PreviewImageData image_data;
Jerry Zhangd9f30052018-03-27 15:29:09 -0700855 if (!GetExifFromRawImage(stream.get(), temp, image_data)) {
Jaesung Chung8409c062016-01-19 10:48:30 +0900856 // Couldn't parse EXIF data from a image file via piex.
857 break;
Andreas Gampe5a15d0d2014-11-10 18:19:40 -0800858 }
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800859
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900860 info.mThumbCompressedSize = image_data.thumbnail.length;
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800861 info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
Jaesung Chung8409c062016-01-19 10:48:30 +0900862 info.mImagePixWidth = image_data.full_width;
863 info.mImagePixHeight = image_data.full_height;
864
865 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700866 }
867 }
868
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400869 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400870 return MTP_RESPONSE_OK;
871}
872
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700873void* MtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
Jerry Zhangd9f30052018-03-27 15:29:09 -0700874 MtpStringBuffer path;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700875 int64_t length;
876 MtpObjectFormat format;
877 void* result = NULL;
878 outThumbSize = 0;
879
Jaesung Chung8409c062016-01-19 10:48:30 +0900880 if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK) {
881 switch (format) {
882 case MTP_FORMAT_EXIF_JPEG:
Chong Zhang6e18cce2017-08-16 11:57:02 -0700883 case MTP_FORMAT_HEIF:
Jaesung Chung8409c062016-01-19 10:48:30 +0900884 case MTP_FORMAT_JFIF: {
Marco Nelissen5954d212019-06-27 15:56:32 -0700885 JNIEnv* env = AndroidRuntime::getJNIEnv();
886 jbyteArray thumbData = (jbyteArray) env->CallObjectMethod(
887 mDatabase, method_getThumbnailData, (jint)handle);
888 if (thumbData == NULL) {
889 return nullptr;
Chong Zhang63f81922018-03-14 18:57:05 -0700890 }
Marco Nelissen5954d212019-06-27 15:56:32 -0700891 jsize thumbSize = env->GetArrayLength(thumbData);
892 result = malloc(thumbSize);
893 if (result) {
894 env->GetByteArrayRegion(thumbData, 0, thumbSize, (jbyte*)result);
895 outThumbSize = thumbSize;
Marco Nelissen3cd393c2014-01-10 10:39:27 -0800896 }
Marco Nelissen5954d212019-06-27 15:56:32 -0700897 env->DeleteLocalRef(thumbData);
Jaesung Chung8409c062016-01-19 10:48:30 +0900898 break;
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700899 }
Jaesung Chung8409c062016-01-19 10:48:30 +0900900
901 // See the above comment on getObjectInfo() method.
902 case MTP_FORMAT_DNG:
903 case MTP_FORMAT_TIFF:
904 case MTP_FORMAT_TIFF_EP:
905 case MTP_FORMAT_DEFINED: {
Jerry Zhangd9f30052018-03-27 15:29:09 -0700906 String8 temp(path);
907 std::unique_ptr<FileStream> stream(new FileStream(temp));
Jaesung Chung8409c062016-01-19 10:48:30 +0900908 piex::PreviewImageData image_data;
Jerry Zhangd9f30052018-03-27 15:29:09 -0700909 if (!GetExifFromRawImage(stream.get(), temp, image_data)) {
Jaesung Chung8409c062016-01-19 10:48:30 +0900910 // Couldn't parse EXIF data from a image file via piex.
911 break;
912 }
913
Jaesung Chung742e89f2016-04-13 14:13:10 +0900914 if (image_data.thumbnail.length == 0
Insun Kang82c2ce12016-04-19 17:56:10 +0900915 || image_data.thumbnail.format != ::piex::Image::kJpegCompressed) {
Jaesung Chung742e89f2016-04-13 14:13:10 +0900916 // No thumbnail or non jpeg thumbnail.
Jaesung Chung8409c062016-01-19 10:48:30 +0900917 break;
918 }
919
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900920 result = malloc(image_data.thumbnail.length);
Jaesung Chung8409c062016-01-19 10:48:30 +0900921 if (result) {
922 piex::Error err = stream.get()->GetData(
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900923 image_data.thumbnail.offset,
924 image_data.thumbnail.length,
Jaesung Chung8409c062016-01-19 10:48:30 +0900925 (std::uint8_t *)result);
926 if (err == piex::Error::kOk) {
Jaesung Chungfd3446e2016-04-06 21:42:39 +0900927 outThumbSize = image_data.thumbnail.length;
Jaesung Chung8409c062016-01-19 10:48:30 +0900928 } else {
929 free(result);
Chong Zhange6b98532017-10-24 16:07:18 -0700930 result = NULL;
Jaesung Chung8409c062016-01-19 10:48:30 +0900931 }
932 }
933 break;
934 }
Mike Lockwoodc89f2222011-04-24 18:40:17 -0700935 }
936 }
937
938 return result;
939}
940
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700941MtpResponseCode MtpDatabase::getObjectFilePath(MtpObjectHandle handle,
Jerry Zhangd9f30052018-03-27 15:29:09 -0700942 MtpStringBuffer& outFilePath,
Daichi Hirono486ad2e2016-02-29 17:28:47 +0900943 int64_t& outFileLength,
944 MtpObjectFormat& outFormat) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400945 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59c777a2010-08-02 10:37:41 -0400946 jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400947 (jint)handle, mStringBuffer, mLongBuffer);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400948 if (result != MTP_RESPONSE_OK) {
949 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400950 return result;
Mike Lockwood59e3f0d2010-09-02 14:57:30 -0400951 }
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400952
953 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
Jerry Zhangd9f30052018-03-27 15:29:09 -0700954 outFilePath.set(str);
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400955 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
956
957 jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
Mike Lockwood365e03e2010-12-08 16:08:01 -0800958 outFileLength = longValues[0];
959 outFormat = longValues[1];
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400960 env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
Elliott Hughes15dd15f2011-04-08 17:42:34 -0700961
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400962 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59c777a2010-08-02 10:37:41 -0400963 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400964}
965
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700966MtpResponseCode MtpDatabase::beginDeleteObject(MtpObjectHandle handle) {
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400967 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700968 MtpResponseCode result = env->CallIntMethod(mDatabase, method_beginDeleteObject, (jint)handle);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -0400969
970 checkAndClearExceptionFromCallback(env, __FUNCTION__);
971 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -0400972}
973
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700974void MtpDatabase::endDeleteObject(MtpObjectHandle handle, bool succeeded) {
Jerry Zhang952558d2017-09-26 17:49:52 -0700975 JNIEnv* env = AndroidRuntime::getJNIEnv();
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700976 env->CallVoidMethod(mDatabase, method_endDeleteObject, (jint)handle, (jboolean) succeeded);
Jerry Zhang952558d2017-09-26 17:49:52 -0700977
978 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700979}
980
981MtpResponseCode MtpDatabase::beginMoveObject(MtpObjectHandle handle, MtpObjectHandle newParent,
982 MtpStorageID newStorage) {
983 JNIEnv* env = AndroidRuntime::getJNIEnv();
984 MtpResponseCode result = env->CallIntMethod(mDatabase, method_beginMoveObject,
985 (jint)handle, (jint)newParent, (jint) newStorage);
986
987 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Jerry Zhang952558d2017-09-26 17:49:52 -0700988 return result;
989}
990
Jerry Zhangf9c5c252017-08-16 18:07:51 -0700991void MtpDatabase::endMoveObject(MtpObjectHandle oldParent, MtpObjectHandle newParent,
992 MtpStorageID oldStorage, MtpStorageID newStorage,
993 MtpObjectHandle handle, bool succeeded) {
994 JNIEnv* env = AndroidRuntime::getJNIEnv();
995 env->CallVoidMethod(mDatabase, method_endMoveObject,
996 (jint)oldParent, (jint) newParent, (jint) oldStorage, (jint) newStorage,
997 (jint) handle, (jboolean) succeeded);
998
999 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1000}
1001
1002MtpResponseCode MtpDatabase::beginCopyObject(MtpObjectHandle handle, MtpObjectHandle newParent,
1003 MtpStorageID newStorage) {
1004 JNIEnv* env = AndroidRuntime::getJNIEnv();
1005 MtpResponseCode result = env->CallIntMethod(mDatabase, method_beginCopyObject,
1006 (jint)handle, (jint)newParent, (jint) newStorage);
1007
1008 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1009 return result;
1010}
1011
1012void MtpDatabase::endCopyObject(MtpObjectHandle handle, bool succeeded) {
1013 JNIEnv* env = AndroidRuntime::getJNIEnv();
1014 env->CallVoidMethod(mDatabase, method_endCopyObject, (jint)handle, (jboolean)succeeded);
1015
1016 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1017}
1018
1019
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001020struct PropertyTableEntry {
1021 MtpObjectProperty property;
1022 int type;
1023};
1024
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001025static const PropertyTableEntry kObjectPropertyTable[] = {
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001026 { MTP_PROPERTY_STORAGE_ID, MTP_TYPE_UINT32 },
1027 { MTP_PROPERTY_OBJECT_FORMAT, MTP_TYPE_UINT16 },
1028 { MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16 },
1029 { MTP_PROPERTY_OBJECT_SIZE, MTP_TYPE_UINT64 },
1030 { MTP_PROPERTY_OBJECT_FILE_NAME, MTP_TYPE_STR },
1031 { MTP_PROPERTY_DATE_MODIFIED, MTP_TYPE_STR },
1032 { MTP_PROPERTY_PARENT_OBJECT, MTP_TYPE_UINT32 },
1033 { MTP_PROPERTY_PERSISTENT_UID, MTP_TYPE_UINT128 },
1034 { MTP_PROPERTY_NAME, MTP_TYPE_STR },
Mike Lockwoodae078f72010-09-26 12:35:51 -04001035 { MTP_PROPERTY_DISPLAY_NAME, MTP_TYPE_STR },
1036 { MTP_PROPERTY_DATE_ADDED, MTP_TYPE_STR },
1037 { MTP_PROPERTY_ARTIST, MTP_TYPE_STR },
1038 { MTP_PROPERTY_ALBUM_NAME, MTP_TYPE_STR },
1039 { MTP_PROPERTY_ALBUM_ARTIST, MTP_TYPE_STR },
1040 { MTP_PROPERTY_TRACK, MTP_TYPE_UINT16 },
1041 { MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR },
1042 { MTP_PROPERTY_GENRE, MTP_TYPE_STR },
1043 { MTP_PROPERTY_COMPOSER, MTP_TYPE_STR },
1044 { MTP_PROPERTY_DURATION, MTP_TYPE_UINT32 },
1045 { MTP_PROPERTY_DESCRIPTION, MTP_TYPE_STR },
Mike Lockwood71827742015-01-23 10:50:08 -08001046 { MTP_PROPERTY_AUDIO_WAVE_CODEC, MTP_TYPE_UINT32 },
1047 { MTP_PROPERTY_BITRATE_TYPE, MTP_TYPE_UINT16 },
1048 { MTP_PROPERTY_AUDIO_BITRATE, MTP_TYPE_UINT32 },
1049 { MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_TYPE_UINT16 },
1050 { MTP_PROPERTY_SAMPLE_RATE, MTP_TYPE_UINT32 },
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001051};
1052
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001053static const PropertyTableEntry kDevicePropertyTable[] = {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001054 { MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER, MTP_TYPE_STR },
1055 { MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME, MTP_TYPE_STR },
1056 { MTP_DEVICE_PROPERTY_IMAGE_SIZE, MTP_TYPE_STR },
Mike Lockwood56c85242014-03-07 13:29:08 -08001057 { MTP_DEVICE_PROPERTY_BATTERY_LEVEL, MTP_TYPE_UINT8 },
Jerry Zhang13bb2f42016-12-14 15:39:29 -08001058 { MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE, MTP_TYPE_UINT32 },
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001059};
1060
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001061bool MtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001062 int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
1063 const PropertyTableEntry* entry = kObjectPropertyTable;
1064 for (int i = 0; i < count; i++, entry++) {
1065 if (entry->property == property) {
1066 type = entry->type;
1067 return true;
1068 }
1069 }
1070 return false;
1071}
1072
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001073bool MtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001074 int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
1075 const PropertyTableEntry* entry = kDevicePropertyTable;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001076 for (int i = 0; i < count; i++, entry++) {
1077 if (entry->property == property) {
1078 type = entry->type;
1079 return true;
1080 }
1081 }
1082 return false;
1083}
1084
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001085MtpObjectHandleList* MtpDatabase::getObjectReferences(MtpObjectHandle handle) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001086 JNIEnv* env = AndroidRuntime::getJNIEnv();
1087 jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
1088 (jint)handle);
1089 if (!array)
1090 return NULL;
1091 MtpObjectHandleList* list = new MtpObjectHandleList();
1092 jint* handles = env->GetIntArrayElements(array, 0);
1093 jsize length = env->GetArrayLength(array);
1094 for (int i = 0; i < length; i++)
Jerry Zhangd9f30052018-03-27 15:29:09 -07001095 list->push_back(handles[i]);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001096 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood88394712010-09-27 10:01:00 -04001097 env->DeleteLocalRef(array);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001098
1099 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1100 return list;
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001101}
1102
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001103MtpResponseCode MtpDatabase::setObjectReferences(MtpObjectHandle handle,
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001104 MtpObjectHandleList* references) {
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001105 JNIEnv* env = AndroidRuntime::getJNIEnv();
1106 int count = references->size();
1107 jintArray array = env->NewIntArray(count);
1108 if (!array) {
Steve Block3762c312012-01-06 19:20:56 +00001109 ALOGE("out of memory in setObjectReferences");
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001110 return false;
1111 }
1112 jint* handles = env->GetIntArrayElements(array, 0);
1113 for (int i = 0; i < count; i++)
1114 handles[i] = (*references)[i];
1115 env->ReleaseIntArrayElements(array, handles, 0);
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001116 MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001117 (jint)handle, array);
Mike Lockwood88394712010-09-27 10:01:00 -04001118 env->DeleteLocalRef(array);
Mike Lockwood9a2046f2010-08-03 15:30:09 -04001119
Mike Lockwood0a7fa0a2010-08-24 11:25:28 -04001120 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1121 return result;
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001122}
1123
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001124MtpProperty* MtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
Daichi Hirono486ad2e2016-02-29 17:28:47 +09001125 MtpObjectFormat format) {
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001126 static const int channelEnum[] = {
1127 1, // mono
1128 2, // stereo
1129 3, // 2.1
1130 4, // 3
1131 5, // 3.1
1132 6, // 4
1133 7, // 4.1
1134 8, // 5
1135 9, // 5.1
1136 };
1137 static const int bitrateEnum[] = {
1138 1, // fixed rate
1139 2, // variable rate
1140 };
1141
Mike Lockwood828d19d2010-08-10 15:20:35 -04001142 MtpProperty* result = NULL;
1143 switch (property) {
1144 case MTP_PROPERTY_OBJECT_FORMAT:
Mike Lockwood9b5e9c42010-12-07 18:53:50 -08001145 // use format as default value
1146 result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
1147 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001148 case MTP_PROPERTY_PROTECTION_STATUS:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001149 case MTP_PROPERTY_TRACK:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001150 result = new MtpProperty(property, MTP_TYPE_UINT16);
1151 break;
1152 case MTP_PROPERTY_STORAGE_ID:
1153 case MTP_PROPERTY_PARENT_OBJECT:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001154 case MTP_PROPERTY_DURATION:
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001155 case MTP_PROPERTY_AUDIO_WAVE_CODEC:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001156 result = new MtpProperty(property, MTP_TYPE_UINT32);
1157 break;
1158 case MTP_PROPERTY_OBJECT_SIZE:
1159 result = new MtpProperty(property, MTP_TYPE_UINT64);
1160 break;
1161 case MTP_PROPERTY_PERSISTENT_UID:
1162 result = new MtpProperty(property, MTP_TYPE_UINT128);
1163 break;
Mike Lockwoodd3bfecb2010-09-23 23:04:28 -04001164 case MTP_PROPERTY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001165 case MTP_PROPERTY_DISPLAY_NAME:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001166 case MTP_PROPERTY_ARTIST:
1167 case MTP_PROPERTY_ALBUM_NAME:
1168 case MTP_PROPERTY_ALBUM_ARTIST:
Mike Lockwoodae078f72010-09-26 12:35:51 -04001169 case MTP_PROPERTY_GENRE:
1170 case MTP_PROPERTY_COMPOSER:
1171 case MTP_PROPERTY_DESCRIPTION:
Mike Lockwood828d19d2010-08-10 15:20:35 -04001172 result = new MtpProperty(property, MTP_TYPE_STR);
1173 break;
Mike Lockwood5b19af02010-11-23 18:38:55 -05001174 case MTP_PROPERTY_DATE_MODIFIED:
1175 case MTP_PROPERTY_DATE_ADDED:
1176 case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
1177 result = new MtpProperty(property, MTP_TYPE_STR);
1178 result->setFormDateTime();
1179 break;
Mike Lockwood5ebac832010-10-12 11:33:47 -04001180 case MTP_PROPERTY_OBJECT_FILE_NAME:
Mike Lockwood6a6a3af2010-10-12 14:19:51 -04001181 // We allow renaming files and folders
1182 result = new MtpProperty(property, MTP_TYPE_STR, true);
Mike Lockwood5ebac832010-10-12 11:33:47 -04001183 break;
Mike Lockwood92b53bc2014-03-13 14:51:29 -07001184 case MTP_PROPERTY_BITRATE_TYPE:
1185 result = new MtpProperty(property, MTP_TYPE_UINT16);
1186 result->setFormEnum(bitrateEnum, sizeof(bitrateEnum)/sizeof(bitrateEnum[0]));
1187 break;
1188 case MTP_PROPERTY_AUDIO_BITRATE:
1189 result = new MtpProperty(property, MTP_TYPE_UINT32);
1190 result->setFormRange(1, 1536000, 1);
1191 break;
1192 case MTP_PROPERTY_NUMBER_OF_CHANNELS:
1193 result = new MtpProperty(property, MTP_TYPE_UINT16);
1194 result->setFormEnum(channelEnum, sizeof(channelEnum)/sizeof(channelEnum[0]));
1195 break;
1196 case MTP_PROPERTY_SAMPLE_RATE:
1197 result = new MtpProperty(property, MTP_TYPE_UINT32);
1198 result->setFormRange(8000, 48000, 1);
1199 break;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001200 }
1201
1202 return result;
1203}
1204
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001205MtpProperty* MtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001206 JNIEnv* env = AndroidRuntime::getJNIEnv();
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001207 MtpProperty* result = NULL;
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001208 bool writable = false;
1209
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001210 // get current value
1211 jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
1212 (jint)property, mLongBuffer, mStringBuffer);
1213 if (ret == MTP_RESPONSE_OK) {
1214 switch (property) {
1215 case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
1216 case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
1217 writable = true;
1218 // fall through
Ray Essick67004bc2018-11-01 13:57:11 -07001219 FALLTHROUGH_INTENDED;
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001220 case MTP_DEVICE_PROPERTY_IMAGE_SIZE:
1221 {
1222 result = new MtpProperty(property, MTP_TYPE_STR, writable);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001223 jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
1224 result->setCurrentValue(str);
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001225 // for read-only properties it is safe to assume current value is default value
1226 if (!writable)
1227 result->setDefaultValue(str);
Mike Lockwooda2a21282010-09-25 21:21:05 -04001228 env->ReleaseCharArrayElements(mStringBuffer, str, 0);
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001229 break;
Mike Lockwooda2a21282010-09-25 21:21:05 -04001230 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001231 case MTP_DEVICE_PROPERTY_BATTERY_LEVEL:
1232 {
1233 result = new MtpProperty(property, MTP_TYPE_UINT8);
1234 jlong* arr = env->GetLongArrayElements(mLongBuffer, 0);
1235 result->setFormRange(0, arr[1], 1);
1236 result->mCurrentValue.u.u8 = (uint8_t) arr[0];
1237 env->ReleaseLongArrayElements(mLongBuffer, arr, 0);
1238 break;
1239 }
1240 case MTP_DEVICE_PROPERTY_PERCEIVED_DEVICE_TYPE:
1241 {
1242 jlong* arr = env->GetLongArrayElements(mLongBuffer, 0);
1243 result = new MtpProperty(property, MTP_TYPE_UINT32);
1244 result->mCurrentValue.u.u32 = (uint32_t) arr[0];
1245 env->ReleaseLongArrayElements(mLongBuffer, arr, 0);
1246 break;
1247 }
1248 default:
1249 ALOGE("Unrecognized property %x", property);
Mike Lockwood56c85242014-03-07 13:29:08 -08001250 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001251 } else {
1252 ALOGE("unable to read device property, response: %04X", ret);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001253 }
1254
Mike Lockwoodea93fa12010-12-07 10:41:35 -08001255 checkAndClearExceptionFromCallback(env, __FUNCTION__);
Mike Lockwood59e3f0d2010-09-02 14:57:30 -04001256 return result;
Mike Lockwood828d19d2010-08-10 15:20:35 -04001257}
1258
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001259// ----------------------------------------------------------------------------
1260
1261static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001262android_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001263{
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001264 MtpDatabase* database = new MtpDatabase(env, thiz);
Ashok Bhate2e59322013-12-17 19:04:19 +00001265 env->SetLongField(thiz, field_context, (jlong)database);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001266 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1267}
1268
1269static void
Mike Lockwood0cd01362010-12-30 11:54:33 -05001270android_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001271{
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001272 MtpDatabase* database = (MtpDatabase *)env->GetLongField(thiz, field_context);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001273 database->cleanup(env);
1274 delete database;
Ashok Bhate2e59322013-12-17 19:04:19 +00001275 env->SetLongField(thiz, field_context, 0);
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001276 checkAndClearExceptionFromCallback(env, __FUNCTION__);
1277}
1278
Mike Lockwood31599912010-11-15 13:43:30 -05001279static jstring
Mark Salyzynaeb75fc2014-03-20 12:09:01 -07001280android_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
Mike Lockwood31599912010-11-15 13:43:30 -05001281{
Mike Lockwood31599912010-11-15 13:43:30 -05001282 char date[20];
1283 formatDateTime(seconds, date, sizeof(date));
1284 return env->NewStringUTF(date);
Mike Lockwood31599912010-11-15 13:43:30 -05001285}
1286
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001287// ----------------------------------------------------------------------------
1288
Daniel Micay76f6a862015-09-19 17:31:01 -04001289static const JNINativeMethod gMtpDatabaseMethods[] = {
Mike Lockwood0cd01362010-12-30 11:54:33 -05001290 {"native_setup", "()V", (void *)android_mtp_MtpDatabase_setup},
1291 {"native_finalize", "()V", (void *)android_mtp_MtpDatabase_finalize},
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001292};
1293
Daniel Micay76f6a862015-09-19 17:31:01 -04001294static const JNINativeMethod gMtpPropertyGroupMethods[] = {
Mike Lockwood31599912010-11-15 13:43:30 -05001295 {"format_date_time", "(J)Ljava/lang/String;",
Mike Lockwood0cd01362010-12-30 11:54:33 -05001296 (void *)android_mtp_MtpPropertyGroup_format_date_time},
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001297};
1298
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001299#define GET_METHOD_ID(name, jclass, signature) \
1300 method_##name = env->GetMethodID(jclass, #name, signature); \
1301 if (method_##name == NULL) { \
1302 ALOGE("Can't find " #name); \
1303 return -1; \
1304 } \
1305
Mike Lockwood0cd01362010-12-30 11:54:33 -05001306int register_android_mtp_MtpDatabase(JNIEnv *env)
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001307{
1308 jclass clazz;
1309
Mike Lockwood0cd01362010-12-30 11:54:33 -05001310 clazz = env->FindClass("android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001311 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001312 ALOGE("Can't find android/mtp/MtpDatabase");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001313 return -1;
1314 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001315 GET_METHOD_ID(beginSendObject, clazz, "(Ljava/lang/String;III)I");
1316 GET_METHOD_ID(endSendObject, clazz, "(IZ)V");
1317 GET_METHOD_ID(rescanFile, clazz, "(Ljava/lang/String;II)V");
1318 GET_METHOD_ID(getObjectList, clazz, "(III)[I");
1319 GET_METHOD_ID(getNumObjects, clazz, "(III)I");
1320 GET_METHOD_ID(getSupportedPlaybackFormats, clazz, "()[I");
1321 GET_METHOD_ID(getSupportedCaptureFormats, clazz, "()[I");
1322 GET_METHOD_ID(getSupportedObjectProperties, clazz, "(I)[I");
1323 GET_METHOD_ID(getSupportedDeviceProperties, clazz, "()[I");
1324 GET_METHOD_ID(setObjectProperty, clazz, "(IIJLjava/lang/String;)I");
1325 GET_METHOD_ID(getDeviceProperty, clazz, "(I[J[C)I");
1326 GET_METHOD_ID(setDeviceProperty, clazz, "(IJLjava/lang/String;)I");
1327 GET_METHOD_ID(getObjectPropertyList, clazz, "(IIIII)Landroid/mtp/MtpPropertyList;");
1328 GET_METHOD_ID(getObjectInfo, clazz, "(I[I[C[J)Z");
1329 GET_METHOD_ID(getObjectFilePath, clazz, "(I[C[J)I");
Marco Nelissen5954d212019-06-27 15:56:32 -07001330 GET_METHOD_ID(getThumbnailInfo, clazz, "(I[J)Z");
1331 GET_METHOD_ID(getThumbnailData, clazz, "(I)[B");
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001332 GET_METHOD_ID(beginDeleteObject, clazz, "(I)I");
1333 GET_METHOD_ID(endDeleteObject, clazz, "(IZ)V");
1334 GET_METHOD_ID(beginMoveObject, clazz, "(III)I");
1335 GET_METHOD_ID(endMoveObject, clazz, "(IIIIIZ)V");
1336 GET_METHOD_ID(beginCopyObject, clazz, "(III)I");
1337 GET_METHOD_ID(endCopyObject, clazz, "(IZ)V");
1338 GET_METHOD_ID(getObjectReferences, clazz, "(I)[I");
1339 GET_METHOD_ID(setObjectReferences, clazz, "(I[I)I");
Mike Lockwood2837eef2010-08-31 16:25:12 -04001340
Ashok Bhate2e59322013-12-17 19:04:19 +00001341 field_context = env->GetFieldID(clazz, "mNativeContext", "J");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001342 if (field_context == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001343 ALOGE("Can't find MtpDatabase.mNativeContext");
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001344 return -1;
1345 }
1346
Mike Lockwood0cd01362010-12-30 11:54:33 -05001347 clazz = env->FindClass("android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001348 if (clazz == NULL) {
Steve Block3762c312012-01-06 19:20:56 +00001349 ALOGE("Can't find android/mtp/MtpPropertyList");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001350 return -1;
1351 }
Jerry Zhangf9c5c252017-08-16 18:07:51 -07001352 GET_METHOD_ID(getCode, clazz, "()I");
1353 GET_METHOD_ID(getCount, clazz, "()I");
1354 GET_METHOD_ID(getObjectHandles, clazz, "()[I");
1355 GET_METHOD_ID(getPropertyCodes, clazz, "()[I");
1356 GET_METHOD_ID(getDataTypes, clazz, "()[I");
1357 GET_METHOD_ID(getLongValues, clazz, "()[J");
1358 GET_METHOD_ID(getStringValues, clazz, "()[Ljava/lang/String;");
Mike Lockwoode2ad6ec2010-10-14 18:03:25 -04001359
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001360 if (AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001361 "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
Mike Lockwood7d7fb632010-12-01 18:46:23 -05001362 return -1;
1363
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001364 return AndroidRuntime::registerNativeMethods(env,
Mike Lockwood0cd01362010-12-30 11:54:33 -05001365 "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
Mike Lockwoodd21eac92010-07-03 00:44:05 -04001366}