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.h"
6
7#include "base/bind.h"
8#include "base/stl_util.h"
9#include "device/bluetooth/bluetooth_device.h"
10#include "device/bluetooth/bluetooth_discovery_session.h"
11
12namespace device {
13
14BluetoothAdapter::ServiceOptions::ServiceOptions() {
15}
16BluetoothAdapter::ServiceOptions::~ServiceOptions() {
17}
18
19#if !defined(OS_CHROMEOS) && !defined(OS_WIN) && !defined(OS_MACOSX)
20//static
21base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
22    const InitCallback& init_callback) {
23  return base::WeakPtr<BluetoothAdapter>();
24}
25#endif  // !defined(OS_CHROMEOS) && !defined(OS_WIN) && !defined(OS_MACOSX)
26
27BluetoothAdapter::BluetoothAdapter()
28    : weak_ptr_factory_(this) {
29}
30
31BluetoothAdapter::~BluetoothAdapter() {
32  STLDeleteValues(&devices_);
33}
34
35base::WeakPtr<BluetoothAdapter> BluetoothAdapter::GetWeakPtrForTesting() {
36  return weak_ptr_factory_.GetWeakPtr();
37}
38
39void BluetoothAdapter::StartDiscoverySession(
40    const DiscoverySessionCallback& callback,
41    const ErrorCallback& error_callback) {
42  AddDiscoverySession(
43      base::Bind(&BluetoothAdapter::OnStartDiscoverySession,
44                 weak_ptr_factory_.GetWeakPtr(),
45                 callback),
46      error_callback);
47}
48
49BluetoothAdapter::DeviceList BluetoothAdapter::GetDevices() {
50  ConstDeviceList const_devices =
51    const_cast<const BluetoothAdapter *>(this)->GetDevices();
52
53  DeviceList devices;
54  for (ConstDeviceList::const_iterator i = const_devices.begin();
55       i != const_devices.end(); ++i)
56    devices.push_back(const_cast<BluetoothDevice *>(*i));
57
58  return devices;
59}
60
61BluetoothAdapter::ConstDeviceList BluetoothAdapter::GetDevices() const {
62  ConstDeviceList devices;
63  for (DevicesMap::const_iterator iter = devices_.begin();
64       iter != devices_.end();
65       ++iter)
66    devices.push_back(iter->second);
67
68  return devices;
69}
70
71BluetoothDevice* BluetoothAdapter::GetDevice(const std::string& address) {
72  return const_cast<BluetoothDevice *>(
73      const_cast<const BluetoothAdapter *>(this)->GetDevice(address));
74}
75
76const BluetoothDevice* BluetoothAdapter::GetDevice(
77    const std::string& address) const {
78  std::string canonicalized_address =
79      BluetoothDevice::CanonicalizeAddress(address);
80  if (canonicalized_address.empty())
81    return NULL;
82
83  DevicesMap::const_iterator iter = devices_.find(canonicalized_address);
84  if (iter != devices_.end())
85    return iter->second;
86
87  return NULL;
88}
89
90void BluetoothAdapter::AddPairingDelegate(
91    BluetoothDevice::PairingDelegate* pairing_delegate,
92    PairingDelegatePriority priority) {
93  // Remove the delegate, if it already exists, before inserting to allow a
94  // change of priority.
95  RemovePairingDelegate(pairing_delegate);
96
97  // Find the first point with a lower priority, or the end of the list.
98  std::list<PairingDelegatePair>::iterator iter = pairing_delegates_.begin();
99  while (iter != pairing_delegates_.end() && iter->second >= priority)
100    ++iter;
101
102  pairing_delegates_.insert(iter, std::make_pair(pairing_delegate, priority));
103}
104
105void BluetoothAdapter::RemovePairingDelegate(
106    BluetoothDevice::PairingDelegate* pairing_delegate) {
107  for (std::list<PairingDelegatePair>::iterator iter =
108       pairing_delegates_.begin(); iter != pairing_delegates_.end(); ++iter) {
109    if (iter->first == pairing_delegate) {
110      RemovePairingDelegateInternal(pairing_delegate);
111      pairing_delegates_.erase(iter);
112      return;
113    }
114  }
115}
116
117BluetoothDevice::PairingDelegate* BluetoothAdapter::DefaultPairingDelegate() {
118  if (pairing_delegates_.empty())
119    return NULL;
120
121  return pairing_delegates_.front().first;
122}
123
124void BluetoothAdapter::OnStartDiscoverySession(
125    const DiscoverySessionCallback& callback) {
126  VLOG(1) << "Discovery session started!";
127  scoped_ptr<BluetoothDiscoverySession> discovery_session(
128      new BluetoothDiscoverySession(scoped_refptr<BluetoothAdapter>(this)));
129  discovery_sessions_.insert(discovery_session.get());
130  callback.Run(discovery_session.Pass());
131}
132
133void BluetoothAdapter::MarkDiscoverySessionsAsInactive() {
134  // As sessions are marked as inactive they will notify the adapter that they
135  // have become inactive, upon which the adapter will remove them from
136  // |discovery_sessions_|. To avoid invalidating the iterator, make a copy
137  // here.
138  std::set<BluetoothDiscoverySession*> temp(discovery_sessions_);
139  for (std::set<BluetoothDiscoverySession*>::iterator
140          iter = temp.begin();
141       iter != temp.end(); ++iter) {
142    (*iter)->MarkAsInactive();
143  }
144}
145
146void BluetoothAdapter::DiscoverySessionBecameInactive(
147    BluetoothDiscoverySession* discovery_session) {
148  DCHECK(!discovery_session->IsActive());
149  discovery_sessions_.erase(discovery_session);
150}
151
152}  // namespace device
153