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

Side by Side Diff: device/bluetooth/bluetooth_device_chromeos.cc

Issue 1367663002: Add Linux support for the Bluetooth API. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor_dbus
Patch Set: rebase Created 5 years, 2 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
OLDNEW
(Empty)
1 // Copyright 2013 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 "device/bluetooth/bluetooth_device_chromeos.h"
6
7 #include <stdio.h>
8
9 #include "base/bind.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/metrics/histogram.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h"
14 #include "dbus/bus.h"
15 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
16 #include "device/bluetooth/bluetooth_gatt_connection_chromeos.h"
17 #include "device/bluetooth/bluetooth_pairing_chromeos.h"
18 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
19 #include "device/bluetooth/bluetooth_socket.h"
20 #include "device/bluetooth/bluetooth_socket_chromeos.h"
21 #include "device/bluetooth/bluetooth_socket_thread.h"
22 #include "device/bluetooth/bluetooth_uuid.h"
23 #include "device/bluetooth/dbus/bluetooth_adapter_client.h"
24 #include "device/bluetooth/dbus/bluetooth_device_client.h"
25 #include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
26 #include "device/bluetooth/dbus/bluetooth_input_client.h"
27 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
28 #include "third_party/cros_system_api/dbus/service_constants.h"
29
30 using device::BluetoothDevice;
31 using device::BluetoothSocket;
32 using device::BluetoothUUID;
33
34 namespace {
35
36 // Histogram enumerations for pairing results.
37 enum UMAPairingResult {
38 UMA_PAIRING_RESULT_SUCCESS,
39 UMA_PAIRING_RESULT_INPROGRESS,
40 UMA_PAIRING_RESULT_FAILED,
41 UMA_PAIRING_RESULT_AUTH_FAILED,
42 UMA_PAIRING_RESULT_AUTH_CANCELED,
43 UMA_PAIRING_RESULT_AUTH_REJECTED,
44 UMA_PAIRING_RESULT_AUTH_TIMEOUT,
45 UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE,
46 UMA_PAIRING_RESULT_UNKNOWN_ERROR,
47 // NOTE: Add new pairing results immediately above this line. Make sure to
48 // update the enum list in tools/histogram/histograms.xml accordinly.
49 UMA_PAIRING_RESULT_COUNT
50 };
51
52 void ParseModalias(const dbus::ObjectPath& object_path,
53 BluetoothDevice::VendorIDSource* vendor_id_source,
54 uint16* vendor_id,
55 uint16* product_id,
56 uint16* device_id) {
57 bluez::BluetoothDeviceClient::Properties* properties =
58 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
59 object_path);
60 DCHECK(properties);
61
62 std::string modalias = properties->modalias.value();
63 BluetoothDevice::VendorIDSource source_value;
64 int vendor_value, product_value, device_value;
65
66 if (sscanf(modalias.c_str(), "bluetooth:v%04xp%04xd%04x",
67 &vendor_value, &product_value, &device_value) == 3) {
68 source_value = BluetoothDevice::VENDOR_ID_BLUETOOTH;
69 } else if (sscanf(modalias.c_str(), "usb:v%04xp%04xd%04x",
70 &vendor_value, &product_value, &device_value) == 3) {
71 source_value = BluetoothDevice::VENDOR_ID_USB;
72 } else {
73 return;
74 }
75
76 if (vendor_id_source != NULL)
77 *vendor_id_source = source_value;
78 if (vendor_id != NULL)
79 *vendor_id = vendor_value;
80 if (product_id != NULL)
81 *product_id = product_value;
82 if (device_id != NULL)
83 *device_id = device_value;
84 }
85
86 void RecordPairingResult(BluetoothDevice::ConnectErrorCode error_code) {
87 UMAPairingResult pairing_result;
88 switch (error_code) {
89 case BluetoothDevice::ERROR_INPROGRESS:
90 pairing_result = UMA_PAIRING_RESULT_INPROGRESS;
91 break;
92 case BluetoothDevice::ERROR_FAILED:
93 pairing_result = UMA_PAIRING_RESULT_FAILED;
94 break;
95 case BluetoothDevice::ERROR_AUTH_FAILED:
96 pairing_result = UMA_PAIRING_RESULT_AUTH_FAILED;
97 break;
98 case BluetoothDevice::ERROR_AUTH_CANCELED:
99 pairing_result = UMA_PAIRING_RESULT_AUTH_CANCELED;
100 break;
101 case BluetoothDevice::ERROR_AUTH_REJECTED:
102 pairing_result = UMA_PAIRING_RESULT_AUTH_REJECTED;
103 break;
104 case BluetoothDevice::ERROR_AUTH_TIMEOUT:
105 pairing_result = UMA_PAIRING_RESULT_AUTH_TIMEOUT;
106 break;
107 case BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
108 pairing_result = UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE;
109 break;
110 default:
111 pairing_result = UMA_PAIRING_RESULT_UNKNOWN_ERROR;
112 }
113
114 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult",
115 pairing_result,
116 UMA_PAIRING_RESULT_COUNT);
117 }
118
119 } // namespace
120
121 namespace chromeos {
122
123 BluetoothDeviceChromeOS::BluetoothDeviceChromeOS(
124 BluetoothAdapterChromeOS* adapter,
125 const dbus::ObjectPath& object_path,
126 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
127 scoped_refptr<device::BluetoothSocketThread> socket_thread)
128 : BluetoothDevice(adapter),
129 object_path_(object_path),
130 num_connecting_calls_(0),
131 connection_monitor_started_(false),
132 ui_task_runner_(ui_task_runner),
133 socket_thread_(socket_thread),
134 weak_ptr_factory_(this) {
135 bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver(
136 this);
137
138 // Add all known GATT services.
139 const std::vector<dbus::ObjectPath> gatt_services =
140 bluez::BluezDBusManager::Get()
141 ->GetBluetoothGattServiceClient()
142 ->GetServices();
143 for (std::vector<dbus::ObjectPath>::const_iterator it = gatt_services.begin();
144 it != gatt_services.end(); ++it) {
145 GattServiceAdded(*it);
146 }
147 }
148
149 BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() {
150 bluez::BluezDBusManager::Get()
151 ->GetBluetoothGattServiceClient()
152 ->RemoveObserver(this);
153
154 // Copy the GATT services list here and clear the original so that when we
155 // send GattServiceRemoved(), GetGattServices() returns no services.
156 GattServiceMap gatt_services = gatt_services_;
157 gatt_services_.clear();
158 for (GattServiceMap::iterator iter = gatt_services.begin();
159 iter != gatt_services.end(); ++iter) {
160 DCHECK(adapter_);
161 adapter()->NotifyGattServiceRemoved(
162 static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second));
163 delete iter->second;
164 }
165 }
166
167 uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const {
168 bluez::BluetoothDeviceClient::Properties* properties =
169 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
170 object_path_);
171 DCHECK(properties);
172
173 return properties->bluetooth_class.value();
174 }
175
176 std::string BluetoothDeviceChromeOS::GetDeviceName() const {
177 bluez::BluetoothDeviceClient::Properties* properties =
178 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
179 object_path_);
180 DCHECK(properties);
181
182 return properties->alias.value();
183 }
184
185 void BluetoothDeviceChromeOS::CreateGattConnectionImpl() {
186 // ChromeOS implementation does not use the default CreateGattConnection
187 // implementation.
188 NOTIMPLEMENTED();
189 }
190
191 void BluetoothDeviceChromeOS::DisconnectGatt() {
192 // ChromeOS implementation does not use the default CreateGattConnection
193 // implementation.
194 NOTIMPLEMENTED();
195 }
196
197 std::string BluetoothDeviceChromeOS::GetAddress() const {
198 bluez::BluetoothDeviceClient::Properties* properties =
199 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
200 object_path_);
201 DCHECK(properties);
202
203 return CanonicalizeAddress(properties->address.value());
204 }
205
206 BluetoothDevice::VendorIDSource
207 BluetoothDeviceChromeOS::GetVendorIDSource() const {
208 VendorIDSource vendor_id_source = VENDOR_ID_UNKNOWN;
209 ParseModalias(object_path_, &vendor_id_source, NULL, NULL, NULL);
210 return vendor_id_source;
211 }
212
213 uint16 BluetoothDeviceChromeOS::GetVendorID() const {
214 uint16 vendor_id = 0;
215 ParseModalias(object_path_, NULL, &vendor_id, NULL, NULL);
216 return vendor_id;
217 }
218
219 uint16 BluetoothDeviceChromeOS::GetProductID() const {
220 uint16 product_id = 0;
221 ParseModalias(object_path_, NULL, NULL, &product_id, NULL);
222 return product_id;
223 }
224
225 uint16 BluetoothDeviceChromeOS::GetDeviceID() const {
226 uint16 device_id = 0;
227 ParseModalias(object_path_, NULL, NULL, NULL, &device_id);
228 return device_id;
229 }
230
231 bool BluetoothDeviceChromeOS::IsPaired() const {
232 bluez::BluetoothDeviceClient::Properties* properties =
233 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
234 object_path_);
235 DCHECK(properties);
236
237 // Trusted devices are devices that don't support pairing but that the
238 // user has explicitly connected; it makes no sense for UI purposes to
239 // treat them differently from each other.
240 return properties->paired.value() || properties->trusted.value();
241 }
242
243 bool BluetoothDeviceChromeOS::IsConnected() const {
244 bluez::BluetoothDeviceClient::Properties* properties =
245 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
246 object_path_);
247 DCHECK(properties);
248
249 return properties->connected.value();
250 }
251
252 bool BluetoothDeviceChromeOS::IsGattConnected() const {
253 NOTIMPLEMENTED();
254 return false;
255 }
256
257 bool BluetoothDeviceChromeOS::IsConnectable() const {
258 bluez::BluetoothInputClient::Properties* input_properties =
259 bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->GetProperties(
260 object_path_);
261 // GetProperties returns NULL when the device does not implement the given
262 // interface. Non HID devices are normally connectable.
263 if (!input_properties)
264 return true;
265
266 return input_properties->reconnect_mode.value() != "device";
267 }
268
269 bool BluetoothDeviceChromeOS::IsConnecting() const {
270 return num_connecting_calls_ > 0;
271 }
272
273 BluetoothDeviceChromeOS::UUIDList BluetoothDeviceChromeOS::GetUUIDs() const {
274 bluez::BluetoothDeviceClient::Properties* properties =
275 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
276 object_path_);
277 DCHECK(properties);
278
279 std::vector<device::BluetoothUUID> uuids;
280 const std::vector<std::string> &dbus_uuids = properties->uuids.value();
281 for (std::vector<std::string>::const_iterator iter = dbus_uuids.begin();
282 iter != dbus_uuids.end(); ++iter) {
283 device::BluetoothUUID uuid(*iter);
284 DCHECK(uuid.IsValid());
285 uuids.push_back(uuid);
286 }
287 return uuids;
288 }
289
290 int16 BluetoothDeviceChromeOS::GetInquiryRSSI() const {
291 bluez::BluetoothDeviceClient::Properties* properties =
292 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
293 object_path_);
294 DCHECK(properties);
295
296 if (!properties->rssi.is_valid())
297 return kUnknownPower;
298
299 return properties->rssi.value();
300 }
301
302 int16 BluetoothDeviceChromeOS::GetInquiryTxPower() const {
303 bluez::BluetoothDeviceClient::Properties* properties =
304 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
305 object_path_);
306 DCHECK(properties);
307
308 if (!properties->tx_power.is_valid())
309 return kUnknownPower;
310
311 return properties->tx_power.value();
312 }
313
314 bool BluetoothDeviceChromeOS::ExpectingPinCode() const {
315 return pairing_.get() && pairing_->ExpectingPinCode();
316 }
317
318 bool BluetoothDeviceChromeOS::ExpectingPasskey() const {
319 return pairing_.get() && pairing_->ExpectingPasskey();
320 }
321
322 bool BluetoothDeviceChromeOS::ExpectingConfirmation() const {
323 return pairing_.get() && pairing_->ExpectingConfirmation();
324 }
325
326 void BluetoothDeviceChromeOS::GetConnectionInfo(
327 const ConnectionInfoCallback& callback) {
328 // DBus method call should gracefully return an error if the device is not
329 // currently connected.
330 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetConnInfo(
331 object_path_, base::Bind(&BluetoothDeviceChromeOS::OnGetConnInfo,
332 weak_ptr_factory_.GetWeakPtr(), callback),
333 base::Bind(&BluetoothDeviceChromeOS::OnGetConnInfoError,
334 weak_ptr_factory_.GetWeakPtr(), callback));
335 }
336
337 void BluetoothDeviceChromeOS::Connect(
338 BluetoothDevice::PairingDelegate* pairing_delegate,
339 const base::Closure& callback,
340 const ConnectErrorCallback& error_callback) {
341 if (num_connecting_calls_++ == 0)
342 adapter()->NotifyDeviceChanged(this);
343
344 VLOG(1) << object_path_.value() << ": Connecting, " << num_connecting_calls_
345 << " in progress";
346
347 if (IsPaired() || !pairing_delegate || !IsPairable()) {
348 // No need to pair, or unable to, skip straight to connection.
349 ConnectInternal(false, callback, error_callback);
350 } else {
351 // Initiate high-security connection with pairing.
352 BeginPairing(pairing_delegate);
353
354 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Pair(
355 object_path_,
356 base::Bind(&BluetoothDeviceChromeOS::OnPair,
357 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
358 base::Bind(&BluetoothDeviceChromeOS::OnPairError,
359 weak_ptr_factory_.GetWeakPtr(), error_callback));
360 }
361 }
362
363 void BluetoothDeviceChromeOS::SetPinCode(const std::string& pincode) {
364 if (!pairing_.get())
365 return;
366
367 pairing_->SetPinCode(pincode);
368 }
369
370 void BluetoothDeviceChromeOS::SetPasskey(uint32 passkey) {
371 if (!pairing_.get())
372 return;
373
374 pairing_->SetPasskey(passkey);
375 }
376
377 void BluetoothDeviceChromeOS::ConfirmPairing() {
378 if (!pairing_.get())
379 return;
380
381 pairing_->ConfirmPairing();
382 }
383
384 void BluetoothDeviceChromeOS::RejectPairing() {
385 if (!pairing_.get())
386 return;
387
388 pairing_->RejectPairing();
389 }
390
391 void BluetoothDeviceChromeOS::CancelPairing() {
392 bool canceled = false;
393
394 // If there is a callback in progress that we can reply to then use that
395 // to cancel the current pairing request.
396 if (pairing_.get() && pairing_->CancelPairing())
397 canceled = true;
398
399 // If not we have to send an explicit CancelPairing() to the device instead.
400 if (!canceled) {
401 VLOG(1) << object_path_.value() << ": No pairing context or callback. "
402 << "Sending explicit cancel";
403 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->CancelPairing(
404 object_path_, base::Bind(&base::DoNothing),
405 base::Bind(&BluetoothDeviceChromeOS::OnCancelPairingError,
406 weak_ptr_factory_.GetWeakPtr()));
407 }
408
409 // Since there is no callback to this method it's possible that the pairing
410 // delegate is going to be freed before things complete (indeed it's
411 // documented that this is the method you should call while freeing the
412 // pairing delegate), so clear our the context holding on to it.
413 EndPairing();
414 }
415
416 void BluetoothDeviceChromeOS::Disconnect(const base::Closure& callback,
417 const ErrorCallback& error_callback) {
418 VLOG(1) << object_path_.value() << ": Disconnecting";
419 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Disconnect(
420 object_path_, base::Bind(&BluetoothDeviceChromeOS::OnDisconnect,
421 weak_ptr_factory_.GetWeakPtr(), callback),
422 base::Bind(&BluetoothDeviceChromeOS::OnDisconnectError,
423 weak_ptr_factory_.GetWeakPtr(), error_callback));
424 }
425
426 void BluetoothDeviceChromeOS::Forget(const ErrorCallback& error_callback) {
427 VLOG(1) << object_path_.value() << ": Removing device";
428 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->RemoveDevice(
429 adapter()->object_path(), object_path_, base::Bind(&base::DoNothing),
430 base::Bind(&BluetoothDeviceChromeOS::OnForgetError,
431 weak_ptr_factory_.GetWeakPtr(), error_callback));
432 }
433
434 void BluetoothDeviceChromeOS::ConnectToService(
435 const BluetoothUUID& uuid,
436 const ConnectToServiceCallback& callback,
437 const ConnectToServiceErrorCallback& error_callback) {
438 VLOG(1) << object_path_.value() << ": Connecting to service: "
439 << uuid.canonical_value();
440 scoped_refptr<BluetoothSocketChromeOS> socket =
441 BluetoothSocketChromeOS::CreateBluetoothSocket(
442 ui_task_runner_, socket_thread_);
443 socket->Connect(this, uuid, BluetoothSocketChromeOS::SECURITY_LEVEL_MEDIUM,
444 base::Bind(callback, socket), error_callback);
445 }
446
447 void BluetoothDeviceChromeOS::ConnectToServiceInsecurely(
448 const BluetoothUUID& uuid,
449 const ConnectToServiceCallback& callback,
450 const ConnectToServiceErrorCallback& error_callback) {
451 VLOG(1) << object_path_.value() << ": Connecting insecurely to service: "
452 << uuid.canonical_value();
453 scoped_refptr<BluetoothSocketChromeOS> socket =
454 BluetoothSocketChromeOS::CreateBluetoothSocket(
455 ui_task_runner_, socket_thread_);
456 socket->Connect(this, uuid, BluetoothSocketChromeOS::SECURITY_LEVEL_LOW,
457 base::Bind(callback, socket), error_callback);
458 }
459
460 void BluetoothDeviceChromeOS::CreateGattConnection(
461 const GattConnectionCallback& callback,
462 const ConnectErrorCallback& error_callback) {
463 // TODO(sacomoto): Workaround to retrieve the connection for already connected
464 // devices. Currently, BluetoothGattConnection::Disconnect doesn't do
465 // anything, the unique underlying physical GATT connection is kept. This
466 // should be removed once the correct behavour is implemented and the GATT
467 // connections are reference counted (see todo below).
468 if (IsConnected()) {
469 OnCreateGattConnection(callback);
470 return;
471 }
472
473 // TODO(armansito): Until there is a way to create a reference counted GATT
474 // connection in bluetoothd, simply do a regular connect.
475 Connect(NULL,
476 base::Bind(&BluetoothDeviceChromeOS::OnCreateGattConnection,
477 weak_ptr_factory_.GetWeakPtr(),
478 callback),
479 error_callback);
480 }
481
482 BluetoothPairingChromeOS* BluetoothDeviceChromeOS::BeginPairing(
483 BluetoothDevice::PairingDelegate* pairing_delegate) {
484 pairing_.reset(new BluetoothPairingChromeOS(this, pairing_delegate));
485 return pairing_.get();
486 }
487
488 void BluetoothDeviceChromeOS::EndPairing() {
489 pairing_.reset();
490 }
491
492 BluetoothPairingChromeOS* BluetoothDeviceChromeOS::GetPairing() const {
493 return pairing_.get();
494 }
495
496 BluetoothAdapterChromeOS* BluetoothDeviceChromeOS::adapter() const {
497 return static_cast<BluetoothAdapterChromeOS*>(adapter_);
498 }
499
500 void BluetoothDeviceChromeOS::GattServiceAdded(
501 const dbus::ObjectPath& object_path) {
502 if (GetGattService(object_path.value())) {
503 VLOG(1) << "Remote GATT service already exists: " << object_path.value();
504 return;
505 }
506
507 bluez::BluetoothGattServiceClient::Properties* properties =
508 bluez::BluezDBusManager::Get()
509 ->GetBluetoothGattServiceClient()
510 ->GetProperties(object_path);
511 DCHECK(properties);
512 if (properties->device.value() != object_path_) {
513 VLOG(2) << "Remote GATT service does not belong to this device.";
514 return;
515 }
516
517 VLOG(1) << "Adding new remote GATT service for device: " << GetAddress();
518
519 BluetoothRemoteGattServiceChromeOS* service =
520 new BluetoothRemoteGattServiceChromeOS(adapter(), this, object_path);
521
522 gatt_services_[service->GetIdentifier()] = service;
523 DCHECK(service->object_path() == object_path);
524 DCHECK(service->GetUUID().IsValid());
525
526 DCHECK(adapter_);
527 adapter()->NotifyGattServiceAdded(service);
528 }
529
530 void BluetoothDeviceChromeOS::GattServiceRemoved(
531 const dbus::ObjectPath& object_path) {
532 GattServiceMap::iterator iter = gatt_services_.find(object_path.value());
533 if (iter == gatt_services_.end()) {
534 VLOG(3) << "Unknown GATT service removed: " << object_path.value();
535 return;
536 }
537
538 BluetoothRemoteGattServiceChromeOS* service =
539 static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second);
540
541 VLOG(1) << "Removing remote GATT service with UUID: '"
542 << service->GetUUID().canonical_value()
543 << "' from device: " << GetAddress();
544
545 DCHECK(service->object_path() == object_path);
546 gatt_services_.erase(iter);
547
548 DCHECK(adapter_);
549 adapter()->NotifyGattServiceRemoved(service);
550
551 delete service;
552 }
553
554 void BluetoothDeviceChromeOS::OnGetConnInfo(
555 const ConnectionInfoCallback& callback,
556 int16 rssi,
557 int16 transmit_power,
558 int16 max_transmit_power) {
559 callback.Run(ConnectionInfo(rssi, transmit_power, max_transmit_power));
560 }
561
562 void BluetoothDeviceChromeOS::OnGetConnInfoError(
563 const ConnectionInfoCallback& callback,
564 const std::string& error_name,
565 const std::string& error_message) {
566 LOG(WARNING) << object_path_.value()
567 << ": Failed to get connection info: " << error_name << ": "
568 << error_message;
569 callback.Run(ConnectionInfo());
570 }
571
572 void BluetoothDeviceChromeOS::ConnectInternal(
573 bool after_pairing,
574 const base::Closure& callback,
575 const ConnectErrorCallback& error_callback) {
576 VLOG(1) << object_path_.value() << ": Connecting";
577 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Connect(
578 object_path_,
579 base::Bind(&BluetoothDeviceChromeOS::OnConnect,
580 weak_ptr_factory_.GetWeakPtr(), after_pairing, callback),
581 base::Bind(&BluetoothDeviceChromeOS::OnConnectError,
582 weak_ptr_factory_.GetWeakPtr(), after_pairing,
583 error_callback));
584 }
585
586 void BluetoothDeviceChromeOS::OnConnect(bool after_pairing,
587 const base::Closure& callback) {
588 if (--num_connecting_calls_ == 0)
589 adapter()->NotifyDeviceChanged(this);
590
591 DCHECK(num_connecting_calls_ >= 0);
592 VLOG(1) << object_path_.value() << ": Connected, " << num_connecting_calls_
593 << " still in progress";
594
595 SetTrusted();
596
597 if (after_pairing)
598 UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult",
599 UMA_PAIRING_RESULT_SUCCESS,
600 UMA_PAIRING_RESULT_COUNT);
601
602 callback.Run();
603 }
604
605 void BluetoothDeviceChromeOS::OnCreateGattConnection(
606 const GattConnectionCallback& callback) {
607 scoped_ptr<device::BluetoothGattConnection> conn(
608 new BluetoothGattConnectionChromeOS(
609 adapter_, GetAddress(), object_path_));
610 callback.Run(conn.Pass());
611 }
612
613 void BluetoothDeviceChromeOS::OnConnectError(
614 bool after_pairing,
615 const ConnectErrorCallback& error_callback,
616 const std::string& error_name,
617 const std::string& error_message) {
618 if (--num_connecting_calls_ == 0)
619 adapter()->NotifyDeviceChanged(this);
620
621 DCHECK(num_connecting_calls_ >= 0);
622 LOG(WARNING) << object_path_.value() << ": Failed to connect device: "
623 << error_name << ": " << error_message;
624 VLOG(1) << object_path_.value() << ": " << num_connecting_calls_
625 << " still in progress";
626
627 // Determine the error code from error_name.
628 ConnectErrorCode error_code = ERROR_UNKNOWN;
629 if (error_name == bluetooth_device::kErrorFailed) {
630 error_code = ERROR_FAILED;
631 } else if (error_name == bluetooth_device::kErrorInProgress) {
632 error_code = ERROR_INPROGRESS;
633 } else if (error_name == bluetooth_device::kErrorNotSupported) {
634 error_code = ERROR_UNSUPPORTED_DEVICE;
635 }
636
637 if (after_pairing)
638 RecordPairingResult(error_code);
639 error_callback.Run(error_code);
640 }
641
642 void BluetoothDeviceChromeOS::OnPair(
643 const base::Closure& callback,
644 const ConnectErrorCallback& error_callback) {
645 VLOG(1) << object_path_.value() << ": Paired";
646
647 EndPairing();
648
649 ConnectInternal(true, callback, error_callback);
650 }
651
652 void BluetoothDeviceChromeOS::OnPairError(
653 const ConnectErrorCallback& error_callback,
654 const std::string& error_name,
655 const std::string& error_message) {
656 if (--num_connecting_calls_ == 0)
657 adapter()->NotifyDeviceChanged(this);
658
659 DCHECK(num_connecting_calls_ >= 0);
660 LOG(WARNING) << object_path_.value() << ": Failed to pair device: "
661 << error_name << ": " << error_message;
662 VLOG(1) << object_path_.value() << ": " << num_connecting_calls_
663 << " still in progress";
664
665 EndPairing();
666
667 // Determine the error code from error_name.
668 ConnectErrorCode error_code = ERROR_UNKNOWN;
669 if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) {
670 error_code = ERROR_FAILED;
671 } else if (error_name == bluetooth_device::kErrorFailed) {
672 error_code = ERROR_FAILED;
673 } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) {
674 error_code = ERROR_AUTH_FAILED;
675 } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) {
676 error_code = ERROR_AUTH_CANCELED;
677 } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) {
678 error_code = ERROR_AUTH_REJECTED;
679 } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) {
680 error_code = ERROR_AUTH_TIMEOUT;
681 }
682
683 RecordPairingResult(error_code);
684 error_callback.Run(error_code);
685 }
686
687 void BluetoothDeviceChromeOS::OnCancelPairingError(
688 const std::string& error_name,
689 const std::string& error_message) {
690 LOG(WARNING) << object_path_.value() << ": Failed to cancel pairing: "
691 << error_name << ": " << error_message;
692 }
693
694 void BluetoothDeviceChromeOS::SetTrusted() {
695 // Unconditionally send the property change, rather than checking the value
696 // first; there's no harm in doing this and it solves any race conditions
697 // with the property becoming true or false and this call happening before
698 // we get the D-Bus signal about the earlier change.
699 bluez::BluezDBusManager::Get()
700 ->GetBluetoothDeviceClient()
701 ->GetProperties(object_path_)
702 ->trusted.Set(true, base::Bind(&BluetoothDeviceChromeOS::OnSetTrusted,
703 weak_ptr_factory_.GetWeakPtr()));
704 }
705
706 void BluetoothDeviceChromeOS::OnSetTrusted(bool success) {
707 LOG_IF(WARNING, !success) << object_path_.value()
708 << ": Failed to set device as trusted";
709 }
710
711 void BluetoothDeviceChromeOS::OnDisconnect(const base::Closure& callback) {
712 VLOG(1) << object_path_.value() << ": Disconnected";
713 callback.Run();
714 }
715
716 void BluetoothDeviceChromeOS::OnDisconnectError(
717 const ErrorCallback& error_callback,
718 const std::string& error_name,
719 const std::string& error_message) {
720 LOG(WARNING) << object_path_.value() << ": Failed to disconnect device: "
721 << error_name << ": " << error_message;
722 error_callback.Run();
723 }
724
725 void BluetoothDeviceChromeOS::OnForgetError(
726 const ErrorCallback& error_callback,
727 const std::string& error_name,
728 const std::string& error_message) {
729 LOG(WARNING) << object_path_.value() << ": Failed to remove device: "
730 << error_name << ": " << error_message;
731 error_callback.Run();
732 }
733
734 } // namespace chromeos
OLDNEW
« no previous file with comments | « device/bluetooth/bluetooth_device_chromeos.h ('k') | device/bluetooth/bluetooth_discovery_session_outcome.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698