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_adapter_bluez.h"
6
7 #include <algorithm>
8 #include <cstdint>
9 #include <limits>
10 #include <memory>
11 #include <set>
12 #include <string>
13 #include <utility>
14
15 #include "base/bind.h"
16 #include "base/callback_helpers.h"
17 #include "base/location.h"
18 #include "base/logging.h"
19 #include "base/memory/ptr_util.h"
20 #include "base/metrics/histogram_macros.h"
21 #include "base/single_thread_task_runner.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/threading/thread_task_runner_handle.h"
24 #include "base/time/time.h"
25 #include "build/build_config.h"
26 #include "build/chromeos_buildflags.h"
27 #include "components/device_event_log/device_event_log.h"
28 #include "device/bluetooth/bluetooth_common.h"
29 #include "device/bluetooth/bluetooth_device.h"
30 #include "device/bluetooth/bluetooth_discovery_session_outcome.h"
31 #include "device/bluetooth/bluetooth_socket_thread.h"
32 #include "device/bluetooth/bluez/bluetooth_adapter_profile_bluez.h"
33 #include "device/bluetooth/bluez/bluetooth_advertisement_bluez.h"
34 #include "device/bluetooth/bluez/bluetooth_device_bluez.h"
35 #include "device/bluetooth/bluez/bluetooth_gatt_service_bluez.h"
36 #include "device/bluetooth/bluez/bluetooth_local_gatt_characteristic_bluez.h"
37 #include "device/bluetooth/bluez/bluetooth_local_gatt_service_bluez.h"
38 #include "device/bluetooth/bluez/bluetooth_pairing_bluez.h"
39 #include "device/bluetooth/bluez/bluetooth_socket_bluez.h"
40 #include "device/bluetooth/dbus/bluetooth_adapter_client.h"
41 #include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
42 #include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
43 #include "device/bluetooth/dbus/bluetooth_battery_client.h"
44 #include "device/bluetooth/dbus/bluetooth_device_client.h"
45 #include "device/bluetooth/dbus/bluetooth_gatt_application_service_provider.h"
46 #include "device/bluetooth/dbus/bluetooth_gatt_manager_client.h"
47 #include "device/bluetooth/dbus/bluetooth_input_client.h"
48 #include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h"
49 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
50 #include "device/bluetooth/public/cpp/bluetooth_address.h"
51 #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
52 #include "third_party/cros_system_api/dbus/service_constants.h"
53
54 #if BUILDFLAG(IS_ASH)
55 #include "chromeos/constants/devicetype.h"
56 #include "device/bluetooth/bluetooth_adapter_factory.h"
57 #include "device/bluetooth/chromeos/bluetooth_utils.h"
58 #endif
59
60 using device::BluetoothAdapter;
61 using device::BluetoothDevice;
62 using UUIDSet = device::BluetoothDevice::UUIDSet;
63 using device::BluetoothDiscoveryFilter;
64 using device::BluetoothSocket;
65 using device::BluetoothUUID;
66 using device::UMABluetoothDiscoverySessionOutcome;
67
68 namespace {
69
70 // The agent path is relatively meaningless since BlueZ only permits one to
71 // exist per D-Bus connection, it just has to be unique within Chromium.
72 const char kAgentPath[] = "/org/chromium/bluetooth_agent";
73 const char kGattApplicationObjectPath[] = "/gatt_application";
74
OnUnregisterAgentError(const std::string & error_name,const std::string & error_message)75 void OnUnregisterAgentError(const std::string& error_name,
76 const std::string& error_message) {
77 // It's okay if the agent didn't exist, it means we never saw an adapter.
78 if (error_name == bluetooth_agent_manager::kErrorDoesNotExist)
79 return;
80
81 BLUETOOTH_LOG(ERROR) << "Failed to unregister pairing agent: " << error_name
82 << ": " << error_message;
83 }
84
TranslateDiscoveryErrorToUMA(const std::string & error_name)85 UMABluetoothDiscoverySessionOutcome TranslateDiscoveryErrorToUMA(
86 const std::string& error_name) {
87 if (error_name == bluez::BluetoothAdapterClient::kUnknownAdapterError) {
88 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_UNKNOWN_ADAPTER;
89 } else if (error_name == bluez::BluetoothAdapterClient::kNoResponseError) {
90 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_NO_RESPONSE;
91 } else if (error_name == bluetooth_device::kErrorInProgress) {
92 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_IN_PROGRESS;
93 } else if (error_name == bluetooth_device::kErrorNotReady) {
94 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_NOT_READY;
95 } else if (error_name == bluetooth_device::kErrorNotSupported) {
96 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_UNSUPPORTED_DEVICE;
97 } else if (error_name == bluetooth_device::kErrorFailed) {
98 return UMABluetoothDiscoverySessionOutcome::FAILED;
99 } else {
100 BLUETOOTH_LOG(ERROR) << "Unrecognized DBus error " << error_name;
101 return UMABluetoothDiscoverySessionOutcome::UNKNOWN;
102 }
103 }
104
105 #if BUILDFLAG(IS_ASH)
ConvertServiceDataMap(const base::flat_map<std::string,std::vector<uint8_t>> & input)106 device::BluetoothDevice::ServiceDataMap ConvertServiceDataMap(
107 const base::flat_map<std::string, std::vector<uint8_t>>& input) {
108 device::BluetoothDevice::ServiceDataMap output;
109 for (auto& i : input) {
110 output[BluetoothUUID(i.first)] = i.second;
111 }
112
113 return output;
114 }
115
ConvertManufacturerDataMap(const base::flat_map<uint16_t,std::vector<uint8_t>> & input)116 device::BluetoothDevice::ManufacturerDataMap ConvertManufacturerDataMap(
117 const base::flat_map<uint16_t, std::vector<uint8_t>>& input) {
118 return device::BluetoothDevice::ManufacturerDataMap(input.begin(),
119 input.end());
120 }
121 #endif // BUILDFLAG(IS_ASH)
122
123 } // namespace
124
125 namespace device {
126
127 // static
CreateAdapter()128 scoped_refptr<BluetoothAdapter> BluetoothAdapter::CreateAdapter() {
129 return bluez::BluetoothAdapterBlueZ::CreateAdapter();
130 }
131
132 } // namespace device
133
134 namespace bluez {
135
136 namespace {
137
OnRegistrationErrorCallback(device::BluetoothGattService::ErrorCallback error_callback,bool is_register_callback,const std::string & error_name,const std::string & error_message)138 void OnRegistrationErrorCallback(
139 device::BluetoothGattService::ErrorCallback error_callback,
140 bool is_register_callback,
141 const std::string& error_name,
142 const std::string& error_message) {
143 if (is_register_callback) {
144 BLUETOOTH_LOG(ERROR) << "Failed to Register service: " << error_name << ", "
145 << error_message;
146 } else {
147 BLUETOOTH_LOG(ERROR) << "Failed to Unregister service: " << error_name
148 << ", " << error_message;
149 }
150 std::move(error_callback)
151 .Run(BluetoothGattServiceBlueZ::DBusErrorToServiceError(error_name));
152 }
153
SetIntervalErrorCallbackConnector(device::BluetoothAdapter::AdvertisementErrorCallback error_callback,const std::string & error_name,const std::string & error_message)154 void SetIntervalErrorCallbackConnector(
155 device::BluetoothAdapter::AdvertisementErrorCallback error_callback,
156 const std::string& error_name,
157 const std::string& error_message) {
158 BLUETOOTH_LOG(ERROR) << "Error while registering advertisement. error_name = "
159 << error_name << ", error_message = " << error_message;
160
161 device::BluetoothAdvertisement::ErrorCode code = device::
162 BluetoothAdvertisement::ErrorCode::INVALID_ADVERTISEMENT_ERROR_CODE;
163 if (error_name == bluetooth_advertising_manager::kErrorInvalidArguments) {
164 code = device::BluetoothAdvertisement::ErrorCode::
165 ERROR_INVALID_ADVERTISEMENT_INTERVAL;
166 }
167 std::move(error_callback).Run(code);
168 }
169
ResetAdvertisingErrorCallbackConnector(device::BluetoothAdapter::AdvertisementErrorCallback error_callback,const std::string & error_name,const std::string & error_message)170 void ResetAdvertisingErrorCallbackConnector(
171 device::BluetoothAdapter::AdvertisementErrorCallback error_callback,
172 const std::string& error_name,
173 const std::string& error_message) {
174 BLUETOOTH_LOG(ERROR) << "Error while resetting advertising. error_name = "
175 << error_name << ", error_message = " << error_message;
176
177 std::move(error_callback)
178 .Run(device::BluetoothAdvertisement::ErrorCode::ERROR_RESET_ADVERTISING);
179 }
180
181 } // namespace
182
183 // static
CreateAdapter()184 scoped_refptr<BluetoothAdapterBlueZ> BluetoothAdapterBlueZ::CreateAdapter() {
185 return base::WrapRefCounted(new BluetoothAdapterBlueZ());
186 }
187
Initialize(base::OnceClosure callback)188 void BluetoothAdapterBlueZ::Initialize(base::OnceClosure callback) {
189 init_callback_ = std::move(callback);
190
191 // Can't initialize the adapter until DBus clients are ready.
192 if (bluez::BluezDBusManager::Get()->IsObjectManagerSupportKnown()) {
193 base::ThreadTaskRunnerHandle::Get()->PostTask(
194 FROM_HERE, base::BindOnce(&BluetoothAdapterBlueZ::Init,
195 weak_ptr_factory_.GetWeakPtr()));
196 return;
197 }
198 bluez::BluezDBusManager::Get()->CallWhenObjectManagerSupportIsKnown(
199 base::BindOnce(&BluetoothAdapterBlueZ::Init,
200 weak_ptr_factory_.GetWeakPtr()));
201 }
202
Shutdown()203 void BluetoothAdapterBlueZ::Shutdown() {
204 if (dbus_is_shutdown_)
205 return;
206
207 BLUETOOTH_LOG(EVENT) << "BluetoothAdapterBlueZ::Shutdown";
208
209 DCHECK(bluez::BluezDBusManager::IsInitialized())
210 << "Call BluetoothAdapterFactory::Shutdown() before "
211 "BluezDBusManager::Shutdown().";
212
213 // Since we don't initialize anything if Object Manager is not supported,
214 // no need to do any clean up.
215 if (!bluez::BluezDBusManager::Get()->IsObjectManagerSupported()) {
216 dbus_is_shutdown_ = true;
217 return;
218 }
219
220 if (IsPresent())
221 RemoveAdapter(); // Also deletes devices_.
222 DCHECK(devices_.empty());
223
224 // profiles_ must be empty because all BluetoothSockets have been notified
225 // that this adapter is disappearing.
226 DCHECK(profiles_.empty());
227
228 // Some profiles may have been released but not yet removed; it is safe to
229 // delete them.
230 for (auto& it : released_profiles_)
231 delete it.second;
232 released_profiles_.clear();
233
234 for (auto& it : profile_queues_)
235 delete it.second;
236 profile_queues_.clear();
237
238 // This may call unregister on advertisements that have already been
239 // unregistered but that's fine. The advertisement object keeps a track of
240 // the fact that it has been already unregistered and will call our empty
241 // error callback with an "Already unregistered" error, which we'll ignore.
242 for (auto& it : advertisements_) {
243 it->Unregister(base::DoNothing(), base::DoNothing());
244 }
245 advertisements_.clear();
246
247 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(
248 this);
249 bluez::BluezDBusManager::Get()->GetBluetoothBatteryClient()->RemoveObserver(
250 this);
251 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(
252 this);
253 bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->RemoveObserver(
254 this);
255 bluez::BluezDBusManager::Get()
256 ->GetBluetoothAgentManagerClient()
257 ->RemoveObserver(this);
258
259 BLUETOOTH_LOG(EVENT) << "Unregistering pairing agent";
260 bluez::BluezDBusManager::Get()
261 ->GetBluetoothAgentManagerClient()
262 ->UnregisterAgent(dbus::ObjectPath(kAgentPath), base::DoNothing(),
263 base::BindOnce(&OnUnregisterAgentError));
264
265 agent_.reset();
266
267 dbus_is_shutdown_ = true;
268 }
269
BluetoothAdapterBlueZ()270 BluetoothAdapterBlueZ::BluetoothAdapterBlueZ()
271 : initialized_(false), dbus_is_shutdown_(false) {
272 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
273 socket_thread_ = device::BluetoothSocketThread::Get();
274 }
275
Init()276 void BluetoothAdapterBlueZ::Init() {
277 // We may have been shutdown already, in which case do nothing. If the
278 // platform doesn't support Object Manager then Bluez 5 is probably not
279 // present. In this case we just return without initializing anything.
280 if (dbus_is_shutdown_ ||
281 !bluez::BluezDBusManager::Get()->IsObjectManagerSupported()) {
282 initialized_ = true;
283 std::move(init_callback_).Run();
284 return;
285 }
286
287 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->AddObserver(
288 this);
289 bluez::BluezDBusManager::Get()->GetBluetoothBatteryClient()->AddObserver(
290 this);
291 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
292 bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->AddObserver(this);
293 bluez::BluezDBusManager::Get()->GetBluetoothAgentManagerClient()->AddObserver(
294 this);
295
296 // Register the pairing agent.
297 dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus();
298 agent_.reset(bluez::BluetoothAgentServiceProvider::Create(
299 system_bus, dbus::ObjectPath(kAgentPath), this));
300 DCHECK(agent_.get());
301
302 std::vector<dbus::ObjectPath> object_paths = bluez::BluezDBusManager::Get()
303 ->GetBluetoothAdapterClient()
304 ->GetAdapters();
305
306 BLUETOOTH_LOG(EVENT) << "BlueZ Adapter Initialized.";
307 if (!object_paths.empty()) {
308 BLUETOOTH_LOG(EVENT) << "BlueZ Adapters available: " << object_paths.size();
309 SetAdapter(object_paths[0]);
310 }
311 initialized_ = true;
312 std::move(init_callback_).Run();
313 }
314
~BluetoothAdapterBlueZ()315 BluetoothAdapterBlueZ::~BluetoothAdapterBlueZ() {
316 Shutdown();
317 }
318
GetAddress() const319 std::string BluetoothAdapterBlueZ::GetAddress() const {
320 if (!IsPresent())
321 return std::string();
322
323 bluez::BluetoothAdapterClient::Properties* properties =
324 bluez::BluezDBusManager::Get()
325 ->GetBluetoothAdapterClient()
326 ->GetProperties(object_path_);
327 DCHECK(properties);
328
329 return device::CanonicalizeBluetoothAddress(properties->address.value());
330 }
331
GetName() const332 std::string BluetoothAdapterBlueZ::GetName() const {
333 if (!IsPresent())
334 return std::string();
335
336 bluez::BluetoothAdapterClient::Properties* properties =
337 bluez::BluezDBusManager::Get()
338 ->GetBluetoothAdapterClient()
339 ->GetProperties(object_path_);
340 DCHECK(properties);
341
342 return properties->alias.value();
343 }
344
GetSystemName() const345 std::string BluetoothAdapterBlueZ::GetSystemName() const {
346 if (!IsPresent())
347 return std::string();
348
349 bluez::BluetoothAdapterClient::Properties* properties =
350 bluez::BluezDBusManager::Get()
351 ->GetBluetoothAdapterClient()
352 ->GetProperties(object_path_);
353 DCHECK(properties);
354
355 return properties ? properties->name.value() : std::string();
356 }
357
SetName(const std::string & name,base::OnceClosure callback,ErrorCallback error_callback)358 void BluetoothAdapterBlueZ::SetName(const std::string& name,
359 base::OnceClosure callback,
360 ErrorCallback error_callback) {
361 if (!IsPresent()) {
362 std::move(error_callback).Run();
363 return;
364 }
365
366 bluez::BluezDBusManager::Get()
367 ->GetBluetoothAdapterClient()
368 ->GetProperties(object_path_)
369 ->alias.Set(name, base::BindOnce(
370 &BluetoothAdapterBlueZ::OnPropertyChangeCompleted,
371 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
372 std::move(error_callback)));
373 }
374
IsInitialized() const375 bool BluetoothAdapterBlueZ::IsInitialized() const {
376 return initialized_;
377 }
378
IsPresent() const379 bool BluetoothAdapterBlueZ::IsPresent() const {
380 return !dbus_is_shutdown_ && !object_path_.value().empty();
381 }
382
IsPowered() const383 bool BluetoothAdapterBlueZ::IsPowered() const {
384 if (!IsPresent())
385 return false;
386
387 bluez::BluetoothAdapterClient::Properties* properties =
388 bluez::BluezDBusManager::Get()
389 ->GetBluetoothAdapterClient()
390 ->GetProperties(object_path_);
391
392 return properties->powered.value();
393 }
394
SetPowered(bool powered,base::OnceClosure callback,ErrorCallback error_callback)395 void BluetoothAdapterBlueZ::SetPowered(bool powered,
396 base::OnceClosure callback,
397 ErrorCallback error_callback) {
398 if (!IsPresent()) {
399 BLUETOOTH_LOG(ERROR) << "SetPowered: " << powered << ". Not Present!";
400 std::move(error_callback).Run();
401 return;
402 }
403
404 BLUETOOTH_LOG(EVENT) << "SetPowered: " << powered;
405
406 bluez::BluezDBusManager::Get()
407 ->GetBluetoothAdapterClient()
408 ->GetProperties(object_path_)
409 ->powered.Set(
410 powered,
411 base::BindOnce(&BluetoothAdapterBlueZ::OnPropertyChangeCompleted,
412 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
413 std::move(error_callback)));
414 }
415
IsDiscoverable() const416 bool BluetoothAdapterBlueZ::IsDiscoverable() const {
417 if (!IsPresent())
418 return false;
419
420 bluez::BluetoothAdapterClient::Properties* properties =
421 bluez::BluezDBusManager::Get()
422 ->GetBluetoothAdapterClient()
423 ->GetProperties(object_path_);
424
425 return properties->discoverable.value();
426 }
427
SetDiscoverable(bool discoverable,base::OnceClosure callback,ErrorCallback error_callback)428 void BluetoothAdapterBlueZ::SetDiscoverable(bool discoverable,
429 base::OnceClosure callback,
430 ErrorCallback error_callback) {
431 if (!IsPresent()) {
432 std::move(error_callback).Run();
433 return;
434 }
435
436 BLUETOOTH_LOG(EVENT) << "SetDiscoverable: " << discoverable;
437
438 bluez::BluezDBusManager::Get()
439 ->GetBluetoothAdapterClient()
440 ->GetProperties(object_path_)
441 ->discoverable.Set(
442 discoverable,
443 base::BindOnce(&BluetoothAdapterBlueZ::OnSetDiscoverable,
444 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
445 std::move(error_callback)));
446 }
447
GetDiscoverableTimeout() const448 uint32_t BluetoothAdapterBlueZ::GetDiscoverableTimeout() const {
449 if (!IsPresent())
450 return 0;
451
452 bluez::BluetoothAdapterClient::Properties* properties =
453 bluez::BluezDBusManager::Get()
454 ->GetBluetoothAdapterClient()
455 ->GetProperties(object_path_);
456
457 return properties->discoverable_timeout.value();
458 }
459
IsDiscovering() const460 bool BluetoothAdapterBlueZ::IsDiscovering() const {
461 if (!IsPresent())
462 return false;
463
464 return NumScanningDiscoverySessions() > 0;
465 }
466
IsDiscoveringForTesting() const467 bool BluetoothAdapterBlueZ::IsDiscoveringForTesting() const {
468 if (!IsPresent())
469 return false;
470
471 bluez::BluetoothAdapterClient::Properties* properties =
472 bluez::BluezDBusManager::Get()
473 ->GetBluetoothAdapterClient()
474 ->GetProperties(object_path_);
475 return properties->discovering.value();
476 }
477
478 std::unordered_map<BluetoothDevice*, UUIDSet>
RetrieveGattConnectedDevicesWithDiscoveryFilter(const BluetoothDiscoveryFilter & discovery_filter)479 BluetoothAdapterBlueZ::RetrieveGattConnectedDevicesWithDiscoveryFilter(
480 const BluetoothDiscoveryFilter& discovery_filter) {
481 std::unordered_map<BluetoothDevice*, UUIDSet> connected_devices;
482
483 std::set<BluetoothUUID> filter_uuids;
484 discovery_filter.GetUUIDs(filter_uuids);
485
486 for (BluetoothDevice* device : GetDevices()) {
487 if (device->IsGattConnected() &&
488 (device->GetType() & device::BLUETOOTH_TRANSPORT_LE)) {
489 UUIDSet device_uuids = device->GetUUIDs();
490
491 UUIDSet intersection;
492 for (const BluetoothUUID& uuid : filter_uuids) {
493 if (base::Contains(device_uuids, uuid)) {
494 intersection.insert(uuid);
495 }
496 }
497
498 if (filter_uuids.empty() || !intersection.empty()) {
499 connected_devices[device] = std::move(intersection);
500 }
501 }
502 }
503
504 return connected_devices;
505 }
506
GetUUIDs() const507 BluetoothAdapterBlueZ::UUIDList BluetoothAdapterBlueZ::GetUUIDs() const {
508 if (!IsPresent())
509 return UUIDList();
510
511 bluez::BluetoothAdapterClient::Properties* properties =
512 bluez::BluezDBusManager::Get()
513 ->GetBluetoothAdapterClient()
514 ->GetProperties(object_path_);
515 DCHECK(properties);
516
517 std::vector<std::string> uuids = properties->uuids.value();
518
519 return UUIDList(uuids.begin(), uuids.end());
520 }
521
CreateRfcommService(const BluetoothUUID & uuid,const ServiceOptions & options,CreateServiceCallback callback,CreateServiceErrorCallback error_callback)522 void BluetoothAdapterBlueZ::CreateRfcommService(
523 const BluetoothUUID& uuid,
524 const ServiceOptions& options,
525 CreateServiceCallback callback,
526 CreateServiceErrorCallback error_callback) {
527 DCHECK(!dbus_is_shutdown_);
528 BLUETOOTH_LOG(DEBUG) << object_path_.value() << ": Creating RFCOMM service: "
529 << uuid.canonical_value();
530 scoped_refptr<BluetoothSocketBlueZ> socket =
531 BluetoothSocketBlueZ::CreateBluetoothSocket(ui_task_runner_,
532 socket_thread_);
533 socket->Listen(this, BluetoothSocketBlueZ::kRfcomm, uuid, options,
534 base::BindOnce(std::move(callback), socket),
535 std::move(error_callback));
536 }
537
CreateL2capService(const BluetoothUUID & uuid,const ServiceOptions & options,CreateServiceCallback callback,CreateServiceErrorCallback error_callback)538 void BluetoothAdapterBlueZ::CreateL2capService(
539 const BluetoothUUID& uuid,
540 const ServiceOptions& options,
541 CreateServiceCallback callback,
542 CreateServiceErrorCallback error_callback) {
543 DCHECK(!dbus_is_shutdown_);
544 BLUETOOTH_LOG(DEBUG) << object_path_.value() << ": Creating L2CAP service: "
545 << uuid.canonical_value();
546 scoped_refptr<BluetoothSocketBlueZ> socket =
547 BluetoothSocketBlueZ::CreateBluetoothSocket(ui_task_runner_,
548 socket_thread_);
549 socket->Listen(this, BluetoothSocketBlueZ::kL2cap, uuid, options,
550 base::BindOnce(std::move(callback), socket),
551 std::move(error_callback));
552 }
553
RegisterAdvertisement(std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement_data,CreateAdvertisementCallback callback,AdvertisementErrorCallback error_callback)554 void BluetoothAdapterBlueZ::RegisterAdvertisement(
555 std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement_data,
556 CreateAdvertisementCallback callback,
557 AdvertisementErrorCallback error_callback) {
558 scoped_refptr<BluetoothAdvertisementBlueZ> advertisement(
559 new BluetoothAdvertisementBlueZ(std::move(advertisement_data), this));
560 advertisement->Register(base::BindOnce(std::move(callback), advertisement),
561 std::move(error_callback));
562 advertisements_.emplace_back(advertisement);
563 }
564
SetAdvertisingInterval(const base::TimeDelta & min,const base::TimeDelta & max,base::OnceClosure callback,AdvertisementErrorCallback error_callback)565 void BluetoothAdapterBlueZ::SetAdvertisingInterval(
566 const base::TimeDelta& min,
567 const base::TimeDelta& max,
568 base::OnceClosure callback,
569 AdvertisementErrorCallback error_callback) {
570 DCHECK(bluez::BluezDBusManager::Get());
571 uint16_t min_ms = static_cast<uint16_t>(
572 std::min(static_cast<int64_t>(std::numeric_limits<uint16_t>::max()),
573 min.InMilliseconds()));
574 uint16_t max_ms = static_cast<uint16_t>(
575 std::min(static_cast<int64_t>(std::numeric_limits<uint16_t>::max()),
576 max.InMilliseconds()));
577 bluez::BluezDBusManager::Get()
578 ->GetBluetoothLEAdvertisingManagerClient()
579 ->SetAdvertisingInterval(
580 object_path_, min_ms, max_ms, std::move(callback),
581 base::BindOnce(&SetIntervalErrorCallbackConnector,
582 std::move(error_callback)));
583 }
584
ResetAdvertising(base::OnceClosure callback,AdvertisementErrorCallback error_callback)585 void BluetoothAdapterBlueZ::ResetAdvertising(
586 base::OnceClosure callback,
587 AdvertisementErrorCallback error_callback) {
588 DCHECK(bluez::BluezDBusManager::Get());
589 bluez::BluezDBusManager::Get()
590 ->GetBluetoothLEAdvertisingManagerClient()
591 ->ResetAdvertising(object_path_, std::move(callback),
592 base::BindOnce(&ResetAdvertisingErrorCallbackConnector,
593 std::move(error_callback)));
594 }
595
ConnectDevice(const std::string & address,const base::Optional<device::BluetoothDevice::AddressType> & address_type,ConnectDeviceCallback callback,ErrorCallback error_callback)596 void BluetoothAdapterBlueZ::ConnectDevice(
597 const std::string& address,
598 const base::Optional<device::BluetoothDevice::AddressType>& address_type,
599 ConnectDeviceCallback callback,
600 ErrorCallback error_callback) {
601 DCHECK(bluez::BluezDBusManager::Get());
602
603 base::Optional<BluetoothAdapterClient::AddressType> client_address_type;
604 if (address_type) {
605 switch (*address_type) {
606 case device::BluetoothDevice::AddressType::ADDR_TYPE_PUBLIC:
607 client_address_type = BluetoothAdapterClient::AddressType::kPublic;
608 break;
609 case device::BluetoothDevice::AddressType::ADDR_TYPE_RANDOM:
610 client_address_type = BluetoothAdapterClient::AddressType::kRandom;
611 break;
612 case device::BluetoothDevice::AddressType::ADDR_TYPE_UNKNOWN:
613 default:
614 // Keep |client_address_type| unset.
615 break;
616 };
617 }
618
619 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->ConnectDevice(
620 object_path_, address, client_address_type,
621 base::BindOnce(&BluetoothAdapterBlueZ::OnConnectDevice,
622 weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
623 base::BindOnce(&BluetoothAdapterBlueZ::OnConnectDeviceError,
624 weak_ptr_factory_.GetWeakPtr(),
625 std::move(error_callback)));
626 }
627
GetGattService(const std::string & identifier) const628 device::BluetoothLocalGattService* BluetoothAdapterBlueZ::GetGattService(
629 const std::string& identifier) const {
630 const auto& service = owned_gatt_services_.find(dbus::ObjectPath(identifier));
631 return service == owned_gatt_services_.end() ? nullptr
632 : service->second.get();
633 }
634
RemovePairingDelegateInternal(BluetoothDevice::PairingDelegate * pairing_delegate)635 void BluetoothAdapterBlueZ::RemovePairingDelegateInternal(
636 BluetoothDevice::PairingDelegate* pairing_delegate) {
637 // Check if any device is using the pairing delegate.
638 // If so, clear the pairing context which will make any responses no-ops.
639 for (auto iter = devices_.begin(); iter != devices_.end(); ++iter) {
640 BluetoothDeviceBlueZ* device_bluez =
641 static_cast<BluetoothDeviceBlueZ*>(iter->second.get());
642
643 BluetoothPairingBlueZ* pairing = device_bluez->GetPairing();
644 if (pairing && pairing->GetPairingDelegate() == pairing_delegate)
645 device_bluez->EndPairing();
646 }
647 }
648
AdapterAdded(const dbus::ObjectPath & object_path)649 void BluetoothAdapterBlueZ::AdapterAdded(const dbus::ObjectPath& object_path) {
650 // Set the adapter to the newly added adapter only if no adapter is present.
651 if (!IsPresent())
652 SetAdapter(object_path);
653 }
654
AdapterRemoved(const dbus::ObjectPath & object_path)655 void BluetoothAdapterBlueZ::AdapterRemoved(
656 const dbus::ObjectPath& object_path) {
657 if (object_path == object_path_)
658 RemoveAdapter();
659 }
660
AdapterPropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)661 void BluetoothAdapterBlueZ::AdapterPropertyChanged(
662 const dbus::ObjectPath& object_path,
663 const std::string& property_name) {
664 if (object_path != object_path_)
665 return;
666 DCHECK(IsPresent());
667
668 bluez::BluetoothAdapterClient::Properties* properties =
669 bluez::BluezDBusManager::Get()
670 ->GetBluetoothAdapterClient()
671 ->GetProperties(object_path_);
672
673 if (property_name == properties->powered.name()) {
674 NotifyAdapterPoweredChanged(properties->powered.value());
675 } else if (property_name == properties->discoverable.name()) {
676 DiscoverableChanged(properties->discoverable.value());
677 } else if (property_name == properties->discovering.name()) {
678 DiscoveringChanged(properties->discovering.value());
679 }
680 }
681
BatteryAdded(const dbus::ObjectPath & object_path)682 void BluetoothAdapterBlueZ::BatteryAdded(const dbus::ObjectPath& object_path) {
683 BLUETOOTH_LOG(DEBUG) << "Battery added " << object_path.value();
684
685 UpdateDeviceBatteryLevelFromBatteryClient(object_path);
686 }
687
BatteryRemoved(const dbus::ObjectPath & object_path)688 void BluetoothAdapterBlueZ::BatteryRemoved(
689 const dbus::ObjectPath& object_path) {
690 BLUETOOTH_LOG(DEBUG) << "Battery removed " << object_path.value();
691
692 UpdateDeviceBatteryLevelFromBatteryClient(object_path);
693 }
694
BatteryPropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)695 void BluetoothAdapterBlueZ::BatteryPropertyChanged(
696 const dbus::ObjectPath& object_path,
697 const std::string& property_name) {
698 BLUETOOTH_LOG(DEBUG) << "Battery property changed " << object_path.value();
699
700 if (property_name == bluetooth_battery::kPercentageProperty)
701 UpdateDeviceBatteryLevelFromBatteryClient(object_path);
702 }
703
DeviceAdded(const dbus::ObjectPath & object_path)704 void BluetoothAdapterBlueZ::DeviceAdded(const dbus::ObjectPath& object_path) {
705 DCHECK(bluez::BluezDBusManager::Get());
706 bluez::BluetoothDeviceClient::Properties* properties =
707 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
708 object_path);
709 if (!properties || properties->adapter.value() != object_path_)
710 return;
711 DCHECK(IsPresent());
712
713 BluetoothDeviceBlueZ* device_bluez = new BluetoothDeviceBlueZ(
714 this, object_path, ui_task_runner_, socket_thread_);
715 DCHECK(devices_.find(device_bluez->GetAddress()) == devices_.end());
716
717 devices_[device_bluez->GetAddress()] = base::WrapUnique(device_bluez);
718
719 if (properties->rssi.is_valid() && properties->eir.is_valid()) {
720 NotifyDeviceAdvertisementReceived(device_bluez, properties->rssi.value(),
721 properties->eir.value());
722 }
723
724 for (auto& observer : observers_)
725 observer.DeviceAdded(this, device_bluez);
726 }
727
DeviceRemoved(const dbus::ObjectPath & object_path)728 void BluetoothAdapterBlueZ::DeviceRemoved(const dbus::ObjectPath& object_path) {
729 for (auto iter = devices_.begin(); iter != devices_.end(); ++iter) {
730 BluetoothDeviceBlueZ* device_bluez =
731 static_cast<BluetoothDeviceBlueZ*>(iter->second.get());
732 if (device_bluez->object_path() == object_path) {
733 std::unique_ptr<BluetoothDevice> scoped_device = std::move(iter->second);
734 devices_.erase(iter);
735
736 for (auto& observer : observers_)
737 observer.DeviceRemoved(this, device_bluez);
738 return;
739 }
740 }
741 }
742
DevicePropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)743 void BluetoothAdapterBlueZ::DevicePropertyChanged(
744 const dbus::ObjectPath& object_path,
745 const std::string& property_name) {
746 BluetoothDeviceBlueZ* device_bluez = GetDeviceWithPath(object_path);
747 if (!device_bluez)
748 return;
749
750 bluez::BluetoothDeviceClient::Properties* properties =
751 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
752 object_path);
753
754 if (property_name == properties->address.name()) {
755 for (auto iter = devices_.begin(); iter != devices_.end(); ++iter) {
756 if (iter->second->GetAddress() == device_bluez->GetAddress()) {
757 std::string old_address = iter->first;
758 BLUETOOTH_LOG(EVENT) << "Device changed address, old: " << old_address
759 << " new: " << device_bluez->GetAddress();
760 std::unique_ptr<BluetoothDevice> scoped_device =
761 std::move(iter->second);
762 devices_.erase(iter);
763
764 DCHECK(devices_.find(device_bluez->GetAddress()) == devices_.end());
765 devices_[device_bluez->GetAddress()] = std::move(scoped_device);
766 NotifyDeviceAddressChanged(device_bluez, old_address);
767 break;
768 }
769 }
770 }
771
772 if (property_name == properties->service_data.name())
773 device_bluez->UpdateServiceData();
774 else if (property_name == properties->manufacturer_data.name())
775 device_bluez->UpdateManufacturerData();
776 else if (property_name == properties->advertising_data_flags.name())
777 device_bluez->UpdateAdvertisingDataFlags();
778
779 if (property_name == properties->bluetooth_class.name() ||
780 property_name == properties->appearance.name() ||
781 property_name == properties->address.name() ||
782 property_name == properties->name.name() ||
783 property_name == properties->paired.name() ||
784 property_name == properties->trusted.name() ||
785 property_name == properties->connected.name() ||
786 property_name == properties->uuids.name() ||
787 property_name == properties->rssi.name() ||
788 property_name == properties->tx_power.name() ||
789 property_name == properties->service_data.name() ||
790 property_name == properties->manufacturer_data.name() ||
791 property_name == properties->advertising_data_flags.name()) {
792 NotifyDeviceChanged(device_bluez);
793 }
794
795 if (property_name == properties->mtu.name())
796 NotifyDeviceMTUChanged(device_bluez, properties->mtu.value());
797
798 // Bluez does not currently provide an explicit signal for an advertisement
799 // packet being received. Currently, it implicitly does so by notifying of an
800 // RSSI change. We also listen for whether the EIR packet data has changed.
801 if ((property_name == properties->rssi.name() ||
802 property_name == properties->eir.name()) &&
803 properties->rssi.is_valid() && properties->eir.is_valid()) {
804 NotifyDeviceAdvertisementReceived(device_bluez, properties->rssi.value(),
805 properties->eir.value());
806 }
807
808 if (property_name == properties->connected.name())
809 NotifyDeviceConnectedStateChanged(device_bluez,
810 properties->connected.value());
811
812 if (property_name == properties->services_resolved.name() &&
813 properties->services_resolved.value()) {
814 device_bluez->UpdateGattServices(object_path);
815 NotifyGattServicesDiscovered(device_bluez);
816 }
817
818 // When a device becomes paired, mark it as trusted so that the user does
819 // not need to approve every incoming connection
820 if (property_name == properties->paired.name()) {
821 if (properties->paired.value() && !properties->trusted.value()) {
822 device_bluez->SetTrusted();
823 }
824 NotifyDevicePairedChanged(device_bluez, properties->paired.value());
825 }
826
827 // UMA connection counting
828 if (property_name == properties->connected.name()) {
829 int count = 0;
830
831 for (auto iter = devices_.begin(); iter != devices_.end(); ++iter) {
832 if (iter->second->IsPaired() && iter->second->IsConnected())
833 ++count;
834 }
835
836 UMA_HISTOGRAM_COUNTS_100("Bluetooth.ConnectedDeviceCount", count);
837 }
838 }
839
InputPropertyChanged(const dbus::ObjectPath & object_path,const std::string & property_name)840 void BluetoothAdapterBlueZ::InputPropertyChanged(
841 const dbus::ObjectPath& object_path,
842 const std::string& property_name) {
843 BluetoothDeviceBlueZ* device_bluez = GetDeviceWithPath(object_path);
844 if (!device_bluez)
845 return;
846
847 bluez::BluetoothInputClient::Properties* properties =
848 bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->GetProperties(
849 object_path);
850
851 // Properties structure can be removed, which triggers a change in the
852 // BluetoothDevice::IsConnectable() property, as does a change in the
853 // actual reconnect_mode property.
854 if (!properties || property_name == properties->reconnect_mode.name()) {
855 NotifyDeviceChanged(device_bluez);
856 }
857 }
858
AgentManagerAdded(const dbus::ObjectPath & object_path)859 void BluetoothAdapterBlueZ::AgentManagerAdded(
860 const dbus::ObjectPath& object_path) {
861 BLUETOOTH_LOG(DEBUG) << "Registering pairing agent";
862 bluez::BluezDBusManager::Get()
863 ->GetBluetoothAgentManagerClient()
864 ->RegisterAgent(
865 dbus::ObjectPath(kAgentPath),
866 bluetooth_agent_manager::kKeyboardDisplayCapability,
867 base::BindOnce(&BluetoothAdapterBlueZ::OnRegisterAgent,
868 weak_ptr_factory_.GetWeakPtr()),
869 base::BindOnce(&BluetoothAdapterBlueZ::OnRegisterAgentError,
870 weak_ptr_factory_.GetWeakPtr()));
871 }
872
AgentManagerRemoved(const dbus::ObjectPath & object_path)873 void BluetoothAdapterBlueZ::AgentManagerRemoved(
874 const dbus::ObjectPath& object_path) {}
875
Released()876 void BluetoothAdapterBlueZ::Released() {
877 BLUETOOTH_LOG(EVENT) << "Released";
878 if (!IsPresent())
879 return;
880 DCHECK(agent_.get());
881
882 // Called after we unregister the pairing agent, e.g. when changing I/O
883 // capabilities. Nothing much to be done right now.
884 }
885
RequestPinCode(const dbus::ObjectPath & device_path,PinCodeCallback callback)886 void BluetoothAdapterBlueZ::RequestPinCode(const dbus::ObjectPath& device_path,
887 PinCodeCallback callback) {
888 DCHECK(IsPresent());
889 DCHECK(agent_.get());
890 BLUETOOTH_LOG(EVENT) << device_path.value() << ": RequestPinCode";
891
892 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
893 if (!pairing) {
894 std::move(callback).Run(REJECTED, "");
895 return;
896 }
897
898 pairing->RequestPinCode(std::move(callback));
899 }
900
DisplayPinCode(const dbus::ObjectPath & device_path,const std::string & pincode)901 void BluetoothAdapterBlueZ::DisplayPinCode(const dbus::ObjectPath& device_path,
902 const std::string& pincode) {
903 DCHECK(IsPresent());
904 DCHECK(agent_.get());
905 BLUETOOTH_LOG(EVENT) << device_path.value()
906 << ": DisplayPinCode: " << pincode;
907
908 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
909 if (!pairing)
910 return;
911
912 pairing->DisplayPinCode(pincode);
913 }
914
RequestPasskey(const dbus::ObjectPath & device_path,PasskeyCallback callback)915 void BluetoothAdapterBlueZ::RequestPasskey(const dbus::ObjectPath& device_path,
916 PasskeyCallback callback) {
917 DCHECK(IsPresent());
918 DCHECK(agent_.get());
919 BLUETOOTH_LOG(EVENT) << device_path.value() << ": RequestPasskey";
920
921 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
922 if (!pairing) {
923 std::move(callback).Run(REJECTED, 0);
924 return;
925 }
926
927 pairing->RequestPasskey(std::move(callback));
928 }
929
DisplayPasskey(const dbus::ObjectPath & device_path,uint32_t passkey,uint16_t entered)930 void BluetoothAdapterBlueZ::DisplayPasskey(const dbus::ObjectPath& device_path,
931 uint32_t passkey,
932 uint16_t entered) {
933 DCHECK(IsPresent());
934 DCHECK(agent_.get());
935 BLUETOOTH_LOG(EVENT) << device_path.value() << ": DisplayPasskey: " << passkey
936 << " (" << entered << " entered)";
937
938 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
939 if (!pairing)
940 return;
941
942 if (entered == 0)
943 pairing->DisplayPasskey(passkey);
944
945 pairing->KeysEntered(entered);
946 }
947
RequestConfirmation(const dbus::ObjectPath & device_path,uint32_t passkey,ConfirmationCallback callback)948 void BluetoothAdapterBlueZ::RequestConfirmation(
949 const dbus::ObjectPath& device_path,
950 uint32_t passkey,
951 ConfirmationCallback callback) {
952 DCHECK(IsPresent());
953 DCHECK(agent_.get());
954 BLUETOOTH_LOG(EVENT) << device_path.value()
955 << ": RequestConfirmation: " << passkey;
956
957 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
958 if (!pairing) {
959 std::move(callback).Run(REJECTED);
960 return;
961 }
962
963 pairing->RequestConfirmation(passkey, std::move(callback));
964 }
965
RequestAuthorization(const dbus::ObjectPath & device_path,ConfirmationCallback callback)966 void BluetoothAdapterBlueZ::RequestAuthorization(
967 const dbus::ObjectPath& device_path,
968 ConfirmationCallback callback) {
969 DCHECK(IsPresent());
970 DCHECK(agent_.get());
971 BLUETOOTH_LOG(EVENT) << device_path.value() << ": RequestAuthorization";
972
973 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
974 if (!pairing) {
975 std::move(callback).Run(REJECTED);
976 return;
977 }
978
979 pairing->RequestAuthorization(std::move(callback));
980 }
981
AuthorizeService(const dbus::ObjectPath & device_path,const std::string & uuid,ConfirmationCallback callback)982 void BluetoothAdapterBlueZ::AuthorizeService(
983 const dbus::ObjectPath& device_path,
984 const std::string& uuid,
985 ConfirmationCallback callback) {
986 DCHECK(IsPresent());
987 DCHECK(agent_.get());
988 BLUETOOTH_LOG(EVENT) << device_path.value() << ": AuthorizeService: " << uuid;
989
990 BluetoothDeviceBlueZ* device_bluez = GetDeviceWithPath(device_path);
991 if (!device_bluez) {
992 std::move(callback).Run(CANCELLED);
993 return;
994 }
995
996 // We always set paired devices to Trusted, so the only reason that this
997 // method call would ever be called is in the case of a race condition where
998 // our "Set('Trusted', true)" method call is still pending in the Bluetooth
999 // daemon because it's busy handling the incoming connection.
1000 if (device_bluez->IsPaired()) {
1001 std::move(callback).Run(SUCCESS);
1002 return;
1003 }
1004
1005 // TODO(keybuk): reject service authorizations when not paired, determine
1006 // whether this is acceptable long-term.
1007 BLUETOOTH_LOG(ERROR) << "Rejecting service connection from unpaired device "
1008 << device_bluez->GetAddress() << " for UUID " << uuid;
1009 std::move(callback).Run(REJECTED);
1010 }
1011
Cancel()1012 void BluetoothAdapterBlueZ::Cancel() {
1013 DCHECK(IsPresent());
1014 DCHECK(agent_.get());
1015 BLUETOOTH_LOG(EVENT) << "Cancel";
1016 }
1017
OnRegisterAgent()1018 void BluetoothAdapterBlueZ::OnRegisterAgent() {
1019 BLUETOOTH_LOG(EVENT)
1020 << "Pairing agent registered, requesting to be made default";
1021
1022 bluez::BluezDBusManager::Get()
1023 ->GetBluetoothAgentManagerClient()
1024 ->RequestDefaultAgent(
1025 dbus::ObjectPath(kAgentPath),
1026 base::BindOnce(&BluetoothAdapterBlueZ::OnRequestDefaultAgent,
1027 weak_ptr_factory_.GetWeakPtr()),
1028 base::BindOnce(&BluetoothAdapterBlueZ::OnRequestDefaultAgentError,
1029 weak_ptr_factory_.GetWeakPtr()));
1030 }
1031
OnRegisterAgentError(const std::string & error_name,const std::string & error_message)1032 void BluetoothAdapterBlueZ::OnRegisterAgentError(
1033 const std::string& error_name,
1034 const std::string& error_message) {
1035 // Our agent being already registered isn't an error.
1036 if (error_name == bluetooth_agent_manager::kErrorAlreadyExists)
1037 return;
1038
1039 BLUETOOTH_LOG(ERROR) << "Failed to register pairing agent: " << error_name
1040 << ": " << error_message;
1041 }
1042
OnRequestDefaultAgent()1043 void BluetoothAdapterBlueZ::OnRequestDefaultAgent() {
1044 BLUETOOTH_LOG(EVENT) << "Pairing agent now default";
1045 }
1046
OnRequestDefaultAgentError(const std::string & error_name,const std::string & error_message)1047 void BluetoothAdapterBlueZ::OnRequestDefaultAgentError(
1048 const std::string& error_name,
1049 const std::string& error_message) {
1050 BLUETOOTH_LOG(ERROR) << "Failed to make pairing agent default: " << error_name
1051 << ": " << error_message;
1052 }
1053
CreateServiceRecord(const BluetoothServiceRecordBlueZ & record,ServiceRecordCallback callback,ServiceRecordErrorCallback error_callback)1054 void BluetoothAdapterBlueZ::CreateServiceRecord(
1055 const BluetoothServiceRecordBlueZ& record,
1056 ServiceRecordCallback callback,
1057 ServiceRecordErrorCallback error_callback) {
1058 bluez::BluezDBusManager::Get()
1059 ->GetBluetoothAdapterClient()
1060 ->CreateServiceRecord(
1061 object_path_, record, std::move(callback),
1062 base::BindOnce(&BluetoothAdapterBlueZ::ServiceRecordErrorConnector,
1063 weak_ptr_factory_.GetWeakPtr(),
1064 std::move(error_callback)));
1065 }
1066
RemoveServiceRecord(uint32_t handle,base::OnceClosure callback,ServiceRecordErrorCallback error_callback)1067 void BluetoothAdapterBlueZ::RemoveServiceRecord(
1068 uint32_t handle,
1069 base::OnceClosure callback,
1070 ServiceRecordErrorCallback error_callback) {
1071 bluez::BluezDBusManager::Get()
1072 ->GetBluetoothAdapterClient()
1073 ->RemoveServiceRecord(
1074 object_path_, handle, std::move(callback),
1075 base::BindOnce(&BluetoothAdapterBlueZ::ServiceRecordErrorConnector,
1076 weak_ptr_factory_.GetWeakPtr(),
1077 std::move(error_callback)));
1078 }
1079
GetDeviceWithPath(const dbus::ObjectPath & object_path)1080 BluetoothDeviceBlueZ* BluetoothAdapterBlueZ::GetDeviceWithPath(
1081 const dbus::ObjectPath& object_path) {
1082 if (!IsPresent())
1083 return nullptr;
1084
1085 for (auto iter = devices_.begin(); iter != devices_.end(); ++iter) {
1086 BluetoothDeviceBlueZ* device_bluez =
1087 static_cast<BluetoothDeviceBlueZ*>(iter->second.get());
1088 if (device_bluez->object_path() == object_path)
1089 return device_bluez;
1090 }
1091
1092 return nullptr;
1093 }
1094
GetPairing(const dbus::ObjectPath & object_path)1095 BluetoothPairingBlueZ* BluetoothAdapterBlueZ::GetPairing(
1096 const dbus::ObjectPath& object_path) {
1097 DCHECK(IsPresent());
1098 BluetoothDeviceBlueZ* device_bluez = GetDeviceWithPath(object_path);
1099 if (!device_bluez) {
1100 BLUETOOTH_LOG(ERROR) << "Pairing Agent request for unknown device: "
1101 << object_path.value();
1102 return nullptr;
1103 }
1104
1105 BluetoothPairingBlueZ* pairing = device_bluez->GetPairing();
1106 if (pairing)
1107 return pairing;
1108
1109 // The device doesn't have its own pairing context, so this is an incoming
1110 // pairing request that should use our best default delegate (if we have one).
1111 BluetoothDevice::PairingDelegate* pairing_delegate = DefaultPairingDelegate();
1112 if (!pairing_delegate)
1113 return nullptr;
1114
1115 return device_bluez->BeginPairing(pairing_delegate);
1116 }
1117
SetAdapter(const dbus::ObjectPath & object_path)1118 void BluetoothAdapterBlueZ::SetAdapter(const dbus::ObjectPath& object_path) {
1119 DCHECK(!IsPresent());
1120 DCHECK(!dbus_is_shutdown_);
1121 object_path_ = object_path;
1122
1123 BLUETOOTH_LOG(EVENT) << object_path_.value() << ": using adapter.";
1124
1125 #if BUILDFLAG(IS_ASH)
1126 SetStandardChromeOSAdapterName();
1127 #endif
1128
1129 bluez::BluetoothAdapterClient::Properties* properties =
1130 bluez::BluezDBusManager::Get()
1131 ->GetBluetoothAdapterClient()
1132 ->GetProperties(object_path_);
1133
1134 PresentChanged(true);
1135
1136 if (properties->powered.value())
1137 NotifyAdapterPoweredChanged(true);
1138 if (properties->discoverable.value())
1139 DiscoverableChanged(true);
1140 if (properties->discovering.value())
1141 DiscoveringChanged(true);
1142
1143 std::vector<dbus::ObjectPath> device_paths =
1144 bluez::BluezDBusManager::Get()
1145 ->GetBluetoothDeviceClient()
1146 ->GetDevicesForAdapter(object_path_);
1147
1148 for (auto iter = device_paths.begin(); iter != device_paths.end(); ++iter) {
1149 DeviceAdded(*iter);
1150 }
1151 }
1152
1153 #if BUILDFLAG(IS_ASH)
SetStandardChromeOSAdapterName()1154 void BluetoothAdapterBlueZ::SetStandardChromeOSAdapterName() {
1155 DCHECK(IsPresent());
1156
1157 std::string alias;
1158 switch (chromeos::GetDeviceType()) {
1159 case chromeos::DeviceType::kChromebase:
1160 alias = "Chromebase";
1161 break;
1162 case chromeos::DeviceType::kChromebit:
1163 alias = "Chromebit";
1164 break;
1165 case chromeos::DeviceType::kChromebook:
1166 alias = "Chromebook";
1167 break;
1168 case chromeos::DeviceType::kChromebox:
1169 alias = "Chromebox";
1170 break;
1171 case chromeos::DeviceType::kUnknown:
1172 alias = "Chromebook";
1173 break;
1174 }
1175 // Take the lower 2 bytes of hashed Bluetooth address and combine it with the
1176 // device type to create a more identifiable device name.
1177 const std::string address = GetAddress();
1178 alias = base::StringPrintf("%s_%04X", alias.c_str(),
1179 base::PersistentHash(address) & 0xFFFF);
1180 SetName(alias, base::DoNothing(), base::DoNothing());
1181 }
1182 #endif
1183
RemoveAdapter()1184 void BluetoothAdapterBlueZ::RemoveAdapter() {
1185 DCHECK(IsPresent());
1186 BLUETOOTH_LOG(EVENT) << object_path_.value() << ": adapter removed.";
1187
1188 bluez::BluetoothAdapterClient::Properties* properties =
1189 bluez::BluezDBusManager::Get()
1190 ->GetBluetoothAdapterClient()
1191 ->GetProperties(object_path_);
1192
1193 object_path_ = dbus::ObjectPath("");
1194
1195 if (properties->powered.value())
1196 NotifyAdapterPoweredChanged(false);
1197 if (properties->discoverable.value())
1198 DiscoverableChanged(false);
1199
1200 // The properties->discovering.value() may not be up to date with the real
1201 // discovering state (BlueZ bug: http://crbug.com/822104).
1202 // When the adapter is removed, make sure to clear all discovery sessions no
1203 // matter what the current properties->discovering.value() is.
1204 // DiscoveringChanged() properly handles the case where there is no discovery
1205 // sessions currently.
1206 DiscoveringChanged(false);
1207
1208 // Move all elements of the original devices list to a new list here,
1209 // leaving the original list empty so that when we send DeviceRemoved(),
1210 // GetDevices() returns no devices.
1211 DevicesMap devices_swapped;
1212 devices_swapped.swap(devices_);
1213
1214 for (auto& iter : devices_swapped) {
1215 for (auto& observer : observers_)
1216 observer.DeviceRemoved(this, iter.second.get());
1217 }
1218
1219 PresentChanged(false);
1220 }
1221
DiscoverableChanged(bool discoverable)1222 void BluetoothAdapterBlueZ::DiscoverableChanged(bool discoverable) {
1223 for (auto& observer : observers_)
1224 observer.AdapterDiscoverableChanged(this, discoverable);
1225 }
1226
DiscoveringChanged(bool discovering)1227 void BluetoothAdapterBlueZ::DiscoveringChanged(bool discovering) {
1228 // If the adapter stopped discovery due to a reason other than a request by
1229 // us, reset the count to 0.
1230 BLUETOOTH_LOG(EVENT) << "Discovering changed: " << discovering;
1231 if (!discovering && NumScanningDiscoverySessions() > 0) {
1232 BLUETOOTH_LOG(DEBUG) << "Marking sessions as inactive.";
1233 MarkDiscoverySessionsAsInactive();
1234 }
1235
1236 for (auto& observer : observers_)
1237 observer.AdapterDiscoveringChanged(this, discovering);
1238 }
1239
PresentChanged(bool present)1240 void BluetoothAdapterBlueZ::PresentChanged(bool present) {
1241 for (auto& observer : observers_)
1242 observer.AdapterPresentChanged(this, present);
1243 }
1244
NotifyDeviceAddressChanged(BluetoothDeviceBlueZ * device,const std::string & old_address)1245 void BluetoothAdapterBlueZ::NotifyDeviceAddressChanged(
1246 BluetoothDeviceBlueZ* device,
1247 const std::string& old_address) {
1248 DCHECK(device->adapter_ == this);
1249
1250 for (auto& observer : observers_)
1251 observer.DeviceAddressChanged(this, device, old_address);
1252 }
1253
NotifyDeviceMTUChanged(BluetoothDeviceBlueZ * device,uint16_t mtu)1254 void BluetoothAdapterBlueZ::NotifyDeviceMTUChanged(BluetoothDeviceBlueZ* device,
1255 uint16_t mtu) {
1256 DCHECK(device->adapter_ == this);
1257
1258 for (auto& observer : observers_)
1259 observer.DeviceMTUChanged(this, device, mtu);
1260 }
1261
NotifyDeviceAdvertisementReceived(BluetoothDeviceBlueZ * device,int16_t rssi,const std::vector<uint8_t> & eir)1262 void BluetoothAdapterBlueZ::NotifyDeviceAdvertisementReceived(
1263 BluetoothDeviceBlueZ* device,
1264 int16_t rssi,
1265 const std::vector<uint8_t>& eir) {
1266 DCHECK(device->adapter_ == this);
1267
1268 for (auto& observer : observers_)
1269 observer.DeviceAdvertisementReceived(this, device, rssi, eir);
1270
1271 #if BUILDFLAG(IS_ASH)
1272 if (ble_scan_parser_.is_bound()) {
1273 ScanRecordCallback callback =
1274 base::BindOnce(&BluetoothAdapterBlueZ::OnAdvertisementReceived,
1275 weak_ptr_factory_.GetWeakPtr(), device->GetAddress(),
1276 device->GetName() ? *(device->GetName()) : std::string(),
1277 rssi, device->GetAppearance());
1278 ble_scan_parser_->Parse(eir, std::move(callback));
1279 }
1280 #endif // BUILDFLAG(IS_ASH)
1281 }
1282
1283 #if BUILDFLAG(IS_ASH)
OnAdvertisementReceived(std::string device_address,std::string device_name,uint8_t rssi,uint16_t device_appearance,ScanRecordPtr scan_record)1284 void BluetoothAdapterBlueZ::OnAdvertisementReceived(std::string device_address,
1285 std::string device_name,
1286 uint8_t rssi,
1287 uint16_t device_appearance,
1288 ScanRecordPtr scan_record) {
1289 // Ignore the packet if it could not be parsed successfully.
1290 if (!scan_record)
1291 return;
1292
1293 auto service_data_map = ConvertServiceDataMap(scan_record->service_data_map);
1294 auto manufacturer_data_map =
1295 ConvertManufacturerDataMap(scan_record->manufacturer_data_map);
1296 for (auto& observer : observers_) {
1297 observer.DeviceAdvertisementReceived(
1298 device_address, device_name, scan_record->advertisement_name, rssi,
1299 scan_record->tx_power, device_appearance, scan_record->service_uuids,
1300 service_data_map, manufacturer_data_map);
1301 }
1302 }
1303 #endif // BUILDFLAG(IS_ASH)
1304
NotifyDeviceConnectedStateChanged(BluetoothDeviceBlueZ * device,bool is_now_connected)1305 void BluetoothAdapterBlueZ::NotifyDeviceConnectedStateChanged(
1306 BluetoothDeviceBlueZ* device,
1307 bool is_now_connected) {
1308 DCHECK_EQ(device->adapter_, this);
1309 DCHECK_EQ(device->IsConnected(), is_now_connected);
1310
1311 for (auto& observer : observers_)
1312 observer.DeviceConnectedStateChanged(this, device, is_now_connected);
1313 }
1314
UseProfile(const BluetoothUUID & uuid,const dbus::ObjectPath & device_path,const bluez::BluetoothProfileManagerClient::Options & options,bluez::BluetoothProfileServiceProvider::Delegate * delegate,ProfileRegisteredCallback success_callback,ErrorCompletionCallback error_callback)1315 void BluetoothAdapterBlueZ::UseProfile(
1316 const BluetoothUUID& uuid,
1317 const dbus::ObjectPath& device_path,
1318 const bluez::BluetoothProfileManagerClient::Options& options,
1319 bluez::BluetoothProfileServiceProvider::Delegate* delegate,
1320 ProfileRegisteredCallback success_callback,
1321 ErrorCompletionCallback error_callback) {
1322 DCHECK(delegate);
1323
1324 if (!IsPresent()) {
1325 BLUETOOTH_LOG(DEBUG) << "Adapter not present, erroring out";
1326 std::move(error_callback).Run("Adapter not present");
1327 return;
1328 }
1329
1330 if (profiles_.find(uuid) != profiles_.end()) {
1331 // TODO(jamuraa) check that the options are the same and error when they are
1332 // not.
1333 SetProfileDelegate(uuid, device_path, delegate, std::move(success_callback),
1334 std::move(error_callback));
1335 return;
1336 }
1337
1338 if (profile_queues_.find(uuid) == profile_queues_.end()) {
1339 BluetoothAdapterProfileBlueZ::Register(
1340 uuid, options,
1341 base::BindOnce(&BluetoothAdapterBlueZ::OnRegisterProfile, this, uuid),
1342 base::BindOnce(&BluetoothAdapterBlueZ::OnRegisterProfileError, this,
1343 uuid));
1344
1345 profile_queues_[uuid] = new std::vector<RegisterProfileCompletionPair>();
1346 }
1347
1348 auto copyable_error_callback =
1349 base::AdaptCallbackForRepeating(std::move(error_callback));
1350 profile_queues_[uuid]->push_back(std::make_pair(
1351 base::BindOnce(&BluetoothAdapterBlueZ::SetProfileDelegate, this, uuid,
1352 device_path, delegate, std::move(success_callback),
1353 copyable_error_callback),
1354 copyable_error_callback));
1355 }
1356
ReleaseProfile(const dbus::ObjectPath & device_path,BluetoothAdapterProfileBlueZ * profile)1357 void BluetoothAdapterBlueZ::ReleaseProfile(
1358 const dbus::ObjectPath& device_path,
1359 BluetoothAdapterProfileBlueZ* profile) {
1360 BLUETOOTH_LOG(EVENT) << "Releasing Profile: "
1361 << profile->uuid().canonical_value() << " from "
1362 << device_path.value();
1363 BluetoothUUID uuid = profile->uuid();
1364 auto iter = profiles_.find(uuid);
1365 if (iter == profiles_.end()) {
1366 BLUETOOTH_LOG(ERROR) << "Profile not found for: " << uuid.canonical_value();
1367 return;
1368 }
1369 released_profiles_[uuid] = iter->second;
1370 profiles_.erase(iter);
1371 profile->RemoveDelegate(device_path,
1372 base::BindOnce(&BluetoothAdapterBlueZ::RemoveProfile,
1373 weak_ptr_factory_.GetWeakPtr(), uuid));
1374 }
1375
RemoveProfile(const BluetoothUUID & uuid)1376 void BluetoothAdapterBlueZ::RemoveProfile(const BluetoothUUID& uuid) {
1377 BLUETOOTH_LOG(EVENT) << "Remove Profile: " << uuid.canonical_value();
1378
1379 auto iter = released_profiles_.find(uuid);
1380 if (iter == released_profiles_.end()) {
1381 BLUETOOTH_LOG(ERROR) << "Released Profile not found: "
1382 << uuid.canonical_value();
1383 return;
1384 }
1385 delete iter->second;
1386 released_profiles_.erase(iter);
1387 }
1388
AddLocalGattService(std::unique_ptr<BluetoothLocalGattServiceBlueZ> service)1389 void BluetoothAdapterBlueZ::AddLocalGattService(
1390 std::unique_ptr<BluetoothLocalGattServiceBlueZ> service) {
1391 owned_gatt_services_[service->object_path()] = std::move(service);
1392 }
1393
RemoveLocalGattService(BluetoothLocalGattServiceBlueZ * service)1394 void BluetoothAdapterBlueZ::RemoveLocalGattService(
1395 BluetoothLocalGattServiceBlueZ* service) {
1396 auto service_iter = owned_gatt_services_.find(service->object_path());
1397 if (service_iter == owned_gatt_services_.end()) {
1398 BLUETOOTH_LOG(ERROR) << "Trying to remove service: "
1399 << service->object_path().value()
1400 << " from adapter: " << object_path_.value()
1401 << " that doesn't own it.";
1402 return;
1403 }
1404
1405 if (registered_gatt_services_.count(service->object_path()) != 0) {
1406 registered_gatt_services_.erase(service->object_path());
1407 UpdateRegisteredApplication(true, base::DoNothing(), base::DoNothing());
1408 }
1409
1410 owned_gatt_services_.erase(service_iter);
1411 }
1412
RegisterGattService(BluetoothLocalGattServiceBlueZ * service,base::OnceClosure callback,device::BluetoothGattService::ErrorCallback error_callback)1413 void BluetoothAdapterBlueZ::RegisterGattService(
1414 BluetoothLocalGattServiceBlueZ* service,
1415 base::OnceClosure callback,
1416 device::BluetoothGattService::ErrorCallback error_callback) {
1417 if (registered_gatt_services_.count(service->object_path()) > 0) {
1418 BLUETOOTH_LOG(ERROR)
1419 << "Re-registering a service that is already registered!";
1420 std::move(error_callback)
1421 .Run(device::BluetoothGattService::GATT_ERROR_FAILED);
1422 return;
1423 }
1424
1425 registered_gatt_services_[service->object_path()] = service;
1426
1427 // Always assume that we were already registered. If we weren't registered
1428 // we'll just get an error back which we can ignore. Any other approach will
1429 // introduce a race since we will always have a period when we may have been
1430 // registered with BlueZ, but not know that the registration succeeded
1431 // because the callback hasn't come back yet.
1432 UpdateRegisteredApplication(true, std::move(callback),
1433 std::move(error_callback));
1434 }
1435
UnregisterGattService(BluetoothLocalGattServiceBlueZ * service,base::OnceClosure callback,device::BluetoothGattService::ErrorCallback error_callback)1436 void BluetoothAdapterBlueZ::UnregisterGattService(
1437 BluetoothLocalGattServiceBlueZ* service,
1438 base::OnceClosure callback,
1439 device::BluetoothGattService::ErrorCallback error_callback) {
1440 DCHECK(bluez::BluezDBusManager::Get());
1441
1442 if (registered_gatt_services_.count(service->object_path()) == 0) {
1443 BLUETOOTH_LOG(ERROR)
1444 << "Unregistering a service that isn't registered! path: "
1445 << service->object_path().value();
1446 std::move(error_callback)
1447 .Run(device::BluetoothGattService::GATT_ERROR_FAILED);
1448 return;
1449 }
1450
1451 registered_gatt_services_.erase(service->object_path());
1452 UpdateRegisteredApplication(false, std::move(callback),
1453 std::move(error_callback));
1454 }
1455
IsGattServiceRegistered(BluetoothLocalGattServiceBlueZ * service)1456 bool BluetoothAdapterBlueZ::IsGattServiceRegistered(
1457 BluetoothLocalGattServiceBlueZ* service) {
1458 return registered_gatt_services_.count(service->object_path()) != 0;
1459 }
1460
SendValueChanged(BluetoothLocalGattCharacteristicBlueZ * characteristic,const std::vector<uint8_t> & value)1461 bool BluetoothAdapterBlueZ::SendValueChanged(
1462 BluetoothLocalGattCharacteristicBlueZ* characteristic,
1463 const std::vector<uint8_t>& value) {
1464 if (registered_gatt_services_.count(
1465 static_cast<BluetoothLocalGattServiceBlueZ*>(
1466 characteristic->GetService())
1467 ->object_path()) == 0)
1468 return false;
1469 gatt_application_provider_->SendValueChanged(characteristic->object_path(),
1470 value);
1471 return true;
1472 }
1473
GetApplicationObjectPath() const1474 dbus::ObjectPath BluetoothAdapterBlueZ::GetApplicationObjectPath() const {
1475 return dbus::ObjectPath(object_path_.value() + kGattApplicationObjectPath);
1476 }
1477
OnRegisterProfile(const BluetoothUUID & uuid,std::unique_ptr<BluetoothAdapterProfileBlueZ> profile)1478 void BluetoothAdapterBlueZ::OnRegisterProfile(
1479 const BluetoothUUID& uuid,
1480 std::unique_ptr<BluetoothAdapterProfileBlueZ> profile) {
1481 profiles_[uuid] = profile.release();
1482
1483 if (profile_queues_.find(uuid) == profile_queues_.end())
1484 return;
1485
1486 for (auto& it : *profile_queues_[uuid])
1487 std::move(it.first).Run();
1488 delete profile_queues_[uuid];
1489 profile_queues_.erase(uuid);
1490 }
1491
SetProfileDelegate(const BluetoothUUID & uuid,const dbus::ObjectPath & device_path,bluez::BluetoothProfileServiceProvider::Delegate * delegate,ProfileRegisteredCallback success_callback,ErrorCompletionCallback error_callback)1492 void BluetoothAdapterBlueZ::SetProfileDelegate(
1493 const BluetoothUUID& uuid,
1494 const dbus::ObjectPath& device_path,
1495 bluez::BluetoothProfileServiceProvider::Delegate* delegate,
1496 ProfileRegisteredCallback success_callback,
1497 ErrorCompletionCallback error_callback) {
1498 if (profiles_.find(uuid) == profiles_.end()) {
1499 std::move(error_callback).Run("Cannot find profile!");
1500 return;
1501 }
1502
1503 if (profiles_[uuid]->SetDelegate(device_path, delegate)) {
1504 std::move(success_callback).Run(profiles_[uuid]);
1505 return;
1506 }
1507 // Already set
1508 std::move(error_callback).Run(bluetooth_agent_manager::kErrorAlreadyExists);
1509 }
1510
OnRegisterProfileError(const BluetoothUUID & uuid,const std::string & error_name,const std::string & error_message)1511 void BluetoothAdapterBlueZ::OnRegisterProfileError(
1512 const BluetoothUUID& uuid,
1513 const std::string& error_name,
1514 const std::string& error_message) {
1515 BLUETOOTH_LOG(ERROR) << object_path_.value()
1516 << ": Failed to register profile: " << error_name << ": "
1517 << error_message;
1518 if (profile_queues_.find(uuid) == profile_queues_.end())
1519 return;
1520
1521 for (auto& it : *profile_queues_[uuid])
1522 std::move(it.second).Run(error_message);
1523
1524 delete profile_queues_[uuid];
1525 profile_queues_.erase(uuid);
1526 }
1527
OnSetDiscoverable(base::OnceClosure callback,ErrorCallback error_callback,bool success)1528 void BluetoothAdapterBlueZ::OnSetDiscoverable(base::OnceClosure callback,
1529 ErrorCallback error_callback,
1530 bool success) {
1531 if (!IsPresent()) {
1532 std::move(error_callback).Run();
1533 return;
1534 }
1535
1536 // Set the discoverable_timeout property to zero so the adapter remains
1537 // discoverable forever.
1538 bluez::BluezDBusManager::Get()
1539 ->GetBluetoothAdapterClient()
1540 ->GetProperties(object_path_)
1541 ->discoverable_timeout.Set(
1542 0, base::BindOnce(&BluetoothAdapterBlueZ::OnPropertyChangeCompleted,
1543 weak_ptr_factory_.GetWeakPtr(), std::move(callback),
1544 std::move(error_callback)));
1545 }
1546
OnPropertyChangeCompleted(base::OnceClosure callback,ErrorCallback error_callback,bool success)1547 void BluetoothAdapterBlueZ::OnPropertyChangeCompleted(
1548 base::OnceClosure callback,
1549 ErrorCallback error_callback,
1550 bool success) {
1551 if (IsPresent() && success) {
1552 std::move(callback).Run();
1553 } else {
1554 std::move(error_callback).Run();
1555 }
1556 }
1557
GetWeakPtr()1558 base::WeakPtr<BluetoothAdapter> BluetoothAdapterBlueZ::GetWeakPtr() {
1559 return weak_ptr_factory_.GetWeakPtr();
1560 }
1561
1562 // BluetoothAdapterBlueZ should override SetPowered() instead.
SetPoweredImpl(bool powered)1563 bool BluetoothAdapterBlueZ::SetPoweredImpl(bool powered) {
1564 NOTREACHED();
1565 return false;
1566 }
1567
UpdateFilter(std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter,DiscoverySessionResultCallback callback)1568 void BluetoothAdapterBlueZ::UpdateFilter(
1569 std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter,
1570 DiscoverySessionResultCallback callback) {
1571 DCHECK_GT(NumDiscoverySessions(), 0);
1572 if (!IsPresent()) {
1573 std::move(callback).Run(
1574 true, UMABluetoothDiscoverySessionOutcome::ADAPTER_NOT_PRESENT);
1575 return;
1576 }
1577
1578 BLUETOOTH_LOG(EVENT) << __func__;
1579
1580 auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
1581
1582 // DCHECK(IsDiscovering()) is removed due to BlueZ bug
1583 // (https://crbug.com/822104).
1584 // TODO(sonnysasaka): Put it back here when BlueZ bug is fixed.
1585 SetDiscoveryFilter(
1586 std::move(discovery_filter),
1587 base::BindOnce(copyable_callback, /*is_error=*/false,
1588 UMABluetoothDiscoverySessionOutcome::SUCCESS),
1589 base::BindOnce(copyable_callback, true));
1590 return;
1591 }
1592
StartScanWithFilter(std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter,DiscoverySessionResultCallback callback)1593 void BluetoothAdapterBlueZ::StartScanWithFilter(
1594 std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter,
1595 DiscoverySessionResultCallback callback) {
1596 DCHECK(discovery_filter.get());
1597
1598 if (!IsPresent()) {
1599 std::move(callback).Run(
1600 true, UMABluetoothDiscoverySessionOutcome::ADAPTER_NOT_PRESENT);
1601 return;
1602 }
1603
1604 BLUETOOTH_LOG(EVENT) << __func__;
1605
1606 auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
1607 SetDiscoveryFilter(
1608 std::move(discovery_filter),
1609 base::BindOnce(
1610 &BluetoothAdapterBlueZ::OnPreSetDiscoveryFilter,
1611 weak_ptr_factory_.GetWeakPtr(),
1612 base::BindOnce(copyable_callback, /*is_error=*/false,
1613 UMABluetoothDiscoverySessionOutcome::SUCCESS),
1614 base::BindOnce(copyable_callback, true)),
1615 base::BindOnce(
1616 &BluetoothAdapterBlueZ::OnPreSetDiscoveryFilterError,
1617 weak_ptr_factory_.GetWeakPtr(),
1618 base::BindOnce(copyable_callback, /*is_error=*/false,
1619 UMABluetoothDiscoverySessionOutcome::SUCCESS),
1620 base::BindOnce(copyable_callback, true)));
1621 }
1622
StopScan(DiscoverySessionResultCallback callback)1623 void BluetoothAdapterBlueZ::StopScan(DiscoverySessionResultCallback callback) {
1624 #if BUILDFLAG(IS_ASH)
1625 ble_scan_parser_.reset();
1626 #endif // BUILDFLAG(IS_ASH)
1627
1628 // Not having an adapter qualifies as not scanning so we callback a success
1629 if (!IsPresent()) {
1630 std::move(callback).Run(
1631 /*is_error=*/false,
1632 UMABluetoothDiscoverySessionOutcome::ADAPTER_NOT_PRESENT);
1633 return;
1634 }
1635
1636 BLUETOOTH_LOG(EVENT) << __func__;
1637
1638 DCHECK_EQ(NumDiscoverySessions(), 0);
1639
1640 // Confirm that there are no more discovery sessions left.
1641 DCHECK_EQ(NumDiscoverySessions(), 0);
1642 auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
1643 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StopDiscovery(
1644 object_path_,
1645 base::BindOnce(
1646 &BluetoothAdapterBlueZ::OnStopDiscovery,
1647 weak_ptr_factory_.GetWeakPtr(),
1648 base::BindOnce(copyable_callback, /*is_error=*/false,
1649 UMABluetoothDiscoverySessionOutcome::SUCCESS)),
1650 base::BindOnce(&BluetoothAdapterBlueZ::OnStopDiscoveryError,
1651 weak_ptr_factory_.GetWeakPtr(),
1652 base::BindOnce(copyable_callback, /*is_error=*/true)));
1653 }
1654
SetDiscoveryFilter(std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,base::OnceClosure callback,DiscoverySessionErrorCallback error_callback)1655 void BluetoothAdapterBlueZ::SetDiscoveryFilter(
1656 std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,
1657 base::OnceClosure callback,
1658 DiscoverySessionErrorCallback error_callback) {
1659 DCHECK(discovery_filter.get());
1660
1661 if (!IsPresent()) {
1662 std::move(error_callback)
1663 .Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED);
1664 return;
1665 }
1666
1667 bluez::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter;
1668 uint16_t pathloss;
1669 int16_t rssi;
1670 uint8_t transport;
1671 std::set<device::BluetoothUUID> uuids;
1672
1673 if (discovery_filter->GetPathloss(&pathloss))
1674 dbus_discovery_filter.pathloss = std::make_unique<uint16_t>(pathloss);
1675
1676 if (discovery_filter->GetRSSI(&rssi))
1677 dbus_discovery_filter.rssi = std::make_unique<int16_t>(rssi);
1678
1679 transport = discovery_filter->GetTransport();
1680 if (transport == device::BLUETOOTH_TRANSPORT_LE) {
1681 dbus_discovery_filter.transport = std::make_unique<std::string>("le");
1682 } else if (transport == device::BLUETOOTH_TRANSPORT_CLASSIC) {
1683 dbus_discovery_filter.transport = std::make_unique<std::string>("bredr");
1684 } else if (transport == device::BLUETOOTH_TRANSPORT_DUAL) {
1685 dbus_discovery_filter.transport = std::make_unique<std::string>("auto");
1686 }
1687
1688 discovery_filter->GetUUIDs(uuids);
1689 if (uuids.size()) {
1690 dbus_discovery_filter.uuids = std::make_unique<std::vector<std::string>>();
1691
1692 for (const auto& it : uuids)
1693 dbus_discovery_filter.uuids.get()->push_back(it.value());
1694 }
1695
1696 auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
1697 auto copyable_error_callback =
1698 base::AdaptCallbackForRepeating(std::move(error_callback));
1699 bluez::BluezDBusManager::Get()
1700 ->GetBluetoothAdapterClient()
1701 ->SetDiscoveryFilter(
1702 object_path_, dbus_discovery_filter,
1703 base::BindOnce(&BluetoothAdapterBlueZ::OnSetDiscoveryFilter,
1704 weak_ptr_factory_.GetWeakPtr(), copyable_callback,
1705 copyable_error_callback),
1706 base::BindOnce(&BluetoothAdapterBlueZ::OnSetDiscoveryFilterError,
1707 weak_ptr_factory_.GetWeakPtr(), copyable_callback,
1708 copyable_error_callback));
1709 }
1710
OnStartDiscovery(base::OnceClosure callback,DiscoverySessionErrorCallback error_callback)1711 void BluetoothAdapterBlueZ::OnStartDiscovery(
1712 base::OnceClosure callback,
1713 DiscoverySessionErrorCallback error_callback) {
1714 // Report success on the original request and increment the count.
1715 BLUETOOTH_LOG(EVENT) << __func__;
1716
1717 #if BUILDFLAG(IS_ASH)
1718 device::BluetoothAdapterFactory::BleScanParserCallback
1719 ble_scan_parser_callback =
1720 device::BluetoothAdapterFactory::GetBleScanParserCallback();
1721 if (ble_scan_parser_callback) {
1722 // To avoid repeatedly restarting a crashed data decoder service,
1723 // don't add a connection error handler here. Wait to establish a
1724 // new connection after all discovery sessions are stopped.
1725 ble_scan_parser_.Bind(ble_scan_parser_callback.Run());
1726 } else {
1727 #if DCHECK_IS_ON()
1728 static bool logged_once = false;
1729 DLOG_IF(ERROR, !logged_once)
1730 << "Attempted to connect to "
1731 "unconfigured BluetoothAdapterFactory::GetBleScanParserCallback()";
1732 logged_once = true;
1733 #endif // DCHECK_IS_ON()
1734 }
1735 #endif // BUILDFLAG(IS_ASH)
1736
1737 if (IsPresent()) {
1738 std::move(callback).Run();
1739 } else {
1740 std::move(error_callback)
1741 .Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED);
1742 }
1743 }
1744
OnStartDiscoveryError(base::OnceClosure callback,DiscoverySessionErrorCallback error_callback,const std::string & error_name,const std::string & error_message)1745 void BluetoothAdapterBlueZ::OnStartDiscoveryError(
1746 base::OnceClosure callback,
1747 DiscoverySessionErrorCallback error_callback,
1748 const std::string& error_name,
1749 const std::string& error_message) {
1750 BLUETOOTH_LOG(ERROR) << object_path_.value()
1751 << ": Failed to start discovery: " << error_name << ": "
1752 << error_message;
1753
1754 std::move(error_callback).Run(TranslateDiscoveryErrorToUMA(error_name));
1755 }
1756
OnStopDiscovery(base::OnceClosure callback)1757 void BluetoothAdapterBlueZ::OnStopDiscovery(base::OnceClosure callback) {
1758 // Report success on the original request and decrement the count.
1759 BLUETOOTH_LOG(EVENT) << __func__;
1760 DCHECK_GE(NumDiscoverySessions(), 0);
1761 std::move(callback).Run();
1762 }
1763
OnStopDiscoveryError(DiscoverySessionErrorCallback error_callback,const std::string & error_name,const std::string & error_message)1764 void BluetoothAdapterBlueZ::OnStopDiscoveryError(
1765 DiscoverySessionErrorCallback error_callback,
1766 const std::string& error_name,
1767 const std::string& error_message) {
1768 BLUETOOTH_LOG(ERROR) << object_path_.value()
1769 << ": Failed to stop discovery: " << error_name << ": "
1770 << error_message;
1771
1772 std::move(error_callback).Run(TranslateDiscoveryErrorToUMA(error_name));
1773 }
1774
OnPreSetDiscoveryFilter(base::OnceClosure callback,DiscoverySessionErrorCallback error_callback)1775 void BluetoothAdapterBlueZ::OnPreSetDiscoveryFilter(
1776 base::OnceClosure callback,
1777 DiscoverySessionErrorCallback error_callback) {
1778 auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
1779 auto copyable_error_callback =
1780 base::AdaptCallbackForRepeating(std::move(error_callback));
1781 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1782 object_path_,
1783 base::BindOnce(&BluetoothAdapterBlueZ::OnStartDiscovery,
1784 weak_ptr_factory_.GetWeakPtr(), copyable_callback,
1785 copyable_error_callback),
1786 base::BindOnce(&BluetoothAdapterBlueZ::OnStartDiscoveryError,
1787 weak_ptr_factory_.GetWeakPtr(), copyable_callback,
1788 copyable_error_callback));
1789 }
1790
OnPreSetDiscoveryFilterError(base::OnceClosure callback,DiscoverySessionErrorCallback error_callback,UMABluetoothDiscoverySessionOutcome outcome)1791 void BluetoothAdapterBlueZ::OnPreSetDiscoveryFilterError(
1792 base::OnceClosure callback,
1793 DiscoverySessionErrorCallback error_callback,
1794 UMABluetoothDiscoverySessionOutcome outcome) {
1795 BLUETOOTH_LOG(ERROR) << object_path_.value()
1796 << ": Failed to pre set discovery filter.";
1797
1798 std::move(error_callback).Run(outcome);
1799 }
1800
OnSetDiscoveryFilter(base::OnceClosure callback,DiscoverySessionErrorCallback error_callback)1801 void BluetoothAdapterBlueZ::OnSetDiscoveryFilter(
1802 base::OnceClosure callback,
1803 DiscoverySessionErrorCallback error_callback) {
1804 // Report success on the original request and increment the count.
1805 BLUETOOTH_LOG(EVENT) << __func__;
1806 if (IsPresent()) {
1807 std::move(callback).Run();
1808 } else {
1809 std::move(error_callback)
1810 .Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED);
1811 }
1812 }
1813
OnSetDiscoveryFilterError(base::OnceClosure callback,DiscoverySessionErrorCallback error_callback,const std::string & error_name,const std::string & error_message)1814 void BluetoothAdapterBlueZ::OnSetDiscoveryFilterError(
1815 base::OnceClosure callback,
1816 DiscoverySessionErrorCallback error_callback,
1817 const std::string& error_name,
1818 const std::string& error_message) {
1819 BLUETOOTH_LOG(ERROR) << object_path_.value()
1820 << ": Failed to set discovery filter: " << error_name
1821 << ": " << error_message;
1822
1823 UMABluetoothDiscoverySessionOutcome outcome =
1824 TranslateDiscoveryErrorToUMA(error_name);
1825 if (outcome == UMABluetoothDiscoverySessionOutcome::FAILED) {
1826 // bluez/doc/adapter-api.txt says "Failed" is returned from
1827 // SetDiscoveryFilter when the controller doesn't support the requested
1828 // transport.
1829 outcome = UMABluetoothDiscoverySessionOutcome::
1830 BLUEZ_DBUS_FAILED_MAYBE_UNSUPPORTED_TRANSPORT;
1831 }
1832 std::move(error_callback).Run(outcome);
1833 }
1834
UpdateRegisteredApplication(bool ignore_unregister_failure,base::OnceClosure callback,device::BluetoothGattService::ErrorCallback error_callback)1835 void BluetoothAdapterBlueZ::UpdateRegisteredApplication(
1836 bool ignore_unregister_failure,
1837 base::OnceClosure callback,
1838 device::BluetoothGattService::ErrorCallback error_callback) {
1839 // If ignore_unregister_failure is set, we'll forward the error_callback to
1840 // the register call (to be called in case the register call fails). If not,
1841 // we'll call the error callback if this unregister itself fails.
1842 auto copyable_error_callback =
1843 base::AdaptCallbackForRepeating(std::move(error_callback));
1844 auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
1845 bluez::BluezDBusManager::Get()
1846 ->GetBluetoothGattManagerClient()
1847 ->UnregisterApplication(
1848 object_path_, GetApplicationObjectPath(),
1849 base::BindOnce(&BluetoothAdapterBlueZ::RegisterApplication,
1850 weak_ptr_factory_.GetWeakPtr(), copyable_callback,
1851 copyable_error_callback),
1852 ignore_unregister_failure
1853 ? base::BindOnce(
1854 &BluetoothAdapterBlueZ::RegisterApplicationOnError,
1855 weak_ptr_factory_.GetWeakPtr(), copyable_callback,
1856 copyable_error_callback)
1857 : base::BindOnce(&OnRegistrationErrorCallback,
1858 copyable_error_callback, false));
1859 }
1860
RegisterApplication(base::OnceClosure callback,device::BluetoothGattService::ErrorCallback error_callback)1861 void BluetoothAdapterBlueZ::RegisterApplication(
1862 base::OnceClosure callback,
1863 device::BluetoothGattService::ErrorCallback error_callback) {
1864 // Recreate our application service provider with the currently registered
1865 // GATT services before we register it.
1866 gatt_application_provider_.reset();
1867 // If we have no services registered, then leave the application unregistered
1868 // and no application provider.
1869 if (registered_gatt_services_.size() == 0) {
1870 std::move(callback).Run();
1871 return;
1872 }
1873 gatt_application_provider_ = BluetoothGattApplicationServiceProvider::Create(
1874 bluez::BluezDBusManager::Get()->GetSystemBus(),
1875 GetApplicationObjectPath(), registered_gatt_services_);
1876
1877 auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
1878 DCHECK(bluez::BluezDBusManager::Get());
1879 bluez::BluezDBusManager::Get()
1880 ->GetBluetoothGattManagerClient()
1881 ->RegisterApplication(object_path_, GetApplicationObjectPath(),
1882 BluetoothGattManagerClient::Options(),
1883 copyable_callback,
1884 base::BindOnce(&OnRegistrationErrorCallback,
1885 std::move(error_callback),
1886 /*is_register_callback=*/true));
1887 }
1888
RegisterApplicationOnError(base::OnceClosure callback,device::BluetoothGattService::ErrorCallback error_callback,const std::string &,const std::string &)1889 void BluetoothAdapterBlueZ::RegisterApplicationOnError(
1890 base::OnceClosure callback,
1891 device::BluetoothGattService::ErrorCallback error_callback,
1892 const std::string& /* error_name */,
1893 const std::string& /* error_message */) {
1894 RegisterApplication(std::move(callback), std::move(error_callback));
1895 }
1896
ServiceRecordErrorConnector(ServiceRecordErrorCallback error_callback,const std::string & error_name,const std::string & error_message)1897 void BluetoothAdapterBlueZ::ServiceRecordErrorConnector(
1898 ServiceRecordErrorCallback error_callback,
1899 const std::string& error_name,
1900 const std::string& error_message) {
1901 BLUETOOTH_LOG(EVENT) << "Creating service record failed: error: "
1902 << error_name << " - " << error_message;
1903
1904 BluetoothServiceRecordBlueZ::ErrorCode code =
1905 BluetoothServiceRecordBlueZ::ErrorCode::UNKNOWN;
1906 if (error_name == bluetooth_adapter::kErrorInvalidArguments) {
1907 code = BluetoothServiceRecordBlueZ::ErrorCode::ERROR_INVALID_ARGUMENTS;
1908 } else if (error_name == bluetooth_adapter::kErrorDoesNotExist) {
1909 code = BluetoothServiceRecordBlueZ::ErrorCode::ERROR_RECORD_DOES_NOT_EXIST;
1910 } else if (error_name == bluetooth_adapter::kErrorAlreadyExists) {
1911 code = BluetoothServiceRecordBlueZ::ErrorCode::ERROR_RECORD_ALREADY_EXISTS;
1912 } else if (error_name == bluetooth_adapter::kErrorNotReady) {
1913 code = BluetoothServiceRecordBlueZ::ErrorCode::ERROR_ADAPTER_NOT_READY;
1914 }
1915
1916 std::move(error_callback).Run(code);
1917 }
1918
OnConnectDevice(ConnectDeviceCallback callback,const dbus::ObjectPath & object_path)1919 void BluetoothAdapterBlueZ::OnConnectDevice(
1920 ConnectDeviceCallback callback,
1921 const dbus::ObjectPath& object_path) {
1922 std::move(callback).Run(GetDeviceWithPath(object_path));
1923 }
1924
OnConnectDeviceError(ErrorCallback error_callback,const std::string & error_name,const std::string & error_message)1925 void BluetoothAdapterBlueZ::OnConnectDeviceError(
1926 ErrorCallback error_callback,
1927 const std::string& error_name,
1928 const std::string& error_message) {
1929 std::move(error_callback).Run();
1930 }
1931
UpdateDeviceBatteryLevelFromBatteryClient(const dbus::ObjectPath & object_path)1932 void BluetoothAdapterBlueZ::UpdateDeviceBatteryLevelFromBatteryClient(
1933 const dbus::ObjectPath& object_path) {
1934 BluetoothDevice* device = GetDeviceWithPath(object_path);
1935
1936 if (!device) {
1937 BLUETOOTH_LOG(ERROR) << "Trying to update battery for non-existing device";
1938 return;
1939 }
1940
1941 bluez::BluetoothBatteryClient::Properties* properties =
1942 bluez::BluezDBusManager::Get()
1943 ->GetBluetoothBatteryClient()
1944 ->GetProperties(object_path);
1945
1946 if (properties && properties->percentage.is_valid()) {
1947 device->SetBatteryPercentage(properties->percentage.value());
1948 return;
1949 }
1950
1951 // |properties| is null or properties->percentage is not valid, that means
1952 // BlueZ has removed the battery info from the device and we should clear our
1953 // value as well.
1954 device->SetBatteryPercentage(base::nullopt);
1955 }
1956
1957 } // namespace bluez
1958