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

Side by Side Diff: device/bluetooth/bluez/bluetooth_audio_sink_bluez.cc

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

Powered by Google App Engine
This is Rietveld 408576698