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_discovery_session_outcome.h"
29 #include "device/bluetooth/bluetooth_pairing_chromeos.h"
30 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
31 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
32 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
33 #include "device/bluetooth/bluetooth_socket_chromeos.h"
34 #include "device/bluetooth/bluetooth_socket_thread.h"
35 #include "device/bluetooth/bluetooth_uuid.h"
36 #include "third_party/cros_system_api/dbus/service_constants.h"
38 using device::BluetoothAdapter
;
39 using device::BluetoothAudioSink
;
40 using device::BluetoothDevice
;
41 using device::BluetoothDiscoveryFilter
;
42 using device::BluetoothSocket
;
43 using device::BluetoothUUID
;
44 using device::UMABluetoothDiscoverySessionOutcome
;
48 // The agent path is relatively meaningless since BlueZ only permits one to
49 // exist per D-Bus connection, it just has to be unique within Chromium.
50 const char kAgentPath
[] = "/org/chromium/bluetooth_agent";
52 void OnUnregisterAgentError(const std::string
& error_name
,
53 const std::string
& error_message
) {
54 // It's okay if the agent didn't exist, it means we never saw an adapter.
55 if (error_name
== bluetooth_agent_manager::kErrorDoesNotExist
)
58 LOG(WARNING
) << "Failed to unregister pairing agent: "
59 << error_name
<< ": " << error_message
;
62 UMABluetoothDiscoverySessionOutcome
TranslateDiscoveryErrorToUMA(
63 const std::string
& error_name
) {
64 if (error_name
== chromeos::BluetoothAdapterClient::kUnknownAdapterError
) {
65 return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_UNKNOWN_ADAPTER
;
66 } else if (error_name
== chromeos::BluetoothAdapterClient::kNoResponseError
) {
67 return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_NO_RESPONSE
;
68 } else if (error_name
== bluetooth_device::kErrorInProgress
) {
69 return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_IN_PROGRESS
;
70 } else if (error_name
== bluetooth_device::kErrorNotReady
) {
71 return UMABluetoothDiscoverySessionOutcome::CHROMEOS_DBUS_NOT_READY
;
72 } else if (error_name
== bluetooth_device::kErrorFailed
) {
73 return UMABluetoothDiscoverySessionOutcome::FAILED
;
75 LOG(WARNING
) << "Can't histogram DBus error " << error_name
;
76 return UMABluetoothDiscoverySessionOutcome::UNKNOWN
;
85 base::WeakPtr
<BluetoothAdapter
> BluetoothAdapter::CreateAdapter(
86 const InitCallback
& init_callback
) {
87 return chromeos::BluetoothAdapterChromeOS::CreateAdapter();
95 base::WeakPtr
<BluetoothAdapter
> BluetoothAdapterChromeOS::CreateAdapter() {
96 BluetoothAdapterChromeOS
* adapter
= new BluetoothAdapterChromeOS();
97 return adapter
->weak_ptr_factory_
.GetWeakPtr();
100 void BluetoothAdapterChromeOS::Shutdown() {
101 if (dbus_is_shutdown_
)
103 DCHECK(DBusThreadManager::IsInitialized())
104 << "Call BluetoothAdapterFactory::Shutdown() before "
105 "DBusThreadManager::Shutdown().";
108 RemoveAdapter(); // Also deletes devices_.
109 DCHECK(devices_
.empty());
110 // profiles_ is empty because all BluetoothSockets have been notified
111 // that this adapter is disappearing.
112 DCHECK(profiles_
.empty());
114 for (auto& it
: profile_queues_
)
116 profile_queues_
.clear();
118 DBusThreadManager::Get()->GetBluetoothAdapterClient()->RemoveObserver(this);
119 DBusThreadManager::Get()->GetBluetoothDeviceClient()->RemoveObserver(this);
120 DBusThreadManager::Get()->GetBluetoothInputClient()->RemoveObserver(this);
122 VLOG(1) << "Unregistering pairing agent";
123 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->UnregisterAgent(
124 dbus::ObjectPath(kAgentPath
), base::Bind(&base::DoNothing
),
125 base::Bind(&OnUnregisterAgentError
));
128 dbus_is_shutdown_
= true;
131 BluetoothAdapterChromeOS::BluetoothAdapterChromeOS()
132 : dbus_is_shutdown_(false),
133 num_discovery_sessions_(0),
134 discovery_request_pending_(false),
135 weak_ptr_factory_(this) {
136 ui_task_runner_
= base::ThreadTaskRunnerHandle::Get();
137 socket_thread_
= device::BluetoothSocketThread::Get();
139 DBusThreadManager::Get()->GetBluetoothAdapterClient()->AddObserver(this);
140 DBusThreadManager::Get()->GetBluetoothDeviceClient()->AddObserver(this);
141 DBusThreadManager::Get()->GetBluetoothInputClient()->AddObserver(this);
143 // Register the pairing agent.
144 dbus::Bus
* system_bus
= DBusThreadManager::Get()->GetSystemBus();
145 agent_
.reset(BluetoothAgentServiceProvider::Create(
146 system_bus
, dbus::ObjectPath(kAgentPath
), this));
147 DCHECK(agent_
.get());
149 std::vector
<dbus::ObjectPath
> object_paths
=
150 DBusThreadManager::Get()->GetBluetoothAdapterClient()->GetAdapters();
152 if (!object_paths
.empty()) {
153 VLOG(1) << object_paths
.size() << " Bluetooth adapter(s) available.";
154 SetAdapter(object_paths
[0]);
158 BluetoothAdapterChromeOS::~BluetoothAdapterChromeOS() {
162 std::string
BluetoothAdapterChromeOS::GetAddress() const {
164 return std::string();
166 BluetoothAdapterClient::Properties
* properties
=
167 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
168 GetProperties(object_path_
);
171 return BluetoothDevice::CanonicalizeAddress(properties
->address
.value());
174 std::string
BluetoothAdapterChromeOS::GetName() const {
176 return std::string();
178 BluetoothAdapterClient::Properties
* properties
=
179 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
180 GetProperties(object_path_
);
183 return properties
->alias
.value();
186 void BluetoothAdapterChromeOS::SetName(const std::string
& name
,
187 const base::Closure
& callback
,
188 const ErrorCallback
& error_callback
) {
190 error_callback
.Run();
194 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
195 GetProperties(object_path_
)->alias
.Set(
197 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
198 weak_ptr_factory_
.GetWeakPtr(),
203 bool BluetoothAdapterChromeOS::IsInitialized() const {
207 bool BluetoothAdapterChromeOS::IsPresent() const {
208 return !dbus_is_shutdown_
&& !object_path_
.value().empty();
211 bool BluetoothAdapterChromeOS::IsPowered() const {
215 BluetoothAdapterClient::Properties
* properties
=
216 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
217 GetProperties(object_path_
);
219 return properties
->powered
.value();
222 void BluetoothAdapterChromeOS::SetPowered(
224 const base::Closure
& callback
,
225 const ErrorCallback
& error_callback
) {
227 error_callback
.Run();
231 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
232 GetProperties(object_path_
)->powered
.Set(
234 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
235 weak_ptr_factory_
.GetWeakPtr(),
240 bool BluetoothAdapterChromeOS::IsDiscoverable() const {
244 BluetoothAdapterClient::Properties
* properties
=
245 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
246 GetProperties(object_path_
);
248 return properties
->discoverable
.value();
251 void BluetoothAdapterChromeOS::SetDiscoverable(
253 const base::Closure
& callback
,
254 const ErrorCallback
& error_callback
) {
256 error_callback
.Run();
260 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
261 GetProperties(object_path_
)->discoverable
.Set(
263 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoverable
,
264 weak_ptr_factory_
.GetWeakPtr(),
269 bool BluetoothAdapterChromeOS::IsDiscovering() const {
273 BluetoothAdapterClient::Properties
* properties
=
274 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
275 GetProperties(object_path_
);
277 return properties
->discovering
.value();
280 void BluetoothAdapterChromeOS::CreateRfcommService(
281 const BluetoothUUID
& uuid
,
282 const ServiceOptions
& options
,
283 const CreateServiceCallback
& callback
,
284 const CreateServiceErrorCallback
& error_callback
) {
285 DCHECK(!dbus_is_shutdown_
);
286 VLOG(1) << object_path_
.value() << ": Creating RFCOMM service: "
287 << uuid
.canonical_value();
288 scoped_refptr
<BluetoothSocketChromeOS
> socket
=
289 BluetoothSocketChromeOS::CreateBluetoothSocket(
290 ui_task_runner_
, socket_thread_
);
292 BluetoothSocketChromeOS::kRfcomm
,
295 base::Bind(callback
, socket
),
299 void BluetoothAdapterChromeOS::CreateL2capService(
300 const BluetoothUUID
& uuid
,
301 const ServiceOptions
& options
,
302 const CreateServiceCallback
& callback
,
303 const CreateServiceErrorCallback
& error_callback
) {
304 DCHECK(!dbus_is_shutdown_
);
305 VLOG(1) << object_path_
.value() << ": Creating L2CAP service: "
306 << uuid
.canonical_value();
307 scoped_refptr
<BluetoothSocketChromeOS
> socket
=
308 BluetoothSocketChromeOS::CreateBluetoothSocket(
309 ui_task_runner_
, socket_thread_
);
311 BluetoothSocketChromeOS::kL2cap
,
314 base::Bind(callback
, socket
),
318 void BluetoothAdapterChromeOS::RegisterAudioSink(
319 const BluetoothAudioSink::Options
& options
,
320 const device::BluetoothAdapter::AcquiredCallback
& callback
,
321 const BluetoothAudioSink::ErrorCallback
& error_callback
) {
322 VLOG(1) << "Registering audio sink";
323 if (!this->IsPresent()) {
324 error_callback
.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER
);
327 scoped_refptr
<BluetoothAudioSinkChromeOS
> audio_sink(
328 new BluetoothAudioSinkChromeOS(this));
329 audio_sink
->Register(
330 options
, base::Bind(&BluetoothAdapterChromeOS::OnRegisterAudioSink
,
331 weak_ptr_factory_
.GetWeakPtr(), callback
,
332 error_callback
, audio_sink
),
336 void BluetoothAdapterChromeOS::RegisterAdvertisement(
337 scoped_ptr
<device::BluetoothAdvertisement::Data
> advertisement_data
,
338 const CreateAdvertisementCallback
& callback
,
339 const CreateAdvertisementErrorCallback
& error_callback
) {
340 scoped_refptr
<BluetoothAdvertisementChromeOS
> advertisement(
341 new BluetoothAdvertisementChromeOS(advertisement_data
.Pass(), this));
342 advertisement
->Register(base::Bind(callback
, advertisement
), error_callback
);
345 void BluetoothAdapterChromeOS::RemovePairingDelegateInternal(
346 BluetoothDevice::PairingDelegate
* pairing_delegate
) {
347 // Check if any device is using the pairing delegate.
348 // If so, clear the pairing context which will make any responses no-ops.
349 for (DevicesMap::iterator iter
= devices_
.begin();
350 iter
!= devices_
.end(); ++iter
) {
351 BluetoothDeviceChromeOS
* device_chromeos
=
352 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
354 BluetoothPairingChromeOS
* pairing
= device_chromeos
->GetPairing();
355 if (pairing
&& pairing
->GetPairingDelegate() == pairing_delegate
)
356 device_chromeos
->EndPairing();
360 void BluetoothAdapterChromeOS::AdapterAdded(
361 const dbus::ObjectPath
& object_path
) {
362 // Set the adapter to the newly added adapter only if no adapter is present.
364 SetAdapter(object_path
);
367 void BluetoothAdapterChromeOS::AdapterRemoved(
368 const dbus::ObjectPath
& object_path
) {
369 if (object_path
== object_path_
)
373 void BluetoothAdapterChromeOS::AdapterPropertyChanged(
374 const dbus::ObjectPath
& object_path
,
375 const std::string
& property_name
) {
376 if (object_path
!= object_path_
)
380 BluetoothAdapterClient::Properties
* properties
=
381 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
382 GetProperties(object_path_
);
384 if (property_name
== properties
->powered
.name()) {
385 PoweredChanged(properties
->powered
.value());
386 } else if (property_name
== properties
->discoverable
.name()) {
387 DiscoverableChanged(properties
->discoverable
.value());
388 } else if (property_name
== properties
->discovering
.name()) {
389 DiscoveringChanged(properties
->discovering
.value());
393 void BluetoothAdapterChromeOS::DeviceAdded(
394 const dbus::ObjectPath
& object_path
) {
395 DCHECK(DBusThreadManager::Get());
396 BluetoothDeviceClient::Properties
* properties
=
397 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
398 GetProperties(object_path
);
399 if (!properties
|| properties
->adapter
.value() != object_path_
)
403 BluetoothDeviceChromeOS
* device_chromeos
=
404 new BluetoothDeviceChromeOS(this,
408 DCHECK(devices_
.find(device_chromeos
->GetAddress()) == devices_
.end());
410 devices_
[device_chromeos
->GetAddress()] = device_chromeos
;
412 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
413 DeviceAdded(this, device_chromeos
));
416 void BluetoothAdapterChromeOS::DeviceRemoved(
417 const dbus::ObjectPath
& object_path
) {
418 for (DevicesMap::iterator iter
= devices_
.begin();
419 iter
!= devices_
.end(); ++iter
) {
420 BluetoothDeviceChromeOS
* device_chromeos
=
421 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
422 if (device_chromeos
->object_path() == object_path
) {
423 devices_
.erase(iter
);
425 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
426 DeviceRemoved(this, device_chromeos
));
427 delete device_chromeos
;
433 void BluetoothAdapterChromeOS::DevicePropertyChanged(
434 const dbus::ObjectPath
& object_path
,
435 const std::string
& property_name
) {
436 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
437 if (!device_chromeos
)
440 BluetoothDeviceClient::Properties
* properties
=
441 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
442 GetProperties(object_path
);
444 if (property_name
== properties
->bluetooth_class
.name() ||
445 property_name
== properties
->address
.name() ||
446 property_name
== properties
->alias
.name() ||
447 property_name
== properties
->paired
.name() ||
448 property_name
== properties
->trusted
.name() ||
449 property_name
== properties
->connected
.name() ||
450 property_name
== properties
->uuids
.name() ||
451 property_name
== properties
->rssi
.name() ||
452 property_name
== properties
->tx_power
.name()) {
453 NotifyDeviceChanged(device_chromeos
);
456 // When a device becomes paired, mark it as trusted so that the user does
457 // not need to approve every incoming connection
458 if (property_name
== properties
->paired
.name() &&
459 properties
->paired
.value() && !properties
->trusted
.value()) {
460 device_chromeos
->SetTrusted();
463 // UMA connection counting
464 if (property_name
== properties
->connected
.name()) {
465 // PlayStation joystick tries to reconnect after disconnection from USB.
466 // If it is still not trusted, set it, so it becomes available on the
467 // list of known devices.
468 if (properties
->connected
.value() && device_chromeos
->IsTrustable() &&
469 !properties
->trusted
.value())
470 device_chromeos
->SetTrusted();
474 for (DevicesMap::iterator iter
= devices_
.begin();
475 iter
!= devices_
.end(); ++iter
) {
476 if (iter
->second
->IsPaired() && iter
->second
->IsConnected())
480 UMA_HISTOGRAM_COUNTS_100("Bluetooth.ConnectedDeviceCount", count
);
484 void BluetoothAdapterChromeOS::InputPropertyChanged(
485 const dbus::ObjectPath
& object_path
,
486 const std::string
& property_name
) {
487 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
488 if (!device_chromeos
)
491 BluetoothInputClient::Properties
* properties
=
492 DBusThreadManager::Get()->GetBluetoothInputClient()->
493 GetProperties(object_path
);
495 // Properties structure can be removed, which triggers a change in the
496 // BluetoothDevice::IsConnectable() property, as does a change in the
497 // actual reconnect_mode property.
498 if (!properties
|| property_name
== properties
->reconnect_mode
.name()) {
499 NotifyDeviceChanged(device_chromeos
);
503 void BluetoothAdapterChromeOS::Released() {
504 VLOG(1) << "Release";
507 DCHECK(agent_
.get());
509 // Called after we unregister the pairing agent, e.g. when changing I/O
510 // capabilities. Nothing much to be done right now.
513 void BluetoothAdapterChromeOS::RequestPinCode(
514 const dbus::ObjectPath
& device_path
,
515 const PinCodeCallback
& callback
) {
517 DCHECK(agent_
.get());
518 VLOG(1) << device_path
.value() << ": RequestPinCode";
520 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
522 callback
.Run(REJECTED
, "");
526 pairing
->RequestPinCode(callback
);
529 void BluetoothAdapterChromeOS::DisplayPinCode(
530 const dbus::ObjectPath
& device_path
,
531 const std::string
& pincode
) {
533 DCHECK(agent_
.get());
534 VLOG(1) << device_path
.value() << ": DisplayPinCode: " << pincode
;
536 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
540 pairing
->DisplayPinCode(pincode
);
543 void BluetoothAdapterChromeOS::RequestPasskey(
544 const dbus::ObjectPath
& device_path
,
545 const PasskeyCallback
& callback
) {
547 DCHECK(agent_
.get());
548 VLOG(1) << device_path
.value() << ": RequestPasskey";
550 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
552 callback
.Run(REJECTED
, 0);
556 pairing
->RequestPasskey(callback
);
559 void BluetoothAdapterChromeOS::DisplayPasskey(
560 const dbus::ObjectPath
& device_path
,
564 DCHECK(agent_
.get());
565 VLOG(1) << device_path
.value() << ": DisplayPasskey: " << passkey
566 << " (" << entered
<< " entered)";
568 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
573 pairing
->DisplayPasskey(passkey
);
575 pairing
->KeysEntered(entered
);
578 void BluetoothAdapterChromeOS::RequestConfirmation(
579 const dbus::ObjectPath
& device_path
,
581 const ConfirmationCallback
& callback
) {
583 DCHECK(agent_
.get());
584 VLOG(1) << device_path
.value() << ": RequestConfirmation: " << passkey
;
586 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
588 callback
.Run(REJECTED
);
592 pairing
->RequestConfirmation(passkey
, callback
);
595 void BluetoothAdapterChromeOS::RequestAuthorization(
596 const dbus::ObjectPath
& device_path
,
597 const ConfirmationCallback
& callback
) {
599 DCHECK(agent_
.get());
600 VLOG(1) << device_path
.value() << ": RequestAuthorization";
602 BluetoothPairingChromeOS
* pairing
= GetPairing(device_path
);
604 callback
.Run(REJECTED
);
608 pairing
->RequestAuthorization(callback
);
611 void BluetoothAdapterChromeOS::AuthorizeService(
612 const dbus::ObjectPath
& device_path
,
613 const std::string
& uuid
,
614 const ConfirmationCallback
& callback
) {
616 DCHECK(agent_
.get());
617 VLOG(1) << device_path
.value() << ": AuthorizeService: " << uuid
;
619 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(device_path
);
620 if (!device_chromeos
) {
621 callback
.Run(CANCELLED
);
625 // We always set paired devices to Trusted, so the only reason that this
626 // method call would ever be called is in the case of a race condition where
627 // our "Set('Trusted', true)" method call is still pending in the Bluetooth
628 // daemon because it's busy handling the incoming connection.
629 if (device_chromeos
->IsPaired()) {
630 callback
.Run(SUCCESS
);
634 // TODO(keybuk): reject service authorizations when not paired, determine
635 // whether this is acceptable long-term.
636 LOG(WARNING
) << "Rejecting service connection from unpaired device "
637 << device_chromeos
->GetAddress() << " for UUID " << uuid
;
638 callback
.Run(REJECTED
);
641 void BluetoothAdapterChromeOS::Cancel() {
643 DCHECK(agent_
.get());
647 void BluetoothAdapterChromeOS::OnRegisterAgent() {
648 VLOG(1) << "Pairing agent registered, requesting to be made default";
650 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
652 dbus::ObjectPath(kAgentPath
),
653 base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgent
,
654 weak_ptr_factory_
.GetWeakPtr()),
655 base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgentError
,
656 weak_ptr_factory_
.GetWeakPtr()));
659 void BluetoothAdapterChromeOS::OnRegisterAgentError(
660 const std::string
& error_name
,
661 const std::string
& error_message
) {
662 // Our agent being already registered isn't an error.
663 if (error_name
== bluetooth_agent_manager::kErrorAlreadyExists
)
666 LOG(WARNING
) << ": Failed to register pairing agent: "
667 << error_name
<< ": " << error_message
;
670 void BluetoothAdapterChromeOS::OnRequestDefaultAgent() {
671 VLOG(1) << "Pairing agent now default";
674 void BluetoothAdapterChromeOS::OnRequestDefaultAgentError(
675 const std::string
& error_name
,
676 const std::string
& error_message
) {
677 LOG(WARNING
) << ": Failed to make pairing agent default: "
678 << error_name
<< ": " << error_message
;
681 void BluetoothAdapterChromeOS::OnRegisterAudioSink(
682 const device::BluetoothAdapter::AcquiredCallback
& callback
,
683 const device::BluetoothAudioSink::ErrorCallback
& error_callback
,
684 scoped_refptr
<BluetoothAudioSink
> audio_sink
) {
686 VLOG(1) << "Failed to register audio sink, adapter not present";
687 error_callback
.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER
);
690 DCHECK(audio_sink
.get());
691 callback
.Run(audio_sink
);
694 BluetoothDeviceChromeOS
*
695 BluetoothAdapterChromeOS::GetDeviceWithPath(
696 const dbus::ObjectPath
& object_path
) {
700 for (DevicesMap::iterator iter
= devices_
.begin(); iter
!= devices_
.end();
702 BluetoothDeviceChromeOS
* device_chromeos
=
703 static_cast<BluetoothDeviceChromeOS
*>(iter
->second
);
704 if (device_chromeos
->object_path() == object_path
)
705 return device_chromeos
;
711 BluetoothPairingChromeOS
* BluetoothAdapterChromeOS::GetPairing(
712 const dbus::ObjectPath
& object_path
) {
714 BluetoothDeviceChromeOS
* device_chromeos
= GetDeviceWithPath(object_path
);
715 if (!device_chromeos
) {
716 LOG(WARNING
) << "Pairing Agent request for unknown device: "
717 << object_path
.value();
721 BluetoothPairingChromeOS
* pairing
= device_chromeos
->GetPairing();
725 // The device doesn't have its own pairing context, so this is an incoming
726 // pairing request that should use our best default delegate (if we have one).
727 BluetoothDevice::PairingDelegate
* pairing_delegate
= DefaultPairingDelegate();
728 if (!pairing_delegate
)
731 return device_chromeos
->BeginPairing(pairing_delegate
);
734 void BluetoothAdapterChromeOS::SetAdapter(const dbus::ObjectPath
& object_path
) {
735 DCHECK(!IsPresent());
736 DCHECK(!dbus_is_shutdown_
);
737 object_path_
= object_path
;
739 VLOG(1) << object_path_
.value() << ": using adapter.";
741 VLOG(1) << "Registering pairing agent";
742 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
744 dbus::ObjectPath(kAgentPath
),
745 bluetooth_agent_manager::kKeyboardDisplayCapability
,
746 base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgent
,
747 weak_ptr_factory_
.GetWeakPtr()),
748 base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgentError
,
749 weak_ptr_factory_
.GetWeakPtr()));
751 SetDefaultAdapterName();
753 BluetoothAdapterClient::Properties
* properties
=
754 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
755 GetProperties(object_path_
);
757 PresentChanged(true);
759 if (properties
->powered
.value())
760 PoweredChanged(true);
761 if (properties
->discoverable
.value())
762 DiscoverableChanged(true);
763 if (properties
->discovering
.value())
764 DiscoveringChanged(true);
766 std::vector
<dbus::ObjectPath
> device_paths
=
767 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
768 GetDevicesForAdapter(object_path_
);
770 for (std::vector
<dbus::ObjectPath
>::iterator iter
= device_paths
.begin();
771 iter
!= device_paths
.end(); ++iter
) {
776 void BluetoothAdapterChromeOS::SetDefaultAdapterName() {
780 switch (chromeos::GetDeviceType()) {
781 case DeviceType::kChromebase
:
782 alias
= "Chromebase";
784 case DeviceType::kChromebit
:
787 case DeviceType::kChromebook
:
788 alias
= "Chromebook";
790 case DeviceType::kChromebox
:
793 case DeviceType::kUnknown
:
794 alias
= "Chromebook";
798 SetName(alias
, base::Bind(&base::DoNothing
), base::Bind(&base::DoNothing
));
801 void BluetoothAdapterChromeOS::RemoveAdapter() {
803 VLOG(1) << object_path_
.value() << ": adapter removed.";
805 BluetoothAdapterClient::Properties
* properties
=
806 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
807 GetProperties(object_path_
);
809 object_path_
= dbus::ObjectPath("");
811 if (properties
->powered
.value())
812 PoweredChanged(false);
813 if (properties
->discoverable
.value())
814 DiscoverableChanged(false);
815 if (properties
->discovering
.value())
816 DiscoveringChanged(false);
818 // Copy the devices list here and clear the original so that when we
819 // send DeviceRemoved(), GetDevices() returns no devices.
820 DevicesMap devices
= devices_
;
823 for (DevicesMap::iterator iter
= devices
.begin();
824 iter
!= devices
.end(); ++iter
) {
825 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
826 DeviceRemoved(this, iter
->second
));
830 PresentChanged(false);
833 void BluetoothAdapterChromeOS::PoweredChanged(bool powered
) {
834 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
835 AdapterPoweredChanged(this, powered
));
838 void BluetoothAdapterChromeOS::DiscoverableChanged(bool discoverable
) {
839 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
840 AdapterDiscoverableChanged(this, discoverable
));
843 void BluetoothAdapterChromeOS::DiscoveringChanged(
845 // If the adapter stopped discovery due to a reason other than a request by
846 // us, reset the count to 0.
847 VLOG(1) << "Discovering changed: " << discovering
;
848 if (!discovering
&& !discovery_request_pending_
&&
849 num_discovery_sessions_
> 0) {
850 VLOG(1) << "Marking sessions as inactive.";
851 num_discovery_sessions_
= 0;
852 MarkDiscoverySessionsAsInactive();
854 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
855 AdapterDiscoveringChanged(this, discovering
));
858 void BluetoothAdapterChromeOS::PresentChanged(bool present
) {
859 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
860 AdapterPresentChanged(this, present
));
863 void BluetoothAdapterChromeOS::NotifyDeviceChanged(
864 BluetoothDeviceChromeOS
* device
) {
866 DCHECK(device
->adapter_
== this);
868 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
, observers_
,
869 DeviceChanged(this, device
));
872 void BluetoothAdapterChromeOS::NotifyGattServiceAdded(
873 BluetoothRemoteGattServiceChromeOS
* service
) {
874 DCHECK_EQ(service
->GetAdapter(), this);
876 static_cast<BluetoothDeviceChromeOS
*>(service
->GetDevice())->adapter_
,
879 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
881 GattServiceAdded(this, service
->GetDevice(), service
));
884 void BluetoothAdapterChromeOS::NotifyGattServiceRemoved(
885 BluetoothRemoteGattServiceChromeOS
* service
) {
886 DCHECK_EQ(service
->GetAdapter(), this);
888 static_cast<BluetoothDeviceChromeOS
*>(service
->GetDevice())->adapter_
,
891 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
893 GattServiceRemoved(this, service
->GetDevice(), service
));
896 void BluetoothAdapterChromeOS::NotifyGattServiceChanged(
897 BluetoothRemoteGattServiceChromeOS
* service
) {
898 DCHECK_EQ(service
->GetAdapter(), this);
900 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
902 GattServiceChanged(this, service
));
905 void BluetoothAdapterChromeOS::NotifyGattDiscoveryComplete(
906 BluetoothRemoteGattServiceChromeOS
* service
) {
907 DCHECK_EQ(service
->GetAdapter(), this);
909 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
911 GattDiscoveryCompleteForService(this, service
));
914 void BluetoothAdapterChromeOS::NotifyGattCharacteristicAdded(
915 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
) {
916 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
917 characteristic
->GetService())->GetAdapter(),
920 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
922 GattCharacteristicAdded(this, characteristic
));
925 void BluetoothAdapterChromeOS::NotifyGattCharacteristicRemoved(
926 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
) {
927 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
928 characteristic
->GetService())->GetAdapter(),
931 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
933 GattCharacteristicRemoved(this, characteristic
));
936 void BluetoothAdapterChromeOS::NotifyGattDescriptorAdded(
937 BluetoothRemoteGattDescriptorChromeOS
* descriptor
) {
938 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
939 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
942 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
944 GattDescriptorAdded(this, descriptor
));
947 void BluetoothAdapterChromeOS::NotifyGattDescriptorRemoved(
948 BluetoothRemoteGattDescriptorChromeOS
* descriptor
) {
949 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
950 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
953 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
955 GattDescriptorRemoved(this, descriptor
));
958 void BluetoothAdapterChromeOS::NotifyGattCharacteristicValueChanged(
959 BluetoothRemoteGattCharacteristicChromeOS
* characteristic
,
960 const std::vector
<uint8
>& value
) {
961 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
962 characteristic
->GetService())->GetAdapter(),
966 BluetoothAdapter::Observer
,
968 GattCharacteristicValueChanged(this, characteristic
, value
));
971 void BluetoothAdapterChromeOS::NotifyGattDescriptorValueChanged(
972 BluetoothRemoteGattDescriptorChromeOS
* descriptor
,
973 const std::vector
<uint8
>& value
) {
974 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS
*>(
975 descriptor
->GetCharacteristic()->GetService())->GetAdapter(),
978 FOR_EACH_OBSERVER(BluetoothAdapter::Observer
,
980 GattDescriptorValueChanged(this, descriptor
, value
));
983 void BluetoothAdapterChromeOS::UseProfile(
984 const BluetoothUUID
& uuid
,
985 const dbus::ObjectPath
& device_path
,
986 const BluetoothProfileManagerClient::Options
& options
,
987 BluetoothProfileServiceProvider::Delegate
* delegate
,
988 const ProfileRegisteredCallback
& success_callback
,
989 const ErrorCompletionCallback
& error_callback
) {
993 VLOG(2) << "Adapter not present, erroring out";
994 error_callback
.Run("Adapter not present");
998 if (profiles_
.find(uuid
) != profiles_
.end()) {
999 // TODO(jamuraa) check that the options are the same and error when they are
1001 SetProfileDelegate(uuid
, device_path
, delegate
, success_callback
,
1006 if (profile_queues_
.find(uuid
) == profile_queues_
.end()) {
1007 BluetoothAdapterProfileChromeOS::Register(
1009 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfile
, this, uuid
),
1010 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfileError
, this,
1013 profile_queues_
[uuid
] = new std::vector
<RegisterProfileCompletionPair
>();
1016 profile_queues_
[uuid
]->push_back(std::make_pair(
1017 base::Bind(&BluetoothAdapterChromeOS::SetProfileDelegate
, this, uuid
,
1018 device_path
, delegate
, success_callback
, error_callback
),
1022 void BluetoothAdapterChromeOS::ReleaseProfile(
1023 const dbus::ObjectPath
& device_path
,
1024 BluetoothAdapterProfileChromeOS
* profile
) {
1025 VLOG(2) << "Releasing Profile: " << profile
->uuid().canonical_value()
1026 << " from " << device_path
.value();
1027 profile
->RemoveDelegate(
1028 device_path
, base::Bind(&BluetoothAdapterChromeOS::RemoveProfile
,
1029 weak_ptr_factory_
.GetWeakPtr(), profile
->uuid()));
1032 void BluetoothAdapterChromeOS::RemoveProfile(const BluetoothUUID
& uuid
) {
1033 VLOG(2) << "Remove Profile: " << uuid
.canonical_value();
1035 if (profiles_
.find(uuid
) != profiles_
.end()) {
1036 delete profiles_
[uuid
];
1037 profiles_
.erase(uuid
);
1041 void BluetoothAdapterChromeOS::OnRegisterProfile(
1042 const BluetoothUUID
& uuid
,
1043 scoped_ptr
<BluetoothAdapterProfileChromeOS
> profile
) {
1044 profiles_
[uuid
] = profile
.release();
1046 if (profile_queues_
.find(uuid
) == profile_queues_
.end())
1049 for (auto& it
: *profile_queues_
[uuid
])
1051 delete profile_queues_
[uuid
];
1052 profile_queues_
.erase(uuid
);
1055 void BluetoothAdapterChromeOS::SetProfileDelegate(
1056 const BluetoothUUID
& uuid
,
1057 const dbus::ObjectPath
& device_path
,
1058 BluetoothProfileServiceProvider::Delegate
* delegate
,
1059 const ProfileRegisteredCallback
& success_callback
,
1060 const ErrorCompletionCallback
& error_callback
) {
1061 if (profiles_
.find(uuid
) == profiles_
.end()) {
1062 error_callback
.Run("Cannot find profile!");
1066 if (profiles_
[uuid
]->SetDelegate(device_path
, delegate
)) {
1067 success_callback
.Run(profiles_
[uuid
]);
1071 error_callback
.Run(bluetooth_agent_manager::kErrorAlreadyExists
);
1074 void BluetoothAdapterChromeOS::OnRegisterProfileError(
1075 const BluetoothUUID
& uuid
,
1076 const std::string
& error_name
,
1077 const std::string
& error_message
) {
1078 VLOG(2) << object_path_
.value() << ": Failed to register profile: "
1079 << error_name
<< ": " << error_message
;
1080 if (profile_queues_
.find(uuid
) == profile_queues_
.end())
1083 for (auto& it
: *profile_queues_
[uuid
])
1084 it
.second
.Run(error_message
);
1086 delete profile_queues_
[uuid
];
1087 profile_queues_
.erase(uuid
);
1090 void BluetoothAdapterChromeOS::OnSetDiscoverable(
1091 const base::Closure
& callback
,
1092 const ErrorCallback
& error_callback
,
1095 error_callback
.Run();
1099 // Set the discoverable_timeout property to zero so the adapter remains
1100 // discoverable forever.
1101 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1102 GetProperties(object_path_
)->discoverable_timeout
.Set(
1104 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted
,
1105 weak_ptr_factory_
.GetWeakPtr(),
1110 void BluetoothAdapterChromeOS::OnPropertyChangeCompleted(
1111 const base::Closure
& callback
,
1112 const ErrorCallback
& error_callback
,
1114 if (IsPresent() && success
) {
1117 error_callback
.Run();
1121 void BluetoothAdapterChromeOS::AddDiscoverySession(
1122 BluetoothDiscoveryFilter
* discovery_filter
,
1123 const base::Closure
& callback
,
1124 const DiscoverySessionErrorCallback
& error_callback
) {
1127 UMABluetoothDiscoverySessionOutcome::ADAPTER_NOT_PRESENT
);
1130 VLOG(1) << __func__
;
1131 if (discovery_request_pending_
) {
1132 // The pending request is either to stop a previous session or to start a
1133 // new one. Either way, queue this one.
1134 DCHECK(num_discovery_sessions_
== 1 || num_discovery_sessions_
== 0);
1135 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1136 << "request to start a new discovery session.";
1137 discovery_request_queue_
.push(
1138 std::make_tuple(discovery_filter
, callback
, error_callback
));
1142 // The adapter is already discovering.
1143 if (num_discovery_sessions_
> 0) {
1144 DCHECK(IsDiscovering());
1145 DCHECK(!discovery_request_pending_
);
1146 num_discovery_sessions_
++;
1147 SetDiscoveryFilter(BluetoothDiscoveryFilter::Merge(
1148 GetMergedDiscoveryFilter().get(), discovery_filter
),
1149 callback
, error_callback
);
1153 // There are no active discovery sessions.
1154 DCHECK_EQ(num_discovery_sessions_
, 0);
1156 if (discovery_filter
) {
1157 discovery_request_pending_
= true;
1159 scoped_ptr
<BluetoothDiscoveryFilter
> df(new BluetoothDiscoveryFilter(
1160 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL
));
1161 df
->CopyFrom(*discovery_filter
);
1164 base::Bind(&BluetoothAdapterChromeOS::OnPreSetDiscoveryFilter
,
1165 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1166 base::Bind(&BluetoothAdapterChromeOS::OnPreSetDiscoveryFilterError
,
1167 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1170 current_filter_
.reset();
1173 // This is the first request to start device discovery.
1174 discovery_request_pending_
= true;
1175 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1177 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery
,
1178 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1179 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError
,
1180 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1183 void BluetoothAdapterChromeOS::RemoveDiscoverySession(
1184 BluetoothDiscoveryFilter
* discovery_filter
,
1185 const base::Closure
& callback
,
1186 const DiscoverySessionErrorCallback
& error_callback
) {
1189 UMABluetoothDiscoverySessionOutcome::ADAPTER_NOT_PRESENT
);
1193 VLOG(1) << __func__
;
1194 // There are active sessions other than the one currently being removed.
1195 if (num_discovery_sessions_
> 1) {
1196 DCHECK(IsDiscovering());
1197 DCHECK(!discovery_request_pending_
);
1198 num_discovery_sessions_
--;
1200 SetDiscoveryFilter(GetMergedDiscoveryFilterMasked(discovery_filter
),
1201 callback
, error_callback
);
1205 // If there is a pending request to BlueZ, then queue this request.
1206 if (discovery_request_pending_
) {
1207 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1208 << "request to stop discovery session.";
1210 UMABluetoothDiscoverySessionOutcome::REMOVE_WITH_PENDING_REQUEST
);
1214 // There are no active sessions. Return error.
1215 if (num_discovery_sessions_
== 0) {
1216 // TODO(armansito): This should never happen once we have the
1217 // DiscoverySession API. Replace this case with an assert once it's
1218 // the deprecated methods have been removed. (See crbug.com/3445008).
1219 VLOG(1) << "No active discovery sessions. Returning error.";
1221 UMABluetoothDiscoverySessionOutcome::ACTIVE_SESSION_NOT_IN_ADAPTER
);
1225 // There is exactly one active discovery session. Request BlueZ to stop
1227 DCHECK_EQ(num_discovery_sessions_
, 1);
1228 discovery_request_pending_
= true;
1229 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1232 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery
,
1233 weak_ptr_factory_
.GetWeakPtr(),
1235 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError
,
1236 weak_ptr_factory_
.GetWeakPtr(),
1240 void BluetoothAdapterChromeOS::SetDiscoveryFilter(
1241 scoped_ptr
<BluetoothDiscoveryFilter
> discovery_filter
,
1242 const base::Closure
& callback
,
1243 const DiscoverySessionErrorCallback
& error_callback
) {
1245 error_callback
.Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED
);
1249 // If old and new filter are equal (null) then don't make request, just call
1251 if (!current_filter_
&& !discovery_filter
.get()) {
1256 // If old and new filter are not null and equal then don't make request, just
1257 // call succes callback
1258 if (current_filter_
&& discovery_filter
&&
1259 current_filter_
->Equals(*discovery_filter
)) {
1264 current_filter_
.reset(discovery_filter
.release());
1266 chromeos::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter
;
1268 if (current_filter_
.get()) {
1272 std::set
<device::BluetoothUUID
> uuids
;
1274 if (current_filter_
->GetPathloss(&pathloss
))
1275 dbus_discovery_filter
.pathloss
.reset(new uint16_t(pathloss
));
1277 if (current_filter_
->GetRSSI(&rssi
))
1278 dbus_discovery_filter
.rssi
.reset(new int16_t(rssi
));
1280 transport
= current_filter_
->GetTransport();
1281 if (transport
== BluetoothDiscoveryFilter::Transport::TRANSPORT_LE
) {
1282 dbus_discovery_filter
.transport
.reset(new std::string("le"));
1283 } else if (transport
==
1284 BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC
) {
1285 dbus_discovery_filter
.transport
.reset(new std::string("bredr"));
1286 } else if (transport
==
1287 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL
) {
1288 dbus_discovery_filter
.transport
.reset(new std::string("auto"));
1291 current_filter_
->GetUUIDs(uuids
);
1293 dbus_discovery_filter
.uuids
=
1294 scoped_ptr
<std::vector
<std::string
>>(new std::vector
<std::string
>);
1296 for (const auto& it
: uuids
)
1297 dbus_discovery_filter
.uuids
.get()->push_back(it
.value());
1301 DBusThreadManager::Get()->GetBluetoothAdapterClient()->SetDiscoveryFilter(
1302 object_path_
, dbus_discovery_filter
,
1303 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilter
,
1304 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1305 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilterError
,
1306 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1309 void BluetoothAdapterChromeOS::OnStartDiscovery(
1310 const base::Closure
& callback
,
1311 const DiscoverySessionErrorCallback
& error_callback
) {
1312 // Report success on the original request and increment the count.
1313 VLOG(1) << __func__
;
1314 DCHECK(discovery_request_pending_
);
1315 DCHECK_EQ(num_discovery_sessions_
, 0);
1316 discovery_request_pending_
= false;
1317 num_discovery_sessions_
++;
1321 error_callback
.Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED
);
1324 // Try to add a new discovery session for each queued request.
1325 ProcessQueuedDiscoveryRequests();
1328 void BluetoothAdapterChromeOS::OnStartDiscoveryError(
1329 const base::Closure
& callback
,
1330 const DiscoverySessionErrorCallback
& error_callback
,
1331 const std::string
& error_name
,
1332 const std::string
& error_message
) {
1333 LOG(WARNING
) << object_path_
.value() << ": Failed to start discovery: "
1334 << error_name
<< ": " << error_message
;
1336 // Failed to start discovery. This can only happen if the count is at 0.
1337 DCHECK_EQ(num_discovery_sessions_
, 0);
1338 DCHECK(discovery_request_pending_
);
1339 discovery_request_pending_
= false;
1341 // Discovery request may fail if discovery was previously initiated by Chrome,
1342 // but the session were invalidated due to the discovery state unexpectedly
1343 // changing to false and then back to true. In this case, report success.
1344 if (IsPresent() && error_name
== bluetooth_device::kErrorInProgress
&&
1346 VLOG(1) << "Discovery previously initiated. Reporting success.";
1347 num_discovery_sessions_
++;
1350 error_callback
.Run(TranslateDiscoveryErrorToUMA(error_name
));
1353 // Try to add a new discovery session for each queued request.
1354 ProcessQueuedDiscoveryRequests();
1357 void BluetoothAdapterChromeOS::OnStopDiscovery(const base::Closure
& callback
) {
1358 // Report success on the original request and decrement the count.
1359 VLOG(1) << __func__
;
1360 DCHECK(discovery_request_pending_
);
1361 DCHECK_EQ(num_discovery_sessions_
, 1);
1362 discovery_request_pending_
= false;
1363 num_discovery_sessions_
--;
1366 current_filter_
.reset();
1368 // Try to add a new discovery session for each queued request.
1369 ProcessQueuedDiscoveryRequests();
1372 void BluetoothAdapterChromeOS::OnStopDiscoveryError(
1373 const DiscoverySessionErrorCallback
& error_callback
,
1374 const std::string
& error_name
,
1375 const std::string
& error_message
) {
1376 LOG(WARNING
) << object_path_
.value() << ": Failed to stop discovery: "
1377 << error_name
<< ": " << error_message
;
1379 // Failed to stop discovery. This can only happen if the count is at 1.
1380 DCHECK(discovery_request_pending_
);
1381 DCHECK_EQ(num_discovery_sessions_
, 1);
1382 discovery_request_pending_
= false;
1383 error_callback
.Run(TranslateDiscoveryErrorToUMA(error_name
));
1385 // Try to add a new discovery session for each queued request.
1386 ProcessQueuedDiscoveryRequests();
1389 void BluetoothAdapterChromeOS::OnPreSetDiscoveryFilter(
1390 const base::Closure
& callback
,
1391 const DiscoverySessionErrorCallback
& error_callback
) {
1392 // This is the first request to start device discovery.
1393 DCHECK(discovery_request_pending_
);
1394 DCHECK_EQ(num_discovery_sessions_
, 0);
1396 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1398 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery
,
1399 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
),
1400 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError
,
1401 weak_ptr_factory_
.GetWeakPtr(), callback
, error_callback
));
1404 void BluetoothAdapterChromeOS::OnPreSetDiscoveryFilterError(
1405 const base::Closure
& callback
,
1406 const DiscoverySessionErrorCallback
& error_callback
,
1407 UMABluetoothDiscoverySessionOutcome outcome
) {
1408 LOG(WARNING
) << object_path_
.value()
1409 << ": Failed to pre set discovery filter.";
1411 // Failed to start discovery. This can only happen if the count is at 0.
1412 DCHECK_EQ(num_discovery_sessions_
, 0);
1413 DCHECK(discovery_request_pending_
);
1414 discovery_request_pending_
= false;
1416 error_callback
.Run(outcome
);
1418 // Try to add a new discovery session for each queued request.
1419 ProcessQueuedDiscoveryRequests();
1422 void BluetoothAdapterChromeOS::OnSetDiscoveryFilter(
1423 const base::Closure
& callback
,
1424 const DiscoverySessionErrorCallback
& error_callback
) {
1425 // Report success on the original request and increment the count.
1426 VLOG(1) << __func__
;
1430 error_callback
.Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED
);
1434 void BluetoothAdapterChromeOS::OnSetDiscoveryFilterError(
1435 const base::Closure
& callback
,
1436 const DiscoverySessionErrorCallback
& error_callback
,
1437 const std::string
& error_name
,
1438 const std::string
& error_message
) {
1439 LOG(WARNING
) << object_path_
.value()
1440 << ": Failed to set discovery filter: " << error_name
<< ": "
1443 UMABluetoothDiscoverySessionOutcome outcome
=
1444 TranslateDiscoveryErrorToUMA(error_name
);
1445 if (outcome
== UMABluetoothDiscoverySessionOutcome::FAILED
) {
1446 // bluez/doc/adapter-api.txt says "Failed" is returned from
1447 // SetDiscoveryFilter when the controller doesn't support the requested
1449 outcome
= UMABluetoothDiscoverySessionOutcome::
1450 CHROMEOS_DBUS_FAILED_MAYBE_UNSUPPORTED_TRANSPORT
;
1452 error_callback
.Run(outcome
);
1454 // Try to add a new discovery session for each queued request.
1455 ProcessQueuedDiscoveryRequests();
1458 void BluetoothAdapterChromeOS::ProcessQueuedDiscoveryRequests() {
1459 while (!discovery_request_queue_
.empty()) {
1460 VLOG(1) << "Process queued discovery request.";
1461 DiscoveryParamTuple params
= discovery_request_queue_
.front();
1462 discovery_request_queue_
.pop();
1463 AddDiscoverySession(std::get
<0>(params
), std::get
<1>(params
),
1464 std::get
<2>(params
));
1466 // If the queued request resulted in a pending call, then let it
1467 // asynchonously process the remaining queued requests once the pending
1469 if (discovery_request_pending_
)
1474 } // namespace chromeos