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