| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "device/bluetooth/bluetooth_audio_sink_chromeos.h" | 5 #include "device/bluetooth/bluetooth_audio_sink_bluez.h" |
| 6 | 6 |
| 7 #include <unistd.h> | 7 #include <unistd.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <sstream> | 10 #include <sstream> |
| 11 #include <string> | 11 #include <string> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/debug/stack_trace.h" | 14 #include "base/debug/stack_trace.h" |
| 15 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "dbus/message.h" | 17 #include "dbus/message.h" |
| 18 #include "device/bluetooth/bluetooth_adapter_chromeos.h" | 18 #include "device/bluetooth/bluetooth_adapter_bluez.h" |
| 19 #include "device/bluetooth/dbus/bluez_dbus_manager.h" | 19 #include "device/bluetooth/dbus/bluez_dbus_manager.h" |
| 20 | 20 |
| 21 using dbus::ObjectPath; | 21 using dbus::ObjectPath; |
| 22 using device::BluetoothAudioSink; | 22 using device::BluetoothAudioSink; |
| 23 | 23 |
| 24 namespace { | 24 namespace { |
| 25 | 25 |
| 26 // TODO(mcchou): Add the constant to dbus/service_constants.h. | 26 // TODO(mcchou): Add the constant to dbus/service_constants.h. |
| 27 const char kBluetoothAudioSinkServicePath[] = "/org/chromium/AudioSink"; | 27 const char kBluetoothAudioSinkServicePath[] = "/org/chromium/AudioSink"; |
| 28 | 28 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 case BluetoothAudioSink::ERROR_NOT_REGISTERED: | 64 case BluetoothAudioSink::ERROR_NOT_REGISTERED: |
| 65 return "not registered"; | 65 return "not registered"; |
| 66 case BluetoothAudioSink::ERROR_NOT_UNREGISTERED: | 66 case BluetoothAudioSink::ERROR_NOT_UNREGISTERED: |
| 67 return "not unregistered"; | 67 return "not unregistered"; |
| 68 default: | 68 default: |
| 69 return "unknown"; | 69 return "unknown"; |
| 70 } | 70 } |
| 71 } | 71 } |
| 72 | 72 |
| 73 // A dummy error callback for calling Unregister() in destructor. | 73 // A dummy error callback for calling Unregister() in destructor. |
| 74 void UnregisterErrorCallback( | 74 void UnregisterErrorCallback(device::BluetoothAudioSink::ErrorCode error_code) { |
| 75 device::BluetoothAudioSink::ErrorCode error_code) { | |
| 76 VLOG(1) << "UnregisterErrorCallback - " << ErrorCodeToString(error_code) | 75 VLOG(1) << "UnregisterErrorCallback - " << ErrorCodeToString(error_code) |
| 77 << "(" << error_code << ")"; | 76 << "(" << error_code << ")"; |
| 78 } | 77 } |
| 79 | 78 |
| 80 } // namespace | 79 } // namespace |
| 81 | 80 |
| 82 namespace chromeos { | 81 namespace bluez { |
| 83 | 82 |
| 84 BluetoothAudioSinkChromeOS::BluetoothAudioSinkChromeOS( | 83 BluetoothAudioSinkBlueZ::BluetoothAudioSinkBlueZ( |
| 85 scoped_refptr<device::BluetoothAdapter> adapter) | 84 scoped_refptr<device::BluetoothAdapter> adapter) |
| 86 : state_(BluetoothAudioSink::STATE_INVALID), | 85 : state_(BluetoothAudioSink::STATE_INVALID), |
| 87 volume_(BluetoothAudioSink::kInvalidVolume), | 86 volume_(BluetoothAudioSink::kInvalidVolume), |
| 88 read_mtu_(kInvalidReadMtu), | 87 read_mtu_(kInvalidReadMtu), |
| 89 write_mtu_(kInvalidWriteMtu), | 88 write_mtu_(kInvalidWriteMtu), |
| 90 read_has_failed_(false), | 89 read_has_failed_(false), |
| 91 adapter_(adapter), | 90 adapter_(adapter), |
| 92 weak_ptr_factory_(this) { | 91 weak_ptr_factory_(this) { |
| 93 VLOG(1) << "BluetoothAudioSinkChromeOS created"; | 92 VLOG(1) << "BluetoothAudioSinkBlueZ created"; |
| 94 | 93 |
| 95 CHECK(adapter_.get()); | 94 CHECK(adapter_.get()); |
| 96 CHECK(adapter_->IsPresent()); | 95 CHECK(adapter_->IsPresent()); |
| 97 CHECK(bluez::BluezDBusManager::IsInitialized()); | 96 CHECK(bluez::BluezDBusManager::IsInitialized()); |
| 98 | 97 |
| 99 adapter_->AddObserver(this); | 98 adapter_->AddObserver(this); |
| 100 | 99 |
| 101 bluez::BluetoothMediaClient* media = | 100 bluez::BluetoothMediaClient* media = |
| 102 bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); | 101 bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); |
| 103 CHECK(media); | 102 CHECK(media); |
| 104 media->AddObserver(this); | 103 media->AddObserver(this); |
| 105 | 104 |
| 106 bluez::BluetoothMediaTransportClient* transport = | 105 bluez::BluetoothMediaTransportClient* transport = |
| 107 bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient(); | 106 bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient(); |
| 108 CHECK(transport); | 107 CHECK(transport); |
| 109 transport->AddObserver(this); | 108 transport->AddObserver(this); |
| 110 | 109 |
| 111 StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED); | 110 StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED); |
| 112 } | 111 } |
| 113 | 112 |
| 114 BluetoothAudioSinkChromeOS::~BluetoothAudioSinkChromeOS() { | 113 BluetoothAudioSinkBlueZ::~BluetoothAudioSinkBlueZ() { |
| 115 VLOG(1) << "BluetoothAudioSinkChromeOS destroyed"; | 114 VLOG(1) << "BluetoothAudioSinkBlueZ destroyed"; |
| 116 | 115 |
| 117 DCHECK(adapter_.get()); | 116 DCHECK(adapter_.get()); |
| 118 | 117 |
| 119 if (state_ != BluetoothAudioSink::STATE_INVALID && media_endpoint_.get()) { | 118 if (state_ != BluetoothAudioSink::STATE_INVALID && media_endpoint_.get()) { |
| 120 Unregister(base::Bind(&base::DoNothing), | 119 Unregister(base::Bind(&base::DoNothing), |
| 121 base::Bind(&UnregisterErrorCallback)); | 120 base::Bind(&UnregisterErrorCallback)); |
| 122 } | 121 } |
| 123 | 122 |
| 124 adapter_->RemoveObserver(this); | 123 adapter_->RemoveObserver(this); |
| 125 | 124 |
| 126 bluez::BluetoothMediaClient* media = | 125 bluez::BluetoothMediaClient* media = |
| 127 bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); | 126 bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); |
| 128 CHECK(media); | 127 CHECK(media); |
| 129 media->RemoveObserver(this); | 128 media->RemoveObserver(this); |
| 130 | 129 |
| 131 bluez::BluetoothMediaTransportClient* transport = | 130 bluez::BluetoothMediaTransportClient* transport = |
| 132 bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient(); | 131 bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient(); |
| 133 CHECK(transport); | 132 CHECK(transport); |
| 134 transport->RemoveObserver(this); | 133 transport->RemoveObserver(this); |
| 135 } | 134 } |
| 136 | 135 |
| 137 void BluetoothAudioSinkChromeOS::Unregister( | 136 void BluetoothAudioSinkBlueZ::Unregister( |
| 138 const base::Closure& callback, | 137 const base::Closure& callback, |
| 139 const device::BluetoothAudioSink::ErrorCallback& error_callback) { | 138 const device::BluetoothAudioSink::ErrorCallback& error_callback) { |
| 140 VLOG(1) << "Unregister"; | 139 VLOG(1) << "Unregister"; |
| 141 | 140 |
| 142 if (!bluez::BluezDBusManager::IsInitialized()) | 141 if (!bluez::BluezDBusManager::IsInitialized()) |
| 143 error_callback.Run(BluetoothAudioSink::ERROR_NOT_UNREGISTERED); | 142 error_callback.Run(BluetoothAudioSink::ERROR_NOT_UNREGISTERED); |
| 144 | 143 |
| 145 bluez::BluetoothMediaClient* media = | 144 bluez::BluetoothMediaClient* media = |
| 146 bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); | 145 bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); |
| 147 CHECK(media); | 146 CHECK(media); |
| 148 | 147 |
| 149 media->UnregisterEndpoint( | 148 media->UnregisterEndpoint( |
| 150 media_path_, | 149 media_path_, endpoint_path_, |
| 151 endpoint_path_, | 150 base::Bind(&BluetoothAudioSinkBlueZ::OnUnregisterSucceeded, |
| 152 base::Bind(&BluetoothAudioSinkChromeOS::OnUnregisterSucceeded, | |
| 153 weak_ptr_factory_.GetWeakPtr(), callback), | 151 weak_ptr_factory_.GetWeakPtr(), callback), |
| 154 base::Bind(&BluetoothAudioSinkChromeOS::OnUnregisterFailed, | 152 base::Bind(&BluetoothAudioSinkBlueZ::OnUnregisterFailed, |
| 155 weak_ptr_factory_.GetWeakPtr(), error_callback)); | 153 weak_ptr_factory_.GetWeakPtr(), error_callback)); |
| 156 } | 154 } |
| 157 | 155 |
| 158 void BluetoothAudioSinkChromeOS::AddObserver( | 156 void BluetoothAudioSinkBlueZ::AddObserver( |
| 159 BluetoothAudioSink::Observer* observer) { | 157 BluetoothAudioSink::Observer* observer) { |
| 160 CHECK(observer); | 158 CHECK(observer); |
| 161 observers_.AddObserver(observer); | 159 observers_.AddObserver(observer); |
| 162 } | 160 } |
| 163 | 161 |
| 164 void BluetoothAudioSinkChromeOS::RemoveObserver( | 162 void BluetoothAudioSinkBlueZ::RemoveObserver( |
| 165 BluetoothAudioSink::Observer* observer) { | 163 BluetoothAudioSink::Observer* observer) { |
| 166 CHECK(observer); | 164 CHECK(observer); |
| 167 observers_.RemoveObserver(observer); | 165 observers_.RemoveObserver(observer); |
| 168 } | 166 } |
| 169 | 167 |
| 170 BluetoothAudioSink::State BluetoothAudioSinkChromeOS::GetState() const { | 168 BluetoothAudioSink::State BluetoothAudioSinkBlueZ::GetState() const { |
| 171 return state_; | 169 return state_; |
| 172 } | 170 } |
| 173 | 171 |
| 174 uint16_t BluetoothAudioSinkChromeOS::GetVolume() const { | 172 uint16_t BluetoothAudioSinkBlueZ::GetVolume() const { |
| 175 return volume_; | 173 return volume_; |
| 176 } | 174 } |
| 177 | 175 |
| 178 void BluetoothAudioSinkChromeOS::Register( | 176 void BluetoothAudioSinkBlueZ::Register( |
| 179 const BluetoothAudioSink::Options& options, | 177 const BluetoothAudioSink::Options& options, |
| 180 const base::Closure& callback, | 178 const base::Closure& callback, |
| 181 const BluetoothAudioSink::ErrorCallback& error_callback) { | 179 const BluetoothAudioSink::ErrorCallback& error_callback) { |
| 182 VLOG(1) << "Register"; | 180 VLOG(1) << "Register"; |
| 183 | 181 |
| 184 DCHECK(adapter_.get()); | 182 DCHECK(adapter_.get()); |
| 185 DCHECK_EQ(state_, BluetoothAudioSink::STATE_DISCONNECTED); | 183 DCHECK_EQ(state_, BluetoothAudioSink::STATE_DISCONNECTED); |
| 186 | 184 |
| 187 // Gets system bus. | 185 // Gets system bus. |
| 188 dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus(); | 186 dbus::Bus* system_bus = bluez::BluezDBusManager::Get()->GetSystemBus(); |
| 189 | 187 |
| 190 // Creates a Media Endpoint with newly-generated path. | 188 // Creates a Media Endpoint with newly-generated path. |
| 191 endpoint_path_ = GenerateEndpointPath(); | 189 endpoint_path_ = GenerateEndpointPath(); |
| 192 media_endpoint_.reset(bluez::BluetoothMediaEndpointServiceProvider::Create( | 190 media_endpoint_.reset(bluez::BluetoothMediaEndpointServiceProvider::Create( |
| 193 system_bus, endpoint_path_, this)); | 191 system_bus, endpoint_path_, this)); |
| 194 | 192 |
| 195 DCHECK(media_endpoint_.get()); | 193 DCHECK(media_endpoint_.get()); |
| 196 | 194 |
| 197 // Creates endpoint properties with |options|. | 195 // Creates endpoint properties with |options|. |
| 198 options_ = options; | 196 options_ = options; |
| 199 bluez::BluetoothMediaClient::EndpointProperties endpoint_properties; | 197 bluez::BluetoothMediaClient::EndpointProperties endpoint_properties; |
| 200 endpoint_properties.uuid = | 198 endpoint_properties.uuid = |
| 201 bluez::BluetoothMediaClient::kBluetoothAudioSinkUUID; | 199 bluez::BluetoothMediaClient::kBluetoothAudioSinkUUID; |
| 202 endpoint_properties.codec = options_.codec; | 200 endpoint_properties.codec = options_.codec; |
| 203 endpoint_properties.capabilities = options_.capabilities; | 201 endpoint_properties.capabilities = options_.capabilities; |
| 204 | 202 |
| 205 media_path_ = static_cast<BluetoothAdapterChromeOS*>( | 203 media_path_ = |
| 206 adapter_.get())->object_path(); | 204 static_cast<BluetoothAdapterBlueZ*>(adapter_.get())->object_path(); |
| 207 | 205 |
| 208 bluez::BluetoothMediaClient* media = | 206 bluez::BluetoothMediaClient* media = |
| 209 bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); | 207 bluez::BluezDBusManager::Get()->GetBluetoothMediaClient(); |
| 210 CHECK(media); | 208 CHECK(media); |
| 211 media->RegisterEndpoint( | 209 media->RegisterEndpoint( |
| 212 media_path_, | 210 media_path_, endpoint_path_, endpoint_properties, |
| 213 endpoint_path_, | 211 base::Bind(&BluetoothAudioSinkBlueZ::OnRegisterSucceeded, |
| 214 endpoint_properties, | |
| 215 base::Bind(&BluetoothAudioSinkChromeOS::OnRegisterSucceeded, | |
| 216 weak_ptr_factory_.GetWeakPtr(), callback), | 212 weak_ptr_factory_.GetWeakPtr(), callback), |
| 217 base::Bind(&BluetoothAudioSinkChromeOS::OnRegisterFailed, | 213 base::Bind(&BluetoothAudioSinkBlueZ::OnRegisterFailed, |
| 218 weak_ptr_factory_.GetWeakPtr(), error_callback)); | 214 weak_ptr_factory_.GetWeakPtr(), error_callback)); |
| 219 } | 215 } |
| 220 | 216 |
| 221 bluez::BluetoothMediaEndpointServiceProvider* | 217 bluez::BluetoothMediaEndpointServiceProvider* |
| 222 BluetoothAudioSinkChromeOS::GetEndpointServiceProvider() { | 218 BluetoothAudioSinkBlueZ::GetEndpointServiceProvider() { |
| 223 return media_endpoint_.get(); | 219 return media_endpoint_.get(); |
| 224 } | 220 } |
| 225 | 221 |
| 226 void BluetoothAudioSinkChromeOS::AdapterPresentChanged( | 222 void BluetoothAudioSinkBlueZ::AdapterPresentChanged( |
| 227 device::BluetoothAdapter* adapter, bool present) { | 223 device::BluetoothAdapter* adapter, |
| 224 bool present) { |
| 228 VLOG(1) << "AdapterPresentChanged: " << present; | 225 VLOG(1) << "AdapterPresentChanged: " << present; |
| 229 | 226 |
| 230 if (adapter != adapter_.get()) | 227 if (adapter != adapter_.get()) |
| 231 return; | 228 return; |
| 232 | 229 |
| 233 if (adapter->IsPresent()) { | 230 if (adapter->IsPresent()) { |
| 234 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); | 231 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); |
| 235 } else { | 232 } else { |
| 236 adapter_->RemoveObserver(this); | 233 adapter_->RemoveObserver(this); |
| 237 StateChanged(BluetoothAudioSink::STATE_INVALID); | 234 StateChanged(BluetoothAudioSink::STATE_INVALID); |
| 238 } | 235 } |
| 239 } | 236 } |
| 240 | 237 |
| 241 void BluetoothAudioSinkChromeOS::AdapterPoweredChanged( | 238 void BluetoothAudioSinkBlueZ::AdapterPoweredChanged( |
| 242 device::BluetoothAdapter* adapter, bool powered) { | 239 device::BluetoothAdapter* adapter, |
| 240 bool powered) { |
| 243 VLOG(1) << "AdapterPoweredChanged: " << powered; | 241 VLOG(1) << "AdapterPoweredChanged: " << powered; |
| 244 | 242 |
| 245 if (adapter != adapter_.get()) | 243 if (adapter != adapter_.get()) |
| 246 return; | 244 return; |
| 247 | 245 |
| 248 // Regardless of the new powered state, |state_| goes to STATE_DISCONNECTED. | 246 // Regardless of the new powered state, |state_| goes to STATE_DISCONNECTED. |
| 249 // If false, the transport is closed, but the endpoint is still valid for use. | 247 // If false, the transport is closed, but the endpoint is still valid for use. |
| 250 // If true, the previous transport has been torn down, so the |state_| has to | 248 // If true, the previous transport has been torn down, so the |state_| has to |
| 251 // be disconnected before SetConfigruation is called. | 249 // be disconnected before SetConfigruation is called. |
| 252 if (state_ != BluetoothAudioSink::STATE_INVALID) | 250 if (state_ != BluetoothAudioSink::STATE_INVALID) |
| 253 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); | 251 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); |
| 254 } | 252 } |
| 255 | 253 |
| 256 void BluetoothAudioSinkChromeOS::MediaRemoved(const ObjectPath& object_path) { | 254 void BluetoothAudioSinkBlueZ::MediaRemoved(const ObjectPath& object_path) { |
| 257 if (object_path == media_path_) { | 255 if (object_path == media_path_) { |
| 258 VLOG(1) << "MediaRemoved: " << object_path.value(); | 256 VLOG(1) << "MediaRemoved: " << object_path.value(); |
| 259 StateChanged(BluetoothAudioSink::STATE_INVALID); | 257 StateChanged(BluetoothAudioSink::STATE_INVALID); |
| 260 } | 258 } |
| 261 } | 259 } |
| 262 | 260 |
| 263 void BluetoothAudioSinkChromeOS::MediaTransportRemoved( | 261 void BluetoothAudioSinkBlueZ::MediaTransportRemoved( |
| 264 const ObjectPath& object_path) { | 262 const ObjectPath& object_path) { |
| 265 // Whenever powered of |adapter_| turns false while present stays true, media | 263 // Whenever powered of |adapter_| turns false while present stays true, media |
| 266 // transport object should be removed accordingly, and the state should be | 264 // transport object should be removed accordingly, and the state should be |
| 267 // changed to STATE_DISCONNECTED. | 265 // changed to STATE_DISCONNECTED. |
| 268 if (object_path == transport_path_) { | 266 if (object_path == transport_path_) { |
| 269 VLOG(1) << "MediaTransportRemoved: " << object_path.value(); | 267 VLOG(1) << "MediaTransportRemoved: " << object_path.value(); |
| 270 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); | 268 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); |
| 271 } | 269 } |
| 272 } | 270 } |
| 273 | 271 |
| 274 void BluetoothAudioSinkChromeOS::MediaTransportPropertyChanged( | 272 void BluetoothAudioSinkBlueZ::MediaTransportPropertyChanged( |
| 275 const ObjectPath& object_path, | 273 const ObjectPath& object_path, |
| 276 const std::string& property_name) { | 274 const std::string& property_name) { |
| 277 if (object_path != transport_path_) | 275 if (object_path != transport_path_) |
| 278 return; | 276 return; |
| 279 | 277 |
| 280 VLOG(1) << "MediaTransportPropertyChanged: " << property_name; | 278 VLOG(1) << "MediaTransportPropertyChanged: " << property_name; |
| 281 | 279 |
| 282 // Retrieves the property set of the transport object with |object_path|. | 280 // Retrieves the property set of the transport object with |object_path|. |
| 283 bluez::BluetoothMediaTransportClient::Properties* properties = | 281 bluez::BluetoothMediaTransportClient::Properties* properties = |
| 284 bluez::BluezDBusManager::Get() | 282 bluez::BluezDBusManager::Get() |
| (...skipping 10 matching lines...) Expand all Loading... |
| 295 StateChanged(BluetoothAudioSink::STATE_PENDING); | 293 StateChanged(BluetoothAudioSink::STATE_PENDING); |
| 296 } else if (properties->state.value() == | 294 } else if (properties->state.value() == |
| 297 bluez::BluetoothMediaTransportClient::kStateActive) { | 295 bluez::BluetoothMediaTransportClient::kStateActive) { |
| 298 StateChanged(BluetoothAudioSink::STATE_ACTIVE); | 296 StateChanged(BluetoothAudioSink::STATE_ACTIVE); |
| 299 } | 297 } |
| 300 } else if (property_name == properties->volume.name()) { | 298 } else if (property_name == properties->volume.name()) { |
| 301 VolumeChanged(properties->volume.value()); | 299 VolumeChanged(properties->volume.value()); |
| 302 } | 300 } |
| 303 } | 301 } |
| 304 | 302 |
| 305 void BluetoothAudioSinkChromeOS::SetConfiguration( | 303 void BluetoothAudioSinkBlueZ::SetConfiguration( |
| 306 const ObjectPath& transport_path, | 304 const ObjectPath& transport_path, |
| 307 const TransportProperties& properties) { | 305 const TransportProperties& properties) { |
| 308 VLOG(1) << "SetConfiguration"; | 306 VLOG(1) << "SetConfiguration"; |
| 309 transport_path_ = transport_path; | 307 transport_path_ = transport_path; |
| 310 | 308 |
| 311 // The initial state for a connection should be "idle". | 309 // The initial state for a connection should be "idle". |
| 312 if (properties.state != bluez::BluetoothMediaTransportClient::kStateIdle) { | 310 if (properties.state != bluez::BluetoothMediaTransportClient::kStateIdle) { |
| 313 VLOG(1) << "SetConfiugration - unexpected state :" << properties.state; | 311 VLOG(1) << "SetConfiugration - unexpected state :" << properties.state; |
| 314 return; | 312 return; |
| 315 } | 313 } |
| 316 | 314 |
| 317 // Updates |volume_| if the volume level is provided in |properties|. | 315 // Updates |volume_| if the volume level is provided in |properties|. |
| 318 if (properties.volume.get()) { | 316 if (properties.volume.get()) { |
| 319 VolumeChanged(*properties.volume); | 317 VolumeChanged(*properties.volume); |
| 320 } | 318 } |
| 321 | 319 |
| 322 StateChanged(BluetoothAudioSink::STATE_IDLE); | 320 StateChanged(BluetoothAudioSink::STATE_IDLE); |
| 323 } | 321 } |
| 324 | 322 |
| 325 void BluetoothAudioSinkChromeOS::SelectConfiguration( | 323 void BluetoothAudioSinkBlueZ::SelectConfiguration( |
| 326 const std::vector<uint8_t>& capabilities, | 324 const std::vector<uint8_t>& capabilities, |
| 327 const SelectConfigurationCallback& callback) { | 325 const SelectConfigurationCallback& callback) { |
| 328 VLOG(1) << "SelectConfiguration"; | 326 VLOG(1) << "SelectConfiguration"; |
| 329 callback.Run(options_.capabilities); | 327 callback.Run(options_.capabilities); |
| 330 } | 328 } |
| 331 | 329 |
| 332 void BluetoothAudioSinkChromeOS::ClearConfiguration( | 330 void BluetoothAudioSinkBlueZ::ClearConfiguration( |
| 333 const ObjectPath& transport_path) { | 331 const ObjectPath& transport_path) { |
| 334 if (transport_path != transport_path_) | 332 if (transport_path != transport_path_) |
| 335 return; | 333 return; |
| 336 | 334 |
| 337 VLOG(1) << "ClearConfiguration"; | 335 VLOG(1) << "ClearConfiguration"; |
| 338 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); | 336 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); |
| 339 } | 337 } |
| 340 | 338 |
| 341 void BluetoothAudioSinkChromeOS::Released() { | 339 void BluetoothAudioSinkBlueZ::Released() { |
| 342 VLOG(1) << "Released"; | 340 VLOG(1) << "Released"; |
| 343 StateChanged(BluetoothAudioSink::STATE_INVALID); | 341 StateChanged(BluetoothAudioSink::STATE_INVALID); |
| 344 } | 342 } |
| 345 | 343 |
| 346 void BluetoothAudioSinkChromeOS::OnFileCanReadWithoutBlocking(int fd) { | 344 void BluetoothAudioSinkBlueZ::OnFileCanReadWithoutBlocking(int fd) { |
| 347 ReadFromFile(); | 345 ReadFromFile(); |
| 348 } | 346 } |
| 349 | 347 |
| 350 void BluetoothAudioSinkChromeOS::OnFileCanWriteWithoutBlocking(int fd) { | 348 void BluetoothAudioSinkBlueZ::OnFileCanWriteWithoutBlocking(int fd) { |
| 351 // Do nothing for now. | 349 // Do nothing for now. |
| 352 } | 350 } |
| 353 | 351 |
| 354 void BluetoothAudioSinkChromeOS::AcquireFD() { | 352 void BluetoothAudioSinkBlueZ::AcquireFD() { |
| 355 VLOG(1) << "AcquireFD - transport path: " << transport_path_.value(); | 353 VLOG(1) << "AcquireFD - transport path: " << transport_path_.value(); |
| 356 | 354 |
| 357 read_has_failed_ = false; | 355 read_has_failed_ = false; |
| 358 | 356 |
| 359 bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient()->Acquire( | 357 bluez::BluezDBusManager::Get()->GetBluetoothMediaTransportClient()->Acquire( |
| 360 transport_path_, | 358 transport_path_, base::Bind(&BluetoothAudioSinkBlueZ::OnAcquireSucceeded, |
| 361 base::Bind(&BluetoothAudioSinkChromeOS::OnAcquireSucceeded, | 359 weak_ptr_factory_.GetWeakPtr()), |
| 362 weak_ptr_factory_.GetWeakPtr()), | 360 base::Bind(&BluetoothAudioSinkBlueZ::OnAcquireFailed, |
| 363 base::Bind(&BluetoothAudioSinkChromeOS::OnAcquireFailed, | |
| 364 weak_ptr_factory_.GetWeakPtr())); | 361 weak_ptr_factory_.GetWeakPtr())); |
| 365 } | 362 } |
| 366 | 363 |
| 367 void BluetoothAudioSinkChromeOS::WatchFD() { | 364 void BluetoothAudioSinkBlueZ::WatchFD() { |
| 368 CHECK(file_.get() && file_->IsValid()); | 365 CHECK(file_.get() && file_->IsValid()); |
| 369 | 366 |
| 370 VLOG(1) << "WatchFD - file: " << file_->GetPlatformFile() | 367 VLOG(1) << "WatchFD - file: " << file_->GetPlatformFile() |
| 371 << ", file validity: " << file_->IsValid(); | 368 << ", file validity: " << file_->IsValid(); |
| 372 | 369 |
| 373 base::MessageLoopForIO::current()->WatchFileDescriptor( | 370 base::MessageLoopForIO::current()->WatchFileDescriptor( |
| 374 file_->GetPlatformFile(), true, base::MessageLoopForIO::WATCH_READ, | 371 file_->GetPlatformFile(), true, base::MessageLoopForIO::WATCH_READ, |
| 375 &fd_read_watcher_, this); | 372 &fd_read_watcher_, this); |
| 376 } | 373 } |
| 377 | 374 |
| 378 void BluetoothAudioSinkChromeOS::StopWatchingFD() { | 375 void BluetoothAudioSinkBlueZ::StopWatchingFD() { |
| 379 if (!file_.get()) { | 376 if (!file_.get()) { |
| 380 VLOG(1) << "StopWatchingFD - skip"; | 377 VLOG(1) << "StopWatchingFD - skip"; |
| 381 return; | 378 return; |
| 382 } | 379 } |
| 383 | 380 |
| 384 bool stopped = fd_read_watcher_.StopWatchingFileDescriptor(); | 381 bool stopped = fd_read_watcher_.StopWatchingFileDescriptor(); |
| 385 VLOG(1) << "StopWatchingFD - watch stopped: " << stopped; | 382 VLOG(1) << "StopWatchingFD - watch stopped: " << stopped; |
| 386 CHECK(stopped); | 383 CHECK(stopped); |
| 387 | 384 |
| 388 read_mtu_ = kInvalidReadMtu; | 385 read_mtu_ = kInvalidReadMtu; |
| 389 write_mtu_ = kInvalidWriteMtu; | 386 write_mtu_ = kInvalidWriteMtu; |
| 390 file_.reset(); // This will close the file descriptor. | 387 file_.reset(); // This will close the file descriptor. |
| 391 } | 388 } |
| 392 | 389 |
| 393 void BluetoothAudioSinkChromeOS::ReadFromFile() { | 390 void BluetoothAudioSinkBlueZ::ReadFromFile() { |
| 394 DCHECK(file_.get() && file_->IsValid()); | 391 DCHECK(file_.get() && file_->IsValid()); |
| 395 DCHECK(data_.get()); | 392 DCHECK(data_.get()); |
| 396 | 393 |
| 397 int size = file_->ReadAtCurrentPosNoBestEffort(data_.get(), read_mtu_); | 394 int size = file_->ReadAtCurrentPosNoBestEffort(data_.get(), read_mtu_); |
| 398 | 395 |
| 399 if (size == -1) { | 396 if (size == -1) { |
| 400 // To reduce the number of logs, log only once for multiple failures. | 397 // To reduce the number of logs, log only once for multiple failures. |
| 401 if (!read_has_failed_) { | 398 if (!read_has_failed_) { |
| 402 VLOG(1) << "ReadFromFile - failed"; | 399 VLOG(1) << "ReadFromFile - failed"; |
| 403 read_has_failed_ = true; | 400 read_has_failed_ = true; |
| 404 } | 401 } |
| 405 return; | 402 return; |
| 406 } | 403 } |
| 407 | 404 |
| 408 VLOG(1) << "ReadFromFile - read " << size << " bytes"; | 405 VLOG(1) << "ReadFromFile - read " << size << " bytes"; |
| 409 FOR_EACH_OBSERVER( | 406 FOR_EACH_OBSERVER( |
| 410 BluetoothAudioSink::Observer, observers_, | 407 BluetoothAudioSink::Observer, observers_, |
| 411 BluetoothAudioSinkDataAvailable(this, data_.get(), size, read_mtu_)); | 408 BluetoothAudioSinkDataAvailable(this, data_.get(), size, read_mtu_)); |
| 412 } | 409 } |
| 413 | 410 |
| 414 void BluetoothAudioSinkChromeOS::StateChanged( | 411 void BluetoothAudioSinkBlueZ::StateChanged(BluetoothAudioSink::State state) { |
| 415 BluetoothAudioSink::State state) { | |
| 416 if (state == state_) | 412 if (state == state_) |
| 417 return; | 413 return; |
| 418 | 414 |
| 419 VLOG(1) << "StateChanged - state: " << StateToString(state); | 415 VLOG(1) << "StateChanged - state: " << StateToString(state); |
| 420 | 416 |
| 421 switch (state) { | 417 switch (state) { |
| 422 case BluetoothAudioSink::STATE_INVALID: | 418 case BluetoothAudioSink::STATE_INVALID: |
| 423 ResetMedia(); | 419 ResetMedia(); |
| 424 ResetEndpoint(); | 420 ResetEndpoint(); |
| 425 case BluetoothAudioSink::STATE_DISCONNECTED: | 421 case BluetoothAudioSink::STATE_DISCONNECTED: |
| (...skipping 10 matching lines...) Expand all Loading... |
| 436 break; | 432 break; |
| 437 default: | 433 default: |
| 438 break; | 434 break; |
| 439 } | 435 } |
| 440 | 436 |
| 441 state_ = state; | 437 state_ = state; |
| 442 FOR_EACH_OBSERVER(BluetoothAudioSink::Observer, observers_, | 438 FOR_EACH_OBSERVER(BluetoothAudioSink::Observer, observers_, |
| 443 BluetoothAudioSinkStateChanged(this, state_)); | 439 BluetoothAudioSinkStateChanged(this, state_)); |
| 444 } | 440 } |
| 445 | 441 |
| 446 void BluetoothAudioSinkChromeOS::VolumeChanged(uint16_t volume) { | 442 void BluetoothAudioSinkBlueZ::VolumeChanged(uint16_t volume) { |
| 447 if (volume == volume_) | 443 if (volume == volume_) |
| 448 return; | 444 return; |
| 449 | 445 |
| 450 VLOG(1) << "VolumeChanged: " << volume; | 446 VLOG(1) << "VolumeChanged: " << volume; |
| 451 | 447 |
| 452 volume_ = std::min(volume, BluetoothAudioSink::kInvalidVolume); | 448 volume_ = std::min(volume, BluetoothAudioSink::kInvalidVolume); |
| 453 FOR_EACH_OBSERVER(BluetoothAudioSink::Observer, observers_, | 449 FOR_EACH_OBSERVER(BluetoothAudioSink::Observer, observers_, |
| 454 BluetoothAudioSinkVolumeChanged(this, volume_)); | 450 BluetoothAudioSinkVolumeChanged(this, volume_)); |
| 455 } | 451 } |
| 456 | 452 |
| 457 void BluetoothAudioSinkChromeOS::OnRegisterSucceeded( | 453 void BluetoothAudioSinkBlueZ::OnRegisterSucceeded( |
| 458 const base::Closure& callback) { | 454 const base::Closure& callback) { |
| 459 DCHECK(media_endpoint_.get()); | 455 DCHECK(media_endpoint_.get()); |
| 460 VLOG(1) << "OnRegisterSucceeded"; | 456 VLOG(1) << "OnRegisterSucceeded"; |
| 461 | 457 |
| 462 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); | 458 StateChanged(BluetoothAudioSink::STATE_DISCONNECTED); |
| 463 callback.Run(); | 459 callback.Run(); |
| 464 } | 460 } |
| 465 | 461 |
| 466 void BluetoothAudioSinkChromeOS::OnRegisterFailed( | 462 void BluetoothAudioSinkBlueZ::OnRegisterFailed( |
| 467 const BluetoothAudioSink::ErrorCallback& error_callback, | 463 const BluetoothAudioSink::ErrorCallback& error_callback, |
| 468 const std::string& error_name, | 464 const std::string& error_name, |
| 469 const std::string& error_message) { | 465 const std::string& error_message) { |
| 470 VLOG(1) << "OnRegisterFailed - error name: " << error_name | 466 VLOG(1) << "OnRegisterFailed - error name: " << error_name |
| 471 << ", error message: " << error_message; | 467 << ", error message: " << error_message; |
| 472 | 468 |
| 473 ResetEndpoint(); | 469 ResetEndpoint(); |
| 474 error_callback.Run(BluetoothAudioSink::ERROR_NOT_REGISTERED); | 470 error_callback.Run(BluetoothAudioSink::ERROR_NOT_REGISTERED); |
| 475 } | 471 } |
| 476 | 472 |
| 477 void BluetoothAudioSinkChromeOS::OnUnregisterSucceeded( | 473 void BluetoothAudioSinkBlueZ::OnUnregisterSucceeded( |
| 478 const base::Closure& callback) { | 474 const base::Closure& callback) { |
| 479 VLOG(1) << "Unregistered - endpoint: " << endpoint_path_.value(); | 475 VLOG(1) << "Unregistered - endpoint: " << endpoint_path_.value(); |
| 480 | 476 |
| 481 // Once the state becomes STATE_INVALID, media, media transport and media | 477 // Once the state becomes STATE_INVALID, media, media transport and media |
| 482 // endpoint will be reset. | 478 // endpoint will be reset. |
| 483 StateChanged(BluetoothAudioSink::STATE_INVALID); | 479 StateChanged(BluetoothAudioSink::STATE_INVALID); |
| 484 callback.Run(); | 480 callback.Run(); |
| 485 } | 481 } |
| 486 | 482 |
| 487 void BluetoothAudioSinkChromeOS::OnUnregisterFailed( | 483 void BluetoothAudioSinkBlueZ::OnUnregisterFailed( |
| 488 const device::BluetoothAudioSink::ErrorCallback& error_callback, | 484 const device::BluetoothAudioSink::ErrorCallback& error_callback, |
| 489 const std::string& error_name, | 485 const std::string& error_name, |
| 490 const std::string& error_message) { | 486 const std::string& error_message) { |
| 491 VLOG(1) << "OnUnregisterFailed - error name: " << error_name | 487 VLOG(1) << "OnUnregisterFailed - error name: " << error_name |
| 492 << ", error message: " << error_message; | 488 << ", error message: " << error_message; |
| 493 | 489 |
| 494 error_callback.Run(BluetoothAudioSink::ERROR_NOT_UNREGISTERED); | 490 error_callback.Run(BluetoothAudioSink::ERROR_NOT_UNREGISTERED); |
| 495 } | 491 } |
| 496 | 492 |
| 497 void BluetoothAudioSinkChromeOS::OnAcquireSucceeded( | 493 void BluetoothAudioSinkBlueZ::OnAcquireSucceeded(dbus::FileDescriptor* fd, |
| 498 dbus::FileDescriptor* fd, | 494 const uint16_t read_mtu, |
| 499 const uint16_t read_mtu, | 495 const uint16_t write_mtu) { |
| 500 const uint16_t write_mtu) { | |
| 501 CHECK(fd); | 496 CHECK(fd); |
| 502 fd->CheckValidity(); | 497 fd->CheckValidity(); |
| 503 CHECK(fd->is_valid() && fd->value() != kInvalidFd); | 498 CHECK(fd->is_valid() && fd->value() != kInvalidFd); |
| 504 CHECK_GT(read_mtu, kInvalidReadMtu); | 499 CHECK_GT(read_mtu, kInvalidReadMtu); |
| 505 CHECK_GT(write_mtu, kInvalidWriteMtu); | 500 CHECK_GT(write_mtu, kInvalidWriteMtu); |
| 506 | 501 |
| 507 // Avoids unnecessary memory reallocation if read MTU doesn't change. | 502 // Avoids unnecessary memory reallocation if read MTU doesn't change. |
| 508 if (read_mtu != read_mtu_) { | 503 if (read_mtu != read_mtu_) { |
| 509 read_mtu_ = read_mtu; | 504 read_mtu_ = read_mtu; |
| 510 data_.reset(new char[read_mtu_]); | 505 data_.reset(new char[read_mtu_]); |
| 511 VLOG(1) << "OnAcquireSucceeded - allocate " << read_mtu_ | 506 VLOG(1) << "OnAcquireSucceeded - allocate " << read_mtu_ |
| 512 << " bytes of memory"; | 507 << " bytes of memory"; |
| 513 } | 508 } |
| 514 | 509 |
| 515 write_mtu_ = write_mtu; | 510 write_mtu_ = write_mtu; |
| 516 | 511 |
| 517 // Avoids closing the same file descriptor caused by reassignment. | 512 // Avoids closing the same file descriptor caused by reassignment. |
| 518 if (!file_.get() || file_->GetPlatformFile() != fd->value()) { | 513 if (!file_.get() || file_->GetPlatformFile() != fd->value()) { |
| 519 // Takes ownership of the file descriptor. | 514 // Takes ownership of the file descriptor. |
| 520 file_.reset(new base::File(fd->TakeValue())); | 515 file_.reset(new base::File(fd->TakeValue())); |
| 521 DCHECK(file_->IsValid()); | 516 DCHECK(file_->IsValid()); |
| 522 VLOG(1) << "OnAcquireSucceeded - update file"; | 517 VLOG(1) << "OnAcquireSucceeded - update file"; |
| 523 } | 518 } |
| 524 | 519 |
| 525 VLOG(1) << "OnAcquireSucceeded - file: " << file_->GetPlatformFile() | 520 VLOG(1) << "OnAcquireSucceeded - file: " << file_->GetPlatformFile() |
| 526 << ", read MTU: " << read_mtu_ << ", write MTU: " << write_mtu_; | 521 << ", read MTU: " << read_mtu_ << ", write MTU: " << write_mtu_; |
| 527 } | 522 } |
| 528 | 523 |
| 529 void BluetoothAudioSinkChromeOS::OnAcquireFailed( | 524 void BluetoothAudioSinkBlueZ::OnAcquireFailed( |
| 530 const std::string& error_name, | 525 const std::string& error_name, |
| 531 const std::string& error_message) { | 526 const std::string& error_message) { |
| 532 VLOG(1) << "OnAcquireFailed - error name: " << error_name | 527 VLOG(1) << "OnAcquireFailed - error name: " << error_name |
| 533 << ", error message: " << error_message; | 528 << ", error message: " << error_message; |
| 534 } | 529 } |
| 535 | 530 |
| 536 void BluetoothAudioSinkChromeOS::OnReleaseFDSucceeded() { | 531 void BluetoothAudioSinkBlueZ::OnReleaseFDSucceeded() { |
| 537 VLOG(1) << "OnReleaseFDSucceeded"; | 532 VLOG(1) << "OnReleaseFDSucceeded"; |
| 538 } | 533 } |
| 539 | 534 |
| 540 void BluetoothAudioSinkChromeOS::OnReleaseFDFailed( | 535 void BluetoothAudioSinkBlueZ::OnReleaseFDFailed( |
| 541 const std::string& error_name, | 536 const std::string& error_name, |
| 542 const std::string& error_message) { | 537 const std::string& error_message) { |
| 543 VLOG(1) << "OnReleaseFDFailed - error name: " << error_name | 538 VLOG(1) << "OnReleaseFDFailed - error name: " << error_name |
| 544 << ", error message: " << error_message; | 539 << ", error message: " << error_message; |
| 545 } | 540 } |
| 546 | 541 |
| 547 void BluetoothAudioSinkChromeOS::ResetMedia() { | 542 void BluetoothAudioSinkBlueZ::ResetMedia() { |
| 548 VLOG(1) << "ResetMedia"; | 543 VLOG(1) << "ResetMedia"; |
| 549 | 544 |
| 550 media_path_ = dbus::ObjectPath(""); | 545 media_path_ = dbus::ObjectPath(""); |
| 551 } | 546 } |
| 552 | 547 |
| 553 void BluetoothAudioSinkChromeOS::ResetTransport() { | 548 void BluetoothAudioSinkBlueZ::ResetTransport() { |
| 554 if (!transport_path_.IsValid()) { | 549 if (!transport_path_.IsValid()) { |
| 555 VLOG(1) << "ResetTransport - skip"; | 550 VLOG(1) << "ResetTransport - skip"; |
| 556 return; | 551 return; |
| 557 } | 552 } |
| 558 | 553 |
| 559 VLOG(1) << "ResetTransport - clean-up"; | 554 VLOG(1) << "ResetTransport - clean-up"; |
| 560 | 555 |
| 561 VolumeChanged(BluetoothAudioSink::kInvalidVolume); | 556 VolumeChanged(BluetoothAudioSink::kInvalidVolume); |
| 562 transport_path_ = dbus::ObjectPath(""); | 557 transport_path_ = dbus::ObjectPath(""); |
| 563 read_mtu_ = kInvalidReadMtu; | 558 read_mtu_ = kInvalidReadMtu; |
| 564 write_mtu_ = kInvalidWriteMtu; | 559 write_mtu_ = kInvalidWriteMtu; |
| 565 file_.reset(); | 560 file_.reset(); |
| 566 } | 561 } |
| 567 | 562 |
| 568 void BluetoothAudioSinkChromeOS::ResetEndpoint() { | 563 void BluetoothAudioSinkBlueZ::ResetEndpoint() { |
| 569 VLOG(1) << "ResetEndpoint"; | 564 VLOG(1) << "ResetEndpoint"; |
| 570 | 565 |
| 571 endpoint_path_ = ObjectPath(""); | 566 endpoint_path_ = ObjectPath(""); |
| 572 media_endpoint_ = nullptr; | 567 media_endpoint_ = nullptr; |
| 573 } | 568 } |
| 574 | 569 |
| 575 } // namespace chromeos | 570 } // namespace bluez |
| OLD | NEW |