bluetooth_gatt_descriptor_service_provider_impl.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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. #include "device/bluetooth/dbus/bluetooth_gatt_descriptor_service_provider_impl.h"
  5. #include <cstddef>
  6. #include "base/bind.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/logging.h"
  9. #include "base/strings/string_util.h"
  10. #include "device/bluetooth/bluetooth_gatt_service.h"
  11. #include "device/bluetooth/dbus/bluetooth_gatt_attribute_helpers.h"
  12. #include "third_party/cros_system_api/dbus/service_constants.h"
  13. namespace bluez {
  14. namespace {
  15. const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
  16. const char kErrorPropertyReadOnly[] =
  17. "org.freedesktop.DBus.Error.PropertyReadOnly";
  18. const char kErrorFailed[] = "org.freedesktop.DBus.Error.Failed";
  19. } // namespace
  20. // The BluetoothGattDescriptorServiceProvider implementation used in production.
  21. BluetoothGattDescriptorServiceProviderImpl::
  22. BluetoothGattDescriptorServiceProviderImpl(
  23. dbus::Bus* bus,
  24. const dbus::ObjectPath& object_path,
  25. std::unique_ptr<BluetoothGattAttributeValueDelegate> delegate,
  26. const std::string& uuid,
  27. const std::vector<std::string>& flags,
  28. const dbus::ObjectPath& characteristic_path)
  29. : origin_thread_id_(base::PlatformThread::CurrentId()),
  30. uuid_(uuid),
  31. flags_(flags),
  32. bus_(bus),
  33. delegate_(std::move(delegate)),
  34. object_path_(object_path),
  35. characteristic_path_(characteristic_path) {
  36. DVLOG(1) << "Created Bluetooth GATT characteristic descriptor: "
  37. << object_path.value() << " UUID: " << uuid;
  38. if (!bus_)
  39. return;
  40. DCHECK(delegate_);
  41. DCHECK(!uuid_.empty());
  42. DCHECK(object_path_.IsValid());
  43. DCHECK(characteristic_path_.IsValid());
  44. DCHECK(base::StartsWith(object_path_.value(),
  45. characteristic_path_.value() + "/",
  46. base::CompareCase::SENSITIVE));
  47. exported_object_ = bus_->GetExportedObject(object_path_);
  48. exported_object_->ExportMethod(
  49. dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
  50. base::BindRepeating(&BluetoothGattDescriptorServiceProviderImpl::Get,
  51. weak_ptr_factory_.GetWeakPtr()),
  52. base::BindOnce(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
  53. weak_ptr_factory_.GetWeakPtr()));
  54. exported_object_->ExportMethod(
  55. dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet,
  56. base::BindRepeating(&BluetoothGattDescriptorServiceProviderImpl::Set,
  57. weak_ptr_factory_.GetWeakPtr()),
  58. base::BindOnce(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
  59. weak_ptr_factory_.GetWeakPtr()));
  60. exported_object_->ExportMethod(
  61. dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
  62. base::BindRepeating(&BluetoothGattDescriptorServiceProviderImpl::GetAll,
  63. weak_ptr_factory_.GetWeakPtr()),
  64. base::BindOnce(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
  65. weak_ptr_factory_.GetWeakPtr()));
  66. // org.bluez.GattDescriptor1 interface:
  67. exported_object_->ExportMethod(
  68. bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
  69. bluetooth_gatt_descriptor::kReadValue,
  70. base::BindRepeating(
  71. &BluetoothGattDescriptorServiceProviderImpl::ReadValue,
  72. weak_ptr_factory_.GetWeakPtr()),
  73. base::BindOnce(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
  74. weak_ptr_factory_.GetWeakPtr()));
  75. exported_object_->ExportMethod(
  76. bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface,
  77. bluetooth_gatt_descriptor::kWriteValue,
  78. base::BindRepeating(
  79. &BluetoothGattDescriptorServiceProviderImpl::WriteValue,
  80. weak_ptr_factory_.GetWeakPtr()),
  81. base::BindOnce(&BluetoothGattDescriptorServiceProviderImpl::OnExported,
  82. weak_ptr_factory_.GetWeakPtr()));
  83. }
  84. BluetoothGattDescriptorServiceProviderImpl::
  85. ~BluetoothGattDescriptorServiceProviderImpl() {
  86. DVLOG(1) << "Cleaning up Bluetooth GATT characteristic descriptor: "
  87. << object_path_.value();
  88. if (bus_)
  89. bus_->UnregisterExportedObject(object_path_);
  90. }
  91. void BluetoothGattDescriptorServiceProviderImpl::SendValueChanged(
  92. const std::vector<uint8_t>& value) {
  93. DVLOG(2) << "Emitting a PropertiesChanged signal for descriptor value.";
  94. dbus::Signal signal(dbus::kDBusPropertiesInterface,
  95. dbus::kDBusPropertiesChangedSignal);
  96. dbus::MessageWriter writer(&signal);
  97. dbus::MessageWriter array_writer(NULL);
  98. dbus::MessageWriter dict_entry_writer(NULL);
  99. dbus::MessageWriter variant_writer(NULL);
  100. // interface_name
  101. writer.AppendString(
  102. bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface);
  103. // changed_properties
  104. writer.OpenArray("{sv}", &array_writer);
  105. array_writer.OpenDictEntry(&dict_entry_writer);
  106. dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kValueProperty);
  107. dict_entry_writer.OpenVariant("ay", &variant_writer);
  108. variant_writer.AppendArrayOfBytes(value.data(), value.size());
  109. dict_entry_writer.CloseContainer(&variant_writer);
  110. array_writer.CloseContainer(&dict_entry_writer);
  111. writer.CloseContainer(&array_writer);
  112. // invalidated_properties.
  113. writer.OpenArray("s", &array_writer);
  114. writer.CloseContainer(&array_writer);
  115. exported_object_->SendSignal(&signal);
  116. }
  117. bool BluetoothGattDescriptorServiceProviderImpl::OnOriginThread() {
  118. return base::PlatformThread::CurrentId() == origin_thread_id_;
  119. }
  120. void BluetoothGattDescriptorServiceProviderImpl::Get(
  121. dbus::MethodCall* method_call,
  122. dbus::ExportedObject::ResponseSender response_sender) {
  123. DVLOG(2) << "BluetoothGattDescriptorServiceProvider::Get: "
  124. << object_path_.value();
  125. DCHECK(OnOriginThread());
  126. dbus::MessageReader reader(method_call);
  127. std::string interface_name;
  128. std::string property_name;
  129. if (!reader.PopString(&interface_name) || !reader.PopString(&property_name) ||
  130. reader.HasMoreData()) {
  131. std::unique_ptr<dbus::ErrorResponse> error_response =
  132. dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
  133. "Expected 'ss'.");
  134. std::move(response_sender).Run(std::move(error_response));
  135. return;
  136. }
  137. // Only the GATT descriptor interface is supported.
  138. if (interface_name !=
  139. bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) {
  140. std::unique_ptr<dbus::ErrorResponse> error_response =
  141. dbus::ErrorResponse::FromMethodCall(
  142. method_call, kErrorInvalidArgs,
  143. "No such interface: '" + interface_name + "'.");
  144. std::move(response_sender).Run(std::move(error_response));
  145. return;
  146. }
  147. std::unique_ptr<dbus::Response> response =
  148. dbus::Response::FromMethodCall(method_call);
  149. dbus::MessageWriter writer(response.get());
  150. dbus::MessageWriter variant_writer(NULL);
  151. if (property_name == bluetooth_gatt_descriptor::kUUIDProperty) {
  152. writer.OpenVariant("s", &variant_writer);
  153. variant_writer.AppendString(uuid_);
  154. writer.CloseContainer(&variant_writer);
  155. } else if (property_name ==
  156. bluetooth_gatt_descriptor::kCharacteristicProperty) {
  157. writer.OpenVariant("o", &variant_writer);
  158. variant_writer.AppendObjectPath(characteristic_path_);
  159. writer.CloseContainer(&variant_writer);
  160. } else if (property_name == bluetooth_gatt_descriptor::kFlagsProperty) {
  161. writer.OpenVariant("as", &variant_writer);
  162. variant_writer.AppendArrayOfStrings(flags_);
  163. writer.CloseContainer(&variant_writer);
  164. } else {
  165. response = dbus::ErrorResponse::FromMethodCall(
  166. method_call, kErrorInvalidArgs,
  167. "No such property: '" + property_name + "'.");
  168. }
  169. std::move(response_sender).Run(std::move(response));
  170. }
  171. void BluetoothGattDescriptorServiceProviderImpl::Set(
  172. dbus::MethodCall* method_call,
  173. dbus::ExportedObject::ResponseSender response_sender) {
  174. DVLOG(2) << "BluetoothGattDescriptorServiceProviderImpl::Set: "
  175. << object_path_.value();
  176. DCHECK(OnOriginThread());
  177. // All of the properties on this interface are read-only, so just return
  178. // error.
  179. std::unique_ptr<dbus::ErrorResponse> error_response =
  180. dbus::ErrorResponse::FromMethodCall(method_call, kErrorPropertyReadOnly,
  181. "All properties are read-only.");
  182. std::move(response_sender).Run(std::move(error_response));
  183. }
  184. void BluetoothGattDescriptorServiceProviderImpl::GetAll(
  185. dbus::MethodCall* method_call,
  186. dbus::ExportedObject::ResponseSender response_sender) {
  187. DVLOG(2) << "BluetoothGattDescriptorServiceProvider::GetAll: "
  188. << object_path_.value();
  189. DCHECK(OnOriginThread());
  190. dbus::MessageReader reader(method_call);
  191. std::string interface_name;
  192. if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
  193. std::unique_ptr<dbus::ErrorResponse> error_response =
  194. dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
  195. "Expected 's'.");
  196. std::move(response_sender).Run(std::move(error_response));
  197. return;
  198. }
  199. // Only the GATT descriptor interface is supported.
  200. if (interface_name !=
  201. bluetooth_gatt_descriptor::kBluetoothGattDescriptorInterface) {
  202. std::unique_ptr<dbus::ErrorResponse> error_response =
  203. dbus::ErrorResponse::FromMethodCall(
  204. method_call, kErrorInvalidArgs,
  205. "No such interface: '" + interface_name + "'.");
  206. std::move(response_sender).Run(std::move(error_response));
  207. return;
  208. }
  209. std::unique_ptr<dbus::Response> response =
  210. dbus::Response::FromMethodCall(method_call);
  211. dbus::MessageWriter writer(response.get());
  212. WriteProperties(&writer);
  213. std::move(response_sender).Run(std::move(response));
  214. }
  215. void BluetoothGattDescriptorServiceProviderImpl::ReadValue(
  216. dbus::MethodCall* method_call,
  217. dbus::ExportedObject::ResponseSender response_sender) {
  218. DVLOG(3) << "BluetoothGattDescriptorServiceProvider::ReadValue: "
  219. << object_path_.value();
  220. DCHECK(OnOriginThread());
  221. dbus::MessageReader reader(method_call);
  222. std::map<std::string, dbus::MessageReader> options;
  223. dbus::ObjectPath device_path;
  224. ReadOptions(&reader, &options);
  225. auto it = options.find(bluetooth_gatt_descriptor::kOptionDevice);
  226. if (it != options.end())
  227. it->second.PopObjectPath(&device_path);
  228. if (device_path.value().empty()) {
  229. LOG(WARNING) << "ReadValue called with incorrect parameters: "
  230. << method_call->ToString();
  231. // Continue on with an empty device path. This will return a null device to
  232. // the delegate, which should know how to handle it.
  233. }
  234. // GetValue() promises to only call either the success or error callback.
  235. auto split_response_sender =
  236. base::SplitOnceCallback(std::move(response_sender));
  237. DCHECK(delegate_);
  238. delegate_->GetValue(
  239. device_path,
  240. base::BindOnce(&BluetoothGattDescriptorServiceProviderImpl::OnReadValue,
  241. weak_ptr_factory_.GetWeakPtr(), method_call,
  242. std::move(split_response_sender.first)));
  243. }
  244. void BluetoothGattDescriptorServiceProviderImpl::WriteValue(
  245. dbus::MethodCall* method_call,
  246. dbus::ExportedObject::ResponseSender response_sender) {
  247. DVLOG(3) << "BluetoothGattDescriptorServiceProvider::WriteValue: "
  248. << object_path_.value();
  249. DCHECK(OnOriginThread());
  250. dbus::MessageReader reader(method_call);
  251. const uint8_t* bytes = NULL;
  252. size_t length = 0;
  253. std::vector<uint8_t> value;
  254. if (!reader.PopArrayOfBytes(&bytes, &length)) {
  255. LOG(WARNING) << "Error reading value parameter. WriteValue called with "
  256. "incorrect parameters: "
  257. << method_call->ToString();
  258. }
  259. if (bytes)
  260. value.assign(bytes, bytes + length);
  261. std::map<std::string, dbus::MessageReader> options;
  262. dbus::ObjectPath device_path;
  263. ReadOptions(&reader, &options);
  264. auto it = options.find(bluetooth_gatt_descriptor::kOptionDevice);
  265. if (it != options.end())
  266. it->second.PopObjectPath(&device_path);
  267. if (device_path.value().empty()) {
  268. LOG(WARNING) << "WriteValue called with incorrect parameters: "
  269. << method_call->ToString();
  270. // Continue on with an empty device path. This will return a null device to
  271. // the delegate, which should know how to handle it.
  272. }
  273. // SetValue() promises to only call either the success or error callback.
  274. auto split_response_sender =
  275. base::SplitOnceCallback(std::move(response_sender));
  276. DCHECK(delegate_);
  277. delegate_->SetValue(
  278. device_path, value,
  279. base::BindOnce(&BluetoothGattDescriptorServiceProviderImpl::OnWriteValue,
  280. weak_ptr_factory_.GetWeakPtr(), method_call,
  281. std::move(split_response_sender.first)),
  282. base::BindOnce(
  283. &BluetoothGattDescriptorServiceProviderImpl::OnWriteFailure,
  284. weak_ptr_factory_.GetWeakPtr(), method_call,
  285. std::move(split_response_sender.second)));
  286. }
  287. void BluetoothGattDescriptorServiceProviderImpl::OnExported(
  288. const std::string& interface_name,
  289. const std::string& method_name,
  290. bool success) {
  291. DVLOG_IF(1, !success) << "Failed to export " << interface_name << "."
  292. << method_name;
  293. }
  294. void BluetoothGattDescriptorServiceProviderImpl::OnReadValue(
  295. dbus::MethodCall* method_call,
  296. dbus::ExportedObject::ResponseSender response_sender,
  297. absl::optional<device::BluetoothGattService::GattErrorCode> error_code,
  298. const std::vector<uint8_t>& value) {
  299. if (error_code.has_value()) {
  300. DVLOG(2) << "Failed to get descriptor value. Report error.";
  301. std::unique_ptr<dbus::ErrorResponse> error_response =
  302. dbus::ErrorResponse::FromMethodCall(method_call, kErrorFailed,
  303. "Failed to get descriptor value.");
  304. std::move(response_sender).Run(std::move(error_response));
  305. return;
  306. }
  307. DVLOG(3) << "Descriptor value obtained from delegate. Responding to "
  308. "ReadValue.";
  309. std::unique_ptr<dbus::Response> response =
  310. dbus::Response::FromMethodCall(method_call);
  311. dbus::MessageWriter writer(response.get());
  312. writer.AppendArrayOfBytes(value.data(), value.size());
  313. std::move(response_sender).Run(std::move(response));
  314. }
  315. void BluetoothGattDescriptorServiceProviderImpl::OnWriteValue(
  316. dbus::MethodCall* method_call,
  317. dbus::ExportedObject::ResponseSender response_sender) {
  318. DVLOG(3) << "Responding to WriteValue.";
  319. std::unique_ptr<dbus::Response> response =
  320. dbus::Response::FromMethodCall(method_call);
  321. std::move(response_sender).Run(std::move(response));
  322. }
  323. void BluetoothGattDescriptorServiceProviderImpl::WriteProperties(
  324. dbus::MessageWriter* writer) {
  325. dbus::MessageWriter array_writer(NULL);
  326. dbus::MessageWriter dict_entry_writer(NULL);
  327. dbus::MessageWriter variant_writer(NULL);
  328. writer->OpenArray("{sv}", &array_writer);
  329. // UUID:
  330. array_writer.OpenDictEntry(&dict_entry_writer);
  331. dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kUUIDProperty);
  332. dict_entry_writer.AppendVariantOfString(uuid_);
  333. array_writer.CloseContainer(&dict_entry_writer);
  334. // Characteristic:
  335. array_writer.OpenDictEntry(&dict_entry_writer);
  336. dict_entry_writer.AppendString(
  337. bluetooth_gatt_descriptor::kCharacteristicProperty);
  338. dict_entry_writer.AppendVariantOfObjectPath(characteristic_path_);
  339. array_writer.CloseContainer(&dict_entry_writer);
  340. // Flags:
  341. array_writer.OpenDictEntry(&dict_entry_writer);
  342. dict_entry_writer.AppendString(bluetooth_gatt_descriptor::kFlagsProperty);
  343. dict_entry_writer.OpenVariant("as", &variant_writer);
  344. variant_writer.AppendArrayOfStrings(flags_);
  345. dict_entry_writer.CloseContainer(&variant_writer);
  346. array_writer.CloseContainer(&dict_entry_writer);
  347. writer->CloseContainer(&array_writer);
  348. }
  349. void BluetoothGattDescriptorServiceProviderImpl::OnWriteFailure(
  350. dbus::MethodCall* method_call,
  351. dbus::ExportedObject::ResponseSender response_sender) {
  352. DVLOG(2) << "Failed to set descriptor value. Report error.";
  353. std::unique_ptr<dbus::ErrorResponse> error_response =
  354. dbus::ErrorResponse::FromMethodCall(method_call, kErrorFailed,
  355. "Failed to set descriptor value.");
  356. std::move(response_sender).Run(std::move(error_response));
  357. }
  358. const dbus::ObjectPath&
  359. BluetoothGattDescriptorServiceProviderImpl::object_path() const {
  360. return object_path_;
  361. }
  362. } // namespace bluez