Commit ac03835c authored by mcchou's avatar mcchou Committed by Commit bot

chromeos/dbus: Add BlueZ Media Endpoint Service Provider API.

This CL adds the BlueZ Media Endpoint service provider class and its
fake class, and add the files in chromeos/chromeos.gyp.

BUG=429016

Review URL: https://codereview.chromium.org/725383003

Cr-Commit-Position: refs/heads/master@{#304976}
parent 8b216d8e
......@@ -75,6 +75,8 @@
'dbus/bluetooth_media_client.h',
'dbus/bluetooth_media_transport_client.cc',
'dbus/bluetooth_media_transport_client.h',
'dbus/bluetooth_media_endpoint_service_provider.cc',
'dbus/bluetooth_media_endpoint_service_provider.h',
'dbus/bluetooth_profile_manager_client.cc',
'dbus/bluetooth_profile_manager_client.h',
'dbus/bluetooth_profile_service_provider.cc',
......@@ -124,6 +126,8 @@
'dbus/face_bluetooth_media_client.h',
'dbus/fake_bluetooth_media_transport_client.cc',
'dbus/fake_bluetooth_media_transport_client.h',
'dbus/fake_bluetooth_media_endpoint_service_provider.cc',
'dbus/fake_bluetooth_media_endpoint_service_provider.h',
'dbus/fake_bluetooth_profile_manager_client.cc',
'dbus/fake_bluetooth_profile_manager_client.h',
'dbus/fake_bluetooth_profile_service_provider.cc',
......
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h"
#include <string>
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/platform_thread.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h"
#include "dbus/bus.h"
#include "dbus/exported_object.h"
#include "dbus/message.h"
namespace {
// TODO(mcchou): Move these constants to dbus/service_constants.h.
// Bluetooth Media Endpoint service identifier.
const char kBluetoothMediaEndpointInterface[] = "org.bluez.MediaEndpoint1";
// Bluetooth Media Endpoint methods.
const char kSetConfiguration[] = "SetConfiguration";
const char kSelectConfiguration[] = "SelectConfiguration";
const char kClearConfiguration[] = "ClearConfiguration";
const char kRelease[] = "Release";
} // namespace
namespace chromeos {
// The BluetoothMediaEndopintServiceProvider implementation used in production.
class CHROMEOS_EXPORT BluetoothMediaEndpointServiceProviderImpl
: public BluetoothMediaEndpointServiceProvider {
public:
BluetoothMediaEndpointServiceProviderImpl(dbus::Bus* bus,
const dbus::ObjectPath& object_path,
Delegate* delegate)
: origin_thread_id_(base::PlatformThread::CurrentId()),
bus_(bus),
delegate_(delegate),
object_path_(object_path),
weak_ptr_factory_(this) {
VLOG(1) << "Creating Bluetooth Media Endpoint: " << object_path_.value();
DCHECK(bus_);
DCHECK(delegate_);
DCHECK(object_path_.IsValid());
exported_object_ = bus_->GetExportedObject(object_path_);
exported_object_->ExportMethod(
kBluetoothMediaEndpointInterface,
kSetConfiguration,
base::Bind(
&BluetoothMediaEndpointServiceProviderImpl::SetConfiguration,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported,
weak_ptr_factory_.GetWeakPtr()));
exported_object_->ExportMethod(
kBluetoothMediaEndpointInterface,
kSelectConfiguration,
base::Bind(
&BluetoothMediaEndpointServiceProviderImpl::SelectConfiguration,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported,
weak_ptr_factory_.GetWeakPtr()));
exported_object_->ExportMethod(
kBluetoothMediaEndpointInterface,
kClearConfiguration,
base::Bind(
&BluetoothMediaEndpointServiceProviderImpl::ClearConfiguration,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported,
weak_ptr_factory_.GetWeakPtr()));
exported_object_->ExportMethod(
kBluetoothMediaEndpointInterface,
kRelease,
base::Bind(&BluetoothMediaEndpointServiceProviderImpl::Release,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&BluetoothMediaEndpointServiceProviderImpl::OnExported,
weak_ptr_factory_.GetWeakPtr()));
}
~BluetoothMediaEndpointServiceProviderImpl() override {
VLOG(1) << "Cleaning up Bluetooth Media Endpoint: "
<< object_path_.value();
bus_->UnregisterExportedObject(object_path_);
}
private:
// Returns true if the current thread is on the origin thread, false
// otherwise.
bool OnOriginThread() const {
return base::PlatformThread::CurrentId() == origin_thread_id_;
}
// Called by dbus:: when a method is exported.
void OnExported(const std::string& interface_name,
const std::string& method_name,
bool success) {
LOG_IF(WARNING, !success) << "Failed to export "
<< interface_name << "." << method_name;
}
// Called by dbus:: when the remote device connects to the Media Endpoint.
void SetConfiguration(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
DCHECK(OnOriginThread());
DCHECK(delegate_);
dbus::MessageReader reader(method_call);
dbus::ObjectPath transport_path;
dbus::MessageReader properties(method_call);
if (!reader.PopObjectPath(&transport_path) ||
!reader.PopArray(&properties)) {
LOG(WARNING) << "SetConfiguration called with incorrect parameters: "
<< method_call->ToString();
return;
}
delegate_->SetConfiguration(transport_path, properties);
response_sender.Run(dbus::Response::FromMethodCall(method_call));
}
// Called by dbus:: when the remote device receives the configuration for
// media transport.
void SelectConfiguration(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
DCHECK(OnOriginThread());
DCHECK(delegate_);
dbus::MessageReader reader(method_call);
const uint8_t* capabilities = nullptr;
size_t length = 0;
if (!reader.PopArrayOfBytes(&capabilities, &length)) {
LOG(WARNING) << "SelectConfiguration called with incorrect parameters: "
<< method_call->ToString();
return;
}
std::vector<uint8_t> configuration(capabilities, capabilities + length);
// |delegate_| generates the response to |SelectConfiguration| and sends it
// back via |callback|.
Delegate::SelectConfigurationCallback callback = base::Bind(
&BluetoothMediaEndpointServiceProviderImpl::OnConfiguration,
weak_ptr_factory_.GetWeakPtr(),
method_call,
response_sender);
delegate_->SelectConfiguration(configuration, callback);
}
// Called by dbus:: when the remote device is about to close the connection.
void ClearConfiguration(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
DCHECK(OnOriginThread());
DCHECK(delegate_);
dbus::MessageReader reader(method_call);
dbus::ObjectPath transport_path;
if (!reader.PopObjectPath(&transport_path)) {
LOG(WARNING) << "ClearConfiguration called with incorrect parameters: "
<< method_call->ToString();
return;
}
delegate_->ClearConfiguration(transport_path);
response_sender.Run(dbus::Response::FromMethodCall(method_call));
}
// Called by Bluetooth daemon to do the clean up after unregistering the Media
// Endpoint.
void Release(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender) {
DCHECK(OnOriginThread());
DCHECK(delegate_);
delegate_->Release();
response_sender.Run(dbus::Response::FromMethodCall(method_call));
}
// Called by Delegate to response to a method requiring transport
// configuration.
void OnConfiguration(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender,
const std::vector<uint8_t>& configuration) {
DCHECK(OnOriginThread());
// Generates the response to the method call.
scoped_ptr<dbus::Response> response(
dbus::Response::FromMethodCall(method_call));
dbus::MessageWriter writer(response.get());
if (configuration.empty()) {
LOG(WARNING) << "OnConfiguration called with empty configuration.";
writer.AppendArrayOfBytes(nullptr, 0);
} else {
writer.AppendArrayOfBytes(&configuration[0], configuration.size());
}
response_sender.Run(response.Pass());
}
// Origin thread (i.e. the UI thread in production).
base::PlatformThreadId origin_thread_id_;
// D-Bus Bus object is exported on.
dbus::Bus* bus_;
// All incoming method calls are passed on to |delegate_|. |callback| passed
// to |delegate+| will generate the response for those methods whose returns
// are non-void.
Delegate* delegate_;
// D-Bus object path of the object we are exporting, kept so we can unregister
// again in you destructor.
dbus::ObjectPath object_path_;
// D-Bus object we are exporting, owned by this object.
scoped_refptr<dbus::ExportedObject> exported_object_;
// Weak pointer factory for generating 'this' printers that might live longer
// than we do.
// Note This should remain the last member so it'll be destroyed and
// invalidate it's weak pointers before any other members are destroyed.
base::WeakPtrFactory<BluetoothMediaEndpointServiceProviderImpl>
weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BluetoothMediaEndpointServiceProviderImpl);
};
BluetoothMediaEndpointServiceProvider::BluetoothMediaEndpointServiceProvider() {
}
BluetoothMediaEndpointServiceProvider::~BluetoothMediaEndpointServiceProvider()
{}
BluetoothMediaEndpointServiceProvider*
BluetoothMediaEndpointServiceProvider::Create(
dbus::Bus* bus,
const dbus::ObjectPath& object_path,
Delegate* delegate) {
// Returns a real implementation.
if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
return new BluetoothMediaEndpointServiceProviderImpl(
bus, object_path, delegate);
}
// Returns a fake implementation.
return new FakeBluetoothMediaEndpointServiceProvider(object_path, delegate);
}
} // namespace chromeos
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
#define CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
#include <vector>
#include "base/callback.h"
#include "chromeos/chromeos_export.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_path.h"
namespace chromeos {
// BluetoothMediaEndpointServiceProvider is used to provide a D-Bus object that
// the Bluetooth daemon can commuicate with to serve as a media source/sink.
//
// Instantiate with a chosen D-Bus object path and a delegate object, and pass
// the D-Bus object path as |endpoint_path| argument to the
// chromeos::BluetoothMediaClient::RegisterEndoint() method.
//
// After initiating a connection between an audio source and an audio sink, the
// Bluetooth daemon will make calls to this endpoint object and they will be
// passed to user's Delegate object for handling. For SelectConfiguration method
// the response is returned using the SelectConfiguration callback.
class CHROMEOS_EXPORT BluetoothMediaEndpointServiceProvider {
public:
// Delegate is the interface for reacting to endpoint requests. User
// applications will implement this interface to handle either A2DP Sink or
// Source.
class Delegate {
public:
virtual ~Delegate() {}
// SelectConfigurationCallback is used for the SelectConfiguration() method,
// it should be called with two arguements, the |configuration| which is
// agreed by the application and the |length| of |configuration|.
typedef base::Callback<void(const std::vector<uint8_t>&)>
SelectConfigurationCallback;
// This method will be called after an Audio Source receives the agreed
// capabilities from the Audio Sink to set the configuration for the
// media transport object. |transport_path| is the path to the
// MediaTransport object, and |properties| are the properties for that
// MediaTransport object.
virtual void SetConfiguration(const dbus::ObjectPath& transport_path,
const dbus::MessageReader& properties) = 0;
// This method will be called when an Audio Source connects to an Audio Sink
// and asks it to decide the configuration to be used during the oncoming
// streaming. Audio Sources provide |capabilities| as a reference, where
// a user application can use these |capabilities| to figure out
// a well-matched configuration and return it to the Audio Source via
// |callback|.
virtual void SelectConfiguration(
const std::vector<uint8_t>& capabilities,
const SelectConfigurationCallback& callback) = 0;
// This method will be called when an Audio Source disconnects from an Audio
// Sink. A user application is supposed to clear any of its resources which
// it keeps for that particular connection. |transport_path| is the Media
// Transport object which has been kept by an endpoint during the
// connection.
virtual void ClearConfiguration(const dbus::ObjectPath& transport_path) = 0;
// This method will be called when the Bluetooth daemon unregisters the
// Media Endpoint. Media Endpoint objects can use this method to clean up
// tasks. There is no need to unregister the endpoint, since when this
// method gets called, that endpoint has been unregistered.
virtual void Release() = 0;
};
virtual ~BluetoothMediaEndpointServiceProvider();
// Creates the instance where |bus| is the D-Bus bus connection to export the
// object onto, |object_path| is the object path that it should have and
// |delegate| is the object to which all method calls will be passed and
// responses generated from.
static BluetoothMediaEndpointServiceProvider* Create(
dbus::Bus* bus,
const dbus::ObjectPath& object_path,
Delegate* delegate);
protected:
BluetoothMediaEndpointServiceProvider();
private:
DISALLOW_COPY_AND_ASSIGN(BluetoothMediaEndpointServiceProvider);
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/dbus/fake_bluetooth_media_endpoint_service_provider.h"
namespace chromeos {
// TODO(mcchou): Add the logic of the behavior.
FakeBluetoothMediaEndpointServiceProvider::
FakeBluetoothMediaEndpointServiceProvider(
const dbus::ObjectPath object_path, Delegate* delegate)
: object_path_(object_path) , delegate_(delegate) {
VLOG(1) << "Create Bluetooth Media Endpoint: " << object_path_.value();
// TODO(mcchou): Use the FakeBluetoothMediaClient in DBusThreadManager
// to register the FakeBluetoothMediaEndpoint object.
}
FakeBluetoothMediaEndpointServiceProvider::
~FakeBluetoothMediaEndpointServiceProvider() {
VLOG(1) << "Cleaning up Bluetooth Media Endpoint: " << object_path_.value();
// TODO(mcchou): Use the FakeBluetoothMediaClient in DBusThreadManager
// to unregister the FakeBluetoothMediaEndpoint object.
}
void FakeBluetoothMediaEndpointServiceProvider::SetConfiguration(
const dbus::ObjectPath& transport_path,
const dbus::MessageReader& properties) {
VLOG(1) << object_path_.value() << ": SetConfiguration for "
<< transport_path.value();
delegate_->SetConfiguration(transport_path, properties);
}
void FakeBluetoothMediaEndpointServiceProvider::SelectConfiguration(
const std::vector<uint8_t>& capabilities,
const Delegate::SelectConfigurationCallback& callback) {
VLOG(1) << object_path_.value() << ": SelectConfiguration";
delegate_->SelectConfiguration(capabilities, callback);
}
void FakeBluetoothMediaEndpointServiceProvider::ClearConfiguration(
const dbus::ObjectPath& transport_path) {
VLOG(1) << object_path_.value() << ": ClearConfiguration for"
<< transport_path.value();
delegate_->ClearConfiguration(transport_path);
}
void FakeBluetoothMediaEndpointServiceProvider::Release() {
VLOG(1) << object_path_.value() << ": Release";
delegate_->Release();
}
} // namespace chromeos
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
#define CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
#include <vector>
#include "base/logging.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/dbus/bluetooth_media_endpoint_service_provider.h"
#include "dbus/object_path.h"
namespace chromeos {
// FakeBluetoothMediaEndpointServiceProvider simulates the behavior of a local
// Bluetooth Media Endpoint object.
// TODO(mcchou): Add the logic of the behavior.
class CHROMEOS_EXPORT FakeBluetoothMediaEndpointServiceProvider
: public BluetoothMediaEndpointServiceProvider {
public:
FakeBluetoothMediaEndpointServiceProvider(const dbus::ObjectPath object_path,
Delegate* delegate);
~FakeBluetoothMediaEndpointServiceProvider() override;
// Each of these calls the equivalent BluetoothMediaEnpointServiceProvider::
// Delegate method on the object passed on construction.
void SetConfiguration(const dbus::ObjectPath& transport_path,
const dbus::MessageReader& properties);
void SelectConfiguration(
const std::vector<uint8_t>& capabilities,
const Delegate::SelectConfigurationCallback& callback);
void ClearConfiguration(const dbus::ObjectPath& transport_path);
void Release();
private:
// The fake D-Bus object path.
dbus::ObjectPath object_path_;
// All incoming method calls are passed to |delegate_|. |callback| passed to
// |delegate_| will generate the response for those methods which have
// non-void return.
Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(FakeBluetoothMediaEndpointServiceProvider);
};
} // namespace chromeos
#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_MEDIA_ENDPOINT_SERVICE_PROVIDER_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment