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
19 namespace device {
20
BluetoothAdapterWin(const InitCallback & init_callback)21 BluetoothAdapterWin::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
~BluetoothAdapterWin()31 BluetoothAdapterWin::~BluetoothAdapterWin() {
32 if (task_manager_) {
33 task_manager_->RemoveObserver(this);
34 task_manager_->Shutdown();
35 }
36 }
37
AddObserver(BluetoothAdapter::Observer * observer)38 void BluetoothAdapterWin::AddObserver(BluetoothAdapter::Observer* observer) {
39 DCHECK(observer);
40 observers_.AddObserver(observer);
41 }
42
RemoveObserver(BluetoothAdapter::Observer * observer)43 void BluetoothAdapterWin::RemoveObserver(BluetoothAdapter::Observer* observer) {
44 DCHECK(observer);
45 observers_.RemoveObserver(observer);
46 }
47
GetAddress() const48 std::string BluetoothAdapterWin::GetAddress() const {
49 return address_;
50 }
51
GetName() const52 std::string BluetoothAdapterWin::GetName() const {
53 return name_;
54 }
55
56 // TODO(youngki): Return true when |task_manager_| initializes the adapter
57 // state.
IsInitialized() const58 bool BluetoothAdapterWin::IsInitialized() const {
59 return initialized_;
60 }
61
IsPresent() const62 bool BluetoothAdapterWin::IsPresent() const {
63 return !address_.empty();
64 }
65
IsPowered() const66 bool BluetoothAdapterWin::IsPowered() const {
67 return powered_;
68 }
69
SetPowered(bool powered,const base::Closure & callback,const ErrorCallback & error_callback)70 void 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
IsDiscovering() const77 bool 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().
StartDiscovering(const base::Closure & callback,const ErrorCallback & error_callback)84 void 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
StopDiscovering(const base::Closure & callback,const ErrorCallback & error_callback)97 void 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
DiscoveryStarted(bool success)108 void 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
DiscoveryStopped()135 void 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
ReadLocalOutOfBandPairingData(const BluetoothOutOfBandPairingDataCallback & callback,const ErrorCallback & error_callback)155 void BluetoothAdapterWin::ReadLocalOutOfBandPairingData(
156 const BluetoothOutOfBandPairingDataCallback& callback,
157 const ErrorCallback& error_callback) {
158 NOTIMPLEMENTED();
159 }
160
AdapterStateChanged(const BluetoothTaskManagerWin::AdapterState & state)161 void 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
DevicesDiscovered(const ScopedVector<BluetoothTaskManagerWin::DeviceState> & devices)183 void 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
DevicesUpdated(const ScopedVector<BluetoothTaskManagerWin::DeviceState> & devices)200 void 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
Init()211 void 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
InitForTest(scoped_refptr<base::SequencedTaskRunner> ui_task_runner,scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner)219 void 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
MaybePostStartDiscoveryTask()229 void 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
MaybePostStopDiscoveryTask()237 void 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