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/sys_info.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "chromeos/dbus/bluetooth_adapter_client.h"
18 #include "chromeos/dbus/bluetooth_agent_manager_client.h"
19 #include "chromeos/dbus/bluetooth_agent_service_provider.h"
20 #include "chromeos/dbus/bluetooth_device_client.h"
21 #include "chromeos/dbus/bluetooth_input_client.h"
22 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "device/bluetooth/bluetooth_adapter_profile_chromeos.h"
24 #include "device/bluetooth/bluetooth_audio_sink_chromeos.h"
25 #include "device/bluetooth/bluetooth_device.h"
26 #include "device/bluetooth/bluetooth_device_chromeos.h"
27 #include "device/bluetooth/bluetooth_pairing_chromeos.h"
28 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
29 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
30 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
31 #include "device/bluetooth/bluetooth_socket_chromeos.h"
32 #include "device/bluetooth/bluetooth_socket_thread.h"
33 #include "device/bluetooth/bluetooth_uuid.h"
34 #include "third_party/cros_system_api/dbus/service_constants.h"
36 using device::BluetoothAdapter
;
37 using device::BluetoothAudioSink
;
38 using device::BluetoothDevice
;
39 using device::BluetoothDiscoveryFilter
;
40 using device::BluetoothSocket
;
41 using device::BluetoothUUID
;
45 // The agent path is relatively meaningless since BlueZ only permits one to
46 // exist per D-Bus connection, it just has to be unique within Chromium.
47 const char kAgentPath
[] = "/org/chromium/bluetooth_agent";
49 void OnUnregisterAgentError(const std::string
& error_name
,
50 const std::string
& error_message
) {
51 // It's okay if the agent didn't exist, it means we never saw an adapter.
52 if (error_name
== bluetooth_agent_manager::kErrorDoesNotExist
)
55 LOG(WARNING
) << "Failed to unregister pairing agent: "
56 << error_name
<< ": " << error_message
;
64 base::WeakPtr
<BluetoothAdapter
> BluetoothAdapter::CreateAdapter(
65 const InitCallback
& init_callback
) {
66 return chromeos::BluetoothAdapterChromeOS::CreateAdapter();
74 base::WeakPtr
<BluetoothAdapter
> BluetoothAdapterChromeOS::CreateAdapter() {
75 BluetoothAdapterChromeOS
* adapter
= new BluetoothAdapterChromeOS();
76 return adapter
->weak_ptr_factory_
.GetWeakPtr();
79 void BluetoothAdapterChromeOS::Shutdown() {
80 if (dbus_is_shutdown_
)
82 DCHECK(DBusThreadManager::IsInitialized())
83 << "Call BluetoothAdapterFactory::Shutdown() before "
84 "DBusThreadManager::Shutdown().";
87 RemoveAdapter(); // Also deletes devices_.
88 DCHECK(devices_
.empty());
89 // profiles_ should be empty because all BluetoothSockets have been signaled
90 // that this adapter is disappearing.
91 DCHECK(profiles_
.empty());
93 for (auto& it
: profile_queues_
)
95 profile_queues_
.clear();
97 DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(this);
98 DBusThreadManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(this);
99 DBusThreadManager::Get()->GetBluetoothInputClient()->RemoveObserver(this);
101 VLOG(1) << "Unregistering pairing agent";
102 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->UnregisterAgent(
103 dbus::ObjectPath(kAgentPath
), base::Bind(&base::DoNothing
),
104 base::Bind(&OnUnregisterAgentError
));
107 dbus_is_shutdown_
= true;
110 BluetoothAdapterChromeOS::BluetoothAdapterChromeOS()
111 : dbus_is_shutdown_(false),
112 num_discovery_sessions_(0),
113 discovery_request_pending_(false),
114 weak_ptr_factory_(this) {
115 ui_task_runner_
= base::ThreadTaskRunnerHandle::Get();
116 socket_thread_
= device::BluetoothSocketThread::Get();
118 DBusThreadManager::Get()->GetBluetoothAdapterClient()->AddObserver(this);
119 DBusThreadManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
120 DBusThreadManager::Get()->GetBluetoothInputClient()->AddObserver(this);
122 // Register the pairing agent.
123 dbus::Bus
* system_bus
= DBusThreadManager::Get()->GetSystemBus();
124 agent_
.reset(BluetoothAgentServiceProvider::Create(
125 system_bus
, dbus::ObjectPath(kAgentPath
), this));
126 DCHECK(agent_
.get());
128 std::vector
<dbus::ObjectPath
> object_paths
=
129 DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetAdapters();
131 if (!object_paths
.empty()) {
132 VLOG(1) << object_paths
.size() << " Bluetooth adapter(s) available.";
133 SetAdapter(object_paths
[0]);
137 BluetoothAdapterChromeOS::~BluetoothAdapterChromeOS() {
141 std::string
BluetoothAdapterChromeOS::GetAddress() const {
143 return std::string();
145 BluetoothAdapterClient::Properties
* properties
=
146 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
147 GetProperties(object_path_
);
150 return BluetoothDevice::CanonicalizeAddress(properties
->address
.value());
153 std::string
BluetoothAdapterChromeOS::GetName() const {
155 return std::string();
157 BluetoothAdapterClient::Properties
* properties
=
158 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
159 GetProperties(object_path_
);
162 return properties
->alias
.value();
165 void BluetoothAdapterChromeOS::SetName(const std::string
& name
,
166 const base::Closure
& callback
,
167 const ErrorCallback
& error_callback
) {
169 error_callback
.Run();
173 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
174 GetProperties(object_path_
)->alias
.Set(
176 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
177 weak_ptr_factory_
.GetWeakPtr(),
182 bool BluetoothAdapterChromeOS::IsInitialized() const {
186 bool BluetoothAdapterChromeOS::IsPresent() const {
187 return !dbus_is_shutdown_
&& !object_path_
.value().empty();
190 bool BluetoothAdapterChromeOS::IsPowered() const {
194 BluetoothAdapterClient::Properties
* properties
=
195 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
196 GetProperties(object_path_
);
198 return properties
->powered
.value();
201 void BluetoothAdapterChromeOS::SetPowered(
203 const base::Closure
& callback
,
204 const ErrorCallback
& error_callback
) {
206 error_callback
.Run();
210 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
211 GetProperties(object_path_
)->powered
.Set(
213 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
214 weak_ptr_factory_
.GetWeakPtr(),
219 bool BluetoothAdapterChromeOS::IsDiscoverable() const {
223 BluetoothAdapterClient::Properties
* properties
=
224 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
225 GetProperties(object_path_
);
227 return properties
->discoverable
.value();
230 void BluetoothAdapterChromeOS::SetDiscoverable(
232 const base::Closure
& callback
,
233 const ErrorCallback
& error_callback
) {
235 error_callback
.Run();
239 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
240 GetProperties(object_path_
)->discoverable
.Set(
242 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoverable
,
243 weak_ptr_factory_
.GetWeakPtr(),
248 bool BluetoothAdapterChromeOS::IsDiscovering() const {
252 BluetoothAdapterClient::Properties
* properties
=
253 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
254 GetProperties(object_path_
);
256 return properties
->discovering
.value();
259 void BluetoothAdapterChromeOS::CreateRfcommService(
260 const BluetoothUUID
& uuid
,
261 const ServiceOptions
& options
,
262 const CreateServiceCallback
& callback
,
263 const CreateServiceErrorCallback
& error_callback
) {
264 DCHECK(!dbus_is_shutdown_
);
265 VLOG(1) << object_path_
.value() << ": Creating RFCOMM service: "
266 << uuid
.canonical_value();
267 scoped_refptr
<BluetoothSocketChromeOS
> socket
=
268 BluetoothSocketChromeOS::CreateBluetoothSocket(
269 ui_task_runner_
, socket_thread_
);
271 BluetoothSocketChromeOS::kRfcomm
,
274 base::Bind(callback
, socket
),
278 void BluetoothAdapterChromeOS::CreateL2capService(
279 const BluetoothUUID
& uuid
,
280 const ServiceOptions
& options
,
281 const CreateServiceCallback
& callback
,
282 const CreateServiceErrorCallback
& error_callback
) {
283 DCHECK(!dbus_is_shutdown_
);
284 VLOG(1) << object_path_
.value() << ": Creating L2CAP service: "
285 << uuid
.canonical_value();
286 scoped_refptr
<BluetoothSocketChromeOS
> socket
=
287 BluetoothSocketChromeOS::CreateBluetoothSocket(
288 ui_task_runner_
, socket_thread_
);
290 BluetoothSocketChromeOS::kL2cap
,
293 base::Bind(callback
, socket
),
297 void BluetoothAdapterChromeOS::RegisterAudioSink(
298 const BluetoothAudioSink::Options
& options
,
299 const device::BluetoothAdapter::AcquiredCallback
& callback
,
300 const BluetoothAudioSink::ErrorCallback
& error_callback
) {
301 VLOG(1) << "Registering audio sink";
302 if (!this->IsPresent()) {
303 error_callback
.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER
);
306 scoped_refptr
<BluetoothAudioSinkChromeOS
> audio_sink(
307 new BluetoothAudioSinkChromeOS(this));
308 audio_sink
->Register(
309 options
, base::Bind(&BluetoothAdapterChromeOS::OnRegisterAudioSink
,
310 weak_ptr_factory_
.GetWeakPtr(), callback
,
311 error_callback
, audio_sink
),
315 void BluetoothAdapterChromeOS::RemovePairingDelegateInternal(
316 BluetoothDevice::PairingDelegate
* pairing_delegate
) {
317 // Before removing a pairing delegate make sure that there aren't any devices
318 // currently using it; if there are, clear the pairing context which will
319 // make any responses no-ops.
320 for (DevicesMap::iterator iter
= devices_
.begin();
321 iter
!= devices_
.end(); ++iter
) {
322 BluetoothDeviceChromeOS
* device_chromeos
=
323 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
325 BluetoothPairingChromeOS
* pairing
= device_chromeos
->GetPairing();
326 if (pairing
&& pairing
->GetPairingDelegate() == pairing_delegate
)
327 device_chromeos
->EndPairing();
331 void BluetoothAdapterChromeOS::AdapterAdded(
332 const dbus::ObjectPath
& object_path
) {
333 // Set the adapter to the newly added adapter only if no adapter is present.
335 SetAdapter(object_path
);
338 void BluetoothAdapterChromeOS::AdapterRemoved(
339 const dbus::ObjectPath
& object_path
) {
340 if (object_path
== object_path_
)
344 void BluetoothAdapterChromeOS::AdapterPropertyChanged(
345 const dbus::ObjectPath
& object_path
,
346 const std::string
& property_name
) {
347 if (object_path
!= object_path_
)
351 BluetoothAdapterClient::Properties
* properties
=
352 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
353 GetProperties(object_path_
);
355 if (property_name
== properties
->powered
.name())
356 PoweredChanged(properties
->powered
.value());
357 else if (property_name
== properties
->discoverable
.name())
358 DiscoverableChanged(properties
->discoverable
.value());
359 else if (property_name
== properties
->discovering
.name())
360 DiscoveringChanged(properties
->discovering
.value());
363 void BluetoothAdapterChromeOS::DeviceAdded(
364 const dbus::ObjectPath
& object_path
) {
365 DCHECK(DBusThreadManager::Get());
366 BluetoothDeviceClient::Properties
* properties
=
367 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
368 GetProperties(object_path
);
369 if (!properties
|| properties
->adapter
.value() != object_path_
)
373 BluetoothDeviceChromeOS
* device_chromeos
=
374 new BluetoothDeviceChromeOS(this,
378 DCHECK(devices_
.find(device_chromeos
->GetAddress()) == devices_
.end());
380 devices_
[device_chromeos
->GetAddress()] = device_chromeos
;
382 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
383 DeviceAdded(this, device_chromeos
));
386 void BluetoothAdapterChromeOS::DeviceRemoved(
387 const dbus::ObjectPath
& object_path
) {
388 for (DevicesMap::iterator iter
= devices_
.begin();
389 iter
!= devices_
.end(); ++iter
) {
390 BluetoothDeviceChromeOS
* device_chromeos
=
391 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
392 if (device_chromeos
->object_path() == object_path
) {
393 devices_
.erase(iter
);
395 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
396 DeviceRemoved(this, device_chromeos
));
397 delete device_chromeos
;
403 void BluetoothAdapterChromeOS::DevicePropertyChanged(
404 const dbus::ObjectPath
& object_path
,
405 const std::string
& property_name
) {
406 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
407 if (!device_chromeos
)
410 BluetoothDeviceClient::Properties
* properties
=
411 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
412 GetProperties(object_path
);
414 if (property_name
== properties
->bluetooth_class
.name() ||
415 property_name
== properties
->address
.name() ||
416 property_name
== properties
->alias
.name() ||
417 property_name
== properties
->paired
.name() ||
418 property_name
== properties
->trusted
.name() ||
419 property_name
== properties
->connected
.name() ||
420 property_name
== properties
->uuids
.name() ||
421 property_name
== properties
->rssi
.name())
422 NotifyDeviceChanged(device_chromeos
);
424 // When a device becomes paired, mark it as trusted so that the user does
425 // not need to approve every incoming connection
426 if (property_name
== properties
->paired
.name() &&
427 properties
->paired
.value() && !properties
->trusted
.value())
428 device_chromeos
->SetTrusted();
430 // UMA connection counting
431 if (property_name
== properties
->connected
.name()) {
432 // PlayStation joystick tries to reconnect after disconnection from USB.
433 // If it is still not trusted, set it, so it becomes available on the
434 // list of known devices.
435 if (properties
->connected
.value() && device_chromeos
->IsTrustable() &&
436 !properties
->trusted
.value())
437 device_chromeos
->SetTrusted();
441 for (DevicesMap::iterator iter
= devices_
.begin();
442 iter
!= devices_
.end(); ++iter
) {
443 if (iter
->second
->IsPaired() && iter
->second
->IsConnected())
447 UMA_HISTOGRAM_COUNTS_100("Bluetooth.ConnectedDeviceCount", count
);
451 void BluetoothAdapterChromeOS::InputPropertyChanged(
452 const dbus::ObjectPath
& object_path
,
453 const std::string
& property_name
) {
454 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
455 if (!device_chromeos
)
458 BluetoothInputClient::Properties
* properties
=
459 DBusThreadManager::Get()->GetBluetoothInputClient()->
460 GetProperties(object_path
);
462 // Properties structure can be removed, which triggers a change in the
463 // BluetoothDevice::IsConnectable() property, as does a change in the
464 // actual reconnect_mode property.
466 property_name
== properties
->reconnect_mode
.name())
467 NotifyDeviceChanged(device_chromeos
);
470 void BluetoothAdapterChromeOS::Released() {
471 VLOG(1) << "Release";
474 DCHECK(agent_
.get());
476 // Called after we unregister the pairing agent, e.g. when changing I/O
477 // capabilities. Nothing much to be done right now.
480 void BluetoothAdapterChromeOS::RequestPinCode(
481 const dbus::ObjectPath
& device_path
,
482 const PinCodeCallback
& callback
) {
484 DCHECK(agent_
.get());
485 VLOG(1) << device_path
.value() << ": RequestPinCode";
487 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
489 callback
.Run(REJECTED
, "");
493 pairing
->RequestPinCode(callback
);
496 void BluetoothAdapterChromeOS::DisplayPinCode(
497 const dbus::ObjectPath
& device_path
,
498 const std::string
& pincode
) {
500 DCHECK(agent_
.get());
501 VLOG(1) << device_path
.value() << ": DisplayPinCode: " << pincode
;
503 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
507 pairing
->DisplayPinCode(pincode
);
510 void BluetoothAdapterChromeOS::RequestPasskey(
511 const dbus::ObjectPath
& device_path
,
512 const PasskeyCallback
& callback
) {
514 DCHECK(agent_
.get());
515 VLOG(1) << device_path
.value() << ": RequestPasskey";
517 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
519 callback
.Run(REJECTED
, 0);
523 pairing
->RequestPasskey(callback
);
526 void BluetoothAdapterChromeOS::DisplayPasskey(
527 const dbus::ObjectPath
& device_path
,
531 DCHECK(agent_
.get());
532 VLOG(1) << device_path
.value() << ": DisplayPasskey: " << passkey
533 << " (" << entered
<< " entered)";
535 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
540 pairing
->DisplayPasskey(passkey
);
542 pairing
->KeysEntered(entered
);
545 void BluetoothAdapterChromeOS::RequestConfirmation(
546 const dbus::ObjectPath
& device_path
,
548 const ConfirmationCallback
& callback
) {
550 DCHECK(agent_
.get());
551 VLOG(1) << device_path
.value() << ": RequestConfirmation: " << passkey
;
553 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
555 callback
.Run(REJECTED
);
559 pairing
->RequestConfirmation(passkey
, callback
);
562 void BluetoothAdapterChromeOS::RequestAuthorization(
563 const dbus::ObjectPath
& device_path
,
564 const ConfirmationCallback
& callback
) {
566 DCHECK(agent_
.get());
567 VLOG(1) << device_path
.value() << ": RequestAuthorization";
569 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
571 callback
.Run(REJECTED
);
575 pairing
->RequestAuthorization(callback
);
578 void BluetoothAdapterChromeOS::AuthorizeService(
579 const dbus::ObjectPath
& device_path
,
580 const std::string
& uuid
,
581 const ConfirmationCallback
& callback
) {
583 DCHECK(agent_
.get());
584 VLOG(1) << device_path
.value() << ": AuthorizeService: " << uuid
;
586 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(device_path
);
587 if (!device_chromeos
) {
588 callback
.Run(CANCELLED
);
592 // We always set paired devices to Trusted, so the only reason that this
593 // method call would ever be called is in the case of a race condition where
594 // our "Set('Trusted', true)" method call is still pending in the Bluetooth
595 // daemon because it's busy handling the incoming connection.
596 if (device_chromeos
->IsPaired()) {
597 callback
.Run(SUCCESS
);
601 // TODO(keybuk): reject service authorizations when not paired, determine
602 // whether this is acceptable long-term.
603 LOG(WARNING
) << "Rejecting service connection from unpaired device "
604 << device_chromeos
->GetAddress() << " for UUID " << uuid
;
605 callback
.Run(REJECTED
);
608 void BluetoothAdapterChromeOS::Cancel() {
610 DCHECK(agent_
.get());
614 void BluetoothAdapterChromeOS::OnRegisterAgent() {
615 VLOG(1) << "Pairing agent registered, requesting to be made default";
617 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
619 dbus::ObjectPath(kAgentPath
),
620 base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgent
,
621 weak_ptr_factory_
.GetWeakPtr()),
622 base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgentError
,
623 weak_ptr_factory_
.GetWeakPtr()));
626 void BluetoothAdapterChromeOS::OnRegisterAgentError(
627 const std::string
& error_name
,
628 const std::string
& error_message
) {
629 // Our agent being already registered isn't an error.
630 if (error_name
== bluetooth_agent_manager::kErrorAlreadyExists
)
633 LOG(WARNING
) << ": Failed to register pairing agent: "
634 << error_name
<< ": " << error_message
;
637 void BluetoothAdapterChromeOS::OnRequestDefaultAgent() {
638 VLOG(1) << "Pairing agent now default";
641 void BluetoothAdapterChromeOS::OnRequestDefaultAgentError(
642 const std::string
& error_name
,
643 const std::string
& error_message
) {
644 LOG(WARNING
) << ": Failed to make pairing agent default: "
645 << error_name
<< ": " << error_message
;
648 void BluetoothAdapterChromeOS::OnRegisterAudioSink(
649 const device::BluetoothAdapter::AcquiredCallback
& callback
,
650 const device::BluetoothAudioSink::ErrorCallback
& error_callback
,
651 scoped_refptr
<BluetoothAudioSink
> audio_sink
) {
653 VLOG(1) << "Failed to register audio sink, adapter not present";
654 error_callback
.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER
);
657 DCHECK(audio_sink
.get());
658 callback
.Run(audio_sink
);
661 BluetoothDeviceChromeOS
*
662 BluetoothAdapterChromeOS::GetDeviceWithPath(
663 const dbus::ObjectPath
& object_path
) {
667 for (DevicesMap::iterator iter
= devices_
.begin(); iter
!= devices_
.end();
669 BluetoothDeviceChromeOS
* device_chromeos
=
670 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
671 if (device_chromeos
->object_path() == object_path
)
672 return device_chromeos
;
678 BluetoothPairingChromeOS
* BluetoothAdapterChromeOS::GetPairing(
679 const dbus::ObjectPath
& object_path
) {
681 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
682 if (!device_chromeos
) {
683 LOG(WARNING
) << "Pairing Agent request for unknown device: "
684 << object_path
.value();
688 BluetoothPairingChromeOS
* pairing
= device_chromeos
->GetPairing();
692 // The device doesn't have its own pairing context, so this is an incoming
693 // pairing request that should use our best default delegate (if we have one).
694 BluetoothDevice::PairingDelegate
* pairing_delegate
= DefaultPairingDelegate();
695 if (!pairing_delegate
)
698 return device_chromeos
->BeginPairing(pairing_delegate
);
701 void BluetoothAdapterChromeOS::SetAdapter(const dbus::ObjectPath
& object_path
) {
702 DCHECK(!IsPresent());
703 DCHECK(!dbus_is_shutdown_
);
704 object_path_
= object_path
;
706 VLOG(1) << object_path_
.value() << ": using adapter.";
708 VLOG(1) << "Registering pairing agent";
709 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
711 dbus::ObjectPath(kAgentPath
),
712 bluetooth_agent_manager::kKeyboardDisplayCapability
,
713 base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgent
,
714 weak_ptr_factory_
.GetWeakPtr()),
715 base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgentError
,
716 weak_ptr_factory_
.GetWeakPtr()));
718 SetDefaultAdapterName();
720 BluetoothAdapterClient::Properties
* properties
=
721 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
722 GetProperties(object_path_
);
724 PresentChanged(true);
726 if (properties
->powered
.value())
727 PoweredChanged(true);
728 if (properties
->discoverable
.value())
729 DiscoverableChanged(true);
730 if (properties
->discovering
.value())
731 DiscoveringChanged(true);
733 std::vector
<dbus::ObjectPath
> device_paths
=
734 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
735 GetDevicesForAdapter(object_path_
);
737 for (std::vector
<dbus::ObjectPath
>::iterator iter
= device_paths
.begin();
738 iter
!= device_paths
.end(); ++iter
) {
743 void BluetoothAdapterChromeOS::SetDefaultAdapterName() {
745 std::string board
= base::SysInfo::GetLsbReleaseBoard();
747 if (board
.substr(0, 6) == "stumpy") {
749 } else if (board
.substr(0, 4) == "link") {
750 alias
= "Chromebook Pixel";
752 alias
= "Chromebook";
755 SetName(alias
, base::Bind(&base::DoNothing
), base::Bind(&base::DoNothing
));
758 void BluetoothAdapterChromeOS::RemoveAdapter() {
760 VLOG(1) << object_path_
.value() << ": adapter removed.";
762 BluetoothAdapterClient::Properties
* properties
=
763 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
764 GetProperties(object_path_
);
766 object_path_
= dbus::ObjectPath("");
768 if (properties
->powered
.value())
769 PoweredChanged(false);
770 if (properties
->discoverable
.value())
771 DiscoverableChanged(false);
772 if (properties
->discovering
.value())
773 DiscoveringChanged(false);
775 // Copy the devices list here and clear the original so that when we
776 // send DeviceRemoved(), GetDevices() returns no devices.
777 DevicesMap devices
= devices_
;
780 for (DevicesMap::iterator iter
= devices
.begin();
781 iter
!= devices
.end(); ++iter
) {
782 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
783 DeviceRemoved(this, iter
->second
));
787 PresentChanged(false);
790 void BluetoothAdapterChromeOS::PoweredChanged(bool powered
) {
791 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
792 AdapterPoweredChanged(this, powered
));
795 void BluetoothAdapterChromeOS::DiscoverableChanged(bool discoverable
) {
796 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
797 AdapterDiscoverableChanged(this, discoverable
));
800 void BluetoothAdapterChromeOS::DiscoveringChanged(
802 // If the adapter stopped discovery due to a reason other than a request by
803 // us, reset the count to 0.
804 VLOG(1) << "Discovering changed: " << discovering
;
805 if (!discovering
&& !discovery_request_pending_
806 && num_discovery_sessions_
> 0) {
807 VLOG(1) << "Marking sessions as inactive.";
808 num_discovery_sessions_
= 0;
809 MarkDiscoverySessionsAsInactive();
811 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
812 AdapterDiscoveringChanged(this, discovering
));
815 void BluetoothAdapterChromeOS::PresentChanged(bool present
) {
816 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
817 AdapterPresentChanged(this, present
));
820 void BluetoothAdapterChromeOS::NotifyDeviceChanged(
821 BluetoothDeviceChromeOS
* device
) {
822 DCHECK(device
->adapter_
== this);
824 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
825 DeviceChanged(this, device
));
828 void BluetoothAdapterChromeOS::NotifyGattServiceAdded(
829 BluetoothRemoteGattServiceChromeOS
* service
) {
830 DCHECK_EQ(service
->GetAdapter(), this);
832 static_cast<BluetoothDeviceChromeOS
*>(service
->GetDevice())->adapter_
,
835 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
837 GattServiceAdded(this, service
->GetDevice(), service
));
840 void BluetoothAdapterChromeOS::NotifyGattServiceRemoved(
841 BluetoothRemoteGattServiceChromeOS
* service
) {
842 DCHECK_EQ(service
->GetAdapter(), this);
844 static_cast<BluetoothDeviceChromeOS
*>(service
->GetDevice())->adapter_
,
847 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
849 GattServiceRemoved(this, service
->GetDevice(), service
));
852 void BluetoothAdapterChromeOS::NotifyGattServiceChanged(
853 BluetoothRemoteGattServiceChromeOS
* service
) {
854 DCHECK_EQ(service
->GetAdapter(), this);
856 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
858 GattServiceChanged(this, service
));
861 void BluetoothAdapterChromeOS::NotifyGattDiscoveryComplete(
862 BluetoothRemoteGattServiceChromeOS
* service
) {
863 DCHECK_EQ(service
->GetAdapter(), this);
865 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
867 GattDiscoveryCompleteForService(this, service
));
870 void BluetoothAdapterChromeOS::NotifyGattCharacteristicAdded(
871 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
) {
872 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
873 characteristic
->GetService())->GetAdapter(),
876 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
878 GattCharacteristicAdded(this, characteristic
));
881 void BluetoothAdapterChromeOS::NotifyGattCharacteristicRemoved(
882 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
) {
883 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
884 characteristic
->GetService())->GetAdapter(),
887 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
889 GattCharacteristicRemoved(this, characteristic
));
892 void BluetoothAdapterChromeOS::NotifyGattDescriptorAdded(
893 BluetoothRemoteGattDescriptorChromeOS
* descriptor
) {
894 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
895 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
898 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
900 GattDescriptorAdded(this, descriptor
));
903 void BluetoothAdapterChromeOS::NotifyGattDescriptorRemoved(
904 BluetoothRemoteGattDescriptorChromeOS
* descriptor
) {
905 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
906 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
909 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
911 GattDescriptorRemoved(this, descriptor
));
914 void BluetoothAdapterChromeOS::NotifyGattCharacteristicValueChanged(
915 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
,
916 const std::vector
<uint8
>& value
) {
917 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
918 characteristic
->GetService())->GetAdapter(),
922 BluetoothAdapter::Observer
,
924 GattCharacteristicValueChanged(this, characteristic
, value
));
927 void BluetoothAdapterChromeOS::NotifyGattDescriptorValueChanged(
928 BluetoothRemoteGattDescriptorChromeOS
* descriptor
,
929 const std::vector
<uint8
>& value
) {
930 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
931 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
934 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
936 GattDescriptorValueChanged(this, descriptor
, value
));
939 void BluetoothAdapterChromeOS::UseProfile(
940 const BluetoothUUID
& uuid
,
941 const dbus::ObjectPath
& device_path
,
942 const BluetoothProfileManagerClient::Options
& options
,
943 BluetoothProfileServiceProvider::Delegate
* delegate
,
944 const ProfileRegisteredCallback
& success_callback
,
945 const ErrorCompletionCallback
& error_callback
) {
949 VLOG(2) << "Adapter not present, erroring out";
950 error_callback
.Run("Adapter not present");
954 if (profiles_
.find(uuid
) != profiles_
.end()) {
955 // TODO(jamuraa) check that the options are the same and error when they are
957 SetProfileDelegate(uuid
, device_path
, delegate
, success_callback
,
962 if (profile_queues_
.find(uuid
) == profile_queues_
.end()) {
963 BluetoothAdapterProfileChromeOS::Register(
965 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfile
, this, uuid
),
966 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfileError
, this,
969 profile_queues_
[uuid
] = new std::vector
<RegisterProfileCompletionPair
>();
972 profile_queues_
[uuid
]->push_back(std::make_pair(
973 base::Bind(&BluetoothAdapterChromeOS::SetProfileDelegate
, this, uuid
,
974 device_path
, delegate
, success_callback
, error_callback
),
978 void BluetoothAdapterChromeOS::ReleaseProfile(
979 const dbus::ObjectPath
& device_path
,
980 BluetoothAdapterProfileChromeOS
* profile
) {
981 VLOG(2) << "Releasing Profile: " << profile
->uuid().canonical_value()
982 << " from " << device_path
.value();
983 profile
->RemoveDelegate(
984 device_path
, base::Bind(&BluetoothAdapterChromeOS::RemoveProfile
,
985 weak_ptr_factory_
.GetWeakPtr(), profile
->uuid()));
988 void BluetoothAdapterChromeOS::RemoveProfile(const BluetoothUUID
& uuid
) {
989 VLOG(2) << "Remove Profile: " << uuid
.canonical_value();
991 if (profiles_
.find(uuid
) != profiles_
.end()) {
992 delete profiles_
[uuid
];
993 profiles_
.erase(uuid
);
997 void BluetoothAdapterChromeOS::OnRegisterProfile(
998 const BluetoothUUID
& uuid
,
999 scoped_ptr
<BluetoothAdapterProfileChromeOS
> profile
) {
1000 profiles_
[uuid
] = profile
.release();
1002 if (profile_queues_
.find(uuid
) == profile_queues_
.end())
1005 for (auto& it
: *profile_queues_
[uuid
])
1007 delete profile_queues_
[uuid
];
1008 profile_queues_
.erase(uuid
);
1011 void BluetoothAdapterChromeOS::SetProfileDelegate(
1012 const BluetoothUUID
& uuid
,
1013 const dbus::ObjectPath
& device_path
,
1014 BluetoothProfileServiceProvider::Delegate
* delegate
,
1015 const ProfileRegisteredCallback
& success_callback
,
1016 const ErrorCompletionCallback
& error_callback
) {
1017 if (profiles_
.find(uuid
) == profiles_
.end()) {
1018 error_callback
.Run("Cannot find profile!");
1022 if (profiles_
[uuid
]->SetDelegate(device_path
, delegate
)) {
1023 success_callback
.Run(profiles_
[uuid
]);
1027 error_callback
.Run(bluetooth_agent_manager::kErrorAlreadyExists
);
1030 void BluetoothAdapterChromeOS::OnRegisterProfileError(
1031 const BluetoothUUID
& uuid
,
1032 const std::string
& error_name
,
1033 const std::string
& error_message
) {
1034 VLOG(2) << object_path_
.value() << ": Failed to register profile: "
1035 << error_name
<< ": " << error_message
;
1036 if (profile_queues_
.find(uuid
) == profile_queues_
.end())
1039 for (auto& it
: *profile_queues_
[uuid
])
1040 it
.second
.Run(error_message
);
1042 delete profile_queues_
[uuid
];
1043 profile_queues_
.erase(uuid
);
1046 void BluetoothAdapterChromeOS::OnSetDiscoverable(
1047 const base::Closure
& callback
,
1048 const ErrorCallback
& error_callback
,
1051 error_callback
.Run();
1055 // Set the discoverable_timeout property to zero so the adapter remains
1056 // discoverable forever.
1057 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1058 GetProperties(object_path_
)->discoverable_timeout
.Set(
1060 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
1061 weak_ptr_factory_
.GetWeakPtr(),
1066 void BluetoothAdapterChromeOS::OnPropertyChangeCompleted(
1067 const base::Closure
& callback
,
1068 const ErrorCallback
& error_callback
,
1070 if (IsPresent() && success
)
1073 error_callback
.Run();
1076 void BluetoothAdapterChromeOS::AddDiscoverySession(
1077 BluetoothDiscoveryFilter
* discovery_filter
,
1078 const base::Closure
& callback
,
1079 const ErrorCallback
& error_callback
) {
1081 error_callback
.Run();
1084 VLOG(1) << __func__
;
1085 if (discovery_request_pending_
) {
1086 // The pending request is either to stop a previous session or to start a
1087 // new one. Either way, queue this one.
1088 DCHECK(num_discovery_sessions_
== 1 || num_discovery_sessions_
== 0);
1089 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1090 << "request to start a new discovery session.";
1091 discovery_request_queue_
.push(
1092 std::make_tuple(discovery_filter
, callback
, error_callback
));
1096 // The adapter is already discovering.
1097 if (num_discovery_sessions_
> 0) {
1098 DCHECK(IsDiscovering());
1099 DCHECK(!discovery_request_pending_
);
1100 num_discovery_sessions_
++;
1101 SetDiscoveryFilter(BluetoothDiscoveryFilter::Merge(
1102 GetMergedDiscoveryFilter().get(), discovery_filter
),
1103 callback
, error_callback
);
1107 // There are no active discovery sessions.
1108 DCHECK_EQ(num_discovery_sessions_
, 0);
1110 if (discovery_filter
) {
1111 discovery_request_pending_
= true;
1113 scoped_ptr
<BluetoothDiscoveryFilter
> df(new BluetoothDiscoveryFilter(
1114 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL
));
1115 df
->CopyFrom(*discovery_filter
);
1118 base::Bind(&BluetoothAdapterChromeOS::OnPreSetDiscoveryFilter
,
1119 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1120 base::Bind(&BluetoothAdapterChromeOS::OnPreSetDiscoveryFilterError
,
1121 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1124 current_filter_
.reset();
1126 // This is the first request to start device discovery.
1127 discovery_request_pending_
= true;
1128 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1130 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery
,
1131 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1132 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError
,
1133 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1136 void BluetoothAdapterChromeOS::RemoveDiscoverySession(
1137 BluetoothDiscoveryFilter
* discovery_filter
,
1138 const base::Closure
& callback
,
1139 const ErrorCallback
& error_callback
) {
1141 error_callback
.Run();
1145 VLOG(1) << __func__
;
1146 // There are active sessions other than the one currently being removed.
1147 if (num_discovery_sessions_
> 1) {
1148 DCHECK(IsDiscovering());
1149 DCHECK(!discovery_request_pending_
);
1150 num_discovery_sessions_
--;
1152 SetDiscoveryFilter(GetMergedDiscoveryFilterMasked(discovery_filter
),
1153 callback
, error_callback
);
1157 // If there is a pending request to BlueZ, then queue this request.
1158 if (discovery_request_pending_
) {
1159 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1160 << "request to stop discovery session.";
1161 error_callback
.Run();
1165 // There are no active sessions. Return error.
1166 if (num_discovery_sessions_
== 0) {
1167 // TODO(armansito): This should never happen once we have the
1168 // DiscoverySession API. Replace this case with an assert once it's
1169 // the deprecated methods have been removed. (See crbug.com/3445008).
1170 VLOG(1) << "No active discovery sessions. Returning error.";
1171 error_callback
.Run();
1175 // There is exactly one active discovery session. Request BlueZ to stop
1177 DCHECK_EQ(num_discovery_sessions_
, 1);
1178 discovery_request_pending_
= true;
1179 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1182 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery
,
1183 weak_ptr_factory_
.GetWeakPtr(),
1185 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError
,
1186 weak_ptr_factory_
.GetWeakPtr(),
1190 void BluetoothAdapterChromeOS::SetDiscoveryFilter(
1191 scoped_ptr
<BluetoothDiscoveryFilter
> discovery_filter
,
1192 const base::Closure
& callback
,
1193 const ErrorCallback
& error_callback
) {
1195 error_callback
.Run();
1199 // If old and new filter are equal (null) then don't make request, just call
1201 if (!current_filter_
&& !discovery_filter
.get()) {
1206 // If old and new filter are not null and equal then don't make request, just
1207 // call succes callback
1208 if (current_filter_
&& discovery_filter
&&
1209 current_filter_
->Equals(*discovery_filter
)) {
1214 current_filter_
.reset(discovery_filter
.release());
1216 chromeos::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter
;
1218 if (current_filter_
.get()) {
1222 std::set
<device::BluetoothUUID
> uuids
;
1224 if (current_filter_
->GetPathloss(&pathloss
))
1225 dbus_discovery_filter
.pathloss
.reset(new uint16_t(pathloss
));
1227 if (current_filter_
->GetRSSI(&rssi
))
1228 dbus_discovery_filter
.rssi
.reset(new int16_t(rssi
));
1230 transport
= current_filter_
->GetTransport();
1231 if (transport
== BluetoothDiscoveryFilter::Transport::TRANSPORT_LE
) {
1232 dbus_discovery_filter
.transport
.reset(new std::string("le"));
1233 } else if (transport
==
1234 BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC
) {
1235 dbus_discovery_filter
.transport
.reset(new std::string("bredr"));
1236 } else if (transport
==
1237 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL
) {
1238 dbus_discovery_filter
.transport
.reset(new std::string("auto"));
1241 current_filter_
->GetUUIDs(uuids
);
1243 dbus_discovery_filter
.uuids
=
1244 scoped_ptr
<std::vector
<std::string
>>(new std::vector
<std::string
>);
1246 for (const auto& it
: uuids
)
1247 dbus_discovery_filter
.uuids
.get()->push_back(it
.value());
1251 DBusThreadManager::Get()->GetBluetoothAdapterClient()->SetDiscoveryFilter(
1252 object_path_
, dbus_discovery_filter
,
1253 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilter
,
1254 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1255 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilterError
,
1256 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1259 void BluetoothAdapterChromeOS::OnStartDiscovery(
1260 const base::Closure
& callback
,
1261 const ErrorCallback
& error_callback
) {
1262 // Report success on the original request and increment the count.
1263 VLOG(1) << __func__
;
1264 DCHECK(discovery_request_pending_
);
1265 DCHECK_EQ(num_discovery_sessions_
, 0);
1266 discovery_request_pending_
= false;
1267 num_discovery_sessions_
++;
1271 error_callback
.Run();
1273 // Try to add a new discovery session for each queued request.
1274 ProcessQueuedDiscoveryRequests();
1277 void BluetoothAdapterChromeOS::OnStartDiscoveryError(
1278 const base::Closure
& callback
,
1279 const ErrorCallback
& error_callback
,
1280 const std::string
& error_name
,
1281 const std::string
& error_message
) {
1282 LOG(WARNING
) << object_path_
.value() << ": Failed to start discovery: "
1283 << error_name
<< ": " << error_message
;
1285 // Failed to start discovery. This can only happen if the count is at 0.
1286 DCHECK_EQ(num_discovery_sessions_
, 0);
1287 DCHECK(discovery_request_pending_
);
1288 discovery_request_pending_
= false;
1290 // Discovery request may fail if discovery was previously initiated by Chrome,
1291 // but the session were invalidated due to the discovery state unexpectedly
1292 // changing to false and then back to true. In this case, report success.
1293 if (IsPresent() && error_name
== bluetooth_device::kErrorInProgress
&&
1295 VLOG(1) << "Discovery previously initiated. Reporting success.";
1296 num_discovery_sessions_
++;
1299 error_callback
.Run();
1302 // Try to add a new discovery session for each queued request.
1303 ProcessQueuedDiscoveryRequests();
1306 void BluetoothAdapterChromeOS::OnStopDiscovery(const base::Closure
& callback
) {
1307 // Report success on the original request and decrement the count.
1308 VLOG(1) << __func__
;
1309 DCHECK(discovery_request_pending_
);
1310 DCHECK_EQ(num_discovery_sessions_
, 1);
1311 discovery_request_pending_
= false;
1312 num_discovery_sessions_
--;
1315 current_filter_
.reset();
1317 // Try to add a new discovery session for each queued request.
1318 ProcessQueuedDiscoveryRequests();
1321 void BluetoothAdapterChromeOS::OnStopDiscoveryError(
1322 const ErrorCallback
& error_callback
,
1323 const std::string
& error_name
,
1324 const std::string
& error_message
) {
1325 LOG(WARNING
) << object_path_
.value() << ": Failed to stop discovery: "
1326 << error_name
<< ": " << error_message
;
1328 // Failed to stop discovery. This can only happen if the count is at 1.
1329 DCHECK(discovery_request_pending_
);
1330 DCHECK_EQ(num_discovery_sessions_
, 1);
1331 discovery_request_pending_
= false;
1332 error_callback
.Run();
1334 // Try to add a new discovery session for each queued request.
1335 ProcessQueuedDiscoveryRequests();
1338 void BluetoothAdapterChromeOS::OnPreSetDiscoveryFilter(
1339 const base::Closure
& callback
,
1340 const ErrorCallback
& error_callback
) {
1341 // This is the first request to start device discovery.
1342 DCHECK(discovery_request_pending_
);
1343 DCHECK_EQ(num_discovery_sessions_
, 0);
1345 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1347 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery
,
1348 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1349 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError
,
1350 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1353 void BluetoothAdapterChromeOS::OnPreSetDiscoveryFilterError(
1354 const base::Closure
& callback
,
1355 const ErrorCallback
& error_callback
) {
1356 LOG(WARNING
) << object_path_
.value()
1357 << ": Failed to pre set discovery filter.";
1359 // Failed to start discovery. This can only happen if the count is at 0.
1360 DCHECK_EQ(num_discovery_sessions_
, 0);
1361 DCHECK(discovery_request_pending_
);
1362 discovery_request_pending_
= false;
1364 error_callback
.Run();
1366 // Try to add a new discovery session for each queued request.
1367 ProcessQueuedDiscoveryRequests();
1370 void BluetoothAdapterChromeOS::OnSetDiscoveryFilter(
1371 const base::Closure
& callback
,
1372 const ErrorCallback
& error_callback
) {
1373 // Report success on the original request and increment the count.
1374 VLOG(1) << __func__
;
1378 error_callback
.Run();
1381 void BluetoothAdapterChromeOS::OnSetDiscoveryFilterError(
1382 const base::Closure
& callback
,
1383 const ErrorCallback
& error_callback
,
1384 const std::string
& error_name
,
1385 const std::string
& error_message
) {
1386 LOG(WARNING
) << object_path_
.value()
1387 << ": Failed to set discovery filter: " << error_name
<< ": "
1390 error_callback
.Run();
1392 // Try to add a new discovery session for each queued request.
1393 ProcessQueuedDiscoveryRequests();
1396 void BluetoothAdapterChromeOS::ProcessQueuedDiscoveryRequests() {
1397 while (!discovery_request_queue_
.empty()) {
1398 VLOG(1) << "Process queued discovery request.";
1399 DiscoveryParamTuple params
= discovery_request_queue_
.front();
1400 discovery_request_queue_
.pop();
1401 AddDiscoverySession(std::get
<0>(params
), std::get
<1>(params
),
1402 std::get
<2>(params
));
1404 // If the queued request resulted in a pending call, then let it
1405 // asynchonously process the remaining queued requests once the pending
1407 if (discovery_request_pending_
)
1412 } // namespace chromeos