OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/devtools/adb/android_usb_device.h" | 5 #include "chrome/browser/devtools/adb/android_usb_device.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/barrier_closure.h" | 9 #include "base/barrier_closure.h" |
10 #include "base/base64.h" | 10 #include "base/base64.h" |
(...skipping 27 matching lines...) Expand all Loading... | |
38 const uint32 kMaxPayload = 4096; | 38 const uint32 kMaxPayload = 4096; |
39 const uint32 kVersion = 0x01000000; | 39 const uint32 kVersion = 0x01000000; |
40 | 40 |
41 static const char kHostConnectMessage[] = "host::"; | 41 static const char kHostConnectMessage[] = "host::"; |
42 | 42 |
43 using content::BrowserThread; | 43 using content::BrowserThread; |
44 | 44 |
45 typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices; | 45 typedef std::vector<scoped_refptr<UsbDevice> > UsbDevices; |
46 typedef std::set<scoped_refptr<UsbDevice> > UsbDeviceSet; | 46 typedef std::set<scoped_refptr<UsbDevice> > UsbDeviceSet; |
47 | 47 |
48 base::LazyInstance<AndroidUsbDevices>::Leaky g_devices = | 48 // Stores android wrappers around claimed usb devices on caller thread. |
49 base::LazyInstance<std::vector<AndroidUsbDevice*> >::Leaky g_devices = | |
49 LAZY_INSTANCE_INITIALIZER; | 50 LAZY_INSTANCE_INITIALIZER; |
50 | 51 |
51 bool IsAndroidInterface( | 52 bool IsAndroidInterface( |
52 scoped_refptr<const UsbInterfaceDescriptor> interface) { | 53 scoped_refptr<const UsbInterfaceDescriptor> interface) { |
53 if (interface->GetNumAltSettings() == 0) | 54 if (interface->GetNumAltSettings() == 0) |
54 return false; | 55 return false; |
55 | 56 |
56 scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc = | 57 scoped_refptr<const UsbInterfaceAltSettingDescriptor> idesc = |
57 interface->GetAltSetting(0); | 58 interface->GetAltSetting(0); |
58 | 59 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 return NULL; | 94 return NULL; |
94 | 95 |
95 if (!usb_handle->ClaimInterface(interface_id)) | 96 if (!usb_handle->ClaimInterface(interface_id)) |
96 return NULL; | 97 return NULL; |
97 | 98 |
98 base::string16 serial; | 99 base::string16 serial; |
99 if (!usb_handle->GetSerial(&serial) || serial.empty()) | 100 if (!usb_handle->GetSerial(&serial) || serial.empty()) |
100 return NULL; | 101 return NULL; |
101 | 102 |
102 return new AndroidUsbDevice(rsa_key, usb_handle, base::UTF16ToASCII(serial), | 103 return new AndroidUsbDevice(rsa_key, usb_handle, base::UTF16ToASCII(serial), |
103 inbound_address, outbound_address, zero_mask); | 104 inbound_address, outbound_address, zero_mask, |
105 interface_id); | |
104 } | 106 } |
105 | 107 |
106 uint32 Checksum(const std::string& data) { | 108 uint32 Checksum(const std::string& data) { |
107 unsigned char* x = (unsigned char*)data.data(); | 109 unsigned char* x = (unsigned char*)data.data(); |
108 int count = data.length(); | 110 int count = data.length(); |
109 uint32 sum = 0; | 111 uint32 sum = 0; |
110 while (count-- > 0) | 112 while (count-- > 0) |
111 sum += *x++; | 113 sum += *x++; |
112 return sum; | 114 return sum; |
113 } | 115 } |
(...skipping 20 matching lines...) Expand all Loading... | |
134 if (data[i] >= 0x20 && data[i] <= 0x7E) | 136 if (data[i] >= 0x20 && data[i] <= 0x7E) |
135 result += data[i]; | 137 result += data[i]; |
136 else | 138 else |
137 result += "."; | 139 result += "."; |
138 } | 140 } |
139 } | 141 } |
140 LOG(ERROR) << (outgoing ? "[out] " : "[ in] ") << result; | 142 LOG(ERROR) << (outgoing ? "[out] " : "[ in] ") << result; |
141 #endif // 0 | 143 #endif // 0 |
142 } | 144 } |
143 | 145 |
144 void ReleaseInterface(scoped_refptr<UsbDeviceHandle> usb_device) { | 146 void ReleaseInterface(scoped_refptr<UsbDeviceHandle> usb_device, |
145 usb_device->ReleaseInterface(1); | 147 int interface_id) { |
148 usb_device->ReleaseInterface(interface_id); | |
146 usb_device->Close(); | 149 usb_device->Close(); |
147 } | 150 } |
148 | 151 |
149 } // namespace | 152 } // namespace |
150 | 153 |
151 AdbMessage::AdbMessage(uint32 command, | 154 AdbMessage::AdbMessage(uint32 command, |
152 uint32 arg0, | 155 uint32 arg0, |
153 uint32 arg1, | 156 uint32 arg1, |
154 const std::string& body) | 157 const std::string& body) |
155 : command(command), | 158 : command(command), |
156 arg0(arg0), | 159 arg0(arg0), |
157 arg1(arg1), | 160 arg1(arg1), |
158 body(body) { | 161 body(body) { |
159 } | 162 } |
160 | 163 |
161 AdbMessage::~AdbMessage() { | 164 AdbMessage::~AdbMessage() { |
162 } | 165 } |
163 | 166 |
164 static void RespondWithCountOnUIThread(base::Callback<void(int)> callback, | 167 static void RespondWithCountOnUIThread(base::Callback<void(int)> callback, |
165 int count) { | 168 int count) { |
166 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
167 callback.Run(count); | 170 callback.Run(count); |
168 } | 171 } |
169 | 172 |
170 static void RespondOnCallerThread(const AndroidUsbDevicesCallback& callback, | 173 static void RespondOnCallerThread(const AndroidUsbDevicesCallback& callback, |
171 const AndroidUsbDevices& devices) { | 174 AndroidUsbDevices* claimed_devices) { |
Vladislav Kaznacheev
2014/04/10 14:38:11
Unclear name (already claimed or newly claimed?)
pfeldman
2014/04/10 15:37:46
Done.
| |
172 callback.Run(devices); | 175 scoped_ptr<AndroidUsbDevices> devices(claimed_devices); |
176 | |
177 // Add raw pointers to the newly claimed devices. | |
178 for (AndroidUsbDevices::iterator it = devices->begin(); it != devices->end(); | |
179 ++it) { | |
180 g_devices.Get().push_back(*it); | |
181 } | |
182 | |
183 // Return all claimed devices. | |
184 AndroidUsbDevices result(g_devices.Get().begin(), g_devices.Get().end()); | |
185 callback.Run(result); | |
173 } | 186 } |
174 | 187 |
175 static void RespondOnFileThread( | 188 static void RespondOnFileThread( |
176 const AndroidUsbDevicesCallback& callback, | 189 const AndroidUsbDevicesCallback& callback, |
190 AndroidUsbDevices* devices, | |
177 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) { | 191 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) { |
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
179 // Copy g_devices.Get() on file thread. | |
180 caller_message_loop_proxy->PostTask( | 193 caller_message_loop_proxy->PostTask( |
181 FROM_HERE, | 194 FROM_HERE, |
182 base::Bind(&RespondOnCallerThread, callback, g_devices.Get())); | 195 base::Bind(&RespondOnCallerThread, callback, devices)); |
183 } | 196 } |
184 | 197 |
185 static void OpenAndroidDevicesOnFileThread( | 198 static void OpenAndroidDevicesOnFileThread( |
Vladislav Kaznacheev
2014/04/10 14:38:11
's' at the end of 'devices' seems out of place
pfeldman
2014/04/10 15:37:46
Done.
| |
199 AndroidUsbDevices* devices, | |
186 crypto::RSAPrivateKey* rsa_key, | 200 crypto::RSAPrivateKey* rsa_key, |
187 const base::Closure& barrier, | 201 const base::Closure& barrier, |
188 scoped_refptr<UsbDevice> device, | 202 scoped_refptr<UsbDevice> device, |
189 int interface_id, | 203 int interface_id, |
190 bool success) { | 204 bool success) { |
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
192 if (success) { | 206 if (success) { |
193 scoped_refptr<UsbConfigDescriptor> config = device->ListInterfaces(); | 207 scoped_refptr<UsbConfigDescriptor> config = device->ListInterfaces(); |
194 scoped_refptr<UsbDeviceHandle> usb_handle = device->Open(); | 208 scoped_refptr<UsbDeviceHandle> usb_handle = device->Open(); |
195 if (usb_handle) { | 209 if (usb_handle) { |
196 scoped_refptr<AndroidUsbDevice> device = | 210 scoped_refptr<AndroidUsbDevice> android_device = |
197 ClaimInterface(rsa_key, usb_handle, config->GetInterface(interface_id), | 211 ClaimInterface(rsa_key, usb_handle, config->GetInterface(interface_id), |
198 interface_id); | 212 interface_id); |
199 if (device.get()) | 213 if (android_device.get()) |
200 g_devices.Get().push_back(device); | 214 devices->push_back(android_device.get()); |
201 else | 215 else |
202 usb_handle->Close(); | 216 usb_handle->Close(); |
203 } | 217 } |
204 } | 218 } |
205 barrier.Run(); | 219 barrier.Run(); |
206 } | 220 } |
207 | 221 |
208 static void CountOnFileThread( | 222 static void CountOnFileThread( |
209 const base::Callback<void(int)>& callback) { | 223 const base::Callback<void(int)>& callback) { |
210 UsbService* service = UsbService::GetInstance(); | 224 UsbService* service = UsbService::GetInstance(); |
(...skipping 21 matching lines...) Expand all Loading... | |
232 crypto::RSAPrivateKey* rsa_key, | 246 crypto::RSAPrivateKey* rsa_key, |
233 const AndroidUsbDevicesCallback& callback, | 247 const AndroidUsbDevicesCallback& callback, |
234 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) { | 248 scoped_refptr<base::MessageLoopProxy> caller_message_loop_proxy) { |
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
236 | 250 |
237 UsbService* service = UsbService::GetInstance(); | 251 UsbService* service = UsbService::GetInstance(); |
238 UsbDevices usb_devices; | 252 UsbDevices usb_devices; |
239 if (service != NULL) | 253 if (service != NULL) |
240 service->GetDevices(&usb_devices); | 254 service->GetDevices(&usb_devices); |
241 | 255 |
242 AndroidUsbDevices& devices = g_devices.Get(); | |
243 | |
244 // GC Android devices with no actual usb device. | |
245 AndroidUsbDevices::iterator it = devices.begin(); | |
246 UsbDeviceSet claimed_devices; | |
247 while (it != devices.end()) { | |
248 bool found_device = false; | |
249 for (UsbDevices::iterator it2 = usb_devices.begin(); | |
250 it2 != usb_devices.end() && !found_device; ++it2) { | |
251 UsbDevice* usb_device = it2->get(); | |
252 AndroidUsbDevice* device = it->get(); | |
253 if (usb_device == device->usb_device()->device()) { | |
254 found_device = true; | |
255 claimed_devices.insert(usb_device); | |
256 } | |
257 } | |
258 | |
259 if (!found_device) | |
260 it = devices.erase(it); | |
261 else | |
262 ++it; | |
263 } | |
264 | |
265 // Add new devices. | 256 // Add new devices. |
257 AndroidUsbDevices* devices = new AndroidUsbDevices(); | |
266 base::Closure barrier = base::BarrierClosure( | 258 base::Closure barrier = base::BarrierClosure( |
267 usb_devices.size(), base::Bind(&RespondOnFileThread, | 259 usb_devices.size(), base::Bind(&RespondOnFileThread, |
268 callback, | 260 callback, |
261 devices, | |
Vladislav Kaznacheev
2014/04/10 14:38:11
I suggest using base::Owned for this parameter.
pfeldman
2014/04/10 15:37:46
Done.
| |
269 caller_message_loop_proxy)); | 262 caller_message_loop_proxy)); |
270 | 263 |
271 for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end(); | 264 for (UsbDevices::iterator it = usb_devices.begin(); it != usb_devices.end(); |
272 ++it) { | 265 ++it) { |
273 if (ContainsKey(claimed_devices, it->get())) { | |
274 barrier.Run(); | |
275 continue; | |
276 } | |
277 | |
278 scoped_refptr<UsbConfigDescriptor> config = (*it)->ListInterfaces(); | 266 scoped_refptr<UsbConfigDescriptor> config = (*it)->ListInterfaces(); |
279 if (!config) { | 267 if (!config) { |
280 barrier.Run(); | 268 barrier.Run(); |
281 continue; | 269 continue; |
282 } | 270 } |
283 | 271 |
284 bool has_android_interface = false; | 272 bool has_android_interface = false; |
285 for (size_t j = 0; j < config->GetNumInterfaces(); ++j) { | 273 for (size_t j = 0; j < config->GetNumInterfaces(); ++j) { |
286 if (!IsAndroidInterface(config->GetInterface(j))) | 274 if (!IsAndroidInterface(config->GetInterface(j))) |
287 continue; | 275 continue; |
288 | 276 |
289 // Request permission on Chrome OS. | 277 // Request permission on Chrome OS. |
290 #if defined(OS_CHROMEOS) | 278 #if defined(OS_CHROMEOS) |
291 (*it)->RequestUsbAcess(j, base::Bind(&OpenAndroidDevicesOnFileThread, | 279 (*it)->RequestUsbAcess(j, base::Bind(&OpenAndroidDevicesOnFileThread, |
292 rsa_key, barrier, *it, j)); | 280 devices, rsa_key, barrier, *it, j)); |
293 #else | 281 #else |
294 OpenAndroidDevicesOnFileThread(rsa_key, barrier, *it, j, true); | 282 OpenAndroidDevicesOnFileThread(devices, rsa_key, barrier, *it, j, true); |
295 #endif // defined(OS_CHROMEOS) | 283 #endif // defined(OS_CHROMEOS) |
296 | 284 |
297 has_android_interface = true; | 285 has_android_interface = true; |
298 break; | 286 break; |
299 } | 287 } |
300 if (!has_android_interface) | 288 if (!has_android_interface) |
301 barrier.Run(); | 289 barrier.Run(); |
302 } | 290 } |
303 } | 291 } |
304 | 292 |
305 // static | 293 // static |
306 void AndroidUsbDevice::CountDevices( | 294 void AndroidUsbDevice::CountDevices( |
307 const base::Callback<void(int)>& callback) { | 295 const base::Callback<void(int)>& callback) { |
308 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 296 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
309 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 297 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
310 base::Bind(&CountOnFileThread, callback)); | 298 base::Bind(&CountOnFileThread, callback)); |
311 } | 299 } |
312 | 300 |
313 // static | 301 // static |
314 void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key, | 302 void AndroidUsbDevice::Enumerate(crypto::RSAPrivateKey* rsa_key, |
315 const AndroidUsbDevicesCallback& callback) { | 303 const AndroidUsbDevicesCallback& callback) { |
304 | |
305 // Collect devices with closed handles. | |
306 for (std::vector<AndroidUsbDevice*>::iterator it = g_devices.Get().begin(); | |
307 it != g_devices.Get().end(); ++it) { | |
308 if (!(*it)->terminated_) { | |
Vladislav Kaznacheev
2014/04/10 14:38:11
AndroidUsbDevice::terminated() exists (but not use
pfeldman
2014/04/10 15:37:46
Done.
| |
309 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
310 base::Bind(&AndroidUsbDevice::TerminateIfReleased, *it)); | |
311 } | |
312 } | |
313 | |
314 // Then look for the new devices. | |
316 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 315 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
317 base::Bind(&EnumerateOnFileThread, rsa_key, callback, | 316 base::Bind(&EnumerateOnFileThread, rsa_key, callback, |
318 base::MessageLoopProxy::current())); | 317 base::MessageLoopProxy::current())); |
319 } | 318 } |
320 | 319 |
321 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key, | 320 AndroidUsbDevice::AndroidUsbDevice(crypto::RSAPrivateKey* rsa_key, |
322 scoped_refptr<UsbDeviceHandle> usb_device, | 321 scoped_refptr<UsbDeviceHandle> usb_device, |
323 const std::string& serial, | 322 const std::string& serial, |
324 int inbound_address, | 323 int inbound_address, |
325 int outbound_address, | 324 int outbound_address, |
326 int zero_mask) | 325 int zero_mask, |
326 int interface_id) | |
327 : message_loop_(NULL), | 327 : message_loop_(NULL), |
328 rsa_key_(rsa_key->Copy()), | 328 rsa_key_(rsa_key->Copy()), |
329 usb_device_(usb_device), | 329 usb_device_(usb_device), |
330 serial_(serial), | 330 serial_(serial), |
331 inbound_address_(inbound_address), | 331 inbound_address_(inbound_address), |
332 outbound_address_(outbound_address), | 332 outbound_address_(outbound_address), |
333 zero_mask_(zero_mask), | 333 zero_mask_(zero_mask), |
334 interface_id_(interface_id), | |
334 is_connected_(false), | 335 is_connected_(false), |
335 signature_sent_(false), | 336 signature_sent_(false), |
336 last_socket_id_(256), | 337 last_socket_id_(256), |
337 terminated_(false) { | 338 terminated_(false), |
339 weak_factory_(this) { | |
338 } | 340 } |
339 | 341 |
340 void AndroidUsbDevice::InitOnCallerThread() { | 342 void AndroidUsbDevice::InitOnCallerThread() { |
341 if (message_loop_) | 343 if (message_loop_) |
342 return; | 344 return; |
343 message_loop_ = base::MessageLoop::current(); | 345 message_loop_ = base::MessageLoop::current(); |
344 Queue(new AdbMessage(AdbMessage::kCommandCNXN, kVersion, kMaxPayload, | 346 Queue(new AdbMessage(AdbMessage::kCommandCNXN, kVersion, kMaxPayload, |
345 kHostConnectMessage)); | 347 kHostConnectMessage)); |
346 ReadHeader(true); | 348 ReadHeader(); |
347 } | 349 } |
348 | 350 |
349 net::StreamSocket* AndroidUsbDevice::CreateSocket(const std::string& command) { | 351 net::StreamSocket* AndroidUsbDevice::CreateSocket(const std::string& command) { |
352 if (terminated_) | |
353 return NULL; | |
354 | |
350 uint32 socket_id = ++last_socket_id_; | 355 uint32 socket_id = ++last_socket_id_; |
351 sockets_[socket_id] = new AndroidUsbSocket(this, socket_id, command, | 356 sockets_[socket_id] = new AndroidUsbSocket(this, socket_id, command, |
352 base::Bind(&AndroidUsbDevice::SocketDeleted, this)); | 357 base::Bind(&AndroidUsbDevice::SocketDeleted, this)); |
353 return sockets_[socket_id]; | 358 return sockets_[socket_id]; |
354 } | 359 } |
355 | 360 |
356 void AndroidUsbDevice::Send(uint32 command, | 361 void AndroidUsbDevice::Send(uint32 command, |
357 uint32 arg0, | 362 uint32 arg0, |
358 uint32 arg1, | 363 uint32 arg1, |
359 const std::string& body) { | 364 const std::string& body) { |
360 scoped_refptr<AdbMessage> m = new AdbMessage(command, arg0, arg1, body); | 365 scoped_refptr<AdbMessage> m = new AdbMessage(command, arg0, arg1, body); |
361 // Delay open request if not yet connected. | 366 // Delay open request if not yet connected. |
362 if (!is_connected_) { | 367 if (!is_connected_) { |
363 pending_messages_.push_back(m); | 368 pending_messages_.push_back(m); |
364 return; | 369 return; |
365 } | 370 } |
366 Queue(m); | 371 Queue(m); |
367 } | 372 } |
368 | 373 |
369 AndroidUsbDevice::~AndroidUsbDevice() { | 374 AndroidUsbDevice::~AndroidUsbDevice() { |
370 Terminate(); | 375 Terminate(); |
371 usb_device_->AddRef(); | |
372 BrowserThread::ReleaseSoon(BrowserThread::FILE, FROM_HERE, | |
373 usb_device_.get()); | |
374 } | 376 } |
375 | 377 |
376 void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) { | 378 void AndroidUsbDevice::Queue(scoped_refptr<AdbMessage> message) { |
377 // Queue header. | 379 // Queue header. |
378 std::vector<uint32> header; | 380 std::vector<uint32> header; |
379 header.push_back(message->command); | 381 header.push_back(message->command); |
380 header.push_back(message->arg0); | 382 header.push_back(message->arg0); |
381 header.push_back(message->arg1); | 383 header.push_back(message->arg1); |
382 bool append_zero = true; | 384 bool append_zero = true; |
383 if (message->body.empty()) | 385 if (message->body.empty()) |
(...skipping 29 matching lines...) Expand all Loading... | |
413 | 415 |
414 void AndroidUsbDevice::ProcessOutgoing() { | 416 void AndroidUsbDevice::ProcessOutgoing() { |
415 if (outgoing_queue_.empty() || terminated_) | 417 if (outgoing_queue_.empty() || terminated_) |
416 return; | 418 return; |
417 | 419 |
418 BulkMessage message = outgoing_queue_.front(); | 420 BulkMessage message = outgoing_queue_.front(); |
419 outgoing_queue_.pop(); | 421 outgoing_queue_.pop(); |
420 DumpMessage(true, message.first->data(), message.second); | 422 DumpMessage(true, message.first->data(), message.second); |
421 usb_device_->BulkTransfer(USB_DIRECTION_OUTBOUND, outbound_address_, | 423 usb_device_->BulkTransfer(USB_DIRECTION_OUTBOUND, outbound_address_, |
422 message.first, message.second, kUsbTimeout, | 424 message.first, message.second, kUsbTimeout, |
423 base::Bind(&AndroidUsbDevice::OutgoingMessageSent, this)); | 425 base::Bind(&AndroidUsbDevice::OutgoingMessageSent, |
426 weak_factory_.GetWeakPtr())); | |
424 } | 427 } |
425 | 428 |
426 void AndroidUsbDevice::OutgoingMessageSent(UsbTransferStatus status, | 429 void AndroidUsbDevice::OutgoingMessageSent(UsbTransferStatus status, |
427 scoped_refptr<net::IOBuffer> buffer, | 430 scoped_refptr<net::IOBuffer> buffer, |
428 size_t result) { | 431 size_t result) { |
429 if (status != USB_TRANSFER_COMPLETED) | 432 if (status != USB_TRANSFER_COMPLETED) |
430 return; | 433 return; |
431 message_loop_->PostTask(FROM_HERE, | 434 message_loop_->PostTask(FROM_HERE, |
432 base::Bind(&AndroidUsbDevice::ProcessOutgoing, | 435 base::Bind(&AndroidUsbDevice::ProcessOutgoing, this)); |
433 this)); | |
434 } | 436 } |
435 | 437 |
436 void AndroidUsbDevice::ReadHeader(bool initial) { | 438 void AndroidUsbDevice::ReadHeader() { |
437 if (terminated_) | 439 if (terminated_) |
438 return; | 440 return; |
439 if (!initial && HasOneRef()) | |
440 return; // Stop polling. | |
441 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kHeaderSize); | 441 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kHeaderSize); |
442 usb_device_->BulkTransfer(USB_DIRECTION_INBOUND, inbound_address_, | 442 usb_device_->BulkTransfer(USB_DIRECTION_INBOUND, inbound_address_, |
443 buffer, kHeaderSize, kUsbTimeout, | 443 buffer, kHeaderSize, kUsbTimeout, |
444 base::Bind(&AndroidUsbDevice::ParseHeader, this)); | 444 base::Bind(&AndroidUsbDevice::ParseHeader, |
445 weak_factory_.GetWeakPtr())); | |
445 } | 446 } |
446 | 447 |
447 void AndroidUsbDevice::ParseHeader(UsbTransferStatus status, | 448 void AndroidUsbDevice::ParseHeader(UsbTransferStatus status, |
448 scoped_refptr<net::IOBuffer> buffer, | 449 scoped_refptr<net::IOBuffer> buffer, |
449 size_t result) { | 450 size_t result) { |
450 if (status == USB_TRANSFER_TIMEOUT) { | 451 if (status == USB_TRANSFER_TIMEOUT) { |
451 message_loop_->PostTask(FROM_HERE, | 452 message_loop_->PostTask(FROM_HERE, |
452 base::Bind(&AndroidUsbDevice::ReadHeader, this, | 453 base::Bind(&AndroidUsbDevice::ReadHeader, this)); |
453 false)); | |
454 return; | 454 return; |
455 } | 455 } |
456 | 456 |
457 if (status != USB_TRANSFER_COMPLETED || result != kHeaderSize) { | 457 if (status != USB_TRANSFER_COMPLETED || result != kHeaderSize) { |
458 TransferError(status); | 458 TransferError(status); |
459 return; | 459 return; |
460 } | 460 } |
461 | 461 |
462 DumpMessage(false, buffer->data(), result); | 462 DumpMessage(false, buffer->data(), result); |
463 std::vector<uint32> header(6); | 463 std::vector<uint32> header(6); |
(...skipping 16 matching lines...) Expand all Loading... | |
480 } | 480 } |
481 | 481 |
482 message_loop_->PostTask(FROM_HERE, | 482 message_loop_->PostTask(FROM_HERE, |
483 base::Bind(&AndroidUsbDevice::ReadBody, this, | 483 base::Bind(&AndroidUsbDevice::ReadBody, this, |
484 message, data_length, data_check)); | 484 message, data_length, data_check)); |
485 } | 485 } |
486 | 486 |
487 void AndroidUsbDevice::ReadBody(scoped_refptr<AdbMessage> message, | 487 void AndroidUsbDevice::ReadBody(scoped_refptr<AdbMessage> message, |
488 uint32 data_length, | 488 uint32 data_length, |
489 uint32 data_check) { | 489 uint32 data_check) { |
490 if (terminated_) | |
491 return; | |
490 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_length); | 492 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_length); |
491 usb_device_->BulkTransfer(USB_DIRECTION_INBOUND, inbound_address_, | 493 usb_device_->BulkTransfer(USB_DIRECTION_INBOUND, inbound_address_, |
492 buffer, data_length, kUsbTimeout, | 494 buffer, data_length, kUsbTimeout, |
493 base::Bind(&AndroidUsbDevice::ParseBody, this, message, data_length, | 495 base::Bind(&AndroidUsbDevice::ParseBody, weak_factory_.GetWeakPtr(), |
494 data_check)); | 496 message, data_length, data_check)); |
495 } | 497 } |
496 | 498 |
497 void AndroidUsbDevice::ParseBody(scoped_refptr<AdbMessage> message, | 499 void AndroidUsbDevice::ParseBody(scoped_refptr<AdbMessage> message, |
498 uint32 data_length, | 500 uint32 data_length, |
499 uint32 data_check, | 501 uint32 data_check, |
500 UsbTransferStatus status, | 502 UsbTransferStatus status, |
501 scoped_refptr<net::IOBuffer> buffer, | 503 scoped_refptr<net::IOBuffer> buffer, |
502 size_t result) { | 504 size_t result) { |
503 if (status == USB_TRANSFER_TIMEOUT) { | 505 if (status == USB_TRANSFER_TIMEOUT) { |
504 message_loop_->PostTask(FROM_HERE, | 506 message_loop_->PostTask(FROM_HERE, |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
565 case AdbMessage::kCommandCLSE: | 567 case AdbMessage::kCommandCLSE: |
566 { | 568 { |
567 AndroidUsbSockets::iterator it = sockets_.find(message->arg1); | 569 AndroidUsbSockets::iterator it = sockets_.find(message->arg1); |
568 if (it != sockets_.end()) | 570 if (it != sockets_.end()) |
569 it->second->HandleIncoming(message); | 571 it->second->HandleIncoming(message); |
570 } | 572 } |
571 break; | 573 break; |
572 default: | 574 default: |
573 break; | 575 break; |
574 } | 576 } |
575 ReadHeader(false); | 577 ReadHeader(); |
576 } | 578 } |
577 | 579 |
578 void AndroidUsbDevice::TransferError(UsbTransferStatus status) { | 580 void AndroidUsbDevice::TransferError(UsbTransferStatus status) { |
579 message_loop_->PostTask(FROM_HERE, | 581 message_loop_->PostTask(FROM_HERE, |
580 base::Bind(&AndroidUsbDevice::Terminate, | 582 base::Bind(&AndroidUsbDevice::Terminate, this)); |
581 this)); | 583 } |
584 | |
585 void AndroidUsbDevice::TerminateIfReleased() { | |
586 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
587 if (usb_device_->device()) | |
Vladislav Kaznacheev
2014/04/10 14:38:11
usb_device_ pointer can be set to NULL by a differ
pfeldman
2014/04/10 15:37:46
Done.
| |
588 return; | |
589 message_loop_->PostTask(FROM_HERE, | |
590 base::Bind(&AndroidUsbDevice::Terminate, this)); | |
582 } | 591 } |
583 | 592 |
584 void AndroidUsbDevice::Terminate() { | 593 void AndroidUsbDevice::Terminate() { |
594 std::vector<AndroidUsbDevice*>::iterator it = | |
595 std::find(g_devices.Get().begin(), g_devices.Get().end(), this); | |
596 if (it != g_devices.Get().end()) | |
597 g_devices.Get().erase(it); | |
598 | |
585 if (terminated_) | 599 if (terminated_) |
586 return; | 600 return; |
587 | 601 |
588 terminated_ = true; | 602 terminated_ = true; |
Vladislav Kaznacheev
2014/04/10 14:38:11
terminated_ is always in sync with !usb_device_. D
pfeldman
2014/04/10 15:37:46
Done.
| |
589 | 603 |
590 // Iterate over copy. | 604 // Iterate over copy. |
591 AndroidUsbSockets sockets(sockets_); | 605 AndroidUsbSockets sockets(sockets_); |
592 for (AndroidUsbSockets::iterator it = sockets.begin(); | 606 for (AndroidUsbSockets::iterator it = sockets.begin(); |
593 it != sockets.end(); ++it) { | 607 it != sockets.end(); ++it) { |
594 it->second->Terminated(); | 608 it->second->Terminated(); |
595 } | 609 } |
610 DCHECK(sockets_.empty()); | |
596 | 611 |
597 BrowserThread::PostTask( | 612 BrowserThread::PostTask( |
598 BrowserThread::FILE, FROM_HERE, | 613 BrowserThread::FILE, FROM_HERE, |
599 base::Bind(&ReleaseInterface, usb_device_)); | 614 base::Bind(&ReleaseInterface, usb_device_, interface_id_)); |
615 usb_device_ = NULL; | |
600 } | 616 } |
601 | 617 |
602 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) { | 618 void AndroidUsbDevice::SocketDeleted(uint32 socket_id) { |
603 sockets_.erase(socket_id); | 619 sockets_.erase(socket_id); |
604 } | 620 } |
OLD | NEW |