Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1351)

Side by Side Diff: chrome/browser/devtools/device/usb/android_usb_discovery_test.cc

Issue 291193007: Added android usb device discovery test via mocked usb service. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 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.
4
5 #include <algorithm>
6
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"
20
21 using content::BrowserThread;
22 using namespace usb_service;
23 namespace {
24 const int kClass = 0xff;
25 const int kSubclass = 0x42;
26 const int kProtocol = 0x1;
27
28 const uint32 kMaxPayload = 4096;
29 const uint32 kVersion = 0x01000000;
30
31 const char kOpenedUnixSocketsCommand[] = "shell:cat /proc/net/unix";
32 const char kDeviceModelCommand[] = "shell:getprop ro.product.model";
33 const char kDumpsysCommand[] = "shell:dumpsys window policy";
34 const char kListProcessesCommand[] = "shell:ps";
35 const char kInstalledChromePackagesCommand[] = "shell:pm list packages";
36 const char kDeviceModel[] = "Nexus 5";
37 const char kDeviceSerial[] = "Sample serial";
38
39 const char kSampleOpenedUnixSockets[] =
40 "Num RefCount Protocol Flags Type St Inode Path\n"
41 "00000000: 00000004 00000000"
42 " 00000000 0002 01 3328 /dev/socket/wpa_wlan0\n"
43 "00000000: 00000002 00000000"
44 " 00010000 0001 01 5394 /dev/socket/vold\n";
45
46 const char kSampleListProcesses[] =
47 "USER PID PPID VSIZE RSS WCHAN PC NAME\n"
48 "root 1 0 688 508 ffffffff 00000000 S /init\r\n"
49 "u0_a75 2425 123 933736 193024 ffffffff 00000000 S com.sample.feed\r\n"
50 "nfc 741 123 706448 26316 ffffffff 00000000 S com.android.nfc\r\n"
51 "u0_a76 1001 124 111111 222222 ffffffff 00000000 S com.android.chrome\r\n"
52 "u0_a78 1003 126 111111 222222 ffffffff 00000000 S com.noprocess.app\r\n";
53
54 const char kSampleListPackages[] =
55 "package:com.sample.feed\r\n"
56 "package:com.android.nfc\r\n"
57 "package:com.android.chrome\r\n"
58 "package:com.chrome.beta\r\n"
59 "package:com.google.android.apps.chrome\r\n";
60
61 const char kSampleDumpsys[] =
62 "WINDOW MANAGER POLICY STATE (dumpsys window policy)\r\n"
63 " mSafeMode=false mSystemReady=true mSystemBooted=true\r\n"
64 " mStable=(0,50)-(720,1184)\r\n" // Only mStable parameter is parsed
65 " mForceStatusBar=false mForceStatusBarFromKeyguard=false\r\n";
66
67 const char* GetMockShellResponse(std::string command) {
68 if (command == kDeviceModelCommand) {
69 return kDeviceModel;
70 } else if (command == kOpenedUnixSocketsCommand) {
71 return kSampleOpenedUnixSockets;
72 } else if (command == kDumpsysCommand) {
73 return kSampleDumpsys;
74 } else if (command == kListProcessesCommand) {
75 return kSampleListProcesses;
76 } else if (command == kInstalledChromePackagesCommand) {
77 return kSampleListPackages;
78 }
79
80 DCHECK(false) << "Should not be reached";
81
82 return "";
83 }
84
85 class MockUsbEndpointDescriptor : public UsbEndpointDescriptor {
86 public:
87 virtual int GetAddress() const OVERRIDE { return address_; }
88
89 virtual UsbEndpointDirection GetDirection() const OVERRIDE {
90 return direction_;
91 }
92
93 virtual int GetMaximumPacketSize() const OVERRIDE {
94 return maximum_packet_size_;
95 }
96
97 virtual UsbSynchronizationType GetSynchronizationType() const OVERRIDE {
98 return usb_synchronization_type_;
99 }
100
101 virtual UsbTransferType GetTransferType() const OVERRIDE {
102 return usb_transfer_type_;
103 }
104 virtual UsbUsageType GetUsageType() const OVERRIDE { return usb_usage_type_; }
105
106 virtual int GetPollingInterval() const OVERRIDE { return polling_interval_; }
107
108 int address_;
109 UsbEndpointDirection direction_;
110 int maximum_packet_size_;
111 UsbSynchronizationType usb_synchronization_type_;
112 UsbTransferType usb_transfer_type_;
113 UsbUsageType usb_usage_type_;
114 int polling_interval_;
115
116 private:
117 virtual ~MockUsbEndpointDescriptor() {}
118 };
119
120 class MockUsbInterfaceAltSettingDescriptor
121 : public UsbInterfaceAltSettingDescriptor {
122 public:
123 MockUsbInterfaceAltSettingDescriptor(int interface_number,
124 int alternate_setting)
125 : interface_number_(interface_number),
126 alternate_setting_(alternate_setting) {}
127
128 virtual size_t GetNumEndpoints() const OVERRIDE {
129 // See IsAndroidInterface function in android_usb_device.cc
130 return 2;
131 }
132
133 virtual scoped_refptr<const UsbEndpointDescriptor> GetEndpoint(
134 size_t index) const OVERRIDE {
135 EXPECT_GT(static_cast<size_t>(2), index);
136 MockUsbEndpointDescriptor* result = new MockUsbEndpointDescriptor();
137 result->address_ = index + 1;
138 result->usb_transfer_type_ = USB_TRANSFER_BULK;
139 result->direction_ =
140 ((index == 0) ? USB_DIRECTION_INBOUND : USB_DIRECTION_OUTBOUND);
141 result->maximum_packet_size_ = 1 << 20; // 1Mb maximum packet size
142 return result;
143 }
144
145 virtual int GetInterfaceNumber() const OVERRIDE { return interface_number_; }
146
147 virtual int GetAlternateSetting() const OVERRIDE {
148 return alternate_setting_;
149 }
150
151 virtual int GetInterfaceClass() const OVERRIDE { return kClass; }
152
153 virtual int GetInterfaceSubclass() const OVERRIDE { return kSubclass; }
154
155 virtual int GetInterfaceProtocol() const OVERRIDE { return kProtocol; }
156
157 protected:
158 virtual ~MockUsbInterfaceAltSettingDescriptor() {};
159
160 private:
161 const int interface_number_;
162 const int alternate_setting_;
163 };
164
165 class MockUsbInterfaceDescriptor : public UsbInterfaceDescriptor {
166 public:
167 explicit MockUsbInterfaceDescriptor(int interface_number)
168 : interface_number_(interface_number) {}
169
170 virtual size_t GetNumAltSettings() const OVERRIDE {
171 // See IsAndroidInterface function in android_usb_device.cc
172 return 1;
173 }
174 virtual scoped_refptr<const UsbInterfaceAltSettingDescriptor> GetAltSetting(
175 size_t index) const OVERRIDE {
176 EXPECT_EQ(static_cast<size_t>(0), index);
177 return new MockUsbInterfaceAltSettingDescriptor(interface_number_, 0);
178 }
179
180 protected:
181 const int interface_number_;
182 virtual ~MockUsbInterfaceDescriptor() {}
183 };
184
185 class MockUsbConfigDescriptor : public UsbConfigDescriptor {
186 public:
187 MockUsbConfigDescriptor() {}
188
189 virtual size_t GetNumInterfaces() const OVERRIDE { return 1; }
190
191 virtual scoped_refptr<const UsbInterfaceDescriptor> GetInterface(
192 size_t index) const OVERRIDE {
193 EXPECT_EQ(static_cast<size_t>(0), index);
194 return new MockUsbInterfaceDescriptor(index);
195 }
196
197 protected:
198 virtual ~MockUsbConfigDescriptor() {};
199 };
200
201 class MockUsbDevice;
202
203 class MockUsbDeviceHandle : public UsbDeviceHandle {
204 public:
205 explicit MockUsbDeviceHandle(MockUsbDevice* device)
206 : device_(device), remaining_body_length_(0) {}
207
208 virtual scoped_refptr<UsbDevice> GetDevice() const OVERRIDE {
209 return device_;
210 }
211
212 virtual void Close() OVERRIDE { device_ = NULL; }
213
214 virtual bool ClaimInterface(const int interface_number) OVERRIDE;
215 virtual bool ReleaseInterface(const int interface_number) OVERRIDE;
216 virtual bool SetInterfaceAlternateSetting(
217 const int interface_number,
218 const int alternate_setting) OVERRIDE {
219 return true;
220 }
221
222 virtual bool ResetDevice() OVERRIDE { return true; }
223
224 virtual bool GetSerial(base::string16* serial) OVERRIDE {
225 *serial = base::UTF8ToUTF16(kDeviceSerial);
226 return true;
227 }
228
229 // Async IO. Can be called on any thread.
230 virtual void ControlTransfer(const UsbEndpointDirection direction,
231 const TransferRequestType request_type,
232 const TransferRecipient recipient,
233 const uint8 request,
234 const uint16 value,
235 const uint16 index,
236 net::IOBuffer* buffer,
237 const size_t length,
238 const unsigned int timeout,
239 const UsbTransferCallback& callback) OVERRIDE {}
240
241 virtual void BulkTransfer(const UsbEndpointDirection direction,
242 const uint8 endpoint,
243 net::IOBuffer* buffer,
244 const size_t length,
245 const unsigned int timeout,
246 const UsbTransferCallback& callback) OVERRIDE {
247 if (direction == USB_DIRECTION_OUTBOUND) {
248 if (remaining_body_length_ == 0) {
249 std::vector<uint32> header(6);
250 memcpy(&header[0], buffer->data(), length);
251 current_message_ = new AdbMessage(header[0], header[1], header[2], "");
252 remaining_body_length_ = header[3];
253 uint32 magic = header[5];
254 if ((current_message_->command ^ 0xffffffff) != magic) {
255 DCHECK(false) << "Header checksum error";
256 return;
257 }
258 } else {
259 DCHECK(current_message_);
260 current_message_->body += std::string(buffer->data(), length);
261 remaining_body_length_ -= length;
262 }
263
264 if (remaining_body_length_ == 0) {
265 ProcessIncoming();
266 }
267
268 base::MessageLoop::current()->PostTask(
269 FROM_HERE,
270 base::Bind(callback,
271 usb_service::USB_TRANSFER_COMPLETED,
272 scoped_refptr<net::IOBuffer>(),
273 0));
274
275 } else if (direction == USB_DIRECTION_INBOUND) {
276 queries_.push(Query(callback, make_scoped_refptr(buffer), length));
277 ProcessQueries();
278 }
279 }
280
281 template <class T>
282 void append(T data) {
283 std::copy(reinterpret_cast<char*>(&data),
284 (reinterpret_cast<char*>(&data)) + sizeof(T),
285 std::back_inserter(output_buffer_));
286 }
287
288 // Copied from AndroidUsbDevice::Checksum
289 uint32 Checksum(const std::string& data) {
290 unsigned char* x = (unsigned char*)data.data();
291 int count = data.length();
292 uint32 sum = 0;
293 while (count-- > 0)
294 sum += *x++;
295 return sum;
296 }
297
298 void ProcessIncoming() {
299 DCHECK(current_message_);
300 switch (current_message_->command) {
301 case AdbMessage::kCommandCNXN:
302 WriteResponse(new AdbMessage(AdbMessage::kCommandCNXN,
303 kVersion,
304 kMaxPayload,
305 "device::ro.product.name=SampleProduct;ro."
306 "product.model=SampleModel;ro.product."
307 "device=SampleDevice;"));
308 break;
309 case AdbMessage::kCommandOPEN:
310 DCHECK(current_message_->arg1 == 0);
311 DCHECK(current_message_->arg0 != 0);
312 if (current_message_->body.find("shell:") != std::string::npos) {
313 WriteResponse(new AdbMessage(AdbMessage::kCommandOKAY,
314 ++next_local_socket_,
315 current_message_->arg0,
316 ""));
317 WriteResponse(
318 new AdbMessage(AdbMessage::kCommandWRTE,
319 next_local_socket_,
320 current_message_->arg0,
321 GetMockShellResponse(current_message_->body.substr(
322 0, current_message_->body.size() - 1))));
323 WriteResponse(new AdbMessage(
324 AdbMessage::kCommandCLSE, 0, current_message_->arg0, ""));
325 }
326 default:
327 return;
328 }
329 ProcessQueries();
330 }
331
332 void WriteResponse(scoped_refptr<AdbMessage> response) {
333 append(response->command);
334 append(response->arg0);
335 append(response->arg1);
336 bool add_zero = response->body.length() &&
337 (response->command != AdbMessage::kCommandWRTE);
338 append(static_cast<uint32>(response->body.length() + (add_zero ? 1 : 0)));
339 append(Checksum(response->body));
340 append(response->command ^ 0xffffffff);
341 std::copy(response->body.begin(),
342 response->body.end(),
343 std::back_inserter(output_buffer_));
344 if (add_zero) {
345 output_buffer_.push_back(0);
346 }
347 ProcessQueries();
348 }
349
350 void ProcessQueries() {
351 if (!queries_.size())
352 return;
353 Query query = queries_.front();
354
355 if (query.size > output_buffer_.size())
356 return;
357
358 queries_.pop();
359 std::copy(output_buffer_.begin(),
360 output_buffer_.begin() + query.size,
361 query.buffer->data());
362 output_buffer_.erase(output_buffer_.begin(),
363 output_buffer_.begin() + query.size);
364 base::MessageLoop::current()->PostTask(
365 FROM_HERE,
366 base::Bind(query.callback,
367 usb_service::USB_TRANSFER_COMPLETED,
368 query.buffer,
369 query.size));
370 }
371
372 virtual void InterruptTransfer(const UsbEndpointDirection direction,
373 const uint8 endpoint,
374 net::IOBuffer* buffer,
375 const size_t length,
376 const unsigned int timeout,
377 const UsbTransferCallback& callback) OVERRIDE {
378 }
379
380 virtual void IsochronousTransfer(
381 const UsbEndpointDirection direction,
382 const uint8 endpoint,
383 net::IOBuffer* buffer,
384 const size_t length,
385 const unsigned int packets,
386 const unsigned int packet_length,
387 const unsigned int timeout,
388 const UsbTransferCallback& callback) OVERRIDE {}
389
390 protected:
391 virtual ~MockUsbDeviceHandle() {}
392
393 struct Query {
394 UsbTransferCallback callback;
395 scoped_refptr<net::IOBuffer> buffer;
396 size_t size;
397
398 Query(UsbTransferCallback callback,
399 scoped_refptr<net::IOBuffer> buffer,
400 int size)
401 : callback(callback), buffer(buffer), size(size) {};
402 };
403
404 scoped_refptr<MockUsbDevice> device_;
405 uint32 remaining_body_length_;
406 scoped_refptr<AdbMessage> current_message_;
407 std::vector<char> output_buffer_;
408 std::queue<Query> queries_;
409 int next_local_socket_ = 1;
410 };
411
412 class MockUsbDevice : public UsbDevice {
413 public:
414 MockUsbDevice() : UsbDevice(0, 0, 0) {}
415
416 virtual scoped_refptr<UsbDeviceHandle> Open() OVERRIDE {
417 return new MockUsbDeviceHandle(this);
418 }
419
420 virtual scoped_refptr<UsbConfigDescriptor> ListInterfaces() OVERRIDE {
421 return new MockUsbConfigDescriptor();
422 }
423
424 virtual bool Close(scoped_refptr<UsbDeviceHandle> handle) OVERRIDE {
425 return true;
426 }
427
428 #if defined(OS_CHROMEOS)
429 // On ChromeOS, if an interface of a claimed device is not claimed, the
430 // permission broker can change the owner of the device so that the unclaimed
431 // interfaces can be used. If this argument is missing, permission broker will
432 // not be used and this method fails if the device is claimed.
433 virtual void RequestUsbAcess(
434 int interface_id,
435 const base::Callback<void(bool success)>& callback) OVERRIDE {
436 callback.Run(true);
437 }
438 #endif // OS_CHROMEOS
439
440 std::set<int> claimed_interfaces_;
441
442 protected:
443 virtual ~MockUsbDevice() {}
444 };
445
446 class MockUsbService : public UsbService {
447 public:
448 MockUsbService() { devices_.push_back(new MockUsbDevice()); }
449
450 virtual ~MockUsbService() {}
451
452 virtual scoped_refptr<UsbDevice> GetDeviceById(uint32 unique_id) OVERRIDE {
453 NOTIMPLEMENTED();
454 return NULL;
455 }
456
457 virtual void GetDevices(
458 std::vector<scoped_refptr<UsbDevice> >* devices) OVERRIDE {
459 STLClearObject(devices);
460 std::copy(devices_.begin(), devices_.end(), back_inserter(*devices));
461 }
462
463 std::vector<scoped_refptr<UsbDevice> > devices_;
464 };
465
466 bool MockUsbDeviceHandle::ClaimInterface(const int interface_number) {
467 if (device_->claimed_interfaces_.find(interface_number) !=
468 device_->claimed_interfaces_.end())
469 return false;
470
471 device_->claimed_interfaces_.insert(interface_number);
472 return true;
473 }
474
475 bool MockUsbDeviceHandle::ReleaseInterface(const int interface_number) {
476 if (device_->claimed_interfaces_.find(interface_number) ==
477 device_->claimed_interfaces_.end())
478 return false;
479
480 device_->claimed_interfaces_.erase(interface_number);
481 return true;
482 }
483
484 class AndroidUsbDiscoveryTest
485 : public InProcessBrowserTest,
486 public DevToolsAndroidBridge::DeviceListListener {
487 protected:
488 virtual void SetUpOnMainThread() OVERRIDE {
489 scoped_refptr<content::MessageLoopRunner> runner =
490 new content::MessageLoopRunner;
491
492 BrowserThread::PostTaskAndReply(
493 BrowserThread::FILE,
494 FROM_HERE,
495 base::Bind(&AndroidUsbDiscoveryTest::SetUpService, this),
496 runner->QuitClosure());
497 runner->Run();
498
499 adb_bridge_ =
500 DevToolsAndroidBridge::Factory::GetForProfile(browser()->profile());
501
502 scoped_refptr<UsbDeviceProvider> provider =
503 new UsbDeviceProvider(browser()->profile());
504
505 AndroidDeviceManager::DeviceProviders providers;
506 providers.push_back(provider);
507
508 adb_bridge_->set_device_providers_for_test(providers);
509
510 runner_ = new content::MessageLoopRunner;
511 }
512
513 void SetUpService() {
514 service_ = new MockUsbService();
515 UsbService::SetInstanceForTest(service_);
516 }
517
518 virtual void CleanUpOnMainThread() OVERRIDE {
519 scoped_refptr<content::MessageLoopRunner> runner =
520 new content::MessageLoopRunner;
521 UsbService* service = NULL;
522 BrowserThread::PostTaskAndReply(
523 BrowserThread::FILE,
524 FROM_HERE,
525 base::Bind(&UsbService::SetInstanceForTest, service),
526 runner->QuitClosure());
527 runner->Run();
528 }
529
530 virtual void DeviceListChanged(
531 const DevToolsAndroidBridge::RemoteDevices& devices) OVERRIDE {
532 if (devices.size() > 0) {
533 if (devices[0]->is_connected()) {
534 ASSERT_EQ(kDeviceModel, devices[0]->model());
535 ASSERT_EQ(kDeviceSerial, devices[0]->serial());
536 adb_bridge_->RemoveDeviceListListener(this);
537 runner_->Quit();
538 }
539 }
540 }
541
542 bool passed = false;
543 scoped_refptr<content::MessageLoopRunner> runner_;
544 MockUsbService* service_;
545 scoped_refptr<DevToolsAndroidBridge> adb_bridge_;
546 };
547
548 } // namespace
549
550 IN_PROC_BROWSER_TEST_F(AndroidUsbDiscoveryTest, TestDeviceDiscovery) {
551 if (!adb_bridge_) {
552 FAIL() << "Failed to get DevToolsAndroidBridge.";
553 }
554
555 adb_bridge_->AddDeviceListListener(this);
556
557 runner_->Run();
558 }
OLDNEW
« no previous file with comments | « no previous file | chrome/chrome_tests.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698