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_socket_thread.h" 18#include "device/bluetooth/bluetooth_socket_win.h" 19#include "device/bluetooth/bluetooth_task_manager_win.h" 20#include "device/bluetooth/bluetooth_uuid.h" 21 22namespace device { 23 24// static 25base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( 26 const InitCallback& init_callback) { 27 return BluetoothAdapterWin::CreateAdapter(init_callback); 28} 29 30// static 31base::WeakPtr<BluetoothAdapter> BluetoothAdapterWin::CreateAdapter( 32 const InitCallback& init_callback) { 33 BluetoothAdapterWin* adapter = new BluetoothAdapterWin(init_callback); 34 adapter->Init(); 35 return adapter->weak_ptr_factory_.GetWeakPtr(); 36} 37 38BluetoothAdapterWin::BluetoothAdapterWin(const InitCallback& init_callback) 39 : BluetoothAdapter(), 40 init_callback_(init_callback), 41 initialized_(false), 42 powered_(false), 43 discovery_status_(NOT_DISCOVERING), 44 num_discovery_listeners_(0), 45 weak_ptr_factory_(this) { 46} 47 48BluetoothAdapterWin::~BluetoothAdapterWin() { 49 if (task_manager_) { 50 task_manager_->RemoveObserver(this); 51 task_manager_->Shutdown(); 52 } 53} 54 55void BluetoothAdapterWin::AddObserver(BluetoothAdapter::Observer* observer) { 56 DCHECK(observer); 57 observers_.AddObserver(observer); 58} 59 60void BluetoothAdapterWin::RemoveObserver(BluetoothAdapter::Observer* observer) { 61 DCHECK(observer); 62 observers_.RemoveObserver(observer); 63} 64 65std::string BluetoothAdapterWin::GetAddress() const { 66 return address_; 67} 68 69std::string BluetoothAdapterWin::GetName() const { 70 return name_; 71} 72 73void BluetoothAdapterWin::SetName(const std::string& name, 74 const base::Closure& callback, 75 const ErrorCallback& error_callback) { 76 NOTIMPLEMENTED(); 77} 78 79// TODO(youngki): Return true when |task_manager_| initializes the adapter 80// state. 81bool BluetoothAdapterWin::IsInitialized() const { 82 return initialized_; 83} 84 85bool BluetoothAdapterWin::IsPresent() const { 86 return !address_.empty(); 87} 88 89bool BluetoothAdapterWin::IsPowered() const { 90 return powered_; 91} 92 93void BluetoothAdapterWin::SetPowered( 94 bool powered, 95 const base::Closure& callback, 96 const ErrorCallback& error_callback) { 97 task_manager_->PostSetPoweredBluetoothTask(powered, callback, error_callback); 98} 99 100bool BluetoothAdapterWin::IsDiscoverable() const { 101 NOTIMPLEMENTED(); 102 return false; 103} 104 105void BluetoothAdapterWin::SetDiscoverable( 106 bool discoverable, 107 const base::Closure& callback, 108 const ErrorCallback& error_callback) { 109 NOTIMPLEMENTED(); 110} 111 112bool BluetoothAdapterWin::IsDiscovering() const { 113 return discovery_status_ == DISCOVERING || 114 discovery_status_ == DISCOVERY_STOPPING; 115} 116 117void BluetoothAdapterWin::DiscoveryStarted(bool success) { 118 discovery_status_ = success ? DISCOVERING : NOT_DISCOVERING; 119 for (std::vector<std::pair<base::Closure, ErrorCallback> >::const_iterator 120 iter = on_start_discovery_callbacks_.begin(); 121 iter != on_start_discovery_callbacks_.end(); 122 ++iter) { 123 if (success) 124 ui_task_runner_->PostTask(FROM_HERE, iter->first); 125 else 126 ui_task_runner_->PostTask(FROM_HERE, iter->second); 127 } 128 num_discovery_listeners_ = on_start_discovery_callbacks_.size(); 129 on_start_discovery_callbacks_.clear(); 130 131 if (success) { 132 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, 133 AdapterDiscoveringChanged(this, true)); 134 135 // If there are stop discovery requests, post the stop discovery again. 136 MaybePostStopDiscoveryTask(); 137 } else if (!on_stop_discovery_callbacks_.empty()) { 138 // If there are stop discovery requests but start discovery has failed, 139 // notify that stop discovery has been complete. 140 DiscoveryStopped(); 141 } 142} 143 144void BluetoothAdapterWin::DiscoveryStopped() { 145 discovered_devices_.clear(); 146 bool was_discovering = IsDiscovering(); 147 discovery_status_ = NOT_DISCOVERING; 148 for (std::vector<base::Closure>::const_iterator iter = 149 on_stop_discovery_callbacks_.begin(); 150 iter != on_stop_discovery_callbacks_.end(); 151 ++iter) { 152 ui_task_runner_->PostTask(FROM_HERE, *iter); 153 } 154 num_discovery_listeners_ = 0; 155 on_stop_discovery_callbacks_.clear(); 156 if (was_discovering) 157 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, 158 AdapterDiscoveringChanged(this, false)); 159 160 // If there are start discovery requests, post the start discovery again. 161 MaybePostStartDiscoveryTask(); 162} 163 164void BluetoothAdapterWin::CreateRfcommService( 165 const BluetoothUUID& uuid, 166 const ServiceOptions& options, 167 const CreateServiceCallback& callback, 168 const CreateServiceErrorCallback& error_callback) { 169 scoped_refptr<BluetoothSocketWin> socket = 170 BluetoothSocketWin::CreateBluetoothSocket( 171 ui_task_runner_, socket_thread_); 172 socket->Listen(this, uuid, options, 173 base::Bind(callback, socket), 174 error_callback); 175} 176 177void BluetoothAdapterWin::CreateL2capService( 178 const BluetoothUUID& uuid, 179 const ServiceOptions& options, 180 const CreateServiceCallback& callback, 181 const CreateServiceErrorCallback& error_callback) { 182 // TODO(keybuk): implement. 183 NOTIMPLEMENTED(); 184} 185 186void BluetoothAdapterWin::RemovePairingDelegateInternal( 187 BluetoothDevice::PairingDelegate* pairing_delegate) { 188} 189 190void BluetoothAdapterWin::AdapterStateChanged( 191 const BluetoothTaskManagerWin::AdapterState& state) { 192 DCHECK(thread_checker_.CalledOnValidThread()); 193 name_ = state.name; 194 bool was_present = IsPresent(); 195 bool is_present = !state.address.empty(); 196 address_ = BluetoothDevice::CanonicalizeAddress(state.address); 197 if (was_present != is_present) { 198 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, 199 AdapterPresentChanged(this, is_present)); 200 } 201 if (powered_ != state.powered) { 202 powered_ = state.powered; 203 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, 204 AdapterPoweredChanged(this, powered_)); 205 } 206 if (!initialized_) { 207 initialized_ = true; 208 init_callback_.Run(); 209 } 210} 211 212void BluetoothAdapterWin::DevicesPolled( 213 const ScopedVector<BluetoothTaskManagerWin::DeviceState>& devices) { 214 DCHECK(thread_checker_.CalledOnValidThread()); 215 216 // We are receiving a new list of all devices known to the system. Merge this 217 // new list with the list we know of (|devices_|) and raise corresponding 218 // DeviceAdded, DeviceRemoved and DeviceChanged events. 219 220 typedef std::set<std::string> DeviceAddressSet; 221 DeviceAddressSet known_devices; 222 for (DevicesMap::const_iterator iter = devices_.begin(); 223 iter != devices_.end(); 224 ++iter) { 225 known_devices.insert((*iter).first); 226 } 227 228 DeviceAddressSet new_devices; 229 for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter = 230 devices.begin(); 231 iter != devices.end(); 232 ++iter) { 233 new_devices.insert((*iter)->address); 234 } 235 236 // Process device removal first 237 DeviceAddressSet removed_devices = 238 base::STLSetDifference<DeviceAddressSet>(known_devices, new_devices); 239 for (DeviceAddressSet::const_iterator iter = removed_devices.begin(); 240 iter != removed_devices.end(); 241 ++iter) { 242 BluetoothDevice* device_win = devices_[(*iter)]; 243 devices_.erase(*iter); 244 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, 245 observers_, 246 DeviceRemoved(this, device_win)); 247 delete device_win; 248 } 249 250 // Process added and (maybe) changed devices in one pass 251 DeviceAddressSet added_devices = 252 base::STLSetDifference<DeviceAddressSet>(new_devices, known_devices); 253 DeviceAddressSet changed_devices = 254 base::STLSetIntersection<DeviceAddressSet>(known_devices, new_devices); 255 for (ScopedVector<BluetoothTaskManagerWin::DeviceState>::const_iterator iter = 256 devices.begin(); 257 iter != devices.end(); 258 ++iter) { 259 BluetoothTaskManagerWin::DeviceState* device_state = (*iter); 260 if (added_devices.find(device_state->address) != added_devices.end()) { 261 BluetoothDeviceWin* device_win = 262 new BluetoothDeviceWin(*device_state, 263 ui_task_runner_, 264 socket_thread_, 265 NULL, 266 net::NetLog::Source()); 267 devices_[device_state->address] = device_win; 268 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, 269 observers_, 270 DeviceAdded(this, device_win)); 271 } else if (changed_devices.find(device_state->address) != 272 changed_devices.end()) { 273 BluetoothDeviceWin* device_win = 274 static_cast<BluetoothDeviceWin*>(devices_[device_state->address]); 275 if (!device_win->IsEqual(*device_state)) { 276 device_win->Update(*device_state); 277 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, 278 observers_, 279 DeviceChanged(this, device_win)); 280 } 281 } 282 } 283} 284 285// If the method is called when |discovery_status_| is DISCOVERY_STOPPING, 286// starting again is handled by BluetoothAdapterWin::DiscoveryStopped(). 287void BluetoothAdapterWin::AddDiscoverySession( 288 const base::Closure& callback, 289 const ErrorCallback& error_callback) { 290 if (discovery_status_ == DISCOVERING) { 291 num_discovery_listeners_++; 292 callback.Run(); 293 return; 294 } 295 on_start_discovery_callbacks_.push_back( 296 std::make_pair(callback, error_callback)); 297 MaybePostStartDiscoveryTask(); 298} 299 300void BluetoothAdapterWin::RemoveDiscoverySession( 301 const base::Closure& callback, 302 const ErrorCallback& error_callback) { 303 if (discovery_status_ == NOT_DISCOVERING) { 304 error_callback.Run(); 305 return; 306 } 307 on_stop_discovery_callbacks_.push_back(callback); 308 MaybePostStopDiscoveryTask(); 309} 310 311void BluetoothAdapterWin::Init() { 312 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 313 socket_thread_ = BluetoothSocketThread::Get(); 314 task_manager_ = 315 new BluetoothTaskManagerWin(ui_task_runner_); 316 task_manager_->AddObserver(this); 317 task_manager_->Initialize(); 318} 319 320void BluetoothAdapterWin::InitForTest( 321 scoped_refptr<base::SequencedTaskRunner> ui_task_runner, 322 scoped_refptr<base::SequencedTaskRunner> bluetooth_task_runner) { 323 ui_task_runner_ = ui_task_runner; 324 task_manager_ = 325 new BluetoothTaskManagerWin(ui_task_runner_); 326 task_manager_->AddObserver(this); 327 task_manager_->InitializeWithBluetoothTaskRunner(bluetooth_task_runner); 328} 329 330void BluetoothAdapterWin::MaybePostStartDiscoveryTask() { 331 if (discovery_status_ == NOT_DISCOVERING && 332 !on_start_discovery_callbacks_.empty()) { 333 discovery_status_ = DISCOVERY_STARTING; 334 task_manager_->PostStartDiscoveryTask(); 335 } 336} 337 338void BluetoothAdapterWin::MaybePostStopDiscoveryTask() { 339 if (discovery_status_ != DISCOVERING) 340 return; 341 342 if (on_stop_discovery_callbacks_.size() < num_discovery_listeners_) { 343 for (std::vector<base::Closure>::const_iterator iter = 344 on_stop_discovery_callbacks_.begin(); 345 iter != on_stop_discovery_callbacks_.end(); 346 ++iter) { 347 ui_task_runner_->PostTask(FROM_HERE, *iter); 348 } 349 num_discovery_listeners_ -= on_stop_discovery_callbacks_.size(); 350 on_stop_discovery_callbacks_.clear(); 351 return; 352 } 353 354 discovery_status_ = DISCOVERY_STOPPING; 355 task_manager_->PostStopDiscoveryTask(); 356} 357 358} // namespace device 359