Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dc079229 authored by Daichi Hirono's avatar Daichi Hirono Committed by Android (Google) Code Review
Browse files

Merge "Add getPartialObject to Java MtpDevice class."

parents ed950933 52da3ad9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -22452,6 +22452,7 @@ package android.mtp {
    method public int[] getObjectHandles(int, int, int);
    method public android.mtp.MtpObjectInfo getObjectInfo(int);
    method public long getParent(int);
    method public int getPartialObject(int, int, int, byte[]) throws java.io.IOException;
    method public long getStorageId(int);
    method public int[] getStorageIds();
    method public android.mtp.MtpStorageInfo getStorageInfo(int);
+1 −0
Original line number Diff line number Diff line
@@ -23998,6 +23998,7 @@ package android.mtp {
    method public int[] getObjectHandles(int, int, int);
    method public android.mtp.MtpObjectInfo getObjectInfo(int);
    method public long getParent(int);
    method public int getPartialObject(int, int, int, byte[]) throws java.io.IOException;
    method public long getStorageId(int);
    method public int[] getStorageIds();
    method public android.mtp.MtpStorageInfo getStorageInfo(int);
+1 −0
Original line number Diff line number Diff line
@@ -22460,6 +22460,7 @@ package android.mtp {
    method public int[] getObjectHandles(int, int, int);
    method public android.mtp.MtpObjectInfo getObjectInfo(int);
    method public long getParent(int);
    method public int getPartialObject(int, int, int, byte[]) throws java.io.IOException;
    method public long getStorageId(int);
    method public int[] getStorageIds();
    method public android.mtp.MtpStorageInfo getStorageInfo(int);
+20 −1
Original line number Diff line number Diff line
@@ -19,9 +19,10 @@ package android.mtp;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor;

import java.io.IOException;

/**
 * This class represents an MTP or PTP device connected on the USB host bus. An application can
 * instantiate an object of this type, by referencing an attached {@link
@@ -157,6 +158,22 @@ public final class MtpDevice {
        return native_get_object(objectHandle, objectSize);
    }

    /**
     * Obtains object bytes in the specified range and writes it to an array.
     * This call may block for an arbitrary amount of time depending on the size
     * of the data and speed of the devices.
     *
     * @param objectHandle handle of the object to read
     * @param offset Start index of reading range.
     * @param size Size of reading range.
     * @param buffer Array to write data.
     * @return Size of bytes that are actually read.
     */
    public int getPartialObject(int objectHandle, int offset, int size, byte[] buffer)
            throws IOException {
        return native_get_partial_object(objectHandle, offset, size, buffer);
    }

    /**
     * Returns the thumbnail data for an object as a byte array.
     * The size and format of the thumbnail data can be determined via
@@ -323,6 +340,8 @@ public final class MtpDevice {
    private native int[] native_get_object_handles(int storageId, int format, int objectHandle);
    private native MtpObjectInfo native_get_object_info(int objectHandle);
    private native byte[] native_get_object(int objectHandle, int objectSize);
    private native int native_get_partial_object(
            int objectHandle, int offset, int objectSize, byte[] buffer) throws IOException;
    private native byte[] native_get_thumbnail(int objectHandle);
    private native boolean native_delete_object(int objectHandle);
    private native long native_get_parent(int objectHandle);
+68 −23
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/Log.h"
#include "nativehelper/ScopedLocalRef.h"
#include "private/android_filesystem_config.h"

#include "MtpTypes.h"
@@ -41,6 +42,8 @@ using namespace android;

// ----------------------------------------------------------------------------

namespace {

static jfieldID field_context;

jclass clazz_deviceInfo;
@@ -93,6 +96,28 @@ static jfieldID field_objectInfo_keywords;
// MtpEvent fields
static jfieldID field_event_eventCode;

class JavaArrayWriter {
    JNIEnv* mEnv;
    jbyteArray mArray;
    jsize mSize;

public:
    JavaArrayWriter(JNIEnv* env, jbyteArray array) :
        mEnv(env), mArray(array), mSize(mEnv->GetArrayLength(mArray)) {}
    bool write(void* data, uint32_t offset, uint32_t length) {
        if (static_cast<uint32_t>(mSize) < offset + length) {
            return false;
        }
        mEnv->SetByteArrayRegion(mArray, offset, length, static_cast<jbyte*>(data));
        return true;
    }
    static bool writeTo(void* data, uint32_t offset, uint32_t length, void* clientData) {
        return static_cast<JavaArrayWriter*>(clientData)->write(data, offset, length);
    }
};

}

MtpDevice* get_device_from_object(JNIEnv* env, jobject javaDevice)
{
    return (MtpDevice*)env->GetLongField(javaDevice, field_context);
@@ -307,38 +332,57 @@ android_mtp_MtpDevice_get_object_info(JNIEnv *env, jobject thiz, jint objectID)
    return info;
}

struct get_object_callback_data {
    JNIEnv *env;
    jbyteArray array;
};

static bool get_object_callback(void* data, int offset, int length, void* clientData)
{
    get_object_callback_data* cbData = (get_object_callback_data *)clientData;
    cbData->env->SetByteArrayRegion(cbData->array, offset, length, (jbyte *)data);
    return true;
}

static jbyteArray
android_mtp_MtpDevice_get_object(JNIEnv *env, jobject thiz, jint objectID, jint objectSize)
{
    MtpDevice* device = get_device_from_object(env, thiz);
    if (!device)
        return NULL;
    if (!device) {
        return nullptr;
    }

    jbyteArray array = env->NewByteArray(objectSize);
    if (!array) {
    ScopedLocalRef<jbyteArray> array(env, env->NewByteArray(objectSize));
    if (!array.get()) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return NULL;
        return nullptr;
    }

    get_object_callback_data data;
    data.env = env;
    data.array = array;
    JavaArrayWriter writer(env, array.get());

    if (device->readObject(objectID, get_object_callback, objectSize, &data))
        return array;
    return NULL;
    if (device->readObject(objectID, JavaArrayWriter::writeTo, objectSize, &writer)) {
        return array.release();
    }
    return nullptr;
}

static jint
android_mtp_MtpDevice_get_partial_object(JNIEnv *env,
                                         jobject thiz,
                                         jint objectID,
                                         jint offset,
                                         jint size,
                                         jbyteArray array)
{
    if (array == nullptr) {
        jniThrowException(env, "java/lang/IllegalArgumentException", "Array must not be null.");
        return -1;
    }

    MtpDevice* const device = get_device_from_object(env, thiz);
    if (!device) {
        jniThrowException(env, "java/io/IOException", "Failed to obtain MtpDevice.");
        return -1;
    }

    JavaArrayWriter writer(env, array);
    const int64_t result = device->readPartialObject(
            objectID, offset, size, JavaArrayWriter::writeTo, &writer);

    if (result >= 0) {
        return static_cast<jint>(result);
    } else {
        jniThrowException(env, "java/io/IOException", "Failed to read data.");
        return -1;
    }
}

static jbyteArray
@@ -547,6 +591,7 @@ static const JNINativeMethod gMethods[] = {
    {"native_get_object_info",  "(I)Landroid/mtp/MtpObjectInfo;",
                                        (void *)android_mtp_MtpDevice_get_object_info},
    {"native_get_object",       "(II)[B",(void *)android_mtp_MtpDevice_get_object},
    {"native_get_partial_object", "(III[B)I", (void *) android_mtp_MtpDevice_get_partial_object},
    {"native_get_thumbnail",    "(I)[B",(void *)android_mtp_MtpDevice_get_thumbnail},
    {"native_delete_object",    "(I)Z", (void *)android_mtp_MtpDevice_delete_object},
    {"native_get_parent",       "(I)J", (void *)android_mtp_MtpDevice_get_parent},