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