New APIs for USB host support:
UsbManager: - is now a service retrievable via Context.getSystemService(Context.USB_SERVICE). - provides support for returning a list all connected USB devices - broadcasts ACTION_USB_DEVICE_ATTACHED and USB_DEVICE_DETACHED when devices are added and removed from the USB host bus UsbDevice: - represents an attached USB device. UsbInterface: - represents an interface on a USB device - devices may have multiple interfaces if they provide multiple sets of functionality (for example, android phones typically have interfaces for both USB mass storage and adb) UsbEndpoint: - represents an endpoint on a USB interface - endpoints are used for sending or receiving data (only in one or the other direction) UsbRequest: - encapsulates a send or receive request to be sent over an endpoint Change-Id: Ieef3e434c62760770ea839070cf5eba1a705967a Signed-off-by: Mike Lockwood <lockwood@android.com>
This commit is contained in:
@@ -115,6 +115,7 @@ LOCAL_SRC_FILES += \
|
||||
core/java/android/content/pm/IPackageMoveObserver.aidl \
|
||||
core/java/android/content/pm/IPackageStatsObserver.aidl \
|
||||
core/java/android/database/IContentObserver.aidl \
|
||||
core/java/android/hardware/IUsbManager.aidl \
|
||||
core/java/android/net/IConnectivityManager.aidl \
|
||||
core/java/android/net/INetworkManagementEventObserver.aidl \
|
||||
core/java/android/net/IThrottleManager.aidl \
|
||||
|
||||
1280
api/current.xml
1280
api/current.xml
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,9 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteDatabase.CursorFactory;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.IUsbManager;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.UsbManager;
|
||||
import android.location.CountryDetector;
|
||||
import android.location.ICountryDetector;
|
||||
import android.location.ILocationManager;
|
||||
@@ -399,6 +401,12 @@ class ContextImpl extends Context {
|
||||
return new UiModeManager();
|
||||
}});
|
||||
|
||||
registerService(USB_SERVICE, new StaticServiceFetcher() {
|
||||
public Object createStaticService() {
|
||||
IBinder b = ServiceManager.getService(USB_SERVICE);
|
||||
return new UsbManager(IUsbManager.Stub.asInterface(b));
|
||||
}});
|
||||
|
||||
registerService(VIBRATOR_SERVICE, new ServiceFetcher() {
|
||||
public Object createService(ContextImpl ctx) {
|
||||
return new Vibrator();
|
||||
|
||||
@@ -1662,6 +1662,16 @@ public abstract class Context {
|
||||
/** @hide */
|
||||
public static final String SIP_SERVICE = "sip";
|
||||
|
||||
/**
|
||||
* Use with {@link #getSystemService} to retrieve a {@link
|
||||
* android.hardware.UsbManager} for access to USB devices (as a USB host)
|
||||
* and for controlling this device's behavior as a USB device.
|
||||
*
|
||||
* @see #getSystemService
|
||||
* @see android.harware.UsbManager
|
||||
*/
|
||||
public static final String USB_SERVICE = "usb";
|
||||
|
||||
/**
|
||||
* Determine whether the given permission is allowed for a particular
|
||||
* process and user ID running in the system.
|
||||
|
||||
28
core/java/android/hardware/IUsbManager.aidl
Normal file
28
core/java/android/hardware/IUsbManager.aidl
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
|
||||
/** @hide */
|
||||
interface IUsbManager
|
||||
{
|
||||
/* Returns a list of all currently attached USB devices */
|
||||
void getDeviceList(out Bundle devices);
|
||||
ParcelFileDescriptor openDevice(String deviceName);
|
||||
}
|
||||
63
core/java/android/hardware/UsbConstants.java
Normal file
63
core/java/android/hardware/UsbConstants.java
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
/**
|
||||
* Contains constants for the USB protocol.
|
||||
* These constants correspond to definitions in linux/usb/ch9.h in the linux kernel.
|
||||
*/
|
||||
public final class UsbConstants {
|
||||
|
||||
public static final int USB_ENDPOINT_DIR_MASK = 0x80;
|
||||
public static final int USB_DIR_OUT = 0;
|
||||
public static final int USB_DIR_IN = 0x80;
|
||||
|
||||
public static final int USB_TYPE_MASK = (0x03 << 5);
|
||||
public static final int USB_TYPE_STANDARD = (0x00 << 5);
|
||||
public static final int USB_TYPE_CLASS = (0x01 << 5);
|
||||
public static final int USB_TYPE_VENDOR = (0x02 << 5);
|
||||
public static final int USB_TYPE_RESERVED = (0x03 << 5);
|
||||
|
||||
public static final int USB_ENDPOINT_NUMBER_MASK = 0x0f;
|
||||
|
||||
// flags for endpoint attributes
|
||||
public static final int USB_ENDPOINT_XFERTYPE_MASK = 0x03;
|
||||
public static final int USB_ENDPOINT_XFER_CONTROL = 0;
|
||||
public static final int USB_ENDPOINT_XFER_ISOC = 1;
|
||||
public static final int USB_ENDPOINT_XFER_BULK = 2;
|
||||
public static final int USB_ENDPOINT_XFER_INT = 3;
|
||||
|
||||
public static final int USB_CLASS_PER_INTERFACE = 0;
|
||||
public static final int USB_CLASS_AUDIO = 1;
|
||||
public static final int USB_CLASS_COMM = 2;
|
||||
public static final int USB_CLASS_HID = 3;
|
||||
public static final int USB_CLASS_PHYSICA = 5;
|
||||
public static final int USB_CLASS_STILL_IMAGE = 6;
|
||||
public static final int USB_CLASS_PRINTER = 7;
|
||||
public static final int USB_CLASS_MASS_STORAGE = 8;
|
||||
public static final int USB_CLASS_HUB = 9;
|
||||
public static final int USB_CLASS_CDC_DATA = 0x0a;
|
||||
public static final int USB_CLASS_CSCID = 0x0b;
|
||||
public static final int USB_CLASS_CONTENT_SEC = 0x0d;
|
||||
public static final int USB_CLASS_VIDEO = 0x0e;
|
||||
public static final int USB_CLASS_WIRELESS_CONTROLLER = 0xe0;
|
||||
public static final int USB_CLASS_MISC = 0xef;
|
||||
public static final int USB_CLASS_APP_SPEC = 0xfe;
|
||||
public static final int USB_CLASS_VENDOR_SPEC = 0xff;
|
||||
public static final int USB_SUBCLASS_VENDOR_SPEC = 0xff;
|
||||
|
||||
}
|
||||
19
core/java/android/hardware/UsbDevice.aidl
Normal file
19
core/java/android/hardware/UsbDevice.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2010, 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;
|
||||
|
||||
parcelable UsbDevice;
|
||||
314
core/java/android/hardware/UsbDevice.java
Normal file
314
core/java/android/hardware/UsbDevice.java
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
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 {
|
||||
|
||||
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() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* UsbDevice should only be instantiated by UsbService implementation
|
||||
* @hide
|
||||
*/
|
||||
public UsbDevice(String name, int vendorId, int productId,
|
||||
int Class, int subClass, int protocol, Parcelable[] interfaces) {
|
||||
mName = name;
|
||||
mVendorId = vendorId;
|
||||
mProductId = productId;
|
||||
mClass = Class;
|
||||
mSubclass = subClass;
|
||||
mProtocol = protocol;
|
||||
mInterfaces = interfaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the device.
|
||||
* In the standard implementation, this is the path of the device file
|
||||
* for the device in the usbfs file system.
|
||||
*
|
||||
* @return the device name
|
||||
*/
|
||||
public String getDeviceName() {
|
||||
return mName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a unique integer ID for the device.
|
||||
* This is a convenience for clients that want to use an integer to represent
|
||||
* the device, rather than the device name.
|
||||
* IDs are not persistent across USB disconnects.
|
||||
*
|
||||
* @return the device ID
|
||||
*/
|
||||
public int getDeviceId() {
|
||||
return getDeviceId(mName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a vendor ID for the device.
|
||||
*
|
||||
* @return the device vendor ID
|
||||
*/
|
||||
public int getVendorId() {
|
||||
return mVendorId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a product ID for the device.
|
||||
*
|
||||
* @return the device product ID
|
||||
*/
|
||||
public int getProductId() {
|
||||
return mProductId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the devices's class field.
|
||||
* Some useful constants for USB device classes can be found in
|
||||
* {@link android.hardware.UsbConstants}
|
||||
*
|
||||
* @return the devices's class
|
||||
*/
|
||||
public int getDeviceClass() {
|
||||
return mClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the device's subclass field.
|
||||
*
|
||||
* @return the device's subclass
|
||||
*/
|
||||
public int getDeviceSubclass() {
|
||||
return mSubclass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the device's subclass field.
|
||||
*
|
||||
* @return the device's protocol
|
||||
*/
|
||||
public int getDeviceProtocol() {
|
||||
return mProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of {@link android.hardware.UsbInterface}s this device contains.
|
||||
*
|
||||
* @return the number of interfaces
|
||||
*/
|
||||
public int getInterfaceCount() {
|
||||
return mInterfaces.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link android.hardware.UsbInterface} at the given index.
|
||||
*
|
||||
* @return the interface
|
||||
*/
|
||||
public UsbInterface getInterface(int index) {
|
||||
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.UsbInterface}.
|
||||
* This must be done before sending or receiving data on any
|
||||
* {@link android.hardware.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.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.
|
||||
*
|
||||
* @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
|
||||
* @return length of data transferred (or zero) for success,
|
||||
* or negative value for failure
|
||||
*/
|
||||
public int sendControlRequest(int requestType, int request, int value,
|
||||
int index, byte[] buffer, int length) {
|
||||
return native_control_request(requestType, request, value, index, buffer, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for the result of a {@link android.hardware.UsbRequest#queue} operation
|
||||
* Note that this may return requests queued on multiple {@link android.hardware.UsbEndpoint}s.
|
||||
* When multiple endpoints are in use, {@link android.hardware.UsbRequest#getEndpoint} and
|
||||
* {@link android.hardware.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) {
|
||||
return ((UsbDevice)o).mName.equals(mName);
|
||||
} else if (o instanceof String) {
|
||||
return ((String)o).equals(mName);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UsbDevice[mName=" + mName + ",mVendorId=" + mVendorId +
|
||||
",mProductId=" + mProductId + ",mClass=" + mClass +
|
||||
",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
|
||||
",mInterfaces=" + mInterfaces + "]";
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<UsbDevice> CREATOR =
|
||||
new Parcelable.Creator<UsbDevice>() {
|
||||
public UsbDevice createFromParcel(Parcel in) {
|
||||
String name = in.readString();
|
||||
int vendorId = in.readInt();
|
||||
int productId = in.readInt();
|
||||
int clasz = in.readInt();
|
||||
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;
|
||||
}
|
||||
|
||||
public UsbDevice[] newArray(int size) {
|
||||
return new UsbDevice[size];
|
||||
}
|
||||
};
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeString(mName);
|
||||
parcel.writeInt(mVendorId);
|
||||
parcel.writeInt(mProductId);
|
||||
parcel.writeInt(mClass);
|
||||
parcel.writeInt(mSubclass);
|
||||
parcel.writeInt(mProtocol);
|
||||
parcel.writeParcelableArray(mInterfaces, 0);
|
||||
}
|
||||
|
||||
public static int getDeviceId(String name) {
|
||||
return native_get_device_id(name);
|
||||
}
|
||||
|
||||
public static String getDeviceName(int id) {
|
||||
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);
|
||||
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);
|
||||
}
|
||||
19
core/java/android/hardware/UsbEndpoint.aidl
Normal file
19
core/java/android/hardware/UsbEndpoint.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
parcelable UsbEndpoint;
|
||||
176
core/java/android/hardware/UsbEndpoint.java
Normal file
176
core/java/android/hardware/UsbEndpoint.java
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* A class representing an endpoint on a {@link android.hardware.UsbInterface}.
|
||||
*/
|
||||
public final class UsbEndpoint implements Parcelable {
|
||||
|
||||
private int mAddress;
|
||||
private int mAttributes;
|
||||
private int mMaxPacketSize;
|
||||
private int mInterval;
|
||||
private UsbInterface mInterface;
|
||||
|
||||
private UsbEndpoint() {
|
||||
}
|
||||
|
||||
/**
|
||||
* UsbEndpoint should only be instantiated by UsbService implementation
|
||||
* @hide
|
||||
*/
|
||||
public UsbEndpoint(int address, int attributes, int maxPacketSize, int interval) {
|
||||
mAddress = address;
|
||||
mAttributes = attributes;
|
||||
mMaxPacketSize = maxPacketSize;
|
||||
mInterval = interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the endpoint's address field.
|
||||
*
|
||||
* @return the endpoint's address
|
||||
*/
|
||||
public int getAddress() {
|
||||
return mAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the endpoint's endpoint number from its address
|
||||
*
|
||||
* @return the endpoint's endpoint number
|
||||
*/
|
||||
public int getEndpointNumber() {
|
||||
return mAddress & UsbConstants.USB_ENDPOINT_NUMBER_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the endpoint's direction.
|
||||
* Returns {@link android.hardware.UsbConstants#USB_DIR_OUT}
|
||||
* if the direction is host to device, and
|
||||
* {@link android.hardware.UsbConstants#USB_DIR_IN} if the
|
||||
* direction is device to host.
|
||||
*
|
||||
* @return the endpoint's direction
|
||||
*/
|
||||
public int getDirection() {
|
||||
return mAddress & UsbConstants.USB_ENDPOINT_DIR_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the endpoint's attributes field.
|
||||
*
|
||||
* @return the endpoint's attributes
|
||||
*/
|
||||
public int getAttributes() {
|
||||
return mAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the endpoint's type.
|
||||
* Possible results are:
|
||||
* <ul>
|
||||
* <li>{@link android.hardware.UsbConstants#USB_ENDPOINT_XFER_CONTROL} (endpoint zero)
|
||||
* <li>{@link android.hardware.UsbConstants#USB_ENDPOINT_XFER_ISOC} (isochronous endpoint)
|
||||
* <li>{@link android.hardware.UsbConstants#USB_ENDPOINT_XFER_BULK} (bulk endpoint)
|
||||
* <li>{@link android.hardware.UsbConstants#USB_ENDPOINT_XFER_INT} (interrupt endpoint)
|
||||
* </ul>
|
||||
*
|
||||
* @return the endpoint's type
|
||||
*/
|
||||
public int getType() {
|
||||
return mAttributes & UsbConstants.USB_ENDPOINT_XFERTYPE_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the endpoint's maximum packet size.
|
||||
*
|
||||
* @return the endpoint's maximum packet size
|
||||
*/
|
||||
public int getMaxPacketSize() {
|
||||
return mMaxPacketSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the endpoint's interval field.
|
||||
*
|
||||
* @return the endpoint's interval
|
||||
*/
|
||||
public int getInterval() {
|
||||
return mInterval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link android.hardware.UsbInterface} this endpoint belongs to.
|
||||
*
|
||||
* @return the endpoint's interface
|
||||
*/
|
||||
public UsbInterface getInterface() {
|
||||
return mInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link android.hardware.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 +
|
||||
",mMaxPacketSize=" + mMaxPacketSize + ",mInterval=" + mInterval +"]";
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<UsbEndpoint> CREATOR =
|
||||
new Parcelable.Creator<UsbEndpoint>() {
|
||||
public UsbEndpoint createFromParcel(Parcel in) {
|
||||
int address = in.readInt();
|
||||
int attributes = in.readInt();
|
||||
int maxPacketSize = in.readInt();
|
||||
int interval = in.readInt();
|
||||
return new UsbEndpoint(address, attributes, maxPacketSize, interval);
|
||||
}
|
||||
|
||||
public UsbEndpoint[] newArray(int size) {
|
||||
return new UsbEndpoint[size];
|
||||
}
|
||||
};
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeInt(mAddress);
|
||||
parcel.writeInt(mAttributes);
|
||||
parcel.writeInt(mMaxPacketSize);
|
||||
parcel.writeInt(mInterval);
|
||||
}
|
||||
}
|
||||
19
core/java/android/hardware/UsbInterface.aidl
Normal file
19
core/java/android/hardware/UsbInterface.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
parcelable UsbInterface;
|
||||
159
core/java/android/hardware/UsbInterface.java
Normal file
159
core/java/android/hardware/UsbInterface.java
Normal file
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* A class representing an interface on a {@link android.hardware.UsbDevice}.
|
||||
*/
|
||||
public final class UsbInterface implements Parcelable {
|
||||
|
||||
private int mId;
|
||||
private int mClass;
|
||||
private int mSubclass;
|
||||
private int mProtocol;
|
||||
private UsbDevice mDevice;
|
||||
private Parcelable[] mEndpoints;
|
||||
|
||||
private UsbInterface() {
|
||||
}
|
||||
|
||||
/**
|
||||
* UsbInterface should only be instantiated by UsbService implementation
|
||||
* @hide
|
||||
*/
|
||||
public UsbInterface(int id, int Class, int subClass, int protocol,
|
||||
Parcelable[] endpoints) {
|
||||
mId = id;
|
||||
mClass = Class;
|
||||
mSubclass = subClass;
|
||||
mProtocol = protocol;
|
||||
mEndpoints = endpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interface's ID field.
|
||||
*
|
||||
* @return the interface's ID
|
||||
*/
|
||||
public int getId() {
|
||||
return mId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interface's class field.
|
||||
* Some useful constants for USB classes can be found in
|
||||
* {@link android.hardware.UsbConstants}
|
||||
*
|
||||
* @return the interface's class
|
||||
*/
|
||||
public int getInterfaceClass() {
|
||||
return mClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interface's subclass field.
|
||||
*
|
||||
* @return the interface's subclass
|
||||
*/
|
||||
public int getInterfaceSubclass() {
|
||||
return mSubclass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interface's protocol field.
|
||||
*
|
||||
* @return the interface's protocol
|
||||
*/
|
||||
public int getInterfaceProtocol() {
|
||||
return mProtocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of {@link android.hardware.UsbEndpoint}s this interface contains.
|
||||
*
|
||||
* @return the number of endpoints
|
||||
*/
|
||||
public int getEndpointCount() {
|
||||
return mEndpoints.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link android.hardware.UsbEndpoint} at the given index.
|
||||
*
|
||||
* @return the endpoint
|
||||
*/
|
||||
public UsbEndpoint getEndpoint(int index) {
|
||||
return (UsbEndpoint)mEndpoints[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link android.hardware.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 +
|
||||
",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
|
||||
",mEndpoints=" + mEndpoints + "]";
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<UsbInterface> CREATOR =
|
||||
new Parcelable.Creator<UsbInterface>() {
|
||||
public UsbInterface createFromParcel(Parcel in) {
|
||||
int id = in.readInt();
|
||||
int Class = in.readInt();
|
||||
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;
|
||||
}
|
||||
|
||||
public UsbInterface[] newArray(int size) {
|
||||
return new UsbInterface[size];
|
||||
}
|
||||
};
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel parcel, int flags) {
|
||||
parcel.writeInt(mId);
|
||||
parcel.writeInt(mClass);
|
||||
parcel.writeInt(mSubclass);
|
||||
parcel.writeInt(mProtocol);
|
||||
parcel.writeParcelableArray(mEndpoints, 0);
|
||||
}
|
||||
}
|
||||
@@ -17,17 +17,31 @@
|
||||
|
||||
package android.hardware;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Class for accessing USB state information.
|
||||
* @hide
|
||||
* This class allows you to access the state of USB, both in host and device mode.
|
||||
*
|
||||
* <p>You can obtain an instance of this class by calling
|
||||
* {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
|
||||
*
|
||||
* {@samplecode
|
||||
* UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);
|
||||
* }
|
||||
*/
|
||||
public class UsbManager {
|
||||
private static final String TAG = "UsbManager";
|
||||
|
||||
/**
|
||||
* Broadcast Action: A sticky broadcast for USB state change events.
|
||||
* Broadcast Action: A sticky broadcast for USB state change events when in device mode.
|
||||
*
|
||||
* This is a sticky broadcast for clients that includes USB connected/disconnected state,
|
||||
* the USB configuration that is currently set and a bundle containing name/value pairs
|
||||
@@ -39,6 +53,22 @@ public class UsbManager {
|
||||
public static final String ACTION_USB_STATE =
|
||||
"android.hardware.action.USB_STATE";
|
||||
|
||||
/**
|
||||
* Broadcast Action: A broadcast for USB device attached event.
|
||||
*
|
||||
* This intent is sent when a USB device is attached to the USB bus when in host mode.
|
||||
*/
|
||||
public static final String ACTION_USB_DEVICE_ATTACHED =
|
||||
"android.hardware.action.USB_DEVICE_ATTACHED";
|
||||
|
||||
/**
|
||||
* Broadcast Action: A broadcast for USB device detached event.
|
||||
*
|
||||
* This intent is sent when a USB device is detached from the USB bus when in host mode.
|
||||
*/
|
||||
public static final String ACTION_USB_DEVICE_DETACHED =
|
||||
"android.hardware.action.USB_DEVICE_DETACHED";
|
||||
|
||||
/**
|
||||
* Boolean extra indicating whether USB is connected or disconnected.
|
||||
* Used in extras for the {@link #ACTION_USB_STATE} broadcast.
|
||||
@@ -87,6 +117,103 @@ public class UsbManager {
|
||||
*/
|
||||
public static final String USB_FUNCTION_DISABLED = "disabled";
|
||||
|
||||
/**
|
||||
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} and
|
||||
* {@link #ACTION_USB_DEVICE_DETACHED} broadcasts
|
||||
* containing the device's ID (String).
|
||||
*/
|
||||
public static final String EXTRA_DEVICE_NAME = "device_name";
|
||||
|
||||
/**
|
||||
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} broadcast
|
||||
* containing the device's vendor ID (int).
|
||||
*/
|
||||
public static final String EXTRA_VENDOR_ID = "vendor_id";
|
||||
|
||||
/**
|
||||
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} broadcast
|
||||
* containing the device's product ID (int).
|
||||
*/
|
||||
public static final String EXTRA_PRODUCT_ID = "product_id";
|
||||
|
||||
/**
|
||||
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} broadcast
|
||||
* containing the device's class (int).
|
||||
*/
|
||||
public static final String EXTRA_DEVICE_CLASS = "device_class";
|
||||
|
||||
/**
|
||||
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} broadcast
|
||||
* containing the device's class (int).
|
||||
*/
|
||||
public static final String EXTRA_DEVICE_SUBCLASS = "device_subclass";
|
||||
|
||||
/**
|
||||
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} broadcast
|
||||
* containing the device's class (int).
|
||||
*/
|
||||
public static final String EXTRA_DEVICE_PROTOCOL = "device_protocol";
|
||||
|
||||
/**
|
||||
* Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} broadcast
|
||||
* containing the UsbDevice object for the device.
|
||||
*/
|
||||
public static final String EXTRA_DEVICE = "device";
|
||||
|
||||
private IUsbManager mService;
|
||||
|
||||
/**
|
||||
* {@hide}
|
||||
*/
|
||||
public UsbManager(IUsbManager service) {
|
||||
mService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a HashMap containing all USB devices currently attached.
|
||||
* USB device name is the key for the returned HashMap.
|
||||
* The result will be empty if no devices are attached, or if
|
||||
* USB host mode is inactive or unsupported.
|
||||
*
|
||||
* @return HashMap containing all connected USB devices.
|
||||
*/
|
||||
public HashMap<String,UsbDevice> getDeviceList() {
|
||||
Bundle bundle = new Bundle();
|
||||
try {
|
||||
mService.getDeviceList(bundle);
|
||||
HashMap<String,UsbDevice> result = new HashMap<String,UsbDevice>();
|
||||
for (String name : bundle.keySet()) {
|
||||
result.put(name, (UsbDevice)bundle.get(name));
|
||||
}
|
||||
return result;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "RemoteException in getDeviceList", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the device so it can be used to send and receive
|
||||
* data using {@link android.hardware.UsbRequest}.
|
||||
*
|
||||
* @param device the device to open
|
||||
* @return true if we successfully opened the device
|
||||
*/
|
||||
public boolean openDevice(UsbDevice device) {
|
||||
try {
|
||||
ParcelFileDescriptor pfd = mService.openDevice(device.getDeviceName());
|
||||
if (pfd == null) {
|
||||
return false;
|
||||
}
|
||||
boolean result = device.open(pfd);
|
||||
pfd.close();
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "exception in UsbManager.openDevice", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static File getFunctionEnableFile(String function) {
|
||||
return new File("/sys/class/usb_composite/" + function + "/enable");
|
||||
}
|
||||
@@ -94,6 +221,9 @@ public class UsbManager {
|
||||
/**
|
||||
* Returns true if the specified USB function is supported by the kernel.
|
||||
* Note that a USB function maybe supported but disabled.
|
||||
*
|
||||
* @param function name of the USB function
|
||||
* @return true if the USB function is supported.
|
||||
*/
|
||||
public static boolean isFunctionSupported(String function) {
|
||||
return getFunctionEnableFile(function).exists();
|
||||
@@ -101,6 +231,9 @@ public class UsbManager {
|
||||
|
||||
/**
|
||||
* Returns true if the specified USB function is currently enabled.
|
||||
*
|
||||
* @param function name of the USB function
|
||||
* @return true if the USB function is enabled.
|
||||
*/
|
||||
public static boolean isFunctionEnabled(String function) {
|
||||
try {
|
||||
|
||||
177
core/java/android/hardware/UsbRequest.java
Normal file
177
core/java/android/hardware/UsbRequest.java
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
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.UsbDevice}.
|
||||
* UsbRequests are sent asynchronously via {@link #queue} and the results
|
||||
* are read by {@link android.hardware.UsbDevice#requestWait}.
|
||||
*/
|
||||
public class UsbRequest {
|
||||
|
||||
private static final String TAG = "UsbRequest";
|
||||
|
||||
// used by the JNI code
|
||||
private int mNativeContext;
|
||||
|
||||
private UsbEndpoint mEndpoint;
|
||||
|
||||
// for temporarily saving current buffer across queue and dequeue
|
||||
private ByteBuffer mBuffer;
|
||||
private int mLength;
|
||||
|
||||
// for client use
|
||||
private Object mClientData;
|
||||
|
||||
public UsbRequest() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the request so it can read or write data on the given endpoint.
|
||||
* Whether the request allows reading or writing depends on the direction of the endpoint.
|
||||
*
|
||||
* @param endpoint the endpoint to be used for this request.
|
||||
* @return true if the request was successfully opened.
|
||||
*/
|
||||
public boolean initialize(UsbEndpoint endpoint) {
|
||||
mEndpoint = endpoint;
|
||||
return native_init(endpoint.getDevice(),
|
||||
endpoint.getAddress(), endpoint.getAttributes(),
|
||||
endpoint.getMaxPacketSize(), endpoint.getInterval());
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases all resources related to this request.
|
||||
*/
|
||||
public void close() {
|
||||
mEndpoint = null;
|
||||
native_close();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
if (mEndpoint != null) {
|
||||
Log.v(TAG, "endpoint still open in finalize(): " + this);
|
||||
close();
|
||||
}
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the endpoint for the request, or null if the request is not opened.
|
||||
*
|
||||
* @return the request's endpoint
|
||||
*/
|
||||
public UsbEndpoint getEndpoint() {
|
||||
return mEndpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client data for the request.
|
||||
* 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.UsbDevice#requestWait}
|
||||
*
|
||||
* @return the client data for the request
|
||||
*/
|
||||
public Object getClientData() {
|
||||
return mClientData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client data for the request.
|
||||
* 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.UsbDevice#requestWait}
|
||||
*
|
||||
* @param data the client data for the request
|
||||
*/
|
||||
public void setClientData(Object data) {
|
||||
mClientData = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queues the request to send or receive data on its endpoint.
|
||||
* For OUT endpoints, the given buffer data will be sent on the endpoint.
|
||||
* 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.UsbDevice#requestWait}
|
||||
*
|
||||
* @param buffer the buffer containing the bytes to write, or location to store
|
||||
* the results of a read
|
||||
* @param length number of bytes to read or write
|
||||
* @return true if the queueing operation succeeded
|
||||
*/
|
||||
public boolean queue(ByteBuffer buffer, int length) {
|
||||
boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
|
||||
boolean result;
|
||||
if (buffer.isDirect()) {
|
||||
result = native_queue_direct(buffer, length, out);
|
||||
} else if (buffer.hasArray()) {
|
||||
result = native_queue_array(buffer.array(), length, out);
|
||||
} else {
|
||||
throw new IllegalArgumentException("buffer is not direct and has no array");
|
||||
}
|
||||
if (result) {
|
||||
// save our buffer for when the request has completed
|
||||
mBuffer = buffer;
|
||||
mLength = length;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* package */ void dequeue() {
|
||||
boolean out = (mEndpoint.getDirection() == UsbConstants.USB_DIR_OUT);
|
||||
if (mBuffer.isDirect()) {
|
||||
native_dequeue_direct();
|
||||
} else {
|
||||
native_dequeue_array(mBuffer.array(), mLength, out);
|
||||
}
|
||||
mBuffer = null;
|
||||
mLength = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels a pending queue operation.
|
||||
*
|
||||
* @return true if cancelling succeeded
|
||||
*/
|
||||
public boolean cancel() {
|
||||
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 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);
|
||||
private native boolean native_queue_direct(ByteBuffer buffer, int length, boolean out);
|
||||
private native void native_dequeue_direct();
|
||||
private native boolean native_cancel();
|
||||
}
|
||||
@@ -124,6 +124,8 @@ LOCAL_SRC_FILES:= \
|
||||
android_media_ToneGenerator.cpp \
|
||||
android_hardware_Camera.cpp \
|
||||
android_hardware_SensorManager.cpp \
|
||||
android_hardware_UsbDevice.cpp \
|
||||
android_hardware_UsbRequest.cpp \
|
||||
android_debug_JNITest.cpp \
|
||||
android_util_FileObserver.cpp \
|
||||
android/opengl/poly_clip.cpp.arm \
|
||||
@@ -202,6 +204,7 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
libwpa_client \
|
||||
libjpeg \
|
||||
libnfc_ndef \
|
||||
libusbhost \
|
||||
|
||||
ifeq ($(USE_OPENGL_RENDERER),true)
|
||||
LOCAL_SHARED_LIBRARIES += libhwui
|
||||
|
||||
@@ -77,6 +77,8 @@ 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_UsbRequest(JNIEnv *env);
|
||||
|
||||
extern int register_android_media_AudioRecord(JNIEnv *env);
|
||||
extern int register_android_media_AudioSystem(JNIEnv *env);
|
||||
@@ -1275,6 +1277,8 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_com_android_internal_os_ZygoteInit),
|
||||
REG_JNI(register_android_hardware_Camera),
|
||||
REG_JNI(register_android_hardware_SensorManager),
|
||||
REG_JNI(register_android_hardware_UsbDevice),
|
||||
REG_JNI(register_android_hardware_UsbRequest),
|
||||
REG_JNI(register_android_media_AudioRecord),
|
||||
REG_JNI(register_android_media_AudioSystem),
|
||||
REG_JNI(register_android_media_AudioTrack),
|
||||
|
||||
239
core/jni/android_hardware_UsbDevice.cpp
Normal file
239
core/jni/android_hardware_UsbDevice.cpp
Normal file
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 "UsbDeviceJNI"
|
||||
|
||||
#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 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 jint
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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_send_control(device, requestType, request,
|
||||
value, index, length, bufferBytes);
|
||||
|
||||
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)
|
||||
{
|
||||
const char *nameStr = env->GetStringUTFChars(name, NULL);
|
||||
int id = usb_device_get_unique_id_from_name(nameStr);
|
||||
env->ReleaseStringUTFChars(name, nameStr);
|
||||
return id;
|
||||
}
|
||||
|
||||
static jstring
|
||||
android_hardware_UsbDevice_get_device_name(JNIEnv *env, jobject clazz, jint id)
|
||||
{
|
||||
char* name = usb_device_get_name_from_unique_id(id);
|
||||
jstring result = env->NewStringUTF(name);
|
||||
free(name);
|
||||
return result;
|
||||
}
|
||||
|
||||
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[BI)I",
|
||||
(void *)android_hardware_UsbDevice_control_request},
|
||||
{"native_request_wait", "()Landroid/hardware/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 },
|
||||
{ "native_get_device_name", "(I)Ljava/lang/String;",
|
||||
(void*)android_hardware_UsbDevice_get_device_name },
|
||||
};
|
||||
|
||||
int register_android_hardware_UsbDevice(JNIEnv *env)
|
||||
{
|
||||
jclass clazz = env->FindClass("android/hardware/UsbDevice");
|
||||
if (clazz == NULL) {
|
||||
LOGE("Can't find android/hardware/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/UsbDevice",
|
||||
method_table, NELEM(method_table));
|
||||
}
|
||||
|
||||
124
core/jni/android_hardware_UsbEndpoint.cpp
Normal file
124
core/jni/android_hardware_UsbEndpoint.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 "UsbEndpoint"
|
||||
|
||||
#include "utils/Log.h"
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
|
||||
#include <usbhost/usbhost.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
static jfieldID field_context;
|
||||
static jfieldID field_address;
|
||||
static jfieldID field_attributes;
|
||||
static jfieldID field_max_packet_size;
|
||||
static jfieldID field_interval;
|
||||
|
||||
struct usb_endpoint* get_endpoint_from_object(JNIEnv* env, jobject javaEndpoint)
|
||||
{
|
||||
return (struct usb_endpoint*)env->GetIntField(javaEndpoint, field_context);
|
||||
}
|
||||
|
||||
// in android_hardware_UsbDevice.cpp
|
||||
extern struct usb_device* get_device_from_object(JNIEnv* env, jobject javaDevice);
|
||||
|
||||
static jboolean
|
||||
android_hardware_UsbEndpoint_init(JNIEnv *env, jobject thiz, jobject javaDevice)
|
||||
{
|
||||
LOGD("open\n");
|
||||
|
||||
struct usb_device* device = get_device_from_object(env, javaDevice);
|
||||
if (!device) {
|
||||
LOGE("device null in native_init");
|
||||
return false;
|
||||
}
|
||||
|
||||
// construct an endpoint descriptor from the Java object fields
|
||||
struct usb_endpoint_descriptor desc;
|
||||
desc.bLength = USB_DT_ENDPOINT_SIZE;
|
||||
desc.bDescriptorType = USB_DT_ENDPOINT;
|
||||
desc.bEndpointAddress = env->GetIntField(thiz, field_address);
|
||||
desc.bmAttributes = env->GetIntField(thiz, field_attributes);
|
||||
desc.wMaxPacketSize = env->GetIntField(thiz, field_max_packet_size);
|
||||
desc.bInterval = env->GetIntField(thiz, field_interval);
|
||||
|
||||
struct usb_endpoint* endpoint = usb_endpoint_init(device, &desc);
|
||||
if (endpoint)
|
||||
env->SetIntField(thiz, field_context, (int)device);
|
||||
return (endpoint != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
android_hardware_UsbEndpoint_close(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
LOGD("close\n");
|
||||
struct usb_endpoint* endpoint = get_endpoint_from_object(env, thiz);
|
||||
if (endpoint) {
|
||||
usb_endpoint_close(endpoint);
|
||||
env->SetIntField(thiz, field_context, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static JNINativeMethod method_table[] = {
|
||||
{"native_init", "(Landroid/hardware/UsbDevice;)Z",
|
||||
(void *)android_hardware_UsbEndpoint_init},
|
||||
{"native_close", "()V", (void *)android_hardware_UsbEndpoint_close},
|
||||
};
|
||||
|
||||
int register_android_hardware_UsbEndpoint(JNIEnv *env)
|
||||
{
|
||||
jclass clazz = env->FindClass("android/hardware/UsbEndpoint");
|
||||
if (clazz == NULL) {
|
||||
LOGE("Can't find android/hardware/UsbEndpoint");
|
||||
return -1;
|
||||
}
|
||||
field_context = env->GetFieldID(clazz, "mNativeContext", "I");
|
||||
if (field_context == NULL) {
|
||||
LOGE("Can't find UsbEndpoint.mNativeContext");
|
||||
return -1;
|
||||
}
|
||||
field_address = env->GetFieldID(clazz, "mAddress", "I");
|
||||
if (field_address == NULL) {
|
||||
LOGE("Can't find UsbEndpoint.mAddress");
|
||||
return -1;
|
||||
}
|
||||
field_attributes = env->GetFieldID(clazz, "mAttributes", "I");
|
||||
if (field_attributes == NULL) {
|
||||
LOGE("Can't find UsbEndpoint.mAttributes");
|
||||
return -1;
|
||||
}
|
||||
field_max_packet_size = env->GetFieldID(clazz, "mMaxPacketSize", "I");
|
||||
if (field_max_packet_size == NULL) {
|
||||
LOGE("Can't find UsbEndpoint.mMaxPacketSize");
|
||||
return -1;
|
||||
}
|
||||
field_interval = env->GetFieldID(clazz, "mInterval", "I");
|
||||
if (field_interval == NULL) {
|
||||
LOGE("Can't find UsbEndpoint.mInterval");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(env, "android/hardware/UsbEndpoint",
|
||||
method_table, NELEM(method_table));
|
||||
}
|
||||
|
||||
217
core/jni/android_hardware_UsbRequest.cpp
Normal file
217
core/jni/android_hardware_UsbRequest.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright (C) 2010 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 "UsbRequestJNI"
|
||||
|
||||
#include "utils/Log.h"
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
|
||||
#include <usbhost/usbhost.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace android;
|
||||
|
||||
static jfieldID field_context;
|
||||
|
||||
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);
|
||||
|
||||
static jboolean
|
||||
android_hardware_UsbRequest_init(JNIEnv *env, jobject thiz, jobject java_device,
|
||||
jint ep_address, jint ep_attributes, jint ep_max_packet_size, jint ep_interval)
|
||||
{
|
||||
LOGD("init\n");
|
||||
|
||||
struct usb_device* device = get_device_from_object(env, java_device);
|
||||
if (!device) {
|
||||
LOGE("device null in native_init");
|
||||
return false;
|
||||
}
|
||||
|
||||
// construct an endpoint descriptor from the Java object fields
|
||||
struct usb_endpoint_descriptor desc;
|
||||
desc.bLength = USB_DT_ENDPOINT_SIZE;
|
||||
desc.bDescriptorType = USB_DT_ENDPOINT;
|
||||
desc.bEndpointAddress = ep_address;
|
||||
desc.bmAttributes = ep_attributes;
|
||||
desc.wMaxPacketSize = ep_max_packet_size;
|
||||
desc.bInterval = ep_interval;
|
||||
|
||||
struct usb_request* request = usb_request_new(device, &desc);
|
||||
if (request)
|
||||
env->SetIntField(thiz, field_context, (int)request);
|
||||
return (request != NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
android_hardware_UsbRequest_close(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
LOGD("close\n");
|
||||
struct usb_request* request = get_request_from_object(env, thiz);
|
||||
if (request) {
|
||||
usb_request_free(request);
|
||||
env->SetIntField(thiz, field_context, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_hardware_UsbRequest_queue_array(JNIEnv *env, jobject thiz,
|
||||
jbyteArray buffer, jint length, jboolean out)
|
||||
{
|
||||
struct usb_request* request = get_request_from_object(env, thiz);
|
||||
if (!request) {
|
||||
LOGE("request is closed in native_queue");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer && length) {
|
||||
request->buffer = malloc(length);
|
||||
if (!request->buffer)
|
||||
return false;
|
||||
if (out) {
|
||||
// copy data from Java buffer to native buffer
|
||||
env->GetByteArrayRegion(buffer, 0, length, (jbyte *)request->buffer);
|
||||
}
|
||||
} else {
|
||||
request->buffer = NULL;
|
||||
}
|
||||
request->buffer_length = length;
|
||||
|
||||
if (usb_request_queue(request)) {
|
||||
if (request->buffer) {
|
||||
// free our buffer if usb_request_queue fails
|
||||
free(request->buffer);
|
||||
request->buffer = NULL;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
// save a reference to ourselves so UsbDevice.waitRequest() can find us
|
||||
request->client_data = (void *)env->NewGlobalRef(thiz);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
android_hardware_UsbRequest_dequeue_array(JNIEnv *env, jobject thiz,
|
||||
jbyteArray buffer, jint length, jboolean out)
|
||||
{
|
||||
struct usb_request* request = get_request_from_object(env, thiz);
|
||||
if (!request) {
|
||||
LOGE("request is closed in native_dequeue");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer && length && request->buffer && !out) {
|
||||
// copy data from native buffer to Java buffer
|
||||
env->SetByteArrayRegion(buffer, 0, length, (jbyte *)request->buffer);
|
||||
}
|
||||
free(request->buffer);
|
||||
env->DeleteGlobalRef((jobject)request->client_data);
|
||||
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_hardware_UsbRequest_queue_direct(JNIEnv *env, jobject thiz,
|
||||
jobject buffer, jint length, jboolean out)
|
||||
{
|
||||
struct usb_request* request = get_request_from_object(env, thiz);
|
||||
if (!request) {
|
||||
LOGE("request is closed in native_queue");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buffer && length) {
|
||||
request->buffer = env->GetDirectBufferAddress(buffer);
|
||||
if (!request->buffer)
|
||||
return false;
|
||||
} else {
|
||||
request->buffer = NULL;
|
||||
}
|
||||
request->buffer_length = length;
|
||||
|
||||
if (usb_request_queue(request)) {
|
||||
request->buffer = NULL;
|
||||
return false;
|
||||
} else {
|
||||
// save a reference to ourselves so UsbDevice.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);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
android_hardware_UsbRequest_dequeue_direct(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
struct usb_request* request = get_request_from_object(env, thiz);
|
||||
if (!request) {
|
||||
LOGE("request is closed in native_dequeue");
|
||||
return;
|
||||
}
|
||||
// all we need to do is delete our global ref
|
||||
env->DeleteGlobalRef((jobject)request->client_data);
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_hardware_UsbRequest_cancel(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
struct usb_request* request = get_request_from_object(env, thiz);
|
||||
if (!request) {
|
||||
LOGE("request is closed in native_cancel");
|
||||
return false;
|
||||
}
|
||||
return (usb_request_cancel(request) == 0);
|
||||
}
|
||||
|
||||
static JNINativeMethod method_table[] = {
|
||||
{"native_init", "(Landroid/hardware/UsbDevice;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},
|
||||
{"native_dequeue_array", "([BIZ)V", (void *)android_hardware_UsbRequest_dequeue_array},
|
||||
{"native_queue_direct", "(Ljava/nio/ByteBuffer;IZ)Z",
|
||||
(void *)android_hardware_UsbRequest_queue_direct},
|
||||
{"native_dequeue_direct", "()V", (void *)android_hardware_UsbRequest_dequeue_direct},
|
||||
{"native_cancel", "()Z", (void *)android_hardware_UsbRequest_cancel},
|
||||
};
|
||||
|
||||
int register_android_hardware_UsbRequest(JNIEnv *env)
|
||||
{
|
||||
jclass clazz = env->FindClass("android/hardware/UsbRequest");
|
||||
if (clazz == NULL) {
|
||||
LOGE("Can't find android/hardware/UsbRequest");
|
||||
return -1;
|
||||
}
|
||||
field_context = env->GetFieldID(clazz, "mNativeContext", "I");
|
||||
if (field_context == NULL) {
|
||||
LOGE("Can't find UsbRequest.mNativeContext");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return AndroidRuntime::registerNativeMethods(env, "android/hardware/UsbRequest",
|
||||
method_table, NELEM(method_table));
|
||||
}
|
||||
|
||||
@@ -85,6 +85,8 @@
|
||||
<protected-broadcast android:name="android.hardware.action.USB_CONNECTED" />
|
||||
<protected-broadcast android:name="android.hardware.action.USB_DISCONNECTED" />
|
||||
<protected-broadcast android:name="android.hardware.action.USB_STATE" />
|
||||
<protected-broadcast android:name="android.hardware.action.USB_DEVICE_ATTACHED" />
|
||||
<protected-broadcast android:name="android.hardware.action.USB_DEVICE_DETACHED" />
|
||||
|
||||
<protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
|
||||
<protected-broadcast android:name="android.nfc.action.TRANSACTION_DETECTED" />
|
||||
|
||||
@@ -405,6 +405,7 @@ class ServerThread extends Thread {
|
||||
Slog.i(TAG, "USB Observer");
|
||||
// Listen for USB changes
|
||||
usb = new UsbService(context);
|
||||
ServiceManager.addService(Context.USB_SERVICE, usb);
|
||||
} catch (Throwable e) {
|
||||
Slog.e(TAG, "Failure starting UsbService", e);
|
||||
}
|
||||
|
||||
@@ -19,10 +19,18 @@ package com.android.server;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.hardware.IUsbManager;
|
||||
import android.hardware.UsbConstants;
|
||||
import android.hardware.UsbDevice;
|
||||
import android.hardware.UsbEndpoint;
|
||||
import android.hardware.UsbInterface;
|
||||
import android.hardware.UsbManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Parcelable;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.UEventObserver;
|
||||
import android.provider.Settings;
|
||||
import android.util.Log;
|
||||
@@ -32,11 +40,12 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* <p>UsbService monitors for changes to USB state.
|
||||
*/
|
||||
class UsbService {
|
||||
class UsbService extends IUsbManager.Stub {
|
||||
private static final String TAG = UsbService.class.getSimpleName();
|
||||
private static final boolean LOG = false;
|
||||
|
||||
@@ -68,10 +77,12 @@ class UsbService {
|
||||
private int mLastConnected = -1;
|
||||
private int mLastConfiguration = -1;
|
||||
|
||||
// lists of enabled and disabled USB functions
|
||||
// lists of enabled and disabled USB functions (for USB device mode)
|
||||
private final ArrayList<String> mEnabledFunctions = new ArrayList<String>();
|
||||
private final ArrayList<String> mDisabledFunctions = new ArrayList<String>();
|
||||
|
||||
private final HashMap<String,UsbDevice> mDevices = new HashMap<String,UsbDevice>();
|
||||
|
||||
private boolean mSystemReady;
|
||||
|
||||
private final Context mContext;
|
||||
@@ -186,8 +197,106 @@ class UsbService {
|
||||
}
|
||||
}
|
||||
|
||||
// called from JNI in monitorUsbHostBus()
|
||||
private void usbDeviceAdded(String deviceName, int vendorID, int productID,
|
||||
int deviceClass, int deviceSubclass, int deviceProtocol,
|
||||
/* array of quintuples containing id, class, subclass, protocol
|
||||
and number of endpoints for each interface */
|
||||
int[] interfaceValues,
|
||||
/* array of quadruples containing address, attributes, max packet size
|
||||
and interval for each endpoint */
|
||||
int[] endpointValues) {
|
||||
|
||||
// ignore hubs
|
||||
if (deviceClass == UsbConstants.USB_CLASS_HUB) {
|
||||
return;
|
||||
}
|
||||
|
||||
synchronized (mDevices) {
|
||||
if (mDevices.get(deviceName) != null) {
|
||||
Log.w(TAG, "device already on mDevices list: " + deviceName);
|
||||
return;
|
||||
}
|
||||
|
||||
int numInterfaces = interfaceValues.length / 5;
|
||||
Parcelable[] interfaces = new UsbInterface[numInterfaces];
|
||||
try {
|
||||
// repackage interfaceValues as an array of UsbInterface
|
||||
int intf, endp, ival = 0, eval = 0;
|
||||
boolean hasGoodInterface = false;
|
||||
for (intf = 0; intf < numInterfaces; intf++) {
|
||||
int interfaceId = interfaceValues[ival++];
|
||||
int interfaceClass = interfaceValues[ival++];
|
||||
int interfaceSubclass = interfaceValues[ival++];
|
||||
int interfaceProtocol = interfaceValues[ival++];
|
||||
int numEndpoints = interfaceValues[ival++];
|
||||
|
||||
Parcelable[] endpoints = new UsbEndpoint[numEndpoints];
|
||||
for (endp = 0; endp < numEndpoints; endp++) {
|
||||
int address = endpointValues[eval++];
|
||||
int attributes = endpointValues[eval++];
|
||||
int maxPacketSize = endpointValues[eval++];
|
||||
int interval = endpointValues[eval++];
|
||||
endpoints[endp] = new UsbEndpoint(address, attributes,
|
||||
maxPacketSize, interval);
|
||||
}
|
||||
|
||||
if (interfaceClass != UsbConstants.USB_CLASS_HUB) {
|
||||
hasGoodInterface = true;
|
||||
}
|
||||
interfaces[intf] = new UsbInterface(interfaceId, interfaceClass,
|
||||
interfaceSubclass, interfaceProtocol, endpoints);
|
||||
}
|
||||
|
||||
if (!hasGoodInterface) {
|
||||
return;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// beware of index out of bound exceptions, which might happen if
|
||||
// a device does not set bNumEndpoints correctly
|
||||
Log.e(TAG, "error parsing USB descriptors", e);
|
||||
return;
|
||||
}
|
||||
|
||||
UsbDevice device = new UsbDevice(deviceName, vendorID, productID,
|
||||
deviceClass, deviceSubclass, deviceProtocol, interfaces);
|
||||
mDevices.put(deviceName, device);
|
||||
|
||||
Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED);
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE_NAME, deviceName);
|
||||
intent.putExtra(UsbManager.EXTRA_VENDOR_ID, vendorID);
|
||||
intent.putExtra(UsbManager.EXTRA_PRODUCT_ID, productID);
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE_CLASS, deviceClass);
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE_SUBCLASS, deviceSubclass);
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE_PROTOCOL, deviceProtocol);
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE, device);
|
||||
Log.d(TAG, "usbDeviceAdded, sending " + intent);
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
// called from JNI in monitorUsbHostBus()
|
||||
private void usbDeviceRemoved(String deviceName) {
|
||||
synchronized (mDevices) {
|
||||
UsbDevice device = mDevices.remove(deviceName);
|
||||
if (device != null) {
|
||||
Intent intent = new Intent(UsbManager.ACTION_USB_DEVICE_DETACHED);
|
||||
intent.putExtra(UsbManager.EXTRA_DEVICE_NAME, deviceName);
|
||||
Log.d(TAG, "usbDeviceRemoved, sending " + intent);
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initHostSupport() {
|
||||
// temporarily disabled
|
||||
// Create a thread to call into native code to wait for USB host events.
|
||||
// This thread will call us back on usbDeviceAdded and usbDeviceRemoved.
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
monitorUsbHostBus();
|
||||
}
|
||||
};
|
||||
new Thread(null, runnable, "UsbService host thread").start();
|
||||
}
|
||||
|
||||
void systemReady() {
|
||||
@@ -208,6 +317,21 @@ class UsbService {
|
||||
mHandler.sendEmptyMessageDelayed(MSG_UPDATE, delayed ? UPDATE_DELAY : 0);
|
||||
}
|
||||
|
||||
/* Returns a list of all currently attached USB devices */
|
||||
public void getDeviceList(Bundle devices) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null);
|
||||
synchronized (mDevices) {
|
||||
for (String name : mDevices.keySet()) {
|
||||
devices.putParcelable(name, mDevices.get(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ParcelFileDescriptor openDevice(String deviceName) {
|
||||
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.ACCESS_USB, null);
|
||||
return nativeOpenDevice(deviceName);
|
||||
}
|
||||
|
||||
private final Handler mHandler = new Handler() {
|
||||
private void addEnabledFunctions(Intent intent) {
|
||||
// include state of all USB functions in our extras
|
||||
@@ -249,4 +373,7 @@ class UsbService {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private native void monitorUsbHostBus();
|
||||
private native ParcelFileDescriptor nativeOpenDevice(String deviceName);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ LOCAL_SRC_FILES:= \
|
||||
com_android_server_LightsService.cpp \
|
||||
com_android_server_PowerManagerService.cpp \
|
||||
com_android_server_SystemServer.cpp \
|
||||
com_android_server_UsbService.cpp \
|
||||
com_android_server_VibratorService.cpp \
|
||||
com_android_server_location_GpsLocationProvider.cpp \
|
||||
onload.cpp
|
||||
|
||||
210
services/jni/com_android_server_UsbService.cpp
Normal file
210
services/jni/com_android_server_UsbService.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2009 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 "UsbService"
|
||||
#include "utils/Log.h"
|
||||
|
||||
#include "jni.h"
|
||||
#include "JNIHelp.h"
|
||||
#include "android_runtime/AndroidRuntime.h"
|
||||
#include "utils/Vector.h"
|
||||
|
||||
#include <usbhost/usbhost.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
namespace android
|
||||
{
|
||||
|
||||
static struct file_descriptor_offsets_t
|
||||
{
|
||||
jclass mClass;
|
||||
jmethodID mConstructor;
|
||||
jfieldID mDescriptor;
|
||||
} gFileDescriptorOffsets;
|
||||
|
||||
static struct parcel_file_descriptor_offsets_t
|
||||
{
|
||||
jclass mClass;
|
||||
jmethodID mConstructor;
|
||||
} gParcelFileDescriptorOffsets;
|
||||
|
||||
static jmethodID method_usbDeviceAdded;
|
||||
static jmethodID method_usbDeviceRemoved;
|
||||
|
||||
static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) {
|
||||
if (env->ExceptionCheck()) {
|
||||
LOGE("An exception was thrown by callback '%s'.", methodName);
|
||||
LOGE_EX(env);
|
||||
env->ExceptionClear();
|
||||
}
|
||||
}
|
||||
|
||||
static int usb_device_added(const char *devname, void* client_data) {
|
||||
struct usb_descriptor_header* desc;
|
||||
struct usb_descriptor_iter iter;
|
||||
|
||||
struct usb_device *device = usb_device_open(devname);
|
||||
if (!device) {
|
||||
LOGE("usb_device_open failed\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
jobject thiz = (jobject)client_data;
|
||||
Vector<int> interfaceValues;
|
||||
Vector<int> endpointValues;
|
||||
const usb_device_descriptor* deviceDesc = usb_device_get_device_descriptor(device);
|
||||
|
||||
uint16_t vendorId = usb_device_get_vendor_id(device);
|
||||
uint16_t productId = usb_device_get_product_id(device);
|
||||
uint8_t deviceClass = deviceDesc->bDeviceClass;
|
||||
uint8_t deviceSubClass = deviceDesc->bDeviceSubClass;
|
||||
uint8_t protocol = deviceDesc->bDeviceProtocol;
|
||||
|
||||
usb_descriptor_iter_init(device, &iter);
|
||||
|
||||
while ((desc = usb_descriptor_iter_next(&iter)) != NULL) {
|
||||
if (desc->bDescriptorType == USB_DT_INTERFACE) {
|
||||
struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)desc;
|
||||
|
||||
// push class, subclass, protocol and number of endpoints into interfaceValues vector
|
||||
interfaceValues.add(interface->bInterfaceNumber);
|
||||
interfaceValues.add(interface->bInterfaceClass);
|
||||
interfaceValues.add(interface->bInterfaceSubClass);
|
||||
interfaceValues.add(interface->bInterfaceProtocol);
|
||||
interfaceValues.add(interface->bNumEndpoints);
|
||||
} else if (desc->bDescriptorType == USB_DT_ENDPOINT) {
|
||||
struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)desc;
|
||||
|
||||
// push address, attributes, max packet size and interval into endpointValues vector
|
||||
endpointValues.add(endpoint->bEndpointAddress);
|
||||
endpointValues.add(endpoint->bmAttributes);
|
||||
endpointValues.add(__le16_to_cpu(endpoint->wMaxPacketSize));
|
||||
endpointValues.add(endpoint->bInterval);
|
||||
}
|
||||
}
|
||||
|
||||
usb_device_close(device);
|
||||
|
||||
// handle generic device notification
|
||||
int length = interfaceValues.size();
|
||||
jintArray interfaceArray = env->NewIntArray(length);
|
||||
env->SetIntArrayRegion(interfaceArray, 0, length, interfaceValues.array());
|
||||
|
||||
length = endpointValues.size();
|
||||
jintArray endpointArray = env->NewIntArray(length);
|
||||
env->SetIntArrayRegion(endpointArray, 0, length, endpointValues.array());
|
||||
|
||||
env->CallVoidMethod(thiz, method_usbDeviceAdded,
|
||||
env->NewStringUTF(devname), vendorId, productId, deviceClass,
|
||||
deviceSubClass, protocol, interfaceArray, endpointArray);
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usb_device_removed(const char *devname, void* client_data) {
|
||||
JNIEnv* env = AndroidRuntime::getJNIEnv();
|
||||
jobject thiz = (jobject)client_data;
|
||||
|
||||
env->CallVoidMethod(thiz, method_usbDeviceRemoved, env->NewStringUTF(devname));
|
||||
checkAndClearExceptionFromCallback(env, __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void android_server_UsbService_monitorUsbHostBus(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
struct usb_host_context* context = usb_host_init();
|
||||
if (!context) {
|
||||
LOGE("usb_host_init failed");
|
||||
return;
|
||||
}
|
||||
// this will never return so it is safe to pass thiz directly
|
||||
usb_host_run(context, usb_device_added, usb_device_removed, NULL, (void *)thiz);
|
||||
}
|
||||
|
||||
static jobject android_server_UsbService_openDevice(JNIEnv *env, jobject thiz, jstring deviceName)
|
||||
{
|
||||
const char *deviceNameStr = env->GetStringUTFChars(deviceName, NULL);
|
||||
struct usb_device* device = usb_device_open(deviceNameStr);
|
||||
env->ReleaseStringUTFChars(deviceName, deviceNameStr);
|
||||
|
||||
if (!device)
|
||||
return NULL;
|
||||
|
||||
int fd = usb_device_get_fd(device);
|
||||
if (fd < 0)
|
||||
return NULL;
|
||||
int newFD = dup(fd);
|
||||
usb_device_close(device);
|
||||
|
||||
jobject fileDescriptor = env->NewObject(gFileDescriptorOffsets.mClass,
|
||||
gFileDescriptorOffsets.mConstructor);
|
||||
if (fileDescriptor != NULL) {
|
||||
env->SetIntField(fileDescriptor, gFileDescriptorOffsets.mDescriptor, newFD);
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
return env->NewObject(gParcelFileDescriptorOffsets.mClass,
|
||||
gParcelFileDescriptorOffsets.mConstructor, fileDescriptor);
|
||||
}
|
||||
|
||||
static JNINativeMethod method_table[] = {
|
||||
{ "monitorUsbHostBus", "()V", (void*)android_server_UsbService_monitorUsbHostBus },
|
||||
{ "nativeOpenDevice", "(Ljava/lang/String;)Landroid/os/ParcelFileDescriptor;",
|
||||
(void*)android_server_UsbService_openDevice },
|
||||
};
|
||||
|
||||
int register_android_server_UsbService(JNIEnv *env)
|
||||
{
|
||||
jclass clazz = env->FindClass("com/android/server/UsbService");
|
||||
if (clazz == NULL) {
|
||||
LOGE("Can't find com/android/server/UsbService");
|
||||
return -1;
|
||||
}
|
||||
method_usbDeviceAdded = env->GetMethodID(clazz, "usbDeviceAdded", "(Ljava/lang/String;IIIII[I[I)V");
|
||||
if (method_usbDeviceAdded == NULL) {
|
||||
LOGE("Can't find usbDeviceAdded");
|
||||
return -1;
|
||||
}
|
||||
method_usbDeviceRemoved = env->GetMethodID(clazz, "usbDeviceRemoved", "(Ljava/lang/String;)V");
|
||||
if (method_usbDeviceRemoved == NULL) {
|
||||
LOGE("Can't find usbDeviceRemoved");
|
||||
return -1;
|
||||
}
|
||||
|
||||
clazz = env->FindClass("java/io/FileDescriptor");
|
||||
LOG_FATAL_IF(clazz == NULL, "Unable to find class java.io.FileDescriptor");
|
||||
gFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
|
||||
gFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "()V");
|
||||
gFileDescriptorOffsets.mDescriptor = env->GetFieldID(clazz, "descriptor", "I");
|
||||
LOG_FATAL_IF(gFileDescriptorOffsets.mDescriptor == NULL,
|
||||
"Unable to find descriptor field in java.io.FileDescriptor");
|
||||
|
||||
clazz = env->FindClass("android/os/ParcelFileDescriptor");
|
||||
LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
|
||||
gParcelFileDescriptorOffsets.mClass = (jclass) env->NewGlobalRef(clazz);
|
||||
gParcelFileDescriptorOffsets.mConstructor = env->GetMethodID(clazz, "<init>", "(Ljava/io/FileDescriptor;)V");
|
||||
LOG_FATAL_IF(gParcelFileDescriptorOffsets.mConstructor == NULL,
|
||||
"Unable to find constructor for android.os.ParcelFileDescriptor");
|
||||
|
||||
return jniRegisterNativeMethods(env, "com/android/server/UsbService",
|
||||
method_table, NELEM(method_table));
|
||||
}
|
||||
|
||||
};
|
||||
@@ -13,6 +13,7 @@ int register_android_server_InputWindowHandle(JNIEnv* env);
|
||||
int register_android_server_InputManager(JNIEnv* env);
|
||||
int register_android_server_LightsService(JNIEnv* env);
|
||||
int register_android_server_PowerManagerService(JNIEnv* env);
|
||||
int register_android_server_UsbService(JNIEnv* env);
|
||||
int register_android_server_VibratorService(JNIEnv* env);
|
||||
int register_android_server_SystemServer(JNIEnv* env);
|
||||
int register_android_server_location_GpsLocationProvider(JNIEnv* env);
|
||||
@@ -40,6 +41,7 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||
register_android_server_LightsService(env);
|
||||
register_android_server_AlarmManagerService(env);
|
||||
register_android_server_BatteryService(env);
|
||||
register_android_server_UsbService(env);
|
||||
register_android_server_VibratorService(env);
|
||||
register_android_server_SystemServer(env);
|
||||
register_android_server_location_GpsLocationProvider(env);
|
||||
|
||||
Reference in New Issue
Block a user