| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "device/bluetooth/bluetooth_adapter_win.h" |
| |
| #include <hash_set> |
| #include <string> |
| #include <utility> |
| |
| #include "base/logging.h" |
| #include "base/sequenced_task_runner.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/stl_util.h" |
| #include "base/thread_task_runner_handle.h" |
| #include "device/bluetooth/bluetooth_device_win.h" |
| #include "device/bluetooth/bluetooth_socket_thread.h" |
| #include "device/bluetooth/bluetooth_task_manager_win.h" |
| |
| namespace device { |
| |
| // static |
| base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( |
| const InitCallback& init_callback) { |
| return BluetoothAdapterWin::CreateAdapter(init_callback); |
| } |
| |
| // static |
| base::WeakPtr<BluetoothAdapter> BluetoothAdapterWin::CreateAdapter( |
| const InitCallback& init_callback) { |
| BluetoothAdapterWin* adapter = new BluetoothAdapterWin(init_callback); |
| adapter->Init(); |
| return adapter->weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| BluetoothAdapterWin::BluetoothAdapterWin(const InitCallback& init_callback) |
| : BluetoothAdapter(), |
| init_callback_(init_callback), |
| initialized_(false), |
| powered_(false), |
| discovery_status_(NOT_DISCOVERING), |
| num_discovery_listeners_(0), |
| weak_ptr_factory_(this) { |
| } |
| |
| BluetoothAdapterWin::~BluetoothAdapterWin() { |
| if (task_manager_) { |
| task_manager_->RemoveObserver(this); |
| task_manager_->Shutdown(); |
| } |
| } |
| |
| void BluetoothAdapterWin::AddObserver(BluetoothAdapter::Observer* observer) { |
| DCHECK(observer); |
| observers_.AddObserver(observer); |
| } |
| |
| void BluetoothAdapterWin::RemoveObserver(BluetoothAdapter::Observer* observer) { |
| DCHECK(observer); |
| observers_.RemoveObserver(observer); |
| } |
| |
| std::string BluetoothAdapterWin::GetAddress() const { |
| return address_; |
| } |
| |
| std::string BluetoothAdapterWin::GetName() const { |
| return name_; |
| } |
| |
| void BluetoothAdapterWin::SetName(const std::string& name, |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) { |
| NOTIMPLEMENTED(); |
| } |
| |
| // TODO(youngki): Return true when |task_manager_| initializes the adapter |
| // state. |
| bool BluetoothAdapterWin::IsInitialized() const { |
| return initialized_; |
| } |
| |
| bool BluetoothAdapterWin::IsPresent() const { |
| return !address_.empty(); |
| } |
| |
| bool BluetoothAdapterWin::IsPowered() const { |
| return powered_; |
| } |
| |
| void BluetoothAdapterWin::SetPowered( |
| bool powered, |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) { |
| task_manager_->PostSetPoweredBluetoothTask(powered, callback, error_callback); |
| } |
| |
| bool BluetoothAdapterWin::IsDiscoverable() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| void BluetoothAdapterWin::SetDiscoverable( |
| bool discoverable, |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) { |
| NOTIMPLEMENTED(); |
| } |
| |
| bool BluetoothAdapterWin::IsDiscovering() const { |
| return discovery_status_ == DISCOVERING || |
| discovery_status_ == DISCOVERY_STOPPING; |
| } |
| |
| void BluetoothAdapterWin::DiscoveryStarted(bool success) { |
| discovery_status_ = success ? DISCOVERING : NOT_DISCOVERING; |
| for (std::vector<std::pair<base::Closure, ErrorCallback> >::const_iterator |
| iter = on_start_discovery_callbacks_.begin(); |
| iter != on_start_discovery_callbacks_.end(); |
| ++iter) { |
| if (success) |
| ui_task_runner_->PostTask(FROM_HERE, iter->first); |
| else |
| ui_task_runner_->PostTask(FROM_HERE, iter->second); |
| } |
| num_discovery_listeners_ = on_start_discovery_callbacks_.size(); |
| on_start_discovery_callbacks_.clear(); |
| |
| if (success) { |
| FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| AdapterDiscoveringChanged(this, true)); |
| |
| // If there are stop discovery requests, post the stop discovery again. |
| MaybePostStopDiscoveryTask(); |
| } else if (!on_stop_discovery_callbacks_.empty()) { |
| // If there are stop discovery requests but start discovery has failed, |
| // notify that stop discovery has been complete. |
| DiscoveryStopped(); |
| } |
| } |
| |
| void BluetoothAdapterWin::DiscoveryStopped() { |
| discovered_devices_.clear(); |
| bool was_discovering = IsDiscovering(); |
| discovery_status_ = NOT_DISCOVERING; |
| for (std::vector<base::Closure>::const_iterator iter = |
| on_stop_discovery_callbacks_.begin(); |
| iter != on_stop_discovery_callbacks_.end(); |
| ++iter) { |
| ui_task_runner_->PostTask(FROM_HERE, *iter); |
| } |
| num_discovery_listeners_ = 0; |
| on_stop_discovery_callbacks_.clear(); |
| if (was_discovering) |
| FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| AdapterDiscoveringChanged(this, false)); |
| |
| // If there are start discovery requests, post the start discovery again. |
| MaybePostStartDiscoveryTask(); |
| } |
| |
| void BluetoothAdapterWin::ReadLocalOutOfBandPairingData( |
| const BluetoothOutOfBandPairingDataCallback& callback, |
| const ErrorCallback& error_callback) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void BluetoothAdapterWin::RemovePairingDelegateInternal( |
| BluetoothDevice::PairingDelegate* pairing_delegate) { |
| } |
| |
| void BluetoothAdapterWin::AdapterStateChanged( |
| const BluetoothTaskManagerWin::AdapterState& state) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| name_ = state.name; |
| bool was_present = IsPresent(); |
| bool is_present = !state.address.empty(); |
| address_ = state.address; |
| if (was_present != is_present) { |
| FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| AdapterPresentChanged(this, is_present)); |
| } |
| if (powered_ != state.powered) { |
| powered_ = state.powered; |
| FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| AdapterPoweredChanged(this, powered_)); |
| } |
| if (!initialized_) { |
| initialized_ = true; |
| init_callback_.Run(); |
| } |
| } |
| |
| void BluetoothAdapterWin::DevicesDiscovered( |
| const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter = |
| devices.begin(); |
| iter != devices.end(); |
| ++iter) { |
| if (discovered_devices_.find((*iter)->address) == |
| discovered_devices_.end()) { |
| BluetoothDeviceWin device_win( |
| **iter, ui_task_runner_, socket_thread_, NULL, net::NetLog::Source()); |
| FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
| DeviceAdded(this, &device_win)); |
| discovered_devices_.insert((*iter)->address); |
| } |
| } |
| } |
| |
| void BluetoothAdapterWin::DevicesUpdated( |
| const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices) { |
| STLDeleteValues(&devices_); |
| for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter = |
| devices.begin(); |
| iter != devices.end(); |
| ++iter) { |
| devices_[(*iter)->address] = new BluetoothDeviceWin( |
| **iter, ui_task_runner_, socket_thread_, NULL, net::NetLog::Source()); |
| } |
| } |
| |
| // If the method is called when |discovery_status_| is DISCOVERY_STOPPING, |
| // starting again is handled by BluetoothAdapterWin::DiscoveryStopped(). |
| void BluetoothAdapterWin::AddDiscoverySession( |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) { |
| if (discovery_status_ == DISCOVERING) { |
| num_discovery_listeners_++; |
| callback.Run(); |
| return; |
| } |
| on_start_discovery_callbacks_.push_back( |
| std::make_pair(callback, error_callback)); |
| MaybePostStartDiscoveryTask(); |
| } |
| |
| void BluetoothAdapterWin::RemoveDiscoverySession( |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) { |
| if (discovery_status_ == NOT_DISCOVERING) { |
| error_callback.Run(); |
| return; |
| } |
| on_stop_discovery_callbacks_.push_back(callback); |
| MaybePostStopDiscoveryTask(); |
| } |
| |
| void BluetoothAdapterWin::Init() { |
| ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| socket_thread_ = BluetoothSocketThread::Get(); |
| task_manager_ = |
| new BluetoothTaskManagerWin(ui_task_runner_); |
| task_manager_->AddObserver(this); |
| task_manager_->Initialize(); |
| } |
| |
| void BluetoothAdapterWin::InitForTest( |
| scoped_refptr<base::SequencedTaskRunner> ui_task_runner, |
| scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner) { |
| ui_task_runner_ = ui_task_runner; |
| task_manager_ = |
| new BluetoothTaskManagerWin(ui_task_runner_); |
| task_manager_->AddObserver(this); |
| task_manager_->InitializeWithBluetoothTaskRunner(bluetooth_task_runner); |
| } |
| |
| void BluetoothAdapterWin::MaybePostStartDiscoveryTask() { |
| if (discovery_status_ == NOT_DISCOVERING && |
| !on_start_discovery_callbacks_.empty()) { |
| discovery_status_ = DISCOVERY_STARTING; |
| task_manager_->PostStartDiscoveryTask(); |
| } |
| } |
| |
| void BluetoothAdapterWin::MaybePostStopDiscoveryTask() { |
| if (discovery_status_ != DISCOVERING) |
| return; |
| |
| if (on_stop_discovery_callbacks_.size() < num_discovery_listeners_) { |
| for (std::vector<base::Closure>::const_iterator iter = |
| on_stop_discovery_callbacks_.begin(); |
| iter != on_stop_discovery_callbacks_.end(); |
| ++iter) { |
| ui_task_runner_->PostTask(FROM_HERE, *iter); |
| } |
| num_discovery_listeners_ -= on_stop_discovery_callbacks_.size(); |
| on_stop_discovery_callbacks_.clear(); |
| return; |
| } |
| |
| discovery_status_ = DISCOVERY_STOPPING; |
| task_manager_->PostStopDiscoveryTask(); |
| } |
| |
| } // namespace device |