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