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/strings/utf_string_conversions.h"
9 #include "chrome/browser/devtools/device/adb/mock_adb_server.h"
10 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
11 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
12 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/test/base/in_process_browser_test.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/test/test_utils.h"
17 #include "device/usb/usb_descriptors.h"
18 #include "device/usb/usb_device.h"
19 #include "device/usb/usb_device_handle.h"
20 #include "device/usb/usb_service.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 using content::BrowserThread
;
24 using device::UsbConfigDescriptor
;
25 using device::UsbDevice
;
26 using device::UsbDeviceHandle
;
27 using device::UsbEndpointDescriptor
;
28 using device::UsbEndpointDirection
;
29 using device::UsbInterfaceDescriptor
;
30 using device::UsbService
;
31 using device::UsbSynchronizationType
;
32 using device::UsbTransferCallback
;
33 using device::UsbTransferType
;
34 using device::UsbUsageType
;
38 struct NoConfigTraits
{
39 static const int kClass
= 0xff;
40 static const int kSubclass
= 0x42;
41 static const int kProtocol
= 0x1;
42 static const bool kBreaks
= false;
43 static const bool kConfigured
= false;
46 struct AndroidTraits
{
47 static const int kClass
= 0xff;
48 static const int kSubclass
= 0x42;
49 static const int kProtocol
= 0x1;
50 static const bool kBreaks
= false;
51 static const bool kConfigured
= true;
54 struct NonAndroidTraits
{
55 static const int kClass
= 0xf0;
56 static const int kSubclass
= 0x42;
57 static const int kProtocol
= 0x2;
58 static const bool kBreaks
= false;
59 static const bool kConfigured
= true;
62 struct BreakingAndroidTraits
{
63 static const int kClass
= 0xff;
64 static const int kSubclass
= 0x42;
65 static const int kProtocol
= 0x1;
66 static const bool kBreaks
= true;
67 static const bool kConfigured
= true;
70 const uint32 kMaxPayload
= 4096;
71 const uint32 kVersion
= 0x01000000;
73 const char kDeviceManufacturer
[] = "Test Manufacturer";
74 const char kDeviceModel
[] = "Nexus 6";
75 const char kDeviceSerial
[] = "01498B321301A00A";
80 class MockLocalSocket
: public MockAndroidConnection::Delegate
{
82 using Callback
= base::Callback
<void(int command
,
83 const std::string
& message
)>;
85 MockLocalSocket(const Callback
& callback
,
86 const std::string
& serial
,
87 const std::string
& command
)
88 : callback_(callback
),
89 connection_(new MockAndroidConnection(this, serial
, command
)) {
92 void Receive(const std::string
& data
) {
93 connection_
->Receive(data
);
97 void SendSuccess(const std::string
& message
) override
{
99 callback_
.Run(AdbMessage::kCommandWRTE
, message
);
102 void SendRaw(const std::string
& message
) override
{
103 callback_
.Run(AdbMessage::kCommandWRTE
, message
);
106 void Close() override
{
107 callback_
.Run(AdbMessage::kCommandCLSE
, std::string());
111 scoped_ptr
<MockAndroidConnection
> connection_
;
115 class MockUsbDeviceHandle
: public UsbDeviceHandle
{
117 explicit MockUsbDeviceHandle(MockUsbDevice
<T
>* device
)
119 remaining_body_length_(0),
120 last_local_socket_(0),
124 virtual scoped_refptr
<UsbDevice
> GetDevice() const override
{
128 virtual void Close() override
{ device_
= nullptr; }
130 bool SetConfiguration(int configuration_value
) override
{ return true; }
132 bool ClaimInterface(int interface_number
) override
{
133 if (device_
->claimed_interfaces_
.find(interface_number
) !=
134 device_
->claimed_interfaces_
.end())
137 device_
->claimed_interfaces_
.insert(interface_number
);
141 bool ReleaseInterface(int interface_number
) override
{
142 if (device_
->claimed_interfaces_
.find(interface_number
) ==
143 device_
->claimed_interfaces_
.end())
146 device_
->claimed_interfaces_
.erase(interface_number
);
150 virtual bool SetInterfaceAlternateSetting(int interface_number
,
151 int alternate_setting
) override
{
155 virtual bool ResetDevice() override
{ return true; }
156 bool GetStringDescriptor(uint8_t string_id
,
157 base::string16
* content
) override
{
161 // Async IO. Can be called on any thread.
162 virtual void ControlTransfer(UsbEndpointDirection direction
,
163 TransferRequestType request_type
,
164 TransferRecipient recipient
,
168 net::IOBuffer
* buffer
,
170 unsigned int timeout
,
171 const UsbTransferCallback
& callback
) override
{}
173 virtual void BulkTransfer(UsbEndpointDirection direction
,
175 net::IOBuffer
* buffer
,
177 unsigned int timeout
,
178 const UsbTransferCallback
& callback
) override
{
179 if (direction
== device::USB_DIRECTION_OUTBOUND
) {
180 if (remaining_body_length_
== 0) {
181 std::vector
<uint32
> header(6);
182 memcpy(&header
[0], buffer
->data(), length
);
183 current_message_
.reset(
184 new AdbMessage(header
[0], header
[1], header
[2], std::string()));
185 remaining_body_length_
= header
[3];
186 uint32 magic
= header
[5];
187 if ((current_message_
->command
^ 0xffffffff) != magic
) {
188 DCHECK(false) << "Header checksum error";
192 DCHECK(current_message_
.get());
193 current_message_
->body
+= std::string(buffer
->data(), length
);
194 remaining_body_length_
-= length
;
197 if (remaining_body_length_
== 0) {
201 device::UsbTransferStatus status
=
202 broken_
? device::USB_TRANSFER_ERROR
: device::USB_TRANSFER_COMPLETED
;
203 base::MessageLoop::current()->PostTask(
205 base::Bind(callback
, status
, scoped_refptr
<net::IOBuffer
>(), 0));
207 } else if (direction
== device::USB_DIRECTION_INBOUND
) {
208 queries_
.push(Query(callback
, make_scoped_refptr(buffer
), length
));
214 void append(D data
) {
215 std::copy(reinterpret_cast<char*>(&data
),
216 (reinterpret_cast<char*>(&data
)) + sizeof(D
),
217 std::back_inserter(output_buffer_
));
220 // Copied from AndroidUsbDevice::Checksum
221 uint32
Checksum(const std::string
& data
) {
222 unsigned char* x
= (unsigned char*)data
.data();
223 int count
= data
.length();
230 void ProcessIncoming() {
231 DCHECK(current_message_
.get());
232 switch (current_message_
->command
) {
233 case AdbMessage::kCommandCNXN
: {
234 WriteResponse(kVersion
,
236 AdbMessage::kCommandCNXN
,
237 "device::ro.product.name=SampleProduct;ro.product.model="
238 "SampleModel;ro.product.device=SampleDevice;");
241 case AdbMessage::kCommandCLSE
: {
243 current_message_
->arg0
,
244 AdbMessage::kCommandCLSE
,
246 local_sockets_
.erase(current_message_
->arg0
);
249 case AdbMessage::kCommandWRTE
: {
254 auto it
= local_sockets_
.find(current_message_
->arg0
);
255 if (it
== local_sockets_
.end())
258 DCHECK(current_message_
->arg1
!= 0);
259 WriteResponse(current_message_
->arg1
,
260 current_message_
->arg0
,
261 AdbMessage::kCommandOKAY
,
263 it
->second
->Receive(current_message_
->body
);
266 case AdbMessage::kCommandOPEN
: {
267 DCHECK(current_message_
->arg1
== 0);
268 DCHECK(current_message_
->arg0
!= 0);
269 std::string response
;
270 WriteResponse(++last_local_socket_
,
271 current_message_
->arg0
,
272 AdbMessage::kCommandOKAY
,
275 current_message_
->arg0
,
276 make_scoped_ptr(new MockLocalSocket(
277 base::Bind(&MockUsbDeviceHandle::WriteResponse
,
278 base::Unretained(this),
280 current_message_
->arg0
),
282 current_message_
->body
.substr(
283 0, current_message_
->body
.size() - 1))));
293 void WriteResponse(int arg0
, int arg1
, int command
, const std::string
& body
) {
297 bool add_zero
= !body
.empty() && (command
!= AdbMessage::kCommandWRTE
);
298 append(static_cast<uint32
>(body
.size() + (add_zero
? 1 : 0)));
299 append(Checksum(body
));
300 append(command
^ 0xffffffff);
301 std::copy(body
.begin(), body
.end(), std::back_inserter(output_buffer_
));
303 output_buffer_
.push_back(0);
308 void ProcessQueries() {
309 if (!queries_
.size())
311 Query query
= queries_
.front();
313 base::MessageLoop::current()->PostTask(
315 base::Bind(query
.callback
,
316 device::USB_TRANSFER_ERROR
,
321 if (query
.size
> output_buffer_
.size())
325 std::copy(output_buffer_
.begin(),
326 output_buffer_
.begin() + query
.size
,
327 query
.buffer
->data());
328 output_buffer_
.erase(output_buffer_
.begin(),
329 output_buffer_
.begin() + query
.size
);
330 base::MessageLoop::current()->PostTask(
332 base::Bind(query
.callback
,
333 device::USB_TRANSFER_COMPLETED
,
339 virtual void InterruptTransfer(UsbEndpointDirection direction
,
341 net::IOBuffer
* buffer
,
343 unsigned int timeout
,
344 const UsbTransferCallback
& callback
) override
{
347 virtual void IsochronousTransfer(
348 UsbEndpointDirection direction
,
350 net::IOBuffer
* buffer
,
352 unsigned int packets
,
353 unsigned int packet_length
,
354 unsigned int timeout
,
355 const UsbTransferCallback
& callback
) override
{}
358 virtual ~MockUsbDeviceHandle() {}
361 UsbTransferCallback callback
;
362 scoped_refptr
<net::IOBuffer
> buffer
;
365 Query(UsbTransferCallback callback
,
366 scoped_refptr
<net::IOBuffer
> buffer
,
368 : callback(callback
), buffer(buffer
), size(size
) {};
371 scoped_refptr
<MockUsbDevice
<T
> > device_
;
372 uint32 remaining_body_length_
;
373 scoped_ptr
<AdbMessage
> current_message_
;
374 std::vector
<char> output_buffer_
;
375 std::queue
<Query
> queries_
;
376 base::ScopedPtrHashMap
<int, MockLocalSocket
> local_sockets_
;
377 int last_local_socket_
;
382 class MockUsbDevice
: public UsbDevice
{
384 MockUsbDevice() : UsbDevice(0, 0, 0) {
385 UsbEndpointDescriptor bulk_in
;
386 bulk_in
.address
= 0x81;
387 bulk_in
.direction
= device::USB_DIRECTION_INBOUND
;
388 bulk_in
.maximum_packet_size
= 512;
389 bulk_in
.transfer_type
= device::USB_TRANSFER_BULK
;
391 UsbEndpointDescriptor bulk_out
;
392 bulk_out
.address
= 0x01;
393 bulk_out
.direction
= device::USB_DIRECTION_OUTBOUND
;
394 bulk_out
.maximum_packet_size
= 512;
395 bulk_out
.transfer_type
= device::USB_TRANSFER_BULK
;
397 UsbInterfaceDescriptor interface_desc
;
398 interface_desc
.interface_number
= 0;
399 interface_desc
.alternate_setting
= 0;
400 interface_desc
.interface_class
= T::kClass
;
401 interface_desc
.interface_subclass
= T::kSubclass
;
402 interface_desc
.interface_protocol
= T::kProtocol
;
403 interface_desc
.endpoints
.push_back(bulk_in
);
404 interface_desc
.endpoints
.push_back(bulk_out
);
406 config_desc_
.interfaces
.push_back(interface_desc
);
409 virtual scoped_refptr
<UsbDeviceHandle
> Open() override
{
410 return new MockUsbDeviceHandle
<T
>(this);
413 virtual const UsbConfigDescriptor
* GetConfiguration() override
{
414 return T::kConfigured
? &config_desc_
: nullptr;
417 virtual bool GetManufacturer(base::string16
* manufacturer
) override
{
418 *manufacturer
= base::UTF8ToUTF16(kDeviceManufacturer
);
422 virtual bool GetProduct(base::string16
* product
) override
{
423 *product
= base::UTF8ToUTF16(kDeviceModel
);
427 virtual bool GetSerialNumber(base::string16
* serial
) override
{
428 *serial
= base::UTF8ToUTF16(kDeviceSerial
);
432 virtual bool Close(scoped_refptr
<UsbDeviceHandle
> handle
) override
{
436 std::set
<int> claimed_interfaces_
;
439 virtual ~MockUsbDevice() {}
442 UsbConfigDescriptor config_desc_
;
445 class MockUsbService
: public UsbService
{
448 devices_
.push_back(new MockUsbDevice
<AndroidTraits
>());
451 scoped_refptr
<UsbDevice
> GetDeviceById(uint32 unique_id
) override
{
456 void GetDevices(std::vector
<scoped_refptr
<UsbDevice
>>* devices
) override
{
457 STLClearObject(devices
);
458 std::copy(devices_
.begin(), devices_
.end(), back_inserter(*devices
));
461 std::vector
<scoped_refptr
<UsbDevice
> > devices_
;
464 class MockBreakingUsbService
: public UsbService
{
466 scoped_refptr
<UsbDevice
> GetDeviceById(uint32 unique_id
) override
{
471 void GetDevices(std::vector
<scoped_refptr
<UsbDevice
>>* devices
) override
{
472 STLClearObject(devices
);
473 devices
->push_back(new MockUsbDevice
<BreakingAndroidTraits
>());
477 class MockNoConfigUsbService
: public UsbService
{
479 scoped_refptr
<UsbDevice
> GetDeviceById(uint32 unique_id
) override
{
484 void GetDevices(std::vector
<scoped_refptr
<UsbDevice
>>* devices
) override
{
485 STLClearObject(devices
);
486 devices
->push_back(new MockUsbDevice
<AndroidTraits
>());
487 devices
->push_back(new MockUsbDevice
<NoConfigTraits
>());
491 class MockUsbServiceForCheckingTraits
: public UsbService
{
493 MockUsbServiceForCheckingTraits() : step_(0) {}
495 scoped_refptr
<UsbDevice
> GetDeviceById(uint32 unique_id
) override
{
500 void GetDevices(std::vector
<scoped_refptr
<UsbDevice
>>* devices
) override
{
501 STLClearObject(devices
);
502 // This switch should be kept in sync with
503 // AndroidUsbBrowserTest::DeviceCountChanged.
510 devices
->push_back(new MockUsbDevice
<AndroidTraits
>());
513 // Android and non-android device.
514 devices
->push_back(new MockUsbDevice
<AndroidTraits
>());
515 devices
->push_back(new MockUsbDevice
<NonAndroidTraits
>());
518 // Non-android device.
519 devices
->push_back(new MockUsbDevice
<NonAndroidTraits
>());
529 class DevToolsAndroidBridgeWarmUp
530 : public DevToolsAndroidBridge::DeviceCountListener
{
532 DevToolsAndroidBridgeWarmUp(base::Closure closure
,
533 DevToolsAndroidBridge
* adb_bridge
)
534 : closure_(closure
), adb_bridge_(adb_bridge
) {}
536 void DeviceCountChanged(int count
) override
{
537 adb_bridge_
->RemoveDeviceCountListener(this);
541 base::Closure closure_
;
542 DevToolsAndroidBridge
* adb_bridge_
;
545 class AndroidUsbDiscoveryTest
: public InProcessBrowserTest
{
547 AndroidUsbDiscoveryTest()
548 : scheduler_invoked_(0) {
550 void SetUpOnMainThread() override
{
551 scoped_refptr
<content::MessageLoopRunner
> runner
=
552 new content::MessageLoopRunner
;
554 BrowserThread::PostTaskAndReply(
557 base::Bind(&AndroidUsbDiscoveryTest::SetUpService
, this),
558 runner
->QuitClosure());
562 DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile());
564 adb_bridge_
->set_task_scheduler_for_test(base::Bind(
565 &AndroidUsbDiscoveryTest::ScheduleDeviceCountRequest
, this));
567 scoped_refptr
<UsbDeviceProvider
> provider
=
568 new UsbDeviceProvider(browser()->profile());
570 AndroidDeviceManager::DeviceProviders providers
;
571 providers
.push_back(provider
);
572 adb_bridge_
->set_device_providers_for_test(providers
);
573 runner_
= new content::MessageLoopRunner
;
576 void ScheduleDeviceCountRequest(const base::Closure
& request
) {
577 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
578 scheduler_invoked_
++;
579 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
, request
);
582 virtual void SetUpService() {
583 UsbService::SetInstanceForTest(new MockUsbService());
586 void TearDownOnMainThread() override
{
587 scoped_refptr
<content::MessageLoopRunner
> runner
=
588 new content::MessageLoopRunner
;
589 UsbService
* service
= nullptr;
590 BrowserThread::PostTaskAndReply(
593 base::Bind(&UsbService::SetInstanceForTest
, service
),
594 runner
->QuitClosure());
598 scoped_refptr
<content::MessageLoopRunner
> runner_
;
599 DevToolsAndroidBridge
* adb_bridge_
;
600 int scheduler_invoked_
;
603 class AndroidUsbCountTest
: public AndroidUsbDiscoveryTest
{
605 void SetUpOnMainThread() override
{
606 AndroidUsbDiscoveryTest::SetUpOnMainThread();
607 DevToolsAndroidBridgeWarmUp
warmup(runner_
->QuitClosure(), adb_bridge_
);
608 adb_bridge_
->AddDeviceCountListener(&warmup
);
610 runner_
= new content::MessageLoopRunner
;
614 class AndroidUsbTraitsTest
: public AndroidUsbDiscoveryTest
{
616 void SetUpService() override
{
617 UsbService::SetInstanceForTest(new MockUsbServiceForCheckingTraits());
621 class AndroidBreakingUsbTest
: public AndroidUsbDiscoveryTest
{
623 void SetUpService() override
{
624 UsbService::SetInstanceForTest(new MockBreakingUsbService());
628 class AndroidNoConfigUsbTest
: public AndroidUsbDiscoveryTest
{
630 void SetUpService() override
{
631 UsbService::SetInstanceForTest(new MockNoConfigUsbService());
635 class MockListListener
: public DevToolsAndroidBridge::DeviceListListener
{
637 MockListListener(DevToolsAndroidBridge
* adb_bridge
,
638 const base::Closure
& callback
)
639 : adb_bridge_(adb_bridge
),
640 callback_(callback
) {
643 void DeviceListChanged(
644 const DevToolsAndroidBridge::RemoteDevices
& devices
) override
{
645 if (devices
.size() > 0) {
646 for (const auto& device
: devices
) {
647 if (device
->is_connected()) {
648 ASSERT_EQ(kDeviceModel
, device
->model());
649 ASSERT_EQ(kDeviceSerial
, device
->serial());
650 adb_bridge_
->RemoveDeviceListListener(this);
658 DevToolsAndroidBridge
* adb_bridge_
;
659 base::Closure callback_
;
662 class MockCountListener
: public DevToolsAndroidBridge::DeviceCountListener
{
664 explicit MockCountListener(DevToolsAndroidBridge
* adb_bridge
)
665 : adb_bridge_(adb_bridge
),
670 void DeviceCountChanged(int count
) override
{
672 adb_bridge_
->RemoveDeviceCountListener(this);
677 ShutdownOnUIThread();
680 void ShutdownOnUIThread() {
681 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
682 if (reposts_left_
-- == 0) {
683 base::MessageLoop::current()->Quit();
685 BrowserThread::PostTask(
688 base::Bind(&MockCountListener::ShutdownOnFileThread
,
689 base::Unretained(this)));
693 void ShutdownOnFileThread() {
694 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
695 BrowserThread::PostTask(BrowserThread::UI
,
697 base::Bind(&MockCountListener::ShutdownOnUIThread
,
698 base::Unretained(this)));
701 DevToolsAndroidBridge
* adb_bridge_
;
706 class MockCountListenerWithReAdd
: public MockCountListener
{
708 explicit MockCountListenerWithReAdd(
709 DevToolsAndroidBridge
* adb_bridge
)
710 : MockCountListener(adb_bridge
),
714 void DeviceCountChanged(int count
) override
{
716 adb_bridge_
->RemoveDeviceCountListener(this);
717 if (readd_count_
> 0) {
719 adb_bridge_
->AddDeviceCountListener(this);
720 adb_bridge_
->RemoveDeviceCountListener(this);
721 adb_bridge_
->AddDeviceCountListener(this);
730 class MockCountListenerWithReAddWhileQueued
: public MockCountListener
{
732 MockCountListenerWithReAddWhileQueued(
733 DevToolsAndroidBridge
* adb_bridge
)
734 : MockCountListener(adb_bridge
),
738 void DeviceCountChanged(int count
) override
{
742 base::MessageLoop::current()->PostTask(
744 base::Bind(&MockCountListenerWithReAddWhileQueued::ReAdd
,
745 base::Unretained(this)));
747 adb_bridge_
->RemoveDeviceCountListener(this);
753 adb_bridge_
->RemoveDeviceCountListener(this);
754 adb_bridge_
->AddDeviceCountListener(this);
760 class MockCountListenerForCheckingTraits
: public MockCountListener
{
762 MockCountListenerForCheckingTraits(
763 DevToolsAndroidBridge
* adb_bridge
)
764 : MockCountListener(adb_bridge
),
767 void DeviceCountChanged(int count
) override
{
770 // Check for 0 devices when no devices present.
774 // Check for 1 device when only android device present.
778 // Check for 1 device when android and non-android devices present.
782 // Check for 0 devices when only non-android devices present.
784 adb_bridge_
->RemoveDeviceCountListener(this);
788 EXPECT_TRUE(false) << "Unknown step " << step_
;
798 IN_PROC_BROWSER_TEST_F(AndroidUsbDiscoveryTest
, TestDeviceDiscovery
) {
799 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
800 adb_bridge_
->AddDeviceListListener(&listener
);
804 IN_PROC_BROWSER_TEST_F(AndroidBreakingUsbTest
, TestDeviceBreaking
) {
805 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
806 adb_bridge_
->AddDeviceListListener(&listener
);
810 IN_PROC_BROWSER_TEST_F(AndroidNoConfigUsbTest
, TestDeviceNoConfig
) {
811 MockListListener
listener(adb_bridge_
, runner_
->QuitClosure());
812 adb_bridge_
->AddDeviceListListener(&listener
);
816 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
817 TestNoMultipleCallsRemoveInCallback
) {
818 MockCountListener
listener(adb_bridge_
);
819 adb_bridge_
->AddDeviceCountListener(&listener
);
821 EXPECT_EQ(1, listener
.invoked_
);
822 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
825 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
826 TestNoMultipleCallsRemoveAddInCallback
) {
827 MockCountListenerWithReAdd
listener(adb_bridge_
);
828 adb_bridge_
->AddDeviceCountListener(&listener
);
830 EXPECT_EQ(3, listener
.invoked_
);
831 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
834 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
835 TestNoMultipleCallsRemoveAddOnStart
) {
836 MockCountListener
listener(adb_bridge_
);
837 adb_bridge_
->AddDeviceCountListener(&listener
);
838 adb_bridge_
->RemoveDeviceCountListener(&listener
);
839 adb_bridge_
->AddDeviceCountListener(&listener
);
841 EXPECT_EQ(1, listener
.invoked_
);
842 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
845 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest
,
846 TestNoMultipleCallsRemoveAddWhileQueued
) {
847 MockCountListenerWithReAddWhileQueued
listener(adb_bridge_
);
848 adb_bridge_
->AddDeviceCountListener(&listener
);
850 EXPECT_EQ(2, listener
.invoked_
);
851 EXPECT_EQ(listener
.invoked_
- 1, scheduler_invoked_
);
854 IN_PROC_BROWSER_TEST_F(AndroidUsbTraitsTest
, TestDeviceCounting
) {
855 MockCountListenerForCheckingTraits
listener(adb_bridge_
);
856 adb_bridge_
->AddDeviceCountListener(&listener
);