• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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