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

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

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

Powered by Google App Engine
This is Rietveld 408576698