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 // Async IO. Can be called on any thread.
170 void ControlTransfer(UsbEndpointDirection direction
,
171 TransferRequestType request_type
,
172 TransferRecipient recipient
,
176 scoped_refptr
<net::IOBuffer
> buffer
,
178 unsigned int timeout
,
179 const TransferCallback
& callback
) override
{}
181 void BulkTransfer(UsbEndpointDirection direction
,
183 scoped_refptr
<net::IOBuffer
> buffer
,
185 unsigned int timeout
,
186 const TransferCallback
& callback
) override
{
187 if (direction
== device::USB_DIRECTION_OUTBOUND
) {
188 if (remaining_body_length_
== 0) {
189 std::vector
<uint32
> header(6);
190 memcpy(&header
[0], buffer
->data(), length
);
191 current_message_
.reset(
192 new AdbMessage(header
[0], header
[1], header
[2], std::string()));
193 remaining_body_length_
= header
[3];
194 uint32 magic
= header
[5];
195 if ((current_message_
->command
^ 0xffffffff) != magic
) {
196 DCHECK(false) << "Header checksum error";
200 DCHECK(current_message_
.get());
201 current_message_
->body
+= std::string(buffer
->data(), length
);
202 remaining_body_length_
-= length
;
205 if (remaining_body_length_
== 0) {
209 device::UsbTransferStatus status
=
210 broken_
? device::USB_TRANSFER_ERROR
: device::USB_TRANSFER_COMPLETED
;
211 base::ThreadTaskRunnerHandle::Get()->PostTask(
212 FROM_HERE
, base::Bind(callback
, status
, nullptr, 0));
214 } else if (direction
== device::USB_DIRECTION_INBOUND
) {
215 queries_
.push(Query(callback
, buffer
, length
));
221 void append(D data
) {
222 std::copy(reinterpret_cast<char*>(&data
),
223 (reinterpret_cast<char*>(&data
)) + sizeof(D
),
224 std::back_inserter(output_buffer_
));
227 // Copied from AndroidUsbDevice::Checksum
228 uint32
Checksum(const std::string
& data
) {
229 unsigned char* x
= (unsigned char*)data
.data();
230 int count
= data
.length();
237 void ProcessIncoming() {
238 DCHECK(current_message_
.get());
239 switch (current_message_
->command
) {
240 case AdbMessage::kCommandCNXN
: {
241 WriteResponse(kVersion
,
243 AdbMessage::kCommandCNXN
,
244 "device::ro.product.name=SampleProduct;ro.product.model="
245 "SampleModel;ro.product.device=SampleDevice;");
248 case AdbMessage::kCommandCLSE
: {
250 current_message_
->arg0
,
251 AdbMessage::kCommandCLSE
,
253 local_sockets_
.erase(current_message_
->arg0
);
256 case AdbMessage::kCommandWRTE
: {
261 auto it
= local_sockets_
.find(current_message_
->arg0
);
262 if (it
== local_sockets_
.end())
265 DCHECK(current_message_
->arg1
!= 0);
266 WriteResponse(current_message_
->arg1
,
267 current_message_
->arg0
,
268 AdbMessage::kCommandOKAY
,
270 it
->second
->Receive(current_message_
->body
);
273 case AdbMessage::kCommandOPEN
: {
274 DCHECK(current_message_
->arg1
== 0);
275 DCHECK(current_message_
->arg0
!= 0);
276 std::string response
;
277 WriteResponse(++last_local_socket_
,
278 current_message_
->arg0
,
279 AdbMessage::kCommandOKAY
,
282 current_message_
->arg0
,
283 make_scoped_ptr(new MockLocalSocket(
284 base::Bind(&MockUsbDeviceHandle::WriteResponse
,
285 base::Unretained(this),
287 current_message_
->arg0
),
289 current_message_
->body
.substr(
290 0, current_message_
->body
.size() - 1))));
300 void WriteResponse(int arg0
, int arg1
, int command
, const std::string
& body
) {
304 bool add_zero
= !body
.empty() && (command
!= AdbMessage::kCommandWRTE
);
305 append(static_cast<uint32
>(body
.size() + (add_zero
? 1 : 0)));
306 append(Checksum(body
));
307 append(command
^ 0xffffffff);
308 std::copy(body
.begin(), body
.end(), std::back_inserter(output_buffer_
));
310 output_buffer_
.push_back(0);
315 void ProcessQueries() {
316 if (!queries_
.size())
318 Query query
= queries_
.front();
320 base::ThreadTaskRunnerHandle::Get()->PostTask(
322 base::Bind(query
.callback
, device::USB_TRANSFER_ERROR
, nullptr, 0));
325 if (query
.size
> output_buffer_
.size())
329 std::copy(output_buffer_
.begin(),
330 output_buffer_
.begin() + query
.size
,
331 query
.buffer
->data());
332 output_buffer_
.erase(output_buffer_
.begin(),
333 output_buffer_
.begin() + query
.size
);
334 base::ThreadTaskRunnerHandle::Get()->PostTask(
335 FROM_HERE
, base::Bind(query
.callback
, device::USB_TRANSFER_COMPLETED
,
336 query
.buffer
, query
.size
));
339 void InterruptTransfer(UsbEndpointDirection direction
,
341 scoped_refptr
<net::IOBuffer
> buffer
,
343 unsigned int timeout
,
344 const TransferCallback
& callback
) override
{}
346 void IsochronousTransfer(UsbEndpointDirection direction
,
348 scoped_refptr
<net::IOBuffer
> buffer
,
350 unsigned int packets
,
351 unsigned int packet_length
,
352 unsigned int timeout
,
353 const TransferCallback
& callback
) override
{}
356 virtual ~MockUsbDeviceHandle() {}
359 TransferCallback callback
;
360 scoped_refptr
<net::IOBuffer
> buffer
;
363 Query(TransferCallback callback
,
364 scoped_refptr
<net::IOBuffer
> buffer
,
366 : callback(callback
), buffer(buffer
), size(size
) {}
369 scoped_refptr
<MockUsbDevice
<T
> > device_
;
370 uint32 remaining_body_length_
;
371 scoped_ptr
<AdbMessage
> current_message_
;
372 std::vector
<char> output_buffer_
;
373 std::queue
<Query
> queries_
;
374 base::ScopedPtrHashMap
<int, scoped_ptr
<MockLocalSocket
>> local_sockets_
;
375 int last_local_socket_
;
380 class MockUsbDevice
: public UsbDevice
{
385 base::UTF8ToUTF16(kDeviceManufacturer
),
386 base::UTF8ToUTF16(kDeviceModel
),
387 base::UTF8ToUTF16(kDeviceSerial
)) {
388 UsbEndpointDescriptor bulk_in
;
389 bulk_in
.address
= 0x81;
390 bulk_in
.direction
= device::USB_DIRECTION_INBOUND
;
391 bulk_in
.maximum_packet_size
= 512;
392 bulk_in
.transfer_type
= device::USB_TRANSFER_BULK
;
394 UsbEndpointDescriptor bulk_out
;
395 bulk_out
.address
= 0x01;
396 bulk_out
.direction
= device::USB_DIRECTION_OUTBOUND
;
397 bulk_out
.maximum_packet_size
= 512;
398 bulk_out
.transfer_type
= device::USB_TRANSFER_BULK
;
400 UsbInterfaceDescriptor interface_desc
;
401 interface_desc
.interface_number
= 0;
402 interface_desc
.alternate_setting
= 0;
403 interface_desc
.interface_class
= T::kClass
;
404 interface_desc
.interface_subclass
= T::kSubclass
;
405 interface_desc
.interface_protocol
= T::kProtocol
;
406 interface_desc
.endpoints
.push_back(bulk_in
);
407 interface_desc
.endpoints
.push_back(bulk_out
);
409 config_desc_
.interfaces
.push_back(interface_desc
);
412 void Open(const OpenCallback
& callback
) override
{
413 base::ThreadTaskRunnerHandle::Get()->PostTask(
414 FROM_HERE
, base::Bind(callback
, make_scoped_refptr(
415 new MockUsbDeviceHandle
<T
>(this))));
418 const UsbConfigDescriptor
* GetConfiguration() override
{
419 return T::kConfigured
? &config_desc_
: nullptr;
422 bool Close(scoped_refptr
<UsbDeviceHandle
> handle
) override
{
426 std::set
<int> claimed_interfaces_
;
429 virtual ~MockUsbDevice() {}
432 UsbConfigDescriptor config_desc_
;
435 class MockUsbService
: public UsbService
{
438 devices_
.push_back(new MockUsbDevice
<AndroidTraits
>());
441 scoped_refptr
<UsbDevice
> GetDevice(const std::string
& guid
) override
{
446 void GetDevices(const GetDevicesCallback
& callback
) override
{
447 callback
.Run(devices_
);
450 std::vector
<scoped_refptr
<UsbDevice
> > devices_
;
453 class MockBreakingUsbService
: public MockUsbService
{
455 MockBreakingUsbService() {
457 devices_
.push_back(new MockUsbDevice
<BreakingAndroidTraits
>());
461 class MockNoConfigUsbService
: public MockUsbService
{
463 MockNoConfigUsbService() {
464 devices_
.push_back(new MockUsbDevice
<NoConfigTraits
>());
468 class MockUsbServiceForCheckingTraits
: public MockUsbService
{
470 MockUsbServiceForCheckingTraits() : step_(0) {}
472 void GetDevices(const GetDevicesCallback
& callback
) override
{
473 std::vector
<scoped_refptr
<UsbDevice
>> devices
;
474 // This switch should be kept in sync with
475 // AndroidUsbBrowserTest::DeviceCountChanged.
482 devices
.push_back(new MockUsbDevice
<AndroidTraits
>());
485 // Android and non-android device.
486 devices
.push_back(new MockUsbDevice
<AndroidTraits
>());
487 devices
.push_back(new MockUsbDevice
<NonAndroidTraits
>());
490 // Non-android device.
491 devices
.push_back(new MockUsbDevice
<NonAndroidTraits
>());
495 callback
.Run(devices
);
502 class DevToolsAndroidBridgeWarmUp
503 : public DevToolsAndroidBridge::DeviceCountListener
{
505 DevToolsAndroidBridgeWarmUp(base::Closure closure
,
506 DevToolsAndroidBridge
* adb_bridge
)
507 : closure_(closure
), adb_bridge_(adb_bridge
) {}
509 void DeviceCountChanged(int count
) override
{
510 adb_bridge_
->RemoveDeviceCountListener(this);
514 base::Closure closure_
;
515 DevToolsAndroidBridge
* adb_bridge_
;
518 class AndroidUsbDiscoveryTest
: public InProcessBrowserTest
{
520 AndroidUsbDiscoveryTest()
521 : scheduler_invoked_(0) {
523 void SetUpOnMainThread() override
{
524 mock_usb_service_
.reset(CreateMockService());
527 DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile());
529 adb_bridge_
->set_task_scheduler_for_test(base::Bind(
530 &AndroidUsbDiscoveryTest::ScheduleDeviceCountRequest
, this));
532 scoped_refptr
<UsbDeviceProvider
> provider
=
533 new UsbDeviceProvider(browser()->profile());
535 AndroidDeviceManager::DeviceProviders providers
;
536 providers
.push_back(provider
);
537 adb_bridge_
->set_device_providers_for_test(providers
);
538 runner_
= new content::MessageLoopRunner
;
541 void ScheduleDeviceCountRequest(const base::Closure
& request
) {
542 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
543 scheduler_invoked_
++;
544 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, request
);
547 virtual MockUsbService
* CreateMockService() { return new MockUsbService(); }
549 scoped_refptr
<content::MessageLoopRunner
> runner_
;
550 scoped_ptr
<MockUsbService
> mock_usb_service_
;
551 DevToolsAndroidBridge
* adb_bridge_
;
552 int scheduler_invoked_
;
555 class AndroidUsbCountTest
: public AndroidUsbDiscoveryTest
{
557 void SetUpOnMainThread() override
{
558 AndroidUsbDiscoveryTest::SetUpOnMainThread();
559 DevToolsAndroidBridgeWarmUp
warmup(runner_
->QuitClosure(), adb_bridge_
);
560 adb_bridge_
->AddDeviceCountListener(&warmup
);
562 runner_
= new content::MessageLoopRunner
;
566 class AndroidUsbTraitsTest
: public AndroidUsbDiscoveryTest
{
568 MockUsbService
* CreateMockService() override
{
569 return new MockUsbServiceForCheckingTraits();
573 class AndroidBreakingUsbTest
: public AndroidUsbDiscoveryTest
{
575 MockUsbService
* CreateMockService() override
{
576 return new MockBreakingUsbService();
580 class AndroidNoConfigUsbTest
: public AndroidUsbDiscoveryTest
{
582 MockUsbService
* CreateMockService() override
{
583 return new MockNoConfigUsbService();
587 class MockListListener
: public DevToolsAndroidBridge::DeviceListListener
{
589 MockListListener(DevToolsAndroidBridge
* adb_bridge
,
590 const base::Closure
& callback
)
591 : adb_bridge_(adb_bridge
),
592 callback_(callback
) {
595 void DeviceListChanged(
596 const DevToolsAndroidBridge::RemoteDevices
& devices
) override
{
597 if (devices
.size() > 0) {
598 for (const auto& device
: devices
) {
599 if (device
->is_connected()) {
600 ASSERT_EQ(kDeviceModel
, device
->model());
601 ASSERT_EQ(kDeviceSerial
, device
->serial());
602 adb_bridge_
->RemoveDeviceListListener(this);
610 DevToolsAndroidBridge
* adb_bridge_
;
611 base::Closure callback_
;
614 class MockCountListener
: public DevToolsAndroidBridge::DeviceCountListener
{
616 explicit MockCountListener(DevToolsAndroidBridge
* adb_bridge
)
617 : adb_bridge_(adb_bridge
), invoked_(0) {}
619 void DeviceCountChanged(int count
) override
{
621 adb_bridge_
->RemoveDeviceCountListener(this);
625 void Shutdown() { base::MessageLoop::current()->Quit(); }
627 DevToolsAndroidBridge
* adb_bridge_
;
631 class MockCountListenerWithReAdd
: public MockCountListener
{
633 explicit MockCountListenerWithReAdd(
634 DevToolsAndroidBridge
* adb_bridge
)
635 : MockCountListener(adb_bridge
),
639 void DeviceCountChanged(int count
) override
{
641 adb_bridge_
->RemoveDeviceCountListener(this);
642 if (readd_count_
> 0) {
644 adb_bridge_
->AddDeviceCountListener(this);
645 adb_bridge_
->RemoveDeviceCountListener(this);
646 adb_bridge_
->AddDeviceCountListener(this);
655 class MockCountListenerWithReAddWhileQueued
: public MockCountListener
{
657 MockCountListenerWithReAddWhileQueued(
658 DevToolsAndroidBridge
* adb_bridge
)
659 : MockCountListener(adb_bridge
),
663 void DeviceCountChanged(int count
) override
{
667 base::ThreadTaskRunnerHandle::Get()->PostTask(
668 FROM_HERE
, base::Bind(&MockCountListenerWithReAddWhileQueued::ReAdd
,
669 base::Unretained(this)));
671 adb_bridge_
->RemoveDeviceCountListener(this);
677 adb_bridge_
->RemoveDeviceCountListener(this);
678 adb_bridge_
->AddDeviceCountListener(this);
684 class MockCountListenerForCheckingTraits
: public MockCountListener
{
686 MockCountListenerForCheckingTraits(
687 DevToolsAndroidBridge
* adb_bridge
)
688 : MockCountListener(adb_bridge
),
691 void DeviceCountChanged(int count
) override
{
694 // Check for 0 devices when no devices present.
698 // Check for 1 device when only android device present.
702 // Check for 1 device when android and non-android devices present.
706 // Check for 0 devices when only non-android devices present.
708 adb_bridge_
->RemoveDeviceCountListener(this);
712 EXPECT_TRUE(false) << "Unknown step " << step_
;
722 IN_PROC_BROWSER_TEST_F(AndroidUsbDiscoveryTest
, TestDeviceDiscovery
) {
723 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
724 adb_bridge_
->AddDeviceListListener(&listener
);
728 IN_PROC_BROWSER_TEST_F(AndroidBreakingUsbTest
, TestDeviceBreaking
) {
729 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
730 adb_bridge_
->AddDeviceListListener(&listener
);
734 IN_PROC_BROWSER_TEST_F(AndroidNoConfigUsbTest
, TestDeviceNoConfig
) {
735 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
736 adb_bridge_
->AddDeviceListListener(&listener
);
740 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
741 TestNoMultipleCallsRemoveInCallback
) {
742 MockCountListener
listener(adb_bridge_
);
743 adb_bridge_
->AddDeviceCountListener(&listener
);
745 EXPECT_EQ(1, listener
.invoked_
);
746 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
747 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
750 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
751 TestNoMultipleCallsRemoveAddInCallback
) {
752 MockCountListenerWithReAdd
listener(adb_bridge_
);
753 adb_bridge_
->AddDeviceCountListener(&listener
);
755 EXPECT_EQ(3, listener
.invoked_
);
756 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
757 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
760 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
761 TestNoMultipleCallsRemoveAddOnStart
) {
762 MockCountListener
listener(adb_bridge_
);
763 adb_bridge_
->AddDeviceCountListener(&listener
);
764 adb_bridge_
->RemoveDeviceCountListener(&listener
);
765 adb_bridge_
->AddDeviceCountListener(&listener
);
767 EXPECT_EQ(1, listener
.invoked_
);
768 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
769 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
772 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
773 TestNoMultipleCallsRemoveAddWhileQueued
) {
774 MockCountListenerWithReAddWhileQueued
listener(adb_bridge_
);
775 adb_bridge_
->AddDeviceCountListener(&listener
);
777 EXPECT_EQ(2, listener
.invoked_
);
778 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
779 EXPECT_TRUE(base::MessageLoop::current()->IsIdleForTesting());
782 IN_PROC_BROWSER_TEST_F(AndroidUsbTraitsTest
, TestDeviceCounting
) {
783 MockCountListenerForCheckingTraits
listener(adb_bridge_
);
784 adb_bridge_
->AddDeviceCountListener(&listener
);