Extensions: Store disable reasons in Sync
[chromium-blink-merge.git] / device / bluetooth / bluetooth_adapter_chromeos.cc
bloba521c8f95a2f76d1d82bab850b349196a6cc6124
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/sys_info.h"
16 #include "base/thread_task_runner_handle.h"
17 #include "chromeos/dbus/bluetooth_adapter_client.h"
18 #include "chromeos/dbus/bluetooth_agent_manager_client.h"
19 #include "chromeos/dbus/bluetooth_agent_service_provider.h"
20 #include "chromeos/dbus/bluetooth_device_client.h"
21 #include "chromeos/dbus/bluetooth_input_client.h"
22 #include "chromeos/dbus/dbus_thread_manager.h"
23 #include "device/bluetooth/bluetooth_adapter_profile_chromeos.h"
24 #include "device/bluetooth/bluetooth_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();
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_ should be empty because all BluetoothSockets have been signaled
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 // Before removing a pairing delegate make sure that there aren't any devices
328 // currently using it; if there are, clear the pairing context which will
329 // make any responses no-ops.
330 for (DevicesMap::iterator iter = devices_.begin();
331 iter != devices_.end(); ++iter) {
332 BluetoothDeviceChromeOS* device_chromeos =
333 static_cast<BluetoothDeviceChromeOS*>(iter->second);
335 BluetoothPairingChromeOS* pairing = device_chromeos->GetPairing();
336 if (pairing && pairing->GetPairingDelegate() == pairing_delegate)
337 device_chromeos->EndPairing();
341 void BluetoothAdapterChromeOS::AdapterAdded(
342 const dbus::ObjectPath& object_path) {
343 // Set the adapter to the newly added adapter only if no adapter is present.
344 if (!IsPresent())
345 SetAdapter(object_path);
348 void BluetoothAdapterChromeOS::AdapterRemoved(
349 const dbus::ObjectPath& object_path) {
350 if (object_path == object_path_)
351 RemoveAdapter();
354 void BluetoothAdapterChromeOS::AdapterPropertyChanged(
355 const dbus::ObjectPath& object_path,
356 const std::string& property_name) {
357 if (object_path != object_path_)
358 return;
359 DCHECK(IsPresent());
361 BluetoothAdapterClient::Properties* properties =
362 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
363 GetProperties(object_path_);
365 if (property_name == properties->powered.name())
366 PoweredChanged(properties->powered.value());
367 else if (property_name == properties->discoverable.name())
368 DiscoverableChanged(properties->discoverable.value());
369 else if (property_name == properties->discovering.name())
370 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);
435 // When a device becomes paired, mark it as trusted so that the user does
436 // not need to approve every incoming connection
437 if (property_name == properties->paired.name() &&
438 properties->paired.value() && !properties->trusted.value())
439 device_chromeos->SetTrusted();
441 // UMA connection counting
442 if (property_name == properties->connected.name()) {
443 // PlayStation joystick tries to reconnect after disconnection from USB.
444 // If it is still not trusted, set it, so it becomes available on the
445 // list of known devices.
446 if (properties->connected.value() && device_chromeos->IsTrustable() &&
447 !properties->trusted.value())
448 device_chromeos->SetTrusted();
450 int count = 0;
452 for (DevicesMap::iterator iter = devices_.begin();
453 iter != devices_.end(); ++iter) {
454 if (iter->second->IsPaired() && iter->second->IsConnected())
455 ++count;
458 UMA_HISTOGRAM_COUNTS_100("Bluetooth.ConnectedDeviceCount", count);
462 void BluetoothAdapterChromeOS::InputPropertyChanged(
463 const dbus::ObjectPath& object_path,
464 const std::string& property_name) {
465 BluetoothDeviceChromeOS* device_chromeos = GetDeviceWithPath(object_path);
466 if (!device_chromeos)
467 return;
469 BluetoothInputClient::Properties* properties =
470 DBusThreadManager::Get()->GetBluetoothInputClient()->
471 GetProperties(object_path);
473 // Properties structure can be removed, which triggers a change in the
474 // BluetoothDevice::IsConnectable() property, as does a change in the
475 // actual reconnect_mode property.
476 if (!properties ||
477 property_name == properties->reconnect_mode.name())
478 NotifyDeviceChanged(device_chromeos);
481 void BluetoothAdapterChromeOS::Released() {
482 VLOG(1) << "Release";
483 if (!IsPresent())
484 return;
485 DCHECK(agent_.get());
487 // Called after we unregister the pairing agent, e.g. when changing I/O
488 // capabilities. Nothing much to be done right now.
491 void BluetoothAdapterChromeOS::RequestPinCode(
492 const dbus::ObjectPath& device_path,
493 const PinCodeCallback& callback) {
494 DCHECK(IsPresent());
495 DCHECK(agent_.get());
496 VLOG(1) << device_path.value() << ": RequestPinCode";
498 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
499 if (!pairing) {
500 callback.Run(REJECTED, "");
501 return;
504 pairing->RequestPinCode(callback);
507 void BluetoothAdapterChromeOS::DisplayPinCode(
508 const dbus::ObjectPath& device_path,
509 const std::string& pincode) {
510 DCHECK(IsPresent());
511 DCHECK(agent_.get());
512 VLOG(1) << device_path.value() << ": DisplayPinCode: " << pincode;
514 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
515 if (!pairing)
516 return;
518 pairing->DisplayPinCode(pincode);
521 void BluetoothAdapterChromeOS::RequestPasskey(
522 const dbus::ObjectPath& device_path,
523 const PasskeyCallback& callback) {
524 DCHECK(IsPresent());
525 DCHECK(agent_.get());
526 VLOG(1) << device_path.value() << ": RequestPasskey";
528 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
529 if (!pairing) {
530 callback.Run(REJECTED, 0);
531 return;
534 pairing->RequestPasskey(callback);
537 void BluetoothAdapterChromeOS::DisplayPasskey(
538 const dbus::ObjectPath& device_path,
539 uint32 passkey,
540 uint16 entered) {
541 DCHECK(IsPresent());
542 DCHECK(agent_.get());
543 VLOG(1) << device_path.value() << ": DisplayPasskey: " << passkey
544 << " (" << entered << " entered)";
546 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
547 if (!pairing)
548 return;
550 if (entered == 0)
551 pairing->DisplayPasskey(passkey);
553 pairing->KeysEntered(entered);
556 void BluetoothAdapterChromeOS::RequestConfirmation(
557 const dbus::ObjectPath& device_path,
558 uint32 passkey,
559 const ConfirmationCallback& callback) {
560 DCHECK(IsPresent());
561 DCHECK(agent_.get());
562 VLOG(1) << device_path.value() << ": RequestConfirmation: " << passkey;
564 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
565 if (!pairing) {
566 callback.Run(REJECTED);
567 return;
570 pairing->RequestConfirmation(passkey, callback);
573 void BluetoothAdapterChromeOS::RequestAuthorization(
574 const dbus::ObjectPath& device_path,
575 const ConfirmationCallback& callback) {
576 DCHECK(IsPresent());
577 DCHECK(agent_.get());
578 VLOG(1) << device_path.value() << ": RequestAuthorization";
580 BluetoothPairingChromeOS* pairing = GetPairing(device_path);
581 if (!pairing) {
582 callback.Run(REJECTED);
583 return;
586 pairing->RequestAuthorization(callback);
589 void BluetoothAdapterChromeOS::AuthorizeService(
590 const dbus::ObjectPath& device_path,
591 const std::string& uuid,
592 const ConfirmationCallback& callback) {
593 DCHECK(IsPresent());
594 DCHECK(agent_.get());
595 VLOG(1) << device_path.value() << ": AuthorizeService: " << uuid;
597 BluetoothDeviceChromeOS* device_chromeos = GetDeviceWithPath(device_path);
598 if (!device_chromeos) {
599 callback.Run(CANCELLED);
600 return;
603 // We always set paired devices to Trusted, so the only reason that this
604 // method call would ever be called is in the case of a race condition where
605 // our "Set('Trusted', true)" method call is still pending in the Bluetooth
606 // daemon because it's busy handling the incoming connection.
607 if (device_chromeos->IsPaired()) {
608 callback.Run(SUCCESS);
609 return;
612 // TODO(keybuk): reject service authorizations when not paired, determine
613 // whether this is acceptable long-term.
614 LOG(WARNING) << "Rejecting service connection from unpaired device "
615 << device_chromeos->GetAddress() << " for UUID " << uuid;
616 callback.Run(REJECTED);
619 void BluetoothAdapterChromeOS::Cancel() {
620 DCHECK(IsPresent());
621 DCHECK(agent_.get());
622 VLOG(1) << "Cancel";
625 void BluetoothAdapterChromeOS::OnRegisterAgent() {
626 VLOG(1) << "Pairing agent registered, requesting to be made default";
628 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
629 RequestDefaultAgent(
630 dbus::ObjectPath(kAgentPath),
631 base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgent,
632 weak_ptr_factory_.GetWeakPtr()),
633 base::Bind(&BluetoothAdapterChromeOS::OnRequestDefaultAgentError,
634 weak_ptr_factory_.GetWeakPtr()));
637 void BluetoothAdapterChromeOS::OnRegisterAgentError(
638 const std::string& error_name,
639 const std::string& error_message) {
640 // Our agent being already registered isn't an error.
641 if (error_name == bluetooth_agent_manager::kErrorAlreadyExists)
642 return;
644 LOG(WARNING) << ": Failed to register pairing agent: "
645 << error_name << ": " << error_message;
648 void BluetoothAdapterChromeOS::OnRequestDefaultAgent() {
649 VLOG(1) << "Pairing agent now default";
652 void BluetoothAdapterChromeOS::OnRequestDefaultAgentError(
653 const std::string& error_name,
654 const std::string& error_message) {
655 LOG(WARNING) << ": Failed to make pairing agent default: "
656 << error_name << ": " << error_message;
659 void BluetoothAdapterChromeOS::OnRegisterAudioSink(
660 const device::BluetoothAdapter::AcquiredCallback& callback,
661 const device::BluetoothAudioSink::ErrorCallback& error_callback,
662 scoped_refptr<BluetoothAudioSink> audio_sink) {
663 if (!IsPresent()) {
664 VLOG(1) << "Failed to register audio sink, adapter not present";
665 error_callback.Run(BluetoothAudioSink::ERROR_INVALID_ADAPTER);
666 return;
668 DCHECK(audio_sink.get());
669 callback.Run(audio_sink);
672 BluetoothDeviceChromeOS*
673 BluetoothAdapterChromeOS::GetDeviceWithPath(
674 const dbus::ObjectPath& object_path) {
675 if (!IsPresent())
676 return NULL;
678 for (DevicesMap::iterator iter = devices_.begin(); iter != devices_.end();
679 ++iter) {
680 BluetoothDeviceChromeOS* device_chromeos =
681 static_cast<BluetoothDeviceChromeOS*>(iter->second);
682 if (device_chromeos->object_path() == object_path)
683 return device_chromeos;
686 return NULL;
689 BluetoothPairingChromeOS* BluetoothAdapterChromeOS::GetPairing(
690 const dbus::ObjectPath& object_path) {
691 DCHECK(IsPresent());
692 BluetoothDeviceChromeOS* device_chromeos = GetDeviceWithPath(object_path);
693 if (!device_chromeos) {
694 LOG(WARNING) << "Pairing Agent request for unknown device: "
695 << object_path.value();
696 return NULL;
699 BluetoothPairingChromeOS* pairing = device_chromeos->GetPairing();
700 if (pairing)
701 return pairing;
703 // The device doesn't have its own pairing context, so this is an incoming
704 // pairing request that should use our best default delegate (if we have one).
705 BluetoothDevice::PairingDelegate* pairing_delegate = DefaultPairingDelegate();
706 if (!pairing_delegate)
707 return NULL;
709 return device_chromeos->BeginPairing(pairing_delegate);
712 void BluetoothAdapterChromeOS::SetAdapter(const dbus::ObjectPath& object_path) {
713 DCHECK(!IsPresent());
714 DCHECK(!dbus_is_shutdown_);
715 object_path_ = object_path;
717 VLOG(1) << object_path_.value() << ": using adapter.";
719 VLOG(1) << "Registering pairing agent";
720 DBusThreadManager::Get()->GetBluetoothAgentManagerClient()->
721 RegisterAgent(
722 dbus::ObjectPath(kAgentPath),
723 bluetooth_agent_manager::kKeyboardDisplayCapability,
724 base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgent,
725 weak_ptr_factory_.GetWeakPtr()),
726 base::Bind(&BluetoothAdapterChromeOS::OnRegisterAgentError,
727 weak_ptr_factory_.GetWeakPtr()));
729 SetDefaultAdapterName();
731 BluetoothAdapterClient::Properties* properties =
732 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
733 GetProperties(object_path_);
735 PresentChanged(true);
737 if (properties->powered.value())
738 PoweredChanged(true);
739 if (properties->discoverable.value())
740 DiscoverableChanged(true);
741 if (properties->discovering.value())
742 DiscoveringChanged(true);
744 std::vector<dbus::ObjectPath> device_paths =
745 DBusThreadManager::Get()->GetBluetoothDeviceClient()->
746 GetDevicesForAdapter(object_path_);
748 for (std::vector<dbus::ObjectPath>::iterator iter = device_paths.begin();
749 iter != device_paths.end(); ++iter) {
750 DeviceAdded(*iter);
754 void BluetoothAdapterChromeOS::SetDefaultAdapterName() {
755 DCHECK(IsPresent());
756 std::string board = base::SysInfo::GetLsbReleaseBoard();
757 std::string alias;
758 if (board.substr(0, 6) == "stumpy") {
759 alias = "Chromebox";
760 } else if (board.substr(0, 4) == "link") {
761 alias = "Chromebook Pixel";
762 } else {
763 alias = "Chromebook";
766 SetName(alias, base::Bind(&base::DoNothing), base::Bind(&base::DoNothing));
769 void BluetoothAdapterChromeOS::RemoveAdapter() {
770 DCHECK(IsPresent());
771 VLOG(1) << object_path_.value() << ": adapter removed.";
773 BluetoothAdapterClient::Properties* properties =
774 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
775 GetProperties(object_path_);
777 object_path_ = dbus::ObjectPath("");
779 if (properties->powered.value())
780 PoweredChanged(false);
781 if (properties->discoverable.value())
782 DiscoverableChanged(false);
783 if (properties->discovering.value())
784 DiscoveringChanged(false);
786 // Copy the devices list here and clear the original so that when we
787 // send DeviceRemoved(), GetDevices() returns no devices.
788 DevicesMap devices = devices_;
789 devices_.clear();
791 for (DevicesMap::iterator iter = devices.begin();
792 iter != devices.end(); ++iter) {
793 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
794 DeviceRemoved(this, iter->second));
795 delete iter->second;
798 PresentChanged(false);
801 void BluetoothAdapterChromeOS::PoweredChanged(bool powered) {
802 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
803 AdapterPoweredChanged(this, powered));
806 void BluetoothAdapterChromeOS::DiscoverableChanged(bool discoverable) {
807 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
808 AdapterDiscoverableChanged(this, discoverable));
811 void BluetoothAdapterChromeOS::DiscoveringChanged(
812 bool discovering) {
813 // If the adapter stopped discovery due to a reason other than a request by
814 // us, reset the count to 0.
815 VLOG(1) << "Discovering changed: " << discovering;
816 if (!discovering && !discovery_request_pending_
817 && num_discovery_sessions_ > 0) {
818 VLOG(1) << "Marking sessions as inactive.";
819 num_discovery_sessions_ = 0;
820 MarkDiscoverySessionsAsInactive();
822 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
823 AdapterDiscoveringChanged(this, discovering));
826 void BluetoothAdapterChromeOS::PresentChanged(bool present) {
827 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
828 AdapterPresentChanged(this, present));
831 void BluetoothAdapterChromeOS::NotifyDeviceChanged(
832 BluetoothDeviceChromeOS* device) {
833 DCHECK(device->adapter_ == this);
835 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
836 DeviceChanged(this, device));
839 void BluetoothAdapterChromeOS::NotifyGattServiceAdded(
840 BluetoothRemoteGattServiceChromeOS* service) {
841 DCHECK_EQ(service->GetAdapter(), this);
842 DCHECK_EQ(
843 static_cast<BluetoothDeviceChromeOS*>(service->GetDevice())->adapter_,
844 this);
846 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
847 observers_,
848 GattServiceAdded(this, service->GetDevice(), service));
851 void BluetoothAdapterChromeOS::NotifyGattServiceRemoved(
852 BluetoothRemoteGattServiceChromeOS* service) {
853 DCHECK_EQ(service->GetAdapter(), this);
854 DCHECK_EQ(
855 static_cast<BluetoothDeviceChromeOS*>(service->GetDevice())->adapter_,
856 this);
858 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
859 observers_,
860 GattServiceRemoved(this, service->GetDevice(), service));
863 void BluetoothAdapterChromeOS::NotifyGattServiceChanged(
864 BluetoothRemoteGattServiceChromeOS* service) {
865 DCHECK_EQ(service->GetAdapter(), this);
867 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
868 observers_,
869 GattServiceChanged(this, service));
872 void BluetoothAdapterChromeOS::NotifyGattDiscoveryComplete(
873 BluetoothRemoteGattServiceChromeOS* service) {
874 DCHECK_EQ(service->GetAdapter(), this);
876 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
877 observers_,
878 GattDiscoveryCompleteForService(this, service));
881 void BluetoothAdapterChromeOS::NotifyGattCharacteristicAdded(
882 BluetoothRemoteGattCharacteristicChromeOS* characteristic) {
883 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
884 characteristic->GetService())->GetAdapter(),
885 this);
887 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
888 observers_,
889 GattCharacteristicAdded(this, characteristic));
892 void BluetoothAdapterChromeOS::NotifyGattCharacteristicRemoved(
893 BluetoothRemoteGattCharacteristicChromeOS* characteristic) {
894 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
895 characteristic->GetService())->GetAdapter(),
896 this);
898 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
899 observers_,
900 GattCharacteristicRemoved(this, characteristic));
903 void BluetoothAdapterChromeOS::NotifyGattDescriptorAdded(
904 BluetoothRemoteGattDescriptorChromeOS* descriptor) {
905 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
906 descriptor->GetCharacteristic()->GetService())->GetAdapter(),
907 this);
909 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
910 observers_,
911 GattDescriptorAdded(this, descriptor));
914 void BluetoothAdapterChromeOS::NotifyGattDescriptorRemoved(
915 BluetoothRemoteGattDescriptorChromeOS* descriptor) {
916 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
917 descriptor->GetCharacteristic()->GetService())->GetAdapter(),
918 this);
920 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
921 observers_,
922 GattDescriptorRemoved(this, descriptor));
925 void BluetoothAdapterChromeOS::NotifyGattCharacteristicValueChanged(
926 BluetoothRemoteGattCharacteristicChromeOS* characteristic,
927 const std::vector<uint8>& value) {
928 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
929 characteristic->GetService())->GetAdapter(),
930 this);
932 FOR_EACH_OBSERVER(
933 BluetoothAdapter::Observer,
934 observers_,
935 GattCharacteristicValueChanged(this, characteristic, value));
938 void BluetoothAdapterChromeOS::NotifyGattDescriptorValueChanged(
939 BluetoothRemoteGattDescriptorChromeOS* descriptor,
940 const std::vector<uint8>& value) {
941 DCHECK_EQ(static_cast<BluetoothRemoteGattServiceChromeOS*>(
942 descriptor->GetCharacteristic()->GetService())->GetAdapter(),
943 this);
945 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
946 observers_,
947 GattDescriptorValueChanged(this, descriptor, value));
950 void BluetoothAdapterChromeOS::UseProfile(
951 const BluetoothUUID& uuid,
952 const dbus::ObjectPath& device_path,
953 const BluetoothProfileManagerClient::Options& options,
954 BluetoothProfileServiceProvider::Delegate* delegate,
955 const ProfileRegisteredCallback& success_callback,
956 const ErrorCompletionCallback& error_callback) {
957 DCHECK(delegate);
959 if (!IsPresent()) {
960 VLOG(2) << "Adapter not present, erroring out";
961 error_callback.Run("Adapter not present");
962 return;
965 if (profiles_.find(uuid) != profiles_.end()) {
966 // TODO(jamuraa) check that the options are the same and error when they are
967 // not.
968 SetProfileDelegate(uuid, device_path, delegate, success_callback,
969 error_callback);
970 return;
973 if (profile_queues_.find(uuid) == profile_queues_.end()) {
974 BluetoothAdapterProfileChromeOS::Register(
975 uuid, options,
976 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfile, this, uuid),
977 base::Bind(&BluetoothAdapterChromeOS::OnRegisterProfileError, this,
978 uuid));
980 profile_queues_[uuid] = new std::vector<RegisterProfileCompletionPair>();
983 profile_queues_[uuid]->push_back(std::make_pair(
984 base::Bind(&BluetoothAdapterChromeOS::SetProfileDelegate, this, uuid,
985 device_path, delegate, success_callback, error_callback),
986 error_callback));
989 void BluetoothAdapterChromeOS::ReleaseProfile(
990 const dbus::ObjectPath& device_path,
991 BluetoothAdapterProfileChromeOS* profile) {
992 VLOG(2) << "Releasing Profile: " << profile->uuid().canonical_value()
993 << " from " << device_path.value();
994 profile->RemoveDelegate(
995 device_path, base::Bind(&BluetoothAdapterChromeOS::RemoveProfile,
996 weak_ptr_factory_.GetWeakPtr(), profile->uuid()));
999 void BluetoothAdapterChromeOS::RemoveProfile(const BluetoothUUID& uuid) {
1000 VLOG(2) << "Remove Profile: " << uuid.canonical_value();
1002 if (profiles_.find(uuid) != profiles_.end()) {
1003 delete profiles_[uuid];
1004 profiles_.erase(uuid);
1008 void BluetoothAdapterChromeOS::OnRegisterProfile(
1009 const BluetoothUUID& uuid,
1010 scoped_ptr<BluetoothAdapterProfileChromeOS> profile) {
1011 profiles_[uuid] = profile.release();
1013 if (profile_queues_.find(uuid) == profile_queues_.end())
1014 return;
1016 for (auto& it : *profile_queues_[uuid])
1017 it.first.Run();
1018 delete profile_queues_[uuid];
1019 profile_queues_.erase(uuid);
1022 void BluetoothAdapterChromeOS::SetProfileDelegate(
1023 const BluetoothUUID& uuid,
1024 const dbus::ObjectPath& device_path,
1025 BluetoothProfileServiceProvider::Delegate* delegate,
1026 const ProfileRegisteredCallback& success_callback,
1027 const ErrorCompletionCallback& error_callback) {
1028 if (profiles_.find(uuid) == profiles_.end()) {
1029 error_callback.Run("Cannot find profile!");
1030 return;
1033 if (profiles_[uuid]->SetDelegate(device_path, delegate)) {
1034 success_callback.Run(profiles_[uuid]);
1035 return;
1037 // Already set
1038 error_callback.Run(bluetooth_agent_manager::kErrorAlreadyExists);
1041 void BluetoothAdapterChromeOS::OnRegisterProfileError(
1042 const BluetoothUUID& uuid,
1043 const std::string& error_name,
1044 const std::string& error_message) {
1045 VLOG(2) << object_path_.value() << ": Failed to register profile: "
1046 << error_name << ": " << error_message;
1047 if (profile_queues_.find(uuid) == profile_queues_.end())
1048 return;
1050 for (auto& it : *profile_queues_[uuid])
1051 it.second.Run(error_message);
1053 delete profile_queues_[uuid];
1054 profile_queues_.erase(uuid);
1057 void BluetoothAdapterChromeOS::OnSetDiscoverable(
1058 const base::Closure& callback,
1059 const ErrorCallback& error_callback,
1060 bool success) {
1061 if (!IsPresent()) {
1062 error_callback.Run();
1063 return;
1066 // Set the discoverable_timeout property to zero so the adapter remains
1067 // discoverable forever.
1068 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1069 GetProperties(object_path_)->discoverable_timeout.Set(
1071 base::Bind(&BluetoothAdapterChromeOS::OnPropertyChangeCompleted,
1072 weak_ptr_factory_.GetWeakPtr(),
1073 callback,
1074 error_callback));
1077 void BluetoothAdapterChromeOS::OnPropertyChangeCompleted(
1078 const base::Closure& callback,
1079 const ErrorCallback& error_callback,
1080 bool success) {
1081 if (IsPresent() && success)
1082 callback.Run();
1083 else
1084 error_callback.Run();
1087 void BluetoothAdapterChromeOS::AddDiscoverySession(
1088 BluetoothDiscoveryFilter* discovery_filter,
1089 const base::Closure& callback,
1090 const ErrorCallback& error_callback) {
1091 if (!IsPresent()) {
1092 error_callback.Run();
1093 return;
1095 VLOG(1) << __func__;
1096 if (discovery_request_pending_) {
1097 // The pending request is either to stop a previous session or to start a
1098 // new one. Either way, queue this one.
1099 DCHECK(num_discovery_sessions_ == 1 || num_discovery_sessions_ == 0);
1100 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1101 << "request to start a new discovery session.";
1102 discovery_request_queue_.push(
1103 std::make_tuple(discovery_filter, callback, error_callback));
1104 return;
1107 // The adapter is already discovering.
1108 if (num_discovery_sessions_ > 0) {
1109 DCHECK(IsDiscovering());
1110 DCHECK(!discovery_request_pending_);
1111 num_discovery_sessions_++;
1112 SetDiscoveryFilter(BluetoothDiscoveryFilter::Merge(
1113 GetMergedDiscoveryFilter().get(), discovery_filter),
1114 callback, error_callback);
1115 return;
1118 // There are no active discovery sessions.
1119 DCHECK_EQ(num_discovery_sessions_, 0);
1121 if (discovery_filter) {
1122 discovery_request_pending_ = true;
1124 scoped_ptr<BluetoothDiscoveryFilter> df(new BluetoothDiscoveryFilter(
1125 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL));
1126 df->CopyFrom(*discovery_filter);
1127 SetDiscoveryFilter(
1128 df.Pass(),
1129 base::Bind(&BluetoothAdapterChromeOS::OnPreSetDiscoveryFilter,
1130 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
1131 base::Bind(&BluetoothAdapterChromeOS::OnPreSetDiscoveryFilterError,
1132 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1133 return;
1134 } else
1135 current_filter_.reset();
1137 // This is the first request to start device discovery.
1138 discovery_request_pending_ = true;
1139 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1140 object_path_,
1141 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery,
1142 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
1143 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError,
1144 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1147 void BluetoothAdapterChromeOS::RemoveDiscoverySession(
1148 BluetoothDiscoveryFilter* discovery_filter,
1149 const base::Closure& callback,
1150 const ErrorCallback& error_callback) {
1151 if (!IsPresent()) {
1152 error_callback.Run();
1153 return;
1156 VLOG(1) << __func__;
1157 // There are active sessions other than the one currently being removed.
1158 if (num_discovery_sessions_ > 1) {
1159 DCHECK(IsDiscovering());
1160 DCHECK(!discovery_request_pending_);
1161 num_discovery_sessions_--;
1163 SetDiscoveryFilter(GetMergedDiscoveryFilterMasked(discovery_filter),
1164 callback, error_callback);
1165 return;
1168 // If there is a pending request to BlueZ, then queue this request.
1169 if (discovery_request_pending_) {
1170 VLOG(1) << "Pending request to start/stop device discovery. Queueing "
1171 << "request to stop discovery session.";
1172 error_callback.Run();
1173 return;
1176 // There are no active sessions. Return error.
1177 if (num_discovery_sessions_ == 0) {
1178 // TODO(armansito): This should never happen once we have the
1179 // DiscoverySession API. Replace this case with an assert once it's
1180 // the deprecated methods have been removed. (See crbug.com/3445008).
1181 VLOG(1) << "No active discovery sessions. Returning error.";
1182 error_callback.Run();
1183 return;
1186 // There is exactly one active discovery session. Request BlueZ to stop
1187 // discovery.
1188 DCHECK_EQ(num_discovery_sessions_, 1);
1189 discovery_request_pending_ = true;
1190 DBusThreadManager::Get()->GetBluetoothAdapterClient()->
1191 StopDiscovery(
1192 object_path_,
1193 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscovery,
1194 weak_ptr_factory_.GetWeakPtr(),
1195 callback),
1196 base::Bind(&BluetoothAdapterChromeOS::OnStopDiscoveryError,
1197 weak_ptr_factory_.GetWeakPtr(),
1198 error_callback));
1201 void BluetoothAdapterChromeOS::SetDiscoveryFilter(
1202 scoped_ptr<BluetoothDiscoveryFilter> discovery_filter,
1203 const base::Closure& callback,
1204 const ErrorCallback& error_callback) {
1205 if (!IsPresent()) {
1206 error_callback.Run();
1207 return;
1210 // If old and new filter are equal (null) then don't make request, just call
1211 // succes callback
1212 if (!current_filter_ && !discovery_filter.get()) {
1213 callback.Run();
1214 return;
1217 // If old and new filter are not null and equal then don't make request, just
1218 // call succes callback
1219 if (current_filter_ && discovery_filter &&
1220 current_filter_->Equals(*discovery_filter)) {
1221 callback.Run();
1222 return;
1225 current_filter_.reset(discovery_filter.release());
1227 chromeos::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter;
1229 if (current_filter_.get()) {
1230 uint16_t pathloss;
1231 int16_t rssi;
1232 uint8_t transport;
1233 std::set<device::BluetoothUUID> uuids;
1235 if (current_filter_->GetPathloss(&pathloss))
1236 dbus_discovery_filter.pathloss.reset(new uint16_t(pathloss));
1238 if (current_filter_->GetRSSI(&rssi))
1239 dbus_discovery_filter.rssi.reset(new int16_t(rssi));
1241 transport = current_filter_->GetTransport();
1242 if (transport == BluetoothDiscoveryFilter::Transport::TRANSPORT_LE) {
1243 dbus_discovery_filter.transport.reset(new std::string("le"));
1244 } else if (transport ==
1245 BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC) {
1246 dbus_discovery_filter.transport.reset(new std::string("bredr"));
1247 } else if (transport ==
1248 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL) {
1249 dbus_discovery_filter.transport.reset(new std::string("auto"));
1252 current_filter_->GetUUIDs(uuids);
1253 if (uuids.size()) {
1254 dbus_discovery_filter.uuids =
1255 scoped_ptr<std::vector<std::string>>(new std::vector<std::string>);
1257 for (const auto& it : uuids)
1258 dbus_discovery_filter.uuids.get()->push_back(it.value());
1262 DBusThreadManager::Get()->GetBluetoothAdapterClient()->SetDiscoveryFilter(
1263 object_path_, dbus_discovery_filter,
1264 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilter,
1265 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
1266 base::Bind(&BluetoothAdapterChromeOS::OnSetDiscoveryFilterError,
1267 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1270 void BluetoothAdapterChromeOS::OnStartDiscovery(
1271 const base::Closure& callback,
1272 const ErrorCallback& error_callback) {
1273 // Report success on the original request and increment the count.
1274 VLOG(1) << __func__;
1275 DCHECK(discovery_request_pending_);
1276 DCHECK_EQ(num_discovery_sessions_, 0);
1277 discovery_request_pending_ = false;
1278 num_discovery_sessions_++;
1279 if (IsPresent())
1280 callback.Run();
1281 else
1282 error_callback.Run();
1284 // Try to add a new discovery session for each queued request.
1285 ProcessQueuedDiscoveryRequests();
1288 void BluetoothAdapterChromeOS::OnStartDiscoveryError(
1289 const base::Closure& callback,
1290 const ErrorCallback& error_callback,
1291 const std::string& error_name,
1292 const std::string& error_message) {
1293 LOG(WARNING) << object_path_.value() << ": Failed to start discovery: "
1294 << error_name << ": " << error_message;
1296 // Failed to start discovery. This can only happen if the count is at 0.
1297 DCHECK_EQ(num_discovery_sessions_, 0);
1298 DCHECK(discovery_request_pending_);
1299 discovery_request_pending_ = false;
1301 // Discovery request may fail if discovery was previously initiated by Chrome,
1302 // but the session were invalidated due to the discovery state unexpectedly
1303 // changing to false and then back to true. In this case, report success.
1304 if (IsPresent() && error_name == bluetooth_device::kErrorInProgress &&
1305 IsDiscovering()) {
1306 VLOG(1) << "Discovery previously initiated. Reporting success.";
1307 num_discovery_sessions_++;
1308 callback.Run();
1309 } else {
1310 error_callback.Run();
1313 // Try to add a new discovery session for each queued request.
1314 ProcessQueuedDiscoveryRequests();
1317 void BluetoothAdapterChromeOS::OnStopDiscovery(const base::Closure& callback) {
1318 // Report success on the original request and decrement the count.
1319 VLOG(1) << __func__;
1320 DCHECK(discovery_request_pending_);
1321 DCHECK_EQ(num_discovery_sessions_, 1);
1322 discovery_request_pending_ = false;
1323 num_discovery_sessions_--;
1324 callback.Run();
1326 current_filter_.reset();
1328 // Try to add a new discovery session for each queued request.
1329 ProcessQueuedDiscoveryRequests();
1332 void BluetoothAdapterChromeOS::OnStopDiscoveryError(
1333 const ErrorCallback& error_callback,
1334 const std::string& error_name,
1335 const std::string& error_message) {
1336 LOG(WARNING) << object_path_.value() << ": Failed to stop discovery: "
1337 << error_name << ": " << error_message;
1339 // Failed to stop discovery. This can only happen if the count is at 1.
1340 DCHECK(discovery_request_pending_);
1341 DCHECK_EQ(num_discovery_sessions_, 1);
1342 discovery_request_pending_ = false;
1343 error_callback.Run();
1345 // Try to add a new discovery session for each queued request.
1346 ProcessQueuedDiscoveryRequests();
1349 void BluetoothAdapterChromeOS::OnPreSetDiscoveryFilter(
1350 const base::Closure& callback,
1351 const ErrorCallback& error_callback) {
1352 // This is the first request to start device discovery.
1353 DCHECK(discovery_request_pending_);
1354 DCHECK_EQ(num_discovery_sessions_, 0);
1356 DBusThreadManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
1357 object_path_,
1358 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscovery,
1359 weak_ptr_factory_.GetWeakPtr(), callback, error_callback),
1360 base::Bind(&BluetoothAdapterChromeOS::OnStartDiscoveryError,
1361 weak_ptr_factory_.GetWeakPtr(), callback, error_callback));
1364 void BluetoothAdapterChromeOS::OnPreSetDiscoveryFilterError(
1365 const base::Closure& callback,
1366 const ErrorCallback& error_callback) {
1367 LOG(WARNING) << object_path_.value()
1368 << ": Failed to pre set discovery filter.";
1370 // Failed to start discovery. This can only happen if the count is at 0.
1371 DCHECK_EQ(num_discovery_sessions_, 0);
1372 DCHECK(discovery_request_pending_);
1373 discovery_request_pending_ = false;
1375 error_callback.Run();
1377 // Try to add a new discovery session for each queued request.
1378 ProcessQueuedDiscoveryRequests();
1381 void BluetoothAdapterChromeOS::OnSetDiscoveryFilter(
1382 const base::Closure& callback,
1383 const ErrorCallback& error_callback) {
1384 // Report success on the original request and increment the count.
1385 VLOG(1) << __func__;
1386 if (IsPresent())
1387 callback.Run();
1388 else
1389 error_callback.Run();
1392 void BluetoothAdapterChromeOS::OnSetDiscoveryFilterError(
1393 const base::Closure& callback,
1394 const ErrorCallback& error_callback,
1395 const std::string& error_name,
1396 const std::string& error_message) {
1397 LOG(WARNING) << object_path_.value()
1398 << ": Failed to set discovery filter: " << error_name << ": "
1399 << error_message;
1401 error_callback.Run();
1403 // Try to add a new discovery session for each queued request.
1404 ProcessQueuedDiscoveryRequests();
1407 void BluetoothAdapterChromeOS::ProcessQueuedDiscoveryRequests() {
1408 while (!discovery_request_queue_.empty()) {
1409 VLOG(1) << "Process queued discovery request.";
1410 DiscoveryParamTuple params = discovery_request_queue_.front();
1411 discovery_request_queue_.pop();
1412 AddDiscoverySession(std::get<0>(params), std::get<1>(params),
1413 std::get<2>(params));
1415 // If the queued request resulted in a pending call, then let it
1416 // asynchonously process the remaining queued requests once the pending
1417 // call returns.
1418 if (discovery_request_pending_)
1419 return;
1423 } // namespace chromeos