bluetooth_profile_service_provider.cc 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // Copyright 2013 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_profile_service_provider.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/logging.h"
  9. #include "base/memory/raw_ptr.h"
  10. #include "base/memory/ref_counted.h"
  11. #include "base/threading/platform_thread.h"
  12. #include "dbus/exported_object.h"
  13. #include "dbus/message.h"
  14. #include "device/bluetooth/dbus/bluez_dbus_manager.h"
  15. #include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h"
  16. #include "third_party/cros_system_api/dbus/service_constants.h"
  17. namespace bluez {
  18. // The BluetoothProfileServiceProvider implementation used in production.
  19. class BluetoothProfileServiceProviderImpl
  20. : public BluetoothProfileServiceProvider {
  21. public:
  22. BluetoothProfileServiceProviderImpl(dbus::Bus* bus,
  23. const dbus::ObjectPath& object_path,
  24. Delegate* delegate)
  25. : origin_thread_id_(base::PlatformThread::CurrentId()),
  26. bus_(bus),
  27. delegate_(delegate),
  28. object_path_(object_path) {
  29. DVLOG(1) << "Creating Bluetooth Profile: " << object_path_.value();
  30. exported_object_ = bus_->GetExportedObject(object_path_);
  31. exported_object_->ExportMethod(
  32. bluetooth_profile::kBluetoothProfileInterface,
  33. bluetooth_profile::kRelease,
  34. base::BindRepeating(&BluetoothProfileServiceProviderImpl::Release,
  35. weak_ptr_factory_.GetWeakPtr()),
  36. base::BindOnce(&BluetoothProfileServiceProviderImpl::OnExported,
  37. weak_ptr_factory_.GetWeakPtr()));
  38. exported_object_->ExportMethod(
  39. bluetooth_profile::kBluetoothProfileInterface,
  40. bluetooth_profile::kNewConnection,
  41. base::BindRepeating(&BluetoothProfileServiceProviderImpl::NewConnection,
  42. weak_ptr_factory_.GetWeakPtr()),
  43. base::BindOnce(&BluetoothProfileServiceProviderImpl::OnExported,
  44. weak_ptr_factory_.GetWeakPtr()));
  45. exported_object_->ExportMethod(
  46. bluetooth_profile::kBluetoothProfileInterface,
  47. bluetooth_profile::kRequestDisconnection,
  48. base::BindRepeating(
  49. &BluetoothProfileServiceProviderImpl::RequestDisconnection,
  50. weak_ptr_factory_.GetWeakPtr()),
  51. base::BindOnce(&BluetoothProfileServiceProviderImpl::OnExported,
  52. weak_ptr_factory_.GetWeakPtr()));
  53. exported_object_->ExportMethod(
  54. bluetooth_profile::kBluetoothProfileInterface,
  55. bluetooth_profile::kCancel,
  56. base::BindRepeating(&BluetoothProfileServiceProviderImpl::Cancel,
  57. weak_ptr_factory_.GetWeakPtr()),
  58. base::BindOnce(&BluetoothProfileServiceProviderImpl::OnExported,
  59. weak_ptr_factory_.GetWeakPtr()));
  60. }
  61. BluetoothProfileServiceProviderImpl(
  62. const BluetoothProfileServiceProviderImpl&) = delete;
  63. BluetoothProfileServiceProviderImpl& operator=(
  64. const BluetoothProfileServiceProviderImpl&) = delete;
  65. ~BluetoothProfileServiceProviderImpl() override {
  66. DVLOG(1) << "Cleaning up Bluetooth Profile: " << object_path_.value();
  67. // Unregister the object path so we can reuse with a new agent.
  68. bus_->UnregisterExportedObject(object_path_);
  69. }
  70. private:
  71. // Returns true if the current thread is on the origin thread.
  72. bool OnOriginThread() {
  73. return base::PlatformThread::CurrentId() == origin_thread_id_;
  74. }
  75. // Called by dbus:: when the profile is unregistered from the Bluetooth
  76. // daemon, generally by our request.
  77. void Release(dbus::MethodCall* method_call,
  78. dbus::ExportedObject::ResponseSender response_sender) {
  79. DCHECK(OnOriginThread());
  80. DCHECK(delegate_);
  81. delegate_->Released();
  82. std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call));
  83. }
  84. // Called by dbus:: when the Bluetooth daemon establishes a new connection
  85. // to the profile.
  86. void NewConnection(dbus::MethodCall* method_call,
  87. dbus::ExportedObject::ResponseSender response_sender) {
  88. DCHECK(OnOriginThread());
  89. DCHECK(delegate_);
  90. dbus::MessageReader reader(method_call);
  91. dbus::ObjectPath device_path;
  92. base::ScopedFD fd;
  93. dbus::MessageReader array_reader(NULL);
  94. if (!reader.PopObjectPath(&device_path) || !reader.PopFileDescriptor(&fd) ||
  95. !reader.PopArray(&array_reader)) {
  96. LOG(WARNING) << "NewConnection called with incorrect paramters: "
  97. << method_call->ToString();
  98. return;
  99. }
  100. Delegate::Options options;
  101. while (array_reader.HasMoreData()) {
  102. dbus::MessageReader dict_entry_reader(NULL);
  103. std::string key;
  104. if (!array_reader.PopDictEntry(&dict_entry_reader) ||
  105. !dict_entry_reader.PopString(&key)) {
  106. LOG(WARNING) << "NewConnection called with incorrect paramters: "
  107. << method_call->ToString();
  108. } else {
  109. if (key == bluetooth_profile::kVersionProperty)
  110. dict_entry_reader.PopVariantOfUint16(&options.version);
  111. else if (key == bluetooth_profile::kFeaturesProperty)
  112. dict_entry_reader.PopVariantOfUint16(&options.features);
  113. }
  114. }
  115. Delegate::ConfirmationCallback callback =
  116. base::BindOnce(&BluetoothProfileServiceProviderImpl::OnConfirmation,
  117. weak_ptr_factory_.GetWeakPtr(), method_call,
  118. std::move(response_sender));
  119. delegate_->NewConnection(device_path, std::move(fd), options,
  120. std::move(callback));
  121. }
  122. // Called by dbus:: when the Bluetooth daemon is about to disconnect the
  123. // profile.
  124. void RequestDisconnection(
  125. dbus::MethodCall* method_call,
  126. dbus::ExportedObject::ResponseSender response_sender) {
  127. DCHECK(OnOriginThread());
  128. DCHECK(delegate_);
  129. dbus::MessageReader reader(method_call);
  130. dbus::ObjectPath device_path;
  131. if (!reader.PopObjectPath(&device_path)) {
  132. LOG(WARNING) << "RequestDisconnection called with incorrect paramters: "
  133. << method_call->ToString();
  134. return;
  135. }
  136. Delegate::ConfirmationCallback callback =
  137. base::BindOnce(&BluetoothProfileServiceProviderImpl::OnConfirmation,
  138. weak_ptr_factory_.GetWeakPtr(), method_call,
  139. std::move(response_sender));
  140. delegate_->RequestDisconnection(device_path, std::move(callback));
  141. }
  142. // Called by dbus:: when the request failed before a reply was returned
  143. // from the device.
  144. void Cancel(dbus::MethodCall* method_call,
  145. dbus::ExportedObject::ResponseSender response_sender) {
  146. DCHECK(OnOriginThread());
  147. DCHECK(delegate_);
  148. delegate_->Cancel();
  149. std::move(response_sender).Run(dbus::Response::FromMethodCall(method_call));
  150. }
  151. // Called by dbus:: when a method is exported.
  152. void OnExported(const std::string& interface_name,
  153. const std::string& method_name,
  154. bool success) {
  155. DVLOG_IF(1, !success) << "Failed to export " << interface_name << "."
  156. << method_name;
  157. }
  158. // Called by the Delegate in response to a method requiring confirmation.
  159. void OnConfirmation(dbus::MethodCall* method_call,
  160. dbus::ExportedObject::ResponseSender response_sender,
  161. Delegate::Status status) {
  162. DCHECK(OnOriginThread());
  163. switch (status) {
  164. case Delegate::SUCCESS: {
  165. std::move(response_sender)
  166. .Run(dbus::Response::FromMethodCall(method_call));
  167. break;
  168. }
  169. case Delegate::REJECTED: {
  170. std::move(response_sender)
  171. .Run(dbus::ErrorResponse::FromMethodCall(
  172. method_call, bluetooth_profile::kErrorRejected, "rejected"));
  173. break;
  174. }
  175. case Delegate::CANCELLED: {
  176. std::move(response_sender)
  177. .Run(dbus::ErrorResponse::FromMethodCall(
  178. method_call, bluetooth_profile::kErrorCanceled, "canceled"));
  179. break;
  180. }
  181. default:
  182. NOTREACHED() << "Unexpected status code from delegate: " << status;
  183. }
  184. }
  185. // Origin thread (i.e. the UI thread in production).
  186. base::PlatformThreadId origin_thread_id_;
  187. // D-Bus bus object is exported on, not owned by this object and must
  188. // outlive it.
  189. raw_ptr<dbus::Bus> bus_;
  190. // All incoming method calls are passed on to the Delegate and a callback
  191. // passed to generate the reply. |delegate_| is generally the object that
  192. // owns this one, and must outlive it.
  193. raw_ptr<Delegate> delegate_;
  194. // D-Bus object path of object we are exporting, kept so we can unregister
  195. // again in our destructor.
  196. dbus::ObjectPath object_path_;
  197. // D-Bus object we are exporting, owned by this object.
  198. scoped_refptr<dbus::ExportedObject> exported_object_;
  199. // Weak pointer factory for generating 'this' pointers that might live longer
  200. // than we do.
  201. // Note: This should remain the last member so it'll be destroyed and
  202. // invalidate its weak pointers before any other members are destroyed.
  203. base::WeakPtrFactory<BluetoothProfileServiceProviderImpl> weak_ptr_factory_{
  204. this};
  205. };
  206. BluetoothProfileServiceProvider::BluetoothProfileServiceProvider() = default;
  207. BluetoothProfileServiceProvider::~BluetoothProfileServiceProvider() = default;
  208. // static
  209. BluetoothProfileServiceProvider* BluetoothProfileServiceProvider::Create(
  210. dbus::Bus* bus,
  211. const dbus::ObjectPath& object_path,
  212. Delegate* delegate) {
  213. if (!bluez::BluezDBusManager::Get()->IsUsingFakes()) {
  214. return new BluetoothProfileServiceProviderImpl(bus, object_path, delegate);
  215. }
  216. #if defined(USE_REAL_DBUS_CLIENTS)
  217. LOG(FATAL) << "Fake is unavailable if USE_REAL_DBUS_CLIENTS is defined.";
  218. return nullptr;
  219. #else
  220. return new FakeBluetoothProfileServiceProvider(object_path, delegate);
  221. #endif // defined(USE_REAL_DBUS_CLIENTS)
  222. }
  223. } // namespace bluez