Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / device / bluetooth / bluetooth_adapter_chromeos.cc
blob345bdeb70c1c7d49c78e6dbf8284a284e575cdfa
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"
7 #include <string>
9 #include "base/bind.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;
44 namespace {
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)
54 return;
56 LOG(WARNING) << "Failed to unregister pairing agent: "
57 << error_name << ": " << error_message;
60 } // namespace
62 namespace device {
64 // static
65 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
66 const InitCallback& init_callback) {
67 return chromeos::BluetoothAdapterChromeOS::CreateAdapter();
70 } // namespace device
72 namespace chromeos {
74 // static
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_)
82 return;
83 DCHECK(DBusThreadManager::IsInitialized())
84 << "Call BluetoothAdapterFactory::Shutdown() before "
85 "DBusThreadManager::Shutdown().";
87 if (IsPresent())
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_)
95 delete it.second;
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));
107 agent_.reset();
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() {
139 Shutdown();
142 std::string BluetoothAdapterChromeOS::GetAddress() const {
143 if (!IsPresent())
144 return std::string();
146 BluetoothAdapterClient::Properties* properties =
147 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
148 GetProperties(object_path_);
149 DCHECK(properties);
151 return BluetoothDevice::CanonicalizeAddress(properties->address.value());
154 std::string BluetoothAdapterChromeOS::GetName() const {
155 if (!IsPresent())
156 return std::string();
158 BluetoothAdapterClient::Properties* properties =
159 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
160 GetProperties(object_path_);
161 DCHECK(properties);
163 return properties->alias.value();
166 void BluetoothAdapterChromeOS::SetName(const std::string& name,
167 const base::Closure& callback,
168 const ErrorCallback& error_callback) {
169 if (!IsPresent()) {
170 error_callback.Run();
171 return;
174 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
175 GetProperties(object_path_)->alias.Set(
176 name,
177 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
178 weak_ptr_factory_.GetWeakPtr(),
179 callback,
180 error_callback));
183 bool BluetoothAdapterChromeOS::IsInitialized() const {
184 return true;
187 bool BluetoothAdapterChromeOS::IsPresent() const {
188 return !dbus_is_shutdown_ && !object_path_.value().empty();
191 bool BluetoothAdapterChromeOS::IsPowered() const {
192 if (!IsPresent())
193 return false;
195 BluetoothAdapterClient::Properties* properties =
196 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
197 GetProperties(object_path_);
199 return properties->powered.value();
202 void BluetoothAdapterChromeOS::SetPowered(
203 bool powered,
204 const base::Closure& callback,
205 const ErrorCallback& error_callback) {
206 if (!IsPresent()) {
207 error_callback.Run();
208 return;
211 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
212 GetProperties(object_path_)->powered.Set(
213 powered,
214 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
215 weak_ptr_factory_.GetWeakPtr(),
216 callback,
217 error_callback));
220 bool BluetoothAdapterChromeOS::IsDiscoverable() const {
221 if (!IsPresent())
222 return false;
224 BluetoothAdapterClient::Properties* properties =
225 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
226 GetProperties(object_path_);
228 return properties->discoverable.value();
231 void BluetoothAdapterChromeOS::SetDiscoverable(
232 bool discoverable,
233 const base::Closure& callback,
234 const ErrorCallback& error_callback) {
235 if (!IsPresent()) {
236 error_callback.Run();
237 return;
240 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
241 GetProperties(object_path_)->discoverable.Set(
242 discoverable,
243 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoverable,
244 weak_ptr_factory_.GetWeakPtr(),
245 callback,
246 error_callback));
249 bool BluetoothAdapterChromeOS::IsDiscovering() const {
250 if (!IsPresent())
251 return false;
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_);
271 socket->Listen(this,
272 BluetoothSocketChromeOS::kRfcomm,
273 uuid,
274 options,
275 base::Bind(callback, socket),
276 error_callback);
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_);
290 socket->Listen(this,
291 BluetoothSocketChromeOS::kL2cap,
292 uuid,
293 options,
294 base::Bind(callback, socket),
295 error_callback);
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);
305 return;
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),
313 error_callback);
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.
343 if (!IsPresent())
344 SetAdapter(object_path);
347 void BluetoothAdapterChromeOS::AdapterRemoved(
348 const dbus::ObjectPath& object_path) {
349 if (object_path == object_path_)
350 RemoveAdapter();
353 void BluetoothAdapterChromeOS::AdapterPropertyChanged(
354 const dbus::ObjectPath& object_path,
355 const std::string& property_name) {
356 if (object_path != object_path_)
357 return;
358 DCHECK(IsPresent());
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_)
380 return;
381 DCHECK(IsPresent());
383 BluetoothDeviceChromeOS* device_chromeos =
384 new BluetoothDeviceChromeOS(this,
385 object_path,
386 ui_task_runner_,
387 socket_thread_);
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;
408 return;
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)
418 return;
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();
452 int count = 0;
454 for (DevicesMap::iterator iter = devices_.begin();
455 iter != devices_.end(); ++iter) {
456 if (iter->second->IsPaired() && iter->second->IsConnected())
457 ++count;
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)
469 return;
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";
485 if (!IsPresent())
486 return;
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) {
496 DCHECK(IsPresent());
497 DCHECK(agent_.get());
498 VLOG(1) << device_path.value() << ": RequestPinCode";
500 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
501 if (!pairing) {
502 callback.Run(REJECTED, "");
503 return;
506 pairing->RequestPinCode(callback);
509 void BluetoothAdapterChromeOS::DisplayPinCode(
510 const dbus::ObjectPath& device_path,
511 const std::string& pincode) {
512 DCHECK(IsPresent());
513 DCHECK(agent_.get());
514 VLOG(1) << device_path.value() << ": DisplayPinCode: " << pincode;
516 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
517 if (!pairing)
518 return;
520 pairing->DisplayPinCode(pincode);
523 void BluetoothAdapterChromeOS::RequestPasskey(
524 const dbus::ObjectPath& device_path,
525 const PasskeyCallback& callback) {
526 DCHECK(IsPresent());
527 DCHECK(agent_.get());
528 VLOG(1) << device_path.value() << ": RequestPasskey";
530 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
531 if (!pairing) {
532 callback.Run(REJECTED, 0);
533 return;
536 pairing->RequestPasskey(callback);
539 void BluetoothAdapterChromeOS::DisplayPasskey(
540 const dbus::ObjectPath& device_path,
541 uint32 passkey,
542 uint16 entered) {
543 DCHECK(IsPresent());
544 DCHECK(agent_.get());
545 VLOG(1) << device_path.value() << ": DisplayPasskey: " << passkey
546 << " (" << entered << " entered)";
548 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
549 if (!pairing)
550 return;
552 if (entered == 0)
553 pairing->DisplayPasskey(passkey);
555 pairing->KeysEntered(entered);
558 void BluetoothAdapterChromeOS::RequestConfirmation(
559 const dbus::ObjectPath& device_path,
560 uint32 passkey,
561 const ConfirmationCallback& callback) {
562 DCHECK(IsPresent());
563 DCHECK(agent_.get());
564 VLOG(1) << device_path.value() << ": RequestConfirmation: " << passkey;
566 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
567 if (!pairing) {
568 callback.Run(REJECTED);
569 return;
572 pairing->RequestConfirmation(passkey, callback);
575 void BluetoothAdapterChromeOS::RequestAuthorization(
576 const dbus::ObjectPath& device_path,
577 const ConfirmationCallback& callback) {
578 DCHECK(IsPresent());
579 DCHECK(agent_.get());
580 VLOG(1) << device_path.value() << ": RequestAuthorization";
582 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
583 if (!pairing) {
584 callback.Run(REJECTED);
585 return;
588 pairing->RequestAuthorization(callback);
591 void BluetoothAdapterChromeOS::AuthorizeService(
592 const dbus::ObjectPath& device_path,
593 const std::string& uuid,
594 const ConfirmationCallback& callback) {
595 DCHECK(IsPresent());
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);
602 return;
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);
611 return;
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() {
622 DCHECK(IsPresent());
623 DCHECK(agent_.get());
624 VLOG(1) << "Cancel";
627 void BluetoothAdapterChromeOS::OnRegisterAgent() {
628 VLOG(1) << "Pairing agent registered, requesting to be made default";
630 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
631 RequestDefaultAgent(
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)
644 return;
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) {
665 if (!IsPresent()) {
666 VLOG(1) << "Failed to register audio sink, adapter not present";
667 error_callback.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER);
668 return;
670 DCHECK(audio_sink.get());
671 callback.Run(audio_sink);
674 BluetoothDeviceChromeOS*
675 BluetoothAdapterChromeOS::GetDeviceWithPath(
676 const dbus::ObjectPath& object_path) {
677 if (!IsPresent())
678 return nullptr;
680 for (DevicesMap::iterator iter = devices_.begin(); iter != devices_.end();
681 ++iter) {
682 BluetoothDeviceChromeOS* device_chromeos =
683 static_cast<BluetoothDeviceChromeOS*>(iter->second);
684 if (device_chromeos->object_path() == object_path)
685 return device_chromeos;
688 return nullptr;
691 BluetoothPairingChromeOS* BluetoothAdapterChromeOS::GetPairing(
692 const dbus::ObjectPath& object_path) {
693 DCHECK(IsPresent());
694 BluetoothDeviceChromeOS* device_chromeos = GetDeviceWithPath(object_path);
695 if (!device_chromeos) {
696 LOG(WARNING) << "Pairing Agent request for unknown device: "
697 << object_path.value();
698 return nullptr;
701 BluetoothPairingChromeOS* pairing = device_chromeos->GetPairing();
702 if (pairing)
703 return pairing;
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)
709 return nullptr;
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()->
723 RegisterAgent(
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) {
752 DeviceAdded(*iter);
756 void BluetoothAdapterChromeOS::SetDefaultAdapterName() {
757 DCHECK(IsPresent());
759 std::string alias;
760 switch (chromeos::GetDeviceType()) {
761 case DeviceType::kChromebase:
762 alias = "Chromebase";
763 break;
764 case DeviceType::kChromebit:
765 alias = "Chromebit";
766 break;
767 case DeviceType::kChromebook:
768 alias = "Chromebook";
769 break;
770 case DeviceType::kChromebox:
771 alias = "Chromebox";
772 break;
773 case DeviceType::kUnknown:
774 alias = "Chromebook";
775 break;
778 SetName(alias, base::Bind(&base::DoNothing), base::Bind(&base::DoNothing));
781 void BluetoothAdapterChromeOS::RemoveAdapter() {
782 DCHECK(IsPresent());
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_;
801 devices_.clear();
803 for (DevicesMap::iterator iter = devices.begin();
804 iter != devices.end(); ++iter) {
805 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
806 DeviceRemoved(this, iter->second));
807 delete 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(
824 bool discovering) {
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) {
845 DCHECK(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);
855 DCHECK_EQ(
856 static_cast<BluetoothDeviceChromeOS*>(service->GetDevice())->adapter_,
857 this);
859 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
860 observers_,
861 GattServiceAdded(this, service->GetDevice(), service));
864 void BluetoothAdapterChromeOS::NotifyGattServiceRemoved(
865 BluetoothRemoteGattServiceChromeOS* service) {
866 DCHECK_EQ(service->GetAdapter(), this);
867 DCHECK_EQ(
868 static_cast<BluetoothDeviceChromeOS*>(service->GetDevice())->adapter_,
869 this);
871 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
872 observers_,
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,
881 observers_,
882 GattServiceChanged(this, service));
885 void BluetoothAdapterChromeOS::NotifyGattDiscoveryComplete(
886 BluetoothRemoteGattServiceChromeOS* service) {
887 DCHECK_EQ(service->GetAdapter(), this);
889 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
890 observers_,
891 GattDiscoveryCompleteForService(this, service));
894 void BluetoothAdapterChromeOS::NotifyGattCharacteristicAdded(
895 BluetoothRemoteGattCharacteristicChromeOS* characteristic) {
896 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
897 characteristic->GetService())->GetAdapter(),
898 this);
900 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
901 observers_,
902 GattCharacteristicAdded(this, characteristic));
905 void BluetoothAdapterChromeOS::NotifyGattCharacteristicRemoved(
906 BluetoothRemoteGattCharacteristicChromeOS* characteristic) {
907 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
908 characteristic->GetService())->GetAdapter(),
909 this);
911 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
912 observers_,
913 GattCharacteristicRemoved(this, characteristic));
916 void BluetoothAdapterChromeOS::NotifyGattDescriptorAdded(
917 BluetoothRemoteGattDescriptorChromeOS* descriptor) {
918 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
919 descriptor->GetCharacteristic()->GetService())->GetAdapter(),
920 this);
922 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
923 observers_,
924 GattDescriptorAdded(this, descriptor));
927 void BluetoothAdapterChromeOS::NotifyGattDescriptorRemoved(
928 BluetoothRemoteGattDescriptorChromeOS* descriptor) {
929 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
930 descriptor->GetCharacteristic()->GetService())->GetAdapter(),
931 this);
933 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
934 observers_,
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(),
943 this);
945 FOR_EACH_OBSERVER(
946 BluetoothAdapter::Observer,
947 observers_,
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(),
956 this);
958 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
959 observers_,
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) {
970 DCHECK(delegate);
972 if (!IsPresent()) {
973 VLOG(2) << "Adapter not present, erroring out";
974 error_callback.Run("Adapter not present");
975 return;
978 if (profiles_.find(uuid) != profiles_.end()) {
979 // TODO(jamuraa) check that the options are the same and error when they are
980 // not.
981 SetProfileDelegate(uuid, device_path, delegate, success_callback,
982 error_callback);
983 return;
986 if (profile_queues_.find(uuid) == profile_queues_.end()) {
987 BluetoothAdapterProfileChromeOS::Register(
988 uuid, options,
989 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfile, this, uuid),
990 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfileError, this,
991 uuid));
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),
999 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())
1027 return;
1029 for (auto& it : *profile_queues_[uuid])
1030 it.first.Run();
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!");
1043 return;
1046 if (profiles_[uuid]->SetDelegate(device_path, delegate)) {
1047 success_callback.Run(profiles_[uuid]);
1048 return;
1050 // Already set
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())
1061 return;
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,
1073 bool success) {
1074 if (!IsPresent()) {
1075 error_callback.Run();
1076 return;
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(),
1086 callback,
1087 error_callback));
1090 void BluetoothAdapterChromeOS::OnPropertyChangeCompleted(
1091 const base::Closure& callback,
1092 const ErrorCallback& error_callback,
1093 bool success) {
1094 if (IsPresent() && success) {
1095 callback.Run();
1096 } else {
1097 error_callback.Run();
1101 void BluetoothAdapterChromeOS::AddDiscoverySession(
1102 BluetoothDiscoveryFilter* discovery_filter,
1103 const base::Closure& callback,
1104 const ErrorCallback& error_callback) {
1105 if (!IsPresent()) {
1106 error_callback.Run();
1107 return;
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));
1118 return;
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);
1129 return;
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);
1141 SetDiscoveryFilter(
1142 df.Pass(),
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));
1147 return;
1148 } else {
1149 current_filter_.reset();
1152 // This is the first request to start device discovery.
1153 discovery_request_pending_ = true;
1154 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1155 object_path_,
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) {
1166 if (!IsPresent()) {
1167 error_callback.Run();
1168 return;
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);
1180 return;
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();
1188 return;
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();
1198 return;
1201 // There is exactly one active discovery session. Request BlueZ to stop
1202 // discovery.
1203 DCHECK_EQ(num_discovery_sessions_, 1);
1204 discovery_request_pending_ = true;
1205 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1206 StopDiscovery(
1207 object_path_,
1208 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery,
1209 weak_ptr_factory_.GetWeakPtr(),
1210 callback),
1211 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError,
1212 weak_ptr_factory_.GetWeakPtr(),
1213 error_callback));
1216 void BluetoothAdapterChromeOS::SetDiscoveryFilter(
1217 scoped_ptr<BluetoothDiscoveryFilter> discovery_filter,
1218 const base::Closure& callback,
1219 const ErrorCallback& error_callback) {
1220 if (!IsPresent()) {
1221 error_callback.Run();
1222 return;
1225 // If old and new filter are equal (null) then don't make request, just call
1226 // succes callback
1227 if (!current_filter_ && !discovery_filter.get()) {
1228 callback.Run();
1229 return;
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)) {
1236 callback.Run();
1237 return;
1240 current_filter_.reset(discovery_filter.release());
1242 chromeos::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter;
1244 if (current_filter_.get()) {
1245 uint16_t pathloss;
1246 int16_t rssi;
1247 uint8_t transport;
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);
1268 if (uuids.size()) {
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_++;
1294 if (IsPresent()) {
1295 callback.Run();
1296 } else {
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 &&
1321 IsDiscovering()) {
1322 VLOG(1) << "Discovery previously initiated. Reporting success.";
1323 num_discovery_sessions_++;
1324 callback.Run();
1325 } else {
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_--;
1340 callback.Run();
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(
1373 object_path_,
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__;
1402 if (IsPresent()) {
1403 callback.Run();
1404 } else {
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 << ": "
1416 << error_message;
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
1434 // call returns.
1435 if (discovery_request_pending_)
1436 return;
1440 } // namespace chromeos