bluetooth_gatt_service_service_provider_impl.cc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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_service_service_provider_impl.h"
  5. #include "base/bind.h"
  6. #include "base/logging.h"
  7. #include "third_party/cros_system_api/dbus/service_constants.h"
  8. namespace bluez {
  9. namespace {
  10. const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
  11. const char kErrorPropertyReadOnly[] =
  12. "org.freedesktop.DBus.Error.PropertyReadOnly";
  13. } // namespace
  14. BluetoothGattServiceServiceProviderImpl::
  15. BluetoothGattServiceServiceProviderImpl(
  16. dbus::Bus* bus,
  17. const dbus::ObjectPath& object_path,
  18. const std::string& uuid,
  19. bool is_primary,
  20. const std::vector<dbus::ObjectPath>& includes)
  21. : origin_thread_id_(base::PlatformThread::CurrentId()),
  22. uuid_(uuid),
  23. is_primary_(is_primary),
  24. includes_(includes),
  25. bus_(bus),
  26. object_path_(object_path) {
  27. DVLOG(1) << "Creating Bluetooth GATT service: " << object_path_.value()
  28. << " UUID: " << uuid;
  29. if (!bus_)
  30. return;
  31. DCHECK(!uuid_.empty());
  32. DCHECK(object_path_.IsValid());
  33. exported_object_ = bus_->GetExportedObject(object_path_);
  34. exported_object_->ExportMethod(
  35. dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
  36. base::BindRepeating(&BluetoothGattServiceServiceProviderImpl::Get,
  37. weak_ptr_factory_.GetWeakPtr()),
  38. base::BindOnce(&BluetoothGattServiceServiceProviderImpl::OnExported,
  39. weak_ptr_factory_.GetWeakPtr()));
  40. exported_object_->ExportMethod(
  41. dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesSet,
  42. base::BindRepeating(&BluetoothGattServiceServiceProviderImpl::Set,
  43. weak_ptr_factory_.GetWeakPtr()),
  44. base::BindOnce(&BluetoothGattServiceServiceProviderImpl::OnExported,
  45. weak_ptr_factory_.GetWeakPtr()));
  46. exported_object_->ExportMethod(
  47. dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
  48. base::BindRepeating(&BluetoothGattServiceServiceProviderImpl::GetAll,
  49. weak_ptr_factory_.GetWeakPtr()),
  50. base::BindOnce(&BluetoothGattServiceServiceProviderImpl::OnExported,
  51. weak_ptr_factory_.GetWeakPtr()));
  52. }
  53. BluetoothGattServiceServiceProviderImpl::
  54. ~BluetoothGattServiceServiceProviderImpl() {
  55. DVLOG(1) << "Cleaning up Bluetooth GATT service: " << object_path_.value();
  56. if (bus_)
  57. bus_->UnregisterExportedObject(object_path_);
  58. }
  59. bool BluetoothGattServiceServiceProviderImpl::OnOriginThread() {
  60. return base::PlatformThread::CurrentId() == origin_thread_id_;
  61. }
  62. void BluetoothGattServiceServiceProviderImpl::Get(
  63. dbus::MethodCall* method_call,
  64. dbus::ExportedObject::ResponseSender response_sender) {
  65. DVLOG(2) << "BluetoothGattServiceServiceProvider::Get: "
  66. << object_path_.value();
  67. DCHECK(OnOriginThread());
  68. dbus::MessageReader reader(method_call);
  69. std::string interface_name;
  70. std::string property_name;
  71. if (!reader.PopString(&interface_name) || !reader.PopString(&property_name) ||
  72. reader.HasMoreData()) {
  73. std::unique_ptr<dbus::ErrorResponse> error_response =
  74. dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
  75. "Expected 'ss'.");
  76. std::move(response_sender).Run(std::move(error_response));
  77. return;
  78. }
  79. // Only the GATT service interface is allowed.
  80. if (interface_name !=
  81. bluetooth_gatt_service::kBluetoothGattServiceInterface) {
  82. std::unique_ptr<dbus::ErrorResponse> error_response =
  83. dbus::ErrorResponse::FromMethodCall(
  84. method_call, kErrorInvalidArgs,
  85. "No such interface: '" + interface_name + "'.");
  86. std::move(response_sender).Run(std::move(error_response));
  87. return;
  88. }
  89. // Return error if |property_name| is unknown.
  90. if (property_name != bluetooth_gatt_service::kUUIDProperty &&
  91. property_name != bluetooth_gatt_service::kIncludesProperty) {
  92. std::unique_ptr<dbus::ErrorResponse> error_response =
  93. dbus::ErrorResponse::FromMethodCall(
  94. method_call, kErrorInvalidArgs,
  95. "No such property: '" + property_name + "'.");
  96. std::move(response_sender).Run(std::move(error_response));
  97. return;
  98. }
  99. std::unique_ptr<dbus::Response> response =
  100. dbus::Response::FromMethodCall(method_call);
  101. dbus::MessageWriter writer(response.get());
  102. dbus::MessageWriter variant_writer(NULL);
  103. if (property_name == bluetooth_gatt_service::kUUIDProperty) {
  104. writer.OpenVariant("s", &variant_writer);
  105. variant_writer.AppendString(uuid_);
  106. writer.CloseContainer(&variant_writer);
  107. } else {
  108. writer.OpenVariant("ao", &variant_writer);
  109. variant_writer.AppendArrayOfObjectPaths(includes_);
  110. writer.CloseContainer(&variant_writer);
  111. }
  112. std::move(response_sender).Run(std::move(response));
  113. }
  114. void BluetoothGattServiceServiceProviderImpl::Set(
  115. dbus::MethodCall* method_call,
  116. dbus::ExportedObject::ResponseSender response_sender) {
  117. DVLOG(2) << "BluetoothGattServiceServiceProviderImpl::Set: "
  118. << object_path_.value();
  119. DCHECK(OnOriginThread());
  120. // All of the properties on this interface are read-only, so just return
  121. // error.
  122. std::unique_ptr<dbus::ErrorResponse> error_response =
  123. dbus::ErrorResponse::FromMethodCall(method_call, kErrorPropertyReadOnly,
  124. "All properties are read-only.");
  125. std::move(response_sender).Run(std::move(error_response));
  126. }
  127. void BluetoothGattServiceServiceProviderImpl::GetAll(
  128. dbus::MethodCall* method_call,
  129. dbus::ExportedObject::ResponseSender response_sender) {
  130. DVLOG(2) << "BluetoothGattServiceServiceProvider::GetAll: "
  131. << object_path_.value();
  132. DCHECK(OnOriginThread());
  133. dbus::MessageReader reader(method_call);
  134. std::string interface_name;
  135. if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
  136. std::unique_ptr<dbus::ErrorResponse> error_response =
  137. dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
  138. "Expected 's'.");
  139. std::move(response_sender).Run(std::move(error_response));
  140. return;
  141. }
  142. // Only the GATT service interface is allowed.
  143. if (interface_name !=
  144. bluetooth_gatt_service::kBluetoothGattServiceInterface) {
  145. std::unique_ptr<dbus::ErrorResponse> error_response =
  146. dbus::ErrorResponse::FromMethodCall(
  147. method_call, kErrorInvalidArgs,
  148. "No such interface: '" + interface_name + "'.");
  149. std::move(response_sender).Run(std::move(error_response));
  150. return;
  151. }
  152. std::unique_ptr<dbus::Response> response =
  153. dbus::Response::FromMethodCall(method_call);
  154. dbus::MessageWriter writer(response.get());
  155. WriteProperties(&writer);
  156. std::move(response_sender).Run(std::move(response));
  157. }
  158. void BluetoothGattServiceServiceProviderImpl::WriteProperties(
  159. dbus::MessageWriter* writer) {
  160. dbus::MessageWriter array_writer(NULL);
  161. dbus::MessageWriter dict_entry_writer(NULL);
  162. dbus::MessageWriter variant_writer(NULL);
  163. writer->OpenArray("{sv}", &array_writer);
  164. array_writer.OpenDictEntry(&dict_entry_writer);
  165. dict_entry_writer.AppendString(bluetooth_gatt_service::kUUIDProperty);
  166. dict_entry_writer.AppendVariantOfString(uuid_);
  167. array_writer.CloseContainer(&dict_entry_writer);
  168. array_writer.OpenDictEntry(&dict_entry_writer);
  169. dict_entry_writer.AppendString(bluetooth_gatt_service::kPrimaryProperty);
  170. dict_entry_writer.AppendVariantOfBool(is_primary_);
  171. array_writer.CloseContainer(&dict_entry_writer);
  172. array_writer.OpenDictEntry(&dict_entry_writer);
  173. dict_entry_writer.AppendString(bluetooth_gatt_service::kIncludesProperty);
  174. dict_entry_writer.OpenVariant("ao", &variant_writer);
  175. variant_writer.AppendArrayOfObjectPaths(includes_);
  176. dict_entry_writer.CloseContainer(&variant_writer);
  177. array_writer.CloseContainer(&dict_entry_writer);
  178. writer->CloseContainer(&array_writer);
  179. }
  180. void BluetoothGattServiceServiceProviderImpl::OnExported(
  181. const std::string& interface_name,
  182. const std::string& method_name,
  183. bool success) {
  184. DVLOG_IF(1, !success) << "Failed to export " << interface_name << "."
  185. << method_name;
  186. }
  187. const dbus::ObjectPath& BluetoothGattServiceServiceProviderImpl::object_path()
  188. const {
  189. return object_path_;
  190. }
  191. } // namespace bluez