1// Copyright (c) 2012 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.
4
5#include "device/bluetooth/bluetooth_adapter_win.h"
6
7#include <hash_set>
8#include <string>
9#include <utility>
10
11#include "base/logging.h"
12#include "base/sequenced_task_runner.h"
13#include "base/single_thread_task_runner.h"
14#include "base/stl_util.h"
15#include "base/thread_task_runner_handle.h"
16#include "device/bluetooth/bluetooth_device_win.h"
17#include "device/bluetooth/bluetooth_task_manager_win.h"
18
19namespace device {
20
21BluetoothAdapterWin::BluetoothAdapterWin(const InitCallback& init_callback)
22    : BluetoothAdapter(),
23      init_callback_(init_callback),
24      initialized_(false),
25      powered_(false),
26      discovery_status_(NOT_DISCOVERING),
27      num_discovery_listeners_(0),
28      weak_ptr_factory_(this) {
29}
30
31BluetoothAdapterWin::~BluetoothAdapterWin() {
32  if (task_manager_) {
33    task_manager_->RemoveObserver(this);
34    task_manager_->Shutdown();
35  }
36}
37
38void BluetoothAdapterWin::AddObserver(BluetoothAdapter::Observer* observer) {
39  DCHECK(observer);
40  observers_.AddObserver(observer);
41}
42
43void BluetoothAdapterWin::RemoveObserver(BluetoothAdapter::Observer* observer) {
44  DCHECK(observer);
45  observers_.RemoveObserver(observer);
46}
47
48std::string BluetoothAdapterWin::GetAddress() const {
49  return address_;
50}
51
52std::string BluetoothAdapterWin::GetName() const {
53  return name_;
54}
55
56// TODO(youngki): Return true when |task_manager_| initializes the adapter
57// state.
58bool BluetoothAdapterWin::IsInitialized() const {
59  return initialized_;
60}
61
62bool BluetoothAdapterWin::IsPresent() const {
63  return !address_.empty();
64}
65
66bool BluetoothAdapterWin::IsPowered() const {
67  return powered_;
68}
69
70void BluetoothAdapterWin::SetPowered(
71    bool powered,
72    const base::Closure& callback,
73    const ErrorCallback& error_callback) {
74  task_manager_->PostSetPoweredBluetoothTask(powered, callback, error_callback);
75}
76
77bool BluetoothAdapterWin::IsDiscovering() const {
78  return discovery_status_ == DISCOVERING ||
79      discovery_status_ == DISCOVERY_STOPPING;
80}
81
82// If the method is called when |discovery_status_| is DISCOVERY_STOPPING,
83// starting again is handled by BluetoothAdapterWin::DiscoveryStopped().
84void BluetoothAdapterWin::StartDiscovering(
85    const base::Closure& callback,
86    const ErrorCallback& error_callback) {
87  if (discovery_status_ == DISCOVERING) {
88    num_discovery_listeners_++;
89    callback.Run();
90    return;
91  }
92  on_start_discovery_callbacks_.push_back(
93      std::make_pair(callback, error_callback));
94  MaybePostStartDiscoveryTask();
95}
96
97void BluetoothAdapterWin::StopDiscovering(
98    const base::Closure& callback,
99    const ErrorCallback& error_callback) {
100  if (discovery_status_ == NOT_DISCOVERING) {
101    error_callback.Run();
102    return;
103  }
104  on_stop_discovery_callbacks_.push_back(callback);
105  MaybePostStopDiscoveryTask();
106}
107
108void BluetoothAdapterWin::DiscoveryStarted(bool success) {
109  discovery_status_ = success ? DISCOVERING : NOT_DISCOVERING;
110  for (std::vector<std::pair<base::Closure, ErrorCallback> >::const_iterator
111       iter = on_start_discovery_callbacks_.begin();
112       iter != on_start_discovery_callbacks_.end();
113       ++iter) {
114    if (success)
115      ui_task_runner_->PostTask(FROM_HERE, iter->first);
116    else
117      ui_task_runner_->PostTask(FROM_HERE, iter->second);
118  }
119  num_discovery_listeners_ = on_start_discovery_callbacks_.size();
120  on_start_discovery_callbacks_.clear();
121
122  if (success) {
123    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
124                      AdapterDiscoveringChanged(this, true));
125
126    // If there are stop discovery requests, post the stop discovery again.
127    MaybePostStopDiscoveryTask();
128  } else if (!on_stop_discovery_callbacks_.empty()) {
129    // If there are stop discovery requests but start discovery has failed,
130    // notify that stop discovery has been complete.
131    DiscoveryStopped();
132  }
133}
134
135void BluetoothAdapterWin::DiscoveryStopped() {
136  discovered_devices_.clear();
137  bool was_discovering = IsDiscovering();
138  discovery_status_ = NOT_DISCOVERING;
139  for (std::vector<base::Closure>::const_iterator iter =
140           on_stop_discovery_callbacks_.begin();
141       iter != on_stop_discovery_callbacks_.end();
142       ++iter) {
143    ui_task_runner_->PostTask(FROM_HERE, *iter);
144  }
145  num_discovery_listeners_ = 0;
146  on_stop_discovery_callbacks_.clear();
147  if (was_discovering)
148    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
149                      AdapterDiscoveringChanged(this, false));
150
151  // If there are start discovery requests, post the start discovery again.
152  MaybePostStartDiscoveryTask();
153}
154
155void BluetoothAdapterWin::ReadLocalOutOfBandPairingData(
156    const BluetoothOutOfBandPairingDataCallback& callback,
157    const ErrorCallback& error_callback) {
158  NOTIMPLEMENTED();
159}
160
161void BluetoothAdapterWin::AdapterStateChanged(
162    const BluetoothTaskManagerWin::AdapterState& state) {
163  DCHECK(thread_checker_.CalledOnValidThread());
164  name_ = state.name;
165  bool was_present = IsPresent();
166  bool is_present = !state.address.empty();
167  address_ = state.address;
168  if (was_present != is_present) {
169    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
170                      AdapterPresentChanged(this, is_present));
171  }
172  if (powered_ != state.powered) {
173    powered_ = state.powered;
174    FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
175                      AdapterPoweredChanged(this, powered_));
176  }
177  if (!initialized_) {
178    initialized_ = true;
179    init_callback_.Run();
180  }
181}
182
183void BluetoothAdapterWin::DevicesDiscovered(
184    const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices) {
185  DCHECK(thread_checker_.CalledOnValidThread());
186  for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter =
187           devices.begin();
188       iter != devices.end();
189       ++iter) {
190    if (discovered_devices_.find((*iter)->address) ==
191        discovered_devices_.end()) {
192      BluetoothDeviceWin device_win(**iter);
193      FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
194                        DeviceAdded(this, &device_win));
195      discovered_devices_.insert((*iter)->address);
196    }
197  }
198}
199
200void BluetoothAdapterWin::DevicesUpdated(
201    const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices) {
202  STLDeleteValues(&devices_);
203  for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter =
204           devices.begin();
205       iter != devices.end();
206       ++iter) {
207    devices_[(*iter)->address] = new BluetoothDeviceWin(**iter);
208  }
209}
210
211void BluetoothAdapterWin::Init() {
212  ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
213  task_manager_ =
214      new BluetoothTaskManagerWin(ui_task_runner_);
215  task_manager_->AddObserver(this);
216  task_manager_->Initialize();
217}
218
219void BluetoothAdapterWin::InitForTest(
220    scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
221    scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner) {
222  ui_task_runner_ = ui_task_runner;
223  task_manager_ =
224      new BluetoothTaskManagerWin(ui_task_runner_);
225  task_manager_->AddObserver(this);
226  task_manager_->InitializeWithBluetoothTaskRunner(bluetooth_task_runner);
227}
228
229void BluetoothAdapterWin::MaybePostStartDiscoveryTask() {
230  if (discovery_status_ == NOT_DISCOVERING &&
231      !on_start_discovery_callbacks_.empty()) {
232    discovery_status_ = DISCOVERY_STARTING;
233    task_manager_->PostStartDiscoveryTask();
234  }
235}
236
237void BluetoothAdapterWin::MaybePostStopDiscoveryTask() {
238  if (discovery_status_ != DISCOVERING)
239    return;
240
241  if (on_stop_discovery_callbacks_.size() < num_discovery_listeners_) {
242    for (std::vector<base::Closure>::const_iterator iter =
243             on_stop_discovery_callbacks_.begin();
244         iter != on_stop_discovery_callbacks_.end();
245         ++iter) {
246      ui_task_runner_->PostTask(FROM_HERE, *iter);
247    }
248    num_discovery_listeners_ -= on_stop_discovery_callbacks_.size();
249    on_stop_discovery_callbacks_.clear();
250    return;
251  }
252
253  discovery_status_ = DISCOVERY_STOPPING;
254  task_manager_->PostStopDiscoveryTask();
255}
256
257}  // namespace device
258