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

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

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

Powered by Google App Engine
This is Rietveld 408576698