Make castv2 performance test work.
[chromium-blink-merge.git] / chrome / browser / devtools / device / usb / android_usb_device.cc
blob9e5d700e885f5df9e14a128a9a87be722b508721
1 // Copyright 2014 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.
5 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
7 #include <set>
9 #include "base/barrier_closure.h"
10 #include "base/base64.h"
11 #include "base/lazy_instance.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/stl_util.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "chrome/browser/devtools/device/usb/android_rsa.h"
18 #include "chrome/browser/devtools/device/usb/android_usb_socket.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "crypto/rsa_private_key.h"
21 #include "device/core/device_client.h"
22 #include "device/usb/usb_descriptors.h"
23 #include "device/usb/usb_device.h"
24 #include "device/usb/usb_service.h"
25 #include "net/base/ip_endpoint.h"
26 #include "net/base/net_errors.h"
27 #include "net/socket/stream_socket.h"
29 using device::UsbConfigDescriptor;
30 using device::UsbDevice;
31 using device::UsbDeviceHandle;
32 using device::UsbInterfaceDescriptor;
33 using device::UsbEndpointDescriptor;
34 using device::UsbService;
35 using device::UsbTransferStatus;
37 namespace {
39 const size_t kHeaderSize = 24;
41 const int kAdbClass = 0xff;
42 const int kAdbSubclass = 0x42;
43 const int kAdbProtocol = 0x1;
45 const int kUsbTimeout = 0;
47 const uint32 kMaxPayload = 4096;
48 const uint32 kVersion = 0x01000000;
50 static const char kHostConnectMessage[] = "host::";
52 using content::BrowserThread;
54 typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices;
55 typedef std::set<scoped_refptr<UsbDevice> > UsbDeviceSet;
57 // Stores android wrappers around claimed usb devices on caller thread.
58 base::LazyInstance<std::vector<AndroidUsbDevice*> >::Leaky g_devices =
59 LAZY_INSTANCE_INITIALIZER;
61 bool IsAndroidInterface(const UsbInterfaceDescriptor& interface) {
62 if (interface.alternate_setting != 0 ||
63 interface.interface_class != kAdbClass ||
64 interface.interface_subclass != kAdbSubclass ||
65 interface.interface_protocol != kAdbProtocol ||
66 interface.endpoints.size() != 2) {
67 return false;
69 return true;
72 scoped_refptr<AndroidUsbDevice> ClaimInterface(
73 crypto::RSAPrivateKey* rsa_key,
74 scoped_refptr<UsbDeviceHandle> usb_handle,
75 const base::string16& serial,
76 const UsbInterfaceDescriptor& interface) {
77 int inbound_address = 0;
78 int outbound_address = 0;
79 int zero_mask = 0;
81 for (const UsbEndpointDescriptor& endpoint : interface.endpoints) {
82 if (endpoint.transfer_type != device::USB_TRANSFER_BULK)
83 continue;
84 if (endpoint.direction == device::USB_DIRECTION_INBOUND)
85 inbound_address = endpoint.address;
86 else
87 outbound_address = endpoint.address;
88 zero_mask = endpoint.maximum_packet_size - 1;
91 if (inbound_address == 0 || outbound_address == 0)
92 return NULL;
94 if (!usb_handle->ClaimInterface(interface.interface_number))
95 return NULL;
97 return new AndroidUsbDevice(rsa_key,
98 usb_handle,
99 base::UTF16ToASCII(serial),
100 inbound_address,
101 outbound_address,
102 zero_mask,
103 interface.interface_number);
106 uint32 Checksum(const std::string& data) {
107 unsigned char* x = (unsigned char*)data.data();
108 int count = data.length();
109 uint32 sum = 0;
110 while (count-- > 0)
111 sum += *x++;
112 return sum;
115 void DumpMessage(bool outgoing, const char* data, size_t length) {
116 #if 0
117 std::string result = "";
118 if (length == kHeaderSize) {
119 for (size_t i = 0; i < 24; ++i) {
120 result += base::StringPrintf("%02x",
121 data[i] > 0 ? data[i] : (data[i] + 0x100) & 0xFF);
122 if ((i + 1) % 4 == 0)
123 result += " ";
125 for (size_t i = 0; i < 24; ++i) {
126 if (data[i] >= 0x20 && data[i] <= 0x7E)
127 result += data[i];
128 else
129 result += ".";
131 } else {
132 result = base::StringPrintf("%d: ", (int)length);
133 for (size_t i = 0; i < length; ++i) {
134 if (data[i] >= 0x20 && data[i] <= 0x7E)
135 result += data[i];
136 else
137 result += ".";
140 LOG(ERROR) << (outgoing ? "[out] " : "[ in] ") << result;
141 #endif // 0
144 void ReleaseInterface(scoped_refptr<UsbDeviceHandle> usb_device,
145 int interface_id) {
146 usb_device->ReleaseInterface(interface_id);
147 usb_device->Close();
150 } // namespace
152 AdbMessage::AdbMessage(uint32 command,
153 uint32 arg0,
154 uint32 arg1,
155 const std::string& body)
156 : command(command),
157 arg0(arg0),
158 arg1(arg1),
159 body(body) {
162 AdbMessage::~AdbMessage() {
165 static void RespondOnCallerThread(const AndroidUsbDevicesCallback& callback,
166 AndroidUsbDevices* new_devices) {
167 scoped_ptr<AndroidUsbDevices> devices(new_devices);
169 // Add raw pointers to the newly claimed devices.
170 for (const scoped_refptr<AndroidUsbDevice>& device : *devices) {
171 g_devices.Get().push_back(device.get());
174 // Return all claimed devices.
175 AndroidUsbDevices result(g_devices.Get().begin(), g_devices.Get().end());
176 callback.Run(result);
179 static void RespondOnFileThread(
180 const AndroidUsbDevicesCallback& callback,
181 AndroidUsbDevices* devices,
182 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) {
183 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
184 caller_message_loop_proxy->PostTask(
185 FROM_HERE,
186 base::Bind(&RespondOnCallerThread, callback, devices));
189 static void OpenAndroidDeviceOnFileThread(
190 AndroidUsbDevices* devices,
191 crypto::RSAPrivateKey* rsa_key,
192 const base::Closure& barrier,
193 scoped_refptr<UsbDevice> device,
194 int interface_id,
195 bool success) {
196 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
197 if (success) {
198 base::string16 serial;
199 if (device->GetSerialNumber(&serial) && !serial.empty()) {
200 const UsbConfigDescriptor* config = device->GetConfiguration();
201 if (config) {
202 scoped_refptr<UsbDeviceHandle> usb_handle = device->Open();
203 if (usb_handle.get()) {
204 scoped_refptr<AndroidUsbDevice> android_device = ClaimInterface(
205 rsa_key, usb_handle, serial, config->interfaces[interface_id]);
206 if (android_device.get())
207 devices->push_back(android_device);
208 else
209 usb_handle->Close();
214 barrier.Run();
217 static int CountOnFileThread() {
218 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
219 UsbService* service = device::DeviceClient::Get()->GetUsbService();
220 UsbDevices usb_devices;
221 if (service != NULL)
222 service->GetDevices(&usb_devices);
223 int device_count = 0;
224 for (const scoped_refptr<UsbDevice>& device : usb_devices) {
225 const UsbConfigDescriptor* config = device->GetConfiguration();
226 if (config) {
227 for (const UsbInterfaceDescriptor& iface : config->interfaces) {
228 if (IsAndroidInterface(iface)) {
229 ++device_count;
234 return device_count;
237 static void EnumerateOnFileThread(
238 crypto::RSAPrivateKey* rsa_key,
239 const AndroidUsbDevicesCallback& callback,
240 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) {
241 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
243 UsbService* service = device::DeviceClient::Get()->GetUsbService();
244 UsbDevices usb_devices;
245 if (service != NULL)
246 service->GetDevices(&usb_devices);
248 // Add new devices.
249 AndroidUsbDevices* devices = new AndroidUsbDevices();
250 base::Closure barrier = base::BarrierClosure(
251 usb_devices.size(), base::Bind(&RespondOnFileThread,
252 callback,
253 devices,
254 caller_message_loop_proxy));
256 for (const scoped_refptr<UsbDevice>& device : usb_devices) {
257 const UsbConfigDescriptor* config = device->GetConfiguration();
258 if (!config) {
259 barrier.Run();
260 continue;
262 bool has_android_interface = false;
263 for (size_t j = 0; j < config->interfaces.size(); ++j) {
264 if (!IsAndroidInterface(config->interfaces[j])) {
265 continue;
268 device->RequestUsbAccess(
269 j, base::Bind(&OpenAndroidDeviceOnFileThread, devices, rsa_key,
270 barrier, device, j));
272 has_android_interface = true;
273 break;
275 if (!has_android_interface)
276 barrier.Run();
280 // static
281 void AndroidUsbDevice::CountDevices(
282 const base::Callback<void(int)>& callback) {
283 BrowserThread::PostTaskAndReplyWithResult(
284 BrowserThread::FILE,
285 FROM_HERE,
286 base::Bind(&CountOnFileThread),
287 callback);
290 // static
291 void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key,
292 const AndroidUsbDevicesCallback& callback) {
294 // Collect devices with closed handles.
295 for (AndroidUsbDevice* device : g_devices.Get()) {
296 if (device->usb_handle_.get()) {
297 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
298 base::Bind(&AndroidUsbDevice::TerminateIfReleased, device,
299 device->usb_handle_));
303 // Then look for the new devices.
304 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
305 base::Bind(&EnumerateOnFileThread, rsa_key, callback,
306 base::MessageLoopProxy::current()));
309 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
310 scoped_refptr<UsbDeviceHandle> usb_device,
311 const std::string& serial,
312 int inbound_address,
313 int outbound_address,
314 int zero_mask,
315 int interface_id)
316 : message_loop_(NULL),
317 rsa_key_(rsa_key->Copy()),
318 usb_handle_(usb_device),
319 serial_(serial),
320 inbound_address_(inbound_address),
321 outbound_address_(outbound_address),
322 zero_mask_(zero_mask),
323 interface_id_(interface_id),
324 is_connected_(false),
325 signature_sent_(false),
326 last_socket_id_(256),
327 weak_factory_(this) {
330 void AndroidUsbDevice::InitOnCallerThread() {
331 if (message_loop_)
332 return;
333 message_loop_ = base::MessageLoop::current();
334 Queue(make_scoped_ptr(new AdbMessage(AdbMessage::kCommandCNXN, kVersion,
335 kMaxPayload, kHostConnectMessage)));
336 ReadHeader();
339 net::StreamSocket* AndroidUsbDevice::CreateSocket(const std::string& command) {
340 if (!usb_handle_.get())
341 return NULL;
343 uint32 socket_id = ++last_socket_id_;
344 sockets_[socket_id] = new AndroidUsbSocket(this, socket_id, command,
345 base::Bind(&AndroidUsbDevice::SocketDeleted, this, socket_id));
346 return sockets_[socket_id];
349 void AndroidUsbDevice::Send(uint32 command,
350 uint32 arg0,
351 uint32 arg1,
352 const std::string& body) {
353 scoped_ptr<AdbMessage> message(new AdbMessage(command, arg0, arg1, body));
354 // Delay open request if not yet connected.
355 if (!is_connected_) {
356 pending_messages_.push_back(message.release());
357 return;
359 Queue(message.Pass());
362 AndroidUsbDevice::~AndroidUsbDevice() {
363 DCHECK(message_loop_ == base::MessageLoop::current());
364 Terminate();
367 void AndroidUsbDevice::Queue(scoped_ptr<AdbMessage> message) {
368 DCHECK(message_loop_ == base::MessageLoop::current());
370 // Queue header.
371 std::vector<uint32> header;
372 header.push_back(message->command);
373 header.push_back(message->arg0);
374 header.push_back(message->arg1);
375 bool append_zero = true;
376 if (message->body.empty())
377 append_zero = false;
378 if (message->command == AdbMessage::kCommandAUTH &&
379 message->arg0 == AdbMessage::kAuthSignature)
380 append_zero = false;
381 if (message->command == AdbMessage::kCommandWRTE)
382 append_zero = false;
384 size_t body_length = message->body.length() + (append_zero ? 1 : 0);
385 header.push_back(body_length);
386 header.push_back(Checksum(message->body));
387 header.push_back(message->command ^ 0xffffffff);
388 scoped_refptr<net::IOBufferWithSize> header_buffer =
389 new net::IOBufferWithSize(kHeaderSize);
390 memcpy(header_buffer.get()->data(), &header[0], kHeaderSize);
391 outgoing_queue_.push(header_buffer);
393 // Queue body.
394 if (!message->body.empty()) {
395 scoped_refptr<net::IOBufferWithSize> body_buffer =
396 new net::IOBufferWithSize(body_length);
397 memcpy(body_buffer->data(), message->body.data(), message->body.length());
398 if (append_zero)
399 body_buffer->data()[body_length - 1] = 0;
400 outgoing_queue_.push(body_buffer);
401 if (zero_mask_ && (body_length & zero_mask_) == 0) {
402 // Send a zero length packet.
403 outgoing_queue_.push(new net::IOBufferWithSize(0));
406 ProcessOutgoing();
409 void AndroidUsbDevice::ProcessOutgoing() {
410 DCHECK(message_loop_ == base::MessageLoop::current());
412 if (outgoing_queue_.empty() || !usb_handle_.get())
413 return;
415 BulkMessage message = outgoing_queue_.front();
416 outgoing_queue_.pop();
417 DumpMessage(true, message->data(), message->size());
418 usb_handle_->BulkTransfer(device::USB_DIRECTION_OUTBOUND,
419 outbound_address_,
420 message.get(),
421 message->size(),
422 kUsbTimeout,
423 base::Bind(&AndroidUsbDevice::OutgoingMessageSent,
424 weak_factory_.GetWeakPtr()));
427 void AndroidUsbDevice::OutgoingMessageSent(UsbTransferStatus status,
428 scoped_refptr<net::IOBuffer> buffer,
429 size_t result) {
430 DCHECK(message_loop_ == base::MessageLoop::current());
432 if (status != device::USB_TRANSFER_COMPLETED)
433 return;
434 message_loop_->PostTask(FROM_HERE,
435 base::Bind(&AndroidUsbDevice::ProcessOutgoing, this));
438 void AndroidUsbDevice::ReadHeader() {
439 DCHECK(message_loop_ == base::MessageLoop::current());
441 if (!usb_handle_.get())
442 return;
443 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kHeaderSize);
444 usb_handle_->BulkTransfer(
445 device::USB_DIRECTION_INBOUND,
446 inbound_address_,
447 buffer.get(),
448 kHeaderSize,
449 kUsbTimeout,
450 base::Bind(&AndroidUsbDevice::ParseHeader, weak_factory_.GetWeakPtr()));
453 void AndroidUsbDevice::ParseHeader(UsbTransferStatus status,
454 scoped_refptr<net::IOBuffer> buffer,
455 size_t result) {
456 DCHECK(message_loop_ == base::MessageLoop::current());
458 if (status == device::USB_TRANSFER_TIMEOUT) {
459 message_loop_->PostTask(FROM_HERE,
460 base::Bind(&AndroidUsbDevice::ReadHeader, this));
461 return;
464 if (status != device::USB_TRANSFER_COMPLETED || result != kHeaderSize) {
465 TransferError(status);
466 return;
469 DumpMessage(false, buffer->data(), result);
470 std::vector<uint32> header(6);
471 memcpy(&header[0], buffer->data(), result);
472 scoped_ptr<AdbMessage> message(
473 new AdbMessage(header[0], header[1], header[2], ""));
474 uint32 data_length = header[3];
475 uint32 data_check = header[4];
476 uint32 magic = header[5];
477 if ((message->command ^ 0xffffffff) != magic) {
478 TransferError(device::USB_TRANSFER_ERROR);
479 return;
482 if (data_length == 0) {
483 message_loop_->PostTask(FROM_HERE,
484 base::Bind(&AndroidUsbDevice::HandleIncoming, this,
485 base::Passed(&message)));
486 return;
489 message_loop_->PostTask(FROM_HERE,
490 base::Bind(&AndroidUsbDevice::ReadBody, this,
491 base::Passed(&message), data_length, data_check));
494 void AndroidUsbDevice::ReadBody(scoped_ptr<AdbMessage> message,
495 uint32 data_length,
496 uint32 data_check) {
497 DCHECK(message_loop_ == base::MessageLoop::current());
499 if (!usb_handle_.get())
500 return;
501 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_length);
502 usb_handle_->BulkTransfer(device::USB_DIRECTION_INBOUND,
503 inbound_address_,
504 buffer.get(),
505 data_length,
506 kUsbTimeout,
507 base::Bind(&AndroidUsbDevice::ParseBody,
508 weak_factory_.GetWeakPtr(),
509 base::Passed(&message),
510 data_length,
511 data_check));
514 void AndroidUsbDevice::ParseBody(scoped_ptr<AdbMessage> message,
515 uint32 data_length,
516 uint32 data_check,
517 UsbTransferStatus status,
518 scoped_refptr<net::IOBuffer> buffer,
519 size_t result) {
520 DCHECK(message_loop_ == base::MessageLoop::current());
522 if (status == device::USB_TRANSFER_TIMEOUT) {
523 message_loop_->PostTask(FROM_HERE,
524 base::Bind(&AndroidUsbDevice::ReadBody, this,
525 base::Passed(&message), data_length, data_check));
526 return;
529 if (status != device::USB_TRANSFER_COMPLETED ||
530 static_cast<uint32>(result) != data_length) {
531 TransferError(status);
532 return;
535 DumpMessage(false, buffer->data(), data_length);
536 message->body = std::string(buffer->data(), result);
537 if (Checksum(message->body) != data_check) {
538 TransferError(device::USB_TRANSFER_ERROR);
539 return;
542 message_loop_->PostTask(FROM_HERE,
543 base::Bind(&AndroidUsbDevice::HandleIncoming, this,
544 base::Passed(&message)));
547 void AndroidUsbDevice::HandleIncoming(scoped_ptr<AdbMessage> message) {
548 DCHECK(message_loop_ == base::MessageLoop::current());
550 switch (message->command) {
551 case AdbMessage::kCommandAUTH:
553 DCHECK_EQ(message->arg0, static_cast<uint32>(AdbMessage::kAuthToken));
554 if (signature_sent_) {
555 Queue(make_scoped_ptr(new AdbMessage(
556 AdbMessage::kCommandAUTH,
557 AdbMessage::kAuthRSAPublicKey, 0,
558 AndroidRSAPublicKey(rsa_key_.get()))));
559 } else {
560 signature_sent_ = true;
561 std::string signature = AndroidRSASign(rsa_key_.get(), message->body);
562 if (!signature.empty()) {
563 Queue(make_scoped_ptr(new AdbMessage(AdbMessage::kCommandAUTH,
564 AdbMessage::kAuthSignature, 0,
565 signature)));
566 } else {
567 Queue(make_scoped_ptr(new AdbMessage(
568 AdbMessage::kCommandAUTH,
569 AdbMessage::kAuthRSAPublicKey, 0,
570 AndroidRSAPublicKey(rsa_key_.get()))));
574 break;
575 case AdbMessage::kCommandCNXN:
577 is_connected_ = true;
578 PendingMessages pending;
579 pending.swap(pending_messages_);
580 for (PendingMessages::iterator it = pending.begin();
581 it != pending.end(); ++it) {
582 Queue(make_scoped_ptr(*it));
585 break;
586 case AdbMessage::kCommandOKAY:
587 case AdbMessage::kCommandWRTE:
588 case AdbMessage::kCommandCLSE:
590 AndroidUsbSockets::iterator it = sockets_.find(message->arg1);
591 if (it != sockets_.end())
592 it->second->HandleIncoming(message.Pass());
594 break;
595 default:
596 break;
598 ReadHeader();
601 void AndroidUsbDevice::TransferError(UsbTransferStatus status) {
602 DCHECK(message_loop_ == base::MessageLoop::current());
604 message_loop_->PostTask(FROM_HERE,
605 base::Bind(&AndroidUsbDevice::Terminate, this));
608 void AndroidUsbDevice::TerminateIfReleased(
609 scoped_refptr<UsbDeviceHandle> usb_handle) {
610 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
611 if (usb_handle->GetDevice().get())
612 return;
613 message_loop_->PostTask(FROM_HERE,
614 base::Bind(&AndroidUsbDevice::Terminate, this));
617 void AndroidUsbDevice::Terminate() {
618 DCHECK(message_loop_ == base::MessageLoop::current());
620 std::vector<AndroidUsbDevice*>::iterator it =
621 std::find(g_devices.Get().begin(), g_devices.Get().end(), this);
622 if (it != g_devices.Get().end())
623 g_devices.Get().erase(it);
625 if (!usb_handle_.get())
626 return;
628 // Make sure we zero-out handle so that closing connections did not open
629 // new connections.
630 scoped_refptr<UsbDeviceHandle> usb_handle = usb_handle_;
631 usb_handle_ = NULL;
633 // Iterate over copy.
634 AndroidUsbSockets sockets(sockets_);
635 for (AndroidUsbSockets::iterator it = sockets.begin();
636 it != sockets.end(); ++it) {
637 it->second->Terminated(true);
639 DCHECK(sockets_.empty());
641 BrowserThread::PostTask(
642 BrowserThread::FILE, FROM_HERE,
643 base::Bind(&ReleaseInterface, usb_handle, interface_id_));
646 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) {
647 DCHECK(message_loop_ == base::MessageLoop::current());
649 sockets_.erase(socket_id);