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

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

Issue 1898643002: Refactor device::BluetoothGattXXX classes to split into remote/local. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "device/bluetooth/bluetooth_adapter_bluez.h"
6
7 #include <memory>
8 #include <set>
9 #include <string>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/metrics/histogram.h"
16 #include "base/sequenced_task_runner.h"
17 #include "base/single_thread_task_runner.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/thread_task_runner_handle.h"
20 #include "build/build_config.h"
21 #include "device/bluetooth/bluetooth_adapter_profile_bluez.h"
22 #include "device/bluetooth/bluetooth_advertisement_bluez.h"
23 #include "device/bluetooth/bluetooth_audio_sink_bluez.h"
24 #include "device/bluetooth/bluetooth_device.h"
25 #include "device/bluetooth/bluetooth_device_bluez.h"
26 #include "device/bluetooth/bluetooth_discovery_session_outcome.h"
27 #include "device/bluetooth/bluetooth_pairing_bluez.h"
28 #include "device/bluetooth/bluetooth_socket_bluez.h"
29 #include "device/bluetooth/bluetooth_socket_thread.h"
30 #include "device/bluetooth/bluetooth_uuid.h"
31 #include "device/bluetooth/dbus/bluetooth_adapter_client.h"
32 #include "device/bluetooth/dbus/bluetooth_agent_manager_client.h"
33 #include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
34 #include "device/bluetooth/dbus/bluetooth_device_client.h"
35 #include "device/bluetooth/dbus/bluetooth_input_client.h"
36 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
37 #include "third_party/cros_system_api/dbus/service_constants.h"
38
39 #if defined(OS_CHROMEOS)
40 #include "chromeos/system/devicetype.h"
41 #endif
42
43 using device::BluetoothAdapter;
44 using device::BluetoothAudioSink;
45 using device::BluetoothDevice;
46 using device::BluetoothDiscoveryFilter;
47 using device::BluetoothSocket;
48 using device::BluetoothUUID;
49 using device::UMABluetoothDiscoverySessionOutcome;
50
51 namespace {
52
53 // The agent path is relatively meaningless since BlueZ only permits one to
54 // exist per D-Bus connection, it just has to be unique within Chromium.
55 const char kAgentPath[] = "/org/chromium/bluetooth_agent";
56
57 void OnUnregisterAgentError(const std::string& error_name,
58 const std::string& error_message) {
59 // It's okay if the agent didn't exist, it means we never saw an adapter.
60 if (error_name == bluetooth_agent_manager::kErrorDoesNotExist)
61 return;
62
63 LOG(WARNING) << "Failed to unregister pairing agent: " << error_name << ": "
64 << error_message;
65 }
66
67 UMABluetoothDiscoverySessionOutcome TranslateDiscoveryErrorToUMA(
68 const std::string& error_name) {
69 if (error_name == bluez::BluetoothAdapterClient::kUnknownAdapterError) {
70 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_UNKNOWN_ADAPTER;
71 } else if (error_name == bluez::BluetoothAdapterClient::kNoResponseError) {
72 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_NO_RESPONSE;
73 } else if (error_name == bluetooth_device::kErrorInProgress) {
74 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_IN_PROGRESS;
75 } else if (error_name == bluetooth_device::kErrorNotReady) {
76 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_NOT_READY;
77 } else if (error_name == bluetooth_device::kErrorNotSupported) {
78 return UMABluetoothDiscoverySessionOutcome::BLUEZ_DBUS_UNSUPPORTED_DEVICE;
79 } else if (error_name == bluetooth_device::kErrorFailed) {
80 return UMABluetoothDiscoverySessionOutcome::FAILED;
81 } else {
82 LOG(WARNING) << "Can't histogram DBus error " << error_name;
83 return UMABluetoothDiscoverySessionOutcome::UNKNOWN;
84 }
85 }
86
87 } // namespace
88
89 namespace device {
90
91 // static
92 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
93 const InitCallback& init_callback) {
94 return bluez::BluetoothAdapterBlueZ::CreateAdapter(init_callback);
95 }
96
97 } // namespace device
98
99 namespace bluez {
100
101 // static
102 base::WeakPtr<BluetoothAdapter> BluetoothAdapterBlueZ::CreateAdapter(
103 const InitCallback& init_callback) {
104 BluetoothAdapterBlueZ* adapter = new BluetoothAdapterBlueZ(init_callback);
105 return adapter->weak_ptr_factory_.GetWeakPtr();
106 }
107
108 void BluetoothAdapterBlueZ::Shutdown() {
109 if (dbus_is_shutdown_)
110 return;
111 DCHECK(bluez::BluezDBusManager::IsInitialized())
112 << "Call BluetoothAdapterFactory::Shutdown() before "
113 "BluezDBusManager::Shutdown().";
114
115 // Since we don't initialize anything if Object Manager is not supported,
116 // no need to do any clean up.
117 if (!bluez::BluezDBusManager::Get()->IsObjectManagerSupported()) {
118 dbus_is_shutdown_ = true;
119 return;
120 }
121
122 if (IsPresent())
123 RemoveAdapter(); // Also deletes devices_.
124 DCHECK(devices_.empty());
125 // profiles_ is empty because all BluetoothSockets have been notified
126 // that this adapter is disappearing.
127 DCHECK(profiles_.empty());
128
129 for (auto& it : profile_queues_)
130 delete it.second;
131 profile_queues_.clear();
132
133 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(
134 this);
135 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(
136 this);
137 bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->RemoveObserver(
138 this);
139
140 VLOG(1) << "Unregistering pairing agent";
141 bluez::BluezDBusManager::Get()
142 ->GetBluetoothAgentManagerClient()
143 ->UnregisterAgent(dbus::ObjectPath(kAgentPath),
144 base::Bind(&base::DoNothing),
145 base::Bind(&OnUnregisterAgentError));
146
147 agent_.reset();
148 dbus_is_shutdown_ = true;
149 }
150
151 BluetoothAdapterBlueZ::BluetoothAdapterBlueZ(const InitCallback& init_callback)
152 : init_callback_(init_callback),
153 initialized_(false),
154 dbus_is_shutdown_(false),
155 num_discovery_sessions_(0),
156 discovery_request_pending_(false),
157 weak_ptr_factory_(this) {
158 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
159 socket_thread_ = device::BluetoothSocketThread::Get();
160
161 // Can't initialize the adapter until DBus clients are ready.
162 if (bluez::BluezDBusManager::Get()->IsObjectManagerSupportKnown()) {
163 base::ThreadTaskRunnerHandle::Get()->PostTask(
164 FROM_HERE, base::Bind(&BluetoothAdapterBlueZ::Init,
165 weak_ptr_factory_.GetWeakPtr()));
166 return;
167 }
168 bluez::BluezDBusManager::Get()->CallWhenObjectManagerSupportIsKnown(
169 base::Bind(&BluetoothAdapterBlueZ::Init, weak_ptr_factory_.GetWeakPtr()));
170 }
171
172 void BluetoothAdapterBlueZ::Init() {
173 // If the platform doesn't support Object Manager then Bluez 5 is probably
174 // not present. In this case we just return without initializing anything.
175 if (!bluez::BluezDBusManager::Get()->IsObjectManagerSupported()) {
176 initialized_ = true;
177 init_callback_.Run();
178 return;
179 }
180
181 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->AddObserver(
182 this);
183 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
184 bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->AddObserver(this);
185
186 // Register the pairing agent.
187 dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus();
188 agent_.reset(bluez::BluetoothAgentServiceProvider::Create(
189 system_bus, dbus::ObjectPath(kAgentPath), this));
190 DCHECK(agent_.get());
191
192 std::vector<dbus::ObjectPath> object_paths = bluez::BluezDBusManager::Get()
193 ->GetBluetoothAdapterClient()
194 ->GetAdapters();
195
196 if (!object_paths.empty()) {
197 VLOG(1) << object_paths.size() << " Bluetooth adapter(s) available.";
198 SetAdapter(object_paths[0]);
199 }
200 initialized_ = true;
201 init_callback_.Run();
202 }
203
204 BluetoothAdapterBlueZ::~BluetoothAdapterBlueZ() {
205 Shutdown();
206 }
207
208 std::string BluetoothAdapterBlueZ::GetAddress() const {
209 if (!IsPresent())
210 return std::string();
211
212 bluez::BluetoothAdapterClient::Properties* properties =
213 bluez::BluezDBusManager::Get()
214 ->GetBluetoothAdapterClient()
215 ->GetProperties(object_path_);
216 DCHECK(properties);
217
218 return BluetoothDevice::CanonicalizeAddress(properties->address.value());
219 }
220
221 std::string BluetoothAdapterBlueZ::GetName() const {
222 if (!IsPresent())
223 return std::string();
224
225 bluez::BluetoothAdapterClient::Properties* properties =
226 bluez::BluezDBusManager::Get()
227 ->GetBluetoothAdapterClient()
228 ->GetProperties(object_path_);
229 DCHECK(properties);
230
231 return properties->alias.value();
232 }
233
234 void BluetoothAdapterBlueZ::SetName(const std::string& name,
235 const base::Closure& callback,
236 const ErrorCallback& error_callback) {
237 if (!IsPresent()) {
238 error_callback.Run();
239 return;
240 }
241
242 bluez::BluezDBusManager::Get()
243 ->GetBluetoothAdapterClient()
244 ->GetProperties(object_path_)
245 ->alias.Set(
246 name,
247 base::Bind(&BluetoothAdapterBlueZ::OnPropertyChangeCompleted,
248 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
249 }
250
251 bool BluetoothAdapterBlueZ::IsInitialized() const {
252 return initialized_;
253 }
254
255 bool BluetoothAdapterBlueZ::IsPresent() const {
256 return !dbus_is_shutdown_ && !object_path_.value().empty();
257 }
258
259 bool BluetoothAdapterBlueZ::IsPowered() const {
260 if (!IsPresent())
261 return false;
262
263 bluez::BluetoothAdapterClient::Properties* properties =
264 bluez::BluezDBusManager::Get()
265 ->GetBluetoothAdapterClient()
266 ->GetProperties(object_path_);
267
268 return properties->powered.value();
269 }
270
271 void BluetoothAdapterBlueZ::SetPowered(bool powered,
272 const base::Closure& callback,
273 const ErrorCallback& error_callback) {
274 if (!IsPresent()) {
275 error_callback.Run();
276 return;
277 }
278
279 bluez::BluezDBusManager::Get()
280 ->GetBluetoothAdapterClient()
281 ->GetProperties(object_path_)
282 ->powered.Set(
283 powered,
284 base::Bind(&BluetoothAdapterBlueZ::OnPropertyChangeCompleted,
285 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
286 }
287
288 bool BluetoothAdapterBlueZ::IsDiscoverable() const {
289 if (!IsPresent())
290 return false;
291
292 bluez::BluetoothAdapterClient::Properties* properties =
293 bluez::BluezDBusManager::Get()
294 ->GetBluetoothAdapterClient()
295 ->GetProperties(object_path_);
296
297 return properties->discoverable.value();
298 }
299
300 void BluetoothAdapterBlueZ::SetDiscoverable(
301 bool discoverable,
302 const base::Closure& callback,
303 const ErrorCallback& error_callback) {
304 if (!IsPresent()) {
305 error_callback.Run();
306 return;
307 }
308
309 bluez::BluezDBusManager::Get()
310 ->GetBluetoothAdapterClient()
311 ->GetProperties(object_path_)
312 ->discoverable.Set(
313 discoverable,
314 base::Bind(&BluetoothAdapterBlueZ::OnSetDiscoverable,
315 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
316 }
317
318 bool BluetoothAdapterBlueZ::IsDiscovering() const {
319 if (!IsPresent())
320 return false;
321
322 bluez::BluetoothAdapterClient::Properties* properties =
323 bluez::BluezDBusManager::Get()
324 ->GetBluetoothAdapterClient()
325 ->GetProperties(object_path_);
326
327 return properties->discovering.value();
328 }
329
330 BluetoothAdapterBlueZ::UUIDList BluetoothAdapterBlueZ::GetUUIDs() const {
331 bluez::BluetoothAdapterClient::Properties* properties =
332 bluez::BluezDBusManager::Get()
333 ->GetBluetoothAdapterClient()
334 ->GetProperties(object_path_);
335 DCHECK(properties);
336
337 std::vector<std::string> uuids = properties->uuids.value();
338
339 return UUIDList(uuids.begin(), uuids.end());
340 }
341
342 void BluetoothAdapterBlueZ::CreateRfcommService(
343 const BluetoothUUID& uuid,
344 const ServiceOptions& options,
345 const CreateServiceCallback& callback,
346 const CreateServiceErrorCallback& error_callback) {
347 DCHECK(!dbus_is_shutdown_);
348 VLOG(1) << object_path_.value()
349 << ": Creating RFCOMM service: " << uuid.canonical_value();
350 scoped_refptr<BluetoothSocketBlueZ> socket =
351 BluetoothSocketBlueZ::CreateBluetoothSocket(ui_task_runner_,
352 socket_thread_);
353 socket->Listen(this, BluetoothSocketBlueZ::kRfcomm, uuid, options,
354 base::Bind(callback, socket), error_callback);
355 }
356
357 void BluetoothAdapterBlueZ::CreateL2capService(
358 const BluetoothUUID& uuid,
359 const ServiceOptions& options,
360 const CreateServiceCallback& callback,
361 const CreateServiceErrorCallback& error_callback) {
362 DCHECK(!dbus_is_shutdown_);
363 VLOG(1) << object_path_.value()
364 << ": Creating L2CAP service: " << uuid.canonical_value();
365 scoped_refptr<BluetoothSocketBlueZ> socket =
366 BluetoothSocketBlueZ::CreateBluetoothSocket(ui_task_runner_,
367 socket_thread_);
368 socket->Listen(this, BluetoothSocketBlueZ::kL2cap, uuid, options,
369 base::Bind(callback, socket), error_callback);
370 }
371
372 void BluetoothAdapterBlueZ::RegisterAudioSink(
373 const BluetoothAudioSink::Options& options,
374 const device::BluetoothAdapter::AcquiredCallback& callback,
375 const BluetoothAudioSink::ErrorCallback& error_callback) {
376 VLOG(1) << "Registering audio sink";
377 if (!this->IsPresent()) {
378 error_callback.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER);
379 return;
380 }
381 scoped_refptr<BluetoothAudioSinkBlueZ> audio_sink(
382 new BluetoothAudioSinkBlueZ(this));
383 audio_sink->Register(options,
384 base::Bind(&BluetoothAdapterBlueZ::OnRegisterAudioSink,
385 weak_ptr_factory_.GetWeakPtr(), callback,
386 error_callback, audio_sink),
387 error_callback);
388 }
389
390 void BluetoothAdapterBlueZ::RegisterAdvertisement(
391 std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement_data,
392 const CreateAdvertisementCallback& callback,
393 const CreateAdvertisementErrorCallback& error_callback) {
394 scoped_refptr<BluetoothAdvertisementBlueZ> advertisement(
395 new BluetoothAdvertisementBlueZ(std::move(advertisement_data), this));
396 advertisement->Register(base::Bind(callback, advertisement), error_callback);
397 }
398
399 void BluetoothAdapterBlueZ::RemovePairingDelegateInternal(
400 BluetoothDevice::PairingDelegate* pairing_delegate) {
401 // Check if any device is using the pairing delegate.
402 // If so, clear the pairing context which will make any responses no-ops.
403 for (DevicesMap::const_iterator iter = devices_.begin();
404 iter != devices_.end(); ++iter) {
405 BluetoothDeviceBlueZ* device_bluez =
406 static_cast<BluetoothDeviceBlueZ*>(iter->second);
407
408 BluetoothPairingBlueZ* pairing = device_bluez->GetPairing();
409 if (pairing && pairing->GetPairingDelegate() == pairing_delegate)
410 device_bluez->EndPairing();
411 }
412 }
413
414 void BluetoothAdapterBlueZ::AdapterAdded(const dbus::ObjectPath& object_path) {
415 // Set the adapter to the newly added adapter only if no adapter is present.
416 if (!IsPresent())
417 SetAdapter(object_path);
418 }
419
420 void BluetoothAdapterBlueZ::AdapterRemoved(
421 const dbus::ObjectPath& object_path) {
422 if (object_path == object_path_)
423 RemoveAdapter();
424 }
425
426 void BluetoothAdapterBlueZ::AdapterPropertyChanged(
427 const dbus::ObjectPath& object_path,
428 const std::string& property_name) {
429 if (object_path != object_path_)
430 return;
431 DCHECK(IsPresent());
432
433 bluez::BluetoothAdapterClient::Properties* properties =
434 bluez::BluezDBusManager::Get()
435 ->GetBluetoothAdapterClient()
436 ->GetProperties(object_path_);
437
438 if (property_name == properties->powered.name()) {
439 PoweredChanged(properties->powered.value());
440 } else if (property_name == properties->discoverable.name()) {
441 DiscoverableChanged(properties->discoverable.value());
442 } else if (property_name == properties->discovering.name()) {
443 DiscoveringChanged(properties->discovering.value());
444 }
445 }
446
447 void BluetoothAdapterBlueZ::DeviceAdded(const dbus::ObjectPath& object_path) {
448 DCHECK(bluez::BluezDBusManager::Get());
449 bluez::BluetoothDeviceClient::Properties* properties =
450 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
451 object_path);
452 if (!properties || properties->adapter.value() != object_path_)
453 return;
454 DCHECK(IsPresent());
455
456 BluetoothDeviceBlueZ* device_bluez = new BluetoothDeviceBlueZ(
457 this, object_path, ui_task_runner_, socket_thread_);
458 DCHECK(devices_.find(device_bluez->GetAddress()) == devices_.end());
459
460 devices_.set(device_bluez->GetAddress(),
461 std::unique_ptr<BluetoothDevice>(device_bluez));
462
463 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
464 DeviceAdded(this, device_bluez));
465 }
466
467 void BluetoothAdapterBlueZ::DeviceRemoved(const dbus::ObjectPath& object_path) {
468 for (DevicesMap::const_iterator iter = devices_.begin();
469 iter != devices_.end(); ++iter) {
470 BluetoothDeviceBlueZ* device_bluez =
471 static_cast<BluetoothDeviceBlueZ*>(iter->second);
472 if (device_bluez->object_path() == object_path) {
473 std::unique_ptr<BluetoothDevice> scoped_device =
474 devices_.take_and_erase(iter->first);
475
476 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
477 DeviceRemoved(this, device_bluez));
478 return;
479 }
480 }
481 }
482
483 void BluetoothAdapterBlueZ::DevicePropertyChanged(
484 const dbus::ObjectPath& object_path,
485 const std::string& property_name) {
486 BluetoothDeviceBlueZ* device_bluez = GetDeviceWithPath(object_path);
487 if (!device_bluez)
488 return;
489
490 bluez::BluetoothDeviceClient::Properties* properties =
491 bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
492 object_path);
493
494 if (property_name == properties->address.name()) {
495 for (DevicesMap::iterator iter = devices_.begin(); iter != devices_.end();
496 ++iter) {
497 if (iter->second->GetAddress() == device_bluez->GetAddress()) {
498 std::string old_address = iter->first;
499 VLOG(1) << "Device changed address, old: " << old_address
500 << " new: " << device_bluez->GetAddress();
501 std::unique_ptr<BluetoothDevice> scoped_device =
502 devices_.take_and_erase(iter);
503 ignore_result(scoped_device.release());
504
505 DCHECK(devices_.find(device_bluez->GetAddress()) == devices_.end());
506 devices_.set(device_bluez->GetAddress(),
507 std::unique_ptr<BluetoothDevice>(device_bluez));
508 NotifyDeviceAddressChanged(device_bluez, old_address);
509 break;
510 }
511 }
512 }
513
514 if (property_name == properties->bluetooth_class.name() ||
515 property_name == properties->appearance.name() ||
516 property_name == properties->address.name() ||
517 property_name == properties->alias.name() ||
518 property_name == properties->paired.name() ||
519 property_name == properties->trusted.name() ||
520 property_name == properties->connected.name() ||
521 property_name == properties->uuids.name() ||
522 property_name == properties->rssi.name() ||
523 property_name == properties->tx_power.name()) {
524 NotifyDeviceChanged(device_bluez);
525 }
526
527 if (property_name == properties->gatt_services.name()) {
528 device_bluez->SetGattServicesDiscoveryComplete(true);
529 NotifyGattServicesDiscovered(device_bluez);
530 }
531
532 // When a device becomes paired, mark it as trusted so that the user does
533 // not need to approve every incoming connection
534 if (property_name == properties->paired.name()) {
535 if (properties->paired.value() && !properties->trusted.value()) {
536 device_bluez->SetTrusted();
537 }
538 NotifyDevicePairedChanged(device_bluez, properties->paired.value());
539 }
540
541 // UMA connection counting
542 if (property_name == properties->connected.name()) {
543 // PlayStation joystick tries to reconnect after disconnection from USB.
544 // If it is still not trusted, set it, so it becomes available on the
545 // list of known devices.
546 if (properties->connected.value()) {
547 if (device_bluez->IsTrustable() && !properties->trusted.value())
548 device_bluez->SetTrusted();
549 } else {
550 device_bluez->SetGattServicesDiscoveryComplete(false);
551 }
552
553 int count = 0;
554
555 for (DevicesMap::const_iterator iter = devices_.begin();
556 iter != devices_.end(); ++iter) {
557 if (iter->second->IsPaired() && iter->second->IsConnected())
558 ++count;
559 }
560
561 UMA_HISTOGRAM_COUNTS_100("Bluetooth.ConnectedDeviceCount", count);
562 }
563 }
564
565 void BluetoothAdapterBlueZ::InputPropertyChanged(
566 const dbus::ObjectPath& object_path,
567 const std::string& property_name) {
568 BluetoothDeviceBlueZ* device_bluez = GetDeviceWithPath(object_path);
569 if (!device_bluez)
570 return;
571
572 bluez::BluetoothInputClient::Properties* properties =
573 bluez::BluezDBusManager::Get()->GetBluetoothInputClient()->GetProperties(
574 object_path);
575
576 // Properties structure can be removed, which triggers a change in the
577 // BluetoothDevice::IsConnectable() property, as does a change in the
578 // actual reconnect_mode property.
579 if (!properties || property_name == properties->reconnect_mode.name()) {
580 NotifyDeviceChanged(device_bluez);
581 }
582 }
583
584 void BluetoothAdapterBlueZ::Released() {
585 VLOG(1) << "Release";
586 if (!IsPresent())
587 return;
588 DCHECK(agent_.get());
589
590 // Called after we unregister the pairing agent, e.g. when changing I/O
591 // capabilities. Nothing much to be done right now.
592 }
593
594 void BluetoothAdapterBlueZ::RequestPinCode(const dbus::ObjectPath& device_path,
595 const PinCodeCallback& callback) {
596 DCHECK(IsPresent());
597 DCHECK(agent_.get());
598 VLOG(1) << device_path.value() << ": RequestPinCode";
599
600 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
601 if (!pairing) {
602 callback.Run(REJECTED, "");
603 return;
604 }
605
606 pairing->RequestPinCode(callback);
607 }
608
609 void BluetoothAdapterBlueZ::DisplayPinCode(const dbus::ObjectPath& device_path,
610 const std::string& pincode) {
611 DCHECK(IsPresent());
612 DCHECK(agent_.get());
613 VLOG(1) << device_path.value() << ": DisplayPinCode: " << pincode;
614
615 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
616 if (!pairing)
617 return;
618
619 pairing->DisplayPinCode(pincode);
620 }
621
622 void BluetoothAdapterBlueZ::RequestPasskey(const dbus::ObjectPath& device_path,
623 const PasskeyCallback& callback) {
624 DCHECK(IsPresent());
625 DCHECK(agent_.get());
626 VLOG(1) << device_path.value() << ": RequestPasskey";
627
628 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
629 if (!pairing) {
630 callback.Run(REJECTED, 0);
631 return;
632 }
633
634 pairing->RequestPasskey(callback);
635 }
636
637 void BluetoothAdapterBlueZ::DisplayPasskey(const dbus::ObjectPath& device_path,
638 uint32_t passkey,
639 uint16_t entered) {
640 DCHECK(IsPresent());
641 DCHECK(agent_.get());
642 VLOG(1) << device_path.value() << ": DisplayPasskey: " << passkey << " ("
643 << entered << " entered)";
644
645 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
646 if (!pairing)
647 return;
648
649 if (entered == 0)
650 pairing->DisplayPasskey(passkey);
651
652 pairing->KeysEntered(entered);
653 }
654
655 void BluetoothAdapterBlueZ::RequestConfirmation(
656 const dbus::ObjectPath& device_path,
657 uint32_t passkey,
658 const ConfirmationCallback& callback) {
659 DCHECK(IsPresent());
660 DCHECK(agent_.get());
661 VLOG(1) << device_path.value() << ": RequestConfirmation: " << passkey;
662
663 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
664 if (!pairing) {
665 callback.Run(REJECTED);
666 return;
667 }
668
669 pairing->RequestConfirmation(passkey, callback);
670 }
671
672 void BluetoothAdapterBlueZ::RequestAuthorization(
673 const dbus::ObjectPath& device_path,
674 const ConfirmationCallback& callback) {
675 DCHECK(IsPresent());
676 DCHECK(agent_.get());
677 VLOG(1) << device_path.value() << ": RequestAuthorization";
678
679 BluetoothPairingBlueZ* pairing = GetPairing(device_path);
680 if (!pairing) {
681 callback.Run(REJECTED);
682 return;
683 }
684
685 pairing->RequestAuthorization(callback);
686 }
687
688 void BluetoothAdapterBlueZ::AuthorizeService(
689 const dbus::ObjectPath& device_path,
690 const std::string& uuid,
691 const ConfirmationCallback& callback) {
692 DCHECK(IsPresent());
693 DCHECK(agent_.get());
694 VLOG(1) << device_path.value() << ": AuthorizeService: " << uuid;
695
696 BluetoothDeviceBlueZ* device_bluez = GetDeviceWithPath(device_path);
697 if (!device_bluez) {
698 callback.Run(CANCELLED);
699 return;
700 }
701
702 // We always set paired devices to Trusted, so the only reason that this
703 // method call would ever be called is in the case of a race condition where
704 // our "Set('Trusted', true)" method call is still pending in the Bluetooth
705 // daemon because it's busy handling the incoming connection.
706 if (device_bluez->IsPaired()) {
707 callback.Run(SUCCESS);
708 return;
709 }
710
711 // TODO(keybuk): reject service authorizations when not paired, determine
712 // whether this is acceptable long-term.
713 LOG(WARNING) << "Rejecting service connection from unpaired device "
714 << device_bluez->GetAddress() << " for UUID " << uuid;
715 callback.Run(REJECTED);
716 }
717
718 void BluetoothAdapterBlueZ::Cancel() {
719 DCHECK(IsPresent());
720 DCHECK(agent_.get());
721 VLOG(1) << "Cancel";
722 }
723
724 void BluetoothAdapterBlueZ::OnRegisterAgent() {
725 VLOG(1) << "Pairing agent registered, requesting to be made default";
726
727 bluez::BluezDBusManager::Get()
728 ->GetBluetoothAgentManagerClient()
729 ->RequestDefaultAgent(
730 dbus::ObjectPath(kAgentPath),
731 base::Bind(&BluetoothAdapterBlueZ::OnRequestDefaultAgent,
732 weak_ptr_factory_.GetWeakPtr()),
733 base::Bind(&BluetoothAdapterBlueZ::OnRequestDefaultAgentError,
734 weak_ptr_factory_.GetWeakPtr()));
735 }
736
737 void BluetoothAdapterBlueZ::OnRegisterAgentError(
738 const std::string& error_name,
739 const std::string& error_message) {
740 // Our agent being already registered isn't an error.
741 if (error_name == bluetooth_agent_manager::kErrorAlreadyExists)
742 return;
743
744 LOG(WARNING) << ": Failed to register pairing agent: " << error_name << ": "
745 << error_message;
746 }
747
748 void BluetoothAdapterBlueZ::OnRequestDefaultAgent() {
749 VLOG(1) << "Pairing agent now default";
750 }
751
752 void BluetoothAdapterBlueZ::OnRequestDefaultAgentError(
753 const std::string& error_name,
754 const std::string& error_message) {
755 LOG(WARNING) << ": Failed to make pairing agent default: " << error_name
756 << ": " << error_message;
757 }
758
759 void BluetoothAdapterBlueZ::OnRegisterAudioSink(
760 const device::BluetoothAdapter::AcquiredCallback& callback,
761 const device::BluetoothAudioSink::ErrorCallback& error_callback,
762 scoped_refptr<BluetoothAudioSink> audio_sink) {
763 if (!IsPresent()) {
764 VLOG(1) << "Failed to register audio sink, adapter not present";
765 error_callback.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER);
766 return;
767 }
768 DCHECK(audio_sink.get());
769 callback.Run(audio_sink);
770 }
771
772 BluetoothDeviceBlueZ* BluetoothAdapterBlueZ::GetDeviceWithPath(
773 const dbus::ObjectPath& object_path) {
774 if (!IsPresent())
775 return nullptr;
776
777 for (DevicesMap::const_iterator iter = devices_.begin();
778 iter != devices_.end(); ++iter) {
779 BluetoothDeviceBlueZ* device_bluez =
780 static_cast<BluetoothDeviceBlueZ*>(iter->second);
781 if (device_bluez->object_path() == object_path)
782 return device_bluez;
783 }
784
785 return nullptr;
786 }
787
788 BluetoothPairingBlueZ* BluetoothAdapterBlueZ::GetPairing(
789 const dbus::ObjectPath& object_path) {
790 DCHECK(IsPresent());
791 BluetoothDeviceBlueZ* device_bluez = GetDeviceWithPath(object_path);
792 if (!device_bluez) {
793 LOG(WARNING) << "Pairing Agent request for unknown device: "
794 << object_path.value();
795 return nullptr;
796 }
797
798 BluetoothPairingBlueZ* pairing = device_bluez->GetPairing();
799 if (pairing)
800 return pairing;
801
802 // The device doesn't have its own pairing context, so this is an incoming
803 // pairing request that should use our best default delegate (if we have one).
804 BluetoothDevice::PairingDelegate* pairing_delegate = DefaultPairingDelegate();
805 if (!pairing_delegate)
806 return nullptr;
807
808 return device_bluez->BeginPairing(pairing_delegate);
809 }
810
811 void BluetoothAdapterBlueZ::SetAdapter(const dbus::ObjectPath& object_path) {
812 DCHECK(!IsPresent());
813 DCHECK(!dbus_is_shutdown_);
814 object_path_ = object_path;
815
816 VLOG(1) << object_path_.value() << ": using adapter.";
817
818 VLOG(1) << "Registering pairing agent";
819 bluez::BluezDBusManager::Get()
820 ->GetBluetoothAgentManagerClient()
821 ->RegisterAgent(dbus::ObjectPath(kAgentPath),
822 bluetooth_agent_manager::kKeyboardDisplayCapability,
823 base::Bind(&BluetoothAdapterBlueZ::OnRegisterAgent,
824 weak_ptr_factory_.GetWeakPtr()),
825 base::Bind(&BluetoothAdapterBlueZ::OnRegisterAgentError,
826 weak_ptr_factory_.GetWeakPtr()));
827
828 #if defined(OS_CHROMEOS)
829 SetStandardChromeOSAdapterName();
830 #endif
831
832 bluez::BluetoothAdapterClient::Properties* properties =
833 bluez::BluezDBusManager::Get()
834 ->GetBluetoothAdapterClient()
835 ->GetProperties(object_path_);
836
837 PresentChanged(true);
838
839 if (properties->powered.value())
840 PoweredChanged(true);
841 if (properties->discoverable.value())
842 DiscoverableChanged(true);
843 if (properties->discovering.value())
844 DiscoveringChanged(true);
845
846 std::vector<dbus::ObjectPath> device_paths =
847 bluez::BluezDBusManager::Get()
848 ->GetBluetoothDeviceClient()
849 ->GetDevicesForAdapter(object_path_);
850
851 for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin();
852 iter != device_paths.end(); ++iter) {
853 DeviceAdded(*iter);
854 }
855 }
856
857 #if defined(OS_CHROMEOS)
858 void BluetoothAdapterBlueZ::SetStandardChromeOSAdapterName() {
859 DCHECK(IsPresent());
860
861 std::string alias;
862 switch (chromeos::GetDeviceType()) {
863 case chromeos::DeviceType::kChromebase:
864 alias = "Chromebase";
865 break;
866 case chromeos::DeviceType::kChromebit:
867 alias = "Chromebit";
868 break;
869 case chromeos::DeviceType::kChromebook:
870 alias = "Chromebook";
871 break;
872 case chromeos::DeviceType::kChromebox:
873 alias = "Chromebox";
874 break;
875 case chromeos::DeviceType::kUnknown:
876 alias = "Chromebook";
877 break;
878 }
879 // Take the lower 2 bytes of hashed Bluetooth address and combine it with the
880 // device type to create a more identifiable device name.
881 const std::string address = GetAddress();
882 alias = base::StringPrintf(
883 "%s_%04X", alias.c_str(),
884 base::SuperFastHash(address.data(), address.size()) & 0xFFFF);
885 SetName(alias, base::Bind(&base::DoNothing), base::Bind(&base::DoNothing));
886 }
887 #endif
888
889 void BluetoothAdapterBlueZ::RemoveAdapter() {
890 DCHECK(IsPresent());
891 VLOG(1) << object_path_.value() << ": adapter removed.";
892
893 bluez::BluetoothAdapterClient::Properties* properties =
894 bluez::BluezDBusManager::Get()
895 ->GetBluetoothAdapterClient()
896 ->GetProperties(object_path_);
897
898 object_path_ = dbus::ObjectPath("");
899
900 if (properties->powered.value())
901 PoweredChanged(false);
902 if (properties->discoverable.value())
903 DiscoverableChanged(false);
904 if (properties->discovering.value())
905 DiscoveringChanged(false);
906
907 // Move all elements of the original devices list to a new list here,
908 // leaving the original list empty so that when we send DeviceRemoved(),
909 // GetDevices() returns no devices.
910 DevicesMap devices_swapped;
911 devices_swapped.swap(devices_);
912
913 for (auto& iter : devices_swapped) {
914 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
915 DeviceRemoved(this, iter.second));
916 }
917
918 PresentChanged(false);
919 }
920
921 void BluetoothAdapterBlueZ::PoweredChanged(bool powered) {
922 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
923 AdapterPoweredChanged(this, powered));
924 }
925
926 void BluetoothAdapterBlueZ::DiscoverableChanged(bool discoverable) {
927 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
928 AdapterDiscoverableChanged(this, discoverable));
929 }
930
931 void BluetoothAdapterBlueZ::DiscoveringChanged(bool discovering) {
932 // If the adapter stopped discovery due to a reason other than a request by
933 // us, reset the count to 0.
934 VLOG(1) << "Discovering changed: " << discovering;
935 if (!discovering && !discovery_request_pending_ &&
936 num_discovery_sessions_ > 0) {
937 VLOG(1) << "Marking sessions as inactive.";
938 num_discovery_sessions_ = 0;
939 MarkDiscoverySessionsAsInactive();
940 }
941 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
942 AdapterDiscoveringChanged(this, discovering));
943 }
944
945 void BluetoothAdapterBlueZ::PresentChanged(bool present) {
946 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
947 AdapterPresentChanged(this, present));
948 }
949
950 void BluetoothAdapterBlueZ::NotifyDeviceChanged(BluetoothDeviceBlueZ* device) {
951 DCHECK(device);
952 DCHECK(device->adapter_ == this);
953
954 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
955 DeviceChanged(this, device));
956 }
957
958 void BluetoothAdapterBlueZ::NotifyDeviceAddressChanged(
959 BluetoothDeviceBlueZ* device,
960 const std::string& old_address) {
961 DCHECK(device->adapter_ == this);
962
963 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
964 DeviceAddressChanged(this, device, old_address));
965 }
966
967 void BluetoothAdapterBlueZ::UseProfile(
968 const BluetoothUUID& uuid,
969 const dbus::ObjectPath& device_path,
970 const bluez::BluetoothProfileManagerClient::Options& options,
971 bluez::BluetoothProfileServiceProvider::Delegate* delegate,
972 const ProfileRegisteredCallback& success_callback,
973 const ErrorCompletionCallback& error_callback) {
974 DCHECK(delegate);
975
976 if (!IsPresent()) {
977 VLOG(2) << "Adapter not present, erroring out";
978 error_callback.Run("Adapter not present");
979 return;
980 }
981
982 if (profiles_.find(uuid) != profiles_.end()) {
983 // TODO(jamuraa) check that the options are the same and error when they are
984 // not.
985 SetProfileDelegate(uuid, device_path, delegate, success_callback,
986 error_callback);
987 return;
988 }
989
990 if (profile_queues_.find(uuid) == profile_queues_.end()) {
991 BluetoothAdapterProfileBlueZ::Register(
992 uuid, options,
993 base::Bind(&BluetoothAdapterBlueZ::OnRegisterProfile, this, uuid),
994 base::Bind(&BluetoothAdapterBlueZ::OnRegisterProfileError, this, uuid));
995
996 profile_queues_[uuid] = new std::vector<RegisterProfileCompletionPair>();
997 }
998
999 profile_queues_[uuid]->push_back(std::make_pair(
1000 base::Bind(&BluetoothAdapterBlueZ::SetProfileDelegate, this, uuid,
1001 device_path, delegate, success_callback, error_callback),
1002 error_callback));
1003 }
1004
1005 void BluetoothAdapterBlueZ::ReleaseProfile(
1006 const dbus::ObjectPath& device_path,
1007 BluetoothAdapterProfileBlueZ* profile) {
1008 VLOG(2) << "Releasing Profile: " << profile->uuid().canonical_value()
1009 << " from " << device_path.value();
1010 profile->RemoveDelegate(
1011 device_path, base::Bind(&BluetoothAdapterBlueZ::RemoveProfile,
1012 weak_ptr_factory_.GetWeakPtr(), profile->uuid()));
1013 }
1014
1015 void BluetoothAdapterBlueZ::RemoveProfile(const BluetoothUUID& uuid) {
1016 VLOG(2) << "Remove Profile: " << uuid.canonical_value();
1017
1018 if (profiles_.find(uuid) != profiles_.end()) {
1019 delete profiles_[uuid];
1020 profiles_.erase(uuid);
1021 }
1022 }
1023
1024 void BluetoothAdapterBlueZ::OnRegisterProfile(
1025 const BluetoothUUID& uuid,
1026 std::unique_ptr<BluetoothAdapterProfileBlueZ> profile) {
1027 profiles_[uuid] = profile.release();
1028
1029 if (profile_queues_.find(uuid) == profile_queues_.end())
1030 return;
1031
1032 for (auto& it : *profile_queues_[uuid])
1033 it.first.Run();
1034 delete profile_queues_[uuid];
1035 profile_queues_.erase(uuid);
1036 }
1037
1038 void BluetoothAdapterBlueZ::SetProfileDelegate(
1039 const BluetoothUUID& uuid,
1040 const dbus::ObjectPath& device_path,
1041 bluez::BluetoothProfileServiceProvider::Delegate* delegate,
1042 const ProfileRegisteredCallback& success_callback,
1043 const ErrorCompletionCallback& error_callback) {
1044 if (profiles_.find(uuid) == profiles_.end()) {
1045 error_callback.Run("Cannot find profile!");
1046 return;
1047 }
1048
1049 if (profiles_[uuid]->SetDelegate(device_path, delegate)) {
1050 success_callback.Run(profiles_[uuid]);
1051 return;
1052 }
1053 // Already set
1054 error_callback.Run(bluetooth_agent_manager::kErrorAlreadyExists);
1055 }
1056
1057 void BluetoothAdapterBlueZ::OnRegisterProfileError(
1058 const BluetoothUUID& uuid,
1059 const std::string& error_name,
1060 const std::string& error_message) {
1061 VLOG(2) << object_path_.value()
1062 << ": Failed to register profile: " << error_name << ": "
1063 << error_message;
1064 if (profile_queues_.find(uuid) == profile_queues_.end())
1065 return;
1066
1067 for (auto& it : *profile_queues_[uuid])
1068 it.second.Run(error_message);
1069
1070 delete profile_queues_[uuid];
1071 profile_queues_.erase(uuid);
1072 }
1073
1074 void BluetoothAdapterBlueZ::OnSetDiscoverable(
1075 const base::Closure& callback,
1076 const ErrorCallback& error_callback,
1077 bool success) {
1078 if (!IsPresent()) {
1079 error_callback.Run();
1080 return;
1081 }
1082
1083 // Set the discoverable_timeout property to zero so the adapter remains
1084 // discoverable forever.
1085 bluez::BluezDBusManager::Get()
1086 ->GetBluetoothAdapterClient()
1087 ->GetProperties(object_path_)
1088 ->discoverable_timeout.Set(
1089 0,
1090 base::Bind(&BluetoothAdapterBlueZ::OnPropertyChangeCompleted,
1091 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1092 }
1093
1094 void BluetoothAdapterBlueZ::OnPropertyChangeCompleted(
1095 const base::Closure& callback,
1096 const ErrorCallback& error_callback,
1097 bool success) {
1098 if (IsPresent() && success) {
1099 callback.Run();
1100 } else {
1101 error_callback.Run();
1102 }
1103 }
1104
1105 void BluetoothAdapterBlueZ::AddDiscoverySession(
1106 BluetoothDiscoveryFilter* discovery_filter,
1107 const base::Closure& callback,
1108 const DiscoverySessionErrorCallback& error_callback) {
1109 if (!IsPresent()) {
1110 error_callback.Run(
1111 UMABluetoothDiscoverySessionOutcome::ADAPTER_NOT_PRESENT);
1112 return;
1113 }
1114 VLOG(1) << __func__;
1115 if (discovery_request_pending_) {
1116 // The pending request is either to stop a previous session or to start a
1117 // new one. Either way, queue this one.
1118 DCHECK(num_discovery_sessions_ == 1 || num_discovery_sessions_ == 0);
1119 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1120 << "request to start a new discovery session.";
1121 discovery_request_queue_.push(
1122 std::make_tuple(discovery_filter, callback, error_callback));
1123 return;
1124 }
1125
1126 // The adapter is already discovering.
1127 if (num_discovery_sessions_ > 0) {
1128 DCHECK(IsDiscovering());
1129 DCHECK(!discovery_request_pending_);
1130 num_discovery_sessions_++;
1131 SetDiscoveryFilter(BluetoothDiscoveryFilter::Merge(
1132 GetMergedDiscoveryFilter().get(), discovery_filter),
1133 callback, error_callback);
1134 return;
1135 }
1136
1137 // There are no active discovery sessions.
1138 DCHECK_EQ(num_discovery_sessions_, 0);
1139
1140 if (discovery_filter) {
1141 discovery_request_pending_ = true;
1142
1143 std::unique_ptr<BluetoothDiscoveryFilter> df(new BluetoothDiscoveryFilter(
1144 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL));
1145 df->CopyFrom(*discovery_filter);
1146 SetDiscoveryFilter(
1147 std::move(df),
1148 base::Bind(&BluetoothAdapterBlueZ::OnPreSetDiscoveryFilter,
1149 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
1150 base::Bind(&BluetoothAdapterBlueZ::OnPreSetDiscoveryFilterError,
1151 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1152 return;
1153 } else {
1154 current_filter_.reset();
1155 }
1156
1157 // This is the first request to start device discovery.
1158 discovery_request_pending_ = true;
1159 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1160 object_path_,
1161 base::Bind(&BluetoothAdapterBlueZ::OnStartDiscovery,
1162 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
1163 base::Bind(&BluetoothAdapterBlueZ::OnStartDiscoveryError,
1164 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1165 }
1166
1167 void BluetoothAdapterBlueZ::RemoveDiscoverySession(
1168 BluetoothDiscoveryFilter* discovery_filter,
1169 const base::Closure& callback,
1170 const DiscoverySessionErrorCallback& error_callback) {
1171 if (!IsPresent()) {
1172 error_callback.Run(
1173 UMABluetoothDiscoverySessionOutcome::ADAPTER_NOT_PRESENT);
1174 return;
1175 }
1176
1177 VLOG(1) << __func__;
1178 // There are active sessions other than the one currently being removed.
1179 if (num_discovery_sessions_ > 1) {
1180 DCHECK(IsDiscovering());
1181 DCHECK(!discovery_request_pending_);
1182 num_discovery_sessions_--;
1183
1184 SetDiscoveryFilter(GetMergedDiscoveryFilterMasked(discovery_filter),
1185 callback, error_callback);
1186 return;
1187 }
1188
1189 // If there is a pending request to BlueZ, then queue this request.
1190 if (discovery_request_pending_) {
1191 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1192 << "request to stop discovery session.";
1193 error_callback.Run(
1194 UMABluetoothDiscoverySessionOutcome::REMOVE_WITH_PENDING_REQUEST);
1195 return;
1196 }
1197
1198 // There are no active sessions. Return error.
1199 if (num_discovery_sessions_ == 0) {
1200 // TODO(armansito): This should never happen once we have the
1201 // DiscoverySession API. Replace this case with an assert once it's
1202 // the deprecated methods have been removed. (See crbug.com/3445008).
1203 VLOG(1) << "No active discovery sessions. Returning error.";
1204 error_callback.Run(
1205 UMABluetoothDiscoverySessionOutcome::ACTIVE_SESSION_NOT_IN_ADAPTER);
1206 return;
1207 }
1208
1209 // There is exactly one active discovery session. Request BlueZ to stop
1210 // discovery.
1211 DCHECK_EQ(num_discovery_sessions_, 1);
1212 discovery_request_pending_ = true;
1213 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StopDiscovery(
1214 object_path_, base::Bind(&BluetoothAdapterBlueZ::OnStopDiscovery,
1215 weak_ptr_factory_.GetWeakPtr(), callback),
1216 base::Bind(&BluetoothAdapterBlueZ::OnStopDiscoveryError,
1217 weak_ptr_factory_.GetWeakPtr(), error_callback));
1218 }
1219
1220 void BluetoothAdapterBlueZ::SetDiscoveryFilter(
1221 std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,
1222 const base::Closure& callback,
1223 const DiscoverySessionErrorCallback& error_callback) {
1224 if (!IsPresent()) {
1225 error_callback.Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED);
1226 return;
1227 }
1228
1229 // If old and new filter are equal (null) then don't make request, just call
1230 // succes callback
1231 if (!current_filter_ && !discovery_filter.get()) {
1232 callback.Run();
1233 return;
1234 }
1235
1236 // If old and new filter are not null and equal then don't make request, just
1237 // call succes callback
1238 if (current_filter_ && discovery_filter &&
1239 current_filter_->Equals(*discovery_filter)) {
1240 callback.Run();
1241 return;
1242 }
1243
1244 current_filter_.reset(discovery_filter.release());
1245
1246 bluez::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter;
1247
1248 if (current_filter_.get()) {
1249 uint16_t pathloss;
1250 int16_t rssi;
1251 uint8_t transport;
1252 std::set<device::BluetoothUUID> uuids;
1253
1254 if (current_filter_->GetPathloss(&pathloss))
1255 dbus_discovery_filter.pathloss.reset(new uint16_t(pathloss));
1256
1257 if (current_filter_->GetRSSI(&rssi))
1258 dbus_discovery_filter.rssi.reset(new int16_t(rssi));
1259
1260 transport = current_filter_->GetTransport();
1261 if (transport == BluetoothDiscoveryFilter::Transport::TRANSPORT_LE) {
1262 dbus_discovery_filter.transport.reset(new std::string("le"));
1263 } else if (transport ==
1264 BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC) {
1265 dbus_discovery_filter.transport.reset(new std::string("bredr"));
1266 } else if (transport ==
1267 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL) {
1268 dbus_discovery_filter.transport.reset(new std::string("auto"));
1269 }
1270
1271 current_filter_->GetUUIDs(uuids);
1272 if (uuids.size()) {
1273 dbus_discovery_filter.uuids = std::unique_ptr<std::vector<std::string>>(
1274 new std::vector<std::string>);
1275
1276 for (const auto& it : uuids)
1277 dbus_discovery_filter.uuids.get()->push_back(it.value());
1278 }
1279 }
1280
1281 bluez::BluezDBusManager::Get()
1282 ->GetBluetoothAdapterClient()
1283 ->SetDiscoveryFilter(
1284 object_path_, dbus_discovery_filter,
1285 base::Bind(&BluetoothAdapterBlueZ::OnSetDiscoveryFilter,
1286 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
1287 base::Bind(&BluetoothAdapterBlueZ::OnSetDiscoveryFilterError,
1288 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1289 }
1290
1291 void BluetoothAdapterBlueZ::OnStartDiscovery(
1292 const base::Closure& callback,
1293 const DiscoverySessionErrorCallback& error_callback) {
1294 // Report success on the original request and increment the count.
1295 VLOG(1) << __func__;
1296 DCHECK(discovery_request_pending_);
1297 DCHECK_EQ(num_discovery_sessions_, 0);
1298 discovery_request_pending_ = false;
1299 num_discovery_sessions_++;
1300 if (IsPresent()) {
1301 callback.Run();
1302 } else {
1303 error_callback.Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED);
1304 }
1305
1306 // Try to add a new discovery session for each queued request.
1307 ProcessQueuedDiscoveryRequests();
1308 }
1309
1310 void BluetoothAdapterBlueZ::OnStartDiscoveryError(
1311 const base::Closure& callback,
1312 const DiscoverySessionErrorCallback& error_callback,
1313 const std::string& error_name,
1314 const std::string& error_message) {
1315 LOG(WARNING) << object_path_.value()
1316 << ": Failed to start discovery: " << error_name << ": "
1317 << error_message;
1318
1319 // Failed to start discovery. This can only happen if the count is at 0.
1320 DCHECK_EQ(num_discovery_sessions_, 0);
1321 DCHECK(discovery_request_pending_);
1322 discovery_request_pending_ = false;
1323
1324 // Discovery request may fail if discovery was previously initiated by Chrome,
1325 // but the session were invalidated due to the discovery state unexpectedly
1326 // changing to false and then back to true. In this case, report success.
1327 if (IsPresent() && error_name == bluetooth_device::kErrorInProgress &&
1328 IsDiscovering()) {
1329 VLOG(1) << "Discovery previously initiated. Reporting success.";
1330 num_discovery_sessions_++;
1331 callback.Run();
1332 } else {
1333 error_callback.Run(TranslateDiscoveryErrorToUMA(error_name));
1334 }
1335
1336 // Try to add a new discovery session for each queued request.
1337 ProcessQueuedDiscoveryRequests();
1338 }
1339
1340 void BluetoothAdapterBlueZ::OnStopDiscovery(const base::Closure& callback) {
1341 // Report success on the original request and decrement the count.
1342 VLOG(1) << __func__;
1343 DCHECK(discovery_request_pending_);
1344 DCHECK_EQ(num_discovery_sessions_, 1);
1345 discovery_request_pending_ = false;
1346 num_discovery_sessions_--;
1347 callback.Run();
1348
1349 current_filter_.reset();
1350
1351 // Try to add a new discovery session for each queued request.
1352 ProcessQueuedDiscoveryRequests();
1353 }
1354
1355 void BluetoothAdapterBlueZ::OnStopDiscoveryError(
1356 const DiscoverySessionErrorCallback& error_callback,
1357 const std::string& error_name,
1358 const std::string& error_message) {
1359 LOG(WARNING) << object_path_.value()
1360 << ": Failed to stop discovery: " << error_name << ": "
1361 << error_message;
1362
1363 // Failed to stop discovery. This can only happen if the count is at 1.
1364 DCHECK(discovery_request_pending_);
1365 DCHECK_EQ(num_discovery_sessions_, 1);
1366 discovery_request_pending_ = false;
1367 error_callback.Run(TranslateDiscoveryErrorToUMA(error_name));
1368
1369 // Try to add a new discovery session for each queued request.
1370 ProcessQueuedDiscoveryRequests();
1371 }
1372
1373 void BluetoothAdapterBlueZ::OnPreSetDiscoveryFilter(
1374 const base::Closure& callback,
1375 const DiscoverySessionErrorCallback& error_callback) {
1376 // This is the first request to start device discovery.
1377 DCHECK(discovery_request_pending_);
1378 DCHECK_EQ(num_discovery_sessions_, 0);
1379
1380 bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1381 object_path_,
1382 base::Bind(&BluetoothAdapterBlueZ::OnStartDiscovery,
1383 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
1384 base::Bind(&BluetoothAdapterBlueZ::OnStartDiscoveryError,
1385 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1386 }
1387
1388 void BluetoothAdapterBlueZ::OnPreSetDiscoveryFilterError(
1389 const base::Closure& callback,
1390 const DiscoverySessionErrorCallback& error_callback,
1391 UMABluetoothDiscoverySessionOutcome outcome) {
1392 LOG(WARNING) << object_path_.value()
1393 << ": Failed to pre set discovery filter.";
1394
1395 // Failed to start discovery. This can only happen if the count is at 0.
1396 DCHECK_EQ(num_discovery_sessions_, 0);
1397 DCHECK(discovery_request_pending_);
1398 discovery_request_pending_ = false;
1399
1400 error_callback.Run(outcome);
1401
1402 // Try to add a new discovery session for each queued request.
1403 ProcessQueuedDiscoveryRequests();
1404 }
1405
1406 void BluetoothAdapterBlueZ::OnSetDiscoveryFilter(
1407 const base::Closure& callback,
1408 const DiscoverySessionErrorCallback& error_callback) {
1409 // Report success on the original request and increment the count.
1410 VLOG(1) << __func__;
1411 if (IsPresent()) {
1412 callback.Run();
1413 } else {
1414 error_callback.Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED);
1415 }
1416 }
1417
1418 void BluetoothAdapterBlueZ::OnSetDiscoveryFilterError(
1419 const base::Closure& callback,
1420 const DiscoverySessionErrorCallback& error_callback,
1421 const std::string& error_name,
1422 const std::string& error_message) {
1423 LOG(WARNING) << object_path_.value()
1424 << ": Failed to set discovery filter: " << error_name << ": "
1425 << error_message;
1426
1427 UMABluetoothDiscoverySessionOutcome outcome =
1428 TranslateDiscoveryErrorToUMA(error_name);
1429 if (outcome == UMABluetoothDiscoverySessionOutcome::FAILED) {
1430 // bluez/doc/adapter-api.txt says "Failed" is returned from
1431 // SetDiscoveryFilter when the controller doesn't support the requested
1432 // transport.
1433 outcome = UMABluetoothDiscoverySessionOutcome::
1434 BLUEZ_DBUS_FAILED_MAYBE_UNSUPPORTED_TRANSPORT;
1435 }
1436 error_callback.Run(outcome);
1437
1438 // Try to add a new discovery session for each queued request.
1439 ProcessQueuedDiscoveryRequests();
1440 }
1441
1442 void BluetoothAdapterBlueZ::ProcessQueuedDiscoveryRequests() {
1443 while (!discovery_request_queue_.empty()) {
1444 VLOG(1) << "Process queued discovery request.";
1445 DiscoveryParamTuple params = discovery_request_queue_.front();
1446 discovery_request_queue_.pop();
1447 AddDiscoverySession(std::get<0>(params), std::get<1>(params),
1448 std::get<2>(params));
1449
1450 // If the queued request resulted in a pending call, then let it
1451 // asynchonously process the remaining queued requests once the pending
1452 // call returns.
1453 if (discovery_request_pending_)
1454 return;
1455 }
1456 }
1457
1458 } // namespace bluez
OLDNEW
« no previous file with comments | « device/bluetooth/bluetooth_adapter_bluez.h ('k') | device/bluetooth/bluetooth_adapter_profile_bluez.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698