Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11726)

Unified Diff: device/bluetooth/bluetooth_audio_sink_chromeos.cc

Issue 1415573014: Reland "Add Linux support for the Bluetooth API" (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: build fix. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
deleted file mode 100644
index 9bb4b601d189d76759ce27ff32662ea5b6894a02..0000000000000000000000000000000000000000
--- a/device/bluetooth/bluetooth_audio_sink_chromeos.cc
+++ /dev/null
@@ -1,575 +0,0 @@
-// Copyright 2015 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 "device/bluetooth/bluetooth_audio_sink_chromeos.h"
-
-#include <unistd.h>
-
-#include <algorithm>
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "base/debug/stack_trace.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "dbus/message.h"
-#include "device/bluetooth/bluetooth_adapter_chromeos.h"
-#include "device/bluetooth/dbus/bluez_dbus_manager.h"
-
-using dbus::ObjectPath;
-using device::BluetoothAudioSink;
-
-namespace {
-
-// TODO(mcchou): Add the constant to dbus/service_constants.h.
-const char kBluetoothAudioSinkServicePath[] = "/org/chromium/AudioSink";
-
-const int kInvalidFd = -1;
-const uint16_t kInvalidReadMtu = 0;
-const uint16_t kInvalidWriteMtu = 0;
-
-ObjectPath GenerateEndpointPath() {
- static unsigned int sequence_number = 0;
- ++sequence_number;
- std::stringstream path;
- path << kBluetoothAudioSinkServicePath << "/endpoint" << sequence_number;
- return ObjectPath(path.str());
-}
-
-std::string StateToString(const BluetoothAudioSink::State& state) {
- switch (state) {
- case BluetoothAudioSink::STATE_INVALID:
- return "invalid";
- case BluetoothAudioSink::STATE_DISCONNECTED:
- return "disconnected";
- case BluetoothAudioSink::STATE_IDLE:
- return "idle";
- case BluetoothAudioSink::STATE_PENDING:
- return "pending";
- case BluetoothAudioSink::STATE_ACTIVE:
- return "active";
- default:
- return "unknown";
- }
-}
-
-std::string ErrorCodeToString(const BluetoothAudioSink::ErrorCode& error_code) {
- switch (error_code) {
- case BluetoothAudioSink::ERROR_UNSUPPORTED_PLATFORM:
- return "unsupported platform";
- case BluetoothAudioSink::ERROR_INVALID_ADAPTER:
- return "invalid adapter";
- case BluetoothAudioSink::ERROR_NOT_REGISTERED:
- return "not registered";
- case BluetoothAudioSink::ERROR_NOT_UNREGISTERED:
- return "not unregistered";
- default:
- return "unknown";
- }
-}
-
-// A dummy error callback for calling Unregister() in destructor.
-void UnregisterErrorCallback(
- device::BluetoothAudioSink::ErrorCode error_code) {
- VLOG(1) << "UnregisterErrorCallback - " << ErrorCodeToString(error_code)
- << "(" << error_code << ")";
-}
-
-} // namespace
-
-namespace chromeos {
-
-BluetoothAudioSinkChromeOS::BluetoothAudioSinkChromeOS(
- scoped_refptr<device::BluetoothAdapter> adapter)
- : state_(BluetoothAudioSink::STATE_INVALID),
- volume_(BluetoothAudioSink::kInvalidVolume),
- read_mtu_(kInvalidReadMtu),
- write_mtu_(kInvalidWriteMtu),
- read_has_failed_(false),
- adapter_(adapter),
- weak_ptr_factory_(this) {
- VLOG(1) << "BluetoothAudioSinkChromeOS created";
-
- CHECK(adapter_.get());
- CHECK(adapter_->IsPresent());
- CHECK(bluez::BluezDBusManager::IsInitialized());
-
- adapter_->AddObserver(this);
-
- bluez::BluetoothMediaClient* media =
- bluez::BluezDBusManager::Get()->GetBluetoothMediaClient();
- CHECK(media);
- media->AddObserver(this);
-
- bluez::BluetoothMediaTransportClient* transport =
- bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient();
- CHECK(transport);
- transport->AddObserver(this);
-
- StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED);
-}
-
-BluetoothAudioSinkChromeOS::~BluetoothAudioSinkChromeOS() {
- VLOG(1) << "BluetoothAudioSinkChromeOS destroyed";
-
- DCHECK(adapter_.get());
-
- if (state_ != BluetoothAudioSink::STATE_INVALID && media_endpoint_.get()) {
- Unregister(base::Bind(&base::DoNothing),
- base::Bind(&UnregisterErrorCallback));
- }
-
- adapter_->RemoveObserver(this);
-
- bluez::BluetoothMediaClient* media =
- bluez::BluezDBusManager::Get()->GetBluetoothMediaClient();
- CHECK(media);
- media->RemoveObserver(this);
-
- bluez::BluetoothMediaTransportClient* transport =
- bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient();
- CHECK(transport);
- transport->RemoveObserver(this);
-}
-
-void BluetoothAudioSinkChromeOS::Unregister(
- const base::Closure& callback,
- const device::BluetoothAudioSink::ErrorCallback& error_callback) {
- VLOG(1) << "Unregister";
-
- if (!bluez::BluezDBusManager::IsInitialized())
- error_callback.Run(BluetoothAudioSink::ERROR_NOT_UNREGISTERED);
-
- bluez::BluetoothMediaClient* media =
- bluez::BluezDBusManager::Get()->GetBluetoothMediaClient();
- CHECK(media);
-
- media->UnregisterEndpoint(
- media_path_,
- endpoint_path_,
- base::Bind(&BluetoothAudioSinkChromeOS::OnUnregisterSucceeded,
- weak_ptr_factory_.GetWeakPtr(), callback),
- base::Bind(&BluetoothAudioSinkChromeOS::OnUnregisterFailed,
- weak_ptr_factory_.GetWeakPtr(), error_callback));
-}
-
-void BluetoothAudioSinkChromeOS::AddObserver(
- BluetoothAudioSink::Observer* observer) {
- CHECK(observer);
- observers_.AddObserver(observer);
-}
-
-void BluetoothAudioSinkChromeOS::RemoveObserver(
- BluetoothAudioSink::Observer* observer) {
- CHECK(observer);
- observers_.RemoveObserver(observer);
-}
-
-BluetoothAudioSink::State BluetoothAudioSinkChromeOS::GetState() const {
- return state_;
-}
-
-uint16_t BluetoothAudioSinkChromeOS::GetVolume() const {
- return volume_;
-}
-
-void BluetoothAudioSinkChromeOS::Register(
- const BluetoothAudioSink::Options& options,
- const base::Closure& callback,
- const BluetoothAudioSink::ErrorCallback& error_callback) {
- VLOG(1) << "Register";
-
- DCHECK(adapter_.get());
- DCHECK_EQ(state_, BluetoothAudioSink::STATE_DISCONNECTED);
-
- // Gets system bus.
- dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus();
-
- // Creates a Media Endpoint with newly-generated path.
- endpoint_path_ = GenerateEndpointPath();
- media_endpoint_.reset(bluez::BluetoothMediaEndpointServiceProvider::Create(
- system_bus, endpoint_path_, this));
-
- DCHECK(media_endpoint_.get());
-
- // Creates endpoint properties with |options|.
- options_ = options;
- bluez::BluetoothMediaClient::EndpointProperties endpoint_properties;
- endpoint_properties.uuid =
- bluez::BluetoothMediaClient::kBluetoothAudioSinkUUID;
- endpoint_properties.codec = options_.codec;
- endpoint_properties.capabilities = options_.capabilities;
-
- media_path_ = static_cast<BluetoothAdapterChromeOS*>(
- adapter_.get())->object_path();
-
- bluez::BluetoothMediaClient* media =
- bluez::BluezDBusManager::Get()->GetBluetoothMediaClient();
- CHECK(media);
- 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));
-}
-
-bluez::BluetoothMediaEndpointServiceProvider*
-BluetoothAudioSinkChromeOS::GetEndpointServiceProvider() {
- return media_endpoint_.get();
-}
-
-void BluetoothAudioSinkChromeOS::AdapterPresentChanged(
- device::BluetoothAdapter* adapter, bool present) {
- VLOG(1) << "AdapterPresentChanged: " << present;
-
- if (adapter != adapter_.get())
- return;
-
- if (adapter->IsPresent()) {
- StateChanged(BluetoothAudioSink::STATE_DISCONNECTED);
- } else {
- adapter_->RemoveObserver(this);
- StateChanged(BluetoothAudioSink::STATE_INVALID);
- }
-}
-
-void BluetoothAudioSinkChromeOS::AdapterPoweredChanged(
- device::BluetoothAdapter* adapter, bool powered) {
- VLOG(1) << "AdapterPoweredChanged: " << powered;
-
- if (adapter != adapter_.get())
- return;
-
- // Regardless of the new powered state, |state_| goes to STATE_DISCONNECTED.
- // If false, the transport is closed, but the endpoint is still valid for use.
- // If true, the previous transport has been torn down, so the |state_| has to
- // be disconnected before SetConfigruation is called.
- if (state_ != BluetoothAudioSink::STATE_INVALID)
- StateChanged(BluetoothAudioSink::STATE_DISCONNECTED);
-}
-
-void BluetoothAudioSinkChromeOS::MediaRemoved(const ObjectPath& object_path) {
- if (object_path == media_path_) {
- VLOG(1) << "MediaRemoved: " << object_path.value();
- StateChanged(BluetoothAudioSink::STATE_INVALID);
- }
-}
-
-void BluetoothAudioSinkChromeOS::MediaTransportRemoved(
- const ObjectPath& object_path) {
- // 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.
- if (object_path == transport_path_) {
- VLOG(1) << "MediaTransportRemoved: " << object_path.value();
- StateChanged(BluetoothAudioSink::STATE_DISCONNECTED);
- }
-}
-
-void BluetoothAudioSinkChromeOS::MediaTransportPropertyChanged(
- const ObjectPath& object_path,
- const std::string& property_name) {
- if (object_path != transport_path_)
- return;
-
- VLOG(1) << "MediaTransportPropertyChanged: " << property_name;
-
- // Retrieves the property set of the transport object with |object_path|.
- bluez::BluetoothMediaTransportClient::Properties* properties =
- bluez::BluezDBusManager::Get()
- ->GetBluetoothMediaTransportClient()
- ->GetProperties(object_path);
-
- // Dispatches a property changed event to the corresponding handler.
- if (property_name == properties->state.name()) {
- if (properties->state.value() ==
- bluez::BluetoothMediaTransportClient::kStateIdle) {
- StateChanged(BluetoothAudioSink::STATE_IDLE);
- } else if (properties->state.value() ==
- bluez::BluetoothMediaTransportClient::kStatePending) {
- StateChanged(BluetoothAudioSink::STATE_PENDING);
- } else if (properties->state.value() ==
- bluez::BluetoothMediaTransportClient::kStateActive) {
- StateChanged(BluetoothAudioSink::STATE_ACTIVE);
- }
- } else if (property_name == properties->volume.name()) {
- VolumeChanged(properties->volume.value());
- }
-}
-
-void BluetoothAudioSinkChromeOS::SetConfiguration(
- const ObjectPath& transport_path,
- const TransportProperties& properties) {
- VLOG(1) << "SetConfiguration";
- transport_path_ = transport_path;
-
- // The initial state for a connection should be "idle".
- if (properties.state != bluez::BluetoothMediaTransportClient::kStateIdle) {
- VLOG(1) << "SetConfiugration - unexpected state :" << properties.state;
- return;
- }
-
- // Updates |volume_| if the volume level is provided in |properties|.
- if (properties.volume.get()) {
- VolumeChanged(*properties.volume);
- }
-
- StateChanged(BluetoothAudioSink::STATE_IDLE);
-}
-
-void BluetoothAudioSinkChromeOS::SelectConfiguration(
- const std::vector<uint8_t>& capabilities,
- const SelectConfigurationCallback& callback) {
- VLOG(1) << "SelectConfiguration";
- callback.Run(options_.capabilities);
-}
-
-void BluetoothAudioSinkChromeOS::ClearConfiguration(
- const ObjectPath& transport_path) {
- if (transport_path != transport_path_)
- return;
-
- VLOG(1) << "ClearConfiguration";
- StateChanged(BluetoothAudioSink::STATE_DISCONNECTED);
-}
-
-void BluetoothAudioSinkChromeOS::Released() {
- VLOG(1) << "Released";
- StateChanged(BluetoothAudioSink::STATE_INVALID);
-}
-
-void BluetoothAudioSinkChromeOS::OnFileCanReadWithoutBlocking(int fd) {
- ReadFromFile();
-}
-
-void BluetoothAudioSinkChromeOS::OnFileCanWriteWithoutBlocking(int fd) {
- // Do nothing for now.
-}
-
-void BluetoothAudioSinkChromeOS::AcquireFD() {
- VLOG(1) << "AcquireFD - transport path: " << transport_path_.value();
-
- read_has_failed_ = false;
-
- bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient()->Acquire(
- transport_path_,
- base::Bind(&BluetoothAudioSinkChromeOS::OnAcquireSucceeded,
- weak_ptr_factory_.GetWeakPtr()),
- base::Bind(&BluetoothAudioSinkChromeOS::OnAcquireFailed,
- weak_ptr_factory_.GetWeakPtr()));
-}
-
-void BluetoothAudioSinkChromeOS::WatchFD() {
- CHECK(file_.get() && file_->IsValid());
-
- VLOG(1) << "WatchFD - file: " << file_->GetPlatformFile()
- << ", file validity: " << file_->IsValid();
-
- base::MessageLoopForIO::current()->WatchFileDescriptor(
- file_->GetPlatformFile(), true, base::MessageLoopForIO::WATCH_READ,
- &fd_read_watcher_, this);
-}
-
-void BluetoothAudioSinkChromeOS::StopWatchingFD() {
- if (!file_.get()) {
- VLOG(1) << "StopWatchingFD - skip";
- return;
- }
-
- bool stopped = fd_read_watcher_.StopWatchingFileDescriptor();
- VLOG(1) << "StopWatchingFD - watch stopped: " << stopped;
- CHECK(stopped);
-
- read_mtu_ = kInvalidReadMtu;
- write_mtu_ = kInvalidWriteMtu;
- file_.reset(); // This will close the file descriptor.
-}
-
-void BluetoothAudioSinkChromeOS::ReadFromFile() {
- DCHECK(file_.get() && file_->IsValid());
- DCHECK(data_.get());
-
- int size = file_->ReadAtCurrentPosNoBestEffort(data_.get(), read_mtu_);
-
- if (size == -1) {
- // To reduce the number of logs, log only once for multiple failures.
- if (!read_has_failed_) {
- VLOG(1) << "ReadFromFile - failed";
- read_has_failed_ = true;
- }
- return;
- }
-
- VLOG(1) << "ReadFromFile - read " << size << " bytes";
- FOR_EACH_OBSERVER(
- BluetoothAudioSink::Observer, observers_,
- BluetoothAudioSinkDataAvailable(this, data_.get(), size, read_mtu_));
-}
-
-void BluetoothAudioSinkChromeOS::StateChanged(
- BluetoothAudioSink::State state) {
- if (state == state_)
- return;
-
- VLOG(1) << "StateChanged - state: " << StateToString(state);
-
- switch (state) {
- case BluetoothAudioSink::STATE_INVALID:
- ResetMedia();
- ResetEndpoint();
- case BluetoothAudioSink::STATE_DISCONNECTED:
- ResetTransport();
- break;
- case BluetoothAudioSink::STATE_IDLE:
- StopWatchingFD();
- break;
- case BluetoothAudioSink::STATE_PENDING:
- AcquireFD();
- break;
- case BluetoothAudioSink::STATE_ACTIVE:
- WatchFD();
- break;
- default:
- break;
- }
-
- state_ = state;
- FOR_EACH_OBSERVER(BluetoothAudioSink::Observer, observers_,
- BluetoothAudioSinkStateChanged(this, state_));
-}
-
-void BluetoothAudioSinkChromeOS::VolumeChanged(uint16_t volume) {
- if (volume == volume_)
- return;
-
- VLOG(1) << "VolumeChanged: " << volume;
-
- volume_ = std::min(volume, BluetoothAudioSink::kInvalidVolume);
- FOR_EACH_OBSERVER(BluetoothAudioSink::Observer, observers_,
- BluetoothAudioSinkVolumeChanged(this, volume_));
-}
-
-void BluetoothAudioSinkChromeOS::OnRegisterSucceeded(
- const base::Closure& callback) {
- DCHECK(media_endpoint_.get());
- VLOG(1) << "OnRegisterSucceeded";
-
- StateChanged(BluetoothAudioSink::STATE_DISCONNECTED);
- callback.Run();
-}
-
-void BluetoothAudioSinkChromeOS::OnRegisterFailed(
- const BluetoothAudioSink::ErrorCallback& error_callback,
- const std::string& error_name,
- const std::string& error_message) {
- VLOG(1) << "OnRegisterFailed - error name: " << error_name
- << ", error message: " << error_message;
-
- ResetEndpoint();
- error_callback.Run(BluetoothAudioSink::ERROR_NOT_REGISTERED);
-}
-
-void BluetoothAudioSinkChromeOS::OnUnregisterSucceeded(
- const base::Closure& callback) {
- VLOG(1) << "Unregistered - endpoint: " << endpoint_path_.value();
-
- // Once the state becomes STATE_INVALID, media, media transport and media
- // endpoint will be reset.
- StateChanged(BluetoothAudioSink::STATE_INVALID);
- callback.Run();
-}
-
-void BluetoothAudioSinkChromeOS::OnUnregisterFailed(
- const device::BluetoothAudioSink::ErrorCallback& error_callback,
- const std::string& error_name,
- const std::string& error_message) {
- VLOG(1) << "OnUnregisterFailed - error name: " << error_name
- << ", error message: " << error_message;
-
- error_callback.Run(BluetoothAudioSink::ERROR_NOT_UNREGISTERED);
-}
-
-void BluetoothAudioSinkChromeOS::OnAcquireSucceeded(
- dbus::FileDescriptor* fd,
- const uint16_t read_mtu,
- const uint16_t write_mtu) {
- CHECK(fd);
- fd->CheckValidity();
- CHECK(fd->is_valid() && fd->value() != kInvalidFd);
- CHECK_GT(read_mtu, kInvalidReadMtu);
- CHECK_GT(write_mtu, kInvalidWriteMtu);
-
- // Avoids unnecessary memory reallocation if read MTU doesn't change.
- if (read_mtu != read_mtu_) {
- read_mtu_ = read_mtu;
- data_.reset(new char[read_mtu_]);
- VLOG(1) << "OnAcquireSucceeded - allocate " << read_mtu_
- << " bytes of memory";
- }
-
- write_mtu_ = write_mtu;
-
- // Avoids closing the same file descriptor caused by reassignment.
- if (!file_.get() || file_->GetPlatformFile() != fd->value()) {
- // Takes ownership of the file descriptor.
- file_.reset(new base::File(fd->TakeValue()));
- DCHECK(file_->IsValid());
- VLOG(1) << "OnAcquireSucceeded - update file";
- }
-
- VLOG(1) << "OnAcquireSucceeded - file: " << file_->GetPlatformFile()
- << ", read MTU: " << read_mtu_ << ", write MTU: " << write_mtu_;
-}
-
-void BluetoothAudioSinkChromeOS::OnAcquireFailed(
- const std::string& error_name,
- const std::string& error_message) {
- VLOG(1) << "OnAcquireFailed - error name: " << error_name
- << ", error message: " << error_message;
-}
-
-void BluetoothAudioSinkChromeOS::OnReleaseFDSucceeded() {
- VLOG(1) << "OnReleaseFDSucceeded";
-}
-
-void BluetoothAudioSinkChromeOS::OnReleaseFDFailed(
- const std::string& error_name,
- const std::string& error_message) {
- VLOG(1) << "OnReleaseFDFailed - error name: " << error_name
- << ", error message: " << error_message;
-}
-
-void BluetoothAudioSinkChromeOS::ResetMedia() {
- VLOG(1) << "ResetMedia";
-
- media_path_ = dbus::ObjectPath("");
-}
-
-void BluetoothAudioSinkChromeOS::ResetTransport() {
- if (!transport_path_.IsValid()) {
- VLOG(1) << "ResetTransport - skip";
- return;
- }
-
- VLOG(1) << "ResetTransport - clean-up";
-
- VolumeChanged(BluetoothAudioSink::kInvalidVolume);
- transport_path_ = dbus::ObjectPath("");
- read_mtu_ = kInvalidReadMtu;
- write_mtu_ = kInvalidWriteMtu;
- file_.reset();
-}
-
-void BluetoothAudioSinkChromeOS::ResetEndpoint() {
- VLOG(1) << "ResetEndpoint";
-
- endpoint_path_ = ObjectPath("");
- media_endpoint_ = nullptr;
-}
-
-} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698