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.
7 #include "base/containers/scoped_ptr_hash_map.h"
8 #include "base/location.h"
9 #include "base/single_thread_task_runner.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "chrome/browser/devtools/device/adb/mock_adb_server.h"
13 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
14 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
15 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/test/base/in_process_browser_test.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/test/test_utils.h"
20 #include "device/usb/usb_descriptors.h"
21 #include "device/usb/usb_device.h"
22 #include "device/usb/usb_device_handle.h"
23 #include "device/usb/usb_service.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using content::BrowserThread
;
27 using device::UsbConfigDescriptor
;
28 using device::UsbDevice
;
29 using device::UsbDeviceHandle
;
30 using device::UsbEndpointDescriptor
;
31 using device::UsbEndpointDirection
;
32 using device::UsbInterfaceDescriptor
;
33 using device::UsbService
;
34 using device::UsbSynchronizationType
;
35 using device::UsbTransferType
;
36 using device::UsbUsageType
;
40 struct NoConfigTraits
{
41 static const int kClass
= 0xff;
42 static const int kSubclass
= 0x42;
43 static const int kProtocol
= 0x1;
44 static const bool kBreaks
= false;
45 static const bool kConfigured
= false;
48 struct AndroidTraits
{
49 static const int kClass
= 0xff;
50 static const int kSubclass
= 0x42;
51 static const int kProtocol
= 0x1;
52 static const bool kBreaks
= false;
53 static const bool kConfigured
= true;
56 struct NonAndroidTraits
{
57 static const int kClass
= 0xf0;
58 static const int kSubclass
= 0x42;
59 static const int kProtocol
= 0x2;
60 static const bool kBreaks
= false;
61 static const bool kConfigured
= true;
64 struct BreakingAndroidTraits
{
65 static const int kClass
= 0xff;
66 static const int kSubclass
= 0x42;
67 static const int kProtocol
= 0x1;
68 static const bool kBreaks
= true;
69 static const bool kConfigured
= true;
72 const uint32 kMaxPayload
= 4096;
73 const uint32 kVersion
= 0x01000000;
75 const char kDeviceManufacturer
[] = "Test Manufacturer";
76 const char kDeviceModel
[] = "Nexus 6";
77 const char kDeviceSerial
[] = "01498B321301A00A";
82 class MockLocalSocket
: public MockAndroidConnection::Delegate
{
84 using Callback
= base::Callback
<void(int command
,
85 const std::string
& message
)>;
87 MockLocalSocket(const Callback
& callback
,
88 const std::string
& serial
,
89 const std::string
& command
)
90 : callback_(callback
),
91 connection_(new MockAndroidConnection(this, serial
, command
)) {
94 void Receive(const std::string
& data
) {
95 connection_
->Receive(data
);
99 void SendSuccess(const std::string
& message
) override
{
100 if (!message
.empty())
101 callback_
.Run(AdbMessage::kCommandWRTE
, message
);
104 void SendRaw(const std::string
& message
) override
{
105 callback_
.Run(AdbMessage::kCommandWRTE
, message
);
108 void Close() override
{
109 callback_
.Run(AdbMessage::kCommandCLSE
, std::string());
113 scoped_ptr
<MockAndroidConnection
> connection_
;
117 class MockUsbDeviceHandle
: public UsbDeviceHandle
{
119 explicit MockUsbDeviceHandle(MockUsbDevice
<T
>* device
)
121 remaining_body_length_(0),
122 last_local_socket_(0),
126 scoped_refptr
<UsbDevice
> GetDevice() const override
{
130 void Close() override
{ device_
= nullptr; }
132 void SetConfiguration(int configuration_value
,
133 const ResultCallback
& callback
) override
{
137 void ClaimInterface(int interface_number
,
138 const ResultCallback
& callback
) override
{
139 bool success
= false;
140 if (device_
->claimed_interfaces_
.find(interface_number
) ==
141 device_
->claimed_interfaces_
.end()) {
142 device_
->claimed_interfaces_
.insert(interface_number
);
146 base::ThreadTaskRunnerHandle::Get()->PostTask(
147 FROM_HERE
, base::Bind(callback
, success
));
150 bool ReleaseInterface(int interface_number
) override
{
151 if (device_
->claimed_interfaces_
.find(interface_number
) ==
152 device_
->claimed_interfaces_
.end())
155 device_
->claimed_interfaces_
.erase(interface_number
);
159 void SetInterfaceAlternateSetting(int interface_number
,
160 int alternate_setting
,
161 const ResultCallback
& callback
) override
{
165 void ResetDevice(const ResultCallback
& callback
) override
{
169 void ClearHalt(uint8 endpoint
, const ResultCallback
& callback
) override
{
173 // Async IO. Can be called on any thread.
174 void ControlTransfer(UsbEndpointDirection direction
,
175 TransferRequestType request_type
,
176 TransferRecipient recipient
,
180 scoped_refptr
<net::IOBuffer
> buffer
,
182 unsigned int timeout
,
183 const TransferCallback
& callback
) override
{}
185 void BulkTransfer(UsbEndpointDirection direction
,
187 scoped_refptr
<net::IOBuffer
> buffer
,
189 unsigned int timeout
,
190 const TransferCallback
& callback
) override
{
191 if (direction
== device::USB_DIRECTION_OUTBOUND
) {
192 if (remaining_body_length_
== 0) {
193 std::vector
<uint32
> header(6);
194 memcpy(&header
[0], buffer
->data(), length
);
195 current_message_
.reset(
196 new AdbMessage(header
[0], header
[1], header
[2], std::string()));
197 remaining_body_length_
= header
[3];
198 uint32 magic
= header
[5];
199 if ((current_message_
->command
^ 0xffffffff) != magic
) {
200 DCHECK(false) << "Header checksum error";
204 DCHECK(current_message_
.get());
205 current_message_
->body
+= std::string(buffer
->data(), length
);
206 remaining_body_length_
-= length
;
209 if (remaining_body_length_
== 0) {
213 device::UsbTransferStatus status
=
214 broken_
? device::USB_TRANSFER_ERROR
: device::USB_TRANSFER_COMPLETED
;
215 base::ThreadTaskRunnerHandle::Get()->PostTask(
216 FROM_HERE
, base::Bind(callback
, status
, nullptr, 0));
218 } else if (direction
== device::USB_DIRECTION_INBOUND
) {
219 queries_
.push(Query(callback
, buffer
, length
));
225 void append(D data
) {
226 std::copy(reinterpret_cast<char*>(&data
),
227 (reinterpret_cast<char*>(&data
)) + sizeof(D
),
228 std::back_inserter(output_buffer_
));
231 // Copied from AndroidUsbDevice::Checksum
232 uint32
Checksum(const std::string
& data
) {
233 unsigned char* x
= (unsigned char*)data
.data();
234 int count
= data
.length();
241 void ProcessIncoming() {
242 DCHECK(current_message_
.get());
243 switch (current_message_
->command
) {
244 case AdbMessage::kCommandCNXN
: {
245 WriteResponse(kVersion
,
247 AdbMessage::kCommandCNXN
,
248 "device::ro.product.name=SampleProduct;ro.product.model="
249 "SampleModel;ro.product.device=SampleDevice;");
252 case AdbMessage::kCommandCLSE
: {
254 current_message_
->arg0
,
255 AdbMessage::kCommandCLSE
,
257 local_sockets_
.erase(current_message_
->arg0
);
260 case AdbMessage::kCommandWRTE
: {
265 auto it
= local_sockets_
.find(current_message_
->arg0
);
266 if (it
== local_sockets_
.end())
269 DCHECK(current_message_
->arg1
!= 0);
270 WriteResponse(current_message_
->arg1
,
271 current_message_
->arg0
,
272 AdbMessage::kCommandOKAY
,
274 it
->second
->Receive(current_message_
->body
);
277 case AdbMessage::kCommandOPEN
: {
278 DCHECK(current_message_
->arg1
== 0);
279 DCHECK(current_message_
->arg0
!= 0);
280 std::string response
;
281 WriteResponse(++last_local_socket_
,
282 current_message_
->arg0
,
283 AdbMessage::kCommandOKAY
,
286 current_message_
->arg0
,
287 make_scoped_ptr(new MockLocalSocket(
288 base::Bind(&MockUsbDeviceHandle::WriteResponse
,
289 base::Unretained(this),
291 current_message_
->arg0
),
293 current_message_
->body
.substr(
294 0, current_message_
->body
.size() - 1))));
304 void WriteResponse(int arg0
, int arg1
, int command
, const std::string
& body
) {
308 bool add_zero
= !body
.empty() && (command
!= AdbMessage::kCommandWRTE
);
309 append(static_cast<uint32
>(body
.size() + (add_zero
? 1 : 0)));
310 append(Checksum(body
));
311 append(command
^ 0xffffffff);
312 std::copy(body
.begin(), body
.end(), std::back_inserter(output_buffer_
));
314 output_buffer_
.push_back(0);
319 void ProcessQueries() {
320 if (!queries_
.size())
322 Query query
= queries_
.front();
324 base::ThreadTaskRunnerHandle::Get()->PostTask(
326 base::Bind(query
.callback
, device::USB_TRANSFER_ERROR
, nullptr, 0));
329 if (query
.size
> output_buffer_
.size())
333 std::copy(output_buffer_
.begin(),
334 output_buffer_
.begin() + query
.size
,
335 query
.buffer
->data());
336 output_buffer_
.erase(output_buffer_
.begin(),
337 output_buffer_
.begin() + query
.size
);
338 base::ThreadTaskRunnerHandle::Get()->PostTask(
339 FROM_HERE
, base::Bind(query
.callback
, device::USB_TRANSFER_COMPLETED
,
340 query
.buffer
, query
.size
));
343 void InterruptTransfer(UsbEndpointDirection direction
,
345 scoped_refptr
<net::IOBuffer
> buffer
,
347 unsigned int timeout
,
348 const TransferCallback
& callback
) override
{}
350 void IsochronousTransfer(UsbEndpointDirection direction
,
352 scoped_refptr
<net::IOBuffer
> buffer
,
354 unsigned int packets
,
355 unsigned int packet_length
,
356 unsigned int timeout
,
357 const TransferCallback
& callback
) override
{}
360 virtual ~MockUsbDeviceHandle() {}
363 TransferCallback callback
;
364 scoped_refptr
<net::IOBuffer
> buffer
;
367 Query(TransferCallback callback
,
368 scoped_refptr
<net::IOBuffer
> buffer
,
370 : callback(callback
), buffer(buffer
), size(size
) {}
373 scoped_refptr
<MockUsbDevice
<T
> > device_
;
374 uint32 remaining_body_length_
;
375 scoped_ptr
<AdbMessage
> current_message_
;
376 std::vector
<char> output_buffer_
;
377 std::queue
<Query
> queries_
;
378 base::ScopedPtrHashMap
<int, scoped_ptr
<MockLocalSocket
>> local_sockets_
;
379 int last_local_socket_
;
384 class MockUsbDevice
: public UsbDevice
{
389 base::UTF8ToUTF16(kDeviceManufacturer
),
390 base::UTF8ToUTF16(kDeviceModel
),
391 base::UTF8ToUTF16(kDeviceSerial
)) {
392 UsbEndpointDescriptor bulk_in
;
393 bulk_in
.address
= 0x81;
394 bulk_in
.direction
= device::USB_DIRECTION_INBOUND
;
395 bulk_in
.maximum_packet_size
= 512;
396 bulk_in
.transfer_type
= device::USB_TRANSFER_BULK
;
398 UsbEndpointDescriptor bulk_out
;
399 bulk_out
.address
= 0x01;
400 bulk_out
.direction
= device::USB_DIRECTION_OUTBOUND
;
401 bulk_out
.maximum_packet_size
= 512;
402 bulk_out
.transfer_type
= device::USB_TRANSFER_BULK
;
404 UsbInterfaceDescriptor interface_desc
;
405 interface_desc
.interface_number
= 0;
406 interface_desc
.alternate_setting
= 0;
407 interface_desc
.interface_class
= T::kClass
;
408 interface_desc
.interface_subclass
= T::kSubclass
;
409 interface_desc
.interface_protocol
= T::kProtocol
;
410 interface_desc
.endpoints
.push_back(bulk_in
);
411 interface_desc
.endpoints
.push_back(bulk_out
);
413 config_desc_
.interfaces
.push_back(interface_desc
);
416 void Open(const OpenCallback
& callback
) override
{
417 base::ThreadTaskRunnerHandle::Get()->PostTask(
418 FROM_HERE
, base::Bind(callback
, make_scoped_refptr(
419 new MockUsbDeviceHandle
<T
>(this))));
422 const UsbConfigDescriptor
* GetActiveConfiguration() override
{
423 return T::kConfigured
? &config_desc_
: nullptr;
426 bool Close(scoped_refptr
<UsbDeviceHandle
> handle
) override
{
430 std::set
<int> claimed_interfaces_
;
433 virtual ~MockUsbDevice() {}
436 UsbConfigDescriptor config_desc_
;
439 class MockUsbService
: public UsbService
{
442 devices_
.push_back(new MockUsbDevice
<AndroidTraits
>());
445 scoped_refptr
<UsbDevice
> GetDevice(const std::string
& guid
) override
{
450 void GetDevices(const GetDevicesCallback
& callback
) override
{
451 callback
.Run(devices_
);
454 std::vector
<scoped_refptr
<UsbDevice
> > devices_
;
457 class MockBreakingUsbService
: public MockUsbService
{
459 MockBreakingUsbService() {
461 devices_
.push_back(new MockUsbDevice
<BreakingAndroidTraits
>());
465 class MockNoConfigUsbService
: public MockUsbService
{
467 MockNoConfigUsbService() {
468 devices_
.push_back(new MockUsbDevice
<NoConfigTraits
>());
472 class MockUsbServiceForCheckingTraits
: public MockUsbService
{
474 MockUsbServiceForCheckingTraits() : step_(0) {}
476 void GetDevices(const GetDevicesCallback
& callback
) override
{
477 std::vector
<scoped_refptr
<UsbDevice
>> devices
;
478 // This switch should be kept in sync with
479 // AndroidUsbBrowserTest::DeviceCountChanged.
486 devices
.push_back(new MockUsbDevice
<AndroidTraits
>());
489 // Android and non-android device.
490 devices
.push_back(new MockUsbDevice
<AndroidTraits
>());
491 devices
.push_back(new MockUsbDevice
<NonAndroidTraits
>());
494 // Non-android device.
495 devices
.push_back(new MockUsbDevice
<NonAndroidTraits
>());
499 callback
.Run(devices
);
506 class DevToolsAndroidBridgeWarmUp
507 : public DevToolsAndroidBridge::DeviceCountListener
{
509 DevToolsAndroidBridgeWarmUp(base::Closure closure
,
510 DevToolsAndroidBridge
* adb_bridge
)
511 : closure_(closure
), adb_bridge_(adb_bridge
) {}
513 void DeviceCountChanged(int count
) override
{
514 adb_bridge_
->RemoveDeviceCountListener(this);
518 base::Closure closure_
;
519 DevToolsAndroidBridge
* adb_bridge_
;
522 class AndroidUsbDiscoveryTest
: public InProcessBrowserTest
{
524 AndroidUsbDiscoveryTest()
525 : scheduler_invoked_(0) {
527 void SetUpOnMainThread() override
{
528 mock_usb_service_
.reset(CreateMockService());
531 DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile());
533 adb_bridge_
->set_task_scheduler_for_test(base::Bind(
534 &AndroidUsbDiscoveryTest::ScheduleDeviceCountRequest
, this));
536 scoped_refptr
<UsbDeviceProvider
> provider
=
537 new UsbDeviceProvider(browser()->profile());
539 AndroidDeviceManager::DeviceProviders providers
;
540 providers
.push_back(provider
);
541 adb_bridge_
->set_device_providers_for_test(providers
);
542 runner_
= new content::MessageLoopRunner
;
545 void ScheduleDeviceCountRequest(const base::Closure
& request
) {
546 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
547 scheduler_invoked_
++;
548 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, request
);
551 virtual MockUsbService
* CreateMockService() { return new MockUsbService(); }
553 scoped_refptr
<content::MessageLoopRunner
> runner_
;
554 scoped_ptr
<MockUsbService
> mock_usb_service_
;
555 DevToolsAndroidBridge
* adb_bridge_
;
556 int scheduler_invoked_
;
559 class AndroidUsbCountTest
: public AndroidUsbDiscoveryTest
{
561 void SetUpOnMainThread() override
{
562 AndroidUsbDiscoveryTest::SetUpOnMainThread();
563 DevToolsAndroidBridgeWarmUp
warmup(runner_
->QuitClosure(), adb_bridge_
);
564 adb_bridge_
->AddDeviceCountListener(&warmup
);
566 runner_
= new content::MessageLoopRunner
;
570 class AndroidUsbTraitsTest
: public AndroidUsbDiscoveryTest
{
572 MockUsbService
* CreateMockService() override
{
573 return new MockUsbServiceForCheckingTraits();
577 class AndroidBreakingUsbTest
: public AndroidUsbDiscoveryTest
{
579 MockUsbService
* CreateMockService() override
{
580 return new MockBreakingUsbService();
584 class AndroidNoConfigUsbTest
: public AndroidUsbDiscoveryTest
{
586 MockUsbService
* CreateMockService() override
{
587 return new MockNoConfigUsbService();
591 class MockListListener
: public DevToolsAndroidBridge::DeviceListListener
{
593 MockListListener(DevToolsAndroidBridge
* adb_bridge
,
594 const base::Closure
& callback
)
595 : adb_bridge_(adb_bridge
),
596 callback_(callback
) {
599 void DeviceListChanged(
600 const DevToolsAndroidBridge::RemoteDevices
& devices
) override
{
601 if (devices
.size() > 0) {
602 for (const auto& device
: devices
) {
603 if (device
->is_connected()) {
604 ASSERT_EQ(kDeviceModel
, device
->model());
605 ASSERT_EQ(kDeviceSerial
, device
->serial());
606 adb_bridge_
->RemoveDeviceListListener(this);
614 DevToolsAndroidBridge
* adb_bridge_
;
615 base::Closure callback_
;
618 class MockCountListener
: public DevToolsAndroidBridge::DeviceCountListener
{
620 explicit MockCountListener(DevToolsAndroidBridge
* adb_bridge
)
621 : adb_bridge_(adb_bridge
), invoked_(0) {}
623 void DeviceCountChanged(int count
) override
{
625 adb_bridge_
->RemoveDeviceCountListener(this);
629 void Shutdown() { base::MessageLoop::current()->Quit(); }
631 DevToolsAndroidBridge
* adb_bridge_
;
635 class MockCountListenerWithReAdd
: public MockCountListener
{
637 explicit MockCountListenerWithReAdd(
638 DevToolsAndroidBridge
* adb_bridge
)
639 : MockCountListener(adb_bridge
),
643 void DeviceCountChanged(int count
) override
{
645 adb_bridge_
->RemoveDeviceCountListener(this);
646 if (readd_count_
> 0) {
648 adb_bridge_
->AddDeviceCountListener(this);
649 adb_bridge_
->RemoveDeviceCountListener(this);
650 adb_bridge_
->AddDeviceCountListener(this);
659 class MockCountListenerWithReAddWhileQueued
: public MockCountListener
{
661 MockCountListenerWithReAddWhileQueued(
662 DevToolsAndroidBridge
* adb_bridge
)
663 : MockCountListener(adb_bridge
),
667 void DeviceCountChanged(int count
) override
{
671 base::ThreadTaskRunnerHandle::Get()->PostTask(
672 FROM_HERE
, base::Bind(&MockCountListenerWithReAddWhileQueued::ReAdd
,
673 base::Unretained(this)));
675 adb_bridge_
->RemoveDeviceCountListener(this);
681 adb_bridge_
->RemoveDeviceCountListener(this);
682 adb_bridge_
->AddDeviceCountListener(this);
688 class MockCountListenerForCheckingTraits
: public MockCountListener
{
690 MockCountListenerForCheckingTraits(
691 DevToolsAndroidBridge
* adb_bridge
)
692 : MockCountListener(adb_bridge
),
695 void DeviceCountChanged(int count
) override
{
698 // Check for 0 devices when no devices present.
702 // Check for 1 device when only android device present.
706 // Check for 1 device when android and non-android devices present.
710 // Check for 0 devices when only non-android devices present.
712 adb_bridge_
->RemoveDeviceCountListener(this);
716 EXPECT_TRUE(false) << "Unknown step " << step_
;
726 IN_PROC_BROWSER_TEST_F(AndroidUsbDiscoveryTest
, TestDeviceDiscovery
) {
727 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
728 adb_bridge_
->AddDeviceListListener(&listener
);
732 IN_PROC_BROWSER_TEST_F(AndroidBreakingUsbTest
, TestDeviceBreaking
) {
733 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
734 adb_bridge_
->AddDeviceListListener(&listener
);
738 IN_PROC_BROWSER_TEST_F(AndroidNoConfigUsbTest
, TestDeviceNoConfig
) {
739 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
740 adb_bridge_
->AddDeviceListListener(&listener
);
744 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
745 TestNoMultipleCallsRemoveInCallback
) {
746 MockCountListener
listener(adb_bridge_
);
747 adb_bridge_
->AddDeviceCountListener(&listener
);
749 EXPECT_EQ(1, listener
.invoked_
);
750 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
751 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
754 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
755 TestNoMultipleCallsRemoveAddInCallback
) {
756 MockCountListenerWithReAdd
listener(adb_bridge_
);
757 adb_bridge_
->AddDeviceCountListener(&listener
);
759 EXPECT_EQ(3, listener
.invoked_
);
760 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
761 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
764 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
765 TestNoMultipleCallsRemoveAddOnStart
) {
766 MockCountListener
listener(adb_bridge_
);
767 adb_bridge_
->AddDeviceCountListener(&listener
);
768 adb_bridge_
->RemoveDeviceCountListener(&listener
);
769 adb_bridge_
->AddDeviceCountListener(&listener
);
771 EXPECT_EQ(1, listener
.invoked_
);
772 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
773 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
776 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
777 TestNoMultipleCallsRemoveAddWhileQueued
) {
778 MockCountListenerWithReAddWhileQueued
listener(adb_bridge_
);
779 adb_bridge_
->AddDeviceCountListener(&listener
);
781 EXPECT_EQ(2, listener
.invoked_
);
782 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
783 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
786 IN_PROC_BROWSER_TEST_F(AndroidUsbTraitsTest
, TestDeviceCounting
) {
787 MockCountListenerForCheckingTraits
listener(adb_bridge_
);
788 adb_bridge_
->AddDeviceCountListener(&listener
);