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 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 31 BluetoothAdapterWin::~BluetoothAdapterWin() { 32 if (task_manager_) { 33 task_manager_->RemoveObserver(this); 34 task_manager_->Shutdown(); 35 } 36 } 37 38 void BluetoothAdapterWin::AddObserver(BluetoothAdapter::Observer* observer) { 39 DCHECK(observer); 40 observers_.AddObserver(observer); 41 } 42 43 void BluetoothAdapterWin::RemoveObserver(BluetoothAdapter::Observer* observer) { 44 DCHECK(observer); 45 observers_.RemoveObserver(observer); 46 } 47 48 std::string BluetoothAdapterWin::GetAddress() const { 49 return address_; 50 } 51 52 std::string BluetoothAdapterWin::GetName() const { 53 return name_; 54 } 55 56 // TODO(youngki): Return true when |task_manager_| initializes the adapter 57 // state. 58 bool BluetoothAdapterWin::IsInitialized() const { 59 return initialized_; 60 } 61 62 bool BluetoothAdapterWin::IsPresent() const { 63 return !address_.empty(); 64 } 65 66 bool BluetoothAdapterWin::IsPowered() const { 67 return powered_; 68 } 69 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 77 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(). 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 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 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 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 155 void BluetoothAdapterWin::ReadLocalOutOfBandPairingData( 156 const BluetoothOutOfBandPairingDataCallback& callback, 157 const ErrorCallback& error_callback) { 158 NOTIMPLEMENTED(); 159 } 160 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 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 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 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 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 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 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