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/strings/utf_string_conversions.h"
8 #include "chrome/browser/devtools/device/devtools_android_bridge.h"
9 #include "chrome/browser/devtools/device/usb/android_usb_device.h"
10 #include "chrome/browser/devtools/device/usb/usb_device_provider.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/test/base/in_process_browser_test.h"
13 #include "components/usb_service/usb_device.h"
14 #include "components/usb_service/usb_device_handle.h"
15 #include "components/usb_service/usb_interface.h"
16 #include "components/usb_service/usb_service.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/test/test_utils.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 using content::BrowserThread;
22 using namespace usb_service;
26 struct AndroidTraits {
27 static const int kClass = 0xff;
28 static const int kSubclass = 0x42;
29 static const int kProtocol = 0x1;
32 struct NonAndroidTraits {
33 static const int kClass = 0xf0;
34 static const int kSubclass = 0x42;
35 static const int kProtocol = 0x2;
38 const uint32 kMaxPayload = 4096;
39 const uint32 kVersion = 0x01000000;
41 const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
42 const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
43 const char kDumpsysCommand[] = "shell:dumpsys window policy";
44 const char kListProcessesCommand[] = "shell:ps";
45 const char kInstalledChromePackagesCommand[] = "shell:pm list packages";
46 const char kDeviceManufacturer[] = "Test Manufacturer";
47 const char kDeviceModel[] = "Nexus 5";
48 const char kDeviceSerial[] = "Sample serial";
50 const char kSampleOpenedUnixSockets[] =
51 "Num RefCount Protocol Flags Type St Inode Path\n"
52 "00000000: 00000004 00000000"
53 " 00000000 0002 01 3328 /dev/socket/wpa_wlan0\n"
54 "00000000: 00000002 00000000"
55 " 00010000 0001 01 5394 /dev/socket/vold\n";
57 const char kSampleListProcesses[] =
58 "USER PID PPID VSIZE RSS WCHAN PC NAME\n"
59 "root 1 0 688 508 ffffffff 00000000 S /init\r\n"
60 "u0_a75 2425 123 933736 193024 ffffffff 00000000 S com.sample.feed\r\n"
61 "nfc 741 123 706448 26316 ffffffff 00000000 S com.android.nfc\r\n"
62 "u0_a76 1001 124 111111 222222 ffffffff 00000000 S com.android.chrome\r\n"
63 "u0_a78 1003 126 111111 222222 ffffffff 00000000 S com.noprocess.app\r\n";
65 const char kSampleListPackages[] =
66 "package:com.sample.feed\r\n"
67 "package:com.android.nfc\r\n"
68 "package:com.android.chrome\r\n"
69 "package:com.chrome.beta\r\n"
70 "package:com.google.android.apps.chrome\r\n";
72 const char kSampleDumpsys[] =
73 "WINDOW MANAGER POLICY STATE (dumpsys window policy)\r\n"
74 " mSafeMode=false mSystemReady=true mSystemBooted=true\r\n"
75 " mStable=(0,50)-(720,1184)\r\n" // Only mStable parameter is parsed
76 " mForceStatusBar=false mForceStatusBarFromKeyguard=false\r\n";
78 const char* GetMockShellResponse(std::string command) {
79 if (command == kDeviceModelCommand) {
81 } else if (command == kOpenedUnixSocketsCommand) {
82 return kSampleOpenedUnixSockets;
83 } else if (command == kDumpsysCommand) {
84 return kSampleDumpsys;
85 } else if (command == kListProcessesCommand) {
86 return kSampleListProcesses;
87 } else if (command == kInstalledChromePackagesCommand) {
88 return kSampleListPackages;
91 DCHECK(false) << "Should not be reached";
96 class MockUsbEndpointDescriptor : public UsbEndpointDescriptor {
98 virtual int GetAddress() const OVERRIDE { return address_; }
100 virtual UsbEndpointDirection GetDirection() const OVERRIDE {
104 virtual int GetMaximumPacketSize() const OVERRIDE {
105 return maximum_packet_size_;
108 virtual UsbSynchronizationType GetSynchronizationType() const OVERRIDE {
109 return usb_synchronization_type_;
112 virtual UsbTransferType GetTransferType() const OVERRIDE {
113 return usb_transfer_type_;
115 virtual UsbUsageType GetUsageType() const OVERRIDE { return usb_usage_type_; }
117 virtual int GetPollingInterval() const OVERRIDE { return polling_interval_; }
120 UsbEndpointDirection direction_;
121 int maximum_packet_size_;
122 UsbSynchronizationType usb_synchronization_type_;
123 UsbTransferType usb_transfer_type_;
124 UsbUsageType usb_usage_type_;
125 int polling_interval_;
128 virtual ~MockUsbEndpointDescriptor() {}
132 class MockUsbInterfaceAltSettingDescriptor
133 : public UsbInterfaceAltSettingDescriptor {
135 MockUsbInterfaceAltSettingDescriptor(int interface_number,
136 int alternate_setting)
137 : interface_number_(interface_number),
138 alternate_setting_(alternate_setting) {}
140 virtual size_t GetNumEndpoints() const OVERRIDE {
141 // See IsAndroidInterface function in android_usb_device.cc
145 virtual scoped_refptr<const UsbEndpointDescriptor> GetEndpoint(
146 size_t index) const OVERRIDE {
147 EXPECT_GT(static_cast<size_t>(2), index);
148 MockUsbEndpointDescriptor* result = new MockUsbEndpointDescriptor();
149 result->address_ = index + 1;
150 result->usb_transfer_type_ = USB_TRANSFER_BULK;
152 ((index == 0) ? USB_DIRECTION_INBOUND : USB_DIRECTION_OUTBOUND);
153 result->maximum_packet_size_ = 1 << 20; // 1Mb maximum packet size
157 virtual int GetInterfaceNumber() const OVERRIDE { return interface_number_; }
159 virtual int GetAlternateSetting() const OVERRIDE {
160 return alternate_setting_;
163 virtual int GetInterfaceClass() const OVERRIDE { return T::kClass; }
165 virtual int GetInterfaceSubclass() const OVERRIDE { return T::kSubclass; }
167 virtual int GetInterfaceProtocol() const OVERRIDE { return T::kProtocol; }
170 virtual ~MockUsbInterfaceAltSettingDescriptor() {};
173 const int interface_number_;
174 const int alternate_setting_;
178 class MockUsbInterfaceDescriptor : public UsbInterfaceDescriptor {
180 explicit MockUsbInterfaceDescriptor(int interface_number)
181 : interface_number_(interface_number) {}
183 virtual size_t GetNumAltSettings() const OVERRIDE {
184 // See IsAndroidInterface function in android_usb_device.cc
187 virtual scoped_refptr<const UsbInterfaceAltSettingDescriptor> GetAltSetting(
188 size_t index) const OVERRIDE {
189 EXPECT_EQ(static_cast<size_t>(0), index);
190 return new MockUsbInterfaceAltSettingDescriptor<T>(interface_number_, 0);
194 const int interface_number_;
195 virtual ~MockUsbInterfaceDescriptor() {}
199 class MockUsbConfigDescriptor : public UsbConfigDescriptor {
201 MockUsbConfigDescriptor() {}
203 virtual size_t GetNumInterfaces() const OVERRIDE { return 1; }
205 virtual scoped_refptr<const UsbInterfaceDescriptor> GetInterface(
206 size_t index) const OVERRIDE {
207 EXPECT_EQ(static_cast<size_t>(0), index);
208 return new MockUsbInterfaceDescriptor<T>(index);
212 virtual ~MockUsbConfigDescriptor() {};
219 class MockUsbDeviceHandle : public UsbDeviceHandle {
221 explicit MockUsbDeviceHandle(MockUsbDevice<T>* device)
223 remaining_body_length_(0),
224 next_local_socket_(0) {}
226 virtual scoped_refptr<UsbDevice> GetDevice() const OVERRIDE {
230 virtual void Close() OVERRIDE { device_ = NULL; }
232 bool ClaimInterface(const int interface_number) {
233 if (device_->claimed_interfaces_.find(interface_number) !=
234 device_->claimed_interfaces_.end())
237 device_->claimed_interfaces_.insert(interface_number);
241 bool ReleaseInterface(const int interface_number) {
242 if (device_->claimed_interfaces_.find(interface_number) ==
243 device_->claimed_interfaces_.end())
246 device_->claimed_interfaces_.erase(interface_number);
250 virtual bool SetInterfaceAlternateSetting(
251 const int interface_number,
252 const int alternate_setting) OVERRIDE {
256 virtual bool ResetDevice() OVERRIDE { return true; }
258 virtual bool GetManufacturer(base::string16* manufacturer) OVERRIDE {
259 *manufacturer = base::UTF8ToUTF16(kDeviceManufacturer);
263 virtual bool GetProduct(base::string16* product) OVERRIDE {
264 *product = base::UTF8ToUTF16(kDeviceModel);
268 virtual bool GetSerial(base::string16* serial) OVERRIDE {
269 *serial = base::UTF8ToUTF16(kDeviceSerial);
273 // Async IO. Can be called on any thread.
274 virtual void ControlTransfer(const UsbEndpointDirection direction,
275 const TransferRequestType request_type,
276 const TransferRecipient recipient,
280 net::IOBuffer* buffer,
282 const unsigned int timeout,
283 const UsbTransferCallback& callback) OVERRIDE {}
285 virtual void BulkTransfer(const UsbEndpointDirection direction,
286 const uint8 endpoint,
287 net::IOBuffer* buffer,
289 const unsigned int timeout,
290 const UsbTransferCallback& callback) OVERRIDE {
291 if (direction == USB_DIRECTION_OUTBOUND) {
292 if (remaining_body_length_ == 0) {
293 std::vector<uint32> header(6);
294 memcpy(&header[0], buffer->data(), length);
295 current_message_ = new AdbMessage(header[0], header[1], header[2], "");
296 remaining_body_length_ = header[3];
297 uint32 magic = header[5];
298 if ((current_message_->command ^ 0xffffffff) != magic) {
299 DCHECK(false) << "Header checksum error";
303 DCHECK(current_message_);
304 current_message_->body += std::string(buffer->data(), length);
305 remaining_body_length_ -= length;
308 if (remaining_body_length_ == 0) {
312 base::MessageLoop::current()->PostTask(
315 usb_service::USB_TRANSFER_COMPLETED,
316 scoped_refptr<net::IOBuffer>(),
319 } else if (direction == USB_DIRECTION_INBOUND) {
320 queries_.push(Query(callback, make_scoped_refptr(buffer), length));
326 void append(D data) {
327 std::copy(reinterpret_cast<char*>(&data),
328 (reinterpret_cast<char*>(&data)) + sizeof(D),
329 std::back_inserter(output_buffer_));
332 // Copied from AndroidUsbDevice::Checksum
333 uint32 Checksum(const std::string& data) {
334 unsigned char* x = (unsigned char*)data.data();
335 int count = data.length();
342 void ProcessIncoming() {
343 DCHECK(current_message_);
344 switch (current_message_->command) {
345 case AdbMessage::kCommandCNXN:
346 WriteResponse(new AdbMessage(AdbMessage::kCommandCNXN,
349 "device::ro.product.name=SampleProduct;ro."
350 "product.model=SampleModel;ro.product."
351 "device=SampleDevice;"));
353 case AdbMessage::kCommandOPEN:
354 DCHECK(current_message_->arg1 == 0);
355 DCHECK(current_message_->arg0 != 0);
356 if (current_message_->body.find("shell:") != std::string::npos) {
357 WriteResponse(new AdbMessage(AdbMessage::kCommandOKAY,
358 ++next_local_socket_,
359 current_message_->arg0,
362 new AdbMessage(AdbMessage::kCommandWRTE,
364 current_message_->arg0,
365 GetMockShellResponse(current_message_->body.substr(
366 0, current_message_->body.size() - 1))));
367 WriteResponse(new AdbMessage(
368 AdbMessage::kCommandCLSE, 0, current_message_->arg0, ""));
376 void WriteResponse(scoped_refptr<AdbMessage> response) {
377 append(response->command);
378 append(response->arg0);
379 append(response->arg1);
380 bool add_zero = response->body.length() &&
381 (response->command != AdbMessage::kCommandWRTE);
382 append(static_cast<uint32>(response->body.length() + (add_zero ? 1 : 0)));
383 append(Checksum(response->body));
384 append(response->command ^ 0xffffffff);
385 std::copy(response->body.begin(),
386 response->body.end(),
387 std::back_inserter(output_buffer_));
389 output_buffer_.push_back(0);
394 void ProcessQueries() {
395 if (!queries_.size())
397 Query query = queries_.front();
399 if (query.size > output_buffer_.size())
403 std::copy(output_buffer_.begin(),
404 output_buffer_.begin() + query.size,
405 query.buffer->data());
406 output_buffer_.erase(output_buffer_.begin(),
407 output_buffer_.begin() + query.size);
408 base::MessageLoop::current()->PostTask(
410 base::Bind(query.callback,
411 usb_service::USB_TRANSFER_COMPLETED,
416 virtual void InterruptTransfer(const UsbEndpointDirection direction,
417 const uint8 endpoint,
418 net::IOBuffer* buffer,
420 const unsigned int timeout,
421 const UsbTransferCallback& callback) OVERRIDE {
424 virtual void IsochronousTransfer(
425 const UsbEndpointDirection direction,
426 const uint8 endpoint,
427 net::IOBuffer* buffer,
429 const unsigned int packets,
430 const unsigned int packet_length,
431 const unsigned int timeout,
432 const UsbTransferCallback& callback) OVERRIDE {}
435 virtual ~MockUsbDeviceHandle() {}
438 UsbTransferCallback callback;
439 scoped_refptr<net::IOBuffer> buffer;
442 Query(UsbTransferCallback callback,
443 scoped_refptr<net::IOBuffer> buffer,
445 : callback(callback), buffer(buffer), size(size) {};
448 scoped_refptr<MockUsbDevice<T> > device_;
449 uint32 remaining_body_length_;
450 scoped_refptr<AdbMessage> current_message_;
451 std::vector<char> output_buffer_;
452 std::queue<Query> queries_;
453 int next_local_socket_;
457 class MockUsbDevice : public UsbDevice {
459 MockUsbDevice() : UsbDevice(0, 0, 0) {}
461 virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE {
462 return new MockUsbDeviceHandle<T>(this);
465 virtual scoped_refptr<UsbConfigDescriptor> ListInterfaces() OVERRIDE {
466 return new MockUsbConfigDescriptor<T>();
469 virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) OVERRIDE {
473 #if defined(OS_CHROMEOS)
474 // On ChromeOS, if an interface of a claimed device is not claimed, the
475 // permission broker can change the owner of the device so that the unclaimed
476 // interfaces can be used. If this argument is missing, permission broker will
477 // not be used and this method fails if the device is claimed.
478 virtual void RequestUsbAccess(
480 const base::Callback<void(bool success)>& callback) OVERRIDE {
483 #endif // OS_CHROMEOS
485 std::set<int> claimed_interfaces_;
488 virtual ~MockUsbDevice() {}
491 class MockUsbService : public UsbService {
494 devices_.push_back(new MockUsbDevice<AndroidTraits>());
497 virtual ~MockUsbService() {}
499 virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE {
504 virtual void GetDevices(
505 std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE {
506 STLClearObject(devices);
507 std::copy(devices_.begin(), devices_.end(), back_inserter(*devices));
510 std::vector<scoped_refptr<UsbDevice> > devices_;
513 class MockUsbServiceForCheckingTraits : public UsbService {
515 MockUsbServiceForCheckingTraits() : step_(0) {}
517 virtual ~MockUsbServiceForCheckingTraits() {}
519 virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE {
524 virtual void GetDevices(
525 std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE {
526 STLClearObject(devices);
527 // This switch should be kept in sync with
528 // AndroidUsbBrowserTest::DeviceCountChanged.
535 devices->push_back(new MockUsbDevice<AndroidTraits>());
538 // Android and non-android device.
539 devices->push_back(new MockUsbDevice<AndroidTraits>());
540 devices->push_back(new MockUsbDevice<NonAndroidTraits>());
543 // Non-android device.
544 devices->push_back(new MockUsbDevice<NonAndroidTraits>());
554 class DevToolsAndroidBridgeWarmUp
555 : public DevToolsAndroidBridge::DeviceCountListener {
557 DevToolsAndroidBridgeWarmUp(base::Closure closure,
558 scoped_refptr<DevToolsAndroidBridge> adb_bridge)
559 : closure_(closure), adb_bridge_(adb_bridge) {}
561 virtual void DeviceCountChanged(int count) OVERRIDE {
562 adb_bridge_->RemoveDeviceCountListener(this);
566 base::Closure closure_;
567 scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
570 class AndroidUsbDiscoveryTest : public InProcessBrowserTest {
572 AndroidUsbDiscoveryTest()
573 : scheduler_invoked_(0) {
575 virtual void SetUpOnMainThread() OVERRIDE {
576 scoped_refptr<content::MessageLoopRunner> runner =
577 new content::MessageLoopRunner;
579 BrowserThread::PostTaskAndReply(
582 base::Bind(&AndroidUsbDiscoveryTest::SetUpService, this),
583 runner->QuitClosure());
587 DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile());
589 adb_bridge_->set_task_scheduler_for_test(base::Bind(
590 &AndroidUsbDiscoveryTest::ScheduleDeviceCountRequest, this));
592 scoped_refptr<UsbDeviceProvider> provider =
593 new UsbDeviceProvider(browser()->profile());
595 AndroidDeviceManager::DeviceProviders providers;
596 providers.push_back(provider);
597 adb_bridge_->set_device_providers_for_test(providers);
598 runner_ = new content::MessageLoopRunner;
601 void ScheduleDeviceCountRequest(const base::Closure& request) {
602 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
603 scheduler_invoked_++;
604 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, request);
607 virtual void SetUpService() {
608 UsbService::SetInstanceForTest(new MockUsbService());
611 virtual void TearDownOnMainThread() OVERRIDE {
612 scoped_refptr<content::MessageLoopRunner> runner =
613 new content::MessageLoopRunner;
614 UsbService* service = NULL;
615 BrowserThread::PostTaskAndReply(
618 base::Bind(&UsbService::SetInstanceForTest, service),
619 runner->QuitClosure());
623 scoped_refptr<content::MessageLoopRunner> runner_;
624 scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
625 int scheduler_invoked_;
628 class AndroidUsbCountTest : public AndroidUsbDiscoveryTest {
630 virtual void SetUpOnMainThread() OVERRIDE {
631 AndroidUsbDiscoveryTest::SetUpOnMainThread();
632 DevToolsAndroidBridgeWarmUp warmup(runner_->QuitClosure(), adb_bridge_);
633 adb_bridge_->AddDeviceCountListener(&warmup);
635 runner_ = new content::MessageLoopRunner;
639 class AndroidUsbTraitsTest : public AndroidUsbDiscoveryTest {
641 virtual void SetUpService() OVERRIDE {
642 UsbService::SetInstanceForTest(new MockUsbServiceForCheckingTraits());
646 class MockListListener : public DevToolsAndroidBridge::DeviceListListener {
648 MockListListener(scoped_refptr<DevToolsAndroidBridge> adb_bridge,
649 const base::Closure& callback)
650 : adb_bridge_(adb_bridge),
651 callback_(callback) {
654 virtual void DeviceListChanged(
655 const DevToolsAndroidBridge::RemoteDevices& devices) OVERRIDE {
656 if (devices.size() > 0) {
657 if (devices[0]->is_connected()) {
658 ASSERT_EQ(kDeviceModel, devices[0]->model());
659 ASSERT_EQ(kDeviceSerial, devices[0]->serial());
660 adb_bridge_->RemoveDeviceListListener(this);
666 scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
667 base::Closure callback_;
670 class MockCountListener : public DevToolsAndroidBridge::DeviceCountListener {
672 explicit MockCountListener(scoped_refptr<DevToolsAndroidBridge> adb_bridge)
673 : adb_bridge_(adb_bridge),
678 virtual void DeviceCountChanged(int count) OVERRIDE {
680 adb_bridge_->RemoveDeviceCountListener(this);
685 ShutdownOnUIThread();
688 void ShutdownOnUIThread() {
689 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
690 if (reposts_left_-- == 0) {
691 base::MessageLoop::current()->Quit();
693 BrowserThread::PostTask(
696 base::Bind(&MockCountListener::ShutdownOnFileThread,
697 base::Unretained(this)));
701 void ShutdownOnFileThread() {
702 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
703 BrowserThread::PostTask(BrowserThread::UI,
705 base::Bind(&MockCountListener::ShutdownOnUIThread,
706 base::Unretained(this)));
709 scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
714 class MockCountListenerWithReAdd : public MockCountListener {
716 explicit MockCountListenerWithReAdd(
717 scoped_refptr<DevToolsAndroidBridge> adb_bridge)
718 : MockCountListener(adb_bridge),
722 virtual void DeviceCountChanged(int count) OVERRIDE {
724 adb_bridge_->RemoveDeviceCountListener(this);
725 if (readd_count_ > 0) {
727 adb_bridge_->AddDeviceCountListener(this);
728 adb_bridge_->RemoveDeviceCountListener(this);
729 adb_bridge_->AddDeviceCountListener(this);
738 class MockCountListenerWithReAddWhileQueued : public MockCountListener {
740 MockCountListenerWithReAddWhileQueued(
741 scoped_refptr<DevToolsAndroidBridge> adb_bridge)
742 : MockCountListener(adb_bridge),
746 virtual void DeviceCountChanged(int count) OVERRIDE {
750 base::MessageLoop::current()->PostTask(
752 base::Bind(&MockCountListenerWithReAddWhileQueued::ReAdd,
753 base::Unretained(this)));
755 adb_bridge_->RemoveDeviceCountListener(this);
761 adb_bridge_->RemoveDeviceCountListener(this);
762 adb_bridge_->AddDeviceCountListener(this);
768 class MockCountListenerForCheckingTraits : public MockCountListener {
770 MockCountListenerForCheckingTraits(
771 scoped_refptr<DevToolsAndroidBridge> adb_bridge)
772 : MockCountListener(adb_bridge),
775 virtual void DeviceCountChanged(int count) OVERRIDE {
778 // Check for 0 devices when no devices present.
782 // Check for 1 device when only android device present.
786 // Check for 1 device when android and non-android devices present.
790 // Check for 0 devices when only non-android devices present.
792 adb_bridge_->RemoveDeviceCountListener(this);
796 EXPECT_TRUE(false) << "Unknown step " << step_;
806 IN_PROC_BROWSER_TEST_F(AndroidUsbDiscoveryTest, TestDeviceDiscovery) {
807 MockListListener listener(adb_bridge_, runner_->QuitClosure());
808 adb_bridge_->AddDeviceListListener(&listener);
812 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
813 TestNoMultipleCallsRemoveInCallback) {
814 MockCountListener listener(adb_bridge_);
815 adb_bridge_->AddDeviceCountListener(&listener);
817 EXPECT_EQ(1, listener.invoked_);
818 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
821 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
822 TestNoMultipleCallsRemoveAddInCallback) {
823 MockCountListenerWithReAdd listener(adb_bridge_);
824 adb_bridge_->AddDeviceCountListener(&listener);
826 EXPECT_EQ(3, listener.invoked_);
827 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
830 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
831 TestNoMultipleCallsRemoveAddOnStart) {
832 MockCountListener listener(adb_bridge_);
833 adb_bridge_->AddDeviceCountListener(&listener);
834 adb_bridge_->RemoveDeviceCountListener(&listener);
835 adb_bridge_->AddDeviceCountListener(&listener);
837 EXPECT_EQ(1, listener.invoked_);
838 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
841 IN_PROC_BROWSER_TEST_F(AndroidUsbCountTest,
842 TestNoMultipleCallsRemoveAddWhileQueued) {
843 MockCountListenerWithReAddWhileQueued listener(adb_bridge_);
844 adb_bridge_->AddDeviceCountListener(&listener);
846 EXPECT_EQ(2, listener.invoked_);
847 EXPECT_EQ(listener.invoked_ - 1, scheduler_invoked_);
850 IN_PROC_BROWSER_TEST_F(AndroidUsbTraitsTest, TestDeviceCounting) {
851 MockCountListenerForCheckingTraits listener(adb_bridge_);
852 adb_bridge_->AddDeviceCountListener(&listener);