bluetooth_le_advertisement_service_provider.cc 19 KB

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