Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(337)

Side by Side Diff: chromeos/dbus/bluetooth_advertisement_service_provider.cc

Issue 1052363005: Add DBus bindings for BLE Advertisement. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 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/bluetooth_advertisement_service_provider.h"
6
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/stl_util.h"
11 #include "base/threading/platform_thread.h"
12 #include "chromeos/dbus/dbus_thread_manager.h"
13 #include "chromeos/dbus/fake_bluetooth_advertisement_service_provider.h"
14 #include "dbus/exported_object.h"
15 #include "dbus/message.h"
16 #include "third_party/cros_system_api/dbus/service_constants.h"
17
18 namespace chromeos {
19
20 namespace {
21 const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
22 } // namespace
23
24 // TODO(rkc): Remove these once the service constants header is updated.
25 namespace bluetooth_advertisement {
26 const char kBluetoothAdvertisementInterface[] = "";
27 const char kRelease[] = "";
28
29 const char kTypeProperty[] = "";
30 const char kServiceUUIDsProperty[] = "";
31 const char kManufacturerDataProperty[] = "";
32 const char kSolicitUUIDsProperty[] = "";
33 const char kServiceDataProperty[] = "";
34 }
35
36 // The BluetoothAdvertisementServiceProvider implementation used in production.
37 class BluetoothAdvertisementServiceProviderImpl
38 : public BluetoothAdvertisementServiceProvider {
39 public:
40 BluetoothAdvertisementServiceProviderImpl(
41 dbus::Bus* bus,
42 const dbus::ObjectPath& object_path,
43 Delegate* delegate,
44 AdvertisementType type,
45 scoped_ptr<UUIDList> service_uuids,
46 scoped_ptr<ManufacturerData> manufacturer_data,
47 scoped_ptr<UUIDList> solicit_uuids,
48 scoped_ptr<ServiceData> service_data)
49 : origin_thread_id_(base::PlatformThread::CurrentId()),
50 bus_(bus),
51 delegate_(delegate),
52 object_path_(object_path),
53 type_(type),
54 service_uuids_(service_uuids.Pass()),
55 manufacturer_data_(manufacturer_data.Pass()),
56 solicit_uuids_(solicit_uuids.Pass()),
57 service_data_(service_data.Pass()),
58 weak_ptr_factory_(this) {
59 VLOG(1) << "Creating Bluetooth Advertisement: " << object_path_.value();
60
61 exported_object_ = bus_->GetExportedObject(object_path_);
62
63 // Export Bluetooth Advertisement interface methods.
64 exported_object_->ExportMethod(
65 bluetooth_advertisement::kBluetoothAdvertisementInterface,
66 bluetooth_advertisement::kRelease,
67 base::Bind(&BluetoothAdvertisementServiceProviderImpl::Release,
68 weak_ptr_factory_.GetWeakPtr()),
69 base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported,
70 weak_ptr_factory_.GetWeakPtr()));
71
72 // Export dbus property methods.
73 exported_object_->ExportMethod(
74 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
75 base::Bind(&BluetoothAdvertisementServiceProviderImpl::Get,
76 weak_ptr_factory_.GetWeakPtr()),
77 base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported,
78 weak_ptr_factory_.GetWeakPtr()));
79
80 exported_object_->ExportMethod(
81 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
82 base::Bind(&BluetoothAdvertisementServiceProviderImpl::GetAll,
83 weak_ptr_factory_.GetWeakPtr()),
84 base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported,
85 weak_ptr_factory_.GetWeakPtr()));
86 }
87
88 ~BluetoothAdvertisementServiceProviderImpl() override {
89 VLOG(1) << "Cleaning up Bluetooth Advertisement: " << object_path_.value();
90
91 // Unregister the object path so we can reuse with a new agent.
92 bus_->UnregisterExportedObject(object_path_);
93 }
94
95 private:
96 // Returns true if the current thread is on the origin thread.
97 bool OnOriginThread() {
98 return base::PlatformThread::CurrentId() == origin_thread_id_;
99 }
100
101 // Called by dbus:: when the profile is unregistered from the Bluetooth
102 // daemon, generally by our request.
103 void Release(dbus::MethodCall* method_call,
104 dbus::ExportedObject::ResponseSender response_sender) {
105 DCHECK(OnOriginThread());
106 DCHECK(delegate_);
107
108 delegate_->Released();
109
110 response_sender.Run(dbus::Response::FromMethodCall(method_call));
Marie Janssen 2015/04/09 22:36:27 org.bluez.LEAdvertisement1.Release is noreply
rkc 2015/04/13 19:47:45 Done.
111 }
112
113 // Called by dbus:: when the Bluetooth daemon fetches a single property of
114 // the descriptor.
115 void Get(dbus::MethodCall* method_call,
116 dbus::ExportedObject::ResponseSender response_sender) {
117 VLOG(2) << "BluetoothAdvertisementServiceProvider::Get: "
118 << object_path_.value();
119 DCHECK(OnOriginThread());
120
121 dbus::MessageReader reader(method_call);
122
123 std::string interface_name;
124 std::string property_name;
125 if (!reader.PopString(&interface_name) ||
126 !reader.PopString(&property_name) || reader.HasMoreData()) {
127 scoped_ptr<dbus::ErrorResponse> error_response =
128 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
129 "Expected 'ss'.");
130 response_sender.Run(error_response.Pass());
131 return;
132 }
133
134 // Only the advertisement interface is supported.
135 if (interface_name !=
136 bluetooth_advertisement::kBluetoothAdvertisementInterface) {
137 scoped_ptr<dbus::ErrorResponse> error_response =
138 dbus::ErrorResponse::FromMethodCall(
139 method_call, kErrorInvalidArgs,
140 "No such interface: '" + interface_name + "'.");
141 response_sender.Run(error_response.Pass());
142 return;
143 }
144
145 scoped_ptr<dbus::Response> response =
146 dbus::Response::FromMethodCall(method_call);
147 dbus::MessageWriter writer(response.get());
148 dbus::MessageWriter variant_writer(NULL);
149
150 bool returning_error = false;
151 if (property_name == bluetooth_advertisement::kTypeProperty) {
152 writer.OpenVariant("s", &variant_writer);
153 if (type_ == BROADCAST) {
154 variant_writer.AppendString("broadcast");
155 } else {
156 variant_writer.AppendString("peripheral");
157 }
158 } else if (property_name ==
159 bluetooth_advertisement::kServiceUUIDsProperty) {
160 writer.OpenVariant("as", &variant_writer);
161 variant_writer.AppendArrayOfStrings(*service_uuids_);
162 } else if (property_name ==
163 bluetooth_advertisement::kSolicitUUIDsProperty) {
164 writer.OpenVariant("as", &variant_writer);
165 variant_writer.AppendArrayOfStrings(*solicit_uuids_);
166 } else if (property_name ==
167 bluetooth_advertisement::kManufacturerDataProperty) {
168 writer.OpenVariant("o", &variant_writer);
169 AppendManufacturerDataVariant(&variant_writer);
170 } else if (property_name == bluetooth_advertisement::kServiceDataProperty) {
171 writer.OpenVariant("o", &variant_writer);
172 AppendServiceDataVariant(&variant_writer);
173 } else {
174 returning_error = true;
175 response = dbus::ErrorResponse::FromMethodCall(
176 method_call, kErrorInvalidArgs,
177 "No such property: '" + property_name + "'.");
178 }
179
180 if (!returning_error)
181 writer.CloseContainer(&variant_writer);
182 response_sender.Run(response.Pass());
183 }
184
185 // Called by dbus:: when the Bluetooth daemon fetches all properties of the
186 // descriptor.
187 void GetAll(dbus::MethodCall* method_call,
188 dbus::ExportedObject::ResponseSender response_sender) {
189 VLOG(2) << "BluetoothAdvertisementServiceProvider::GetAll: "
190 << object_path_.value();
191 DCHECK(OnOriginThread());
192
193 dbus::MessageReader reader(method_call);
194
195 std::string interface_name;
196 if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
197 scoped_ptr<dbus::ErrorResponse> error_response =
198 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
199 "Expected 's'.");
200 response_sender.Run(error_response.Pass());
201 return;
202 }
203
204 // Only the advertisement interface is supported.
205 if (interface_name !=
206 bluetooth_advertisement::kBluetoothAdvertisementInterface) {
207 scoped_ptr<dbus::ErrorResponse> error_response =
208 dbus::ErrorResponse::FromMethodCall(
209 method_call, kErrorInvalidArgs,
210 "No such interface: '" + interface_name + "'.");
211 response_sender.Run(error_response.Pass());
212 return;
213 }
214
215 response_sender.Run(CreateGetAllResponse(method_call).Pass());
216 }
217
218 // Called by dbus:: when a method is exported.
219 void OnExported(const std::string& interface_name,
220 const std::string& method_name,
221 bool success) {
222 LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "."
223 << method_name;
224 }
225
226 // Helper for populating the DBus response with the advertisement data.
227 scoped_ptr<dbus::Response> CreateGetAllResponse(
228 dbus::MethodCall* method_call) {
229 VLOG(2) << "Descriptor value obtained from delegate. Responding to "
230 << "GetAll.";
231
232 scoped_ptr<dbus::Response> response =
233 dbus::Response::FromMethodCall(method_call);
234
235 dbus::MessageWriter writer(response.get());
236 dbus::MessageWriter array_writer(NULL);
237
238 writer.OpenArray("{sv}", &array_writer);
239
240 AppendType(&array_writer);
241 AppendServiceUUIDs(&array_writer);
242 AppendManufacturerData(&array_writer);
243 AppendSolicitUUIDs(&array_writer);
244 AppendServiceData(&array_writer);
245
246 writer.CloseContainer(&array_writer);
247 return response;
248 }
249
250 // Called by the Delegate in response to a successful method call to get the
251 // descriptor value.
252 void OnGet(dbus::MethodCall* method_call,
253 dbus::ExportedObject::ResponseSender response_sender,
254 const std::vector<uint8>& value) {
255 VLOG(2) << "Returning descriptor value obtained from delegate.";
256 scoped_ptr<dbus::Response> response =
257 dbus::Response::FromMethodCall(method_call);
258 dbus::MessageWriter writer(response.get());
259 dbus::MessageWriter variant_writer(NULL);
260
261 writer.OpenVariant("ay", &variant_writer);
262 variant_writer.AppendArrayOfBytes(value.data(), value.size());
263 writer.CloseContainer(&variant_writer);
264
265 response_sender.Run(response.Pass());
266 }
267
268 void AppendType(dbus::MessageWriter* array_writer) {
269 dbus::MessageWriter dict_entry_writer(NULL);
270 array_writer->OpenDictEntry(&dict_entry_writer);
271 dict_entry_writer.AppendString(bluetooth_advertisement::kTypeProperty);
272 if (type_ == BROADCAST) {
273 dict_entry_writer.AppendString("broadcast");
274 } else {
275 dict_entry_writer.AppendString("peripheral");
276 }
277 array_writer->CloseContainer(&dict_entry_writer);
278 }
279
280 void AppendServiceUUIDs(dbus::MessageWriter* array_writer) {
281 dbus::MessageWriter dict_entry_writer(NULL);
282 array_writer->OpenDictEntry(&dict_entry_writer);
283 dict_entry_writer.AppendString(
284 bluetooth_advertisement::kServiceUUIDsProperty);
285 dict_entry_writer.AppendArrayOfStrings(*service_uuids_);
286 array_writer->CloseContainer(&dict_entry_writer);
287 }
288
289 void AppendManufacturerData(dbus::MessageWriter* array_writer) {
290 dbus::MessageWriter dict_entry_writer(NULL);
291 array_writer->OpenDictEntry(&dict_entry_writer);
292 dict_entry_writer.AppendString(
293 bluetooth_advertisement::kManufacturerDataProperty);
294 dbus::MessageWriter variant_writer(NULL);
295 dict_entry_writer.OpenVariant("a{qay}", &variant_writer);
296 AppendManufacturerDataVariant(&variant_writer);
297 dict_entry_writer.CloseContainer(&variant_writer);
298 array_writer->CloseContainer(&dict_entry_writer);
299 }
300
301 void AppendSolicitUUIDs(dbus::MessageWriter* array_writer) {
302 dbus::MessageWriter dict_entry_writer(NULL);
303 array_writer->OpenDictEntry(&dict_entry_writer);
304 dict_entry_writer.AppendString(
305 bluetooth_advertisement::kSolicitUUIDsProperty);
306 dict_entry_writer.AppendArrayOfStrings(*solicit_uuids_);
307 array_writer->CloseContainer(&dict_entry_writer);
308 }
309
310 void AppendServiceData(dbus::MessageWriter* array_writer) {
311 dbus::MessageWriter dict_entry_writer(NULL);
312 array_writer->OpenDictEntry(&dict_entry_writer);
313 dict_entry_writer.AppendString(
314 bluetooth_advertisement::kServiceDataProperty);
315 dbus::MessageWriter variant_writer(NULL);
316 dict_entry_writer.OpenVariant("a{say}", &variant_writer);
317 AppendServiceDataVariant(&variant_writer);
318 dict_entry_writer.CloseContainer(&variant_writer);
319 array_writer->CloseContainer(&dict_entry_writer);
320 }
321
322 void AppendManufacturerDataVariant(dbus::MessageWriter* writer) {
323 dbus::MessageWriter array_writer(NULL);
324 writer->OpenArray("{qay}", &array_writer);
325 for (const auto& m : *manufacturer_data_) {
326 dbus::MessageWriter entry_writer(NULL);
327
328 array_writer.OpenDictEntry(&entry_writer);
329
330 entry_writer.AppendUint32(m.first);
331 entry_writer.AppendArrayOfBytes(vector_as_array(&m.second),
332 m.second.size());
333
334 array_writer.CloseContainer(&entry_writer);
335 }
336 writer->CloseContainer(&array_writer);
337 }
338
339 void AppendServiceDataVariant(dbus::MessageWriter* writer) {
340 dbus::MessageWriter array_writer(NULL);
341 writer->OpenArray("{say}", &array_writer);
342 for (const auto& m : *service_data_) {
343 dbus::MessageWriter entry_writer(NULL);
344
345 array_writer.OpenDictEntry(&entry_writer);
346
347 entry_writer.AppendString(m.first);
348 entry_writer.AppendArrayOfBytes(vector_as_array(&m.second),
349 m.second.size());
350
351 array_writer.CloseContainer(&entry_writer);
352 }
353 writer->CloseContainer(&array_writer);
354 }
355
356 // Origin thread (i.e. the UI thread in production).
357 base::PlatformThreadId origin_thread_id_;
358
359 // D-Bus bus object is exported on, not owned by this object and must
360 // outlive it.
361 dbus::Bus* bus_;
362
363 // All incoming method calls are passed on to the Delegate and a callback
364 // passed to generate the reply. |delegate_| is generally the object that
365 // owns this one, and must outlive it.
366 Delegate* delegate_;
367
368 // D-Bus object path of object we are exporting, kept so we can unregister
369 // again in our destructor.
370 dbus::ObjectPath object_path_;
371
372 // Advertisement data that needs to be provided to BlueZ when requested.
373 AdvertisementType type_;
374 scoped_ptr<UUIDList> service_uuids_;
375 scoped_ptr<ManufacturerData> manufacturer_data_;
376 scoped_ptr<UUIDList> solicit_uuids_;
377 scoped_ptr<ServiceData> service_data_;
378
379 // D-Bus object we are exporting, owned by this object.
380 scoped_refptr<dbus::ExportedObject> exported_object_;
381
382 // Weak pointer factory for generating 'this' pointers that might live longer
383 // than we do.
384 // Note: This should remain the last member so it'll be destroyed and
385 // invalidate its weak pointers before any other members are destroyed.
386 base::WeakPtrFactory<BluetoothAdvertisementServiceProviderImpl>
387 weak_ptr_factory_;
388
389 DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementServiceProviderImpl);
390 };
391
392 BluetoothAdvertisementServiceProvider::BluetoothAdvertisementServiceProvider() {
393 }
394
395 BluetoothAdvertisementServiceProvider::
396 ~BluetoothAdvertisementServiceProvider() {
397 }
398
399 // static
400 BluetoothAdvertisementServiceProvider*
401 BluetoothAdvertisementServiceProvider::Create(
402 dbus::Bus* bus,
403 const dbus::ObjectPath& object_path,
404 Delegate* delegate,
405 AdvertisementType type,
406 scoped_ptr<UUIDList> service_uuids,
407 scoped_ptr<ManufacturerData> manufacturer_data,
408 scoped_ptr<UUIDList> solicit_uuids,
409 scoped_ptr<ServiceData> service_data) {
410 if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
411 return new BluetoothAdvertisementServiceProviderImpl(
412 bus, object_path, delegate, type, service_uuids.Pass(),
413 manufacturer_data.Pass(), solicit_uuids.Pass(), service_data.Pass());
414 } else {
415 return new FakeBluetoothAdvertisementServiceProvider(object_path, delegate);
416 }
417 }
418
419 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698