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..01e10b899a81a30efd00ab97ef0413d75b251684 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(); |
+ scoped_refptr<BluetoothAdapterChromeOS> adapter_chromeos( |
armansito
2015/01/30 01:27:46
nit: no need to create a scoped_refptr here, just
Miao
2015/01/30 03:59:04
Done.
|
+ 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); |