| Index: device/bluetooth/bluetooth_audio_sink_chromeos.cc
|
| diff --git a/device/bluetooth/bluetooth_audio_sink_chromeos.cc b/device/bluetooth/bluetooth_audio_sink_chromeos.cc
|
| index 840769e8f1d337d79ec3a1927d9d5ea5aacf5e81..9623c7824e93e50033dbf6f8d4c943e7312b85e4 100644
|
| --- a/device/bluetooth/bluetooth_audio_sink_chromeos.cc
|
| +++ b/device/bluetooth/bluetooth_audio_sink_chromeos.cc
|
| @@ -7,31 +7,47 @@
|
| #include <sstream>
|
|
|
| #include "base/logging.h"
|
| +#include "chromeos/dbus/dbus_thread_manager.h"
|
| +#include "device/bluetooth/bluetooth_adapter_chromeos.h"
|
| +
|
| +namespace {
|
| +
|
| +// TODO(mcchou): Add the constant to dbus/service_constants.h.
|
| +const char kBluetoothAudioSinkServicePath[] = "/org/chromium/AudioSink";
|
| +
|
| +dbus::ObjectPath GenerateEndpointPath() {
|
| + static unsigned int sequence_number = 0;
|
| + ++sequence_number;
|
| + std::stringstream path;
|
| + path << kBluetoothAudioSinkServicePath << "/endpoint" << sequence_number;
|
| + return dbus::ObjectPath(path.str());
|
| +}
|
| +
|
| +} // namespace
|
|
|
| namespace chromeos {
|
|
|
| BluetoothAudioSinkChromeOS::BluetoothAudioSinkChromeOS(
|
| - BluetoothAdapterChromeOS* adapter)
|
| + scoped_refptr<device::BluetoothAdapter> adapter)
|
| : state_(device::BluetoothAudioSink::STATE_INVALID),
|
| - present_(false),
|
| - powered_(false),
|
| volume_(0),
|
| read_mtu_(0),
|
| write_mtu_(0),
|
| adapter_(adapter),
|
| weak_ptr_factory_(this) {
|
| - DCHECK(adapter_);
|
| + DCHECK(adapter_.get());
|
| + DCHECK(adapter_->IsPresent());
|
|
|
| - present_ = adapter_->IsPresent();
|
| - powered_ = adapter_->IsPowered();
|
| - if (present_ && powered_)
|
| - state_ = device::BluetoothAudioSink::STATE_DISCONNECTED;
|
| + StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED);
|
| adapter_->AddObserver(this);
|
| }
|
|
|
| BluetoothAudioSinkChromeOS::~BluetoothAudioSinkChromeOS() {
|
| - DCHECK(adapter_);
|
| + DCHECK(adapter_.get());
|
| adapter_->RemoveObserver(this);
|
| + // TODO(mcchou): BUG=441581
|
| + // Unregister() should be called while media and media endpoint are still
|
| + // valid.
|
| }
|
|
|
| void BluetoothAudioSinkChromeOS::AddObserver(
|
| @@ -57,19 +73,14 @@ uint16_t BluetoothAudioSinkChromeOS::GetVolume() const {
|
| void BluetoothAudioSinkChromeOS::AdapterPresentChanged(
|
| device::BluetoothAdapter* adapter,
|
| bool present) {
|
| - // TODO(mcchou): BUG=441581
|
| - // If |persent| is true, change state to |STATE_DISCONNECTED| and call
|
| - // StateChanged(). Otherwise, change state to |STATE_INVALID| and call
|
| - // StateChanged.
|
| -}
|
| + VLOG(1) << "Bluetooth audio sink: Bluetooth adapter present changed: "
|
| + << present;
|
|
|
| -void BluetoothAudioSinkChromeOS::AdapterPoweredChanged(
|
| - device::BluetoothAdapter* adapter,
|
| - bool powered) {
|
| - // TODO(mcchou): BUG=441581
|
| - // If |powered| is true, change state to |STATE_DISCONNECTED| and call
|
| - // StateChanged(). Otherwise, change state to |STATE_INVALID| and call
|
| - // StateChanged.
|
| + if (adapter->IsPresent()) {
|
| + StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED);
|
| + } else {
|
| + StateChanged(device::BluetoothAudioSink::STATE_INVALID);
|
| + }
|
| }
|
|
|
| void BluetoothAudioSinkChromeOS::MediaRemoved(
|
| @@ -84,6 +95,9 @@ void BluetoothAudioSinkChromeOS::MediaTransportRemoved(
|
| // TODO(mcchou): BUG=441581
|
| // Check if |object_path| equals to |transport_path_|. If true, change the
|
| // state of the audio sink, call StateChanged and reset the audio sink.
|
| + // Whenever powered of |adapter_| turns false while present stays true, media
|
| + // transport object should be removed accordingly, and the state should be
|
| + // changed to STATE_DISCONNECTED.
|
| }
|
|
|
| void BluetoothAudioSinkChromeOS::MediaTransportPropertyChanged(
|
| @@ -106,6 +120,8 @@ void BluetoothAudioSinkChromeOS::SelectConfiguration(
|
| const SelectConfigurationCallback& callback) {
|
| // TODO(mcchou): BUG=441581
|
| // Use SelectConfigurationCallback to return the agreed capabilities.
|
| + VLOG(1) << "Bluetooth audio sink: SelectConfiguration called";
|
| + callback.Run(options_.capabilities);
|
| }
|
|
|
| void BluetoothAudioSinkChromeOS::ClearConfiguration(
|
| @@ -115,8 +131,8 @@ void BluetoothAudioSinkChromeOS::ClearConfiguration(
|
| }
|
|
|
| void BluetoothAudioSinkChromeOS::Release() {
|
| - // TODO(mcchou): BUG=441581
|
| - // Let the audio sink does the clean-up and do nothing here.
|
| + VLOG(1) << "Bluetooth audio sink: Release called";
|
| + StateChanged(device::BluetoothAudioSink::STATE_INVALID);
|
| }
|
|
|
| void BluetoothAudioSinkChromeOS::Register(
|
| @@ -127,19 +143,93 @@ void BluetoothAudioSinkChromeOS::Register(
|
| // Get Media object, initiate an Media Endpoint with options, and return the
|
| // audio sink via callback. Add the audio sink as observer of both Media and
|
| // Media Transport.
|
| + DCHECK(adapter_.get());
|
| + DCHECK_EQ(state_, device::BluetoothAudioSink::STATE_DISCONNECTED);
|
| +
|
| + // Gets system bus.
|
| + dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
|
| +
|
| + // Creates a Media Endpoint with newly-generated path.
|
| + endpoint_path_ = GenerateEndpointPath();
|
| + media_endpoint_.reset(
|
| + BluetoothMediaEndpointServiceProvider::Create(
|
| + system_bus, endpoint_path_, this));
|
| +
|
| + DCHECK(media_endpoint_.get());
|
| +
|
| + // Creates endpoint properties with |options|.
|
| + options_ = options;
|
| + chromeos::BluetoothMediaClient::EndpointProperties endpoint_properties;
|
| + endpoint_properties.uuid = BluetoothMediaClient::kBluetoothAudioSinkUUID;
|
| + endpoint_properties.codec = options_.codec;
|
| + endpoint_properties.capabilities = options_.capabilities;
|
| +
|
| + // Gets Media object exported by D-Bus and registers the endpoint.
|
| + chromeos::BluetoothMediaClient* media =
|
| + DBusThreadManager::Get()->GetBluetoothMediaClient();
|
| + BluetoothAdapterChromeOS* adapter_chromeos =
|
| + static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
|
| + media->AddObserver(this);
|
| + media_path_ = adapter_chromeos->object_path();
|
| + media->RegisterEndpoint(
|
| + media_path_,
|
| + endpoint_path_,
|
| + endpoint_properties,
|
| + base::Bind(&BluetoothAudioSinkChromeOS::OnRegisterSucceeded,
|
| + weak_ptr_factory_.GetWeakPtr(), callback),
|
| + base::Bind(&BluetoothAudioSinkChromeOS::OnRegisterFailed,
|
| + weak_ptr_factory_.GetWeakPtr(), error_callback));
|
| }
|
|
|
| void BluetoothAudioSinkChromeOS::Unregister(
|
| const base::Closure& callback,
|
| const device::BluetoothAudioSink::ErrorCallback& error_callback) {
|
| // TODO(mcchou): BUG=441581
|
| - // Clean |observers_| and |transport_path_| and reset |state_| and |volume_|.
|
| + // Call UnregisterEndpoint on the media object with |media_path_| and clean
|
| + // |observers_| and transport_path_ and reset state_ and volume.
|
| + // Check whether the media endpoint is registered before invoking
|
| + // UnregisterEndpoint.
|
| }
|
|
|
| void BluetoothAudioSinkChromeOS::StateChanged(
|
| device::BluetoothAudioSink::State state) {
|
| - DCHECK_NE(state, state_);
|
| + if (state == state_)
|
| + return;
|
| +
|
| VLOG(1) << "Bluetooth audio sink state changed: " << state;
|
| +
|
| + switch (state) {
|
| + case device::BluetoothAudioSink::STATE_INVALID: {
|
| + // TODO(mcchou): BUG=441581
|
| + // Clean media, media transport and media endpoint.
|
| + break;
|
| + }
|
| + case device::BluetoothAudioSink::STATE_DISCONNECTED: {
|
| + // TODO(mcchou): BUG=441581
|
| + // Clean media transport.
|
| + break;
|
| + }
|
| + case device::BluetoothAudioSink::STATE_IDLE: {
|
| + // TODO(mcchou): BUG=441581
|
| + // Triggered by MediaTransportPropertyChanged. Stop watching on file
|
| + // descriptor if there is one.
|
| + break;
|
| + }
|
| + case device::BluetoothAudioSink::STATE_PENDING: {
|
| + // TODO(mcchou): BUG=441581
|
| + // Call BluetoothMediaTransportClient::Acquire() to get fd and mtus.
|
| + break;
|
| + }
|
| + case device::BluetoothAudioSink::STATE_ACTIVE: {
|
| + // TODO(mcchou): BUG=441581
|
| + // Read from fd and call DataAvailable.
|
| + ReadFromFD();
|
| + break;
|
| + }
|
| + default:
|
| + break;
|
| + }
|
| +
|
| state_ = state;
|
| FOR_EACH_OBSERVER(device::BluetoothAudioSink::Observer, observers_,
|
| BluetoothAudioSinkStateChanged(this, state_));
|
| @@ -153,6 +243,26 @@ void BluetoothAudioSinkChromeOS::VolumeChanged(uint16_t volume) {
|
| BluetoothAudioSinkVolumeChanged(this, volume_));
|
| }
|
|
|
| +void BluetoothAudioSinkChromeOS::OnRegisterSucceeded(
|
| + const base::Closure& callback) {
|
| + VLOG(1) << "Bluetooth audio sink registerd";
|
| +
|
| + StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED);
|
| + callback.Run();
|
| +}
|
| +
|
| +void BluetoothAudioSinkChromeOS::OnRegisterFailed(
|
| + const BluetoothAudioSink::ErrorCallback& error_callback,
|
| + const std::string& error_name,
|
| + const std::string& error_message) {
|
| + DCHECK(media_endpoint_.get());
|
| + VLOG(1) << "Bluetooth audio sink: " << error_name << ": " << error_message;
|
| +
|
| + endpoint_path_ = dbus::ObjectPath("");
|
| + media_endpoint_ = nullptr;
|
| + error_callback.Run(device::BluetoothAudioSink::ERROR_NOT_REGISTERED);
|
| +}
|
| +
|
| void BluetoothAudioSinkChromeOS::ReadFromFD() {
|
| DCHECK_GE(fd_.value(), 0);
|
|
|
|
|