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

Side by Side Diff: device/bluetooth/dbus/bluetooth_gatt_service_service_provider.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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h" 5 #include "device/bluetooth/dbus/bluetooth_gatt_service_service_provider.h"
6 6
7 #include <memory> 7 #include "device/bluetooth/dbus/bluetooth_gatt_service_service_provider_impl.h"
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/threading/platform_thread.h"
16 #include "dbus/exported_object.h"
17 #include "dbus/message.h"
18 #include "device/bluetooth/dbus/bluez_dbus_manager.h" 8 #include "device/bluetooth/dbus/bluez_dbus_manager.h"
19 #include "device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h" 9 #include "device/bluetooth/dbus/fake_bluetooth_gatt_service_service_provider.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
21 10
22 namespace bluez { 11 namespace bluez {
23 namespace {
24 const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
25 const char kErrorPropertyReadOnly[] =
26 "org.freedesktop.DBus.Error.PropertyReadOnly";
27 } // namespace
28
29 // The BluetoothGattServiceServiceProvider implementation used in production.
30 class BluetoothGattServiceServiceProviderImpl
31 : public BluetoothGattServiceServiceProvider {
32 public:
33 BluetoothGattServiceServiceProviderImpl(
34 dbus::Bus* bus,
35 const dbus::ObjectPath& object_path,
36 const std::string& uuid,
37 const std::vector<dbus::ObjectPath>& includes)
38 : origin_thread_id_(base::PlatformThread::CurrentId()),
39 uuid_(uuid),
40 includes_(includes),
41 bus_(bus),
42 object_path_(object_path),
43 weak_ptr_factory_(this) {
44 VLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value()
45 << " UUID: " << uuid;
46 DCHECK(!uuid_.empty());
47 DCHECK(object_path_.IsValid());
48 DCHECK(bus_);
49
50 exported_object_ = bus_->GetExportedObject(object_path_);
51
52 exported_object_->ExportMethod(
53 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
54 base::Bind(&BluetoothGattServiceServiceProviderImpl::Get,
55 weak_ptr_factory_.GetWeakPtr()),
56 base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
57 weak_ptr_factory_.GetWeakPtr()));
58
59 exported_object_->ExportMethod(
60 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet,
61 base::Bind(&BluetoothGattServiceServiceProviderImpl::Set,
62 weak_ptr_factory_.GetWeakPtr()),
63 base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
64 weak_ptr_factory_.GetWeakPtr()));
65
66 exported_object_->ExportMethod(
67 dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
68 base::Bind(&BluetoothGattServiceServiceProviderImpl::GetAll,
69 weak_ptr_factory_.GetWeakPtr()),
70 base::Bind(&BluetoothGattServiceServiceProviderImpl::OnExported,
71 weak_ptr_factory_.GetWeakPtr()));
72 }
73
74 ~BluetoothGattServiceServiceProviderImpl() override {
75 VLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value();
76 bus_->UnregisterExportedObject(object_path_);
77 }
78
79 private:
80 // Returns true if the current thread is on the origin thread.
81 bool OnOriginThread() {
82 return base::PlatformThread::CurrentId() == origin_thread_id_;
83 }
84
85 // Called by dbus:: when the Bluetooth daemon fetches a single property of
86 // the service.
87 void Get(dbus::MethodCall* method_call,
88 dbus::ExportedObject::ResponseSender response_sender) {
89 VLOG(2) << "BluetoothGattServiceServiceProvider::Get: "
90 << object_path_.value();
91 DCHECK(OnOriginThread());
92
93 dbus::MessageReader reader(method_call);
94
95 std::string interface_name;
96 std::string property_name;
97 if (!reader.PopString(&interface_name) ||
98 !reader.PopString(&property_name) || reader.HasMoreData()) {
99 std::unique_ptr<dbus::ErrorResponse> error_response =
100 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
101 "Expected 'ss'.");
102 response_sender.Run(std::move(error_response));
103 return;
104 }
105
106 // Only the GATT service interface is allowed.
107 if (interface_name !=
108 bluetooth_gatt_service::kBluetoothGattServiceInterface) {
109 std::unique_ptr<dbus::ErrorResponse> error_response =
110 dbus::ErrorResponse::FromMethodCall(
111 method_call, kErrorInvalidArgs,
112 "No such interface: '" + interface_name + "'.");
113 response_sender.Run(std::move(error_response));
114 return;
115 }
116
117 // Return error if |property_name| is unknown.
118 if (property_name != bluetooth_gatt_service::kUUIDProperty &&
119 property_name != bluetooth_gatt_service::kIncludesProperty) {
120 std::unique_ptr<dbus::ErrorResponse> error_response =
121 dbus::ErrorResponse::FromMethodCall(
122 method_call, kErrorInvalidArgs,
123 "No such property: '" + property_name + "'.");
124 response_sender.Run(std::move(error_response));
125 return;
126 }
127
128 std::unique_ptr<dbus::Response> response =
129 dbus::Response::FromMethodCall(method_call);
130 dbus::MessageWriter writer(response.get());
131 dbus::MessageWriter variant_writer(NULL);
132
133 if (property_name == bluetooth_gatt_service::kUUIDProperty) {
134 writer.OpenVariant("s", &variant_writer);
135 variant_writer.AppendString(uuid_);
136 writer.CloseContainer(&variant_writer);
137 } else {
138 writer.OpenVariant("ao", &variant_writer);
139 variant_writer.AppendArrayOfObjectPaths(includes_);
140 writer.CloseContainer(&variant_writer);
141 }
142
143 response_sender.Run(std::move(response));
144 }
145
146 // Called by dbus:: when the Bluetooth daemon sets a single property of the
147 // service.
148 void Set(dbus::MethodCall* method_call,
149 dbus::ExportedObject::ResponseSender response_sender) {
150 VLOG(2) << "BluetoothGattServiceServiceProvider::Set: "
151 << object_path_.value();
152 DCHECK(OnOriginThread());
153
154 // All of the properties on this interface are read-only, so just return
155 // error.
156 std::unique_ptr<dbus::ErrorResponse> error_response =
157 dbus::ErrorResponse::FromMethodCall(method_call, kErrorPropertyReadOnly,
158 "All properties are read-only.");
159 response_sender.Run(std::move(error_response));
160 }
161
162 // Called by dbus:: when the Bluetooth daemon fetches all properties of the
163 // service.
164 void GetAll(dbus::MethodCall* method_call,
165 dbus::ExportedObject::ResponseSender response_sender) {
166 VLOG(2) << "BluetoothGattServiceServiceProvider::GetAll: "
167 << object_path_.value();
168 DCHECK(OnOriginThread());
169
170 dbus::MessageReader reader(method_call);
171
172 std::string interface_name;
173 if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
174 std::unique_ptr<dbus::ErrorResponse> error_response =
175 dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
176 "Expected 's'.");
177 response_sender.Run(std::move(error_response));
178 return;
179 }
180
181 // Only the GATT service interface is allowed.
182 if (interface_name !=
183 bluetooth_gatt_service::kBluetoothGattServiceInterface) {
184 std::unique_ptr<dbus::ErrorResponse> error_response =
185 dbus::ErrorResponse::FromMethodCall(
186 method_call, kErrorInvalidArgs,
187 "No such interface: '" + interface_name + "'.");
188 response_sender.Run(std::move(error_response));
189 return;
190 }
191
192 std::unique_ptr<dbus::Response> response =
193 dbus::Response::FromMethodCall(method_call);
194 dbus::MessageWriter writer(response.get());
195 dbus::MessageWriter array_writer(NULL);
196 dbus::MessageWriter dict_entry_writer(NULL);
197 dbus::MessageWriter variant_writer(NULL);
198
199 writer.OpenArray("{sv}", &array_writer);
200
201 array_writer.OpenDictEntry(&dict_entry_writer);
202 dict_entry_writer.AppendString(bluetooth_gatt_service::kUUIDProperty);
203 dict_entry_writer.AppendVariantOfString(uuid_);
204 array_writer.CloseContainer(&dict_entry_writer);
205
206 array_writer.OpenDictEntry(&dict_entry_writer);
207 dict_entry_writer.AppendString(bluetooth_gatt_service::kIncludesProperty);
208 dict_entry_writer.OpenVariant("ao", &variant_writer);
209 variant_writer.AppendArrayOfObjectPaths(includes_);
210 dict_entry_writer.CloseContainer(&variant_writer);
211 array_writer.CloseContainer(&dict_entry_writer);
212
213 writer.CloseContainer(&array_writer);
214
215 response_sender.Run(std::move(response));
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 // Origin thread (i.e. the UI thread in production).
227 base::PlatformThreadId origin_thread_id_;
228
229 // 128-bit service UUID of this object.
230 std::string uuid_;
231
232 // List of object paths that represent other exported GATT services that are
233 // included from this service.
234 std::vector<dbus::ObjectPath> includes_;
235
236 // D-Bus bus object is exported on, not owned by this object and must
237 // outlive it.
238 dbus::Bus* bus_;
239
240 // D-Bus object path of object we are exporting, kept so we can unregister
241 // again in our destructor.
242 dbus::ObjectPath object_path_;
243
244 // D-Bus object we are exporting, owned by this object.
245 scoped_refptr<dbus::ExportedObject> exported_object_;
246
247 // Weak pointer factory for generating 'this' pointers that might live longer
248 // than we do.
249 // Note: This should remain the last member so it'll be destroyed and
250 // invalidate its weak pointers before any other members are destroyed.
251 base::WeakPtrFactory<BluetoothGattServiceServiceProviderImpl>
252 weak_ptr_factory_;
253
254 DISALLOW_COPY_AND_ASSIGN(BluetoothGattServiceServiceProviderImpl);
255 };
256 12
257 BluetoothGattServiceServiceProvider::BluetoothGattServiceServiceProvider() {} 13 BluetoothGattServiceServiceProvider::BluetoothGattServiceServiceProvider() {}
258 14
259 BluetoothGattServiceServiceProvider::~BluetoothGattServiceServiceProvider() {} 15 BluetoothGattServiceServiceProvider::~BluetoothGattServiceServiceProvider() {}
260 16
261 // static 17 // static
262 BluetoothGattServiceServiceProvider* 18 BluetoothGattServiceServiceProvider*
263 BluetoothGattServiceServiceProvider::Create( 19 BluetoothGattServiceServiceProvider::Create(
264 dbus::Bus* bus, 20 dbus::Bus* bus,
265 const dbus::ObjectPath& object_path, 21 const dbus::ObjectPath& object_path,
266 const std::string& uuid, 22 const std::string& uuid,
267 const std::vector<dbus::ObjectPath>& includes) { 23 const std::vector<dbus::ObjectPath>& includes) {
268 if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) { 24 if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) {
269 return new BluetoothGattServiceServiceProviderImpl(bus, object_path, uuid, 25 return new BluetoothGattServiceServiceProviderImpl(bus, object_path, uuid,
270 includes); 26 includes);
271 } 27 }
272 return new FakeBluetoothGattServiceServiceProvider(object_path, uuid, 28 return new FakeBluetoothGattServiceServiceProvider(object_path, uuid,
273 includes); 29 includes);
274 } 30 }
275 31
276 } // namespace bluez 32 } // namespace bluez
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698