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

Side by Side Diff: device/bluetooth/dbus/bluetooth_gatt_characteristic_service_provider_impl.cc

Issue 1914893002: DBus changes for implementing local GATT attributes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@bluetooth_classes
Patch Set: test leak fix Created 4 years, 7 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 2016 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/dbus/bluetooth_gatt_characteristic_service_provider_i mpl.h"
6
7 #include <stddef.h>
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "third_party/cros_system_api/dbus/service_constants.h"
13
14 namespace bluez {
15
16 namespace {
17
18 const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
19 const char kErrorPropertyReadOnly[] =
20 "org.freedesktop.DBus.Error.PropertyReadOnly";
21 const char kErrorFailed[] = "org.freedesktop.DBus.Error.Failed";
22
23 } // namespace
24
25 BluetoothGattCharacteristicServiceProviderImpl::
26 BluetoothGattCharacteristicServiceProviderImpl(
27 dbus::Bus* bus,
28 const dbus::ObjectPath& object_path,
29 std::unique_ptr<BluetoothGattAttributeValueDelegate> delegate,
30 const std::string& uuid,
31 const std::vector<std::string>& flags,
32 const std::vector<std::string>& permissions,
33 const dbus::ObjectPath& service_path)
34 : origin_thread_id_(base::PlatformThread::CurrentId()),
35 uuid_(uuid),
36 bus_(bus),
37 delegate_(std::move(delegate)),
38 object_path_(object_path),
39 service_path_(service_path),
40 weak_ptr_factory_(this) {
41 VLOG(1) << "Created Bluetooth GATT characteristic: " << object_path.value()
42 << " UUID: " << uuid;
43 DCHECK(bus_);
44 DCHECK(delegate_);
45 DCHECK(!uuid_.empty());
46 DCHECK(object_path_.IsValid());
47 DCHECK(service_path_.IsValid());
48 DCHECK(base::StartsWith(object_path_.value(), service_path_.value() + "/",
49 base::CompareCase::SENSITIVE));
50
51 exported_object_ = bus_->GetExportedObject(object_path_);
52
53 exported_object_->ExportMethod(
54 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
55 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Get,
56 weak_ptr_factory_.GetWeakPtr()),
57 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
58 weak_ptr_factory_.GetWeakPtr()));
59
60 exported_object_->ExportMethod(
61 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet,
62 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::Set,
63 weak_ptr_factory_.GetWeakPtr()),
64 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
65 weak_ptr_factory_.GetWeakPtr()));
66
67 exported_object_->ExportMethod(
68 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
69 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::GetAll,
70 weak_ptr_factory_.GetWeakPtr()),
71 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnExported,
72 weak_ptr_factory_.GetWeakPtr()));
73 }
74
75 BluetoothGattCharacteristicServiceProviderImpl::
76 ~BluetoothGattCharacteristicServiceProviderImpl() {
77 VLOG(1) << "Cleaning up Bluetooth GATT characteristic: "
78 << object_path_.value();
79 if (bus_)
80 bus_->UnregisterExportedObject(object_path_);
81 }
82
83 BluetoothGattCharacteristicServiceProviderImpl::
84 BluetoothGattCharacteristicServiceProviderImpl(
85 const dbus::ObjectPath& object_path,
86 const std::string& uuid,
87 const dbus::ObjectPath& service_path)
88 : origin_thread_id_(base::PlatformThread::CurrentId()),
89 uuid_(uuid),
90 bus_(nullptr),
91 delegate_(nullptr),
92 object_path_(object_path),
93 service_path_(service_path),
94 weak_ptr_factory_(this) {}
95
96 void BluetoothGattCharacteristicServiceProviderImpl::SendValueChanged(
97 const std::vector<uint8_t>& value) {
98 VLOG(2) << "Emitting a PropertiesChanged signal for characteristic value.";
99 dbus::Signal signal(dbus::kDBusPropertiesInterface,
100 dbus::kDBusPropertiesChangedSignal);
101 dbus::MessageWriter writer(&signal);
102 dbus::MessageWriter array_writer(NULL);
103 dbus::MessageWriter dict_entry_writer(NULL);
104 dbus::MessageWriter variant_writer(NULL);
105
106 // interface_name
107 writer.AppendString(
108 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface);
109
110 // changed_properties
111 writer.OpenArray("{sv}", &array_writer);
112 array_writer.OpenDictEntry(&dict_entry_writer);
113 dict_entry_writer.AppendString(bluetooth_gatt_characteristic::kValueProperty);
114 dict_entry_writer.OpenVariant("ay", &variant_writer);
115 variant_writer.AppendArrayOfBytes(value.data(), value.size());
116 dict_entry_writer.CloseContainer(&variant_writer);
117 array_writer.CloseContainer(&dict_entry_writer);
118 writer.CloseContainer(&array_writer);
119
120 // invalidated_properties.
121 writer.OpenArray("s", &array_writer);
122 writer.CloseContainer(&array_writer);
123
124 exported_object_->SendSignal(&signal);
125 }
126
127 // Returns true if the current thread is on the origin thread.
128 bool BluetoothGattCharacteristicServiceProviderImpl::OnOriginThread() {
129 return base::PlatformThread::CurrentId() == origin_thread_id_;
130 }
131
132 void BluetoothGattCharacteristicServiceProviderImpl::Get(
133 dbus::MethodCall* method_call,
134 dbus::ExportedObject::ResponseSender response_sender) {
135 VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Get: "
136 << object_path_.value();
137 DCHECK(OnOriginThread());
138
139 dbus::MessageReader reader(method_call);
140
141 std::string interface_name;
142 std::string property_name;
143 if (!reader.PopString(&interface_name) || !reader.PopString(&property_name) ||
144 reader.HasMoreData()) {
145 std::unique_ptr<dbus::ErrorResponse> error_response =
146 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
147 "Expected 'ss'.");
148 response_sender.Run(std::move(error_response));
149 return;
150 }
151
152 // Only the GATT characteristic interface is supported.
153 if (interface_name !=
154 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) {
155 std::unique_ptr<dbus::ErrorResponse> error_response =
156 dbus::ErrorResponse::FromMethodCall(
157 method_call, kErrorInvalidArgs,
158 "No such interface: '" + interface_name + "'.");
159 response_sender.Run(std::move(error_response));
160 return;
161 }
162
163 // If getting the "Value" property, obtain the value from the delegate.
164 if (property_name == bluetooth_gatt_characteristic::kValueProperty) {
165 DCHECK(delegate_);
166 delegate_->GetValue(
167 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGet,
168 weak_ptr_factory_.GetWeakPtr(), method_call,
169 response_sender),
170 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
171 weak_ptr_factory_.GetWeakPtr(), method_call,
172 response_sender));
173 return;
174 }
175
176 std::unique_ptr<dbus::Response> response =
177 dbus::Response::FromMethodCall(method_call);
178 dbus::MessageWriter writer(response.get());
179 dbus::MessageWriter variant_writer(NULL);
180
181 // TODO(armansito): Process the "Flags" and "Permissions" properties below.
182 if (property_name == bluetooth_gatt_characteristic::kUUIDProperty) {
183 writer.OpenVariant("s", &variant_writer);
184 variant_writer.AppendString(uuid_);
185 writer.CloseContainer(&variant_writer);
186 } else if (property_name == bluetooth_gatt_characteristic::kServiceProperty) {
187 writer.OpenVariant("o", &variant_writer);
188 variant_writer.AppendObjectPath(service_path_);
189 writer.CloseContainer(&variant_writer);
190 } else {
191 response = dbus::ErrorResponse::FromMethodCall(
192 method_call, kErrorInvalidArgs,
193 "No such property: '" + property_name + "'.");
194 }
195
196 response_sender.Run(std::move(response));
197 }
198
199 void BluetoothGattCharacteristicServiceProviderImpl::Set(
200 dbus::MethodCall* method_call,
201 dbus::ExportedObject::ResponseSender response_sender) {
202 VLOG(2) << "BluetoothGattCharacteristicServiceProvider::Set: "
203 << object_path_.value();
204 DCHECK(OnOriginThread());
205
206 dbus::MessageReader reader(method_call);
207
208 std::string interface_name;
209 std::string property_name;
210 dbus::MessageReader variant_reader(NULL);
211 if (!reader.PopString(&interface_name) || !reader.PopString(&property_name) ||
212 !reader.PopVariant(&variant_reader) || reader.HasMoreData()) {
213 std::unique_ptr<dbus::ErrorResponse> error_response =
214 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
215 "Expected 'ssv'.");
216 response_sender.Run(std::move(error_response));
217 return;
218 }
219
220 // Only the GATT characteristic interface is allowed.
221 if (interface_name !=
222 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) {
223 std::unique_ptr<dbus::ErrorResponse> error_response =
224 dbus::ErrorResponse::FromMethodCall(
225 method_call, kErrorInvalidArgs,
226 "No such interface: '" + interface_name + "'.");
227 response_sender.Run(std::move(error_response));
228 return;
229 }
230
231 // Only the "Value" property is writeable.
232 if (property_name != bluetooth_gatt_characteristic::kValueProperty) {
233 std::string error_name;
234 std::string error_message;
235 if (property_name == bluetooth_gatt_characteristic::kUUIDProperty ||
236 property_name == bluetooth_gatt_characteristic::kServiceProperty) {
237 error_name = kErrorPropertyReadOnly;
238 error_message = "Read-only property: '" + property_name + "'.";
239 } else {
240 error_name = kErrorInvalidArgs;
241 error_message = "No such property: '" + property_name + "'.";
242 }
243 std::unique_ptr<dbus::ErrorResponse> error_response =
244 dbus::ErrorResponse::FromMethodCall(method_call, error_name,
245 error_message);
246 response_sender.Run(std::move(error_response));
247 return;
248 }
249
250 // Obtain the value.
251 const uint8_t* bytes = NULL;
252 size_t length = 0;
253 if (!variant_reader.PopArrayOfBytes(&bytes, &length)) {
254 std::unique_ptr<dbus::ErrorResponse> error_response =
255 dbus::ErrorResponse::FromMethodCall(
256 method_call, kErrorInvalidArgs,
257 "Property '" + property_name + "' has type 'ay'.");
258 response_sender.Run(std::move(error_response));
259 return;
260 }
261
262 // Pass the set request onto the delegate.
263 std::vector<uint8_t> value(bytes, bytes + length);
264 DCHECK(delegate_);
265 delegate_->SetValue(
266 value,
267 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnSet,
268 weak_ptr_factory_.GetWeakPtr(), method_call, response_sender),
269 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
270 weak_ptr_factory_.GetWeakPtr(), method_call, response_sender));
271 }
272
273 void BluetoothGattCharacteristicServiceProviderImpl::GetAll(
274 dbus::MethodCall* method_call,
275 dbus::ExportedObject::ResponseSender response_sender) {
276 VLOG(2) << "BluetoothGattCharacteristicServiceProvider::GetAll: "
277 << object_path_.value();
278 DCHECK(OnOriginThread());
279
280 dbus::MessageReader reader(method_call);
281
282 std::string interface_name;
283 if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
284 std::unique_ptr<dbus::ErrorResponse> error_response =
285 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
286 "Expected 's'.");
287 response_sender.Run(std::move(error_response));
288 return;
289 }
290
291 // Only the GATT characteristic interface is supported.
292 if (interface_name !=
293 bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface) {
294 std::unique_ptr<dbus::ErrorResponse> error_response =
295 dbus::ErrorResponse::FromMethodCall(
296 method_call, kErrorInvalidArgs,
297 "No such interface: '" + interface_name + "'.");
298 response_sender.Run(std::move(error_response));
299 return;
300 }
301
302 // Try to obtain the value from the delegate. We will construct the
303 // response in the success callback.
304 DCHECK(delegate_);
305 delegate_->GetValue(
306 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnGetAll,
307 weak_ptr_factory_.GetWeakPtr(), method_call, response_sender),
308 base::Bind(&BluetoothGattCharacteristicServiceProviderImpl::OnFailure,
309 weak_ptr_factory_.GetWeakPtr(), method_call, response_sender));
310 }
311
312 void BluetoothGattCharacteristicServiceProviderImpl::OnExported(
313 const std::string& interface_name,
314 const std::string& method_name,
315 bool success) {
316 LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "."
317 << method_name;
318 }
319
320 void BluetoothGattCharacteristicServiceProviderImpl::OnGetAll(
321 dbus::MethodCall* method_call,
322 dbus::ExportedObject::ResponseSender response_sender,
323 const std::vector<uint8_t>& value) {
324 VLOG(2) << "Characteristic value obtained from delegate. Responding to "
325 << "GetAll.";
326
327 std::unique_ptr<dbus::Response> response =
328 dbus::Response::FromMethodCall(method_call);
329 dbus::MessageWriter writer(response.get());
330 WriteProperties(&writer, &value);
331 response_sender.Run(std::move(response));
332 }
333
334 void BluetoothGattCharacteristicServiceProviderImpl::WriteProperties(
335 dbus::MessageWriter* writer,
336 const std::vector<uint8_t>* value) {
337 dbus::MessageWriter array_writer(NULL);
338 dbus::MessageWriter dict_entry_writer(NULL);
339 dbus::MessageWriter variant_writer(NULL);
340
341 writer->OpenArray("{sv}", &array_writer);
342
343 array_writer.OpenDictEntry(&dict_entry_writer);
344 dict_entry_writer.AppendString(bluetooth_gatt_characteristic::kUUIDProperty);
345 dict_entry_writer.AppendVariantOfString(uuid_);
346 array_writer.CloseContainer(&dict_entry_writer);
347
348 array_writer.OpenDictEntry(&dict_entry_writer);
349 dict_entry_writer.AppendString(
350 bluetooth_gatt_characteristic::kServiceProperty);
351 dict_entry_writer.AppendVariantOfObjectPath(service_path_);
352 array_writer.CloseContainer(&dict_entry_writer);
353
354 if (value) {
355 array_writer.OpenDictEntry(&dict_entry_writer);
356 dict_entry_writer.AppendString(
357 bluetooth_gatt_characteristic::kValueProperty);
358 dict_entry_writer.OpenVariant("ay", &variant_writer);
359 variant_writer.AppendArrayOfBytes(value->data(), value->size());
360 dict_entry_writer.CloseContainer(&variant_writer);
361 array_writer.CloseContainer(&dict_entry_writer);
362 }
363
364 // TODO(armansito): Process Flags & Permissions properties.
365
366 writer->CloseContainer(&array_writer);
367 };
368
369 void BluetoothGattCharacteristicServiceProviderImpl::OnGet(
370 dbus::MethodCall* method_call,
371 dbus::ExportedObject::ResponseSender response_sender,
372 const std::vector<uint8_t>& value) {
373 VLOG(2) << "Returning characteristic value obtained from delegate.";
374 std::unique_ptr<dbus::Response> response =
375 dbus::Response::FromMethodCall(method_call);
376 dbus::MessageWriter writer(response.get());
377 dbus::MessageWriter variant_writer(NULL);
378
379 writer.OpenVariant("ay", &variant_writer);
380 variant_writer.AppendArrayOfBytes(value.data(), value.size());
381 writer.CloseContainer(&variant_writer);
382
383 response_sender.Run(std::move(response));
384 }
385
386 void BluetoothGattCharacteristicServiceProviderImpl::OnSet(
387 dbus::MethodCall* method_call,
388 dbus::ExportedObject::ResponseSender response_sender) {
389 VLOG(2) << "Successfully set characteristic value. Return success.";
390 response_sender.Run(dbus::Response::FromMethodCall(method_call));
391 }
392
393 void BluetoothGattCharacteristicServiceProviderImpl::OnFailure(
394 dbus::MethodCall* method_call,
395 dbus::ExportedObject::ResponseSender response_sender) {
396 VLOG(2) << "Failed to get/set characteristic value. Report error.";
397 std::unique_ptr<dbus::ErrorResponse> error_response =
398 dbus::ErrorResponse::FromMethodCall(
399 method_call, kErrorFailed, "Failed to get/set characteristic value.");
400 response_sender.Run(std::move(error_response));
401 }
402
403 const dbus::ObjectPath&
404 BluetoothGattCharacteristicServiceProviderImpl::object_path() const {
405 return object_path_;
406 }
407
408 } // namespace bluez
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698