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