Merge "Add UsbDeviceConnection.requestWait with a timeout"

This commit is contained in:
Philip P. Moltmann
2016-10-27 16:15:11 +00:00
committed by Android (Google) Code Review
5 changed files with 71 additions and 7 deletions

View File

@@ -14781,6 +14781,7 @@ package android.hardware.usb {
method public java.lang.String getSerial();
method public boolean releaseInterface(android.hardware.usb.UsbInterface);
method public android.hardware.usb.UsbRequest requestWait();
method public android.hardware.usb.UsbRequest requestWait(int);
method public boolean setConfiguration(android.hardware.usb.UsbConfiguration);
method public boolean setInterface(android.hardware.usb.UsbInterface);
}

View File

@@ -15990,6 +15990,7 @@ package android.hardware.usb {
method public java.lang.String getSerial();
method public boolean releaseInterface(android.hardware.usb.UsbInterface);
method public android.hardware.usb.UsbRequest requestWait();
method public android.hardware.usb.UsbRequest requestWait(int);
method public boolean resetDevice();
method public boolean setConfiguration(android.hardware.usb.UsbConfiguration);
method public boolean setInterface(android.hardware.usb.UsbInterface);

View File

@@ -14798,6 +14798,7 @@ package android.hardware.usb {
method public java.lang.String getSerial();
method public boolean releaseInterface(android.hardware.usb.UsbInterface);
method public android.hardware.usb.UsbRequest requestWait();
method public android.hardware.usb.UsbRequest requestWait(int);
method public boolean setConfiguration(android.hardware.usb.UsbConfiguration);
method public boolean setInterface(android.hardware.usb.UsbInterface);
}

View File

@@ -21,6 +21,9 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.os.ParcelFileDescriptor;
import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
import java.io.FileDescriptor;
@@ -273,7 +276,40 @@ public class UsbDeviceConnection {
* {@link UsbRequest#queue(ByteBuffer, int)}
*/
public UsbRequest requestWait() {
UsbRequest request = native_request_wait();
// -1 is special value indicating infinite wait
UsbRequest request = native_request_wait(-1);
if (request != null) {
request.dequeue();
}
return request;
}
/**
* Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation
* <p>Note that this may return requests queued on multiple
* {@link android.hardware.usb.UsbEndpoint}s. When multiple endpoints are in use,
* {@link android.hardware.usb.UsbRequest#getEndpoint} and {@link
* android.hardware.usb.UsbRequest#getClientData} can be useful in determining how to process
* the result of this function.</p>
* <p>Position and array offset of the request's buffer are ignored and assumed to be 0. The
* position will be set to the number of bytes read/written.</p>
* <p>Android processes {@link UsbRequest UsbRequests} asynchronously. Hence it is not
* guaranteed that {@link #requestWait(int) requestWait(0)} returns a request that has been
* queued right before even if the request could have been processed immediately.</p>
*
* @param timeout timeout in milliseconds. If 0 this method does not wait.
*
* @return a completed USB request, or {@code null} if an error or time out occurred
*
* @throws IllegalArgumentException if the number of bytes read or written is more than the
* limit of the request's buffer. The number of bytes is
* determined by the {@code length} parameter of
* {@link UsbRequest#queue(ByteBuffer, int)}
*/
public UsbRequest requestWait(int timeout) {
timeout = Preconditions.checkArgumentNonnegative(timeout);
UsbRequest request = native_request_wait(timeout);
if (request != null) {
request.dequeue();
}
@@ -318,7 +354,7 @@ public class UsbDeviceConnection {
int index, byte[] buffer, int offset, int length, int timeout);
private native int native_bulk_request(int endpoint, byte[] buffer,
int offset, int length, int timeout);
private native UsbRequest native_request_wait();
private native UsbRequest native_request_wait(int timeout);
private native String native_get_serial();
private native boolean native_reset_device();
}

View File

@@ -24,12 +24,15 @@
#include <usbhost/usbhost.h>
#include <chrono>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace android;
using namespace std::chrono;
static const int USB_CONTROL_READ_TIMEOUT_MS = 200;
@@ -217,7 +220,7 @@ android_hardware_UsbDeviceConnection_bulk_request(JNIEnv *env, jobject thiz,
}
static jobject
android_hardware_UsbDeviceConnection_request_wait(JNIEnv *env, jobject thiz)
android_hardware_UsbDeviceConnection_request_wait(JNIEnv *env, jobject thiz, jint timeoutMillis)
{
struct usb_device* device = get_device_from_object(env, thiz);
if (!device) {
@@ -225,11 +228,33 @@ android_hardware_UsbDeviceConnection_request_wait(JNIEnv *env, jobject thiz)
return NULL;
}
struct usb_request* request = usb_request_wait(device);
if (request)
struct usb_request* request;
if (timeoutMillis == -1) {
request = usb_request_wait(device, -1);
} else {
steady_clock::time_point currentTime = steady_clock::now();
steady_clock::time_point endTime = currentTime + std::chrono::milliseconds(timeoutMillis);
// Poll the existence of a request via usb_request_wait until we get a result, an unexpected
// error or time out. As several threads can listen on the same fd, we might get wakeups
// without data.
while (1) {
request = usb_request_wait(device, duration_cast<std::chrono::milliseconds>(endTime
- currentTime).count());
int error = errno;
currentTime = steady_clock::now();
if (request != NULL || error != EAGAIN || currentTime >= endTime) {
break;
}
};
}
if (request) {
return (jobject)request->client_data;
else
} else {
return NULL;
}
}
static jstring
@@ -275,7 +300,7 @@ static const JNINativeMethod method_table[] = {
(void *)android_hardware_UsbDeviceConnection_control_request},
{"native_bulk_request", "(I[BIII)I",
(void *)android_hardware_UsbDeviceConnection_bulk_request},
{"native_request_wait", "()Landroid/hardware/usb/UsbRequest;",
{"native_request_wait", "(I)Landroid/hardware/usb/UsbRequest;",
(void *)android_hardware_UsbDeviceConnection_request_wait},
{ "native_get_serial", "()Ljava/lang/String;",
(void*)android_hardware_UsbDeviceConnection_get_serial },