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
3 // found in the LICENSE file.
5 #include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h"
10 #include "base/logging.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/threading/platform_thread.h"
14 #include "chromeos/dbus/dbus_thread_manager.h"
15 #include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h"
17 #include "dbus/exported_object.h"
18 #include "dbus/message.h"
22 // TODO(mcchou): Move these constants to dbus/service_constants.h.
23 // Bluetooth Media Endpoint service identifier.
24 const char kBluetoothMediaEndpointInterface
[] = "org.bluez.MediaEndpoint1";
26 // Bluetooth Media Endpoint methods.
27 const char kSetConfiguration
[] = "SetConfiguration";
28 const char kSelectConfiguration
[] = "SelectConfiguration";
29 const char kClearConfiguration
[] = "ClearConfiguration";
30 const char kRelease
[] = "Release";
36 // The BluetoothMediaEndopintServiceProvider implementation used in production.
37 class CHROMEOS_EXPORT BluetoothMediaEndpointServiceProviderImpl
38 : public BluetoothMediaEndpointServiceProvider
{
40 BluetoothMediaEndpointServiceProviderImpl(dbus::Bus
* bus
,
41 const dbus::ObjectPath
& object_path
,
43 : origin_thread_id_(base::PlatformThread::CurrentId()),
46 object_path_(object_path
),
47 weak_ptr_factory_(this) {
48 VLOG(1) << "Creating Bluetooth Media Endpoint: " << object_path_
.value();
51 DCHECK(object_path_
.IsValid());
53 exported_object_
= bus_
->GetExportedObject(object_path_
);
55 exported_object_
->ExportMethod(
56 kBluetoothMediaEndpointInterface
,
59 &BluetoothMediaEndpointServiceProviderImpl::SetConfiguration
,
60 weak_ptr_factory_
.GetWeakPtr()),
61 base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported
,
62 weak_ptr_factory_
.GetWeakPtr()));
64 exported_object_
->ExportMethod(
65 kBluetoothMediaEndpointInterface
,
68 &BluetoothMediaEndpointServiceProviderImpl::SelectConfiguration
,
69 weak_ptr_factory_
.GetWeakPtr()),
70 base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported
,
71 weak_ptr_factory_
.GetWeakPtr()));
73 exported_object_
->ExportMethod(
74 kBluetoothMediaEndpointInterface
,
77 &BluetoothMediaEndpointServiceProviderImpl::ClearConfiguration
,
78 weak_ptr_factory_
.GetWeakPtr()),
79 base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported
,
80 weak_ptr_factory_
.GetWeakPtr()));
82 exported_object_
->ExportMethod(
83 kBluetoothMediaEndpointInterface
,
85 base::Bind(&BluetoothMediaEndpointServiceProviderImpl::Release
,
86 weak_ptr_factory_
.GetWeakPtr()),
87 base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported
,
88 weak_ptr_factory_
.GetWeakPtr()));
91 ~BluetoothMediaEndpointServiceProviderImpl() override
{
92 VLOG(1) << "Cleaning up Bluetooth Media Endpoint: "
93 << object_path_
.value();
95 bus_
->UnregisterExportedObject(object_path_
);
99 // Returns true if the current thread is on the origin thread, false
101 bool OnOriginThread() const {
102 return base::PlatformThread::CurrentId() == origin_thread_id_
;
105 // Called by dbus:: when a method is exported.
106 void OnExported(const std::string
& interface_name
,
107 const std::string
& method_name
,
109 LOG_IF(WARNING
, !success
) << "Failed to export "
110 << interface_name
<< "." << method_name
;
113 // Called by dbus:: when the remote device connects to the Media Endpoint.
114 void SetConfiguration(dbus::MethodCall
* method_call
,
115 dbus::ExportedObject::ResponseSender response_sender
) {
116 DCHECK(OnOriginThread());
119 dbus::MessageReader
reader(method_call
);
120 dbus::ObjectPath transport_path
;
121 dbus::MessageReader
properties(method_call
);
122 if (!reader
.PopObjectPath(&transport_path
) ||
123 !reader
.PopArray(&properties
)) {
124 LOG(WARNING
) << "SetConfiguration called with incorrect parameters: "
125 << method_call
->ToString();
129 delegate_
->SetConfiguration(transport_path
, properties
);
131 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
134 // Called by dbus:: when the remote device receives the configuration for
136 void SelectConfiguration(
137 dbus::MethodCall
* method_call
,
138 dbus::ExportedObject::ResponseSender response_sender
) {
139 DCHECK(OnOriginThread());
142 dbus::MessageReader
reader(method_call
);
143 const uint8_t* capabilities
= nullptr;
145 if (!reader
.PopArrayOfBytes(&capabilities
, &length
)) {
146 LOG(WARNING
) << "SelectConfiguration called with incorrect parameters: "
147 << method_call
->ToString();
151 std::vector
<uint8_t> configuration(capabilities
, capabilities
+ length
);
153 // |delegate_| generates the response to |SelectConfiguration| and sends it
154 // back via |callback|.
155 Delegate::SelectConfigurationCallback callback
= base::Bind(
156 &BluetoothMediaEndpointServiceProviderImpl::OnConfiguration
,
157 weak_ptr_factory_
.GetWeakPtr(),
161 delegate_
->SelectConfiguration(configuration
, callback
);
164 // Called by dbus:: when the remote device is about to close the connection.
165 void ClearConfiguration(
166 dbus::MethodCall
* method_call
,
167 dbus::ExportedObject::ResponseSender response_sender
) {
168 DCHECK(OnOriginThread());
171 dbus::MessageReader
reader(method_call
);
172 dbus::ObjectPath transport_path
;
173 if (!reader
.PopObjectPath(&transport_path
)) {
174 LOG(WARNING
) << "ClearConfiguration called with incorrect parameters: "
175 << method_call
->ToString();
179 delegate_
->ClearConfiguration(transport_path
);
181 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
184 // Called by Bluetooth daemon to do the clean up after unregistering the Media
186 void Release(dbus::MethodCall
* method_call
,
187 dbus::ExportedObject::ResponseSender response_sender
) {
188 DCHECK(OnOriginThread());
191 delegate_
->Release();
193 response_sender
.Run(dbus::Response::FromMethodCall(method_call
));
196 // Called by Delegate to response to a method requiring transport
198 void OnConfiguration(dbus::MethodCall
* method_call
,
199 dbus::ExportedObject::ResponseSender response_sender
,
200 const std::vector
<uint8_t>& configuration
) {
201 DCHECK(OnOriginThread());
203 // Generates the response to the method call.
204 scoped_ptr
<dbus::Response
> response(
205 dbus::Response::FromMethodCall(method_call
));
206 dbus::MessageWriter
writer(response
.get());
207 if (configuration
.empty()) {
208 LOG(WARNING
) << "OnConfiguration called with empty configuration.";
209 writer
.AppendArrayOfBytes(nullptr, 0);
211 writer
.AppendArrayOfBytes(&configuration
[0], configuration
.size());
213 response_sender
.Run(response
.Pass());
216 // Origin thread (i.e. the UI thread in production).
217 base::PlatformThreadId origin_thread_id_
;
219 // D-Bus Bus object is exported on.
222 // All incoming method calls are passed on to |delegate_|. |callback| passed
223 // to |delegate+| will generate the response for those methods whose returns
227 // D-Bus object path of the object we are exporting, kept so we can unregister
228 // again in you destructor.
229 dbus::ObjectPath object_path_
;
231 // D-Bus object we are exporting, owned by this object.
232 scoped_refptr
<dbus::ExportedObject
> exported_object_
;
234 // Weak pointer factory for generating 'this' printers that might live longer
236 // Note This should remain the last member so it'll be destroyed and
237 // invalidate it's weak pointers before any other members are destroyed.
238 base::WeakPtrFactory
<BluetoothMediaEndpointServiceProviderImpl
>
241 DISALLOW_COPY_AND_ASSIGN(BluetoothMediaEndpointServiceProviderImpl
);
244 BluetoothMediaEndpointServiceProvider::BluetoothMediaEndpointServiceProvider() {
247 BluetoothMediaEndpointServiceProvider::~BluetoothMediaEndpointServiceProvider()
250 BluetoothMediaEndpointServiceProvider
*
251 BluetoothMediaEndpointServiceProvider::Create(
253 const dbus::ObjectPath
& object_path
,
254 Delegate
* delegate
) {
255 // Returns a real implementation.
256 if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH
)) {
257 return new BluetoothMediaEndpointServiceProviderImpl(
258 bus
, object_path
, delegate
);
260 // Returns a fake implementation.
261 return new FakeBluetoothMediaEndpointServiceProvider(object_path
, delegate
);
264 } // namespace chromeos