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.
4
5 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
6
7 #include <set>
8
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"
28
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;
36
37 namespace {
38
39 const size_t kHeaderSize = 24;
40
41 const int kAdbClass = 0xff;
42 const int kAdbSubclass = 0x42;
43 const int kAdbProtocol = 0x1;
44
45 const int kUsbTimeout = 0;
46
47 const uint32 kMaxPayload = 4096;
48 const uint32 kVersion = 0x01000000;
49
50 static const char kHostConnectMessage[] = "host::";
51
52 using content::BrowserThread;
53
54 typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices;
55 typedef std::set<scoped_refptr<UsbDevice> > UsbDeviceSet;
56
57 // Stores android wrappers around claimed usb devices on caller thread.
58 base::LazyInstance<std::vector<AndroidUsbDevice*> >::Leaky g_devices =
59 LAZY_INSTANCE_INITIALIZER;
60
IsAndroidInterface(const UsbInterfaceDescriptor & interface)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;
68 }
69 return true;
70 }
71
ClaimInterface(crypto::RSAPrivateKey * rsa_key,scoped_refptr<UsbDeviceHandle> usb_handle,const base::string16 & serial,const UsbInterfaceDescriptor & interface)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;
80
81 for (UsbEndpointDescriptor::Iterator endpointIt = interface.endpoints.begin();
82 endpointIt != interface.endpoints.end();
83 ++endpointIt) {
84 if (endpointIt->transfer_type != device::USB_TRANSFER_BULK)
85 continue;
86 if (endpointIt->direction == device::USB_DIRECTION_INBOUND)
87 inbound_address = endpointIt->address;
88 else
89 outbound_address = endpointIt->address;
90 zero_mask = endpointIt->maximum_packet_size - 1;
91 }
92
93 if (inbound_address == 0 || outbound_address == 0)
94 return NULL;
95
96 if (!usb_handle->ClaimInterface(interface.interface_number))
97 return NULL;
98
99 return new AndroidUsbDevice(rsa_key,
100 usb_handle,
101 base::UTF16ToASCII(serial),
102 inbound_address,
103 outbound_address,
104 zero_mask,
105 interface.interface_number);
106 }
107
Checksum(const std::string & data)108 uint32 Checksum(const std::string& data) {
109 unsigned char* x = (unsigned char*)data.data();
110 int count = data.length();
111 uint32 sum = 0;
112 while (count-- > 0)
113 sum += *x++;
114 return sum;
115 }
116
DumpMessage(bool outgoing,const char * data,size_t length)117 void DumpMessage(bool outgoing, const char* data, size_t length) {
118 #if 0
119 std::string result = "";
120 if (length == kHeaderSize) {
121 for (size_t i = 0; i < 24; ++i) {
122 result += base::StringPrintf("%02x",
123 data[i] > 0 ? data[i] : (data[i] + 0x100) & 0xFF);
124 if ((i + 1) % 4 == 0)
125 result += " ";
126 }
127 for (size_t i = 0; i < 24; ++i) {
128 if (data[i] >= 0x20 && data[i] <= 0x7E)
129 result += data[i];
130 else
131 result += ".";
132 }
133 } else {
134 result = base::StringPrintf("%d: ", (int)length);
135 for (size_t i = 0; i < length; ++i) {
136 if (data[i] >= 0x20 && data[i] <= 0x7E)
137 result += data[i];
138 else
139 result += ".";
140 }
141 }
142 LOG(ERROR) << (outgoing ? "[out] " : "[ in] ") << result;
143 #endif // 0
144 }
145
ReleaseInterface(scoped_refptr<UsbDeviceHandle> usb_device,int interface_id)146 void ReleaseInterface(scoped_refptr<UsbDeviceHandle> usb_device,
147 int interface_id) {
148 usb_device->ReleaseInterface(interface_id);
149 usb_device->Close();
150 }
151
152 } // namespace
153
AdbMessage(uint32 command,uint32 arg0,uint32 arg1,const std::string & body)154 AdbMessage::AdbMessage(uint32 command,
155 uint32 arg0,
156 uint32 arg1,
157 const std::string& body)
158 : command(command),
159 arg0(arg0),
160 arg1(arg1),
161 body(body) {
162 }
163
~AdbMessage()164 AdbMessage::~AdbMessage() {
165 }
166
RespondOnCallerThread(const AndroidUsbDevicesCallback & callback,AndroidUsbDevices * new_devices)167 static void RespondOnCallerThread(const AndroidUsbDevicesCallback& callback,
168 AndroidUsbDevices* new_devices) {
169 scoped_ptr<AndroidUsbDevices> devices(new_devices);
170
171 // Add raw pointers to the newly claimed devices.
172 for (AndroidUsbDevices::iterator it = devices->begin(); it != devices->end();
173 ++it) {
174 g_devices.Get().push_back(it->get());
175 }
176
177 // Return all claimed devices.
178 AndroidUsbDevices result(g_devices.Get().begin(), g_devices.Get().end());
179 callback.Run(result);
180 }
181
RespondOnFileThread(const AndroidUsbDevicesCallback & callback,AndroidUsbDevices * devices,scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy)182 static void RespondOnFileThread(
183 const AndroidUsbDevicesCallback& callback,
184 AndroidUsbDevices* devices,
185 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
187 caller_message_loop_proxy->PostTask(
188 FROM_HERE,
189 base::Bind(&RespondOnCallerThread, callback, devices));
190 }
191
OpenAndroidDeviceOnFileThread(AndroidUsbDevices * devices,crypto::RSAPrivateKey * rsa_key,const base::Closure & barrier,scoped_refptr<UsbDevice> device,int interface_id,bool success)192 static void OpenAndroidDeviceOnFileThread(
193 AndroidUsbDevices* devices,
194 crypto::RSAPrivateKey* rsa_key,
195 const base::Closure& barrier,
196 scoped_refptr<UsbDevice> device,
197 int interface_id,
198 bool success) {
199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
200 if (success) {
201 base::string16 serial;
202 if (device->GetSerialNumber(&serial) && !serial.empty()) {
203 const UsbConfigDescriptor& config = device->GetConfiguration();
204 scoped_refptr<UsbDeviceHandle> usb_handle = device->Open();
205 if (usb_handle.get()) {
206 scoped_refptr<AndroidUsbDevice> android_device =
207 ClaimInterface(rsa_key, usb_handle, serial,
208 config.interfaces[interface_id]);
209 if (android_device.get())
210 devices->push_back(android_device.get());
211 else
212 usb_handle->Close();
213 }
214 }
215 }
216 barrier.Run();
217 }
218
CountOnFileThread()219 static int CountOnFileThread() {
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
221 UsbService* service = device::DeviceClient::Get()->GetUsbService();
222 UsbDevices usb_devices;
223 if (service != NULL)
224 service->GetDevices(&usb_devices);
225 int device_count = 0;
226 for (UsbDevices::iterator deviceIt = usb_devices.begin();
227 deviceIt != usb_devices.end();
228 ++deviceIt) {
229 const UsbConfigDescriptor& config = (*deviceIt)->GetConfiguration();
230
231 for (UsbInterfaceDescriptor::Iterator ifaceIt = config.interfaces.begin();
232 ifaceIt != config.interfaces.end();
233 ++ifaceIt) {
234 if (IsAndroidInterface(*ifaceIt)) {
235 ++device_count;
236 }
237 }
238 }
239 return device_count;
240 }
241
EnumerateOnFileThread(crypto::RSAPrivateKey * rsa_key,const AndroidUsbDevicesCallback & callback,scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy)242 static void EnumerateOnFileThread(
243 crypto::RSAPrivateKey* rsa_key,
244 const AndroidUsbDevicesCallback& callback,
245 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) {
246 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
247
248 UsbService* service = device::DeviceClient::Get()->GetUsbService();
249 UsbDevices usb_devices;
250 if (service != NULL)
251 service->GetDevices(&usb_devices);
252
253 // Add new devices.
254 AndroidUsbDevices* devices = new AndroidUsbDevices();
255 base::Closure barrier = base::BarrierClosure(
256 usb_devices.size(), base::Bind(&RespondOnFileThread,
257 callback,
258 devices,
259 caller_message_loop_proxy));
260
261 for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end();
262 ++it) {
263 const UsbConfigDescriptor& config = (*it)->GetConfiguration();
264
265 bool has_android_interface = false;
266 for (size_t j = 0; j < config.interfaces.size(); ++j) {
267 if (!IsAndroidInterface(config.interfaces[j])) {
268 continue;
269 }
270
271 // Request permission on Chrome OS.
272 #if defined(OS_CHROMEOS)
273 (*it)->RequestUsbAccess(j, base::Bind(&OpenAndroidDeviceOnFileThread,
274 devices, rsa_key, barrier, *it, j));
275 #else
276 OpenAndroidDeviceOnFileThread(devices, rsa_key, barrier, *it, j, true);
277 #endif // defined(OS_CHROMEOS)
278
279 has_android_interface = true;
280 break;
281 }
282 if (!has_android_interface)
283 barrier.Run();
284 }
285 }
286
287 // static
CountDevices(const base::Callback<void (int)> & callback)288 void AndroidUsbDevice::CountDevices(
289 const base::Callback<void(int)>& callback) {
290 BrowserThread::PostTaskAndReplyWithResult(
291 BrowserThread::FILE,
292 FROM_HERE,
293 base::Bind(&CountOnFileThread),
294 callback);
295 }
296
297 // static
Enumerate(crypto::RSAPrivateKey * rsa_key,const AndroidUsbDevicesCallback & callback)298 void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key,
299 const AndroidUsbDevicesCallback& callback) {
300
301 // Collect devices with closed handles.
302 for (std::vector<AndroidUsbDevice*>::iterator it = g_devices.Get().begin();
303 it != g_devices.Get().end(); ++it) {
304 if ((*it)->usb_handle_.get()) {
305 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
306 base::Bind(&AndroidUsbDevice::TerminateIfReleased, *it,
307 (*it)->usb_handle_));
308 }
309 }
310
311 // Then look for the new devices.
312 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
313 base::Bind(&EnumerateOnFileThread, rsa_key, callback,
314 base::MessageLoopProxy::current()));
315 }
316
AndroidUsbDevice(crypto::RSAPrivateKey * rsa_key,scoped_refptr<UsbDeviceHandle> usb_device,const std::string & serial,int inbound_address,int outbound_address,int zero_mask,int interface_id)317 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key,
318 scoped_refptr<UsbDeviceHandle> usb_device,
319 const std::string& serial,
320 int inbound_address,
321 int outbound_address,
322 int zero_mask,
323 int interface_id)
324 : message_loop_(NULL),
325 rsa_key_(rsa_key->Copy()),
326 usb_handle_(usb_device),
327 serial_(serial),
328 inbound_address_(inbound_address),
329 outbound_address_(outbound_address),
330 zero_mask_(zero_mask),
331 interface_id_(interface_id),
332 is_connected_(false),
333 signature_sent_(false),
334 last_socket_id_(256),
335 weak_factory_(this) {
336 }
337
InitOnCallerThread()338 void AndroidUsbDevice::InitOnCallerThread() {
339 if (message_loop_)
340 return;
341 message_loop_ = base::MessageLoop::current();
342 Queue(new AdbMessage(AdbMessage::kCommandCNXN, kVersion, kMaxPayload,
343 kHostConnectMessage));
344 ReadHeader();
345 }
346
CreateSocket(const std::string & command)347 net::StreamSocket* AndroidUsbDevice::CreateSocket(const std::string& command) {
348 if (!usb_handle_.get())
349 return NULL;
350
351 uint32 socket_id = ++last_socket_id_;
352 sockets_[socket_id] = new AndroidUsbSocket(this, socket_id, command,
353 base::Bind(&AndroidUsbDevice::SocketDeleted, this));
354 return sockets_[socket_id];
355 }
356
Send(uint32 command,uint32 arg0,uint32 arg1,const std::string & body)357 void AndroidUsbDevice::Send(uint32 command,
358 uint32 arg0,
359 uint32 arg1,
360 const std::string& body) {
361 scoped_refptr<AdbMessage> m = new AdbMessage(command, arg0, arg1, body);
362 // Delay open request if not yet connected.
363 if (!is_connected_) {
364 pending_messages_.push_back(m);
365 return;
366 }
367 Queue(m);
368 }
369
~AndroidUsbDevice()370 AndroidUsbDevice::~AndroidUsbDevice() {
371 DCHECK(message_loop_ == base::MessageLoop::current());
372 Terminate();
373 }
374
Queue(scoped_refptr<AdbMessage> message)375 void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) {
376 DCHECK(message_loop_ == base::MessageLoop::current());
377
378 // Queue header.
379 std::vector<uint32> header;
380 header.push_back(message->command);
381 header.push_back(message->arg0);
382 header.push_back(message->arg1);
383 bool append_zero = true;
384 if (message->body.empty())
385 append_zero = false;
386 if (message->command == AdbMessage::kCommandAUTH &&
387 message->arg0 == AdbMessage::kAuthSignature)
388 append_zero = false;
389 if (message->command == AdbMessage::kCommandWRTE)
390 append_zero = false;
391
392 size_t body_length = message->body.length() + (append_zero ? 1 : 0);
393 header.push_back(body_length);
394 header.push_back(Checksum(message->body));
395 header.push_back(message->command ^ 0xffffffff);
396 scoped_refptr<net::IOBufferWithSize> header_buffer =
397 new net::IOBufferWithSize(kHeaderSize);
398 memcpy(header_buffer.get()->data(), &header[0], kHeaderSize);
399 outgoing_queue_.push(header_buffer);
400
401 // Queue body.
402 if (!message->body.empty()) {
403 scoped_refptr<net::IOBufferWithSize> body_buffer =
404 new net::IOBufferWithSize(body_length);
405 memcpy(body_buffer->data(), message->body.data(), message->body.length());
406 if (append_zero)
407 body_buffer->data()[body_length - 1] = 0;
408 outgoing_queue_.push(body_buffer);
409 if (zero_mask_ && (body_length & zero_mask_) == 0) {
410 // Send a zero length packet.
411 outgoing_queue_.push(new net::IOBufferWithSize(0));
412 }
413 }
414 ProcessOutgoing();
415 }
416
ProcessOutgoing()417 void AndroidUsbDevice::ProcessOutgoing() {
418 DCHECK(message_loop_ == base::MessageLoop::current());
419
420 if (outgoing_queue_.empty() || !usb_handle_.get())
421 return;
422
423 BulkMessage message = outgoing_queue_.front();
424 outgoing_queue_.pop();
425 DumpMessage(true, message->data(), message->size());
426 usb_handle_->BulkTransfer(device::USB_DIRECTION_OUTBOUND,
427 outbound_address_,
428 message.get(),
429 message->size(),
430 kUsbTimeout,
431 base::Bind(&AndroidUsbDevice::OutgoingMessageSent,
432 weak_factory_.GetWeakPtr()));
433 }
434
OutgoingMessageSent(UsbTransferStatus status,scoped_refptr<net::IOBuffer> buffer,size_t result)435 void AndroidUsbDevice::OutgoingMessageSent(UsbTransferStatus status,
436 scoped_refptr<net::IOBuffer> buffer,
437 size_t result) {
438 DCHECK(message_loop_ == base::MessageLoop::current());
439
440 if (status != device::USB_TRANSFER_COMPLETED)
441 return;
442 message_loop_->PostTask(FROM_HERE,
443 base::Bind(&AndroidUsbDevice::ProcessOutgoing, this));
444 }
445
ReadHeader()446 void AndroidUsbDevice::ReadHeader() {
447 DCHECK(message_loop_ == base::MessageLoop::current());
448
449 if (!usb_handle_.get())
450 return;
451 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kHeaderSize);
452 usb_handle_->BulkTransfer(
453 device::USB_DIRECTION_INBOUND,
454 inbound_address_,
455 buffer.get(),
456 kHeaderSize,
457 kUsbTimeout,
458 base::Bind(&AndroidUsbDevice::ParseHeader, weak_factory_.GetWeakPtr()));
459 }
460
ParseHeader(UsbTransferStatus status,scoped_refptr<net::IOBuffer> buffer,size_t result)461 void AndroidUsbDevice::ParseHeader(UsbTransferStatus status,
462 scoped_refptr<net::IOBuffer> buffer,
463 size_t result) {
464 DCHECK(message_loop_ == base::MessageLoop::current());
465
466 if (status == device::USB_TRANSFER_TIMEOUT) {
467 message_loop_->PostTask(FROM_HERE,
468 base::Bind(&AndroidUsbDevice::ReadHeader, this));
469 return;
470 }
471
472 if (status != device::USB_TRANSFER_COMPLETED || result != kHeaderSize) {
473 TransferError(status);
474 return;
475 }
476
477 DumpMessage(false, buffer->data(), result);
478 std::vector<uint32> header(6);
479 memcpy(&header[0], buffer->data(), result);
480 scoped_refptr<AdbMessage> message =
481 new AdbMessage(header[0], header[1], header[2], "");
482 uint32 data_length = header[3];
483 uint32 data_check = header[4];
484 uint32 magic = header[5];
485 if ((message->command ^ 0xffffffff) != magic) {
486 TransferError(device::USB_TRANSFER_ERROR);
487 return;
488 }
489
490 if (data_length == 0) {
491 message_loop_->PostTask(FROM_HERE,
492 base::Bind(&AndroidUsbDevice::HandleIncoming, this,
493 message));
494 return;
495 }
496
497 message_loop_->PostTask(FROM_HERE,
498 base::Bind(&AndroidUsbDevice::ReadBody, this,
499 message, data_length, data_check));
500 }
501
ReadBody(scoped_refptr<AdbMessage> message,uint32 data_length,uint32 data_check)502 void AndroidUsbDevice::ReadBody(scoped_refptr<AdbMessage> message,
503 uint32 data_length,
504 uint32 data_check) {
505 DCHECK(message_loop_ == base::MessageLoop::current());
506
507 if (!usb_handle_.get())
508 return;
509 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_length);
510 usb_handle_->BulkTransfer(device::USB_DIRECTION_INBOUND,
511 inbound_address_,
512 buffer.get(),
513 data_length,
514 kUsbTimeout,
515 base::Bind(&AndroidUsbDevice::ParseBody,
516 weak_factory_.GetWeakPtr(),
517 message,
518 data_length,
519 data_check));
520 }
521
ParseBody(scoped_refptr<AdbMessage> message,uint32 data_length,uint32 data_check,UsbTransferStatus status,scoped_refptr<net::IOBuffer> buffer,size_t result)522 void AndroidUsbDevice::ParseBody(scoped_refptr<AdbMessage> message,
523 uint32 data_length,
524 uint32 data_check,
525 UsbTransferStatus status,
526 scoped_refptr<net::IOBuffer> buffer,
527 size_t result) {
528 DCHECK(message_loop_ == base::MessageLoop::current());
529
530 if (status == device::USB_TRANSFER_TIMEOUT) {
531 message_loop_->PostTask(FROM_HERE,
532 base::Bind(&AndroidUsbDevice::ReadBody, this,
533 message, data_length, data_check));
534 return;
535 }
536
537 if (status != device::USB_TRANSFER_COMPLETED ||
538 static_cast<uint32>(result) != data_length) {
539 TransferError(status);
540 return;
541 }
542
543 DumpMessage(false, buffer->data(), data_length);
544 message->body = std::string(buffer->data(), result);
545 if (Checksum(message->body) != data_check) {
546 TransferError(device::USB_TRANSFER_ERROR);
547 return;
548 }
549
550 message_loop_->PostTask(FROM_HERE,
551 base::Bind(&AndroidUsbDevice::HandleIncoming, this,
552 message));
553 }
554
HandleIncoming(scoped_refptr<AdbMessage> message)555 void AndroidUsbDevice::HandleIncoming(scoped_refptr<AdbMessage> message) {
556 DCHECK(message_loop_ == base::MessageLoop::current());
557
558 switch (message->command) {
559 case AdbMessage::kCommandAUTH:
560 {
561 DCHECK_EQ(message->arg0, static_cast<uint32>(AdbMessage::kAuthToken));
562 if (signature_sent_) {
563 Queue(new AdbMessage(AdbMessage::kCommandAUTH,
564 AdbMessage::kAuthRSAPublicKey, 0,
565 AndroidRSAPublicKey(rsa_key_.get())));
566 } else {
567 signature_sent_ = true;
568 std::string signature = AndroidRSASign(rsa_key_.get(), message->body);
569 if (!signature.empty()) {
570 Queue(new AdbMessage(AdbMessage::kCommandAUTH,
571 AdbMessage::kAuthSignature, 0,
572 signature));
573 } else {
574 Queue(new AdbMessage(AdbMessage::kCommandAUTH,
575 AdbMessage::kAuthRSAPublicKey, 0,
576 AndroidRSAPublicKey(rsa_key_.get())));
577 }
578 }
579 }
580 break;
581 case AdbMessage::kCommandCNXN:
582 {
583 is_connected_ = true;
584 PendingMessages pending;
585 pending.swap(pending_messages_);
586 for (PendingMessages::iterator it = pending.begin();
587 it != pending.end(); ++it) {
588 Queue(*it);
589 }
590 }
591 break;
592 case AdbMessage::kCommandOKAY:
593 case AdbMessage::kCommandWRTE:
594 case AdbMessage::kCommandCLSE:
595 {
596 AndroidUsbSockets::iterator it = sockets_.find(message->arg1);
597 if (it != sockets_.end())
598 it->second->HandleIncoming(message);
599 }
600 break;
601 default:
602 break;
603 }
604 ReadHeader();
605 }
606
TransferError(UsbTransferStatus status)607 void AndroidUsbDevice::TransferError(UsbTransferStatus status) {
608 DCHECK(message_loop_ == base::MessageLoop::current());
609
610 message_loop_->PostTask(FROM_HERE,
611 base::Bind(&AndroidUsbDevice::Terminate, this));
612 }
613
TerminateIfReleased(scoped_refptr<UsbDeviceHandle> usb_handle)614 void AndroidUsbDevice::TerminateIfReleased(
615 scoped_refptr<UsbDeviceHandle> usb_handle) {
616 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
617 if (usb_handle->GetDevice().get())
618 return;
619 message_loop_->PostTask(FROM_HERE,
620 base::Bind(&AndroidUsbDevice::Terminate, this));
621 }
622
Terminate()623 void AndroidUsbDevice::Terminate() {
624 DCHECK(message_loop_ == base::MessageLoop::current());
625
626 std::vector<AndroidUsbDevice*>::iterator it =
627 std::find(g_devices.Get().begin(), g_devices.Get().end(), this);
628 if (it != g_devices.Get().end())
629 g_devices.Get().erase(it);
630
631 if (!usb_handle_.get())
632 return;
633
634 // Make sure we zero-out handle so that closing connections did not open
635 // new connections.
636 scoped_refptr<UsbDeviceHandle> usb_handle = usb_handle_;
637 usb_handle_ = NULL;
638
639 // Iterate over copy.
640 AndroidUsbSockets sockets(sockets_);
641 for (AndroidUsbSockets::iterator it = sockets.begin();
642 it != sockets.end(); ++it) {
643 it->second->Terminated(true);
644 }
645 DCHECK(sockets_.empty());
646
647 BrowserThread::PostTask(
648 BrowserThread::FILE, FROM_HERE,
649 base::Bind(&ReleaseInterface, usb_handle, interface_id_));
650 }
651
SocketDeleted(uint32 socket_id)652 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) {
653 DCHECK(message_loop_ == base::MessageLoop::current());
654
655 sockets_.erase(socket_id);
656 }
657