From 787821bce4a07f9b9434180210bf99e6bd2639c9 Mon Sep 17 00:00:00 2001 From: Daichi Hirono Date: Thu, 24 Mar 2016 21:05:51 +0900 Subject: [PATCH] Add getObjectSizeLong hidden API to MtpDevice class. In the MTP spec, the object size is stored in MtpObjectInfo as unsigned 32-bit integer and fetched by the getObjectInfo operation. For the objects that are more than 4GB, the object size is provided as one of extra properties, which are fetched by different operation. The CL adds to getObjectSizeLong hidden method to Java MtpDevice class so that client code can obtain 4GB+ object size. BUG=27805369 Change-Id: I8a5b85c8db39734f00e49709c61b271eb48ff33d --- media/java/android/mtp/MtpDevice.java | 13 ++++++++++ media/jni/android_mtp_MtpDevice.cpp | 37 +++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/media/java/android/mtp/MtpDevice.java b/media/java/android/mtp/MtpDevice.java index 0e7013c97252b..aa99248485c8a 100644 --- a/media/java/android/mtp/MtpDevice.java +++ b/media/java/android/mtp/MtpDevice.java @@ -355,6 +355,18 @@ public final class MtpDevice { } } + /** + * Returns object size in 64-bit integer. + * + * The object size stored in MtpObjectInfo is unsigned 32-bit integer. + * The methods reads 64-bit object size from the object property so that it can fetch 4GB+ + * object size correctly. + * @hide + */ + public long getObjectSizeLong(int handle, int format) throws IOException { + return native_get_object_size_long(handle, format); + } + // used by the JNI code private long mNativeContext; @@ -381,4 +393,5 @@ public final class MtpDevice { private native int native_submit_event_request(); private native MtpEvent native_reap_event_request(int handle); private native void native_discard_event_request(int handle); + private native long native_get_object_size_long(int handle, int format) throws IOException; } diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp index 0ecb75018c45e..f7c6770054892 100644 --- a/media/jni/android_mtp_MtpDevice.cpp +++ b/media/jni/android_mtp_MtpDevice.cpp @@ -42,6 +42,7 @@ #include "MtpDeviceInfo.h" #include "MtpStorageInfo.h" #include "MtpObjectInfo.h" +#include "MtpProperty.h" using namespace android; @@ -700,6 +701,40 @@ static void android_mtp_MtpDevice_discard_event_request(JNIEnv *env, jobject thi device->discardEventRequest(seq); } +static jlong android_mtp_MtpDevice_get_object_size_long( + JNIEnv *env, jobject thiz, jint handle, jint format) { + MtpDevice* const device = get_device_from_object(env, thiz); + if (!device) { + env->ThrowNew(clazz_io_exception, "Failed to obtain MtpDevice."); + return 0; + } + + std::unique_ptr property( + device->getObjectPropDesc(MTP_PROPERTY_OBJECT_SIZE, format)); + if (!property) { + env->ThrowNew(clazz_io_exception, "Failed to obtain property desc."); + return 0; + } + + if (property->getDataType() != MTP_TYPE_UINT64) { + env->ThrowNew(clazz_io_exception, "Unexpected property data type."); + return 0; + } + + if (!device->getObjectPropValue(handle, property.get())) { + env->ThrowNew(clazz_io_exception, "Failed to obtain property value."); + return 0; + } + + const jlong object_size = static_cast(property->getCurrentValue().u.u64); + if (object_size < 0) { + env->ThrowNew(clazz_io_exception, "Object size is too large to express as jlong."); + return 0; + } + + return object_size; +} + // ---------------------------------------------------------------------------- static const JNINativeMethod gMethods[] = { @@ -733,6 +768,8 @@ static const JNINativeMethod gMethods[] = { {"native_reap_event_request", "(I)Landroid/mtp/MtpEvent;", (void *)android_mtp_MtpDevice_reap_event_request}, {"native_discard_event_request", "(I)V", (void *)android_mtp_MtpDevice_discard_event_request}, + + {"native_get_object_size_long", "(II)J", (void *)android_mtp_MtpDevice_get_object_size_long}, }; int register_android_mtp_MtpDevice(JNIEnv *env)