Chromium Code Reviews| 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..a50294b4b28f4fcbb4e8ee7df143d9f75073abe6 100644 |
| --- a/device/bluetooth/bluetooth_audio_sink_chromeos.cc |
| +++ b/device/bluetooth/bluetooth_audio_sink_chromeos.cc |
| @@ -7,30 +7,43 @@ |
| #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<BluetoothAdapterChromeOS> 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()); |
| - present_ = adapter_->IsPresent(); |
| - powered_ = adapter_->IsPowered(); |
| - if (present_ && powered_) |
| - state_ = device::BluetoothAudioSink::STATE_DISCONNECTED; |
| + if (adapter_->IsPresent() && adapter_->IsPowered()) |
|
armansito
2015/01/29 04:22:56
I would DCHECK(adapter_->IsPresent()), since it sh
Miao
2015/01/29 23:58:38
Right, since present is checked in BluetoothAdapte
|
| + StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED); |
| adapter_->AddObserver(this); |
| } |
| BluetoothAudioSinkChromeOS::~BluetoothAudioSinkChromeOS() { |
| - DCHECK(adapter_); |
| + DCHECK(adapter_.get()); |
| adapter_->RemoveObserver(this); |
| } |
| @@ -57,19 +70,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 +92,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 +117,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 +128,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 +140,92 @@ 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 = std::string( |
|
armansito
2015/01/29 04:22:56
std::string() shouldn't be necessary afaik
Miao
2015/01/29 23:58:38
Done.
|
| + 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(); |
| + media->AddObserver(this); |
| + media_path_ = adapter_->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 +239,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; |
|
armansito
2015/01/29 04:22:55
Nice, this deletes the existing BluetoothMediaEndp
Miao
2015/01/29 23:58:38
// operator=. Allows assignment from a nullptr. D
|
| + error_callback.Run(device::BluetoothAudioSink::ERROR_NOT_REGISTERED); |
| +} |
| + |
| void BluetoothAudioSinkChromeOS::ReadFromFD() { |
| DCHECK_GE(fd_.value(), 0); |