diff options
author | reillyg <reillyg@chromium.org> | 2016-01-07 14:00:09 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-01-07 22:00:58 +0000 |
commit | 4e17561af22e80438cd255dd5c92d64b57f4955d (patch) | |
tree | 271502639e3fd5d32adca422eb644af49e7de6d8 /device/usb | |
parent | ff1966e831cce0b4a40cfa2bad90e9b6fdf4eb89 (diff) | |
download | chromium_src-4e17561af22e80438cd255dd5c92d64b57f4955d.zip chromium_src-4e17561af22e80438cd255dd5c92d64b57f4955d.tar.gz chromium_src-4e17561af22e80438cd255dd5c92d64b57f4955d.tar.bz2 |
Reland of Implement basic USB device enumeration on Android. (patchset #1 id:1 of https://codereview.chromium.org/1561283003/ )
Reason for revert:
Lack of GYP dependency on //device/usb Java sources fixed.
Original issue's description:
> Revert of Implement basic USB device enumeration on Android. (patchset #3 id:40001 of https://codereview.chromium.org/1514603006/ )
>
> Reason for revert:
> Speculating that this is the cause of issue 575191.
>
> Original issue's description:
> > Implement basic USB device enumeration on Android.
> >
> > This patch provides a basic implementation of UsbService::GetDevices on
> > Android that populates UsbDevice objects by collecting properties of the
> > Java-side UsbDevice, UsbConfiguration, UsbInterface and UsbEndpoint
> > objects over JNI.
> >
> > It does not support opening devices and does not generate device add or
> > remove notifications.
> >
> > BUG=549257
> >
> > Committed: https://crrev.com/8a310851fb144e91d1777112930ac15c0d88577b
> > Cr-Commit-Position: refs/heads/master@{#367918}
>
> TBR=nasko@chromium.org,qinmin@chromium.org,yfriedman@chromium.org,pfeldman@chromium.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=549257,575191
>
> Committed: https://crrev.com/e3de6dea8003be39328bea275763daab36a8df24
> Cr-Commit-Position: refs/heads/master@{#368077}
TBR=nasko@chromium.org,qinmin@chromium.org,yfriedman@chromium.org,pfeldman@chromium.org
BUG=549257,575191
Review URL: https://codereview.chromium.org/1565313002
Cr-Commit-Position: refs/heads/master@{#368169}
Diffstat (limited to 'device/usb')
25 files changed, 931 insertions, 23 deletions
diff --git a/device/usb/BUILD.gn b/device/usb/BUILD.gn index 99e12ca..6adc36f 100644 --- a/device/usb/BUILD.gn +++ b/device/usb/BUILD.gn @@ -6,23 +6,39 @@ import("//build/config/features.gni") assert(!is_ios) +if (is_android) { + import("//build/config/android/rules.gni") # For generate_jni(). +} + source_ids = "//third_party/usb_ids/usb.ids" generated_ids = "$target_gen_dir/usb_ids_gen.cc" source_set("usb") { sources = [ + "android/usb_jni_registrar.cc", + "android/usb_jni_registrar.h", + "usb_configuration_android.cc", + "usb_configuration_android.h", "usb_descriptors.cc", "usb_descriptors.h", "usb_device.cc", "usb_device.h", + "usb_device_android.cc", + "usb_device_android.h", "usb_device_filter.cc", "usb_device_filter.h", "usb_device_handle.cc", "usb_device_handle.h", + "usb_endpoint_android.cc", + "usb_endpoint_android.h", "usb_ids.cc", "usb_ids.h", + "usb_interface_android.cc", + "usb_interface_android.h", "usb_service.cc", "usb_service.h", + "usb_service_android.cc", + "usb_service_android.h", "webusb_descriptors.cc", "webusb_descriptors.h", generated_ids, @@ -42,10 +58,7 @@ source_set("usb") { } if (is_android) { - sources += [ - "usb_service_android.cc", - "usb_service_android.h", - ] + deps += [ ":jni_headers" ] } else { sources += [ "usb_context.cc", @@ -111,3 +124,32 @@ action("usb_device_ids") { # Only the device_usb target can depend on us. visibility = [ ":usb" ] } + +if (is_android) { + java_sources_needing_jni = [ + "android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java", + "android/java/src/org/chromium/device/usb/ChromeUsbDevice.java", + "android/java/src/org/chromium/device/usb/ChromeUsbEndpoint.java", + "android/java/src/org/chromium/device/usb/ChromeUsbInterface.java", + "android/java/src/org/chromium/device/usb/ChromeUsbService.java", + ] + + generate_jni("jni_headers") { + sources = java_sources_needing_jni + jni_package = "device" + } + + java_cpp_enum("usb_descriptors_javagen") { + sources = [ + "usb_descriptors.h", + ] + } + + android_library("java") { + java_files = java_sources_needing_jni + deps = [ + "//base:base_java", + ] + srcjar_deps = [ ":usb_descriptors_javagen" ] + } +} diff --git a/device/usb/DEPS b/device/usb/DEPS index 25ff287..b1c259f 100644 --- a/device/usb/DEPS +++ b/device/usb/DEPS @@ -1,6 +1,7 @@ include_rules = [ "+chromeos", "+dbus", + "+jni", "-net", "+net/base", diff --git a/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java new file mode 100644 index 0000000..90371e5 --- /dev/null +++ b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java @@ -0,0 +1,68 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.device.usb; + +import android.annotation.TargetApi; +import android.hardware.usb.UsbConfiguration; +import android.hardware.usb.UsbInterface; +import android.os.Build; + +import org.chromium.base.Log; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * Exposes android.hardware.usb.UsbConfiguration as necessary for C++ + * device::UsbConfigurationAndroid. + * + * Lifetime is controlled by device::UsbConfigurationAndroid. + */ +@JNINamespace("device") +@TargetApi(Build.VERSION_CODES.LOLLIPOP) +final class ChromeUsbConfiguration { + private static final String TAG = "Usb"; + + final UsbConfiguration mConfiguration; + + private ChromeUsbConfiguration(UsbConfiguration configuration) { + mConfiguration = configuration; + Log.v(TAG, "ChromeUsbConfiguration created."); + } + + @CalledByNative + private static ChromeUsbConfiguration create(UsbConfiguration configuration) { + return new ChromeUsbConfiguration(configuration); + } + + @CalledByNative + private int getConfigurationValue() { + return mConfiguration.getId(); + } + + @CalledByNative + private boolean isSelfPowered() { + return mConfiguration.isSelfPowered(); + } + + @CalledByNative + private boolean isRemoteWakeup() { + return mConfiguration.isRemoteWakeup(); + } + + @CalledByNative + private int getMaxPower() { + return mConfiguration.getMaxPower(); + } + + @CalledByNative + private UsbInterface[] getInterfaces() { + int count = mConfiguration.getInterfaceCount(); + UsbInterface[] interfaces = new UsbInterface[count]; + for (int i = 0; i < count; ++i) { + interfaces[i] = mConfiguration.getInterface(i); + } + return interfaces; + } +} diff --git a/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbDevice.java b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbDevice.java new file mode 100644 index 0000000..92e4e14 --- /dev/null +++ b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbDevice.java @@ -0,0 +1,84 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.device.usb; + +import android.annotation.TargetApi; +import android.hardware.usb.UsbConfiguration; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbInterface; +import android.os.Build; + +import org.chromium.base.Log; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * Exposes android.hardware.usb.UsbDevice as necessary for C++ + * device::UsbDeviceAndroid. + * + * Lifetime is controlled by device::UsbDeviceAndroid. + */ +@JNINamespace("device") +final class ChromeUsbDevice { + private static final String TAG = "Usb"; + + final UsbDevice mDevice; + + private ChromeUsbDevice(UsbDevice device) { + mDevice = device; + Log.v(TAG, "ChromeUsbDevice created."); + } + + @CalledByNative + private static ChromeUsbDevice create(UsbDevice device) { + return new ChromeUsbDevice(device); + } + + @CalledByNative + private int getVendorId() { + return mDevice.getVendorId(); + } + + @CalledByNative + private int getProductId() { + return mDevice.getProductId(); + } + + @CalledByNative + private String getManufacturerName() { + return mDevice.getManufacturerName(); + } + + @CalledByNative + private String getProductName() { + return mDevice.getProductName(); + } + + @CalledByNative + private String getSerialNumber() { + return mDevice.getSerialNumber(); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + @CalledByNative + private UsbConfiguration[] getConfigurations() { + int count = mDevice.getConfigurationCount(); + UsbConfiguration[] configurations = new UsbConfiguration[count]; + for (int i = 0; i < count; ++i) { + configurations[i] = mDevice.getConfiguration(i); + } + return configurations; + } + + @CalledByNative + private UsbInterface[] getInterfaces() { + int count = mDevice.getInterfaceCount(); + UsbInterface[] interfaces = new UsbInterface[count]; + for (int i = 0; i < count; ++i) { + interfaces[i] = mDevice.getInterface(i); + } + return interfaces; + } +} diff --git a/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbEndpoint.java b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbEndpoint.java new file mode 100644 index 0000000..135dc51 --- /dev/null +++ b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbEndpoint.java @@ -0,0 +1,83 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.device.usb; + +import android.hardware.usb.UsbConstants; +import android.hardware.usb.UsbEndpoint; + +import org.chromium.base.Log; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * Exposes android.hardware.usb.UsbEndpoint as necessary for C++ + * device::UsbEndpointAndroid. + * + * Lifetime is controlled by device::UsbEndpointAndroid. + */ +@JNINamespace("device") +final class ChromeUsbEndpoint { + private static final String TAG = "Usb"; + + final UsbEndpoint mEndpoint; + + private ChromeUsbEndpoint(UsbEndpoint endpoint) { + mEndpoint = endpoint; + Log.v(TAG, "ChromeUsbEndpoint created."); + } + + @CalledByNative + private static ChromeUsbEndpoint create(UsbEndpoint endpoint) { + return new ChromeUsbEndpoint(endpoint); + } + + @CalledByNative + private int getAddress() { + return mEndpoint.getAddress(); + } + + @CalledByNative + private int getDirection() { + switch (mEndpoint.getDirection()) { + case UsbConstants.USB_DIR_IN: + return UsbEndpointDirection.USB_DIRECTION_INBOUND; + case UsbConstants.USB_DIR_OUT: + return UsbEndpointDirection.USB_DIRECTION_OUTBOUND; + default: + throw new AssertionError(); + } + } + + @CalledByNative + private int getMaxPacketSize() { + return mEndpoint.getMaxPacketSize(); + } + + @CalledByNative + private int getAttributes() { + return mEndpoint.getAttributes(); + } + + @CalledByNative + private int getType() { + switch (mEndpoint.getType()) { + case UsbConstants.USB_ENDPOINT_XFER_CONTROL: + return UsbTransferType.USB_TRANSFER_CONTROL; + case UsbConstants.USB_ENDPOINT_XFER_ISOC: + return UsbTransferType.USB_TRANSFER_ISOCHRONOUS; + case UsbConstants.USB_ENDPOINT_XFER_BULK: + return UsbTransferType.USB_TRANSFER_BULK; + case UsbConstants.USB_ENDPOINT_XFER_INT: + return UsbTransferType.USB_TRANSFER_INTERRUPT; + default: + throw new AssertionError(); + } + } + + @CalledByNative + private int getInterval() { + return mEndpoint.getInterval(); + } +} diff --git a/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbInterface.java b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbInterface.java new file mode 100644 index 0000000..cd4f492 --- /dev/null +++ b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbInterface.java @@ -0,0 +1,70 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.device.usb; + +import android.hardware.usb.UsbEndpoint; +import android.hardware.usb.UsbInterface; + +import org.chromium.base.Log; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** + * Exposes android.hardware.usb.UsbInterface as necessary for C++ + * device::UsbInterfaceAndroid. + * + * Lifetime is controlled by device::UsbInterfaceAndroid. + */ +@JNINamespace("device") +final class ChromeUsbInterface { + private static final String TAG = "Usb"; + + final UsbInterface mInterface; + + private ChromeUsbInterface(UsbInterface iface) { + mInterface = iface; + Log.v(TAG, "ChromeUsbInterface created."); + } + + @CalledByNative + private static ChromeUsbInterface create(UsbInterface iface) { + return new ChromeUsbInterface(iface); + } + + @CalledByNative + private int getInterfaceNumber() { + return mInterface.getId(); + } + + @CalledByNative + private int getAlternateSetting() { + return mInterface.getAlternateSetting(); + } + + @CalledByNative + private int getInterfaceClass() { + return mInterface.getInterfaceClass(); + } + + @CalledByNative + private int getInterfaceSubclass() { + return mInterface.getInterfaceSubclass(); + } + + @CalledByNative + private int getInterfaceProtocol() { + return mInterface.getInterfaceProtocol(); + } + + @CalledByNative + private UsbEndpoint[] getEndpoints() { + int count = mInterface.getEndpointCount(); + UsbEndpoint[] endpoints = new UsbEndpoint[count]; + for (int i = 0; i < count; ++i) { + endpoints[i] = mInterface.getEndpoint(i); + } + return endpoints; + } +} diff --git a/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbService.java b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbService.java new file mode 100644 index 0000000..834ddb1 --- /dev/null +++ b/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbService.java @@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.device.usb; + +import android.content.Context; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; + +import org.chromium.base.Log; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +import java.util.HashMap; + +/** + * Exposes android.hardware.usb.UsbManager as necessary for C++ + * device::UsbServiceAndroid. + * + * Lifetime is controlled by device::UsbServiceAndroid. + */ +@JNINamespace("device") +final class ChromeUsbService { + private static final String TAG = "Usb"; + + Context mContext; + + private ChromeUsbService(Context context) { + mContext = context; + Log.v(TAG, "ChromeUsbService created."); + } + + @CalledByNative + private static ChromeUsbService create(Context context) { + return new ChromeUsbService(context); + } + + @CalledByNative + private Object[] getDevices() { + UsbManager manager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE); + HashMap<String, UsbDevice> deviceList = manager.getDeviceList(); + return deviceList.values().toArray(); + } +} diff --git a/device/usb/android/usb_jni_registrar.cc b/device/usb/android/usb_jni_registrar.cc new file mode 100644 index 0000000..1e53c5b --- /dev/null +++ b/device/usb/android/usb_jni_registrar.cc @@ -0,0 +1,35 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/usb/android/usb_jni_registrar.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "device/usb/usb_configuration_android.h" +#include "device/usb/usb_device_android.h" +#include "device/usb/usb_endpoint_android.h" +#include "device/usb/usb_interface_android.h" +#include "device/usb/usb_service_android.h" + +namespace device { +namespace android { +namespace { + +const base::android::RegistrationMethod kRegisteredMethods[] = { + {"UsbConfigurationAndroid", device::UsbConfigurationAndroid::RegisterJNI}, + {"UsbDeviceAndroid", device::UsbDeviceAndroid::RegisterJNI}, + {"UsbEndpointAndroid", device::UsbEndpointAndroid::RegisterJNI}, + {"UsbInterfaceAndroid", device::UsbInterfaceAndroid::RegisterJNI}, + {"UsbServiceAndroid", device::UsbServiceAndroid::RegisterJNI}, +}; + +} // namespace + +bool RegisterUsbJni(JNIEnv* env) { + return RegisterNativeMethods(env, kRegisteredMethods, + arraysize(kRegisteredMethods)); +} + +} // namespace android +} // namespace device diff --git a/device/usb/android/usb_jni_registrar.h b/device/usb/android/usb_jni_registrar.h new file mode 100644 index 0000000..a691583 --- /dev/null +++ b/device/usb/android/usb_jni_registrar.h @@ -0,0 +1,22 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_USB_ANDROID_USB_JNI_REGISTRAR_H_ +#define DEVICE_USB_ANDROID_USB_JNI_REGISTRAR_H_ + +#include <jni.h> + +namespace device { +namespace android { + +// Registers C++ methods in device/usb classes with JNI. +// See https://www.chromium.org/developers/design-documents/android-jni +// +// Must be called before classes in the USB module are used. +bool RegisterUsbJni(JNIEnv* env); + +} // namespace android +} // namespace device + +#endif // DEVICE_USB_ANDROID_USB_JNI_REGISTRAR_H_ diff --git a/device/usb/mock_usb_device.h b/device/usb/mock_usb_device.h index c25a915..91bb0bb 100644 --- a/device/usb/mock_usb_device.h +++ b/device/usb/mock_usb_device.h @@ -5,12 +5,12 @@ #ifndef DEVICE_USB_MOCK_USB_DEVICE_H_ #define DEVICE_USB_MOCK_USB_DEVICE_H_ -#include "device/usb/usb_device.h" - #include <stdint.h> #include <string> +#include <vector> +#include "device/usb/usb_device.h" #include "device/usb/usb_device_handle.h" #include "testing/gmock/include/gmock/gmock.h" @@ -41,7 +41,6 @@ class MockUsbDevice : public UsbDevice { const std::vector<UsbConfigDescriptor>& configurations); MOCK_METHOD1(Open, void(const OpenCallback&)); - MOCK_METHOD1(Close, bool(scoped_refptr<UsbDeviceHandle>)); MOCK_METHOD0(GetActiveConfiguration, const device::UsbConfigDescriptor*()); private: diff --git a/device/usb/usb.gyp b/device/usb/usb.gyp index 453ba1a..a68b187 100644 --- a/device/usb/usb.gyp +++ b/device/usb/usb.gyp @@ -20,6 +20,10 @@ '../..', ], 'sources': [ + 'android/usb_jni_registrar.cc', + 'android/usb_jni_registrar.h', + 'usb_configuration_android.cc', + 'usb_configuration_android.h', 'usb_context.cc', 'usb_context.h', 'usb_descriptors.cc', @@ -28,18 +32,26 @@ 'usb_device_impl.h', 'usb_device.cc', 'usb_device.h', + 'usb_device_android.cc', + 'usb_device_android.h', 'usb_device_filter.cc', 'usb_device_filter.h', 'usb_device_handle_impl.cc', 'usb_device_handle_impl.h', 'usb_device_handle.cc', 'usb_device_handle.h', + 'usb_endpoint_android.cc', + 'usb_endpoint_android.h', 'usb_error.cc', 'usb_error.h', 'usb_ids.cc', 'usb_ids.h', + 'usb_interface_android.cc', + 'usb_interface_android.h', 'usb_service.cc', 'usb_service.h', + 'usb_service_android.cc', + 'usb_service_android.h', 'usb_service_impl.cc', 'usb_service_impl.h', 'webusb_descriptors.cc', @@ -75,13 +87,14 @@ ], }], ['OS=="android"', { + 'dependencies': [ + 'device_usb_java', + 'device_usb_jni_headers', + ], 'dependencies!': [ '../../third_party/libusb/libusb.gyp:libusb', ], - 'sources': [ - 'usb_service_android.cc', - 'usb_service_android.h', - ], + # These sources are libusb-specific. 'sources!': [ 'usb_context.cc', 'usb_context.h', @@ -122,4 +135,45 @@ ], }, ], + 'conditions': [ + ['OS == "android"', { + 'targets': [ + { + 'target_name': 'device_usb_jni_headers', + 'type': 'none', + 'sources': [ + 'android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java', + 'android/java/src/org/chromium/device/usb/ChromeUsbDevice.java', + 'android/java/src/org/chromium/device/usb/ChromeUsbEndpoint.java', + 'android/java/src/org/chromium/device/usb/ChromeUsbInterface.java', + 'android/java/src/org/chromium/device/usb/ChromeUsbService.java', + ], + 'variables': { + 'jni_gen_package': 'device_usb', + }, + 'includes': [ '../../build/jni_generator.gypi' ], + }, + { + 'target_name': 'device_usb_java', + 'type': 'none', + 'dependencies': [ + 'usb_descriptors_javagen', + '../../base/base.gyp:base', + ], + 'variables': { + 'java_in_dir': '../../device/usb/android/java', + }, + 'includes': [ '../../build/java.gypi' ], + }, + { + 'target_name': 'usb_descriptors_javagen', + 'type': 'none', + 'variables': { + 'source_file': 'usb_descriptors.h', + }, + 'includes': [ '../../build/android/java_cpp_enum.gypi' ], + }, + ], + }], + ], } diff --git a/device/usb/usb_configuration_android.cc b/device/usb/usb_configuration_android.cc new file mode 100644 index 0000000..4a9c712 --- /dev/null +++ b/device/usb/usb_configuration_android.cc @@ -0,0 +1,49 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/usb/usb_configuration_android.h" + +#include "device/usb/usb_interface_android.h" +#include "jni/ChromeUsbConfiguration_jni.h" + +using base::android::ScopedJavaLocalRef; + +namespace device { + +// static +bool UsbConfigurationAndroid::RegisterJNI(JNIEnv* env) { + return RegisterNativesImpl(env); // Generated in ChromeUsbConfiguration_jni.h +} + +// static +UsbConfigDescriptor UsbConfigurationAndroid::Convert( + JNIEnv* env, + const base::android::JavaRef<jobject>& usb_configuration) { + ScopedJavaLocalRef<jobject> wrapper = + Java_ChromeUsbConfiguration_create(env, usb_configuration.obj()); + + UsbConfigDescriptor config; + config.configuration_value = + Java_ChromeUsbConfiguration_getConfigurationValue(env, wrapper.obj()); + config.self_powered = + Java_ChromeUsbConfiguration_isSelfPowered(env, wrapper.obj()); + config.remote_wakeup = + Java_ChromeUsbConfiguration_isRemoteWakeup(env, wrapper.obj()); + config.maximum_power = + Java_ChromeUsbConfiguration_getMaxPower(env, wrapper.obj()); + + ScopedJavaLocalRef<jobjectArray> interfaces = + Java_ChromeUsbConfiguration_getInterfaces(env, wrapper.obj()); + jsize count = env->GetArrayLength(interfaces.obj()); + config.interfaces.reserve(count); + for (jsize i = 0; i < count; ++i) { + ScopedJavaLocalRef<jobject> interface( + env, env->GetObjectArrayElement(interfaces.obj(), i)); + config.interfaces.push_back(UsbInterfaceAndroid::Convert(env, interface)); + } + + return config; +} + +} // namespace device diff --git a/device/usb/usb_configuration_android.h b/device/usb/usb_configuration_android.h new file mode 100644 index 0000000..610ac07 --- /dev/null +++ b/device/usb/usb_configuration_android.h @@ -0,0 +1,25 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_USB_USB_CONFIGURATION_ANDROID_H_ +#define DEVICE_USB_USB_CONFIGURATION_ANDROID_H_ + +#include "base/android/scoped_java_ref.h" +#include "device/usb/usb_descriptors.h" + +namespace device { + +class UsbConfigurationAndroid { + public: + // Register C++ methods exposed to Java using JNI. + static bool RegisterJNI(JNIEnv* env); + + static UsbConfigDescriptor Convert( + JNIEnv* env, + const base::android::JavaRef<jobject>& usb_configuration); +}; + +} // namespace device + +#endif // DEVICE_USB_USB_CONFIGURATION_ANDROID_H_ diff --git a/device/usb/usb_descriptors.h b/device/usb/usb_descriptors.h index 93b6f62..adaa0ab 100644 --- a/device/usb/usb_descriptors.h +++ b/device/usb/usb_descriptors.h @@ -12,6 +12,8 @@ namespace device { +// A Java counterpart will be generated for this enum. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.device.usb enum UsbTransferType { USB_TRANSFER_CONTROL = 0, USB_TRANSFER_ISOCHRONOUS, @@ -19,6 +21,8 @@ enum UsbTransferType { USB_TRANSFER_INTERRUPT, }; +// A Java counterpart will be generated for this enum. +// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.device.usb enum UsbEndpointDirection { USB_DIRECTION_INBOUND = 0, USB_DIRECTION_OUTBOUND, diff --git a/device/usb/usb_device.h b/device/usb/usb_device.h index 9822a38..92d0e29 100644 --- a/device/usb/usb_device.h +++ b/device/usb/usb_device.h @@ -7,6 +7,7 @@ #include <stdint.h> +#include <string> #include <vector> #include "base/callback.h" @@ -59,10 +60,6 @@ class UsbDevice : public base::RefCountedThreadSafe<UsbDevice> { // Creates a UsbDeviceHandle for further manipulation. virtual void Open(const OpenCallback& callback) = 0; - // Explicitly closes a device handle. This method will be automatically called - // by the destructor of a UsbDeviceHandle as well. - virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) = 0; - // Gets the UsbConfigDescriptor for the active device configuration or nullptr // if the device is unconfigured. virtual const UsbConfigDescriptor* GetActiveConfiguration() = 0; diff --git a/device/usb/usb_device_android.cc b/device/usb/usb_device_android.cc new file mode 100644 index 0000000..ee9e93b --- /dev/null +++ b/device/usb/usb_device_android.cc @@ -0,0 +1,107 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/usb/usb_device_android.h" + +#include "base/android/build_info.h" +#include "base/android/jni_string.h" +#include "base/bind.h" +#include "base/location.h" +#include "base/thread_task_runner_handle.h" +#include "device/usb/usb_configuration_android.h" +#include "device/usb/usb_device_handle.h" +#include "device/usb/usb_interface_android.h" +#include "jni/ChromeUsbDevice_jni.h" + +using base::android::AttachCurrentThread; +using base::android::ConvertJavaStringToUTF16; +using base::android::JavaRef; +using base::android::ScopedJavaLocalRef; + +namespace device { + +// static +bool UsbDeviceAndroid::RegisterJNI(JNIEnv* env) { + return RegisterNativesImpl(env); // Generated in ChromeUsbDevice_jni.h +} + +// static +scoped_refptr<UsbDeviceAndroid> UsbDeviceAndroid::Create( + JNIEnv* env, + const JavaRef<jobject>& usb_device) { + ScopedJavaLocalRef<jobject> wrapper = + Java_ChromeUsbDevice_create(env, usb_device.obj()); + uint16_t vendor_id = Java_ChromeUsbDevice_getVendorId(env, wrapper.obj()); + uint16_t product_id = Java_ChromeUsbDevice_getProductId(env, wrapper.obj()); + ScopedJavaLocalRef<jstring> manufacturer_string = + Java_ChromeUsbDevice_getManufacturerName(env, wrapper.obj()); + ScopedJavaLocalRef<jstring> product_string = + Java_ChromeUsbDevice_getProductName(env, wrapper.obj()); + ScopedJavaLocalRef<jstring> serial_number = + Java_ChromeUsbDevice_getSerialNumber(env, wrapper.obj()); + return make_scoped_refptr(new UsbDeviceAndroid( + env, vendor_id, product_id, + ConvertJavaStringToUTF16(env, manufacturer_string), + ConvertJavaStringToUTF16(env, product_string), + ConvertJavaStringToUTF16(env, serial_number), wrapper)); +} + +void UsbDeviceAndroid::Open(const OpenCallback& callback) { + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + base::Bind(callback, nullptr)); +} + +const UsbConfigDescriptor* UsbDeviceAndroid::GetActiveConfiguration() { + return nullptr; +} + +UsbDeviceAndroid::UsbDeviceAndroid(JNIEnv* env, + uint16_t vendor_id, + uint16_t product_id, + const base::string16& manufacturer_string, + const base::string16& product_string, + const base::string16& serial_number, + const JavaRef<jobject>& wrapper) + : UsbDevice(vendor_id, + product_id, + manufacturer_string, + product_string, + serial_number) { + j_object_.Reset(wrapper); + + if (base::android::BuildInfo::GetInstance()->sdk_int() >= 21) { + ScopedJavaLocalRef<jobjectArray> configurations = + Java_ChromeUsbDevice_getConfigurations(env, j_object_.obj()); + jsize count = env->GetArrayLength(configurations.obj()); + configurations_.reserve(count); + for (jsize i = 0; i < count; ++i) { + ScopedJavaLocalRef<jobject> config( + env, env->GetObjectArrayElement(configurations.obj(), i)); + configurations_.push_back(UsbConfigurationAndroid::Convert(env, config)); + } + } else { + // Pre-lollipop only the first configuration was supported. Build a basic + // configuration out of the available interfaces. + UsbConfigDescriptor config; + config.configuration_value = 1; // Reasonable guess. + config.self_powered = false; // Arbitrary default. + config.remote_wakeup = false; // Arbitrary default. + config.maximum_power = 0; // Arbitrary default. + + ScopedJavaLocalRef<jobjectArray> interfaces = + Java_ChromeUsbDevice_getInterfaces(env, wrapper.obj()); + jsize count = env->GetArrayLength(interfaces.obj()); + config.interfaces.reserve(count); + for (jsize i = 0; i < count; ++i) { + ScopedJavaLocalRef<jobject> interface( + env, env->GetObjectArrayElement(interfaces.obj(), i)); + config.interfaces.push_back(UsbInterfaceAndroid::Convert(env, interface)); + } + configurations_.push_back(config); + } +} + +UsbDeviceAndroid::~UsbDeviceAndroid() {} + +} // namespace device diff --git a/device/usb/usb_device_android.h b/device/usb/usb_device_android.h new file mode 100644 index 0000000..ad468913 --- /dev/null +++ b/device/usb/usb_device_android.h @@ -0,0 +1,42 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_USB_USB_DEVICE_ANDROID_H_ +#define DEVICE_USB_USB_DEVICE_ANDROID_H_ + +#include "base/android/scoped_java_ref.h" +#include "device/usb/usb_device.h" + +namespace device { + +class UsbDeviceAndroid : public UsbDevice { + public: + // Register C++ methods exposed to Java using JNI. + static bool RegisterJNI(JNIEnv* env); + + static scoped_refptr<UsbDeviceAndroid> Create( + JNIEnv* env, + const base::android::JavaRef<jobject>& usb_device); + + // UsbDevice: + void Open(const OpenCallback& callback) override; + const UsbConfigDescriptor* GetActiveConfiguration() override; + + private: + UsbDeviceAndroid(JNIEnv* env, + uint16_t vendor_id, + uint16_t product_id, + const base::string16& manufacturer_string, + const base::string16& product_string, + const base::string16& serial_number, + const base::android::JavaRef<jobject>& wrapper); + ~UsbDeviceAndroid() override; + + // Java object org.chromium.device.usb.ChromeUsbDevice. + base::android::ScopedJavaGlobalRef<jobject> j_object_; +}; + +} // namespace device + +#endif // DEVICE_USB_USB_DEVICE_ANDROID_H_ diff --git a/device/usb/usb_device_impl.cc b/device/usb/usb_device_impl.cc index 874ccad..271b631 100644 --- a/device/usb/usb_device_impl.cc +++ b/device/usb/usb_device_impl.cc @@ -204,7 +204,7 @@ void UsbDeviceImpl::Open(const OpenCallback& callback) { #endif // defined(OS_CHROMEOS) } -bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) { +void UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) { DCHECK(thread_checker_.CalledOnValidThread()); for (HandlesVector::iterator it = handles_.begin(); it != handles_.end(); @@ -212,10 +212,9 @@ bool UsbDeviceImpl::Close(scoped_refptr<UsbDeviceHandle> handle) { if (it->get() == handle.get()) { (*it)->InternalClose(); handles_.erase(it); - return true; + return; } } - return false; } const UsbConfigDescriptor* UsbDeviceImpl::GetActiveConfiguration() { diff --git a/device/usb/usb_device_impl.h b/device/usb/usb_device_impl.h index 337c0e8..a64e3d1 100644 --- a/device/usb/usb_device_impl.h +++ b/device/usb/usb_device_impl.h @@ -6,6 +6,8 @@ #define DEVICE_USB_USB_DEVICE_IMPL_H_ #include <stdint.h> + +#include <string> #include <utility> #include <vector> @@ -45,7 +47,6 @@ class UsbDeviceImpl : public UsbDevice { void CheckUsbAccess(const ResultCallback& callback) override; #endif // OS_CHROMEOS void Open(const OpenCallback& callback) override; - bool Close(scoped_refptr<UsbDeviceHandle> handle) override; const UsbConfigDescriptor* GetActiveConfiguration() override; // These functions are used during enumeration only. The values must not @@ -87,6 +88,7 @@ class UsbDeviceImpl : public UsbDevice { void ReadAllConfigurations(); // Called by UsbDeviceHandleImpl. + void Close(scoped_refptr<UsbDeviceHandle> handle); void RefreshActiveConfiguration(); private: diff --git a/device/usb/usb_endpoint_android.cc b/device/usb/usb_endpoint_android.cc new file mode 100644 index 0000000..3280b04 --- /dev/null +++ b/device/usb/usb_endpoint_android.cc @@ -0,0 +1,41 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/usb/usb_endpoint_android.h" + +#include "jni/ChromeUsbEndpoint_jni.h" + +namespace device { + +// static +bool UsbEndpointAndroid::RegisterJNI(JNIEnv* env) { + return RegisterNativesImpl(env); // Generated in ChromeUsbEndpoint_jni.h +} + +// static +UsbEndpointDescriptor UsbEndpointAndroid::Convert( + JNIEnv* env, + const base::android::JavaRef<jobject>& usb_endpoint) { + base::android::ScopedJavaLocalRef<jobject> wrapper = + Java_ChromeUsbEndpoint_create(env, usb_endpoint.obj()); + + UsbEndpointDescriptor endpoint; + endpoint.address = Java_ChromeUsbEndpoint_getAddress(env, wrapper.obj()); + endpoint.direction = static_cast<UsbEndpointDirection>( + Java_ChromeUsbEndpoint_getDirection(env, wrapper.obj())); + endpoint.maximum_packet_size = + Java_ChromeUsbEndpoint_getMaxPacketSize(env, wrapper.obj()); + jint attributes = Java_ChromeUsbEndpoint_getAttributes(env, wrapper.obj()); + endpoint.synchronization_type = + static_cast<UsbSynchronizationType>((attributes >> 2) & 3); + endpoint.usage_type = static_cast<UsbUsageType>((attributes >> 4) & 3); + endpoint.transfer_type = static_cast<UsbTransferType>( + Java_ChromeUsbEndpoint_getType(env, wrapper.obj())); + endpoint.polling_interval = + Java_ChromeUsbEndpoint_getInterval(env, wrapper.obj()); + + return endpoint; +} + +} // namespace device diff --git a/device/usb/usb_endpoint_android.h b/device/usb/usb_endpoint_android.h new file mode 100644 index 0000000..3fc835c --- /dev/null +++ b/device/usb/usb_endpoint_android.h @@ -0,0 +1,25 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_USB_USB_ENDPOINT_ANDROID_H_ +#define DEVICE_USB_USB_ENDPOINT_ANDROID_H_ + +#include "base/android/scoped_java_ref.h" +#include "device/usb/usb_descriptors.h" + +namespace device { + +class UsbEndpointAndroid { + public: + // Register C++ methods exposed to Java using JNI. + static bool RegisterJNI(JNIEnv* env); + + static UsbEndpointDescriptor Convert( + JNIEnv* env, + const base::android::JavaRef<jobject>& usb_endpoint); +}; + +} // namespace device + +#endif // DEVICE_USB_USB_ENDPOINT_ANDROID_H_ diff --git a/device/usb/usb_interface_android.cc b/device/usb/usb_interface_android.cc new file mode 100644 index 0000000..60403ae --- /dev/null +++ b/device/usb/usb_interface_android.cc @@ -0,0 +1,51 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/usb/usb_interface_android.h" + +#include "device/usb/usb_endpoint_android.h" +#include "jni/ChromeUsbInterface_jni.h" + +using base::android::ScopedJavaLocalRef; + +namespace device { + +// static +bool UsbInterfaceAndroid::RegisterJNI(JNIEnv* env) { + return RegisterNativesImpl(env); // Generated in ChromeUsbInterface_jni.h +} + +// static +UsbInterfaceDescriptor UsbInterfaceAndroid::Convert( + JNIEnv* env, + const base::android::JavaRef<jobject>& usb_interface) { + ScopedJavaLocalRef<jobject> wrapper = + Java_ChromeUsbInterface_create(env, usb_interface.obj()); + + UsbInterfaceDescriptor interface; + interface.interface_number = + Java_ChromeUsbInterface_getInterfaceNumber(env, wrapper.obj()); + interface.alternate_setting = + Java_ChromeUsbInterface_getAlternateSetting(env, wrapper.obj()); + interface.interface_class = + Java_ChromeUsbInterface_getInterfaceClass(env, wrapper.obj()); + interface.interface_subclass = + Java_ChromeUsbInterface_getInterfaceSubclass(env, wrapper.obj()); + interface.interface_protocol = + Java_ChromeUsbInterface_getInterfaceProtocol(env, wrapper.obj()); + + ScopedJavaLocalRef<jobjectArray> endpoints = + Java_ChromeUsbInterface_getEndpoints(env, wrapper.obj()); + jsize count = env->GetArrayLength(endpoints.obj()); + interface.endpoints.reserve(count); + for (jsize i = 0; i < count; ++i) { + ScopedJavaLocalRef<jobject> endpoint( + env, env->GetObjectArrayElement(endpoints.obj(), i)); + interface.endpoints.push_back(UsbEndpointAndroid::Convert(env, endpoint)); + } + + return interface; +} + +} // namespace device diff --git a/device/usb/usb_interface_android.h b/device/usb/usb_interface_android.h new file mode 100644 index 0000000..ec04b61 --- /dev/null +++ b/device/usb/usb_interface_android.h @@ -0,0 +1,25 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_USB_USB_INTERFACE_ANDROID_H_ +#define DEVICE_USB_USB_INTERFACE_ANDROID_H_ + +#include "base/android/scoped_java_ref.h" +#include "device/usb/usb_descriptors.h" + +namespace device { + +class UsbInterfaceAndroid { + public: + // Register C++ methods exposed to Java using JNI. + static bool RegisterJNI(JNIEnv* env); + + static UsbInterfaceDescriptor Convert( + JNIEnv* env, + const base::android::JavaRef<jobject>& usb_interface); +}; + +} // namespace device + +#endif // DEVICE_USB_USB_INTERFACE_ANDROID_H_ diff --git a/device/usb/usb_service_android.cc b/device/usb/usb_service_android.cc index 45ce499..3bdf3bc 100644 --- a/device/usb/usb_service_android.cc +++ b/device/usb/usb_service_android.cc @@ -4,14 +4,30 @@ #include "device/usb/usb_service_android.h" +#include <string> +#include <vector> + +#include "base/android/context_utils.h" #include "base/bind.h" #include "base/location.h" #include "base/thread_task_runner_handle.h" -#include "device/usb/usb_device.h" +#include "device/usb/usb_device_android.h" +#include "jni/ChromeUsbService_jni.h" + +using base::android::AttachCurrentThread; +using base::android::ScopedJavaLocalRef; namespace device { -UsbServiceAndroid::UsbServiceAndroid() {} +// static +bool UsbServiceAndroid::RegisterJNI(JNIEnv* env) { + return RegisterNativesImpl(env); // Generated in ChromeUsbService_jni.h +} + +UsbServiceAndroid::UsbServiceAndroid() { + j_object_.Reset(Java_ChromeUsbService_create( + AttachCurrentThread(), base::android::GetApplicationContext())); +} UsbServiceAndroid::~UsbServiceAndroid() {} @@ -20,9 +36,20 @@ scoped_refptr<UsbDevice> UsbServiceAndroid::GetDevice(const std::string& guid) { } void UsbServiceAndroid::GetDevices(const GetDevicesCallback& callback) { - std::vector<scoped_refptr<UsbDevice>> empty; + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobjectArray> devices = + Java_ChromeUsbService_getDevices(env, j_object_.obj()); + jsize length = env->GetArrayLength(devices.obj()); + + std::vector<scoped_refptr<UsbDevice>> results; + for (jsize i = 0; i < length; ++i) { + ScopedJavaLocalRef<jobject> raw_device( + env, env->GetObjectArrayElement(devices.obj(), i)); + results.push_back(UsbDeviceAndroid::Create(env, raw_device)); + } + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, - base::Bind(callback, empty)); + base::Bind(callback, results)); } } // namespace device diff --git a/device/usb/usb_service_android.h b/device/usb/usb_service_android.h index d1ffd9d..9cab438 100644 --- a/device/usb/usb_service_android.h +++ b/device/usb/usb_service_android.h @@ -5,6 +5,9 @@ #ifndef DEVICE_USB_USB_SERVICE_ANDROID_H_ #define DEVICE_USB_USB_SERVICE_ANDROID_H_ +#include <string> + +#include "base/android/scoped_java_ref.h" #include "device/usb/usb_service.h" namespace device { @@ -13,11 +16,19 @@ namespace device { // does not return any devices. class UsbServiceAndroid : public UsbService { public: + // Register C++ methods exposed to Java using JNI. + static bool RegisterJNI(JNIEnv* env); + UsbServiceAndroid(); ~UsbServiceAndroid() override; + // UsbService: scoped_refptr<UsbDevice> GetDevice(const std::string& guid) override; void GetDevices(const GetDevicesCallback& callback) override; + + private: + // Java object org.chromium.device.usb.ChromeUsbService. + base::android::ScopedJavaGlobalRef<jobject> j_object_; }; } // namespace device |