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/bluez/bluetooth_device_bluez.h"
6 
7 #include <stdio.h>
8 
9 #include <algorithm>
10 #include <memory>
11 #include <utility>
12 
13 #include "base/bind.h"
14 #include "base/bind_helpers.h"
15 #include "base/callback_helpers.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/metrics/histogram_macros.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "components/device_event_log/device_event_log.h"
21 #include "dbus/bus.h"
22 #include "device/bluetooth/bluetooth_socket.h"
23 #include "device/bluetooth/bluetooth_socket_thread.h"
24 #include "device/bluetooth/bluez/bluetooth_adapter_bluez.h"
25 #include "device/bluetooth/bluez/bluetooth_gatt_connection_bluez.h"
26 #include "device/bluetooth/bluez/bluetooth_pairing_bluez.h"
27 #include "device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h"
28 #include "device/bluetooth/bluez/bluetooth_service_record_bluez.h"
29 #include "device/bluetooth/bluez/bluetooth_socket_bluez.h"
30 #include "device/bluetooth/dbus/bluetooth_adapter_client.h"
31 #include "device/bluetooth/dbus/bluetooth_device_client.h"
32 #include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
33 #include "device/bluetooth/dbus/bluetooth_input_client.h"
34 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
35 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
36 #include "third_party/cros_system_api/dbus/service_constants.h"
37 
38 using device::BluetoothDevice;
39 using device::BluetoothRemoteGattService;
40 using device::BluetoothSocket;
41 using device::BluetoothUUID;
42 
43 namespace {
44 
45 // The unit for connection interval values are in multiples of 1.25ms.
46 const uint16_t MIN_CONNECTION_INTERVAL_LOW = 6;
47 const uint16_t MAX_CONNECTION_INTERVAL_LOW = 6;
48 const uint16_t MIN_CONNECTION_INTERVAL_MEDIUM = 40;
49 const uint16_t MAX_CONNECTION_INTERVAL_MEDIUM = 56;
50 const uint16_t MIN_CONNECTION_INTERVAL_HIGH = 80;
51 const uint16_t MAX_CONNECTION_INTERVAL_HIGH = 100;
52 
53 // Histogram enumerations for pairing results.
54 enum UMAPairingResult {
55   UMA_PAIRING_RESULT_SUCCESS,
56   UMA_PAIRING_RESULT_INPROGRESS,
57   UMA_PAIRING_RESULT_FAILED,
58   UMA_PAIRING_RESULT_AUTH_FAILED,
59   UMA_PAIRING_RESULT_AUTH_CANCELED,
60   UMA_PAIRING_RESULT_AUTH_REJECTED,
61   UMA_PAIRING_RESULT_AUTH_TIMEOUT,
62   UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE,
63   UMA_PAIRING_RESULT_UNKNOWN_ERROR,
64   // NOTE: Add new pairing results immediately above this line. Make sure to
65   // update the enum list in tools/histogram/histograms.xml accordinly.
66   UMA_PAIRING_RESULT_COUNT
67 };
68 
ParseModalias(const dbus::ObjectPath & object_path,BluetoothDevice::VendorIDSource * vendor_id_source,uint16_t * vendor_id,uint16_t * product_id,uint16_t * device_id)69 void ParseModalias(const dbus::ObjectPath& object_path,
70                    BluetoothDevice::VendorIDSource* vendor_id_source,
71                    uint16_t* vendor_id,
72                    uint16_t* product_id,
73                    uint16_t* device_id) {
74   bluez::BluetoothDeviceClient::Properties* properties =
75       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
76           object_path);
77   DCHECK(properties);
78 
79   std::string modalias = properties->modalias.value();
80   BluetoothDevice::VendorIDSource source_value;
81   int vendor_value, product_value, device_value;
82 
83   if (sscanf(modalias.c_str(), "bluetooth:v%04xp%04xd%04x", &vendor_value,
84              &product_value, &device_value) == 3) {
85     source_value = BluetoothDevice::VENDOR_ID_BLUETOOTH;
86   } else if (sscanf(modalias.c_str(), "usb:v%04xp%04xd%04x", &vendor_value,
87                     &product_value, &device_value) == 3) {
88     source_value = BluetoothDevice::VENDOR_ID_USB;
89   } else {
90     return;
91   }
92 
93   if (vendor_id_source != nullptr)
94     *vendor_id_source = source_value;
95   if (vendor_id != nullptr)
96     *vendor_id = vendor_value;
97   if (product_id != nullptr)
98     *product_id = product_value;
99   if (device_id != nullptr)
100     *device_id = device_value;
101 }
102 
RecordPairingResult(BluetoothDevice::ConnectErrorCode error_code)103 void RecordPairingResult(BluetoothDevice::ConnectErrorCode error_code) {
104   UMAPairingResult pairing_result;
105   switch (error_code) {
106     case BluetoothDevice::ERROR_INPROGRESS:
107       pairing_result = UMA_PAIRING_RESULT_INPROGRESS;
108       break;
109     case BluetoothDevice::ERROR_FAILED:
110       pairing_result = UMA_PAIRING_RESULT_FAILED;
111       break;
112     case BluetoothDevice::ERROR_AUTH_FAILED:
113       pairing_result = UMA_PAIRING_RESULT_AUTH_FAILED;
114       break;
115     case BluetoothDevice::ERROR_AUTH_CANCELED:
116       pairing_result = UMA_PAIRING_RESULT_AUTH_CANCELED;
117       break;
118     case BluetoothDevice::ERROR_AUTH_REJECTED:
119       pairing_result = UMA_PAIRING_RESULT_AUTH_REJECTED;
120       break;
121     case BluetoothDevice::ERROR_AUTH_TIMEOUT:
122       pairing_result = UMA_PAIRING_RESULT_AUTH_TIMEOUT;
123       break;
124     case BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
125       pairing_result = UMA_PAIRING_RESULT_UNSUPPORTED_DEVICE;
126       break;
127     default:
128       pairing_result = UMA_PAIRING_RESULT_UNKNOWN_ERROR;
129   }
130 
131   UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult", pairing_result,
132                             UMA_PAIRING_RESULT_COUNT);
133 }
134 
DBusErrorToConnectError(const std::string & error_name)135 BluetoothDevice::ConnectErrorCode DBusErrorToConnectError(
136     const std::string& error_name) {
137   BluetoothDevice::ConnectErrorCode error_code = BluetoothDevice::ERROR_UNKNOWN;
138   if (error_name == bluetooth_device::kErrorConnectionAttemptFailed) {
139     error_code = BluetoothDevice::ERROR_FAILED;
140   } else if (error_name == bluetooth_device::kErrorFailed) {
141     error_code = BluetoothDevice::ERROR_FAILED;
142   } else if (error_name == bluetooth_device::kErrorAuthenticationFailed) {
143     error_code = BluetoothDevice::ERROR_AUTH_FAILED;
144   } else if (error_name == bluetooth_device::kErrorAuthenticationCanceled) {
145     error_code = BluetoothDevice::ERROR_AUTH_CANCELED;
146   } else if (error_name == bluetooth_device::kErrorAuthenticationRejected) {
147     error_code = BluetoothDevice::ERROR_AUTH_REJECTED;
148   } else if (error_name == bluetooth_device::kErrorAuthenticationTimeout) {
149     error_code = BluetoothDevice::ERROR_AUTH_TIMEOUT;
150   }
151   return error_code;
152 }
153 
154 }  // namespace
155 
156 namespace bluez {
157 
BluetoothDeviceBlueZ(BluetoothAdapterBlueZ * adapter,const dbus::ObjectPath & object_path,scoped_refptr<base::SequencedTaskRunner> ui_task_runner,scoped_refptr<device::BluetoothSocketThread> socket_thread)158 BluetoothDeviceBlueZ::BluetoothDeviceBlueZ(
159     BluetoothAdapterBlueZ* adapter,
160     const dbus::ObjectPath& object_path,
161     scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
162     scoped_refptr<device::BluetoothSocketThread> socket_thread)
163     : BluetoothDevice(adapter),
164       object_path_(object_path),
165       num_connecting_calls_(0),
166       ui_task_runner_(ui_task_runner),
167       socket_thread_(socket_thread) {
168   bluez::BluezDBusManager::Get()->GetBluetoothGattServiceClient()->AddObserver(
169       this);
170 
171   // If GATT Services have already been discovered update the list of Gatt
172   // Services.
173   if (IsGattServicesDiscoveryComplete()) {
174     UpdateGattServices(object_path_);
175   } else {
176     BLUETOOTH_LOG(DEBUG)
177         << "Gatt services have not been fully resolved for device "
178         << object_path_.value();
179   }
180 
181   // Update all the data that we cache within Chrome and do not pull from
182   // properties every time. TODO(xiaoyinh): Add a test for this. See
183   // http://crbug.com/688566.
184   UpdateServiceData();
185   UpdateManufacturerData();
186   UpdateAdvertisingDataFlags();
187 }
188 
~BluetoothDeviceBlueZ()189 BluetoothDeviceBlueZ::~BluetoothDeviceBlueZ() {
190   bluez::BluezDBusManager::Get()
191       ->GetBluetoothGattServiceClient()
192       ->RemoveObserver(this);
193 
194   // Copy the GATT services list here and clear the original so that when we
195   // send GattServiceRemoved(), GetGattServices() returns no services.
196   GattServiceMap gatt_services_swapped;
197   gatt_services_swapped.swap(gatt_services_);
198   for (const auto& iter : gatt_services_swapped) {
199     DCHECK(adapter());
200     adapter()->NotifyGattServiceRemoved(
201         static_cast<BluetoothRemoteGattServiceBlueZ*>(iter.second.get()));
202   }
203 
204   // We pause discovery when trying to connect. Ensure discovery is unpaused if
205   // we get destroyed during a pending connection.
206   if (IsConnecting()) {
207     BLUETOOTH_LOG(EVENT) << object_path_.value()
208                          << ": Unpausing discovery. Device removed.";
209     UnpauseDiscovery();
210   }
211 }
212 
GetBluetoothClass() const213 uint32_t BluetoothDeviceBlueZ::GetBluetoothClass() const {
214   bluez::BluetoothDeviceClient::Properties* properties =
215       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
216           object_path_);
217   DCHECK(properties);
218 
219   return properties->bluetooth_class.value();
220 }
221 
GetType() const222 device::BluetoothTransport BluetoothDeviceBlueZ::GetType() const {
223   bluez::BluetoothDeviceClient::Properties* properties =
224       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
225           object_path_);
226   DCHECK(properties);
227 
228   if (!properties->type.is_valid())
229     return device::BLUETOOTH_TRANSPORT_INVALID;
230 
231   std::string type = properties->type.value();
232   if (type == bluez::BluetoothDeviceClient::kTypeBredr) {
233     return device::BLUETOOTH_TRANSPORT_CLASSIC;
234   } else if (type == bluez::BluetoothDeviceClient::kTypeLe) {
235     return device::BLUETOOTH_TRANSPORT_LE;
236   } else if (type == bluez::BluetoothDeviceClient::kTypeDual) {
237     return device::BLUETOOTH_TRANSPORT_DUAL;
238   }
239 
240   NOTREACHED();
241   return device::BLUETOOTH_TRANSPORT_INVALID;
242 }
243 
CreateGattConnectionImpl(base::Optional<BluetoothUUID> service_uuid)244 void BluetoothDeviceBlueZ::CreateGattConnectionImpl(
245     base::Optional<BluetoothUUID> service_uuid) {
246   // TODO(crbug.com/630586): Until there is a way to create a reference counted
247   // GATT connection in bluetoothd, simply do a regular connect.
248   Connect(nullptr,
249           base::BindOnce(&BluetoothDeviceBlueZ::DidConnectGatt,
250                          weak_ptr_factory_.GetWeakPtr()),
251           base::BindOnce(&BluetoothDeviceBlueZ::DidFailToConnectGatt,
252                          weak_ptr_factory_.GetWeakPtr()));
253 }
254 
SetGattServicesDiscoveryComplete(bool complete)255 void BluetoothDeviceBlueZ::SetGattServicesDiscoveryComplete(bool complete) {
256   // BlueZ implementation already tracks service discovery state.
257   NOTIMPLEMENTED();
258 }
259 
IsGattServicesDiscoveryComplete() const260 bool BluetoothDeviceBlueZ::IsGattServicesDiscoveryComplete() const {
261   bluez::BluetoothDeviceClient::Properties* properties =
262       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
263           object_path_);
264   DCHECK(properties);
265 
266   return properties->services_resolved.value();
267 }
268 
DisconnectGatt()269 void BluetoothDeviceBlueZ::DisconnectGatt() {
270   // There isn't currently a good way to manage the ownership of a connection
271   // between Chrome and bluetoothd plugins/profiles. Until a proper reference
272   // count is kept in bluetoothd, we might unwittingly kill a connection to a
273   // device the user is still interested in, e.g. a mouse. A device's paired
274   // status is usually a good indication that the device is being used by other
275   // parts of the system and therefore we leak these connections.
276   // TODO(crbug.com/630586): Call disconnect for all devices.
277 
278   // IsPaired() returns true if we've connected to the device before. So we
279   // check the dbus property directly.
280   // TODO(crbug.com/649651): Use IsPaired once it returns true only for paired
281   // devices.
282   bluez::BluetoothDeviceClient::Properties* properties =
283       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
284           object_path_);
285   DCHECK(properties);
286 
287   if (properties->paired.value()) {
288     BLUETOOTH_LOG(ERROR) << "Leaking connection to paired device.";
289     return;
290   }
291 
292   Disconnect(base::DoNothing(), base::DoNothing());
293 }
294 
GetAddress() const295 std::string BluetoothDeviceBlueZ::GetAddress() const {
296   bluez::BluetoothDeviceClient::Properties* properties =
297       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
298           object_path_);
299   DCHECK(properties);
300 
301   return CanonicalizeAddress(properties->address.value());
302 }
303 
GetVendorIDSource() const304 BluetoothDevice::VendorIDSource BluetoothDeviceBlueZ::GetVendorIDSource()
305     const {
306   VendorIDSource vendor_id_source = VENDOR_ID_UNKNOWN;
307   ParseModalias(object_path_, &vendor_id_source, nullptr, nullptr, nullptr);
308   return vendor_id_source;
309 }
310 
GetVendorID() const311 uint16_t BluetoothDeviceBlueZ::GetVendorID() const {
312   uint16_t vendor_id = 0;
313   ParseModalias(object_path_, nullptr, &vendor_id, nullptr, nullptr);
314   return vendor_id;
315 }
316 
GetProductID() const317 uint16_t BluetoothDeviceBlueZ::GetProductID() const {
318   uint16_t product_id = 0;
319   ParseModalias(object_path_, nullptr, nullptr, &product_id, nullptr);
320   return product_id;
321 }
322 
GetDeviceID() const323 uint16_t BluetoothDeviceBlueZ::GetDeviceID() const {
324   uint16_t device_id = 0;
325   ParseModalias(object_path_, nullptr, nullptr, nullptr, &device_id);
326   return device_id;
327 }
328 
GetAppearance() const329 uint16_t BluetoothDeviceBlueZ::GetAppearance() const {
330   bluez::BluetoothDeviceClient::Properties* properties =
331       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
332           object_path_);
333   DCHECK(properties);
334 
335   if (!properties->appearance.is_valid())
336     return kAppearanceNotPresent;
337 
338   return properties->appearance.value();
339 }
340 
GetName() const341 base::Optional<std::string> BluetoothDeviceBlueZ::GetName() const {
342   bluez::BluetoothDeviceClient::Properties* properties =
343       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
344           object_path_);
345   DCHECK(properties);
346 
347   if (properties->name.is_valid())
348     return properties->name.value();
349   else
350     return base::nullopt;
351 }
352 
IsPaired() const353 bool BluetoothDeviceBlueZ::IsPaired() const {
354   bluez::BluetoothDeviceClient::Properties* properties =
355       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
356           object_path_);
357   DCHECK(properties);
358 
359   // The Paired property reflects the successful pairing for BR/EDR/LE. The
360   // value of the Paired property is always false for the devices that don't
361   // support pairing. Once a device is paired successfully, both Paired and
362   // Trusted properties will be set to true.
363   return properties->paired.value();
364 }
365 
IsConnected() const366 bool BluetoothDeviceBlueZ::IsConnected() const {
367   bluez::BluetoothDeviceClient::Properties* properties =
368       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
369           object_path_);
370   DCHECK(properties);
371 
372   return properties->connected.value();
373 }
374 
IsGattConnected() const375 bool BluetoothDeviceBlueZ::IsGattConnected() const {
376   // Bluez uses the same attribute for GATT Connections and Classic BT
377   // Connections.
378   return IsConnected();
379 }
380 
IsConnectable() const381 bool BluetoothDeviceBlueZ::IsConnectable() const {
382   bluez::BluetoothInputClient::Properties* input_properties =
383       bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->GetProperties(
384           object_path_);
385   // GetProperties returns nullptr when the device does not implement the given
386   // interface. Non HID devices are normally connectable.
387   if (!input_properties)
388     return true;
389 
390   return input_properties->reconnect_mode.value() != "device";
391 }
392 
IsConnecting() const393 bool BluetoothDeviceBlueZ::IsConnecting() const {
394   return num_connecting_calls_ > 0;
395 }
396 
GetUUIDs() const397 BluetoothDevice::UUIDSet BluetoothDeviceBlueZ::GetUUIDs() const {
398   bluez::BluetoothDeviceClient::Properties* properties =
399       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
400           object_path_);
401   DCHECK(properties);
402 
403   UUIDSet uuids;
404   const std::vector<std::string>& dbus_uuids = properties->uuids.value();
405   for (const std::string& dbus_uuid : dbus_uuids) {
406     device::BluetoothUUID uuid(dbus_uuid);
407     DCHECK(uuid.IsValid());
408     uuids.insert(std::move(uuid));
409   }
410   return uuids;
411 }
412 
GetInquiryRSSI() const413 base::Optional<int8_t> BluetoothDeviceBlueZ::GetInquiryRSSI() const {
414   bluez::BluetoothDeviceClient::Properties* properties =
415       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
416           object_path_);
417   DCHECK(properties);
418 
419   if (!properties->rssi.is_valid())
420     return base::nullopt;
421 
422   // BlueZ uses int16_t because there is no int8_t for DBus, so we should never
423   // get an int16_t that cannot be represented by an int8_t. But just in case
424   // clamp the value.
425   return ClampPower(properties->rssi.value());
426 }
427 
GetInquiryTxPower() const428 base::Optional<int8_t> BluetoothDeviceBlueZ::GetInquiryTxPower() const {
429   bluez::BluetoothDeviceClient::Properties* properties =
430       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
431           object_path_);
432   DCHECK(properties);
433 
434   if (!properties->tx_power.is_valid())
435     return base::nullopt;
436 
437   // BlueZ uses int16_t because there is no int8_t for DBus, so we should never
438   // get an int16_t that cannot be represented by an int8_t. But just in case
439   // clamp the value.
440   return ClampPower(properties->tx_power.value());
441 }
442 
ExpectingPinCode() const443 bool BluetoothDeviceBlueZ::ExpectingPinCode() const {
444   return pairing_.get() && pairing_->ExpectingPinCode();
445 }
446 
ExpectingPasskey() const447 bool BluetoothDeviceBlueZ::ExpectingPasskey() const {
448   return pairing_.get() && pairing_->ExpectingPasskey();
449 }
450 
ExpectingConfirmation() const451 bool BluetoothDeviceBlueZ::ExpectingConfirmation() const {
452   return pairing_.get() && pairing_->ExpectingConfirmation();
453 }
454 
GetConnectionInfo(const ConnectionInfoCallback & callback)455 void BluetoothDeviceBlueZ::GetConnectionInfo(
456     const ConnectionInfoCallback& callback) {
457   // DBus method call should gracefully return an error if the device is not
458   // currently connected.
459   bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetConnInfo(
460       object_path_,
461       base::BindOnce(&BluetoothDeviceBlueZ::OnGetConnInfo,
462                      weak_ptr_factory_.GetWeakPtr(), callback),
463       base::BindOnce(&BluetoothDeviceBlueZ::OnGetConnInfoError,
464                      weak_ptr_factory_.GetWeakPtr(), callback));
465 }
466 
SetConnectionLatency(ConnectionLatency connection_latency,const base::Closure & callback,const ErrorCallback & error_callback)467 void BluetoothDeviceBlueZ::SetConnectionLatency(
468     ConnectionLatency connection_latency,
469     const base::Closure& callback,
470     const ErrorCallback& error_callback) {
471   uint16_t min_connection_interval = MIN_CONNECTION_INTERVAL_MEDIUM;
472   uint16_t max_connection_interval = MAX_CONNECTION_INTERVAL_MEDIUM;
473   switch (connection_latency) {
474     case ConnectionLatency::CONNECTION_LATENCY_LOW:
475       min_connection_interval = MIN_CONNECTION_INTERVAL_LOW;
476       max_connection_interval = MAX_CONNECTION_INTERVAL_LOW;
477       break;
478     case ConnectionLatency::CONNECTION_LATENCY_MEDIUM:
479       min_connection_interval = MIN_CONNECTION_INTERVAL_MEDIUM;
480       max_connection_interval = MAX_CONNECTION_INTERVAL_MEDIUM;
481       break;
482     case ConnectionLatency::CONNECTION_LATENCY_HIGH:
483       min_connection_interval = MIN_CONNECTION_INTERVAL_HIGH;
484       max_connection_interval = MAX_CONNECTION_INTERVAL_HIGH;
485       break;
486     default:
487       NOTREACHED();
488       break;
489   }
490 
491   BLUETOOTH_LOG(EVENT) << "Setting LE connection parameters: min="
492                        << min_connection_interval
493                        << ", max=" << max_connection_interval;
494   bluez::BluetoothDeviceClient::ConnectionParameters connection_parameters;
495   connection_parameters.min_connection_interval = min_connection_interval;
496   connection_parameters.max_connection_interval = max_connection_interval;
497 
498   bluez::BluetoothDeviceClient* client =
499       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient();
500   client->SetLEConnectionParameters(
501       object_path_, connection_parameters,
502       base::BindOnce(&BluetoothDeviceBlueZ::OnSetLEConnectionParameters,
503                      weak_ptr_factory_.GetWeakPtr(), callback),
504       base::BindOnce(&BluetoothDeviceBlueZ::OnSetLEConnectionParametersError,
505                      weak_ptr_factory_.GetWeakPtr(), error_callback));
506 }
507 
Connect(BluetoothDevice::PairingDelegate * pairing_delegate,base::OnceClosure callback,ConnectErrorCallback error_callback)508 void BluetoothDeviceBlueZ::Connect(
509     BluetoothDevice::PairingDelegate* pairing_delegate,
510     base::OnceClosure callback,
511     ConnectErrorCallback error_callback) {
512   if (num_connecting_calls_++ == 0)
513     adapter()->NotifyDeviceChanged(this);
514 
515   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Connecting, "
516                        << num_connecting_calls_ << " in progress";
517 
518   // These callbacks are only called once, but are passed to two different
519   // places.
520   base::RepeatingClosure dupe_callback =
521       base::AdaptCallbackForRepeating(std::move(callback));
522   base::RepeatingCallback<ConnectErrorCallback::RunType> dupe_error_callback =
523       base::AdaptCallbackForRepeating(std::move(error_callback));
524 
525   if (IsPaired() || !pairing_delegate) {
526     BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Pausing discovery";
527     // No need to pair, or unable to, skip straight to connection.
528     bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->PauseDiscovery(
529         adapter()->object_path(),
530         base::BindOnce(
531             [](base::WeakPtr<BluetoothDeviceBlueZ> weak_ptr,
532                base::OnceClosure callback,
533                ConnectErrorCallback error_callback) {
534               BLUETOOTH_LOG(EVENT) << "Successfully paused discovery";
535               if (weak_ptr)
536                 weak_ptr->ConnectInternal(false /* after_pairing */,
537                                           std::move(callback),
538                                           std::move(error_callback));
539             },
540             weak_ptr_factory_.GetWeakPtr(), dupe_callback, dupe_error_callback),
541         base::BindOnce(
542             [](base::WeakPtr<BluetoothDeviceBlueZ> weak_ptr,
543                base::OnceClosure callback, ConnectErrorCallback error_callback,
544                const std::string& error_name,
545                const std::string& error_message) {
546               BLUETOOTH_LOG(EVENT) << "Failed to pause discovery";
547               if (weak_ptr)
548                 weak_ptr->ConnectInternal(false, std::move(callback),
549                                           std::move(error_callback));
550             },
551             weak_ptr_factory_.GetWeakPtr(), dupe_callback,
552             dupe_error_callback));
553   } else {
554     // Initiate high-security connection with pairing.
555     BeginPairing(pairing_delegate);
556 
557     bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Pair(
558         object_path_,
559         base::BindOnce(&BluetoothDeviceBlueZ::OnPairDuringConnect,
560                        weak_ptr_factory_.GetWeakPtr(), dupe_callback,
561                        dupe_error_callback),
562         base::BindOnce(&BluetoothDeviceBlueZ::OnPairDuringConnectError,
563                        weak_ptr_factory_.GetWeakPtr(), dupe_error_callback));
564   }
565 }
566 
Pair(BluetoothDevice::PairingDelegate * pairing_delegate,base::OnceClosure callback,ConnectErrorCallback error_callback)567 void BluetoothDeviceBlueZ::Pair(
568     BluetoothDevice::PairingDelegate* pairing_delegate,
569     base::OnceClosure callback,
570     ConnectErrorCallback error_callback) {
571   DCHECK(pairing_delegate);
572   BeginPairing(pairing_delegate);
573 
574   bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Pair(
575       object_path_,
576       base::BindOnce(&BluetoothDeviceBlueZ::OnPair,
577                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
578       base::BindOnce(&BluetoothDeviceBlueZ::OnPairError,
579                      weak_ptr_factory_.GetWeakPtr(),
580                      std::move(error_callback)));
581 }
582 
SetPinCode(const std::string & pincode)583 void BluetoothDeviceBlueZ::SetPinCode(const std::string& pincode) {
584   if (!pairing_.get())
585     return;
586 
587   pairing_->SetPinCode(pincode);
588 }
589 
SetPasskey(uint32_t passkey)590 void BluetoothDeviceBlueZ::SetPasskey(uint32_t passkey) {
591   if (!pairing_.get())
592     return;
593 
594   pairing_->SetPasskey(passkey);
595 }
596 
ConfirmPairing()597 void BluetoothDeviceBlueZ::ConfirmPairing() {
598   if (!pairing_.get())
599     return;
600 
601   pairing_->ConfirmPairing();
602 }
603 
RejectPairing()604 void BluetoothDeviceBlueZ::RejectPairing() {
605   if (!pairing_.get())
606     return;
607 
608   pairing_->RejectPairing();
609 }
610 
CancelPairing()611 void BluetoothDeviceBlueZ::CancelPairing() {
612   bool canceled = false;
613 
614   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": CancelPairing";
615 
616   // If there is a callback in progress that we can reply to then use that
617   // to cancel the current pairing request.
618   if (pairing_.get() && pairing_->CancelPairing())
619     canceled = true;
620 
621   // If not we have to send an explicit CancelPairing() to the device instead.
622   if (!canceled) {
623     BLUETOOTH_LOG(DEBUG) << object_path_.value()
624                          << ": No pairing context or callback. "
625                          << "Sending explicit cancel";
626     bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->CancelPairing(
627         object_path_, base::DoNothing(),
628         base::BindOnce(&BluetoothDeviceBlueZ::OnCancelPairingError,
629                        weak_ptr_factory_.GetWeakPtr()));
630   }
631 
632   // Since there is no callback to this method it's possible that the pairing
633   // delegate is going to be freed before things complete (indeed it's
634   // documented that this is the method you should call while freeing the
635   // pairing delegate), so clear our the context holding on to it.
636   EndPairing();
637 }
638 
Disconnect(const base::Closure & callback,const ErrorCallback & error_callback)639 void BluetoothDeviceBlueZ::Disconnect(const base::Closure& callback,
640                                       const ErrorCallback& error_callback) {
641   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Disconnecting";
642   bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Disconnect(
643       object_path_,
644       base::BindOnce(&BluetoothDeviceBlueZ::OnDisconnect,
645                      weak_ptr_factory_.GetWeakPtr(), callback),
646       base::BindOnce(&BluetoothDeviceBlueZ::OnDisconnectError,
647                      weak_ptr_factory_.GetWeakPtr(), error_callback));
648 }
649 
Forget(const base::Closure & callback,const ErrorCallback & error_callback)650 void BluetoothDeviceBlueZ::Forget(const base::Closure& callback,
651                                   const ErrorCallback& error_callback) {
652   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Removing device";
653   bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->RemoveDevice(
654       adapter()->object_path(), object_path_, callback,
655       base::BindOnce(&BluetoothDeviceBlueZ::OnForgetError,
656                      weak_ptr_factory_.GetWeakPtr(), error_callback));
657 }
658 
ConnectToService(const BluetoothUUID & uuid,const ConnectToServiceCallback & callback,const ConnectToServiceErrorCallback & error_callback)659 void BluetoothDeviceBlueZ::ConnectToService(
660     const BluetoothUUID& uuid,
661     const ConnectToServiceCallback& callback,
662     const ConnectToServiceErrorCallback& error_callback) {
663   BLUETOOTH_LOG(EVENT) << object_path_.value()
664                        << ": Connecting to service: " << uuid.canonical_value();
665   scoped_refptr<BluetoothSocketBlueZ> socket =
666       BluetoothSocketBlueZ::CreateBluetoothSocket(ui_task_runner_,
667                                                   socket_thread_);
668   socket->Connect(this, uuid, BluetoothSocketBlueZ::SECURITY_LEVEL_MEDIUM,
669                   base::Bind(callback, socket), error_callback);
670 }
671 
ConnectToServiceInsecurely(const BluetoothUUID & uuid,const ConnectToServiceCallback & callback,const ConnectToServiceErrorCallback & error_callback)672 void BluetoothDeviceBlueZ::ConnectToServiceInsecurely(
673     const BluetoothUUID& uuid,
674     const ConnectToServiceCallback& callback,
675     const ConnectToServiceErrorCallback& error_callback) {
676   BLUETOOTH_LOG(EVENT) << object_path_.value()
677                        << ": Connecting insecurely to service: "
678                        << uuid.canonical_value();
679   scoped_refptr<BluetoothSocketBlueZ> socket =
680       BluetoothSocketBlueZ::CreateBluetoothSocket(ui_task_runner_,
681                                                   socket_thread_);
682   socket->Connect(this, uuid, BluetoothSocketBlueZ::SECURITY_LEVEL_LOW,
683                   base::Bind(callback, socket), error_callback);
684 }
685 
686 std::unique_ptr<device::BluetoothGattConnection>
CreateBluetoothGattConnectionObject()687 BluetoothDeviceBlueZ::CreateBluetoothGattConnectionObject() {
688   return std::unique_ptr<device::BluetoothGattConnection>(
689       new BluetoothGattConnectionBlueZ(adapter_, GetAddress(), object_path_));
690 }
691 
GetServiceRecords(const GetServiceRecordsCallback & callback,const GetServiceRecordsErrorCallback & error_callback)692 void BluetoothDeviceBlueZ::GetServiceRecords(
693     const GetServiceRecordsCallback& callback,
694     const GetServiceRecordsErrorCallback& error_callback) {
695   bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetServiceRecords(
696       object_path_, callback,
697       base::BindOnce(&BluetoothDeviceBlueZ::OnGetServiceRecordsError,
698                      weak_ptr_factory_.GetWeakPtr(), error_callback));
699 }
700 
701 #if defined(OS_CHROMEOS)
ExecuteWrite(const base::Closure & callback,const ExecuteWriteErrorCallback & error_callback)702 void BluetoothDeviceBlueZ::ExecuteWrite(
703     const base::Closure& callback,
704     const ExecuteWriteErrorCallback& error_callback) {
705   bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ExecuteWrite(
706       object_path_, callback,
707       base::BindOnce(&BluetoothDeviceBlueZ::OnExecuteWriteError,
708                      weak_ptr_factory_.GetWeakPtr(), error_callback));
709 }
710 
AbortWrite(const base::Closure & callback,const AbortWriteErrorCallback & error_callback)711 void BluetoothDeviceBlueZ::AbortWrite(
712     const base::Closure& callback,
713     const AbortWriteErrorCallback& error_callback) {
714   bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AbortWrite(
715       object_path_, callback,
716       base::BindOnce(&BluetoothDeviceBlueZ::OnAbortWriteError,
717                      weak_ptr_factory_.GetWeakPtr(), error_callback));
718 }
719 #endif
720 
UpdateServiceData()721 void BluetoothDeviceBlueZ::UpdateServiceData() {
722   bluez::BluetoothDeviceClient::Properties* properties =
723       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
724           object_path_);
725   if (!properties || !properties->service_data.is_valid())
726     return;
727 
728   service_data_.clear();
729   for (const auto& pair : properties->service_data.value())
730     service_data_[BluetoothUUID(pair.first)] = pair.second;
731 }
732 
UpdateManufacturerData()733 void BluetoothDeviceBlueZ::UpdateManufacturerData() {
734   bluez::BluetoothDeviceClient::Properties* properties =
735       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
736           object_path_);
737   if (!properties || !properties->manufacturer_data.is_valid())
738     return;
739   manufacturer_data_.clear();
740 
741   if (properties->manufacturer_data.is_valid()) {
742     for (const auto& pair : properties->manufacturer_data.value())
743       manufacturer_data_[pair.first] = pair.second;
744   }
745 }
746 
UpdateAdvertisingDataFlags()747 void BluetoothDeviceBlueZ::UpdateAdvertisingDataFlags() {
748   bluez::BluetoothDeviceClient::Properties* properties =
749       bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
750           object_path_);
751   if (!properties || !properties->advertising_data_flags.is_valid())
752     return;
753   // The advertising data flags property is a vector<uint8> because the
754   // Supplement to Bluetooth Core Specification Version 6 page 13 said that
755   // "The Flags field may be zero or more octets long." However, only the first
756   // byte of that is needed because there is only 5 bits of data defined there.
757   advertising_data_flags_ = properties->advertising_data_flags.value()[0];
758 }
759 
BeginPairing(BluetoothDevice::PairingDelegate * pairing_delegate)760 BluetoothPairingBlueZ* BluetoothDeviceBlueZ::BeginPairing(
761     BluetoothDevice::PairingDelegate* pairing_delegate) {
762   pairing_.reset(new BluetoothPairingBlueZ(this, pairing_delegate));
763   return pairing_.get();
764 }
765 
EndPairing()766 void BluetoothDeviceBlueZ::EndPairing() {
767   pairing_.reset();
768 }
769 
GetPairing() const770 BluetoothPairingBlueZ* BluetoothDeviceBlueZ::GetPairing() const {
771   return pairing_.get();
772 }
773 
adapter() const774 BluetoothAdapterBlueZ* BluetoothDeviceBlueZ::adapter() const {
775   return static_cast<BluetoothAdapterBlueZ*>(adapter_);
776 }
777 
GattServiceAdded(const dbus::ObjectPath & object_path)778 void BluetoothDeviceBlueZ::GattServiceAdded(
779     const dbus::ObjectPath& object_path) {
780   if (GetGattService(object_path.value())) {
781     BLUETOOTH_LOG(DEBUG) << "Remote GATT service already exists: "
782                          << object_path.value();
783     return;
784   }
785 
786   bluez::BluetoothGattServiceClient::Properties* properties =
787       bluez::BluezDBusManager::Get()
788           ->GetBluetoothGattServiceClient()
789           ->GetProperties(object_path);
790   DCHECK(properties);
791   if (properties->device.value() != object_path_) {
792     BLUETOOTH_LOG(DEBUG)
793         << "Remote GATT service does not belong to this device.";
794     return;
795   }
796 
797   BLUETOOTH_LOG(EVENT) << "Adding new remote GATT service for device: "
798                        << GetAddress();
799 
800   BluetoothRemoteGattServiceBlueZ* service =
801       new BluetoothRemoteGattServiceBlueZ(adapter(), this, object_path);
802 
803   gatt_services_[service->GetIdentifier()] = base::WrapUnique(service);
804   DCHECK(service->object_path() == object_path);
805   DCHECK(service->GetUUID().IsValid());
806 
807   DCHECK(adapter());
808   adapter()->NotifyGattServiceAdded(service);
809 }
810 
GattServiceRemoved(const dbus::ObjectPath & object_path)811 void BluetoothDeviceBlueZ::GattServiceRemoved(
812     const dbus::ObjectPath& object_path) {
813   auto iter = gatt_services_.find(object_path.value());
814   if (iter == gatt_services_.end()) {
815     DVLOG(3) << "Unknown GATT service removed: " << object_path.value();
816     return;
817   }
818 
819   BluetoothRemoteGattServiceBlueZ* service =
820       static_cast<BluetoothRemoteGattServiceBlueZ*>(iter->second.get());
821 
822   BLUETOOTH_LOG(EVENT) << "Removing remote GATT service with UUID: '"
823                        << service->GetUUID().canonical_value()
824                        << "' from device: " << GetAddress();
825 
826   DCHECK(service->object_path() == object_path);
827   std::unique_ptr<BluetoothRemoteGattService> scoped_service =
828       std::move(gatt_services_[object_path.value()]);
829   gatt_services_.erase(iter);
830 
831   DCHECK(adapter());
832   discovery_complete_notified_.erase(service);
833   adapter()->NotifyGattServiceRemoved(service);
834 }
835 
UpdateGattServices(const dbus::ObjectPath & object_path)836 void BluetoothDeviceBlueZ::UpdateGattServices(
837     const dbus::ObjectPath& object_path) {
838   if (object_path != object_path_) {
839     // No need to update map if update is for a different device.
840     return;
841   }
842 
843   DCHECK(IsGattServicesDiscoveryComplete());
844 
845   DVLOG(3) << "Updating the list of GATT services associated with device "
846            << object_path_.value();
847 
848   const std::vector<dbus::ObjectPath> service_paths =
849       bluez::BluezDBusManager::Get()
850           ->GetBluetoothGattServiceClient()
851           ->GetServices();
852   for (const auto& service_path : service_paths) {
853     // Add all previously unknown GATT services associated with the device.
854     GattServiceAdded(service_path);
855 
856     // If the service does not belong in this device, there is nothing left to
857     // do.
858     BluetoothRemoteGattService* service = GetGattService(service_path.value());
859     if (service == nullptr) {
860       return;
861     }
862 
863     // Notify of GATT discovery complete if we haven't before.
864     auto notified_pair = discovery_complete_notified_.insert(service);
865     if (notified_pair.second) {
866       adapter()->NotifyGattDiscoveryComplete(service);
867     }
868   }
869 }
870 
OnGetConnInfo(const ConnectionInfoCallback & callback,int16_t rssi,int16_t transmit_power,int16_t max_transmit_power)871 void BluetoothDeviceBlueZ::OnGetConnInfo(const ConnectionInfoCallback& callback,
872                                          int16_t rssi,
873                                          int16_t transmit_power,
874                                          int16_t max_transmit_power) {
875   callback.Run(ConnectionInfo(rssi, transmit_power, max_transmit_power));
876 }
877 
OnGetConnInfoError(const ConnectionInfoCallback & callback,const std::string & error_name,const std::string & error_message)878 void BluetoothDeviceBlueZ::OnGetConnInfoError(
879     const ConnectionInfoCallback& callback,
880     const std::string& error_name,
881     const std::string& error_message) {
882   BLUETOOTH_LOG(ERROR) << object_path_.value()
883                        << ": Failed to get connection info: " << error_name
884                        << ": " << error_message;
885   callback.Run(ConnectionInfo());
886 }
887 
OnSetLEConnectionParameters(const base::Closure & callback)888 void BluetoothDeviceBlueZ::OnSetLEConnectionParameters(
889     const base::Closure& callback) {
890   callback.Run();
891 }
892 
OnSetLEConnectionParametersError(const ErrorCallback & callback,const std::string & error_name,const std::string & error_message)893 void BluetoothDeviceBlueZ::OnSetLEConnectionParametersError(
894     const ErrorCallback& callback,
895     const std::string& error_name,
896     const std::string& error_message) {
897   BLUETOOTH_LOG(ERROR) << object_path_.value()
898                        << ": Failed to set connection parameters: "
899                        << error_name << ": " << error_message;
900   callback.Run();
901 }
902 
OnGetServiceRecordsError(const GetServiceRecordsErrorCallback & error_callback,const std::string & error_name,const std::string & error_message)903 void BluetoothDeviceBlueZ::OnGetServiceRecordsError(
904     const GetServiceRecordsErrorCallback& error_callback,
905     const std::string& error_name,
906     const std::string& error_message) {
907   BLUETOOTH_LOG(EVENT) << object_path_.value()
908                        << ": Failed to get service records: " << error_name
909                        << ": " << error_message;
910   BluetoothServiceRecordBlueZ::ErrorCode code =
911       BluetoothServiceRecordBlueZ::ErrorCode::UNKNOWN;
912   if (error_name == bluetooth_device::kErrorNotConnected) {
913     code = BluetoothServiceRecordBlueZ::ErrorCode::ERROR_DEVICE_DISCONNECTED;
914   }
915   error_callback.Run(code);
916 }
917 
918 #if defined(OS_CHROMEOS)
OnExecuteWriteError(const ExecuteWriteErrorCallback & error_callback,const std::string & error_name,const std::string & error_message)919 void BluetoothDeviceBlueZ::OnExecuteWriteError(
920     const ExecuteWriteErrorCallback& error_callback,
921     const std::string& error_name,
922     const std::string& error_message) {
923   BLUETOOTH_LOG(EVENT) << object_path_.value()
924                        << ": Failed to execute write: " << error_name << ": "
925                        << error_message;
926   error_callback.Run(
927       BluetoothGattServiceBlueZ::DBusErrorToServiceError(error_name));
928 }
929 
OnAbortWriteError(const AbortWriteErrorCallback & error_callback,const std::string & error_name,const std::string & error_message)930 void BluetoothDeviceBlueZ::OnAbortWriteError(
931     const AbortWriteErrorCallback& error_callback,
932     const std::string& error_name,
933     const std::string& error_message) {
934   BLUETOOTH_LOG(EVENT) << object_path_.value()
935                        << ": Failed to abort write: " << error_name << ": "
936                        << error_message;
937   error_callback.Run(
938       BluetoothGattServiceBlueZ::DBusErrorToServiceError(error_name));
939 }
940 #endif
941 
ConnectInternal(bool after_pairing,base::OnceClosure callback,ConnectErrorCallback error_callback)942 void BluetoothDeviceBlueZ::ConnectInternal(
943     bool after_pairing,
944     base::OnceClosure callback,
945     ConnectErrorCallback error_callback) {
946   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Connecting";
947   bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->Connect(
948       object_path_,
949       base::BindOnce(&BluetoothDeviceBlueZ::OnConnect,
950                      weak_ptr_factory_.GetWeakPtr(), after_pairing,
951                      std::move(callback)),
952       base::BindOnce(&BluetoothDeviceBlueZ::OnConnectError,
953                      weak_ptr_factory_.GetWeakPtr(), after_pairing,
954                      std::move(error_callback)));
955 }
956 
OnConnect(bool after_pairing,base::OnceClosure callback)957 void BluetoothDeviceBlueZ::OnConnect(bool after_pairing,
958                                      base::OnceClosure callback) {
959   BLUETOOTH_LOG(EVENT) << object_path_.value()
960                        << ": Unpausing discovery after connection";
961   UnpauseDiscovery();
962   if (--num_connecting_calls_ == 0)
963     adapter()->NotifyDeviceChanged(this);
964 
965   DCHECK(num_connecting_calls_ >= 0);
966   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Connected, "
967                        << num_connecting_calls_ << " still in progress";
968 
969   SetTrusted();
970 
971   if (after_pairing)
972     UMA_HISTOGRAM_ENUMERATION("Bluetooth.PairingResult",
973                               UMA_PAIRING_RESULT_SUCCESS,
974                               UMA_PAIRING_RESULT_COUNT);
975 
976   std::move(callback).Run();
977 }
978 
OnConnectError(bool after_pairing,ConnectErrorCallback error_callback,const std::string & error_name,const std::string & error_message)979 void BluetoothDeviceBlueZ::OnConnectError(bool after_pairing,
980                                           ConnectErrorCallback error_callback,
981                                           const std::string& error_name,
982                                           const std::string& error_message) {
983   BLUETOOTH_LOG(EVENT) << object_path_.value()
984                        << ": Unpausing discovery after failed connection";
985   UnpauseDiscovery();
986 
987   if (--num_connecting_calls_ == 0)
988     adapter()->NotifyDeviceChanged(this);
989 
990   DCHECK(num_connecting_calls_ >= 0);
991   BLUETOOTH_LOG(ERROR) << object_path_.value()
992                        << ": Failed to connect device: " << error_name << ": "
993                        << error_message;
994   BLUETOOTH_LOG(DEBUG) << object_path_.value() << ": " << num_connecting_calls_
995                        << " still in progress";
996 
997   // Determine the error code from error_name.
998   ConnectErrorCode error_code = ERROR_UNKNOWN;
999   if (error_name == bluetooth_device::kErrorFailed) {
1000     error_code = ERROR_FAILED;
1001   } else if (error_name == bluetooth_device::kErrorInProgress) {
1002     error_code = ERROR_INPROGRESS;
1003   } else if (error_name == bluetooth_device::kErrorNotSupported) {
1004     error_code = ERROR_UNSUPPORTED_DEVICE;
1005   }
1006 
1007   if (after_pairing)
1008     RecordPairingResult(error_code);
1009   std::move(error_callback).Run(error_code);
1010 }
1011 
OnPairDuringConnect(base::OnceClosure callback,ConnectErrorCallback error_callback)1012 void BluetoothDeviceBlueZ::OnPairDuringConnect(
1013     base::OnceClosure callback,
1014     ConnectErrorCallback error_callback) {
1015   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Paired";
1016 
1017   EndPairing();
1018 
1019   ConnectInternal(true, std::move(callback), std::move(error_callback));
1020 }
1021 
OnPairDuringConnectError(ConnectErrorCallback error_callback,const std::string & error_name,const std::string & error_message)1022 void BluetoothDeviceBlueZ::OnPairDuringConnectError(
1023     ConnectErrorCallback error_callback,
1024     const std::string& error_name,
1025     const std::string& error_message) {
1026   if (--num_connecting_calls_ == 0)
1027     adapter()->NotifyDeviceChanged(this);
1028 
1029   DCHECK(num_connecting_calls_ >= 0);
1030   BLUETOOTH_LOG(ERROR) << object_path_.value()
1031                        << ": Failed to pair device: " << error_name << ": "
1032                        << error_message;
1033   BLUETOOTH_LOG(DEBUG) << object_path_.value() << ": " << num_connecting_calls_
1034                        << " still in progress";
1035 
1036   EndPairing();
1037 
1038   // Determine the error code from error_name.
1039   ConnectErrorCode error_code = DBusErrorToConnectError(error_name);
1040 
1041   RecordPairingResult(error_code);
1042   std::move(error_callback).Run(error_code);
1043 }
1044 
OnPair(base::OnceClosure callback)1045 void BluetoothDeviceBlueZ::OnPair(base::OnceClosure callback) {
1046   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Paired";
1047   EndPairing();
1048   std::move(callback).Run();
1049 }
1050 
OnPairError(ConnectErrorCallback error_callback,const std::string & error_name,const std::string & error_message)1051 void BluetoothDeviceBlueZ::OnPairError(ConnectErrorCallback error_callback,
1052                                        const std::string& error_name,
1053                                        const std::string& error_message) {
1054   BLUETOOTH_LOG(ERROR) << object_path_.value()
1055                        << ": Failed to pair device: " << error_name << ": "
1056                        << error_message;
1057   EndPairing();
1058   ConnectErrorCode error_code = DBusErrorToConnectError(error_name);
1059   RecordPairingResult(error_code);
1060   std::move(error_callback).Run(error_code);
1061 }
1062 
OnCancelPairingError(const std::string & error_name,const std::string & error_message)1063 void BluetoothDeviceBlueZ::OnCancelPairingError(
1064     const std::string& error_name,
1065     const std::string& error_message) {
1066   BLUETOOTH_LOG(ERROR) << object_path_.value()
1067                        << ": Failed to cancel pairing: " << error_name << ": "
1068                        << error_message;
1069 }
1070 
SetTrusted()1071 void BluetoothDeviceBlueZ::SetTrusted() {
1072   // Unconditionally send the property change, rather than checking the value
1073   // first; there's no harm in doing this and it solves any race conditions
1074   // with the property becoming true or false and this call happening before
1075   // we get the D-Bus signal about the earlier change.
1076   bluez::BluezDBusManager::Get()
1077       ->GetBluetoothDeviceClient()
1078       ->GetProperties(object_path_)
1079       ->trusted.Set(true, base::BindOnce(&BluetoothDeviceBlueZ::OnSetTrusted,
1080                                          weak_ptr_factory_.GetWeakPtr()));
1081 }
1082 
OnSetTrusted(bool success)1083 void BluetoothDeviceBlueZ::OnSetTrusted(bool success) {
1084   device_event_log::LogLevel log_level =
1085       success ? device_event_log::LOG_LEVEL_DEBUG
1086               : device_event_log::LOG_LEVEL_ERROR;
1087   DEVICE_LOG(device_event_log::LOG_TYPE_BLUETOOTH, log_level)
1088       << object_path_.value() << ": OnSetTrusted: " << success;
1089 }
1090 
OnDisconnect(const base::Closure & callback)1091 void BluetoothDeviceBlueZ::OnDisconnect(const base::Closure& callback) {
1092   BLUETOOTH_LOG(EVENT) << object_path_.value() << ": Disconnected";
1093   callback.Run();
1094 }
1095 
OnDisconnectError(const ErrorCallback & error_callback,const std::string & error_name,const std::string & error_message)1096 void BluetoothDeviceBlueZ::OnDisconnectError(
1097     const ErrorCallback& error_callback,
1098     const std::string& error_name,
1099     const std::string& error_message) {
1100   BLUETOOTH_LOG(ERROR) << object_path_.value()
1101                        << ": Failed to disconnect device: " << error_name
1102                        << ": " << error_message;
1103   error_callback.Run();
1104 }
1105 
OnForgetError(const ErrorCallback & error_callback,const std::string & error_name,const std::string & error_message)1106 void BluetoothDeviceBlueZ::OnForgetError(const ErrorCallback& error_callback,
1107                                          const std::string& error_name,
1108                                          const std::string& error_message) {
1109   BLUETOOTH_LOG(ERROR) << object_path_.value()
1110                        << ": Failed to remove device: " << error_name << ": "
1111                        << error_message;
1112   error_callback.Run();
1113 }
1114 
UnpauseDiscovery()1115 void BluetoothDeviceBlueZ::UnpauseDiscovery() {
1116   bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->UnpauseDiscovery(
1117       adapter()->object_path(), base::BindOnce([]() {
1118         BLUETOOTH_LOG(EVENT) << "Successfully un-paused discovery";
1119       }),
1120       base::BindOnce(
1121           [](const std::string& error_name, const std::string& error_message) {
1122             BLUETOOTH_LOG(EVENT) << "Failed to un-pause discovery";
1123           }));
1124 }
1125 
1126 }  // namespace bluez
1127