android_mtp_MtpDatabase.cpp revision 8937f1aa8b7ac50f60bf1f391382d4c4055c449d
1d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood/*
2d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Copyright (C) 2010 The Android Open Source Project
3d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
4d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License");
5d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * you may not use this file except in compliance with the License.
6d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * You may obtain a copy of the License at
7d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
8d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *      http://www.apache.org/licenses/LICENSE-2.0
9d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood *
10d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * Unless required by applicable law or agreed to in writing, software
11d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS,
12d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * See the License for the specific language governing permissions and
14d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood * limitations under the License.
15d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood */
16d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
17d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#define LOG_TAG "MtpDatabaseJNI"
18d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include "utils/Log.h"
19d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
20d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include <assert.h>
21aeb75fc5a3dc51bf9d5220647a68c48644c66ea8Mark Salyzyn#include <fcntl.h>
22aeb75fc5a3dc51bf9d5220647a68c48644c66ea8Mark Salyzyn#include <inttypes.h>
23d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include <limits.h>
24aeb75fc5a3dc51bf9d5220647a68c48644c66ea8Mark Salyzyn#include <stdio.h>
25d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include <unistd.h>
26d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
27d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include "jni.h"
28d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include "JNIHelp.h"
29d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include "android_runtime/AndroidRuntime.h"
3087eac99a21772ae56018cb81db6966557b459554Ruben Brunk#include "android_runtime/Log.h"
31d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
32d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include "MtpDatabase.h"
33d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include "MtpDataPacket.h"
349df53fae3afd1c6b5278216be2fd33a255602aefMike Lockwood#include "MtpObjectInfo.h"
35828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood#include "MtpProperty.h"
3659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood#include "MtpStringBuffer.h"
37d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include "MtpUtils.h"
38d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood#include "mtp.h"
39d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
40c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwoodextern "C" {
413cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen#include "libexif/exif-content.h"
423cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen#include "libexif/exif-data.h"
433cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen#include "libexif/exif-tag.h"
443cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen#include "libexif/exif-utils.h"
45c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood}
46c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood
47d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodusing namespace android;
48d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
49d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood// ----------------------------------------------------------------------------
50d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
51d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodstatic jmethodID method_beginSendObject;
52d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodstatic jmethodID method_endSendObject;
53d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodstatic jmethodID method_getObjectList;
547a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwoodstatic jmethodID method_getNumObjects;
554b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwoodstatic jmethodID method_getSupportedPlaybackFormats;
564b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwoodstatic jmethodID method_getSupportedCaptureFormats;
574b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwoodstatic jmethodID method_getSupportedObjectProperties;
584b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwoodstatic jmethodID method_getSupportedDeviceProperties;
59828d19dd96b05fa99abdc517701e5366543c324fMike Lockwoodstatic jmethodID method_setObjectProperty;
6059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodstatic jmethodID method_getDeviceProperty;
6159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodstatic jmethodID method_setDeviceProperty;
62e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodstatic jmethodID method_getObjectPropertyList;
63d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodstatic jmethodID method_getObjectInfo;
64d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodstatic jmethodID method_getObjectFilePath;
65d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodstatic jmethodID method_deleteFile;
669a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodstatic jmethodID method_getObjectReferences;
679a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwoodstatic jmethodID method_setObjectReferences;
682837eefc5459427138c080d445bb491c75630163Mike Lockwoodstatic jmethodID method_sessionStarted;
692837eefc5459427138c080d445bb491c75630163Mike Lockwoodstatic jmethodID method_sessionEnded;
702837eefc5459427138c080d445bb491c75630163Mike Lockwood
71d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodstatic jfieldID field_context;
7256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwoodstatic jfieldID field_batteryLevel;
7356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwoodstatic jfieldID field_batteryScale;
74d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
75e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood// MtpPropertyList fields
76e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodstatic jfieldID field_mCount;
77e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodstatic jfieldID field_mResult;
78e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodstatic jfieldID field_mObjectHandles;
79e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodstatic jfieldID field_mPropertyCodes;
80e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodstatic jfieldID field_mDataTypes;
81e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodstatic jfieldID field_mLongValues;
82e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodstatic jfieldID field_mStringValues;
83e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
84e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
85d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike LockwoodMtpDatabase* getMtpDatabase(JNIEnv *env, jobject database) {
86e2e59326f13cf291bf5b37989390fd2a55a94f0cAshok Bhat    return (MtpDatabase *)env->GetLongField(database, field_context);
87d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
88d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
89d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood// ----------------------------------------------------------------------------
90d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
91d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodclass MyMtpDatabase : public MtpDatabase {
92d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodprivate:
93d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jobject         mDatabase;
94d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jintArray       mIntBuffer;
95d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jlongArray      mLongBuffer;
96d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jcharArray      mStringBuffer;
97d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
98d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodpublic:
99d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                    MyMtpDatabase(JNIEnv *env, jobject client);
100d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    virtual                         ~MyMtpDatabase();
101d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    void                            cleanup(JNIEnv *env);
102d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
103d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    virtual MtpObjectHandle         beginSendObject(const char* path,
104d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpObjectFormat format,
105d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpObjectHandle parent,
106d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpStorageID storage,
107d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            uint64_t size,
108d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            time_t modified);
109d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
110d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    virtual void                    endSendObject(const char* path,
111d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                                            MtpObjectHandle handle,
112d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                                            MtpObjectFormat format,
113d815f79766984fce499e147ecbacc01914683f74Mike Lockwood                                            bool succeeded);
114d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
115d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    virtual MtpObjectHandleList*    getObjectList(MtpStorageID storageID,
116d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                    MtpObjectFormat format,
117d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                    MtpObjectHandle parent);
118d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1197a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    virtual int                     getNumObjects(MtpStorageID storageID,
1207a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                                            MtpObjectFormat format,
1217a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                                            MtpObjectHandle parent);
1227a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood
1234b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    // callee should delete[] the results from these
1244b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    // results can be NULL
1254b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    virtual MtpObjectFormatList*    getSupportedPlaybackFormats();
1264b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    virtual MtpObjectFormatList*    getSupportedCaptureFormats();
1274b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    virtual MtpObjectPropertyList*  getSupportedObjectProperties(MtpObjectFormat format);
1284b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    virtual MtpDevicePropertyList*  getSupportedDeviceProperties();
1294b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
130828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    virtual MtpResponseCode         getObjectPropertyValue(MtpObjectHandle handle,
131d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpObjectProperty property,
132d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpDataPacket& packet);
133d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
134828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    virtual MtpResponseCode         setObjectPropertyValue(MtpObjectHandle handle,
135828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpObjectProperty property,
136828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpDataPacket& packet);
137828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
138828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    virtual MtpResponseCode         getDevicePropertyValue(MtpDeviceProperty property,
139828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpDataPacket& packet);
140828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
141828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    virtual MtpResponseCode         setDevicePropertyValue(MtpDeviceProperty property,
142828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpDataPacket& packet);
143828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
144828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    virtual MtpResponseCode         resetDeviceProperty(MtpDeviceProperty property);
145828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
146e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    virtual MtpResponseCode         getObjectPropertyList(MtpObjectHandle handle,
1477d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                                            uint32_t format, uint32_t property,
148e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                                            int groupCode, int depth,
149e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                                            MtpDataPacket& packet);
150e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
151d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    virtual MtpResponseCode         getObjectInfo(MtpObjectHandle handle,
1529df53fae3afd1c6b5278216be2fd33a255602aefMike Lockwood                                            MtpObjectInfo& info);
153d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
154c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    virtual void*                   getThumbnail(MtpObjectHandle handle, size_t& outThumbSize);
155c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood
15659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    virtual MtpResponseCode         getObjectFilePath(MtpObjectHandle handle,
157365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                                            MtpString& outFilePath,
158365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                                            int64_t& outFileLength,
159365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                                            MtpObjectFormat& outFormat);
16059c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    virtual MtpResponseCode         deleteFile(MtpObjectHandle handle);
161d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
16259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    bool                            getObjectPropertyInfo(MtpObjectProperty property, int& type);
16359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    bool                            getDevicePropertyInfo(MtpDeviceProperty property, int& type);
1649a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
1659a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    virtual MtpObjectHandleList*    getObjectReferences(MtpObjectHandle handle);
1669a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
1679a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    virtual MtpResponseCode         setObjectReferences(MtpObjectHandle handle,
1689a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                                            MtpObjectHandleList* references);
169828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
170828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    virtual MtpProperty*            getObjectPropertyDesc(MtpObjectProperty property,
171828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpObjectFormat format);
172828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
173828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    virtual MtpProperty*            getDevicePropertyDesc(MtpDeviceProperty property);
1742837eefc5459427138c080d445bb491c75630163Mike Lockwood
1752837eefc5459427138c080d445bb491c75630163Mike Lockwood    virtual void                    sessionStarted();
1762837eefc5459427138c080d445bb491c75630163Mike Lockwood
1772837eefc5459427138c080d445bb491c75630163Mike Lockwood    virtual void                    sessionEnded();
178d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood};
179d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1800a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood// ----------------------------------------------------------------------------
1810a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
1820a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwoodstatic void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
1830a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    if (env->ExceptionCheck()) {
1843762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("An exception was thrown by callback '%s'.", methodName);
1850a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood        LOGE_EX(env);
1860a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood        env->ExceptionClear();
1870a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    }
1880a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood}
1890a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
1900a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood// ----------------------------------------------------------------------------
1910a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
192d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike LockwoodMyMtpDatabase::MyMtpDatabase(JNIEnv *env, jobject client)
193d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    :   mDatabase(env->NewGlobalRef(client)),
194d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mIntBuffer(NULL),
195d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mLongBuffer(NULL),
196d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        mStringBuffer(NULL)
197d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood{
198d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    // create buffers for out arguments
199d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    // we don't need to be thread-safe so this is OK
20015dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes    jintArray intArray = env->NewIntArray(3);
20115dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes    if (!intArray) {
20215dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes        return; // Already threw.
20315dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes    }
204d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    mIntBuffer = (jintArray)env->NewGlobalRef(intArray);
20515dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes    jlongArray longArray = env->NewLongArray(2);
20615dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes    if (!longArray) {
20715dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes        return; // Already threw.
20815dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes    }
209d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    mLongBuffer = (jlongArray)env->NewGlobalRef(longArray);
21063ffd78aaab0b0d04012312f0378b0c73b737a2aMike Lockwood    // Needs to be long enough to hold a file path for getObjectFilePath()
21163ffd78aaab0b0d04012312f0378b0c73b737a2aMike Lockwood    jcharArray charArray = env->NewCharArray(PATH_MAX + 1);
21215dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes    if (!charArray) {
21315dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes        return; // Already threw.
21415dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes    }
215d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    mStringBuffer = (jcharArray)env->NewGlobalRef(charArray);
216d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
217d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
218d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodvoid MyMtpDatabase::cleanup(JNIEnv *env) {
219d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->DeleteGlobalRef(mDatabase);
220d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->DeleteGlobalRef(mIntBuffer);
221d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->DeleteGlobalRef(mLongBuffer);
222d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->DeleteGlobalRef(mStringBuffer);
223d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
224d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
225d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike LockwoodMyMtpDatabase::~MyMtpDatabase() {
226d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
227d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
228d815f79766984fce499e147ecbacc01914683f74Mike LockwoodMtpObjectHandle MyMtpDatabase::beginSendObject(const char* path,
229d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpObjectFormat format,
230d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpObjectHandle parent,
231d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpStorageID storage,
232d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            uint64_t size,
233d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            time_t modified) {
234d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
2358839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    jstring pathStr = env->NewStringUTF(path);
2360a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    MtpObjectHandle result = env->CallIntMethod(mDatabase, method_beginSendObject,
2378839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood            pathStr, (jint)format, (jint)parent, (jint)storage,
2380a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood            (jlong)size, (jlong)modified);
2390a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
2408839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    if (pathStr)
2418839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood        env->DeleteLocalRef(pathStr);
2420a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
2430a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return result;
244d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
245d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
246d815f79766984fce499e147ecbacc01914683f74Mike Lockwoodvoid MyMtpDatabase::endSendObject(const char* path, MtpObjectHandle handle,
2477a0bd17bceaf3efc3732e30c538fae420d3b742cMike Lockwood                                MtpObjectFormat format, bool succeeded) {
248d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
2498839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    jstring pathStr = env->NewStringUTF(path);
2508839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    env->CallVoidMethod(mDatabase, method_endSendObject, pathStr,
2517a0bd17bceaf3efc3732e30c538fae420d3b742cMike Lockwood                        (jint)handle, (jint)format, (jboolean)succeeded);
2520a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
2538839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    if (pathStr)
2548839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood        env->DeleteLocalRef(pathStr);
2550a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
256d815f79766984fce499e147ecbacc01914683f74Mike Lockwood}
257d815f79766984fce499e147ecbacc01914683f74Mike Lockwood
258d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike LockwoodMtpObjectHandleList* MyMtpDatabase::getObjectList(MtpStorageID storageID,
259d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                    MtpObjectFormat format,
260d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                    MtpObjectHandle parent) {
261d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
262d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectList,
263d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                (jint)storageID, (jint)format, (jint)parent);
264d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    if (!array)
265d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return NULL;
266d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    MtpObjectHandleList* list = new MtpObjectHandleList();
267d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jint* handles = env->GetIntArrayElements(array, 0);
268d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jsize length = env->GetArrayLength(array);
2697a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    for (int i = 0; i < length; i++)
270d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        list->push(handles[i]);
2710a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    env->ReleaseIntArrayElements(array, handles, 0);
2728839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    env->DeleteLocalRef(array);
2730a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
2740a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
2750a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return list;
276d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
277d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
2787a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwoodint MyMtpDatabase::getNumObjects(MtpStorageID storageID,
2797a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                                MtpObjectFormat format,
2807a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                                MtpObjectHandle parent) {
2817a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
2820a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    int result = env->CallIntMethod(mDatabase, method_getNumObjects,
2837a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood                (jint)storageID, (jint)format, (jint)parent);
2840a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
2850a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
2860a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return result;
2877a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood}
2887a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood
2894b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike LockwoodMtpObjectFormatList* MyMtpDatabase::getSupportedPlaybackFormats() {
2904b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
2914b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
2924b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood            method_getSupportedPlaybackFormats);
2934b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    if (!array)
2944b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return NULL;
2954b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    MtpObjectFormatList* list = new MtpObjectFormatList();
2964b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jint* formats = env->GetIntArrayElements(array, 0);
2974b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jsize length = env->GetArrayLength(array);
2984b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    for (int i = 0; i < length; i++)
2994b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        list->push(formats[i]);
3000a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    env->ReleaseIntArrayElements(array, formats, 0);
3018839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    env->DeleteLocalRef(array);
3020a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
3030a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
3040a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return list;
3054b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood}
3064b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
3074b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike LockwoodMtpObjectFormatList* MyMtpDatabase::getSupportedCaptureFormats() {
3084b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
3094b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
3104b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood            method_getSupportedCaptureFormats);
3114b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    if (!array)
3124b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return NULL;
3134b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    MtpObjectFormatList* list = new MtpObjectFormatList();
3144b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jint* formats = env->GetIntArrayElements(array, 0);
3154b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jsize length = env->GetArrayLength(array);
3164b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    for (int i = 0; i < length; i++)
3174b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        list->push(formats[i]);
3180a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    env->ReleaseIntArrayElements(array, formats, 0);
3198839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    env->DeleteLocalRef(array);
3200a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
3210a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
3220a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return list;
3234b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood}
3244b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
3254b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike LockwoodMtpObjectPropertyList* MyMtpDatabase::getSupportedObjectProperties(MtpObjectFormat format) {
3264b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
3274b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
3284b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood            method_getSupportedObjectProperties, (jint)format);
3294b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    if (!array)
3304b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return NULL;
3314b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    MtpObjectPropertyList* list = new MtpObjectPropertyList();
3324b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jint* properties = env->GetIntArrayElements(array, 0);
3334b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jsize length = env->GetArrayLength(array);
3344b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    for (int i = 0; i < length; i++)
3354b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        list->push(properties[i]);
3360a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    env->ReleaseIntArrayElements(array, properties, 0);
3378839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    env->DeleteLocalRef(array);
3380a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
3390a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
3400a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return list;
3414b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood}
3424b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
3434b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike LockwoodMtpDevicePropertyList* MyMtpDatabase::getSupportedDeviceProperties() {
3444b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
3454b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jintArray array = (jintArray)env->CallObjectMethod(mDatabase,
3464b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood            method_getSupportedDeviceProperties);
3474b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    if (!array)
3484b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return NULL;
3494b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    MtpDevicePropertyList* list = new MtpDevicePropertyList();
3504b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jint* properties = env->GetIntArrayElements(array, 0);
3514b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    jsize length = env->GetArrayLength(array);
3524b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    for (int i = 0; i < length; i++)
3534b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        list->push(properties[i]);
3540a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    env->ReleaseIntArrayElements(array, properties, 0);
3558839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    env->DeleteLocalRef(array);
3560a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
3570a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
3580a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return list;
3594b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood}
3604b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood
361828d19dd96b05fa99abdc517701e5366543c324fMike LockwoodMtpResponseCode MyMtpDatabase::getObjectPropertyValue(MtpObjectHandle handle,
362d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpObjectProperty property,
363d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                                            MtpDataPacket& packet) {
364d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
365e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
3667d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                (jlong)handle, 0, (jlong)property, 0, 0);
367e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    MtpResponseCode result = env->GetIntField(list, field_mResult);
368e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    int count = env->GetIntField(list, field_mCount);
369e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (result == MTP_RESPONSE_OK && count != 1)
370e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        result = MTP_RESPONSE_GENERAL_ERROR;
371e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
372e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (result == MTP_RESPONSE_OK) {
373e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
374e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
375e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
376e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
377e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
378e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
379e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
380e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
381e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
382e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
383e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
384e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        int type = dataTypes[0];
385e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jlong longValue = (longValues ? longValues[0] : 0);
386e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
387e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // special case date properties, which are strings to MTP
388e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // but stored internally as a uint64
389e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (property == MTP_PROPERTY_DATE_MODIFIED || property == MTP_PROPERTY_DATE_ADDED) {
390e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            char    date[20];
391e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            formatDateTime(longValue, date, sizeof(date));
392e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            packet.putString(date);
393e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            goto out;
394e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
395e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        // release date is stored internally as just the year
396e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (property == MTP_PROPERTY_ORIGINAL_RELEASE_DATE) {
397e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            char    date[20];
398aeb75fc5a3dc51bf9d5220647a68c48644c66ea8Mark Salyzyn            snprintf(date, sizeof(date), "%04" PRId64 "0101T000000", longValue);
399e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            packet.putString(date);
400e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            goto out;
401e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
402828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
403e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        switch (type) {
404e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_INT8:
405e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putInt8(longValue);
406e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
407e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_UINT8:
408e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putUInt8(longValue);
409e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
410e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_INT16:
411e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putInt16(longValue);
412e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
413e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_UINT16:
414e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putUInt16(longValue);
415e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
416e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_INT32:
417e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putInt32(longValue);
418e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
419e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_UINT32:
420e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putUInt32(longValue);
421e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
422e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_INT64:
423e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putInt64(longValue);
424e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
425e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_UINT64:
426e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putUInt64(longValue);
427e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
428e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_INT128:
429e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                packet.putInt128(longValue);
430e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
431e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_UINT128:
4328937f1aa8b7ac50f60bf1f391382d4c4055c449dWanwu Peng                packet.putUInt128(longValue);
433e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
434e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            case MTP_TYPE_STR:
435e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            {
436e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                jstring stringValue = (jstring)env->GetObjectArrayElement(stringValuesArray, 0);
43717a24c58bb2e86719f003c80f682beb66803f24dMartin Blumenstingl                const char* str = (stringValue ? env->GetStringUTFChars(stringValue, NULL) : NULL);
438e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                if (stringValue) {
439e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putString(str);
440e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    env->ReleaseStringUTFChars(stringValue, str);
441e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                } else {
442e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putEmptyString();
443e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                }
44417a24c58bb2e86719f003c80f682beb66803f24dMartin Blumenstingl                env->DeleteLocalRef(stringValue);
445e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                break;
446e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood             }
447e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            default:
4483762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("unsupported type in getObjectPropertyValue\n");
449e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
450e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
451e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwoodout:
452e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
453e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
454e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
455e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (longValues)
456e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
457e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
458e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->DeleteLocalRef(objectHandlesArray);
459e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->DeleteLocalRef(propertyCodesArray);
460e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->DeleteLocalRef(dataTypesArray);
461e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (longValuesArray)
462e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            env->DeleteLocalRef(longValuesArray);
463e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (stringValuesArray)
464e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            env->DeleteLocalRef(stringValuesArray);
465d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
4660a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
467e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    env->DeleteLocalRef(list);
4680a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
469e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    return result;
470d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
471d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
4729c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwoodstatic bool readLongValue(int type, MtpDataPacket& packet, jlong& longValue) {
4739c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    switch (type) {
4749c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        case MTP_TYPE_INT8: {
4759c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            int8_t temp;
4769c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            if (!packet.getInt8(temp)) return false;
4779c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            longValue = temp;
4789c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            break;
4799c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        }
4809c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        case MTP_TYPE_UINT8: {
4819c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            uint8_t temp;
4829c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            if (!packet.getUInt8(temp)) return false;
4839c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            longValue = temp;
4849c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            break;
4859c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        }
4869c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        case MTP_TYPE_INT16: {
4879c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            int16_t temp;
4889c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            if (!packet.getInt16(temp)) return false;
4899c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            longValue = temp;
4909c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            break;
4919c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        }
4929c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        case MTP_TYPE_UINT16: {
4939c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            uint16_t temp;
4949c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            if (!packet.getUInt16(temp)) return false;
4959c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            longValue = temp;
4969c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            break;
4979c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        }
4989c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        case MTP_TYPE_INT32: {
4999c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            int32_t temp;
5009c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            if (!packet.getInt32(temp)) return false;
5019c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            longValue = temp;
5029c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            break;
5039c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        }
5049c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        case MTP_TYPE_UINT32: {
5059c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            uint32_t temp;
5069c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            if (!packet.getUInt32(temp)) return false;
5079c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            longValue = temp;
5089c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            break;
5099c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        }
5109c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        case MTP_TYPE_INT64: {
5119c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            int64_t temp;
5129c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            if (!packet.getInt64(temp)) return false;
5139c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            longValue = temp;
5149c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            break;
5159c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        }
5169c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        case MTP_TYPE_UINT64: {
5179c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            uint64_t temp;
5189c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            if (!packet.getUInt64(temp)) return false;
5199c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            longValue = temp;
5209c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            break;
5219c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        }
5229c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        default:
5239c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            ALOGE("unsupported type in readLongValue");
5249c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood            return false;
5259c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    }
5269c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    return true;
5279c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood}
5289c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood
529828d19dd96b05fa99abdc517701e5366543c324fMike LockwoodMtpResponseCode MyMtpDatabase::setObjectPropertyValue(MtpObjectHandle handle,
530828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpObjectProperty property,
531828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpDataPacket& packet) {
53259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    int         type;
53359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
53459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    if (!getObjectPropertyInfo(property, type))
53559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return MTP_RESPONSE_OBJECT_PROP_NOT_SUPPORTED;
53659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
53759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
53859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    jlong longValue = 0;
53959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    jstring stringValue = NULL;
5409c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    MtpResponseCode result = MTP_RESPONSE_INVALID_OBJECT_PROP_FORMAT;
54159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
5429c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    if (type == MTP_TYPE_STR) {
5439c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        MtpStringBuffer buffer;
5449c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        if (!packet.getString(buffer)) goto fail;
5459c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        stringValue = env->NewStringUTF((const char *)buffer);
5469c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    } else {
5479c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        if (!readLongValue(type, packet, longValue)) goto fail;
54859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
54959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
5509c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    result = env->CallIntMethod(mDatabase, method_setObjectProperty,
55159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                (jint)handle, (jint)property, longValue, stringValue);
5528839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    if (stringValue)
5538839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood        env->DeleteLocalRef(stringValue);
55459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
5559c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwoodfail:
55659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
55759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    return result;
558828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood}
559828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
560828d19dd96b05fa99abdc517701e5366543c324fMike LockwoodMtpResponseCode MyMtpDatabase::getDevicePropertyValue(MtpDeviceProperty property,
561828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpDataPacket& packet) {
56256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
56359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
56456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    if (property == MTP_DEVICE_PROPERTY_BATTERY_LEVEL) {
56556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        // special case - implemented here instead of Java
56656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        packet.putUInt8((uint8_t)env->GetIntField(mDatabase, field_batteryLevel));
56756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        return MTP_RESPONSE_OK;
56856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    } else {
56956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        int type;
57056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood
57156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        if (!getDevicePropertyInfo(property, type))
57256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
57356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood
57456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        jint result = env->CallIntMethod(mDatabase, method_getDeviceProperty,
57556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                    (jint)property, mLongBuffer, mStringBuffer);
57656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        if (result != MTP_RESPONSE_OK) {
57756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            checkAndClearExceptionFromCallback(env, __FUNCTION__);
57856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            return result;
57956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        }
58059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
58156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
58256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        jlong longValue = longValues[0];
58356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
58459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
58556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        switch (type) {
58656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_INT8:
58756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putInt8(longValue);
58856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
58956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_UINT8:
59056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putUInt8(longValue);
59156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
59256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_INT16:
59356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putInt16(longValue);
59456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
59556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_UINT16:
59656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putUInt16(longValue);
59756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
59856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_INT32:
59956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putInt32(longValue);
60056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
60156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_UINT32:
60256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putUInt32(longValue);
60356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
60456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_INT64:
60556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putInt64(longValue);
60656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
60756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_UINT64:
60856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putUInt64(longValue);
60956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
61056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_INT128:
61156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putInt128(longValue);
61256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
61356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_UINT128:
61456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putInt128(longValue);
61556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
61656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            case MTP_TYPE_STR:
61756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            {
61856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
61956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                packet.putString(str);
62056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                env->ReleaseCharArrayElements(mStringBuffer, str, 0);
62156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                break;
62256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood             }
62356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            default:
62456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                ALOGE("unsupported type in getDevicePropertyValue\n");
62556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood                return MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
62656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        }
62759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
62856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        checkAndClearExceptionFromCallback(env, __FUNCTION__);
62956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        return MTP_RESPONSE_OK;
63059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
631828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood}
632828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
633828d19dd96b05fa99abdc517701e5366543c324fMike LockwoodMtpResponseCode MyMtpDatabase::setDevicePropertyValue(MtpDeviceProperty property,
634828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpDataPacket& packet) {
63559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    int         type;
63659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
63759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    if (!getDevicePropertyInfo(property, type))
63859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return MTP_RESPONSE_DEVICE_PROP_NOT_SUPPORTED;
63959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
64059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
64159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    jlong longValue = 0;
64259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    jstring stringValue = NULL;
6439c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    MtpResponseCode result = MTP_RESPONSE_INVALID_DEVICE_PROP_FORMAT;
64459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
6459c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    if (type == MTP_TYPE_STR) {
6469c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        MtpStringBuffer buffer;
6479c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        if (!packet.getString(buffer)) goto fail;
6489c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        stringValue = env->NewStringUTF((const char *)buffer);
6499c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    } else {
6509c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood        if (!readLongValue(type, packet, longValue)) goto fail;
65159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
65259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
6539c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwood    result = env->CallIntMethod(mDatabase, method_setDeviceProperty,
65459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood                (jint)property, longValue, stringValue);
6558839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    if (stringValue)
6568839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood        env->DeleteLocalRef(stringValue);
65759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
6589c803fa52606aeb27d4d098161722fb111dd1b23Mike Lockwoodfail:
65959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
66059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    return result;
661828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood}
662828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
663aeb75fc5a3dc51bf9d5220647a68c48644c66ea8Mark SalyzynMtpResponseCode MyMtpDatabase::resetDeviceProperty(MtpDeviceProperty /*property*/) {
664828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    return -1;
665828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood}
666828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
667e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike LockwoodMtpResponseCode MyMtpDatabase::getObjectPropertyList(MtpObjectHandle handle,
6687d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                                            uint32_t format, uint32_t property,
669e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                                            int groupCode, int depth,
670e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                                            MtpDataPacket& packet) {
671e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
672e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    jobject list = env->CallObjectMethod(mDatabase, method_getObjectPropertyList,
6737d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood                (jlong)handle, (jint)format, (jlong)property, (jint)groupCode, (jint)depth);
6747d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
6757d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    if (!list)
6767d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        return MTP_RESPONSE_GENERAL_ERROR;
677e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    int count = env->GetIntField(list, field_mCount);
678e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    MtpResponseCode result = env->GetIntField(list, field_mResult);
679e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
680e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    packet.putUInt32(count);
681e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (count > 0) {
682e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jintArray objectHandlesArray = (jintArray)env->GetObjectField(list, field_mObjectHandles);
683e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jintArray propertyCodesArray = (jintArray)env->GetObjectField(list, field_mPropertyCodes);
684e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jintArray dataTypesArray = (jintArray)env->GetObjectField(list, field_mDataTypes);
685e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jlongArray longValuesArray = (jlongArray)env->GetObjectField(list, field_mLongValues);
686e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jobjectArray stringValuesArray = (jobjectArray)env->GetObjectField(list, field_mStringValues);
687e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
688e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jint* objectHandles = env->GetIntArrayElements(objectHandlesArray, 0);
689e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jint* propertyCodes = env->GetIntArrayElements(propertyCodesArray, 0);
690e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jint* dataTypes = env->GetIntArrayElements(dataTypesArray, 0);
691e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        jlong* longValues = (longValuesArray ? env->GetLongArrayElements(longValuesArray, 0) : NULL);
692e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
693e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        for (int i = 0; i < count; i++) {
694e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            packet.putUInt32(objectHandles[i]);
695e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            packet.putUInt16(propertyCodes[i]);
696e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            int type = dataTypes[i];
697e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            packet.putUInt16(type);
698e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
699e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            switch (type) {
700e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_INT8:
701e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putInt8(longValues[i]);
702e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
703e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_UINT8:
704e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putUInt8(longValues[i]);
705e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
706e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_INT16:
707e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putInt16(longValues[i]);
708e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
709e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_UINT16:
710e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putUInt16(longValues[i]);
711e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
712e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_INT32:
713e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putInt32(longValues[i]);
714e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
715e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_UINT32:
716e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putUInt32(longValues[i]);
717e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
718e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_INT64:
719e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putInt64(longValues[i]);
720e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
721e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_UINT64:
722e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putUInt64(longValues[i]);
723e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
724e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_INT128:
725e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putInt128(longValues[i]);
726e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
727e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_UINT128:
728e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    packet.putUInt128(longValues[i]);
729e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
730e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                case MTP_TYPE_STR: {
731e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    jstring value = (jstring)env->GetObjectArrayElement(stringValuesArray, i);
7322711e494caf9ec665c46258feb36c9654290f6e0Mike Lockwood                    const char *valueStr = (value ? env->GetStringUTFChars(value, NULL) : NULL);
733e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    if (valueStr) {
734e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        packet.putString(valueStr);
735e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        env->ReleaseStringUTFChars(value, valueStr);
736e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    } else {
737e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                        packet.putEmptyString();
738e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    }
739e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    env->DeleteLocalRef(value);
740e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
741e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                }
742e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                default:
7433762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                    ALOGE("bad or unsupported data type in MyMtpDatabase::getObjectPropertyList");
744e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood                    break;
745e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            }
746e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        }
747e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
748e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->ReleaseIntArrayElements(objectHandlesArray, objectHandles, 0);
749e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->ReleaseIntArrayElements(propertyCodesArray, propertyCodes, 0);
750e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->ReleaseIntArrayElements(dataTypesArray, dataTypes, 0);
751e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (longValues)
752e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            env->ReleaseLongArrayElements(longValuesArray, longValues, 0);
753e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
754e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->DeleteLocalRef(objectHandlesArray);
755e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->DeleteLocalRef(propertyCodesArray);
756e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        env->DeleteLocalRef(dataTypesArray);
757e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (longValuesArray)
758e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            env->DeleteLocalRef(longValuesArray);
759e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        if (stringValuesArray)
760e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood            env->DeleteLocalRef(stringValuesArray);
761e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
762e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
763e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    env->DeleteLocalRef(list);
764e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
765e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    return result;
766e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood}
767e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
7685a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampestatic void foreachentry(ExifEntry *entry, void* /* user */) {
7693cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen    char buf[1024];
7703cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen    ALOGI("entry %x, format %d, size %d: %s",
7713cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            entry->tag, entry->format, entry->size, exif_entry_get_value(entry, buf, sizeof(buf)));
7723cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen}
7733cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen
7743cd393c5051ce26c8030736f5524962d98abe849Marco Nelissenstatic void foreachcontent(ExifContent *content, void *user) {
7753cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen    ALOGI("content %d", exif_content_get_ifd(content));
7763cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen    exif_content_foreach_entry(content, foreachentry, user);
7773cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen}
7783cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen
7793cd393c5051ce26c8030736f5524962d98abe849Marco Nelissenstatic long getLongFromExifEntry(ExifEntry *e) {
7803cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen    ExifByteOrder o = exif_data_get_byte_order(e->parent->parent);
7813cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen    return exif_get_long(e->data, o);
7823cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen}
7833cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen
784d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike LockwoodMtpResponseCode MyMtpDatabase::getObjectInfo(MtpObjectHandle handle,
7859df53fae3afd1c6b5278216be2fd33a255602aefMike Lockwood                                            MtpObjectInfo& info) {
786f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    MtpString       path;
787f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    int64_t         length;
788f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    MtpObjectFormat format;
789f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood
790f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    MtpResponseCode result = getObjectFilePath(handle, path, length, format);
791f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    if (result != MTP_RESPONSE_OK) {
792f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood        return result;
793f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    }
794f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    info.mCompressedSize = (length > 0xFFFFFFFFLL ? 0xFFFFFFFF : (uint32_t)length);
795d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
796d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
797f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    if (!env->CallBooleanMethod(mDatabase, method_getObjectInfo,
798f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood                (jint)handle, mIntBuffer, mStringBuffer, mLongBuffer)) {
799d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return MTP_RESPONSE_INVALID_OBJECT_HANDLE;
800f6f16614574767263fcd0073f72c099edaca0607Mike Lockwood    }
801d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
802d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jint* intValues = env->GetIntArrayElements(mIntBuffer, 0);
8039df53fae3afd1c6b5278216be2fd33a255602aefMike Lockwood    info.mStorageID = intValues[0];
8049df53fae3afd1c6b5278216be2fd33a255602aefMike Lockwood    info.mFormat = intValues[1];
8059df53fae3afd1c6b5278216be2fd33a255602aefMike Lockwood    info.mParent = intValues[2];
806d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->ReleaseIntArrayElements(mIntBuffer, intValues, 0);
807d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
808d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
8091341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood    info.mDateCreated = longValues[0];
8101341f1eee3493fc5e263494acb8adebb6f0180b6Mike Lockwood    info.mDateModified = longValues[1];
811d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
812d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
8135a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe    if ((false)) {
8145a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe        info.mAssociationType = (format == MTP_FORMAT_ASSOCIATION ?
8155a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe                                MTP_ASSOCIATION_TYPE_GENERIC_FOLDER :
8165a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe                                MTP_ASSOCIATION_TYPE_UNDEFINED);
8175a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe    }
8189df53fae3afd1c6b5278216be2fd33a255602aefMike Lockwood    info.mAssociationType = MTP_ASSOCIATION_TYPE_UNDEFINED;
819d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
820d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
8216698749dd4d4d6513b26aa9071af290b956b68a7Dan Albert    MtpString temp(reinterpret_cast<char16_t*>(str));
8229df53fae3afd1c6b5278216be2fd33a255602aefMike Lockwood    info.mName = strdup((const char *)temp);
823d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->ReleaseCharArrayElements(mStringBuffer, str, 0);
824d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
825c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    // read EXIF data for thumbnail information
826c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    if (info.mFormat == MTP_FORMAT_EXIF_JPEG || info.mFormat == MTP_FORMAT_JFIF) {
8273cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen
8283cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen        ExifData *exifdata = exif_data_new_from_file(path);
8293cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen        if (exifdata) {
8305a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe            if ((false)) {
8315a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe                exif_data_foreach_content(exifdata, foreachcontent, NULL);
8325a15d0d31b877ef512b3379eac033c6bb041c86aAndreas Gampe            }
8333cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen
8343cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            // XXX get this from exif, or parse jpeg header instead?
8353cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            ExifEntry *w = exif_content_get_entry(
8363cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen                    exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_X_DIMENSION);
8373cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            ExifEntry *h = exif_content_get_entry(
8383cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen                    exifdata->ifd[EXIF_IFD_EXIF], EXIF_TAG_PIXEL_Y_DIMENSION);
8393cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            info.mThumbCompressedSize = exifdata->data ? exifdata->size : 0;
8403cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            info.mThumbFormat = MTP_FORMAT_EXIF_JPEG;
8410937eed32fbe780182cb0349ac29680add7e492cMarco Nelissen            info.mImagePixWidth = w ? getLongFromExifEntry(w) : 0;
8420937eed32fbe780182cb0349ac29680add7e492cMarco Nelissen            info.mImagePixHeight = h ? getLongFromExifEntry(h) : 0;
8433cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            exif_data_unref(exifdata);
844c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood        }
845c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    }
846c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood
8470a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
848d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    return MTP_RESPONSE_OK;
849d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
850d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
851c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwoodvoid* MyMtpDatabase::getThumbnail(MtpObjectHandle handle, size_t& outThumbSize) {
852c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    MtpString path;
853c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    int64_t length;
854c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    MtpObjectFormat format;
855c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    void* result = NULL;
856c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    outThumbSize = 0;
857c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood
858c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    if (getObjectFilePath(handle, path, length, format) == MTP_RESPONSE_OK
859c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood            && (format == MTP_FORMAT_EXIF_JPEG || format == MTP_FORMAT_JFIF)) {
8603cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen
8613cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen        ExifData *exifdata = exif_data_new_from_file(path);
8623cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen        if (exifdata) {
8633cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            if (exifdata->data) {
8643cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen                result = malloc(exifdata->size);
8653cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen                if (result) {
8663cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen                    memcpy(result, exifdata->data, exifdata->size);
867c436772120ceea1d6e3f5b388ef068c99c8bb7d6Mike Lockwood                    outThumbSize = exifdata->size;
8683cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen                }
869c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood            }
8703cd393c5051ce26c8030736f5524962d98abe849Marco Nelissen            exif_data_unref(exifdata);
871c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood        }
872c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    }
873c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood
874c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood    return result;
875c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood}
876c89f22242b955ae748765b3465b819b40f70ee5fMike Lockwood
87759c777a24a2c639dfd84b7bf17e430e6d3424866Mike LockwoodMtpResponseCode MyMtpDatabase::getObjectFilePath(MtpObjectHandle handle,
878365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                                            MtpString& outFilePath,
879365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                                            int64_t& outFileLength,
880365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood                                            MtpObjectFormat& outFormat) {
881d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
88259c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    jint result = env->CallIntMethod(mDatabase, method_getObjectFilePath,
883d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood                (jint)handle, mStringBuffer, mLongBuffer);
88459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    if (result != MTP_RESPONSE_OK) {
88559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        checkAndClearExceptionFromCallback(env, __FUNCTION__);
88659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood        return result;
88759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
888d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
889d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
8906698749dd4d4d6513b26aa9071af290b956b68a7Dan Albert    outFilePath.setTo(reinterpret_cast<char16_t*>(str),
8916698749dd4d4d6513b26aa9071af290b956b68a7Dan Albert                      strlen16(reinterpret_cast<char16_t*>(str)));
892d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->ReleaseCharArrayElements(mStringBuffer, str, 0);
893d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
894d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jlong* longValues = env->GetLongArrayElements(mLongBuffer, 0);
895365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood    outFileLength = longValues[0];
896365e03e4943b2d2f4d1e602409ab0e770ea77d1dMike Lockwood    outFormat = longValues[1];
897d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    env->ReleaseLongArrayElements(mLongBuffer, longValues, 0);
89815dd15fd572df6b6f785dff75f66e9b99f40322aElliott Hughes
8990a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
90059c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    return result;
901d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
902d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
90359c777a24a2c639dfd84b7bf17e430e6d3424866Mike LockwoodMtpResponseCode MyMtpDatabase::deleteFile(MtpObjectHandle handle) {
904d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
9050a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    MtpResponseCode result = env->CallIntMethod(mDatabase, method_deleteFile, (jint)handle);
9060a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
9070a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
9080a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return result;
909d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
910d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
911d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodstruct PropertyTableEntry {
912d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    MtpObjectProperty   property;
913d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    int                 type;
914d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood};
915d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
91659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodstatic const PropertyTableEntry   kObjectPropertyTable[] = {
917d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_STORAGE_ID,        MTP_TYPE_UINT32     },
918d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_OBJECT_FORMAT,     MTP_TYPE_UINT16     },
919d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_PROTECTION_STATUS, MTP_TYPE_UINT16     },
920d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_OBJECT_SIZE,       MTP_TYPE_UINT64     },
921d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_OBJECT_FILE_NAME,  MTP_TYPE_STR        },
922d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_DATE_MODIFIED,     MTP_TYPE_STR        },
923d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_PARENT_OBJECT,     MTP_TYPE_UINT32     },
924d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_PERSISTENT_UID,    MTP_TYPE_UINT128    },
925d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood    {   MTP_PROPERTY_NAME,              MTP_TYPE_STR        },
926ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_DISPLAY_NAME,      MTP_TYPE_STR        },
927ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_DATE_ADDED,        MTP_TYPE_STR        },
928ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_ARTIST,            MTP_TYPE_STR        },
929ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_ALBUM_NAME,        MTP_TYPE_STR        },
930ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_ALBUM_ARTIST,      MTP_TYPE_STR        },
931ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_TRACK,             MTP_TYPE_UINT16     },
932ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_ORIGINAL_RELEASE_DATE, MTP_TYPE_STR    },
933ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_GENRE,             MTP_TYPE_STR        },
934ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_COMPOSER,          MTP_TYPE_STR        },
935ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_DURATION,          MTP_TYPE_UINT32     },
936ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood    {   MTP_PROPERTY_DESCRIPTION,       MTP_TYPE_STR        },
93771827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood    {   MTP_PROPERTY_AUDIO_WAVE_CODEC,  MTP_TYPE_UINT32     },
93871827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood    {   MTP_PROPERTY_BITRATE_TYPE,      MTP_TYPE_UINT16     },
93971827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood    {   MTP_PROPERTY_AUDIO_BITRATE,     MTP_TYPE_UINT32     },
94071827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood    {   MTP_PROPERTY_NUMBER_OF_CHANNELS,MTP_TYPE_UINT16     },
94171827748105252791854b87da8e0e0c66ff0d2cbMike Lockwood    {   MTP_PROPERTY_SAMPLE_RATE,       MTP_TYPE_UINT32     },
942d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood};
943d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
94459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodstatic const PropertyTableEntry   kDevicePropertyTable[] = {
945ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood    {   MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER,    MTP_TYPE_STR },
946ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood    {   MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME,       MTP_TYPE_STR },
947ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood    {   MTP_DEVICE_PROPERTY_IMAGE_SIZE,                 MTP_TYPE_STR },
94856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    {   MTP_DEVICE_PROPERTY_BATTERY_LEVEL,              MTP_TYPE_UINT8 },
94959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood};
95059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
95159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodbool MyMtpDatabase::getObjectPropertyInfo(MtpObjectProperty property, int& type) {
95259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    int count = sizeof(kObjectPropertyTable) / sizeof(kObjectPropertyTable[0]);
95359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    const PropertyTableEntry* entry = kObjectPropertyTable;
95459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    for (int i = 0; i < count; i++, entry++) {
95559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        if (entry->property == property) {
95659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            type = entry->type;
95759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            return true;
95859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        }
95959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
96059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    return false;
96159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood}
96259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
96359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwoodbool MyMtpDatabase::getDevicePropertyInfo(MtpDeviceProperty property, int& type) {
96459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    int count = sizeof(kDevicePropertyTable) / sizeof(kDevicePropertyTable[0]);
96559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    const PropertyTableEntry* entry = kDevicePropertyTable;
966d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    for (int i = 0; i < count; i++, entry++) {
967d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        if (entry->property == property) {
968d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            type = entry->type;
969d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood            return true;
970d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        }
971d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
972d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    return false;
973d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
974d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
9759a2046fb5ceeee4d5334274cbff15f1058bb3244Mike LockwoodMtpObjectHandleList* MyMtpDatabase::getObjectReferences(MtpObjectHandle handle) {
9769a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
9779a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    jintArray array = (jintArray)env->CallObjectMethod(mDatabase, method_getObjectReferences,
9789a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                (jint)handle);
9799a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    if (!array)
9809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        return NULL;
9819a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    MtpObjectHandleList* list = new MtpObjectHandleList();
9829a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    jint* handles = env->GetIntArrayElements(array, 0);
9839a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    jsize length = env->GetArrayLength(array);
9849a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    for (int i = 0; i < length; i++)
9859a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        list->push(handles[i]);
9860a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    env->ReleaseIntArrayElements(array, handles, 0);
9878839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    env->DeleteLocalRef(array);
9880a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood
9890a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
9900a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return list;
9919a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood}
9929a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
9930a7fa0a868ccce920827e141cbbe237594e53364Mike LockwoodMtpResponseCode MyMtpDatabase::setObjectReferences(MtpObjectHandle handle,
9940a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood                                                    MtpObjectHandleList* references) {
9959a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
9969a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    int count = references->size();
9979a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    jintArray array = env->NewIntArray(count);
9989a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    if (!array) {
9993762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("out of memory in setObjectReferences");
10009a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        return false;
10019a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
10029a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    jint* handles = env->GetIntArrayElements(array, 0);
10039a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood     for (int i = 0; i < count; i++)
10049a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        handles[i] = (*references)[i];
10059a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    env->ReleaseIntArrayElements(array, handles, 0);
10060a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    MtpResponseCode result = env->CallIntMethod(mDatabase, method_setObjectReferences,
10079a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood                (jint)handle, array);
10088839471f4d83238f9c017142dcbe3f915f3213fbMike Lockwood    env->DeleteLocalRef(array);
10099a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood
10100a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
10110a7fa0a868ccce920827e141cbbe237594e53364Mike Lockwood    return result;
1012d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
1013d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1014828d19dd96b05fa99abdc517701e5366543c324fMike LockwoodMtpProperty* MyMtpDatabase::getObjectPropertyDesc(MtpObjectProperty property,
1015828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood                                            MtpObjectFormat format) {
101692b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood    static const int channelEnum[] = {
101792b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        1,  // mono
101892b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        2,  // stereo
101992b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        3,  // 2.1
102092b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        4,  // 3
102192b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        5,  // 3.1
102292b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        6,  // 4
102392b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        7,  // 4.1
102492b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        8,  // 5
102592b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        9,  // 5.1
102692b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                    };
102792b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood    static const int bitrateEnum[] = {
102892b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        1,  // fixed rate
102992b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                        2,  // variable rate
103092b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood                                     };
103192b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood
1032828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    MtpProperty* result = NULL;
1033828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    switch (property) {
1034828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood        case MTP_PROPERTY_OBJECT_FORMAT:
10359b5e9c407d35eab4f37c208d81bdf0b8bcdbdf93Mike Lockwood            // use format as default value
10369b5e9c407d35eab4f37c208d81bdf0b8bcdbdf93Mike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT16, false, format);
10379b5e9c407d35eab4f37c208d81bdf0b8bcdbdf93Mike Lockwood            break;
1038828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood        case MTP_PROPERTY_PROTECTION_STATUS:
1039ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_TRACK:
1040828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT16);
1041828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            break;
1042828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood        case MTP_PROPERTY_STORAGE_ID:
1043828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood        case MTP_PROPERTY_PARENT_OBJECT:
1044ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_DURATION:
104592b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood        case MTP_PROPERTY_AUDIO_WAVE_CODEC:
1046828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT32);
1047828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            break;
1048828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood        case MTP_PROPERTY_OBJECT_SIZE:
1049828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT64);
1050828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            break;
1051828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood        case MTP_PROPERTY_PERSISTENT_UID:
1052828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT128);
1053828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            break;
1054d3bfecb0c9bdf3651a06e86c7c8607768a29a9aeMike Lockwood        case MTP_PROPERTY_NAME:
1055ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_DISPLAY_NAME:
1056ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_ARTIST:
1057ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_ALBUM_NAME:
1058ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_ALBUM_ARTIST:
1059ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_GENRE:
1060ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_COMPOSER:
1061ae078f7dacdc719d045c2d19bbce019599fec64eMike Lockwood        case MTP_PROPERTY_DESCRIPTION:
1062828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            result = new MtpProperty(property, MTP_TYPE_STR);
1063828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood            break;
10645b19af05f2c6ad71171f95bdad2484a38b61121fMike Lockwood        case MTP_PROPERTY_DATE_MODIFIED:
10655b19af05f2c6ad71171f95bdad2484a38b61121fMike Lockwood        case MTP_PROPERTY_DATE_ADDED:
10665b19af05f2c6ad71171f95bdad2484a38b61121fMike Lockwood        case MTP_PROPERTY_ORIGINAL_RELEASE_DATE:
10675b19af05f2c6ad71171f95bdad2484a38b61121fMike Lockwood            result = new MtpProperty(property, MTP_TYPE_STR);
10685b19af05f2c6ad71171f95bdad2484a38b61121fMike Lockwood            result->setFormDateTime();
10695b19af05f2c6ad71171f95bdad2484a38b61121fMike Lockwood            break;
10705ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood        case MTP_PROPERTY_OBJECT_FILE_NAME:
10716a6a3aff17e057eeb1457ac4d04ab4b5e8f53abeMike Lockwood            // We allow renaming files and folders
10726a6a3aff17e057eeb1457ac4d04ab4b5e8f53abeMike Lockwood            result = new MtpProperty(property, MTP_TYPE_STR, true);
10735ebac83e20dadf10bd4a0cee4ddf69d0ec049f98Mike Lockwood            break;
107492b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood        case MTP_PROPERTY_BITRATE_TYPE:
107592b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood             result = new MtpProperty(property, MTP_TYPE_UINT16);
107692b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            result->setFormEnum(bitrateEnum, sizeof(bitrateEnum)/sizeof(bitrateEnum[0]));
107792b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            break;
107892b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood        case MTP_PROPERTY_AUDIO_BITRATE:
107992b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT32);
108092b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            result->setFormRange(1, 1536000, 1);
108192b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            break;
108292b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood        case MTP_PROPERTY_NUMBER_OF_CHANNELS:
108392b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT16);
108492b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            result->setFormEnum(channelEnum, sizeof(channelEnum)/sizeof(channelEnum[0]));
108592b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            break;
108692b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood        case MTP_PROPERTY_SAMPLE_RATE:
108792b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT32);
108892b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            result->setFormRange(8000, 48000, 1);
108992b53bc2dd42a3c1d2d7708145099da2a5fe541eMike Lockwood            break;
1090828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    }
1091828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
1092828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood    return result;
1093828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood}
1094828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
1095828d19dd96b05fa99abdc517701e5366543c324fMike LockwoodMtpProperty* MyMtpDatabase::getDevicePropertyDesc(MtpDeviceProperty property) {
1096ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
109759e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    MtpProperty* result = NULL;
1098ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood    bool writable = false;
1099ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood
110059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    switch (property) {
110159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        case MTP_DEVICE_PROPERTY_SYNCHRONIZATION_PARTNER:
110259e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        case MTP_DEVICE_PROPERTY_DEVICE_FRIENDLY_NAME:
1103ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            writable = true;
1104ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            // fall through
110556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        case MTP_DEVICE_PROPERTY_IMAGE_SIZE: {
1106ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            result = new MtpProperty(property, MTP_TYPE_STR, writable);
1107a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood
1108ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood            // get current value
1109a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood            jint ret = env->CallIntMethod(mDatabase, method_getDeviceProperty,
1110a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood                        (jint)property, mLongBuffer, mStringBuffer);
1111a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood            if (ret == MTP_RESPONSE_OK) {
1112a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood                jchar* str = env->GetCharArrayElements(mStringBuffer, 0);
1113a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood                result->setCurrentValue(str);
1114ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                // for read-only properties it is safe to assume current value is default value
1115ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                if (!writable)
1116ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood                    result->setDefaultValue(str);
1117a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood                env->ReleaseCharArrayElements(mStringBuffer, str, 0);
1118a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood            } else {
11193762c311729fe9f3af085c14c5c1fb471d994c03Steve Block                ALOGE("unable to read device property, response: %04X", ret);
1120a2a2128423309641a6b508a15404f3a7e8f3077bMike Lockwood            }
112159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood            break;
112256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        }
112356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        case MTP_DEVICE_PROPERTY_BATTERY_LEVEL:
112456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            result = new MtpProperty(property, MTP_TYPE_UINT8);
112556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            result->setFormRange(0, env->GetIntField(mDatabase, field_batteryScale), 1);
112656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            result->mCurrentValue.u.u8 = (uint8_t)env->GetIntField(mDatabase, field_batteryLevel);
112756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood            break;
112859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
112959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood
1130ea93fa16b166ff477e9cf6bd3ac67c8fb259fb57Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
113159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    return result;
1132828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood}
1133828d19dd96b05fa99abdc517701e5366543c324fMike Lockwood
11342837eefc5459427138c080d445bb491c75630163Mike Lockwoodvoid MyMtpDatabase::sessionStarted() {
11352837eefc5459427138c080d445bb491c75630163Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
11362837eefc5459427138c080d445bb491c75630163Mike Lockwood    env->CallVoidMethod(mDatabase, method_sessionStarted);
11372837eefc5459427138c080d445bb491c75630163Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
11382837eefc5459427138c080d445bb491c75630163Mike Lockwood}
11392837eefc5459427138c080d445bb491c75630163Mike Lockwood
11402837eefc5459427138c080d445bb491c75630163Mike Lockwoodvoid MyMtpDatabase::sessionEnded() {
11412837eefc5459427138c080d445bb491c75630163Mike Lockwood    JNIEnv* env = AndroidRuntime::getJNIEnv();
11422837eefc5459427138c080d445bb491c75630163Mike Lockwood    env->CallVoidMethod(mDatabase, method_sessionEnded);
11432837eefc5459427138c080d445bb491c75630163Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
11442837eefc5459427138c080d445bb491c75630163Mike Lockwood}
11452837eefc5459427138c080d445bb491c75630163Mike Lockwood
1146d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood// ----------------------------------------------------------------------------
1147d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1148d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodstatic void
11490cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodandroid_mtp_MtpDatabase_setup(JNIEnv *env, jobject thiz)
1150d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood{
1151d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    MyMtpDatabase* database = new MyMtpDatabase(env, thiz);
1152e2e59326f13cf291bf5b37989390fd2a55a94f0cAshok Bhat    env->SetLongField(thiz, field_context, (jlong)database);
1153d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
1154d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
1155d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1156d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwoodstatic void
11570cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodandroid_mtp_MtpDatabase_finalize(JNIEnv *env, jobject thiz)
1158d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood{
1159e2e59326f13cf291bf5b37989390fd2a55a94f0cAshok Bhat    MyMtpDatabase* database = (MyMtpDatabase *)env->GetLongField(thiz, field_context);
1160d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    database->cleanup(env);
1161d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    delete database;
1162e2e59326f13cf291bf5b37989390fd2a55a94f0cAshok Bhat    env->SetLongField(thiz, field_context, 0);
1163d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    checkAndClearExceptionFromCallback(env, __FUNCTION__);
1164d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
1165d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
11663159991e586f9e243f60d65a9554828328b00521Mike Lockwoodstatic jstring
1167aeb75fc5a3dc51bf9d5220647a68c48644c66ea8Mark Salyzynandroid_mtp_MtpPropertyGroup_format_date_time(JNIEnv *env, jobject /*thiz*/, jlong seconds)
11683159991e586f9e243f60d65a9554828328b00521Mike Lockwood{
11693159991e586f9e243f60d65a9554828328b00521Mike Lockwood    char    date[20];
11703159991e586f9e243f60d65a9554828328b00521Mike Lockwood    formatDateTime(seconds, date, sizeof(date));
11713159991e586f9e243f60d65a9554828328b00521Mike Lockwood    return env->NewStringUTF(date);
11723159991e586f9e243f60d65a9554828328b00521Mike Lockwood}
11733159991e586f9e243f60d65a9554828328b00521Mike Lockwood
1174d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood// ----------------------------------------------------------------------------
1175d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
117676f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMtpDatabaseMethods[] = {
11770cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwood    {"native_setup",            "()V",  (void *)android_mtp_MtpDatabase_setup},
11780cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwood    {"native_finalize",         "()V",  (void *)android_mtp_MtpDatabase_finalize},
11797d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood};
11807d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
118176f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMtpPropertyGroupMethods[] = {
11823159991e586f9e243f60d65a9554828328b00521Mike Lockwood    {"format_date_time",        "(J)Ljava/lang/String;",
11830cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwood                                        (void *)android_mtp_MtpPropertyGroup_format_date_time},
1184d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood};
1185d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
11860cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwoodint register_android_mtp_MtpDatabase(JNIEnv *env)
1187d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood{
1188d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    jclass clazz;
1189d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
11900cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwood    clazz = env->FindClass("android/mtp/MtpDatabase");
1191d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    if (clazz == NULL) {
11923762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find android/mtp/MtpDatabase");
1193d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return -1;
1194d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
1195d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    method_beginSendObject = env->GetMethodID(clazz, "beginSendObject", "(Ljava/lang/String;IIIJJ)I");
1196d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    if (method_beginSendObject == NULL) {
11973762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find beginSendObject");
1198d815f79766984fce499e147ecbacc01914683f74Mike Lockwood        return -1;
1199d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    }
12007a0bd17bceaf3efc3732e30c538fae420d3b742cMike Lockwood    method_endSendObject = env->GetMethodID(clazz, "endSendObject", "(Ljava/lang/String;IIZ)V");
1201d815f79766984fce499e147ecbacc01914683f74Mike Lockwood    if (method_endSendObject == NULL) {
12023762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find endSendObject");
1203d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return -1;
1204d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
1205d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    method_getObjectList = env->GetMethodID(clazz, "getObjectList", "(III)[I");
1206d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    if (method_getObjectList == NULL) {
12073762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getObjectList");
1208d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return -1;
1209d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
12107a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    method_getNumObjects = env->GetMethodID(clazz, "getNumObjects", "(III)I");
12117a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    if (method_getNumObjects == NULL) {
12123762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getNumObjects");
12137a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood        return -1;
12147a047c89862febf63ce1bb5873179c7a2ff8d9d3Mike Lockwood    }
12154b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    method_getSupportedPlaybackFormats = env->GetMethodID(clazz, "getSupportedPlaybackFormats", "()[I");
12164b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    if (method_getSupportedPlaybackFormats == NULL) {
12173762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getSupportedPlaybackFormats");
12184b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return -1;
12194b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
12204b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    method_getSupportedCaptureFormats = env->GetMethodID(clazz, "getSupportedCaptureFormats", "()[I");
12214b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    if (method_getSupportedCaptureFormats == NULL) {
12223762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getSupportedCaptureFormats");
12234b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return -1;
12244b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
12254b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    method_getSupportedObjectProperties = env->GetMethodID(clazz, "getSupportedObjectProperties", "(I)[I");
12264b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    if (method_getSupportedObjectProperties == NULL) {
12273762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getSupportedObjectProperties");
12284b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return -1;
12294b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
12304b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    method_getSupportedDeviceProperties = env->GetMethodID(clazz, "getSupportedDeviceProperties", "()[I");
12314b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    if (method_getSupportedDeviceProperties == NULL) {
12323762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getSupportedDeviceProperties");
12334b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood        return -1;
12344b322ce4fb86b5a7a6e50633a3a9f498ca8d4706Mike Lockwood    }
123559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    method_setObjectProperty = env->GetMethodID(clazz, "setObjectProperty", "(IIJLjava/lang/String;)I");
123659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    if (method_setObjectProperty == NULL) {
12373762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find setObjectProperty");
123859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return -1;
123959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
124059e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    method_getDeviceProperty = env->GetMethodID(clazz, "getDeviceProperty", "(I[J[C)I");
124159e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    if (method_getDeviceProperty == NULL) {
12423762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getDeviceProperty");
124359e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return -1;
124459e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
124559e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    method_setDeviceProperty = env->GetMethodID(clazz, "setDeviceProperty", "(IJLjava/lang/String;)I");
124659e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    if (method_setDeviceProperty == NULL) {
12473762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find setDeviceProperty");
124859e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood        return -1;
124959e3f0db0855567a95f783f6d1ec36a7cfc4ea83Mike Lockwood    }
1250e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    method_getObjectPropertyList = env->GetMethodID(clazz, "getObjectPropertyList",
12510cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwood            "(JIJII)Landroid/mtp/MtpPropertyList;");
1252e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (method_getObjectPropertyList == NULL) {
12533762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getObjectPropertyList");
1254e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1255e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1256d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    method_getObjectInfo = env->GetMethodID(clazz, "getObjectInfo", "(I[I[C[J)Z");
1257d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    if (method_getObjectInfo == NULL) {
12583762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getObjectInfo");
1259d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return -1;
1260d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
126159c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    method_getObjectFilePath = env->GetMethodID(clazz, "getObjectFilePath", "(I[C[J)I");
1262d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    if (method_getObjectFilePath == NULL) {
12633762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getObjectFilePath");
1264d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return -1;
1265d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
126659c777a24a2c639dfd84b7bf17e430e6d3424866Mike Lockwood    method_deleteFile = env->GetMethodID(clazz, "deleteFile", "(I)I");
1267d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    if (method_deleteFile == NULL) {
12683762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find deleteFile");
1269d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return -1;
1270d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
12719a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    method_getObjectReferences = env->GetMethodID(clazz, "getObjectReferences", "(I)[I");
12729a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    if (method_getObjectReferences == NULL) {
12733762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find getObjectReferences");
12749a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        return -1;
12759a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
12769a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    method_setObjectReferences = env->GetMethodID(clazz, "setObjectReferences", "(I[I)I");
12779a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    if (method_setObjectReferences == NULL) {
12783762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find setObjectReferences");
12799a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood        return -1;
12809a2046fb5ceeee4d5334274cbff15f1058bb3244Mike Lockwood    }
12812837eefc5459427138c080d445bb491c75630163Mike Lockwood    method_sessionStarted = env->GetMethodID(clazz, "sessionStarted", "()V");
12822837eefc5459427138c080d445bb491c75630163Mike Lockwood    if (method_sessionStarted == NULL) {
12833762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find sessionStarted");
12842837eefc5459427138c080d445bb491c75630163Mike Lockwood        return -1;
12852837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
12862837eefc5459427138c080d445bb491c75630163Mike Lockwood    method_sessionEnded = env->GetMethodID(clazz, "sessionEnded", "()V");
12872837eefc5459427138c080d445bb491c75630163Mike Lockwood    if (method_sessionEnded == NULL) {
12883762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find sessionEnded");
12892837eefc5459427138c080d445bb491c75630163Mike Lockwood        return -1;
12902837eefc5459427138c080d445bb491c75630163Mike Lockwood    }
12912837eefc5459427138c080d445bb491c75630163Mike Lockwood
1292e2e59326f13cf291bf5b37989390fd2a55a94f0cAshok Bhat    field_context = env->GetFieldID(clazz, "mNativeContext", "J");
1293d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    if (field_context == NULL) {
12943762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find MtpDatabase.mNativeContext");
1295d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood        return -1;
1296d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    }
129756c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    field_batteryLevel = env->GetFieldID(clazz, "mBatteryLevel", "I");
129856c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    if (field_batteryLevel == NULL) {
129956c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        ALOGE("Can't find MtpDatabase.mBatteryLevel");
130056c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        return -1;
130156c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    }
130256c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    field_batteryScale = env->GetFieldID(clazz, "mBatteryScale", "I");
130356c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    if (field_batteryScale == NULL) {
130456c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        ALOGE("Can't find MtpDatabase.mBatteryScale");
130556c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood        return -1;
130656c85244b9be0fc6f6c2baf5f9a53f2364d5ec5eMike Lockwood    }
1307d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood
1308e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    // now set up fields for MtpPropertyList class
13090cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwood    clazz = env->FindClass("android/mtp/MtpPropertyList");
1310e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (clazz == NULL) {
13113762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find android/mtp/MtpPropertyList");
1312e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1313e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1314e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    field_mCount = env->GetFieldID(clazz, "mCount", "I");
1315e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (field_mCount == NULL) {
13163762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find MtpPropertyList.mCount");
1317e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1318e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1319e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    field_mResult = env->GetFieldID(clazz, "mResult", "I");
1320e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (field_mResult == NULL) {
13213762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find MtpPropertyList.mResult");
1322e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1323e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1324e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    field_mObjectHandles = env->GetFieldID(clazz, "mObjectHandles", "[I");
1325e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (field_mObjectHandles == NULL) {
13263762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find MtpPropertyList.mObjectHandles");
1327e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1328e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1329e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    field_mPropertyCodes = env->GetFieldID(clazz, "mPropertyCodes", "[I");
1330e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (field_mPropertyCodes == NULL) {
13313762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find MtpPropertyList.mPropertyCodes");
1332e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1333e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1334e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    field_mDataTypes = env->GetFieldID(clazz, "mDataTypes", "[I");
1335e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (field_mDataTypes == NULL) {
13363762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find MtpPropertyList.mDataTypes");
1337e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1338e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1339e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    field_mLongValues = env->GetFieldID(clazz, "mLongValues", "[J");
1340e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (field_mLongValues == NULL) {
13413762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find MtpPropertyList.mLongValues");
1342e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1343e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1344e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    field_mStringValues = env->GetFieldID(clazz, "mStringValues", "[Ljava/lang/String;");
1345e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    if (field_mStringValues == NULL) {
13463762c311729fe9f3af085c14c5c1fb471d994c03Steve Block        ALOGE("Can't find MtpPropertyList.mStringValues");
1347e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood        return -1;
1348e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood    }
1349e2ad6ec1718ef0c0e8230f8f62e7cfefcf598b6aMike Lockwood
13507d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood    if (AndroidRuntime::registerNativeMethods(env,
13510cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwood                "android/mtp/MtpDatabase", gMtpDatabaseMethods, NELEM(gMtpDatabaseMethods)))
13527d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood        return -1;
13537d7fb63071ca370f77ed69055ac30341b8388d15Mike Lockwood
1354d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood    return AndroidRuntime::registerNativeMethods(env,
13550cd0136d440cf6ad9d5fab430269116786e671ecMike Lockwood                "android/mtp/MtpPropertyGroup", gMtpPropertyGroupMethods, NELEM(gMtpPropertyGroupMethods));
1356d21eac9c70940f2c73da5faaf401dbbc44b70a15Mike Lockwood}
1357