OSDN Git Service

UsbDevice: Move IO related methods to new UsbDeviceConnection class
authorMike Lockwood <lockwood@android.com>
Fri, 11 Mar 2011 13:18:08 +0000 (08:18 -0500)
committerMike Lockwood <lockwood@android.com>
Fri, 11 Mar 2011 15:24:21 +0000 (10:24 -0500)
UsbDevice is now just an immutable parcelable object like UsbInterface and
UsbEndpoint.
All IO related functionality is now contained in UsbDeviceConnection
and UsbRequest.

Bug: 4067029

Change-Id: Ia84da0b512a697acc940eee0c3566711c62e1a68
Signed-off-by: Mike Lockwood <lockwood@android.com>
14 files changed:
api/current.xml
core/java/android/hardware/usb/UsbDevice.java
core/java/android/hardware/usb/UsbDeviceConnection.java [new file with mode: 0644]
core/java/android/hardware/usb/UsbEndpoint.java
core/java/android/hardware/usb/UsbInterface.java
core/java/android/hardware/usb/UsbManager.java
core/java/android/hardware/usb/UsbRequest.java
core/jni/Android.mk
core/jni/AndroidRuntime.cpp
core/jni/android_hardware_UsbDevice.cpp
core/jni/android_hardware_UsbDeviceConnection.cpp [new file with mode: 0644]
core/jni/android_hardware_UsbRequest.cpp
media/java/android/mtp/MtpClient.java
media/java/android/mtp/MtpDevice.java

index ace309b..b2e71fa 100644 (file)
  extends="java.lang.Object"
  abstract="false"
  static="false"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
 <implements name="android.os.Parcelable">
 </implements>
-<method name="bulkTransfer"
+<method name="describeContents"
  return="int"
  abstract="false"
  native="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="endpoint" type="android.hardware.usb.UsbEndpoint">
-</parameter>
-<parameter name="buffer" type="byte[]">
-</parameter>
-<parameter name="length" type="int">
-</parameter>
-<parameter name="timeout" type="int">
-</parameter>
 </method>
-<method name="claimInterface"
- return="boolean"
+<method name="getDeviceClass"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="intf" type="android.hardware.usb.UsbInterface">
-</parameter>
-<parameter name="force" type="boolean">
-</parameter>
 </method>
-<method name="close"
- return="void"
+<method name="getDeviceId"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
  visibility="public"
 >
 </method>
-<method name="controlTransfer"
+<method name="getDeviceId"
  return="int"
  abstract="false"
  native="false"
  synchronized="false"
- static="false"
+ static="true"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="requestType" type="int">
-</parameter>
-<parameter name="request" type="int">
-</parameter>
-<parameter name="value" type="int">
-</parameter>
-<parameter name="index" type="int">
-</parameter>
-<parameter name="buffer" type="byte[]">
-</parameter>
-<parameter name="length" type="int">
-</parameter>
-<parameter name="timeout" type="int">
+<parameter name="name" type="java.lang.String">
 </parameter>
 </method>
-<method name="describeContents"
- return="int"
+<method name="getDeviceName"
+ return="java.lang.String"
  abstract="false"
  native="false"
  synchronized="false"
  visibility="public"
 >
 </method>
-<method name="getDeviceClass"
- return="int"
+<method name="getDeviceName"
+ return="java.lang.String"
  abstract="false"
  native="false"
  synchronized="false"
- static="false"
+ static="true"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="id" type="int">
+</parameter>
 </method>
-<method name="getDeviceId"
+<method name="getDeviceProtocol"
  return="int"
  abstract="false"
  native="false"
  visibility="public"
 >
 </method>
-<method name="getDeviceId"
+<method name="getDeviceSubclass"
  return="int"
  abstract="false"
  native="false"
  synchronized="false"
- static="true"
+ static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="name" type="java.lang.String">
-</parameter>
 </method>
-<method name="getDeviceName"
- return="java.lang.String"
+<method name="getInterface"
+ return="android.hardware.usb.UsbInterface"
  abstract="false"
  native="false"
  synchronized="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="index" type="int">
+</parameter>
 </method>
-<method name="getDeviceName"
- return="java.lang.String"
+<method name="getInterfaceCount"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
- static="true"
+ static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="id" type="int">
-</parameter>
 </method>
-<method name="getDeviceProtocol"
+<method name="getProductId"
  return="int"
  abstract="false"
  native="false"
  visibility="public"
 >
 </method>
-<method name="getDeviceSubclass"
+<method name="getVendorId"
  return="int"
  abstract="false"
  native="false"
  visibility="public"
 >
 </method>
-<method name="getFileDescriptor"
- return="int"
+<method name="writeToParcel"
+ return="void"
  abstract="false"
  native="false"
  synchronized="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="parcel" type="android.os.Parcel">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
 </method>
-<method name="getInterface"
- return="android.hardware.usb.UsbInterface"
+<field name="CREATOR"
+ type="android.os.Parcelable.Creator"
+ transient="false"
+ volatile="false"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+</class>
+<class name="UsbDeviceConnection"
+ extends="java.lang.Object"
  abstract="false"
- native="false"
- synchronized="false"
  static="false"
  final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="index" type="int">
-</parameter>
-</method>
-<method name="getInterfaceCount"
+<method name="bulkTransfer"
  return="int"
  abstract="false"
  native="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="endpoint" type="android.hardware.usb.UsbEndpoint">
+</parameter>
+<parameter name="buffer" type="byte[]">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+<parameter name="timeout" type="int">
+</parameter>
 </method>
-<method name="getProductId"
- return="int"
+<method name="claimInterface"
+ return="boolean"
  abstract="false"
  native="false"
  synchronized="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="intf" type="android.hardware.usb.UsbInterface">
+</parameter>
+<parameter name="force" type="boolean">
+</parameter>
 </method>
-<method name="getSerial"
- return="java.lang.String"
+<method name="close"
+ return="void"
  abstract="false"
  native="false"
  synchronized="false"
  visibility="public"
 >
 </method>
-<method name="getVendorId"
+<method name="controlTransfer"
  return="int"
  abstract="false"
  native="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="requestType" type="int">
+</parameter>
+<parameter name="request" type="int">
+</parameter>
+<parameter name="value" type="int">
+</parameter>
+<parameter name="index" type="int">
+</parameter>
+<parameter name="buffer" type="byte[]">
+</parameter>
+<parameter name="length" type="int">
+</parameter>
+<parameter name="timeout" type="int">
+</parameter>
 </method>
-<method name="releaseInterface"
- return="boolean"
+<method name="getFileDescriptor"
+ return="int"
  abstract="false"
  native="false"
  synchronized="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="intf" type="android.hardware.usb.UsbInterface">
-</parameter>
 </method>
-<method name="requestWait"
- return="android.hardware.usb.UsbRequest"
+<method name="getSerial"
+ return="java.lang.String"
  abstract="false"
  native="false"
  synchronized="false"
  visibility="public"
 >
 </method>
-<method name="writeToParcel"
- return="void"
+<method name="releaseInterface"
+ return="boolean"
  abstract="false"
  native="false"
  synchronized="false"
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="parcel" type="android.os.Parcel">
-</parameter>
-<parameter name="flags" type="int">
+<parameter name="intf" type="android.hardware.usb.UsbInterface">
 </parameter>
 </method>
-<field name="CREATOR"
- type="android.os.Parcelable.Creator"
- transient="false"
- volatile="false"
- static="true"
- final="true"
+<method name="requestWait"
+ return="android.hardware.usb.UsbRequest"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
-</field>
+</method>
 </class>
 <class name="UsbEndpoint"
  extends="java.lang.Object"
  abstract="false"
  static="false"
- final="true"
+ final="false"
  deprecated="not deprecated"
  visibility="public"
 >
  visibility="public"
 >
 </method>
-<method name="getDevice"
- return="android.hardware.usb.UsbDevice"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getDirection"
  return="int"
  abstract="false"
  visibility="public"
 >
 </method>
-<method name="getInterface"
- return="android.hardware.usb.UsbInterface"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getInterval"
  return="int"
  abstract="false"
  visibility="public"
 >
 </method>
-<method name="getDevice"
- return="android.hardware.usb.UsbDevice"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="getEndpoint"
  return="android.hardware.usb.UsbEndpoint"
  abstract="false"
 </parameter>
 </method>
 <method name="openDevice"
- return="boolean"
+ return="android.hardware.usb.UsbDeviceConnection"
  abstract="false"
  native="false"
  synchronized="false"
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="connection" type="android.hardware.usb.UsbDeviceConnection">
+</parameter>
 <parameter name="endpoint" type="android.hardware.usb.UsbEndpoint">
 </parameter>
 </method>
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="manager" type="android.hardware.usb.UsbManager">
+<parameter name="connection" type="android.hardware.usb.UsbDeviceConnection">
 </parameter>
 </method>
 </class>
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="arg0" type="T">
+<parameter name="t" type="T">
 </parameter>
 </method>
 </interface>
index 39254b3..9e536a7 100644 (file)
@@ -19,33 +19,24 @@ package android.hardware.usb;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
 import java.io.FileDescriptor;
 
-
 /**
  * A class representing a USB device.
  */
-public final class UsbDevice implements Parcelable {
+public class UsbDevice implements Parcelable {
 
     private static final String TAG = "UsbDevice";
 
-    private String mName;
-    private int mVendorId;
-    private int mProductId;
-    private int mClass;
-    private int mSubclass;
-    private int mProtocol;
-    private Parcelable[] mInterfaces;
-
-    // used by the JNI code
-    private int mNativeContext;
-
-    private UsbDevice() {
-    }
-
+    private final String mName;
+    private final int mVendorId;
+    private final int mProductId;
+    private final int mClass;
+    private final int mSubclass;
+    private final int mProtocol;
+    private final Parcelable[] mInterfaces;
 
     /**
      * UsbDevice should only be instantiated by UsbService implementation
@@ -150,114 +141,6 @@ public final class UsbDevice implements Parcelable {
         return (UsbInterface)mInterfaces[index];
     }
 
-    /* package */ boolean open(ParcelFileDescriptor pfd) {
-        return native_open(mName, pfd.getFileDescriptor());
-    }
-
-    /**
-     * Releases all system resources related to the device.
-     */
-    public void close() {
-        native_close();
-    }
-
-    /**
-     * Returns an integer file descriptor for the device, or
-     * -1 if the device is not opened.
-     * This is intended for passing to native code to access the device
-     */
-    public int getFileDescriptor() {
-        return native_get_fd();
-    }
-
-    /**
-     * Claims exclusive access to a {@link android.hardware.usb.UsbInterface}.
-     * This must be done before sending or receiving data on any
-     * {@link android.hardware.usb.UsbEndpoint}s belonging to the interface
-     * @param intf the interface to claim
-     * @param force true to disconnect kernel driver if necessary
-     * @return true if the interface was successfully claimed
-     */
-    public boolean claimInterface(UsbInterface intf, boolean force) {
-        return native_claim_interface(intf.getId(), force);
-    }
-
-    /**
-     * Releases exclusive access to a {@link android.hardware.usb.UsbInterface}.
-     *
-     * @return true if the interface was successfully released
-     */
-    public boolean releaseInterface(UsbInterface intf) {
-        return native_release_interface(intf.getId());
-    }
-
-    /**
-     * Performs a control transaction on endpoint zero for this device.
-     * The direction of the transfer is determined by the request type.
-     * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is
-     * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write,
-     * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer
-     * is a read.
-     *
-     * @param requestType request type for this transaction
-     * @param request request ID for this transaction
-     * @param value value field for this transaction
-     * @param index index field for this transaction
-     * @param buffer buffer for data portion of transaction,
-     * or null if no data needs to be sent or received
-     * @param length the length of the data to send or receive
-     * @param timeout in milliseconds
-     * @return length of data transferred (or zero) for success,
-     * or negative value for failure
-     */
-    public int controlTransfer(int requestType, int request, int value,
-            int index, byte[] buffer, int length, int timeout) {
-        return native_control_request(requestType, request, value, index, buffer, length, timeout);
-    }
-
-    /**
-     * Performs a bulk transaction on the given endpoint.
-     * The direction of the transfer is determined by the direction of the endpoint
-     *
-     * @param endpoint the endpoint for this transaction
-     * @param buffer buffer for data to send or receive,
-     * @param length the length of the data to send or receive
-     * @param timeout in milliseconds
-     * @return length of data transferred (or zero) for success,
-     * or negative value for failure
-     */
-    public int bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) {
-        return native_bulk_request(endpoint.getAddress(), buffer, length, timeout);
-    }
-
-    /**
-     * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation
-     * 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.
-     *
-     * @return a completed USB request, or null if an error occurred
-     */
-    public UsbRequest requestWait() {
-        UsbRequest request = native_request_wait();
-        if (request != null) {
-            request.dequeue();
-        }
-        return request;
-    }
-
-    /**
-     * Returns the serial number for the device.
-     * This will return null if the device has not been opened.
-     *
-     * @return the device serial number
-     */
-    public String getSerial() {
-        return native_get_serial();
-    }
-
     @Override
     public boolean equals(Object o) {
         if (o instanceof UsbDevice) {
@@ -292,11 +175,7 @@ public final class UsbDevice implements Parcelable {
             int subClass = in.readInt();
             int protocol = in.readInt();
             Parcelable[] interfaces = in.readParcelableArray(UsbInterface.class.getClassLoader());
-            UsbDevice result = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol, interfaces);
-            for (int i = 0; i < interfaces.length; i++) {
-                ((UsbInterface)interfaces[i]).setDevice(result);
-            }
-            return result;
+            return new UsbDevice(name, vendorId, productId, clasz, subClass, protocol, interfaces);
         }
 
         public UsbDevice[] newArray(int size) {
@@ -326,17 +205,6 @@ public final class UsbDevice implements Parcelable {
         return native_get_device_name(id);
     }
 
-    private native boolean native_open(String deviceName, FileDescriptor pfd);
-    private native void native_close();
-    private native int native_get_fd();
-    private native boolean native_claim_interface(int interfaceID, boolean force);
-    private native boolean native_release_interface(int interfaceID);
-    private native int native_control_request(int requestType, int request, int value,
-            int index, byte[] buffer, int length, int timeout);
-    private native int native_bulk_request(int endpoint, byte[] buffer, int length, int timeout);
-    private native UsbRequest native_request_wait();
-    private native String native_get_serial();
-
     private static native int native_get_device_id(String name);
     private static native String native_get_device_name(int id);
 }
diff --git a/core/java/android/hardware/usb/UsbDeviceConnection.java b/core/java/android/hardware/usb/UsbDeviceConnection.java
new file mode 100644 (file)
index 0000000..876287c
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.usb;
+
+import android.os.ParcelFileDescriptor;
+import android.util.Log;
+
+import java.io.FileDescriptor;
+
+
+/**
+ * A class representing a USB device.
+ */
+public class UsbDeviceConnection {
+
+    private static final String TAG = "UsbDeviceConnection";
+
+    private final UsbDevice mDevice;
+
+    // used by the JNI code
+    private int mNativeContext;
+
+    /**
+     * UsbDevice should only be instantiated by UsbService implementation
+     * @hide
+     */
+    public UsbDeviceConnection(UsbDevice device) {
+        mDevice = device;
+    }
+
+    /* package */ boolean open(String name, ParcelFileDescriptor pfd) {
+        return native_open(name, pfd.getFileDescriptor());
+    }
+
+    /**
+     * Releases all system resources related to the device.
+     */
+    public void close() {
+        native_close();
+    }
+
+    /**
+     * Returns an integer file descriptor for the device, or
+     * -1 if the device is not opened.
+     * This is intended for passing to native code to access the device
+     */
+    public int getFileDescriptor() {
+        return native_get_fd();
+    }
+
+    /**
+     * Claims exclusive access to a {@link android.hardware.usb.UsbInterface}.
+     * This must be done before sending or receiving data on any
+     * {@link android.hardware.usb.UsbEndpoint}s belonging to the interface
+     * @param intf the interface to claim
+     * @param force true to disconnect kernel driver if necessary
+     * @return true if the interface was successfully claimed
+     */
+    public boolean claimInterface(UsbInterface intf, boolean force) {
+        return native_claim_interface(intf.getId(), force);
+    }
+
+    /**
+     * Releases exclusive access to a {@link android.hardware.usb.UsbInterface}.
+     *
+     * @return true if the interface was successfully released
+     */
+    public boolean releaseInterface(UsbInterface intf) {
+        return native_release_interface(intf.getId());
+    }
+
+    /**
+     * Performs a control transaction on endpoint zero for this device.
+     * The direction of the transfer is determined by the request type.
+     * If requestType & {@link UsbConstants#USB_ENDPOINT_DIR_MASK} is
+     * {@link UsbConstants#USB_DIR_OUT}, then the transfer is a write,
+     * and if it is {@link UsbConstants#USB_DIR_IN}, then the transfer
+     * is a read.
+     *
+     * @param requestType request type for this transaction
+     * @param request request ID for this transaction
+     * @param value value field for this transaction
+     * @param index index field for this transaction
+     * @param buffer buffer for data portion of transaction,
+     * or null if no data needs to be sent or received
+     * @param length the length of the data to send or receive
+     * @param timeout in milliseconds
+     * @return length of data transferred (or zero) for success,
+     * or negative value for failure
+     */
+    public int controlTransfer(int requestType, int request, int value,
+            int index, byte[] buffer, int length, int timeout) {
+        return native_control_request(requestType, request, value, index, buffer, length, timeout);
+    }
+
+    /**
+     * Performs a bulk transaction on the given endpoint.
+     * The direction of the transfer is determined by the direction of the endpoint
+     *
+     * @param endpoint the endpoint for this transaction
+     * @param buffer buffer for data to send or receive,
+     * @param length the length of the data to send or receive
+     * @param timeout in milliseconds
+     * @return length of data transferred (or zero) for success,
+     * or negative value for failure
+     */
+    public int bulkTransfer(UsbEndpoint endpoint, byte[] buffer, int length, int timeout) {
+        return native_bulk_request(endpoint.getAddress(), buffer, length, timeout);
+    }
+
+    /**
+     * Waits for the result of a {@link android.hardware.usb.UsbRequest#queue} operation
+     * 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.
+     *
+     * @return a completed USB request, or null if an error occurred
+     */
+    public UsbRequest requestWait() {
+        UsbRequest request = native_request_wait();
+        if (request != null) {
+            request.dequeue();
+        }
+        return request;
+    }
+
+    /**
+     * Returns the serial number for the device.
+     * This will return null if the device has not been opened.
+     *
+     * @return the device serial number
+     */
+    public String getSerial() {
+        return native_get_serial();
+    }
+
+    private native boolean native_open(String deviceName, FileDescriptor pfd);
+    private native void native_close();
+    private native int native_get_fd();
+    private native boolean native_claim_interface(int interfaceID, boolean force);
+    private native boolean native_release_interface(int interfaceID);
+    private native int native_control_request(int requestType, int request, int value,
+            int index, byte[] buffer, int length, int timeout);
+    private native int native_bulk_request(int endpoint, byte[] buffer, int length, int timeout);
+    private native UsbRequest native_request_wait();
+    private native String native_get_serial();
+}
index a48d88f..bc2c2c1 100644 (file)
@@ -23,16 +23,12 @@ import android.os.Parcelable;
 /**
  * A class representing an endpoint on a {@link android.hardware.usb.UsbInterface}.
  */
-public final class UsbEndpoint implements Parcelable {
+public class UsbEndpoint implements Parcelable {
 
-    private int mAddress;
-    private int mAttributes;
-    private int mMaxPacketSize;
-    private int mInterval;
-    private UsbInterface mInterface;
-
-    private UsbEndpoint() {
-    }
+    private final int mAddress;
+    private final int mAttributes;
+    private final int mMaxPacketSize;
+    private final int mInterval;
 
     /**
      * UsbEndpoint should only be instantiated by UsbService implementation
@@ -119,29 +115,6 @@ public final class UsbEndpoint implements Parcelable {
         return mInterval;
     }
 
-    /**
-     * Returns the {@link android.hardware.usb.UsbInterface} this endpoint belongs to.
-     *
-     * @return the endpoint's interface
-     */
-    public UsbInterface getInterface() {
-        return mInterface;
-    }
-
-    /**
-     * Returns the {@link android.hardware.usb.UsbDevice} this endpoint belongs to.
-     *
-     * @return the endpoint's device
-     */
-    public UsbDevice getDevice() {
-        return mInterface.getDevice();
-    }
-
-    // only used for parcelling
-    /* package */ void setInterface(UsbInterface intf) {
-        mInterface = intf;
-    }
-
     @Override
     public String toString() {
         return "UsbEndpoint[mAddress=" + mAddress + ",mAttributes=" + mAttributes +
index b3b0e81..2b4c7c0 100644 (file)
@@ -25,15 +25,11 @@ import android.os.Parcelable;
  */
 public class UsbInterface implements Parcelable {
 
-    private int mId;
-    private int mClass;
-    private int mSubclass;
-    private int mProtocol;
-    private UsbDevice mDevice;
-    private Parcelable[] mEndpoints;
-
-    private UsbInterface() {
-    }
+    private final int mId;
+    private final int mClass;
+    private final int mSubclass;
+    private final int mProtocol;
+    private final Parcelable[] mEndpoints;
 
     /**
      * UsbInterface should only be instantiated by UsbService implementation
@@ -104,20 +100,6 @@ public class UsbInterface implements Parcelable {
         return (UsbEndpoint)mEndpoints[index];
     }
 
-    /**
-     * Returns the {@link android.hardware.usb.UsbDevice} this interface belongs to.
-     *
-     * @return the interface's device
-     */
-    public UsbDevice getDevice() {
-        return mDevice;
-    }
-
-    // only used for parcelling
-    /* package */ void setDevice(UsbDevice device) {
-        mDevice = device;
-    }
-
     @Override
     public String toString() {
         return "UsbInterface[mId=" + mId + ",mClass=" + mClass +
@@ -133,11 +115,7 @@ public class UsbInterface implements Parcelable {
             int subClass = in.readInt();
             int protocol = in.readInt();
             Parcelable[] endpoints = in.readParcelableArray(UsbEndpoint.class.getClassLoader());
-            UsbInterface result = new UsbInterface(id, Class, subClass, protocol, endpoints);
-            for (int i = 0; i < endpoints.length; i++) {
-                ((UsbEndpoint)endpoints[i]).setInterface(result);
-            }
-            return result;
+            return new UsbInterface(id, Class, subClass, protocol, endpoints);
         }
 
         public UsbInterface[] newArray(int size) {
index e80c744..41ede14 100644 (file)
@@ -227,19 +227,22 @@ public class UsbManager {
      * @param device the device to open
      * @return true if we successfully opened the device
      */
-    public boolean openDevice(UsbDevice device) {
+    public UsbDeviceConnection openDevice(UsbDevice device) {
         try {
-            ParcelFileDescriptor pfd = mService.openDevice(device.getDeviceName());
-            if (pfd == null) {
-                return false;
+            String deviceName = device.getDeviceName();
+            ParcelFileDescriptor pfd = mService.openDevice(deviceName);
+            if (pfd != null) {
+                UsbDeviceConnection connection = new UsbDeviceConnection(device);
+                boolean result = connection.open(deviceName, pfd);
+                pfd.close();
+                if (result) {
+                    return connection;
+                }
             }
-            boolean result = device.open(pfd);
-            pfd.close();
-            return result;
         } catch (Exception e) {
             Log.e(TAG, "exception in UsbManager.openDevice", e);
-            return false;
         }
+        return null;
     }
 
     /**
index 80085c1..5fe6c8c 100644 (file)
@@ -23,9 +23,9 @@ import java.nio.ByteBuffer;
 /**
  * A class representing USB request packet.
  * This can be used for both reading and writing data to or from a
- * {@link android.hardware.usb.UsbDevice}.
+ * {@link android.hardware.usb.UsbDeviceConnection}.
  * UsbRequests are sent asynchronously via {@link #queue} and the results
- * are read by {@link android.hardware.usb.UsbDevice#requestWait}.
+ * are read by {@link android.hardware.usb.UsbDeviceConnection#requestWait}.
  */
 public class UsbRequest {
 
@@ -53,10 +53,9 @@ public class UsbRequest {
      * @param endpoint the endpoint to be used for this request.
      * @return true if the request was successfully opened.
      */
-    public boolean initialize(UsbEndpoint endpoint) {
+    public boolean initialize(UsbDeviceConnection connection, UsbEndpoint endpoint) {
         mEndpoint = endpoint;
-        return native_init(endpoint.getDevice(),
-                endpoint.getAddress(), endpoint.getAttributes(),
+        return native_init(connection, endpoint.getAddress(), endpoint.getAttributes(),
                 endpoint.getMaxPacketSize(), endpoint.getInterval());
     }
 
@@ -94,7 +93,7 @@ public class UsbRequest {
      * This can be used in conjunction with {@link #setClientData}
      * to associate another object with this request, which can be useful for
      * maintaining state between calls to {@link #queue} and
-     * {@link android.hardware.usb.UsbDevice#requestWait}
+     * {@link android.hardware.usb.UsbDeviceConnection#requestWait}
      *
      * @return the client data for the request
      */
@@ -107,7 +106,7 @@ public class UsbRequest {
      * This can be used in conjunction with {@link #getClientData}
      * to associate another object with this request, which can be useful for
      * maintaining state between calls to {@link #queue} and
-     * {@link android.hardware.usb.UsbDevice#requestWait}
+     * {@link android.hardware.usb.UsbDeviceConnection#requestWait}
      *
      * @param data the client data for the request
      */
@@ -121,7 +120,7 @@ public class UsbRequest {
      * For IN endpoints, the endpoint will attempt to read the given number of bytes
      * into the specified buffer.
      * If the queueing operation is successful, we return true and the result will be
-     * returned via {@link android.hardware.usb.UsbDevice#requestWait}
+     * returned via {@link android.hardware.usb.UsbDeviceConnection#requestWait}
      *
      * @param buffer the buffer containing the bytes to write, or location to store
      * the results of a read
@@ -166,8 +165,8 @@ public class UsbRequest {
         return native_cancel();
     }
 
-    private native boolean native_init(UsbDevice device, int ep_address, int ep_attributes,
-            int ep_max_packet_size, int ep_interval);
+    private native boolean native_init(UsbDeviceConnection connection, int ep_address,
+            int ep_attributes, int ep_max_packet_size, int ep_interval);
     private native void native_close();
     private native boolean native_queue_array(byte[] buffer, int length, boolean out);
     private native void native_dequeue_array(byte[] buffer, int length, boolean out);
index 2ed938a..1c4dc29 100644 (file)
@@ -124,6 +124,7 @@ LOCAL_SRC_FILES:= \
        android_hardware_Camera.cpp \
        android_hardware_SensorManager.cpp \
        android_hardware_UsbDevice.cpp \
+       android_hardware_UsbDeviceConnection.cpp \
        android_hardware_UsbRequest.cpp \
        android_debug_JNITest.cpp \
        android_util_FileObserver.cpp \
index 878af3d..0e071a4 100644 (file)
@@ -78,6 +78,7 @@ extern int register_android_opengl_jni_GLES20(JNIEnv* env);
 extern int register_android_hardware_Camera(JNIEnv *env);
 extern int register_android_hardware_SensorManager(JNIEnv *env);
 extern int register_android_hardware_UsbDevice(JNIEnv *env);
+extern int register_android_hardware_UsbDeviceConnection(JNIEnv *env);
 extern int register_android_hardware_UsbRequest(JNIEnv *env);
 
 extern int register_android_media_AudioRecord(JNIEnv *env);
@@ -1274,6 +1275,7 @@ static const RegJNIRec gRegJNI[] = {
     REG_JNI(register_android_hardware_Camera),
     REG_JNI(register_android_hardware_SensorManager),
     REG_JNI(register_android_hardware_UsbDevice),
+    REG_JNI(register_android_hardware_UsbDeviceConnection),
     REG_JNI(register_android_hardware_UsbRequest),
     REG_JNI(register_android_media_AudioRecord),
     REG_JNI(register_android_media_AudioSystem),
index b01820c..c2950ea 100644 (file)
 
 #include <usbhost/usbhost.h>
 
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
 using namespace android;
 
-static jfieldID field_context;
-
-struct usb_device* get_device_from_object(JNIEnv* env, jobject javaDevice)
-{
-    return (struct usb_device*)env->GetIntField(javaDevice, field_context);
-}
-
-// in android_hardware_UsbEndpoint.cpp
-extern struct usb_endpoint* get_endpoint_from_object(JNIEnv* env, jobject javaEndpoint);
-
-static jboolean
-android_hardware_UsbDevice_open(JNIEnv *env, jobject thiz, jstring deviceName,
-        jobject fileDescriptor)
-{
-    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
-    // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy
-    fd = dup(fd);
-    if (fd < 0)
-        return false;
-
-    const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
-    struct usb_device* device = usb_device_new(deviceNameStr, fd);
-    if (device) {
-        env->SetIntField(thiz, field_context, (int)device);
-    } else {
-        LOGE("usb_device_open failed for %s", deviceNameStr);
-        close(fd);
-    }
-
-    env->ReleaseStringUTFChars(deviceName, deviceNameStr);
-    return (device != NULL);
-}
-
-static void
-android_hardware_UsbDevice_close(JNIEnv *env, jobject thiz)
-{
-    LOGD("close\n");
-    struct usb_device* device = get_device_from_object(env, thiz);
-    if (device) {
-        usb_device_close(device);
-        env->SetIntField(thiz, field_context, 0);
-    }
-}
-
-static jint
-android_hardware_UsbDevice_get_fd(JNIEnv *env, jobject thiz)
-{
-    struct usb_device* device = get_device_from_object(env, thiz);
-    if (!device) {
-        LOGE("device is closed in native_get_fd");
-        return -1;
-    }
-    return usb_device_get_fd(device);
-}
-
-static jboolean
-android_hardware_UsbDevice_claim_interface(JNIEnv *env, jobject thiz, int interfaceID, jboolean force)
-{
-    struct usb_device* device = get_device_from_object(env, thiz);
-    if (!device) {
-        LOGE("device is closed in native_claim_interface");
-        return -1;
-    }
-
-    int ret = usb_device_claim_interface(device, interfaceID);
-    if (ret && force && errno == EBUSY) {
-        // disconnect kernel driver and try again
-        usb_device_connect_kernel_driver(device, interfaceID, false);
-        ret = usb_device_claim_interface(device, interfaceID);
-    }
-    return ret == 0;
-}
-
-static jint
-android_hardware_UsbDevice_release_interface(JNIEnv *env, jobject thiz, int interfaceID)
-{
-    struct usb_device* device = get_device_from_object(env, thiz);
-    if (!device) {
-        LOGE("device is closed in native_release_interface");
-        return -1;
-    }
-    int ret = usb_device_release_interface(device, interfaceID);
-    if (ret == 0) {
-        // allow kernel to reconnect its driver
-        usb_device_connect_kernel_driver(device, interfaceID, true);
-    }
-    return ret;
-}
-
-static jint
-android_hardware_UsbDevice_control_request(JNIEnv *env, jobject thiz,
-        jint requestType, jint request, jint value, jint index,
-        jbyteArray buffer, jint length, jint timeout)
-{
-    struct usb_device* device = get_device_from_object(env, thiz);
-    if (!device) {
-        LOGE("device is closed in native_control_request");
-        return -1;
-    }
-
-    jbyte* bufferBytes = NULL;
-    if (buffer) {
-        if (env->GetArrayLength(buffer) < length) {
-            env->ThrowNew(env->FindClass("java/lang/ArrayIndexOutOfBoundsException"), NULL);
-            return -1;
-        }
-        bufferBytes = env->GetByteArrayElements(buffer, 0);
-    }
-
-    jint result = usb_device_control_transfer(device, requestType, request,
-            value, index, bufferBytes, length, timeout);
-
-    if (bufferBytes)
-        env->ReleaseByteArrayElements(buffer, bufferBytes, 0);
-
-    return result;
-}
-
-static jint
-android_hardware_UsbDevice_bulk_request(JNIEnv *env, jobject thiz,
-        jint endpoint, jbyteArray buffer, jint length, jint timeout)
-{
-    struct usb_device* device = get_device_from_object(env, thiz);
-    if (!device) {
-        LOGE("device is closed in native_control_request");
-        return -1;
-    }
-
-    jbyte* bufferBytes = NULL;
-    if (buffer) {
-        if (env->GetArrayLength(buffer) < length) {
-            env->ThrowNew(env->FindClass("java/lang/ArrayIndexOutOfBoundsException"), NULL);
-            return -1;
-        }
-        bufferBytes = env->GetByteArrayElements(buffer, 0);
-    }
-
-    jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout);
-
-    if (bufferBytes)
-        env->ReleaseByteArrayElements(buffer, bufferBytes, 0);
-
-    return result;
-}
-
-static jobject
-android_hardware_UsbDevice_request_wait(JNIEnv *env, jobject thiz)
-{
-    struct usb_device* device = get_device_from_object(env, thiz);
-    if (!device) {
-        LOGE("device is closed in native_request_wait");
-        return NULL;
-    }
-
-    struct usb_request* request = usb_request_wait(device);
-    if (request)
-        return (jobject)request->client_data;
-    else
-        return NULL;
-}
-
-static jstring
-android_hardware_UsbDevice_get_serial(JNIEnv *env, jobject thiz)
-{
-    struct usb_device* device = get_device_from_object(env, thiz);
-    if (!device) {
-        LOGE("device is closed in native_request_wait");
-        return NULL;
-    }
-    char* serial = usb_device_get_serial(device);
-    if (!serial)
-        return NULL;
-    jstring result = env->NewStringUTF(serial);
-    free(serial);
-    return result;
-}
-
 static jint
 android_hardware_UsbDevice_get_device_id(JNIEnv *env, jobject clazz, jstring name)
 {
@@ -227,21 +45,6 @@ android_hardware_UsbDevice_get_device_name(JNIEnv *env, jobject clazz, jint id)
 }
 
 static JNINativeMethod method_table[] = {
-    {"native_open",             "(Ljava/lang/String;Ljava/io/FileDescriptor;)Z",
-                                        (void *)android_hardware_UsbDevice_open},
-    {"native_close",            "()V",  (void *)android_hardware_UsbDevice_close},
-    {"native_get_fd",           "()I",  (void *)android_hardware_UsbDevice_get_fd},
-    {"native_claim_interface",  "(IZ)Z",(void *)android_hardware_UsbDevice_claim_interface},
-    {"native_release_interface","(I)Z", (void *)android_hardware_UsbDevice_release_interface},
-    {"native_control_request",  "(IIII[BII)I",
-                                        (void *)android_hardware_UsbDevice_control_request},
-    {"native_bulk_request",     "(I[BII)I",
-                                        (void *)android_hardware_UsbDevice_bulk_request},
-    {"native_request_wait",             "()Landroid/hardware/usb/UsbRequest;",
-                                        (void *)android_hardware_UsbDevice_request_wait},
-    { "native_get_serial",      "()Ljava/lang/String;",
-                                        (void*)android_hardware_UsbDevice_get_serial },
-
     // static methods
     { "native_get_device_id", "(Ljava/lang/String;)I",
                                         (void*)android_hardware_UsbDevice_get_device_id },
@@ -256,11 +59,6 @@ int register_android_hardware_UsbDevice(JNIEnv *env)
         LOGE("Can't find android/hardware/usb/UsbDevice");
         return -1;
     }
-    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
-    if (field_context == NULL) {
-        LOGE("Can't find UsbDevice.mNativeContext");
-        return -1;
-    }
 
     return AndroidRuntime::registerNativeMethods(env, "android/hardware/usb/UsbDevice",
             method_table, NELEM(method_table));
diff --git a/core/jni/android_hardware_UsbDeviceConnection.cpp b/core/jni/android_hardware_UsbDeviceConnection.cpp
new file mode 100644 (file)
index 0000000..ec36a38
--- /dev/null
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "UsbDeviceConnectionJNI"
+
+#include "utils/Log.h"
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#include <usbhost/usbhost.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+using namespace android;
+
+static jfieldID field_context;
+
+struct usb_device* get_device_from_object(JNIEnv* env, jobject connection)
+{
+    return (struct usb_device*)env->GetIntField(connection, field_context);
+}
+
+static jboolean
+android_hardware_UsbDeviceConnection_open(JNIEnv *env, jobject thiz, jstring deviceName,
+        jobject fileDescriptor)
+{
+    int fd = getParcelFileDescriptorFD(env, fileDescriptor);
+    // duplicate the file descriptor, since ParcelFileDescriptor will eventually close its copy
+    fd = dup(fd);
+    if (fd < 0)
+        return false;
+
+    const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
+    struct usb_device* device = usb_device_new(deviceNameStr, fd);
+    if (device) {
+        env->SetIntField(thiz, field_context, (int)device);
+    } else {
+        LOGE("usb_device_open failed for %s", deviceNameStr);
+        close(fd);
+    }
+
+    env->ReleaseStringUTFChars(deviceName, deviceNameStr);
+    return (device != NULL);
+}
+
+static void
+android_hardware_UsbDeviceConnection_close(JNIEnv *env, jobject thiz)
+{
+    LOGD("close\n");
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (device) {
+        usb_device_close(device);
+        env->SetIntField(thiz, field_context, 0);
+    }
+}
+
+static jint
+android_hardware_UsbDeviceConnection_get_fd(JNIEnv *env, jobject thiz)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        LOGE("device is closed in native_get_fd");
+        return -1;
+    }
+    return usb_device_get_fd(device);
+}
+
+static jboolean
+android_hardware_UsbDeviceConnection_claim_interface(JNIEnv *env, jobject thiz,
+        int interfaceID, jboolean force)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        LOGE("device is closed in native_claim_interface");
+        return -1;
+    }
+
+    int ret = usb_device_claim_interface(device, interfaceID);
+    if (ret && force && errno == EBUSY) {
+        // disconnect kernel driver and try again
+        usb_device_connect_kernel_driver(device, interfaceID, false);
+        ret = usb_device_claim_interface(device, interfaceID);
+    }
+    return ret == 0;
+}
+
+static jint
+android_hardware_UsbDeviceConnection_release_interface(JNIEnv *env, jobject thiz, int interfaceID)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        LOGE("device is closed in native_release_interface");
+        return -1;
+    }
+    int ret = usb_device_release_interface(device, interfaceID);
+    if (ret == 0) {
+        // allow kernel to reconnect its driver
+        usb_device_connect_kernel_driver(device, interfaceID, true);
+    }
+    return ret;
+}
+
+static jint
+android_hardware_UsbDeviceConnection_control_request(JNIEnv *env, jobject thiz,
+        jint requestType, jint request, jint value, jint index,
+        jbyteArray buffer, jint length, jint timeout)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        LOGE("device is closed in native_control_request");
+        return -1;
+    }
+
+    jbyte* bufferBytes = NULL;
+    if (buffer) {
+        if (env->GetArrayLength(buffer) < length) {
+            env->ThrowNew(env->FindClass("java/lang/ArrayIndexOutOfBoundsException"), NULL);
+            return -1;
+        }
+        bufferBytes = env->GetByteArrayElements(buffer, 0);
+    }
+
+    jint result = usb_device_control_transfer(device, requestType, request,
+            value, index, bufferBytes, length, timeout);
+
+    if (bufferBytes)
+        env->ReleaseByteArrayElements(buffer, bufferBytes, 0);
+
+    return result;
+}
+
+static jint
+android_hardware_UsbDeviceConnection_bulk_request(JNIEnv *env, jobject thiz,
+        jint endpoint, jbyteArray buffer, jint length, jint timeout)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        LOGE("device is closed in native_control_request");
+        return -1;
+    }
+
+    jbyte* bufferBytes = NULL;
+    if (buffer) {
+        if (env->GetArrayLength(buffer) < length) {
+            env->ThrowNew(env->FindClass("java/lang/ArrayIndexOutOfBoundsException"), NULL);
+            return -1;
+        }
+        bufferBytes = env->GetByteArrayElements(buffer, 0);
+    }
+
+    jint result = usb_device_bulk_transfer(device, endpoint, bufferBytes, length, timeout);
+
+    if (bufferBytes)
+        env->ReleaseByteArrayElements(buffer, bufferBytes, 0);
+
+    return result;
+}
+
+static jobject
+android_hardware_UsbDeviceConnection_request_wait(JNIEnv *env, jobject thiz)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        LOGE("device is closed in native_request_wait");
+        return NULL;
+    }
+
+    struct usb_request* request = usb_request_wait(device);
+    if (request)
+        return (jobject)request->client_data;
+    else
+        return NULL;
+}
+
+static jstring
+android_hardware_UsbDeviceConnection_get_serial(JNIEnv *env, jobject thiz)
+{
+    struct usb_device* device = get_device_from_object(env, thiz);
+    if (!device) {
+        LOGE("device is closed in native_request_wait");
+        return NULL;
+    }
+    char* serial = usb_device_get_serial(device);
+    if (!serial)
+        return NULL;
+    jstring result = env->NewStringUTF(serial);
+    free(serial);
+    return result;
+}
+
+static JNINativeMethod method_table[] = {
+    {"native_open",             "(Ljava/lang/String;Ljava/io/FileDescriptor;)Z",
+                                        (void *)android_hardware_UsbDeviceConnection_open},
+    {"native_close",            "()V",  (void *)android_hardware_UsbDeviceConnection_close},
+    {"native_get_fd",           "()I",  (void *)android_hardware_UsbDeviceConnection_get_fd},
+    {"native_claim_interface",  "(IZ)Z",(void *)android_hardware_UsbDeviceConnection_claim_interface},
+    {"native_release_interface","(I)Z", (void *)android_hardware_UsbDeviceConnection_release_interface},
+    {"native_control_request",  "(IIII[BII)I",
+                                        (void *)android_hardware_UsbDeviceConnection_control_request},
+    {"native_bulk_request",     "(I[BII)I",
+                                        (void *)android_hardware_UsbDeviceConnection_bulk_request},
+    {"native_request_wait",             "()Landroid/hardware/usb/UsbRequest;",
+                                        (void *)android_hardware_UsbDeviceConnection_request_wait},
+    { "native_get_serial",      "()Ljava/lang/String;",
+                                        (void*)android_hardware_UsbDeviceConnection_get_serial },
+};
+
+int register_android_hardware_UsbDeviceConnection(JNIEnv *env)
+{
+    jclass clazz = env->FindClass("android/hardware/usb/UsbDeviceConnection");
+    if (clazz == NULL) {
+        LOGE("Can't find android/hardware/usb/UsbDeviceConnection");
+        return -1;
+    }
+    field_context = env->GetFieldID(clazz, "mNativeContext", "I");
+    if (field_context == NULL) {
+        LOGE("Can't find UsbDeviceConnection.mNativeContext");
+        return -1;
+    }
+
+    return AndroidRuntime::registerNativeMethods(env, "android/hardware/usb/UsbDeviceConnection",
+            method_table, NELEM(method_table));
+}
+
index b497adb..6bd67d1 100644 (file)
@@ -35,8 +35,8 @@ struct usb_request* get_request_from_object(JNIEnv* env, jobject java_request)
     return (struct usb_request*)env->GetIntField(java_request, field_context);
 }
 
-// in android_hardware_UsbDevice.cpp
-extern struct usb_device* get_device_from_object(JNIEnv* env, jobject java_device);
+// in android_hardware_UsbDeviceConnection.cpp
+extern struct usb_device* get_device_from_object(JNIEnv* env, jobject connection);
 
 static jboolean
 android_hardware_UsbRequest_init(JNIEnv *env, jobject thiz, jobject java_device,
@@ -107,7 +107,7 @@ android_hardware_UsbRequest_queue_array(JNIEnv *env, jobject thiz,
         }
         return false;
     } else {
-        // save a reference to ourselves so UsbDevice.waitRequest() can find us
+        // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
         request->client_data = (void *)env->NewGlobalRef(thiz);
         return true;
     }
@@ -155,7 +155,7 @@ android_hardware_UsbRequest_queue_direct(JNIEnv *env, jobject thiz,
         request->buffer = NULL;
         return false;
     } else {
-        // save a reference to ourselves so UsbDevice.waitRequest() can find us
+        // save a reference to ourselves so UsbDeviceConnection.waitRequest() can find us
         // we also need this to make sure our native buffer is not deallocated
         // while IO is active
         request->client_data = (void *)env->NewGlobalRef(thiz);
@@ -187,7 +187,7 @@ android_hardware_UsbRequest_cancel(JNIEnv *env, jobject thiz)
 }
 
 static JNINativeMethod method_table[] = {
-    {"native_init",             "(Landroid/hardware/usb/UsbDevice;IIII)Z",
+    {"native_init",             "(Landroid/hardware/usb/UsbDeviceConnection;IIII)Z",
                                             (void *)android_hardware_UsbRequest_init},
     {"native_close",            "()V",      (void *)android_hardware_UsbRequest_close},
     {"native_queue_array",      "([BIZ)Z",  (void *)android_hardware_UsbRequest_queue_array},
index d25dcb9..3859caf 100644 (file)
@@ -23,6 +23,7 @@ import android.content.Intent;
 import android.content.IntentFilter;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
+import android.hardware.usb.UsbDeviceConnection;
 import android.hardware.usb.UsbInterface;
 import android.hardware.usb.UsbManager;
 import android.os.ParcelFileDescriptor;
@@ -168,10 +169,13 @@ public class MtpClient {
             if (!mUsbManager.hasPermission(usbDevice)) {
                 mUsbManager.requestPermission(usbDevice, mPermissionIntent);
             } else {
-                MtpDevice mtpDevice = new MtpDevice(usbDevice);
-                if (mtpDevice.open(mUsbManager)) {
-                    mDevices.put(usbDevice.getDeviceName(), mtpDevice);
-                    return mtpDevice;
+                UsbDeviceConnection connection = mUsbManager.openDevice(usbDevice);
+                if (connection != null) {
+                    MtpDevice mtpDevice = new MtpDevice(usbDevice);
+                    if (mtpDevice.open(connection)) {
+                        mDevices.put(usbDevice.getDeviceName(), mtpDevice);
+                        return mtpDevice;
+                    }
                 }
             }
         }
index 22961d7..db2cebd 100644 (file)
@@ -17,7 +17,7 @@
 package android.mtp;
 
 import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbManager;
+import android.hardware.usb.UsbDeviceConnection;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
 
@@ -44,17 +44,20 @@ public final class MtpDevice {
     }
 
     /**
-     * Opens the MTP or PTP device and return an {@link android.mtp.MtpDevice} for it.
+     * Opens the MTP device.  Once the device is open it takes ownership of the
+     * {@link android.hardware.usb.UsbDeviceConnection}.  
+     * The connection will be closed when you call {@link #close()}
+     * The connection will also be closed if this method fails.
      *
-     * @param manager reference to {@link android.hardware.usb.UsbManager}
+     * @param connection an open {@link android.hardware.usb.UsbDeviceConnection} for the device
      * @return true if the device was successfully opened.
      */
-    public boolean open(UsbManager manager) {
-        if (manager.openDevice(mDevice)) {
-            return native_open(mDevice.getDeviceName(), mDevice.getFileDescriptor());
-        } else {
-            return false;
+    public boolean open(UsbDeviceConnection connection) {
+        boolean result = native_open(mDevice.getDeviceName(), connection.getFileDescriptor());
+        if (!result) {
+            connection.close();
         }
+        return result;
     }
 
     /**