1 // Copyright (c) 2013 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 "chromeos/dbus/fake_bluetooth_adapter_client.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/time/time.h"
11 #include "chromeos/dbus/dbus_thread_manager.h"
12 #include "chromeos/dbus/fake_bluetooth_device_client.h"
13 #include "dbus/object_path.h"
14 #include "third_party/cros_system_api/dbus/service_constants.h"
15
16 namespace chromeos {
17
18 namespace {
19
20 // Default interval for delayed tasks.
21 const int kSimulationIntervalMs = 750;
22
23 } // namespace
24
25 const char FakeBluetoothAdapterClient::kAdapterPath[] =
26 "/fake/hci0";
27 const char FakeBluetoothAdapterClient::kAdapterName[] =
28 "Fake Adapter";
29 const char FakeBluetoothAdapterClient::kAdapterAddress[] =
30 "01:1A:2B:1A:2B:03";
31
32 const char FakeBluetoothAdapterClient::kSecondAdapterPath[] =
33 "/fake/hci1";
34 const char FakeBluetoothAdapterClient::kSecondAdapterName[] =
35 "Second Fake Adapter";
36 const char FakeBluetoothAdapterClient::kSecondAdapterAddress[] =
37 "00:DE:51:10:01:00";
38
Properties(const PropertyChangedCallback & callback)39 FakeBluetoothAdapterClient::Properties::Properties(
40 const PropertyChangedCallback& callback)
41 : BluetoothAdapterClient::Properties(
42 NULL,
43 bluetooth_adapter::kBluetoothAdapterInterface,
44 callback) {
45 }
46
~Properties()47 FakeBluetoothAdapterClient::Properties::~Properties() {
48 }
49
Get(dbus::PropertyBase * property,dbus::PropertySet::GetCallback callback)50 void FakeBluetoothAdapterClient::Properties::Get(
51 dbus::PropertyBase* property,
52 dbus::PropertySet::GetCallback callback) {
53 VLOG(1) << "Get " << property->name();
54 callback.Run(false);
55 }
56
GetAll()57 void FakeBluetoothAdapterClient::Properties::GetAll() {
58 VLOG(1) << "GetAll";
59 }
60
Set(dbus::PropertyBase * property,dbus::PropertySet::SetCallback callback)61 void FakeBluetoothAdapterClient::Properties::Set(
62 dbus::PropertyBase *property,
63 dbus::PropertySet::SetCallback callback) {
64 VLOG(1) << "Set " << property->name();
65 if (property->name() == powered.name() ||
66 property->name() == alias.name() ||
67 property->name() == discoverable.name() ||
68 property->name() == discoverable_timeout.name()) {
69 callback.Run(true);
70 property->ReplaceValueWithSetValue();
71 } else {
72 callback.Run(false);
73 }
74 }
75
FakeBluetoothAdapterClient()76 FakeBluetoothAdapterClient::FakeBluetoothAdapterClient()
77 : visible_(true),
78 second_visible_(false),
79 discovering_count_(0),
80 simulation_interval_ms_(kSimulationIntervalMs) {
81 properties_.reset(new Properties(base::Bind(
82 &FakeBluetoothAdapterClient::OnPropertyChanged, base::Unretained(this))));
83
84 properties_->address.ReplaceValue(kAdapterAddress);
85 properties_->name.ReplaceValue("Fake Adapter (Name)");
86 properties_->alias.ReplaceValue(kAdapterName);
87 properties_->pairable.ReplaceValue(true);
88
89 second_properties_.reset(new Properties(base::Bind(
90 &FakeBluetoothAdapterClient::OnPropertyChanged, base::Unretained(this))));
91
92 second_properties_->address.ReplaceValue(kSecondAdapterAddress);
93 second_properties_->name.ReplaceValue("Second Fake Adapter (Name)");
94 second_properties_->alias.ReplaceValue(kSecondAdapterName);
95 second_properties_->pairable.ReplaceValue(true);
96 }
97
~FakeBluetoothAdapterClient()98 FakeBluetoothAdapterClient::~FakeBluetoothAdapterClient() {
99 }
100
Init(dbus::Bus * bus)101 void FakeBluetoothAdapterClient::Init(dbus::Bus* bus) {
102 }
103
AddObserver(Observer * observer)104 void FakeBluetoothAdapterClient::AddObserver(Observer* observer) {
105 observers_.AddObserver(observer);
106 }
107
RemoveObserver(Observer * observer)108 void FakeBluetoothAdapterClient::RemoveObserver(Observer* observer) {
109 observers_.RemoveObserver(observer);
110 }
111
GetAdapters()112 std::vector<dbus::ObjectPath> FakeBluetoothAdapterClient::GetAdapters() {
113 std::vector<dbus::ObjectPath> object_paths;
114 if (visible_)
115 object_paths.push_back(dbus::ObjectPath(kAdapterPath));
116 if (second_visible_)
117 object_paths.push_back(dbus::ObjectPath(kSecondAdapterPath));
118 return object_paths;
119 }
120
121 FakeBluetoothAdapterClient::Properties*
GetProperties(const dbus::ObjectPath & object_path)122 FakeBluetoothAdapterClient::GetProperties(const dbus::ObjectPath& object_path) {
123 if (object_path == dbus::ObjectPath(kAdapterPath))
124 return properties_.get();
125 else if (object_path == dbus::ObjectPath(kSecondAdapterPath))
126 return second_properties_.get();
127 else
128 return NULL;
129 }
130
StartDiscovery(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)131 void FakeBluetoothAdapterClient::StartDiscovery(
132 const dbus::ObjectPath& object_path,
133 const base::Closure& callback,
134 const ErrorCallback& error_callback) {
135 if (object_path != dbus::ObjectPath(kAdapterPath)) {
136 PostDelayedTask(base::Bind(error_callback, kNoResponseError, ""));
137 return;
138 }
139
140 ++discovering_count_;
141 VLOG(1) << "StartDiscovery: " << object_path.value() << ", "
142 << "count is now " << discovering_count_;
143 PostDelayedTask(callback);
144
145 if (discovering_count_ == 1) {
146 properties_->discovering.ReplaceValue(true);
147
148 FakeBluetoothDeviceClient* device_client =
149 static_cast<FakeBluetoothDeviceClient*>(
150 DBusThreadManager::Get()->GetBluetoothDeviceClient());
151 device_client->BeginDiscoverySimulation(dbus::ObjectPath(kAdapterPath));
152 }
153 }
154
StopDiscovery(const dbus::ObjectPath & object_path,const base::Closure & callback,const ErrorCallback & error_callback)155 void FakeBluetoothAdapterClient::StopDiscovery(
156 const dbus::ObjectPath& object_path,
157 const base::Closure& callback,
158 const ErrorCallback& error_callback) {
159 if (object_path != dbus::ObjectPath(kAdapterPath)) {
160 PostDelayedTask(base::Bind(error_callback, kNoResponseError, ""));
161 return;
162 }
163
164 if (!discovering_count_) {
165 LOG(WARNING) << "StopDiscovery called when not discovering";
166 PostDelayedTask(base::Bind(error_callback, kNoResponseError, ""));
167 return;
168 }
169
170 --discovering_count_;
171 VLOG(1) << "StopDiscovery: " << object_path.value() << ", "
172 << "count is now " << discovering_count_;
173 PostDelayedTask(callback);
174
175 if (discovering_count_ == 0) {
176 FakeBluetoothDeviceClient* device_client =
177 static_cast<FakeBluetoothDeviceClient*>(
178 DBusThreadManager::Get()->GetBluetoothDeviceClient());
179 device_client->EndDiscoverySimulation(dbus::ObjectPath(kAdapterPath));
180
181 if (simulation_interval_ms_ > 100) {
182 device_client->BeginIncomingPairingSimulation(
183 dbus::ObjectPath(kAdapterPath));
184 }
185
186 properties_->discovering.ReplaceValue(false);
187 }
188 }
189
RemoveDevice(const dbus::ObjectPath & object_path,const dbus::ObjectPath & device_path,const base::Closure & callback,const ErrorCallback & error_callback)190 void FakeBluetoothAdapterClient::RemoveDevice(
191 const dbus::ObjectPath& object_path,
192 const dbus::ObjectPath& device_path,
193 const base::Closure& callback,
194 const ErrorCallback& error_callback) {
195 if (object_path != dbus::ObjectPath(kAdapterPath)) {
196 error_callback.Run(kNoResponseError, "");
197 return;
198 }
199
200 VLOG(1) << "RemoveDevice: " << object_path.value()
201 << " " << device_path.value();
202 callback.Run();
203
204 FakeBluetoothDeviceClient* device_client =
205 static_cast<FakeBluetoothDeviceClient*>(
206 DBusThreadManager::Get()->GetBluetoothDeviceClient());
207 device_client->RemoveDevice(dbus::ObjectPath(kAdapterPath), device_path);
208 }
209
SetSimulationIntervalMs(int interval_ms)210 void FakeBluetoothAdapterClient::SetSimulationIntervalMs(int interval_ms) {
211 simulation_interval_ms_ = interval_ms;
212 }
213
SetVisible(bool visible)214 void FakeBluetoothAdapterClient::SetVisible(
215 bool visible) {
216 if (visible && !visible_) {
217 // Adapter becoming visible
218 visible_ = visible;
219
220 FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
221 AdapterAdded(dbus::ObjectPath(kAdapterPath)));
222
223 } else if (visible_ && !visible) {
224 // Adapter becoming invisible
225 visible_ = visible;
226
227 FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
228 AdapterRemoved(dbus::ObjectPath(kAdapterPath)));
229 }
230 }
231
SetSecondVisible(bool visible)232 void FakeBluetoothAdapterClient::SetSecondVisible(
233 bool visible) {
234 if (visible && !second_visible_) {
235 // Second adapter becoming visible
236 second_visible_ = visible;
237
238 FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
239 AdapterAdded(dbus::ObjectPath(kSecondAdapterPath)));
240
241 } else if (second_visible_ && !visible) {
242 // Second adapter becoming invisible
243 second_visible_ = visible;
244
245 FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
246 AdapterRemoved(dbus::ObjectPath(kSecondAdapterPath)));
247 }
248 }
249
OnPropertyChanged(const std::string & property_name)250 void FakeBluetoothAdapterClient::OnPropertyChanged(
251 const std::string& property_name) {
252 if (property_name == properties_->powered.name() &&
253 !properties_->powered.value()) {
254 VLOG(1) << "Adapter powered off";
255
256 if (discovering_count_) {
257 discovering_count_ = 0;
258 properties_->discovering.ReplaceValue(false);
259 }
260 }
261
262 FOR_EACH_OBSERVER(BluetoothAdapterClient::Observer, observers_,
263 AdapterPropertyChanged(dbus::ObjectPath(kAdapterPath),
264 property_name));
265 }
266
PostDelayedTask(const base::Closure & callback)267 void FakeBluetoothAdapterClient::PostDelayedTask(
268 const base::Closure& callback) {
269 base::MessageLoop::current()->PostDelayedTask(
270 FROM_HERE, callback,
271 base::TimeDelta::FromMilliseconds(simulation_interval_ms_));
272 }
273
274 } // namespace chromeos
275