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

Side by Side Diff: device/bluetooth/bluetooth_audio_sink_chromeos.cc

Issue 910023002: device/bluetooth:Implement BluetoothMediaEndpointServiceProvider delegate and media-related overrid… (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months 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 unified diff | Download patch
OLDNEW
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_chromeos.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 #include <vector>
8 9
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "chromeos/dbus/dbus_thread_manager.h" 11 #include "chromeos/dbus/dbus_thread_manager.h"
12 #include "dbus/message.h"
11 #include "device/bluetooth/bluetooth_adapter_chromeos.h" 13 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
12 14
13 namespace { 15 namespace {
14 16
15 // TODO(mcchou): Add the constant to dbus/service_constants.h. 17 // TODO(mcchou): Add the constant to dbus/service_constants.h.
16 const char kBluetoothAudioSinkServicePath[] = "/org/chromium/AudioSink"; 18 const char kBluetoothAudioSinkServicePath[] = "/org/chromium/AudioSink";
17 19
18 dbus::ObjectPath GenerateEndpointPath() { 20 dbus::ObjectPath GenerateEndpointPath() {
19 static unsigned int sequence_number = 0; 21 static unsigned int sequence_number = 0;
20 ++sequence_number; 22 ++sequence_number;
21 std::stringstream path; 23 std::stringstream path;
22 path << kBluetoothAudioSinkServicePath << "/endpoint" << sequence_number; 24 path << kBluetoothAudioSinkServicePath << "/endpoint" << sequence_number;
23 return dbus::ObjectPath(path.str()); 25 return dbus::ObjectPath(path.str());
24 } 26 }
25 27
26 } // namespace 28 } // namespace
27 29
28 namespace chromeos { 30 namespace chromeos {
29 31
30 BluetoothAudioSinkChromeOS::BluetoothAudioSinkChromeOS( 32 BluetoothAudioSinkChromeOS::BluetoothAudioSinkChromeOS(
31 scoped_refptr<device::BluetoothAdapter> adapter) 33 scoped_refptr<device::BluetoothAdapter> adapter)
32 : state_(device::BluetoothAudioSink::STATE_INVALID), 34 : state_(device::BluetoothAudioSink::STATE_INVALID),
33 volume_(0), 35 volume_(0),
34 read_mtu_(0), 36 read_mtu_(0),
35 write_mtu_(0), 37 write_mtu_(0),
36 adapter_(adapter), 38 adapter_(adapter),
39 media_endpoint_(nullptr),
37 weak_ptr_factory_(this) { 40 weak_ptr_factory_(this) {
38 DCHECK(adapter_.get()); 41 DCHECK(adapter_.get());
39 DCHECK(adapter_->IsPresent()); 42 DCHECK(adapter_->IsPresent());
40 43
41 StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED); 44 StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED);
42 adapter_->AddObserver(this); 45 adapter_->AddObserver(this);
43 } 46 }
44 47
45 BluetoothAudioSinkChromeOS::~BluetoothAudioSinkChromeOS() { 48 BluetoothAudioSinkChromeOS::~BluetoothAudioSinkChromeOS() {
46 DCHECK(adapter_.get()); 49 DCHECK(adapter_.get());
47 adapter_->RemoveObserver(this); 50 adapter_->RemoveObserver(this);
51
48 // TODO(mcchou): BUG=441581 52 // TODO(mcchou): BUG=441581
49 // Unregister() should be called while media and media endpoint are still 53 // Unregister() should be called while media and media endpoint are still
50 // valid. 54 // valid.
51 } 55 }
52 56
57 void BluetoothAudioSinkChromeOS::Unregister(
58 const base::Closure& callback,
59 const device::BluetoothAudioSink::ErrorCallback& error_callback) {
60 // TODO(mcchou): BUG=441581
61 // Call UnregisterEndpoint on the media object with |media_path_| and clean
62 // |observers_| and transport_path_ and reset state_ and volume.
63 // Check whether the media endpoint is registered before invoking
64 // UnregisterEndpoint.
65 }
66
53 void BluetoothAudioSinkChromeOS::AddObserver( 67 void BluetoothAudioSinkChromeOS::AddObserver(
54 device::BluetoothAudioSink::Observer* observer) { 68 device::BluetoothAudioSink::Observer* observer) {
55 DCHECK(observer); 69 DCHECK(observer);
56 observers_.AddObserver(observer); 70 observers_.AddObserver(observer);
57 } 71 }
58 72
59 void BluetoothAudioSinkChromeOS::RemoveObserver( 73 void BluetoothAudioSinkChromeOS::RemoveObserver(
60 device::BluetoothAudioSink::Observer* observer) { 74 device::BluetoothAudioSink::Observer* observer) {
61 DCHECK(observer); 75 DCHECK(observer);
62 observers_.RemoveObserver(observer); 76 observers_.RemoveObserver(observer);
(...skipping 16 matching lines...) Expand all
79 if (adapter->IsPresent()) { 93 if (adapter->IsPresent()) {
80 StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED); 94 StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED);
81 } else { 95 } else {
82 StateChanged(device::BluetoothAudioSink::STATE_INVALID); 96 StateChanged(device::BluetoothAudioSink::STATE_INVALID);
83 } 97 }
84 } 98 }
85 99
86 void BluetoothAudioSinkChromeOS::MediaRemoved( 100 void BluetoothAudioSinkChromeOS::MediaRemoved(
87 const dbus::ObjectPath& object_path) { 101 const dbus::ObjectPath& object_path) {
88 // TODO(mcchou): BUG=441581 102 // TODO(mcchou): BUG=441581
89 // Check if |object_path| equals to |media_path_|. If true, change the state 103 // Changes |state_| to STATE_INVALID or STATE_DISCONNECTED?
90 // of the audio sink, call StateChanged and reset the audio sink. 104 if (object_path == media_path_) {
105 StateChanged(device::BluetoothAudioSink::STATE_INVALID);
106 }
91 } 107 }
92 108
93 void BluetoothAudioSinkChromeOS::MediaTransportRemoved( 109 void BluetoothAudioSinkChromeOS::MediaTransportRemoved(
94 const dbus::ObjectPath& object_path) { 110 const dbus::ObjectPath& object_path) {
95 // TODO(mcchou): BUG=441581
96 // Check if |object_path| equals to |transport_path_|. If true, change the
97 // state of the audio sink, call StateChanged and reset the audio sink.
98 // Whenever powered of |adapter_| turns false while present stays true, media 111 // Whenever powered of |adapter_| turns false while present stays true, media
99 // transport object should be removed accordingly, and the state should be 112 // transport object should be removed accordingly, and the state should be
100 // changed to STATE_DISCONNECTED. 113 // changed to STATE_DISCONNECTED.
114 if (object_path == transport_path_) {
115 StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED);
116 }
101 } 117 }
102 118
103 void BluetoothAudioSinkChromeOS::MediaTransportPropertyChanged( 119 void BluetoothAudioSinkChromeOS::MediaTransportPropertyChanged(
104 const dbus::ObjectPath& object_path, 120 const dbus::ObjectPath& object_path,
105 const std::string& property_name) { 121 const std::string& property_name) {
106 // TODO(mcchou): BUG=441581 122 // Retrieves the property set of the transport object with |object_path|.
107 // Call StateChanged and VolumeChanged accordingly if there is any change on 123 chromeos::BluetoothMediaTransportClient::Properties* properties =
108 // state/volume. 124 DBusThreadManager::Get()
125 ->GetBluetoothMediaTransportClient()
126 ->GetProperties(object_path);
127
128 // Dispatches a property changed event to the corresponding handler.
129 if (property_name == properties->state.name()) {
130 if (properties->state.value() ==
131 BluetoothMediaTransportClient::kStateIdle) {
132 StateChanged(device::BluetoothAudioSink::STATE_IDLE);
133 } else if (properties->state.value() ==
134 BluetoothMediaTransportClient::kStatePending) {
135 StateChanged(device::BluetoothAudioSink::STATE_PENDING);
136 } else if (properties->state.value() ==
137 BluetoothMediaTransportClient::kStateActive) {
138 StateChanged(device::BluetoothAudioSink::STATE_ACTIVE);
139 }
140 } else if (property_name == properties->volume.name()) {
141 VolumeChanged(properties->volume.value());
142 } else {
143 VLOG(1) << "Bluetooth audio sink: transport property " << property_name
144 << " changed";
145 }
109 } 146 }
110 147
111 void BluetoothAudioSinkChromeOS::SetConfiguration( 148 void BluetoothAudioSinkChromeOS::SetConfiguration(
112 const dbus::ObjectPath& transport_path, 149 const dbus::ObjectPath& transport_path,
113 const dbus::MessageReader& properties) { 150 const TransportProperties& properties) {
114 // TODO(mcchou): BUG=441581 151 // TODO(mcchou): BUG=441581
115 // Update |transport_path_| and store properties if needed. 152 // Stores properties if needed.
153 VLOG(1) << "Bluetooth audio sink: SetConfiguration called";
154 transport_path_ = transport_path;
155 chromeos::DBusThreadManager::Get()
156 ->GetBluetoothMediaTransportClient()
157 ->AddObserver(this);
158
159 // The initial state for a connection should be "idle".
160 if (properties.state.compare(BluetoothMediaTransportClient::kStateIdle) ==
armansito 2015/02/10 00:17:01 nit: You can just compare the strings with operato
Miao 2015/02/10 22:15:21 Done.
161 0) {
162 // Updates |volume_| if the volume level is provided in |properties|.
163 if (properties.volume.get() != nullptr)
164 VolumeChanged(*properties.volume);
165
166 StateChanged(device::BluetoothAudioSink::STATE_IDLE);
167 } else {
168 LOG(WARNING) << "Bluetooth Audio Sink: unexpected state "
169 << properties.state;
armansito 2015/02/10 00:17:02 All of these nested if statements are getting a bi
Miao 2015/02/10 22:15:21 Done.
170 }
116 } 171 }
117 172
118 void BluetoothAudioSinkChromeOS::SelectConfiguration( 173 void BluetoothAudioSinkChromeOS::SelectConfiguration(
119 const std::vector<uint8_t>& capabilities, 174 const std::vector<uint8_t>& capabilities,
120 const SelectConfigurationCallback& callback) { 175 const SelectConfigurationCallback& callback) {
121 // TODO(mcchou): BUG=441581
122 // Use SelectConfigurationCallback to return the agreed capabilities.
123 VLOG(1) << "Bluetooth audio sink: SelectConfiguration called"; 176 VLOG(1) << "Bluetooth audio sink: SelectConfiguration called";
124 callback.Run(options_.capabilities); 177 callback.Run(options_.capabilities);
125 } 178 }
126 179
127 void BluetoothAudioSinkChromeOS::ClearConfiguration( 180 void BluetoothAudioSinkChromeOS::ClearConfiguration(
128 const dbus::ObjectPath& transport_path) { 181 const dbus::ObjectPath& transport_path) {
129 // TODO(mcchou): BUG=441581 182 // TODO(mcchou): BUG=441581
130 // Reset the configuration to the default one and close IOBuffer. 183 // Closes IOBuffer.
armansito 2015/02/10 00:17:02 Well, currently there's no IOBuffer anywhere so th
Miao 2015/02/10 22:15:21 Removed.
184 VLOG(1) << "Bluetooth audio sink: ClearConfiguration called";
185 StateChanged(device::BluetoothAudioSink::STATE_DISCONNECTED);
131 } 186 }
132 187
133 void BluetoothAudioSinkChromeOS::Release() { 188 void BluetoothAudioSinkChromeOS::Released() {
134 VLOG(1) << "Bluetooth audio sink: Release called"; 189 VLOG(1) << "Bluetooth audio sink: Released called";
135 StateChanged(device::BluetoothAudioSink::STATE_INVALID); 190 StateChanged(device::BluetoothAudioSink::STATE_INVALID);
136 } 191 }
137 192
138 void BluetoothAudioSinkChromeOS::Register( 193 void BluetoothAudioSinkChromeOS::Register(
139 const device::BluetoothAudioSink::Options& options, 194 const device::BluetoothAudioSink::Options& options,
140 const base::Closure& callback, 195 const base::Closure& callback,
141 const device::BluetoothAudioSink::ErrorCallback& error_callback) { 196 const device::BluetoothAudioSink::ErrorCallback& error_callback) {
142 // TODO(mcchou): BUG=441581 197 // Gets Media object, initiates an Media Endpoint with options, and returns
armansito 2015/02/10 00:17:02 nit: s/an Media/a Media/
Miao 2015/02/10 22:15:21 Done.
143 // Get Media object, initiate an Media Endpoint with options, and return the 198 // the audio sink via callback. Adds the audio sink as an observer of both
144 // audio sink via callback. Add the audio sink as observer of both Media and 199 // Media.
armansito 2015/02/10 00:17:01 Note: You should avoid comments like this if all t
Miao 2015/02/10 22:15:21 Done.
145 // Media Transport. 200
146 DCHECK(adapter_.get()); 201 DCHECK(adapter_.get());
147 DCHECK_EQ(state_, device::BluetoothAudioSink::STATE_DISCONNECTED); 202 DCHECK_EQ(state_, device::BluetoothAudioSink::STATE_DISCONNECTED);
148 203
149 // Gets system bus. 204 // Gets system bus.
150 dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus(); 205 dbus::Bus* system_bus = DBusThreadManager::Get()->GetSystemBus();
151 206
152 // Creates a Media Endpoint with newly-generated path. 207 // Creates a Media Endpoint with newly-generated path.
153 endpoint_path_ = GenerateEndpointPath(); 208 endpoint_path_ = GenerateEndpointPath();
154 media_endpoint_.reset( 209 media_endpoint_.reset(
155 BluetoothMediaEndpointServiceProvider::Create( 210 BluetoothMediaEndpointServiceProvider::Create(
156 system_bus, endpoint_path_, this)); 211 system_bus, endpoint_path_, this));
157 212
158 DCHECK(media_endpoint_.get()); 213 DCHECK(media_endpoint_.get());
159 214
160 // Creates endpoint properties with |options|. 215 // Creates endpoint properties with |options|.
161 options_ = options; 216 options_ = options;
162 chromeos::BluetoothMediaClient::EndpointProperties endpoint_properties; 217 chromeos::BluetoothMediaClient::EndpointProperties endpoint_properties;
163 endpoint_properties.uuid = BluetoothMediaClient::kBluetoothAudioSinkUUID; 218 endpoint_properties.uuid = BluetoothMediaClient::kBluetoothAudioSinkUUID;
164 endpoint_properties.codec = options_.codec; 219 endpoint_properties.codec = options_.codec;
165 endpoint_properties.capabilities = options_.capabilities; 220 endpoint_properties.capabilities = options_.capabilities;
166 221
167 // Gets Media object exported by D-Bus and registers the endpoint. 222 // Gets Media object exported by D-Bus and registers the endpoint.
168 chromeos::BluetoothMediaClient* media = 223 chromeos::BluetoothMediaClient* media =
169 DBusThreadManager::Get()->GetBluetoothMediaClient(); 224 DBusThreadManager::Get()->GetBluetoothMediaClient();
225 DCHECK(media);
226
170 BluetoothAdapterChromeOS* adapter_chromeos = 227 BluetoothAdapterChromeOS* adapter_chromeos =
171 static_cast<BluetoothAdapterChromeOS*>(adapter_.get()); 228 static_cast<BluetoothAdapterChromeOS*>(adapter_.get());
172 media->AddObserver(this); 229 media->AddObserver(this);
173 media_path_ = adapter_chromeos->object_path(); 230 media_path_ = adapter_chromeos->object_path();
174 media->RegisterEndpoint( 231 media->RegisterEndpoint(
175 media_path_, 232 media_path_,
176 endpoint_path_, 233 endpoint_path_,
177 endpoint_properties, 234 endpoint_properties,
178 base::Bind(&BluetoothAudioSinkChromeOS::OnRegisterSucceeded, 235 base::Bind(&BluetoothAudioSinkChromeOS::OnRegisterSucceeded,
179 weak_ptr_factory_.GetWeakPtr(), callback), 236 weak_ptr_factory_.GetWeakPtr(), callback),
180 base::Bind(&BluetoothAudioSinkChromeOS::OnRegisterFailed, 237 base::Bind(&BluetoothAudioSinkChromeOS::OnRegisterFailed,
181 weak_ptr_factory_.GetWeakPtr(), error_callback)); 238 weak_ptr_factory_.GetWeakPtr(), error_callback));
182 } 239 }
183 240
184 void BluetoothAudioSinkChromeOS::Unregister( 241 BluetoothMediaEndpointServiceProvider*
185 const base::Closure& callback, 242 BluetoothAudioSinkChromeOS::GetEndpointServiceProvider() {
186 const device::BluetoothAudioSink::ErrorCallback& error_callback) { 243 return media_endpoint_.get();
187 // TODO(mcchou): BUG=441581
188 // Call UnregisterEndpoint on the media object with |media_path_| and clean
189 // |observers_| and transport_path_ and reset state_ and volume.
190 // Check whether the media endpoint is registered before invoking
191 // UnregisterEndpoint.
192 } 244 }
193 245
194 void BluetoothAudioSinkChromeOS::StateChanged( 246 void BluetoothAudioSinkChromeOS::StateChanged(
195 device::BluetoothAudioSink::State state) { 247 device::BluetoothAudioSink::State state) {
196 if (state == state_) 248 if (state == state_)
197 return; 249 return;
198 250
199 VLOG(1) << "Bluetooth audio sink state changed: " << state; 251 VLOG(1) << "Bluetooth audio sink state changed: " << state;
200 252
201 switch (state) { 253 switch (state) {
202 case device::BluetoothAudioSink::STATE_INVALID: { 254 case device::BluetoothAudioSink::STATE_INVALID: {
203 // TODO(mcchou): BUG=441581 255 // TODO(mcchou): BUG=441581
204 // Clean media, media transport and media endpoint. 256 ResetMedia();
257 ResetTransport();
258 ResetEndpoint();
205 break; 259 break;
206 } 260 }
207 case device::BluetoothAudioSink::STATE_DISCONNECTED: { 261 case device::BluetoothAudioSink::STATE_DISCONNECTED: {
208 // TODO(mcchou): BUG=441581 262 // TODO(mcchou): BUG=441581
209 // Clean media transport. 263 // Clean media transport and remove the audio sink from its observer list.
264 ResetTransport();
210 break; 265 break;
211 } 266 }
212 case device::BluetoothAudioSink::STATE_IDLE: { 267 case device::BluetoothAudioSink::STATE_IDLE: {
213 // TODO(mcchou): BUG=441581 268 // TODO(mcchou): BUG=441581
214 // Triggered by MediaTransportPropertyChanged. Stop watching on file 269 // Triggered by MediaTransportPropertyChanged and SetConfiguration.
215 // descriptor if there is one. 270 // Stop watching on file descriptor if there is one.
216 break; 271 break;
217 } 272 }
218 case device::BluetoothAudioSink::STATE_PENDING: { 273 case device::BluetoothAudioSink::STATE_PENDING: {
219 // TODO(mcchou): BUG=441581 274 // TODO(mcchou): BUG=441581
220 // Call BluetoothMediaTransportClient::Acquire() to get fd and mtus. 275 // Call BluetoothMediaTransportClient::Acquire() to get fd and mtus.
221 break; 276 break;
222 } 277 }
223 case device::BluetoothAudioSink::STATE_ACTIVE: { 278 case device::BluetoothAudioSink::STATE_ACTIVE: {
224 // TODO(mcchou): BUG=441581 279 // TODO(mcchou): BUG=441581
225 // Read from fd and call DataAvailable. 280 // Read from fd and call DataAvailable.
(...skipping 25 matching lines...) Expand all
251 callback.Run(); 306 callback.Run();
252 } 307 }
253 308
254 void BluetoothAudioSinkChromeOS::OnRegisterFailed( 309 void BluetoothAudioSinkChromeOS::OnRegisterFailed(
255 const BluetoothAudioSink::ErrorCallback& error_callback, 310 const BluetoothAudioSink::ErrorCallback& error_callback,
256 const std::string& error_name, 311 const std::string& error_name,
257 const std::string& error_message) { 312 const std::string& error_message) {
258 DCHECK(media_endpoint_.get()); 313 DCHECK(media_endpoint_.get());
259 VLOG(1) << "Bluetooth audio sink: " << error_name << ": " << error_message; 314 VLOG(1) << "Bluetooth audio sink: " << error_name << ": " << error_message;
260 315
261 endpoint_path_ = dbus::ObjectPath(""); 316 ResetEndpoint();
262 media_endpoint_ = nullptr;
263 error_callback.Run(device::BluetoothAudioSink::ERROR_NOT_REGISTERED); 317 error_callback.Run(device::BluetoothAudioSink::ERROR_NOT_REGISTERED);
264 } 318 }
265 319
266 void BluetoothAudioSinkChromeOS::ReadFromFD() { 320 void BluetoothAudioSinkChromeOS::ReadFromFD() {
267 DCHECK_GE(fd_.value(), 0); 321 DCHECK_GE(fd_.value(), 0);
268 322
269 // TODO(mcchou): BUG=441581 323 // TODO(mcchou): BUG=441581
270 // Read from file descriptor using watcher and create a buffer to contain the 324 // Read from file descriptor using watcher and create a buffer to contain the
271 // data. Notify |Observers_| while there is audio data available. 325 // data. Notify |Observers_| while there is audio data available.
272 } 326 }
273 327
328 void BluetoothAudioSinkChromeOS::ResetMedia() {
329 chromeos::DBusThreadManager::Get()->GetBluetoothMediaClient()
330 ->RemoveObserver(this);
331 media_path_ = dbus::ObjectPath("");
332 }
333
334 void BluetoothAudioSinkChromeOS::ResetTransport() {
335 chromeos::DBusThreadManager::Get()->GetBluetoothMediaTransportClient()
336 ->RemoveObserver(this);
337 transport_path_ = dbus::ObjectPath("");
338 volume_ = 0;
339 read_mtu_ = 0;
340 write_mtu_ = 0;
341 fd_.PutValue(-1);
342 }
343
344 void BluetoothAudioSinkChromeOS::ResetEndpoint() {
345 endpoint_path_ = dbus::ObjectPath("");
346 media_endpoint_ = nullptr;
347 }
348
274 } // namespace chromeos 349 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698