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