usb_device_android.cc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "services/device/usb/usb_device_android.h"
  5. #include <list>
  6. #include <memory>
  7. #include <utility>
  8. #include "base/android/build_info.h"
  9. #include "base/android/jni_string.h"
  10. #include "base/bind.h"
  11. #include "base/location.h"
  12. #include "base/threading/thread_task_runner_handle.h"
  13. #include "services/device/usb/jni_headers/ChromeUsbDevice_jni.h"
  14. #include "services/device/usb/usb_configuration_android.h"
  15. #include "services/device/usb/usb_descriptors.h"
  16. #include "services/device/usb/usb_device_handle_android.h"
  17. #include "services/device/usb/usb_interface_android.h"
  18. #include "services/device/usb/usb_service_android.h"
  19. #include "services/device/usb/webusb_descriptors.h"
  20. using base::android::ConvertJavaStringToUTF16;
  21. using base::android::JavaObjectArrayReader;
  22. using base::android::JavaRef;
  23. using base::android::ScopedJavaLocalRef;
  24. namespace device {
  25. // static
  26. scoped_refptr<UsbDeviceAndroid> UsbDeviceAndroid::Create(
  27. JNIEnv* env,
  28. base::WeakPtr<UsbServiceAndroid> service,
  29. const JavaRef<jobject>& usb_device) {
  30. auto* build_info = base::android::BuildInfo::GetInstance();
  31. ScopedJavaLocalRef<jobject> wrapper =
  32. Java_ChromeUsbDevice_create(env, usb_device);
  33. uint16_t device_version = 0;
  34. if (build_info->sdk_int() >= base::android::SDK_VERSION_MARSHMALLOW)
  35. device_version = Java_ChromeUsbDevice_getDeviceVersion(env, wrapper);
  36. std::u16string manufacturer_string;
  37. ScopedJavaLocalRef<jstring> manufacturer_jstring =
  38. Java_ChromeUsbDevice_getManufacturerName(env, wrapper);
  39. if (!manufacturer_jstring.is_null())
  40. manufacturer_string = ConvertJavaStringToUTF16(env, manufacturer_jstring);
  41. std::u16string product_string;
  42. ScopedJavaLocalRef<jstring> product_jstring =
  43. Java_ChromeUsbDevice_getProductName(env, wrapper);
  44. if (!product_jstring.is_null())
  45. product_string = ConvertJavaStringToUTF16(env, product_jstring);
  46. // Reading the serial number requires device access permission when
  47. // targeting the Q SDK.
  48. std::u16string serial_number;
  49. if (service->HasDevicePermission(wrapper) ||
  50. build_info->sdk_int() < base::android::SDK_VERSION_Q) {
  51. ScopedJavaLocalRef<jstring> serial_jstring =
  52. Java_ChromeUsbDevice_getSerialNumber(env, wrapper);
  53. if (!serial_jstring.is_null())
  54. serial_number = ConvertJavaStringToUTF16(env, serial_jstring);
  55. }
  56. return base::WrapRefCounted(new UsbDeviceAndroid(
  57. env, service,
  58. 0x0200, // USB protocol version, not provided by the Android API.
  59. Java_ChromeUsbDevice_getDeviceClass(env, wrapper),
  60. Java_ChromeUsbDevice_getDeviceSubclass(env, wrapper),
  61. Java_ChromeUsbDevice_getDeviceProtocol(env, wrapper),
  62. Java_ChromeUsbDevice_getVendorId(env, wrapper),
  63. Java_ChromeUsbDevice_getProductId(env, wrapper), device_version,
  64. manufacturer_string, product_string, serial_number, wrapper));
  65. }
  66. void UsbDeviceAndroid::RequestPermission(ResultCallback callback) {
  67. if (!permission_granted_ && service_) {
  68. request_permission_callbacks_.push_back(std::move(callback));
  69. service_->RequestDevicePermission(j_object_);
  70. } else {
  71. base::ThreadTaskRunnerHandle::Get()->PostTask(
  72. FROM_HERE, base::BindOnce(std::move(callback), permission_granted_));
  73. }
  74. }
  75. void UsbDeviceAndroid::Open(OpenCallback callback) {
  76. scoped_refptr<UsbDeviceHandle> device_handle;
  77. if (service_) {
  78. JNIEnv* env = base::android::AttachCurrentThread();
  79. ScopedJavaLocalRef<jobject> connection =
  80. service_->OpenDevice(env, j_object_);
  81. if (!connection.is_null()) {
  82. device_handle = UsbDeviceHandleAndroid::Create(env, this, connection);
  83. handles().push_back(device_handle.get());
  84. }
  85. }
  86. base::ThreadTaskRunnerHandle::Get()->PostTask(
  87. FROM_HERE, base::BindOnce(std::move(callback), device_handle));
  88. }
  89. bool UsbDeviceAndroid::permission_granted() const {
  90. return permission_granted_;
  91. }
  92. UsbDeviceAndroid::UsbDeviceAndroid(JNIEnv* env,
  93. base::WeakPtr<UsbServiceAndroid> service,
  94. uint16_t usb_version,
  95. uint8_t device_class,
  96. uint8_t device_subclass,
  97. uint8_t device_protocol,
  98. uint16_t vendor_id,
  99. uint16_t product_id,
  100. uint16_t device_version,
  101. const std::u16string& manufacturer_string,
  102. const std::u16string& product_string,
  103. const std::u16string& serial_number,
  104. const JavaRef<jobject>& wrapper)
  105. : UsbDevice(usb_version,
  106. device_class,
  107. device_subclass,
  108. device_protocol,
  109. vendor_id,
  110. product_id,
  111. device_version,
  112. manufacturer_string,
  113. product_string,
  114. serial_number,
  115. // We fake the bus and port number, because the underlying Java
  116. // UsbDevice class doesn't offer an interface for getting these
  117. // values, and nothing on Android seems to require them at this
  118. // time (23-Nov-2018)
  119. 0,
  120. 0),
  121. device_id_(Java_ChromeUsbDevice_getDeviceId(env, wrapper)),
  122. service_(service),
  123. j_object_(wrapper) {
  124. JavaObjectArrayReader<jobject> configs(
  125. Java_ChromeUsbDevice_getConfigurations(env, j_object_));
  126. device_info_->configurations.reserve(configs.size());
  127. for (auto config : configs) {
  128. device_info_->configurations.push_back(
  129. UsbConfigurationAndroid::Convert(env, config));
  130. }
  131. if (configurations().size() > 0)
  132. ActiveConfigurationChanged(configurations()[0]->configuration_value);
  133. }
  134. UsbDeviceAndroid::~UsbDeviceAndroid() {}
  135. void UsbDeviceAndroid::PermissionGranted(JNIEnv* env, bool granted) {
  136. if (!granted) {
  137. CallRequestPermissionCallbacks(false);
  138. return;
  139. }
  140. ScopedJavaLocalRef<jstring> serial_jstring =
  141. Java_ChromeUsbDevice_getSerialNumber(env, j_object_);
  142. if (!serial_jstring.is_null())
  143. device_info_->serial_number = ConvertJavaStringToUTF16(env, serial_jstring);
  144. Open(
  145. base::BindOnce(&UsbDeviceAndroid::OnDeviceOpenedToReadDescriptors, this));
  146. }
  147. void UsbDeviceAndroid::CallRequestPermissionCallbacks(bool granted) {
  148. permission_granted_ = granted;
  149. std::list<ResultCallback> callbacks;
  150. callbacks.swap(request_permission_callbacks_);
  151. for (auto& callback : callbacks)
  152. std::move(callback).Run(granted);
  153. }
  154. void UsbDeviceAndroid::OnDeviceOpenedToReadDescriptors(
  155. scoped_refptr<UsbDeviceHandle> device_handle) {
  156. if (!device_handle) {
  157. CallRequestPermissionCallbacks(false);
  158. return;
  159. }
  160. ReadUsbDescriptors(device_handle,
  161. base::BindOnce(&UsbDeviceAndroid::OnReadDescriptors, this,
  162. device_handle));
  163. }
  164. void UsbDeviceAndroid::OnReadDescriptors(
  165. scoped_refptr<UsbDeviceHandle> device_handle,
  166. std::unique_ptr<UsbDeviceDescriptor> descriptor) {
  167. if (!descriptor) {
  168. device_handle->Close();
  169. CallRequestPermissionCallbacks(false);
  170. return;
  171. }
  172. // ReadUsbDescriptors() is called to read properties which aren't always
  173. // available from the Android OS. The other properties should be left alone.
  174. device_info_->usb_version_major = descriptor->device_info->usb_version_major;
  175. device_info_->usb_version_minor = descriptor->device_info->usb_version_minor;
  176. device_info_->usb_version_subminor =
  177. descriptor->device_info->usb_version_subminor;
  178. device_info_->configurations =
  179. std::move(descriptor->device_info->configurations);
  180. if (usb_version() >= 0x0210) {
  181. ReadWebUsbDescriptors(
  182. device_handle,
  183. base::BindOnce(&UsbDeviceAndroid::OnReadWebUsbDescriptors, this,
  184. device_handle));
  185. } else {
  186. device_handle->Close();
  187. CallRequestPermissionCallbacks(true);
  188. }
  189. }
  190. void UsbDeviceAndroid::OnReadWebUsbDescriptors(
  191. scoped_refptr<UsbDeviceHandle> device_handle,
  192. const GURL& landing_page) {
  193. if (landing_page.is_valid())
  194. device_info_->webusb_landing_page = landing_page;
  195. device_handle->Close();
  196. CallRequestPermissionCallbacks(true);
  197. }
  198. } // namespace device