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.
5 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/metrics/histogram.h"
13 #include "base/sequenced_task_runner.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "chromeos/dbus/bluetooth_adapter_client.h"
17 #include "chromeos/dbus/bluetooth_agent_manager_client.h"
18 #include "chromeos/dbus/bluetooth_agent_service_provider.h"
19 #include "chromeos/dbus/bluetooth_device_client.h"
20 #include "chromeos/dbus/bluetooth_input_client.h"
21 #include "chromeos/dbus/dbus_thread_manager.h"
22 #include "chromeos/system/devicetype.h"
23 #include "device/bluetooth/bluetooth_adapter_profile_chromeos.h"
24 #include "device/bluetooth/bluetooth_advertisement_chromeos.h"
25 #include "device/bluetooth/bluetooth_audio_sink_chromeos.h"
26 #include "device/bluetooth/bluetooth_device.h"
27 #include "device/bluetooth/bluetooth_device_chromeos.h"
28 #include "device/bluetooth/bluetooth_pairing_chromeos.h"
29 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
30 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
31 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
32 #include "device/bluetooth/bluetooth_socket_chromeos.h"
33 #include "device/bluetooth/bluetooth_socket_thread.h"
34 #include "device/bluetooth/bluetooth_uuid.h"
35 #include "third_party/cros_system_api/dbus/service_constants.h"
37 using device::BluetoothAdapter
;
38 using device::BluetoothAudioSink
;
39 using device::BluetoothDevice
;
40 using device::BluetoothDiscoveryFilter
;
41 using device::BluetoothSocket
;
42 using device::BluetoothUUID
;
46 // The agent path is relatively meaningless since BlueZ only permits one to
47 // exist per D-Bus connection, it just has to be unique within Chromium.
48 const char kAgentPath
[] = "/org/chromium/bluetooth_agent";
50 void OnUnregisterAgentError(const std::string
& error_name
,
51 const std::string
& error_message
) {
52 // It's okay if the agent didn't exist, it means we never saw an adapter.
53 if (error_name
== bluetooth_agent_manager::kErrorDoesNotExist
)
56 LOG(WARNING
) << "Failed to unregister pairing agent: "
57 << error_name
<< ": " << error_message
;
65 base::WeakPtr
<BluetoothAdapter
> BluetoothAdapter::CreateAdapter(
66 const InitCallback
& init_callback
) {
67 return chromeos::BluetoothAdapterChromeOS::CreateAdapter();
75 base::WeakPtr
<BluetoothAdapter
> BluetoothAdapterChromeOS::CreateAdapter() {
76 BluetoothAdapterChromeOS
* adapter
= new BluetoothAdapterChromeOS();
77 return adapter
->weak_ptr_factory_
.GetWeakPtr();
80 void BluetoothAdapterChromeOS::Shutdown() {
81 if (dbus_is_shutdown_
)
83 DCHECK(DBusThreadManager::IsInitialized())
84 << "Call BluetoothAdapterFactory::Shutdown() before "
85 "DBusThreadManager::Shutdown().";
88 RemoveAdapter(); // Also deletes devices_.
89 DCHECK(devices_
.empty());
90 // profiles_ is empty because all BluetoothSockets have been notified
91 // that this adapter is disappearing.
92 DCHECK(profiles_
.empty());
94 for (auto& it
: profile_queues_
)
96 profile_queues_
.clear();
98 DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(this);
99 DBusThreadManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(this);
100 DBusThreadManager::Get()->GetBluetoothInputClient()->RemoveObserver(this);
102 VLOG(1) << "Unregistering pairing agent";
103 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->UnregisterAgent(
104 dbus::ObjectPath(kAgentPath
), base::Bind(&base::DoNothing
),
105 base::Bind(&OnUnregisterAgentError
));
108 dbus_is_shutdown_
= true;
111 BluetoothAdapterChromeOS::BluetoothAdapterChromeOS()
112 : dbus_is_shutdown_(false),
113 num_discovery_sessions_(0),
114 discovery_request_pending_(false),
115 weak_ptr_factory_(this) {
116 ui_task_runner_
= base::ThreadTaskRunnerHandle::Get();
117 socket_thread_
= device::BluetoothSocketThread::Get();
119 DBusThreadManager::Get()->GetBluetoothAdapterClient()->AddObserver(this);
120 DBusThreadManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
121 DBusThreadManager::Get()->GetBluetoothInputClient()->AddObserver(this);
123 // Register the pairing agent.
124 dbus::Bus
* system_bus
= DBusThreadManager::Get()->GetSystemBus();
125 agent_
.reset(BluetoothAgentServiceProvider::Create(
126 system_bus
, dbus::ObjectPath(kAgentPath
), this));
127 DCHECK(agent_
.get());
129 std::vector
<dbus::ObjectPath
> object_paths
=
130 DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetAdapters();
132 if (!object_paths
.empty()) {
133 VLOG(1) << object_paths
.size() << " Bluetooth adapter(s) available.";
134 SetAdapter(object_paths
[0]);
138 BluetoothAdapterChromeOS::~BluetoothAdapterChromeOS() {
142 std::string
BluetoothAdapterChromeOS::GetAddress() const {
144 return std::string();
146 BluetoothAdapterClient::Properties
* properties
=
147 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
148 GetProperties(object_path_
);
151 return BluetoothDevice::CanonicalizeAddress(properties
->address
.value());
154 std::string
BluetoothAdapterChromeOS::GetName() const {
156 return std::string();
158 BluetoothAdapterClient::Properties
* properties
=
159 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
160 GetProperties(object_path_
);
163 return properties
->alias
.value();
166 void BluetoothAdapterChromeOS::SetName(const std::string
& name
,
167 const base::Closure
& callback
,
168 const ErrorCallback
& error_callback
) {
170 error_callback
.Run();
174 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
175 GetProperties(object_path_
)->alias
.Set(
177 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
178 weak_ptr_factory_
.GetWeakPtr(),
183 bool BluetoothAdapterChromeOS::IsInitialized() const {
187 bool BluetoothAdapterChromeOS::IsPresent() const {
188 return !dbus_is_shutdown_
&& !object_path_
.value().empty();
191 bool BluetoothAdapterChromeOS::IsPowered() const {
195 BluetoothAdapterClient::Properties
* properties
=
196 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
197 GetProperties(object_path_
);
199 return properties
->powered
.value();
202 void BluetoothAdapterChromeOS::SetPowered(
204 const base::Closure
& callback
,
205 const ErrorCallback
& error_callback
) {
207 error_callback
.Run();
211 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
212 GetProperties(object_path_
)->powered
.Set(
214 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
215 weak_ptr_factory_
.GetWeakPtr(),
220 bool BluetoothAdapterChromeOS::IsDiscoverable() const {
224 BluetoothAdapterClient::Properties
* properties
=
225 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
226 GetProperties(object_path_
);
228 return properties
->discoverable
.value();
231 void BluetoothAdapterChromeOS::SetDiscoverable(
233 const base::Closure
& callback
,
234 const ErrorCallback
& error_callback
) {
236 error_callback
.Run();
240 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
241 GetProperties(object_path_
)->discoverable
.Set(
243 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoverable
,
244 weak_ptr_factory_
.GetWeakPtr(),
249 bool BluetoothAdapterChromeOS::IsDiscovering() const {
253 BluetoothAdapterClient::Properties
* properties
=
254 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
255 GetProperties(object_path_
);
257 return properties
->discovering
.value();
260 void BluetoothAdapterChromeOS::CreateRfcommService(
261 const BluetoothUUID
& uuid
,
262 const ServiceOptions
& options
,
263 const CreateServiceCallback
& callback
,
264 const CreateServiceErrorCallback
& error_callback
) {
265 DCHECK(!dbus_is_shutdown_
);
266 VLOG(1) << object_path_
.value() << ": Creating RFCOMM service: "
267 << uuid
.canonical_value();
268 scoped_refptr
<BluetoothSocketChromeOS
> socket
=
269 BluetoothSocketChromeOS::CreateBluetoothSocket(
270 ui_task_runner_
, socket_thread_
);
272 BluetoothSocketChromeOS::kRfcomm
,
275 base::Bind(callback
, socket
),
279 void BluetoothAdapterChromeOS::CreateL2capService(
280 const BluetoothUUID
& uuid
,
281 const ServiceOptions
& options
,
282 const CreateServiceCallback
& callback
,
283 const CreateServiceErrorCallback
& error_callback
) {
284 DCHECK(!dbus_is_shutdown_
);
285 VLOG(1) << object_path_
.value() << ": Creating L2CAP service: "
286 << uuid
.canonical_value();
287 scoped_refptr
<BluetoothSocketChromeOS
> socket
=
288 BluetoothSocketChromeOS::CreateBluetoothSocket(
289 ui_task_runner_
, socket_thread_
);
291 BluetoothSocketChromeOS::kL2cap
,
294 base::Bind(callback
, socket
),
298 void BluetoothAdapterChromeOS::RegisterAudioSink(
299 const BluetoothAudioSink::Options
& options
,
300 const device::BluetoothAdapter::AcquiredCallback
& callback
,
301 const BluetoothAudioSink::ErrorCallback
& error_callback
) {
302 VLOG(1) << "Registering audio sink";
303 if (!this->IsPresent()) {
304 error_callback
.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER
);
307 scoped_refptr
<BluetoothAudioSinkChromeOS
> audio_sink(
308 new BluetoothAudioSinkChromeOS(this));
309 audio_sink
->Register(
310 options
, base::Bind(&BluetoothAdapterChromeOS::OnRegisterAudioSink
,
311 weak_ptr_factory_
.GetWeakPtr(), callback
,
312 error_callback
, audio_sink
),
316 void BluetoothAdapterChromeOS::RegisterAdvertisement(
317 scoped_ptr
<device::BluetoothAdvertisement::Data
> advertisement_data
,
318 const CreateAdvertisementCallback
& callback
,
319 const CreateAdvertisementErrorCallback
& error_callback
) {
320 scoped_refptr
<BluetoothAdvertisementChromeOS
> advertisement(
321 new BluetoothAdvertisementChromeOS(advertisement_data
.Pass(), this));
322 advertisement
->Register(base::Bind(callback
, advertisement
), error_callback
);
325 void BluetoothAdapterChromeOS::RemovePairingDelegateInternal(
326 BluetoothDevice::PairingDelegate
* pairing_delegate
) {
327 // Check if any device is using the pairing delegate.
328 // If so, clear the pairing context which will make any responses no-ops.
329 for (DevicesMap::iterator iter
= devices_
.begin();
330 iter
!= devices_
.end(); ++iter
) {
331 BluetoothDeviceChromeOS
* device_chromeos
=
332 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
334 BluetoothPairingChromeOS
* pairing
= device_chromeos
->GetPairing();
335 if (pairing
&& pairing
->GetPairingDelegate() == pairing_delegate
)
336 device_chromeos
->EndPairing();
340 void BluetoothAdapterChromeOS::AdapterAdded(
341 const dbus::ObjectPath
& object_path
) {
342 // Set the adapter to the newly added adapter only if no adapter is present.
344 SetAdapter(object_path
);
347 void BluetoothAdapterChromeOS::AdapterRemoved(
348 const dbus::ObjectPath
& object_path
) {
349 if (object_path
== object_path_
)
353 void BluetoothAdapterChromeOS::AdapterPropertyChanged(
354 const dbus::ObjectPath
& object_path
,
355 const std::string
& property_name
) {
356 if (object_path
!= object_path_
)
360 BluetoothAdapterClient::Properties
* properties
=
361 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
362 GetProperties(object_path_
);
364 if (property_name
== properties
->powered
.name()) {
365 PoweredChanged(properties
->powered
.value());
366 } else if (property_name
== properties
->discoverable
.name()) {
367 DiscoverableChanged(properties
->discoverable
.value());
368 } else if (property_name
== properties
->discovering
.name()) {
369 DiscoveringChanged(properties
->discovering
.value());
373 void BluetoothAdapterChromeOS::DeviceAdded(
374 const dbus::ObjectPath
& object_path
) {
375 DCHECK(DBusThreadManager::Get());
376 BluetoothDeviceClient::Properties
* properties
=
377 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
378 GetProperties(object_path
);
379 if (!properties
|| properties
->adapter
.value() != object_path_
)
383 BluetoothDeviceChromeOS
* device_chromeos
=
384 new BluetoothDeviceChromeOS(this,
388 DCHECK(devices_
.find(device_chromeos
->GetAddress()) == devices_
.end());
390 devices_
[device_chromeos
->GetAddress()] = device_chromeos
;
392 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
393 DeviceAdded(this, device_chromeos
));
396 void BluetoothAdapterChromeOS::DeviceRemoved(
397 const dbus::ObjectPath
& object_path
) {
398 for (DevicesMap::iterator iter
= devices_
.begin();
399 iter
!= devices_
.end(); ++iter
) {
400 BluetoothDeviceChromeOS
* device_chromeos
=
401 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
402 if (device_chromeos
->object_path() == object_path
) {
403 devices_
.erase(iter
);
405 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
406 DeviceRemoved(this, device_chromeos
));
407 delete device_chromeos
;
413 void BluetoothAdapterChromeOS::DevicePropertyChanged(
414 const dbus::ObjectPath
& object_path
,
415 const std::string
& property_name
) {
416 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
417 if (!device_chromeos
)
420 BluetoothDeviceClient::Properties
* properties
=
421 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
422 GetProperties(object_path
);
424 if (property_name
== properties
->bluetooth_class
.name() ||
425 property_name
== properties
->address
.name() ||
426 property_name
== properties
->alias
.name() ||
427 property_name
== properties
->paired
.name() ||
428 property_name
== properties
->trusted
.name() ||
429 property_name
== properties
->connected
.name() ||
430 property_name
== properties
->uuids
.name() ||
431 property_name
== properties
->rssi
.name() ||
432 property_name
== properties
->tx_power
.name()) {
433 NotifyDeviceChanged(device_chromeos
);
436 // When a device becomes paired, mark it as trusted so that the user does
437 // not need to approve every incoming connection
438 if (property_name
== properties
->paired
.name() &&
439 properties
->paired
.value() && !properties
->trusted
.value()) {
440 device_chromeos
->SetTrusted();
443 // UMA connection counting
444 if (property_name
== properties
->connected
.name()) {
445 // PlayStation joystick tries to reconnect after disconnection from USB.
446 // If it is still not trusted, set it, so it becomes available on the
447 // list of known devices.
448 if (properties
->connected
.value() && device_chromeos
->IsTrustable() &&
449 !properties
->trusted
.value())
450 device_chromeos
->SetTrusted();
454 for (DevicesMap::iterator iter
= devices_
.begin();
455 iter
!= devices_
.end(); ++iter
) {
456 if (iter
->second
->IsPaired() && iter
->second
->IsConnected())
460 UMA_HISTOGRAM_COUNTS_100("Bluetooth.ConnectedDeviceCount", count
);
464 void BluetoothAdapterChromeOS::InputPropertyChanged(
465 const dbus::ObjectPath
& object_path
,
466 const std::string
& property_name
) {
467 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
468 if (!device_chromeos
)
471 BluetoothInputClient::Properties
* properties
=
472 DBusThreadManager::Get()->GetBluetoothInputClient()->
473 GetProperties(object_path
);
475 // Properties structure can be removed, which triggers a change in the
476 // BluetoothDevice::IsConnectable() property, as does a change in the
477 // actual reconnect_mode property.
478 if (!properties
|| property_name
== properties
->reconnect_mode
.name()) {
479 NotifyDeviceChanged(device_chromeos
);
483 void BluetoothAdapterChromeOS::Released() {
484 VLOG(1) << "Release";
487 DCHECK(agent_
.get());
489 // Called after we unregister the pairing agent, e.g. when changing I/O
490 // capabilities. Nothing much to be done right now.
493 void BluetoothAdapterChromeOS::RequestPinCode(
494 const dbus::ObjectPath
& device_path
,
495 const PinCodeCallback
& callback
) {
497 DCHECK(agent_
.get());
498 VLOG(1) << device_path
.value() << ": RequestPinCode";
500 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
502 callback
.Run(REJECTED
, "");
506 pairing
->RequestPinCode(callback
);
509 void BluetoothAdapterChromeOS::DisplayPinCode(
510 const dbus::ObjectPath
& device_path
,
511 const std::string
& pincode
) {
513 DCHECK(agent_
.get());
514 VLOG(1) << device_path
.value() << ": DisplayPinCode: " << pincode
;
516 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
520 pairing
->DisplayPinCode(pincode
);
523 void BluetoothAdapterChromeOS::RequestPasskey(
524 const dbus::ObjectPath
& device_path
,
525 const PasskeyCallback
& callback
) {
527 DCHECK(agent_
.get());
528 VLOG(1) << device_path
.value() << ": RequestPasskey";
530 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
532 callback
.Run(REJECTED
, 0);
536 pairing
->RequestPasskey(callback
);
539 void BluetoothAdapterChromeOS::DisplayPasskey(
540 const dbus::ObjectPath
& device_path
,
544 DCHECK(agent_
.get());
545 VLOG(1) << device_path
.value() << ": DisplayPasskey: " << passkey
546 << " (" << entered
<< " entered)";
548 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
553 pairing
->DisplayPasskey(passkey
);
555 pairing
->KeysEntered(entered
);
558 void BluetoothAdapterChromeOS::RequestConfirmation(
559 const dbus::ObjectPath
& device_path
,
561 const ConfirmationCallback
& callback
) {
563 DCHECK(agent_
.get());
564 VLOG(1) << device_path
.value() << ": RequestConfirmation: " << passkey
;
566 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
568 callback
.Run(REJECTED
);
572 pairing
->RequestConfirmation(passkey
, callback
);
575 void BluetoothAdapterChromeOS::RequestAuthorization(
576 const dbus::ObjectPath
& device_path
,
577 const ConfirmationCallback
& callback
) {
579 DCHECK(agent_
.get());
580 VLOG(1) << device_path
.value() << ": RequestAuthorization";
582 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
584 callback
.Run(REJECTED
);
588 pairing
->RequestAuthorization(callback
);
591 void BluetoothAdapterChromeOS::AuthorizeService(
592 const dbus::ObjectPath
& device_path
,
593 const std::string
& uuid
,
594 const ConfirmationCallback
& callback
) {
596 DCHECK(agent_
.get());
597 VLOG(1) << device_path
.value() << ": AuthorizeService: " << uuid
;
599 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(device_path
);
600 if (!device_chromeos
) {
601 callback
.Run(CANCELLED
);
605 // We always set paired devices to Trusted, so the only reason that this
606 // method call would ever be called is in the case of a race condition where
607 // our "Set('Trusted', true)" method call is still pending in the Bluetooth
608 // daemon because it's busy handling the incoming connection.
609 if (device_chromeos
->IsPaired()) {
610 callback
.Run(SUCCESS
);
614 // TODO(keybuk): reject service authorizations when not paired, determine
615 // whether this is acceptable long-term.
616 LOG(WARNING
) << "Rejecting service connection from unpaired device "
617 << device_chromeos
->GetAddress() << " for UUID " << uuid
;
618 callback
.Run(REJECTED
);
621 void BluetoothAdapterChromeOS::Cancel() {
623 DCHECK(agent_
.get());
627 void BluetoothAdapterChromeOS::OnRegisterAgent() {
628 VLOG(1) << "Pairing agent registered, requesting to be made default";
630 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
632 dbus::ObjectPath(kAgentPath
),
633 base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgent
,
634 weak_ptr_factory_
.GetWeakPtr()),
635 base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgentError
,
636 weak_ptr_factory_
.GetWeakPtr()));
639 void BluetoothAdapterChromeOS::OnRegisterAgentError(
640 const std::string
& error_name
,
641 const std::string
& error_message
) {
642 // Our agent being already registered isn't an error.
643 if (error_name
== bluetooth_agent_manager::kErrorAlreadyExists
)
646 LOG(WARNING
) << ": Failed to register pairing agent: "
647 << error_name
<< ": " << error_message
;
650 void BluetoothAdapterChromeOS::OnRequestDefaultAgent() {
651 VLOG(1) << "Pairing agent now default";
654 void BluetoothAdapterChromeOS::OnRequestDefaultAgentError(
655 const std::string
& error_name
,
656 const std::string
& error_message
) {
657 LOG(WARNING
) << ": Failed to make pairing agent default: "
658 << error_name
<< ": " << error_message
;
661 void BluetoothAdapterChromeOS::OnRegisterAudioSink(
662 const device::BluetoothAdapter::AcquiredCallback
& callback
,
663 const device::BluetoothAudioSink::ErrorCallback
& error_callback
,
664 scoped_refptr
<BluetoothAudioSink
> audio_sink
) {
666 VLOG(1) << "Failed to register audio sink, adapter not present";
667 error_callback
.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER
);
670 DCHECK(audio_sink
.get());
671 callback
.Run(audio_sink
);
674 BluetoothDeviceChromeOS
*
675 BluetoothAdapterChromeOS::GetDeviceWithPath(
676 const dbus::ObjectPath
& object_path
) {
680 for (DevicesMap::iterator iter
= devices_
.begin(); iter
!= devices_
.end();
682 BluetoothDeviceChromeOS
* device_chromeos
=
683 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
684 if (device_chromeos
->object_path() == object_path
)
685 return device_chromeos
;
691 BluetoothPairingChromeOS
* BluetoothAdapterChromeOS::GetPairing(
692 const dbus::ObjectPath
& object_path
) {
694 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
695 if (!device_chromeos
) {
696 LOG(WARNING
) << "Pairing Agent request for unknown device: "
697 << object_path
.value();
701 BluetoothPairingChromeOS
* pairing
= device_chromeos
->GetPairing();
705 // The device doesn't have its own pairing context, so this is an incoming
706 // pairing request that should use our best default delegate (if we have one).
707 BluetoothDevice::PairingDelegate
* pairing_delegate
= DefaultPairingDelegate();
708 if (!pairing_delegate
)
711 return device_chromeos
->BeginPairing(pairing_delegate
);
714 void BluetoothAdapterChromeOS::SetAdapter(const dbus::ObjectPath
& object_path
) {
715 DCHECK(!IsPresent());
716 DCHECK(!dbus_is_shutdown_
);
717 object_path_
= object_path
;
719 VLOG(1) << object_path_
.value() << ": using adapter.";
721 VLOG(1) << "Registering pairing agent";
722 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
724 dbus::ObjectPath(kAgentPath
),
725 bluetooth_agent_manager::kKeyboardDisplayCapability
,
726 base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgent
,
727 weak_ptr_factory_
.GetWeakPtr()),
728 base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgentError
,
729 weak_ptr_factory_
.GetWeakPtr()));
731 SetDefaultAdapterName();
733 BluetoothAdapterClient::Properties
* properties
=
734 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
735 GetProperties(object_path_
);
737 PresentChanged(true);
739 if (properties
->powered
.value())
740 PoweredChanged(true);
741 if (properties
->discoverable
.value())
742 DiscoverableChanged(true);
743 if (properties
->discovering
.value())
744 DiscoveringChanged(true);
746 std::vector
<dbus::ObjectPath
> device_paths
=
747 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
748 GetDevicesForAdapter(object_path_
);
750 for (std::vector
<dbus::ObjectPath
>::iterator iter
= device_paths
.begin();
751 iter
!= device_paths
.end(); ++iter
) {
756 void BluetoothAdapterChromeOS::SetDefaultAdapterName() {
760 switch (chromeos::GetDeviceType()) {
761 case DeviceType::kChromebase
:
762 alias
= "Chromebase";
764 case DeviceType::kChromebit
:
767 case DeviceType::kChromebook
:
768 alias
= "Chromebook";
770 case DeviceType::kChromebox
:
773 case DeviceType::kUnknown
:
774 alias
= "Chromebook";
778 SetName(alias
, base::Bind(&base::DoNothing
), base::Bind(&base::DoNothing
));
781 void BluetoothAdapterChromeOS::RemoveAdapter() {
783 VLOG(1) << object_path_
.value() << ": adapter removed.";
785 BluetoothAdapterClient::Properties
* properties
=
786 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
787 GetProperties(object_path_
);
789 object_path_
= dbus::ObjectPath("");
791 if (properties
->powered
.value())
792 PoweredChanged(false);
793 if (properties
->discoverable
.value())
794 DiscoverableChanged(false);
795 if (properties
->discovering
.value())
796 DiscoveringChanged(false);
798 // Copy the devices list here and clear the original so that when we
799 // send DeviceRemoved(), GetDevices() returns no devices.
800 DevicesMap devices
= devices_
;
803 for (DevicesMap::iterator iter
= devices
.begin();
804 iter
!= devices
.end(); ++iter
) {
805 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
806 DeviceRemoved(this, iter
->second
));
810 PresentChanged(false);
813 void BluetoothAdapterChromeOS::PoweredChanged(bool powered
) {
814 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
815 AdapterPoweredChanged(this, powered
));
818 void BluetoothAdapterChromeOS::DiscoverableChanged(bool discoverable
) {
819 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
820 AdapterDiscoverableChanged(this, discoverable
));
823 void BluetoothAdapterChromeOS::DiscoveringChanged(
825 // If the adapter stopped discovery due to a reason other than a request by
826 // us, reset the count to 0.
827 VLOG(1) << "Discovering changed: " << discovering
;
828 if (!discovering
&& !discovery_request_pending_
&&
829 num_discovery_sessions_
> 0) {
830 VLOG(1) << "Marking sessions as inactive.";
831 num_discovery_sessions_
= 0;
832 MarkDiscoverySessionsAsInactive();
834 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
835 AdapterDiscoveringChanged(this, discovering
));
838 void BluetoothAdapterChromeOS::PresentChanged(bool present
) {
839 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
840 AdapterPresentChanged(this, present
));
843 void BluetoothAdapterChromeOS::NotifyDeviceChanged(
844 BluetoothDeviceChromeOS
* device
) {
846 DCHECK(device
->adapter_
== this);
848 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
849 DeviceChanged(this, device
));
852 void BluetoothAdapterChromeOS::NotifyGattServiceAdded(
853 BluetoothRemoteGattServiceChromeOS
* service
) {
854 DCHECK_EQ(service
->GetAdapter(), this);
856 static_cast<BluetoothDeviceChromeOS
*>(service
->GetDevice())->adapter_
,
859 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
861 GattServiceAdded(this, service
->GetDevice(), service
));
864 void BluetoothAdapterChromeOS::NotifyGattServiceRemoved(
865 BluetoothRemoteGattServiceChromeOS
* service
) {
866 DCHECK_EQ(service
->GetAdapter(), this);
868 static_cast<BluetoothDeviceChromeOS
*>(service
->GetDevice())->adapter_
,
871 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
873 GattServiceRemoved(this, service
->GetDevice(), service
));
876 void BluetoothAdapterChromeOS::NotifyGattServiceChanged(
877 BluetoothRemoteGattServiceChromeOS
* service
) {
878 DCHECK_EQ(service
->GetAdapter(), this);
880 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
882 GattServiceChanged(this, service
));
885 void BluetoothAdapterChromeOS::NotifyGattDiscoveryComplete(
886 BluetoothRemoteGattServiceChromeOS
* service
) {
887 DCHECK_EQ(service
->GetAdapter(), this);
889 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
891 GattDiscoveryCompleteForService(this, service
));
894 void BluetoothAdapterChromeOS::NotifyGattCharacteristicAdded(
895 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
) {
896 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
897 characteristic
->GetService())->GetAdapter(),
900 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
902 GattCharacteristicAdded(this, characteristic
));
905 void BluetoothAdapterChromeOS::NotifyGattCharacteristicRemoved(
906 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
) {
907 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
908 characteristic
->GetService())->GetAdapter(),
911 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
913 GattCharacteristicRemoved(this, characteristic
));
916 void BluetoothAdapterChromeOS::NotifyGattDescriptorAdded(
917 BluetoothRemoteGattDescriptorChromeOS
* descriptor
) {
918 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
919 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
922 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
924 GattDescriptorAdded(this, descriptor
));
927 void BluetoothAdapterChromeOS::NotifyGattDescriptorRemoved(
928 BluetoothRemoteGattDescriptorChromeOS
* descriptor
) {
929 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
930 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
933 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
935 GattDescriptorRemoved(this, descriptor
));
938 void BluetoothAdapterChromeOS::NotifyGattCharacteristicValueChanged(
939 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
,
940 const std::vector
<uint8
>& value
) {
941 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
942 characteristic
->GetService())->GetAdapter(),
946 BluetoothAdapter::Observer
,
948 GattCharacteristicValueChanged(this, characteristic
, value
));
951 void BluetoothAdapterChromeOS::NotifyGattDescriptorValueChanged(
952 BluetoothRemoteGattDescriptorChromeOS
* descriptor
,
953 const std::vector
<uint8
>& value
) {
954 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
955 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
958 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
960 GattDescriptorValueChanged(this, descriptor
, value
));
963 void BluetoothAdapterChromeOS::UseProfile(
964 const BluetoothUUID
& uuid
,
965 const dbus::ObjectPath
& device_path
,
966 const BluetoothProfileManagerClient::Options
& options
,
967 BluetoothProfileServiceProvider::Delegate
* delegate
,
968 const ProfileRegisteredCallback
& success_callback
,
969 const ErrorCompletionCallback
& error_callback
) {
973 VLOG(2) << "Adapter not present, erroring out";
974 error_callback
.Run("Adapter not present");
978 if (profiles_
.find(uuid
) != profiles_
.end()) {
979 // TODO(jamuraa) check that the options are the same and error when they are
981 SetProfileDelegate(uuid
, device_path
, delegate
, success_callback
,
986 if (profile_queues_
.find(uuid
) == profile_queues_
.end()) {
987 BluetoothAdapterProfileChromeOS::Register(
989 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfile
, this, uuid
),
990 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfileError
, this,
993 profile_queues_
[uuid
] = new std::vector
<RegisterProfileCompletionPair
>();
996 profile_queues_
[uuid
]->push_back(std::make_pair(
997 base::Bind(&BluetoothAdapterChromeOS::SetProfileDelegate
, this, uuid
,
998 device_path
, delegate
, success_callback
, error_callback
),
1002 void BluetoothAdapterChromeOS::ReleaseProfile(
1003 const dbus::ObjectPath
& device_path
,
1004 BluetoothAdapterProfileChromeOS
* profile
) {
1005 VLOG(2) << "Releasing Profile: " << profile
->uuid().canonical_value()
1006 << " from " << device_path
.value();
1007 profile
->RemoveDelegate(
1008 device_path
, base::Bind(&BluetoothAdapterChromeOS::RemoveProfile
,
1009 weak_ptr_factory_
.GetWeakPtr(), profile
->uuid()));
1012 void BluetoothAdapterChromeOS::RemoveProfile(const BluetoothUUID
& uuid
) {
1013 VLOG(2) << "Remove Profile: " << uuid
.canonical_value();
1015 if (profiles_
.find(uuid
) != profiles_
.end()) {
1016 delete profiles_
[uuid
];
1017 profiles_
.erase(uuid
);
1021 void BluetoothAdapterChromeOS::OnRegisterProfile(
1022 const BluetoothUUID
& uuid
,
1023 scoped_ptr
<BluetoothAdapterProfileChromeOS
> profile
) {
1024 profiles_
[uuid
] = profile
.release();
1026 if (profile_queues_
.find(uuid
) == profile_queues_
.end())
1029 for (auto& it
: *profile_queues_
[uuid
])
1031 delete profile_queues_
[uuid
];
1032 profile_queues_
.erase(uuid
);
1035 void BluetoothAdapterChromeOS::SetProfileDelegate(
1036 const BluetoothUUID
& uuid
,
1037 const dbus::ObjectPath
& device_path
,
1038 BluetoothProfileServiceProvider::Delegate
* delegate
,
1039 const ProfileRegisteredCallback
& success_callback
,
1040 const ErrorCompletionCallback
& error_callback
) {
1041 if (profiles_
.find(uuid
) == profiles_
.end()) {
1042 error_callback
.Run("Cannot find profile!");
1046 if (profiles_
[uuid
]->SetDelegate(device_path
, delegate
)) {
1047 success_callback
.Run(profiles_
[uuid
]);
1051 error_callback
.Run(bluetooth_agent_manager::kErrorAlreadyExists
);
1054 void BluetoothAdapterChromeOS::OnRegisterProfileError(
1055 const BluetoothUUID
& uuid
,
1056 const std::string
& error_name
,
1057 const std::string
& error_message
) {
1058 VLOG(2) << object_path_
.value() << ": Failed to register profile: "
1059 << error_name
<< ": " << error_message
;
1060 if (profile_queues_
.find(uuid
) == profile_queues_
.end())
1063 for (auto& it
: *profile_queues_
[uuid
])
1064 it
.second
.Run(error_message
);
1066 delete profile_queues_
[uuid
];
1067 profile_queues_
.erase(uuid
);
1070 void BluetoothAdapterChromeOS::OnSetDiscoverable(
1071 const base::Closure
& callback
,
1072 const ErrorCallback
& error_callback
,
1075 error_callback
.Run();
1079 // Set the discoverable_timeout property to zero so the adapter remains
1080 // discoverable forever.
1081 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1082 GetProperties(object_path_
)->discoverable_timeout
.Set(
1084 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
1085 weak_ptr_factory_
.GetWeakPtr(),
1090 void BluetoothAdapterChromeOS::OnPropertyChangeCompleted(
1091 const base::Closure
& callback
,
1092 const ErrorCallback
& error_callback
,
1094 if (IsPresent() && success
) {
1097 error_callback
.Run();
1101 void BluetoothAdapterChromeOS::AddDiscoverySession(
1102 BluetoothDiscoveryFilter
* discovery_filter
,
1103 const base::Closure
& callback
,
1104 const ErrorCallback
& error_callback
) {
1106 error_callback
.Run();
1109 VLOG(1) << __func__
;
1110 if (discovery_request_pending_
) {
1111 // The pending request is either to stop a previous session or to start a
1112 // new one. Either way, queue this one.
1113 DCHECK(num_discovery_sessions_
== 1 || num_discovery_sessions_
== 0);
1114 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1115 << "request to start a new discovery session.";
1116 discovery_request_queue_
.push(
1117 std::make_tuple(discovery_filter
, callback
, error_callback
));
1121 // The adapter is already discovering.
1122 if (num_discovery_sessions_
> 0) {
1123 DCHECK(IsDiscovering());
1124 DCHECK(!discovery_request_pending_
);
1125 num_discovery_sessions_
++;
1126 SetDiscoveryFilter(BluetoothDiscoveryFilter::Merge(
1127 GetMergedDiscoveryFilter().get(), discovery_filter
),
1128 callback
, error_callback
);
1132 // There are no active discovery sessions.
1133 DCHECK_EQ(num_discovery_sessions_
, 0);
1135 if (discovery_filter
) {
1136 discovery_request_pending_
= true;
1138 scoped_ptr
<BluetoothDiscoveryFilter
> df(new BluetoothDiscoveryFilter(
1139 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL
));
1140 df
->CopyFrom(*discovery_filter
);
1143 base::Bind(&BluetoothAdapterChromeOS::OnPreSetDiscoveryFilter
,
1144 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1145 base::Bind(&BluetoothAdapterChromeOS::OnPreSetDiscoveryFilterError
,
1146 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1149 current_filter_
.reset();
1152 // This is the first request to start device discovery.
1153 discovery_request_pending_
= true;
1154 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1156 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery
,
1157 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1158 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError
,
1159 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1162 void BluetoothAdapterChromeOS::RemoveDiscoverySession(
1163 BluetoothDiscoveryFilter
* discovery_filter
,
1164 const base::Closure
& callback
,
1165 const ErrorCallback
& error_callback
) {
1167 error_callback
.Run();
1171 VLOG(1) << __func__
;
1172 // There are active sessions other than the one currently being removed.
1173 if (num_discovery_sessions_
> 1) {
1174 DCHECK(IsDiscovering());
1175 DCHECK(!discovery_request_pending_
);
1176 num_discovery_sessions_
--;
1178 SetDiscoveryFilter(GetMergedDiscoveryFilterMasked(discovery_filter
),
1179 callback
, error_callback
);
1183 // If there is a pending request to BlueZ, then queue this request.
1184 if (discovery_request_pending_
) {
1185 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1186 << "request to stop discovery session.";
1187 error_callback
.Run();
1191 // There are no active sessions. Return error.
1192 if (num_discovery_sessions_
== 0) {
1193 // TODO(armansito): This should never happen once we have the
1194 // DiscoverySession API. Replace this case with an assert once it's
1195 // the deprecated methods have been removed. (See crbug.com/3445008).
1196 VLOG(1) << "No active discovery sessions. Returning error.";
1197 error_callback
.Run();
1201 // There is exactly one active discovery session. Request BlueZ to stop
1203 DCHECK_EQ(num_discovery_sessions_
, 1);
1204 discovery_request_pending_
= true;
1205 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1208 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery
,
1209 weak_ptr_factory_
.GetWeakPtr(),
1211 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError
,
1212 weak_ptr_factory_
.GetWeakPtr(),
1216 void BluetoothAdapterChromeOS::SetDiscoveryFilter(
1217 scoped_ptr
<BluetoothDiscoveryFilter
> discovery_filter
,
1218 const base::Closure
& callback
,
1219 const ErrorCallback
& error_callback
) {
1221 error_callback
.Run();
1225 // If old and new filter are equal (null) then don't make request, just call
1227 if (!current_filter_
&& !discovery_filter
.get()) {
1232 // If old and new filter are not null and equal then don't make request, just
1233 // call succes callback
1234 if (current_filter_
&& discovery_filter
&&
1235 current_filter_
->Equals(*discovery_filter
)) {
1240 current_filter_
.reset(discovery_filter
.release());
1242 chromeos::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter
;
1244 if (current_filter_
.get()) {
1248 std::set
<device::BluetoothUUID
> uuids
;
1250 if (current_filter_
->GetPathloss(&pathloss
))
1251 dbus_discovery_filter
.pathloss
.reset(new uint16_t(pathloss
));
1253 if (current_filter_
->GetRSSI(&rssi
))
1254 dbus_discovery_filter
.rssi
.reset(new int16_t(rssi
));
1256 transport
= current_filter_
->GetTransport();
1257 if (transport
== BluetoothDiscoveryFilter::Transport::TRANSPORT_LE
) {
1258 dbus_discovery_filter
.transport
.reset(new std::string("le"));
1259 } else if (transport
==
1260 BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC
) {
1261 dbus_discovery_filter
.transport
.reset(new std::string("bredr"));
1262 } else if (transport
==
1263 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL
) {
1264 dbus_discovery_filter
.transport
.reset(new std::string("auto"));
1267 current_filter_
->GetUUIDs(uuids
);
1269 dbus_discovery_filter
.uuids
=
1270 scoped_ptr
<std::vector
<std::string
>>(new std::vector
<std::string
>);
1272 for (const auto& it
: uuids
)
1273 dbus_discovery_filter
.uuids
.get()->push_back(it
.value());
1277 DBusThreadManager::Get()->GetBluetoothAdapterClient()->SetDiscoveryFilter(
1278 object_path_
, dbus_discovery_filter
,
1279 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilter
,
1280 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1281 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilterError
,
1282 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1285 void BluetoothAdapterChromeOS::OnStartDiscovery(
1286 const base::Closure
& callback
,
1287 const ErrorCallback
& error_callback
) {
1288 // Report success on the original request and increment the count.
1289 VLOG(1) << __func__
;
1290 DCHECK(discovery_request_pending_
);
1291 DCHECK_EQ(num_discovery_sessions_
, 0);
1292 discovery_request_pending_
= false;
1293 num_discovery_sessions_
++;
1297 error_callback
.Run();
1300 // Try to add a new discovery session for each queued request.
1301 ProcessQueuedDiscoveryRequests();
1304 void BluetoothAdapterChromeOS::OnStartDiscoveryError(
1305 const base::Closure
& callback
,
1306 const ErrorCallback
& error_callback
,
1307 const std::string
& error_name
,
1308 const std::string
& error_message
) {
1309 LOG(WARNING
) << object_path_
.value() << ": Failed to start discovery: "
1310 << error_name
<< ": " << error_message
;
1312 // Failed to start discovery. This can only happen if the count is at 0.
1313 DCHECK_EQ(num_discovery_sessions_
, 0);
1314 DCHECK(discovery_request_pending_
);
1315 discovery_request_pending_
= false;
1317 // Discovery request may fail if discovery was previously initiated by Chrome,
1318 // but the session were invalidated due to the discovery state unexpectedly
1319 // changing to false and then back to true. In this case, report success.
1320 if (IsPresent() && error_name
== bluetooth_device::kErrorInProgress
&&
1322 VLOG(1) << "Discovery previously initiated. Reporting success.";
1323 num_discovery_sessions_
++;
1326 error_callback
.Run();
1329 // Try to add a new discovery session for each queued request.
1330 ProcessQueuedDiscoveryRequests();
1333 void BluetoothAdapterChromeOS::OnStopDiscovery(const base::Closure
& callback
) {
1334 // Report success on the original request and decrement the count.
1335 VLOG(1) << __func__
;
1336 DCHECK(discovery_request_pending_
);
1337 DCHECK_EQ(num_discovery_sessions_
, 1);
1338 discovery_request_pending_
= false;
1339 num_discovery_sessions_
--;
1342 current_filter_
.reset();
1344 // Try to add a new discovery session for each queued request.
1345 ProcessQueuedDiscoveryRequests();
1348 void BluetoothAdapterChromeOS::OnStopDiscoveryError(
1349 const ErrorCallback
& error_callback
,
1350 const std::string
& error_name
,
1351 const std::string
& error_message
) {
1352 LOG(WARNING
) << object_path_
.value() << ": Failed to stop discovery: "
1353 << error_name
<< ": " << error_message
;
1355 // Failed to stop discovery. This can only happen if the count is at 1.
1356 DCHECK(discovery_request_pending_
);
1357 DCHECK_EQ(num_discovery_sessions_
, 1);
1358 discovery_request_pending_
= false;
1359 error_callback
.Run();
1361 // Try to add a new discovery session for each queued request.
1362 ProcessQueuedDiscoveryRequests();
1365 void BluetoothAdapterChromeOS::OnPreSetDiscoveryFilter(
1366 const base::Closure
& callback
,
1367 const ErrorCallback
& error_callback
) {
1368 // This is the first request to start device discovery.
1369 DCHECK(discovery_request_pending_
);
1370 DCHECK_EQ(num_discovery_sessions_
, 0);
1372 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1374 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery
,
1375 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1376 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError
,
1377 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1380 void BluetoothAdapterChromeOS::OnPreSetDiscoveryFilterError(
1381 const base::Closure
& callback
,
1382 const ErrorCallback
& error_callback
) {
1383 LOG(WARNING
) << object_path_
.value()
1384 << ": Failed to pre set discovery filter.";
1386 // Failed to start discovery. This can only happen if the count is at 0.
1387 DCHECK_EQ(num_discovery_sessions_
, 0);
1388 DCHECK(discovery_request_pending_
);
1389 discovery_request_pending_
= false;
1391 error_callback
.Run();
1393 // Try to add a new discovery session for each queued request.
1394 ProcessQueuedDiscoveryRequests();
1397 void BluetoothAdapterChromeOS::OnSetDiscoveryFilter(
1398 const base::Closure
& callback
,
1399 const ErrorCallback
& error_callback
) {
1400 // Report success on the original request and increment the count.
1401 VLOG(1) << __func__
;
1405 error_callback
.Run();
1409 void BluetoothAdapterChromeOS::OnSetDiscoveryFilterError(
1410 const base::Closure
& callback
,
1411 const ErrorCallback
& error_callback
,
1412 const std::string
& error_name
,
1413 const std::string
& error_message
) {
1414 LOG(WARNING
) << object_path_
.value()
1415 << ": Failed to set discovery filter: " << error_name
<< ": "
1418 error_callback
.Run();
1420 // Try to add a new discovery session for each queued request.
1421 ProcessQueuedDiscoveryRequests();
1424 void BluetoothAdapterChromeOS::ProcessQueuedDiscoveryRequests() {
1425 while (!discovery_request_queue_
.empty()) {
1426 VLOG(1) << "Process queued discovery request.";
1427 DiscoveryParamTuple params
= discovery_request_queue_
.front();
1428 discovery_request_queue_
.pop();
1429 AddDiscoverySession(std::get
<0>(params
), std::get
<1>(params
),
1430 std::get
<2>(params
));
1432 // If the queued request resulted in a pending call, then let it
1433 // asynchonously process the remaining queued requests once the pending
1435 if (discovery_request_pending_
)
1440 } // namespace chromeos