1 /*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define LOG_TAG "BTAudioClientIf"
18
19 #include "client_interface.h"
20
21 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
22 #include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h>
23 #include <android/hidl/manager/1.2/IServiceManager.h>
24 #include <base/logging.h>
25 #include <hidl/MQDescriptor.h>
26 #include <hidl/ServiceManagement.h>
27 #include <future>
28
29 #include "osi/include/log.h"
30
31 namespace bluetooth {
32 namespace audio {
33
34 using ::android::hardware::hidl_vec;
35 using ::android::hardware::Return;
36 using ::android::hardware::Void;
37 using ::android::hardware::audio::common::V5_0::SourceMetadata;
38 using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
39 using ::android::hardware::bluetooth::audio::V2_0::
40 IBluetoothAudioProvidersFactory;
41 using DataMQ = ::android::hardware::MessageQueue<
42 uint8_t, ::android::hardware::kSynchronizedReadWrite>;
43
44 static constexpr int kDefaultDataReadTimeoutMs = 10; // 10 ms
45 static constexpr int kDefaultDataReadPollIntervalMs = 1; // non-blocking poll
46 static constexpr char kFullyQualifiedInterfaceName[] =
47 "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory";
48
operator <<(std::ostream & os,const BluetoothAudioCtrlAck & ack)49 std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) {
50 switch (ack) {
51 case BluetoothAudioCtrlAck::SUCCESS_FINISHED:
52 return os << "SUCCESS_FINISHED";
53 case BluetoothAudioCtrlAck::PENDING:
54 return os << "PENDING";
55 case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED:
56 return os << "FAILURE_UNSUPPORTED";
57 case BluetoothAudioCtrlAck::FAILURE_BUSY:
58 return os << "FAILURE_BUSY";
59 case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING:
60 return os << "FAILURE_DISCONNECTING";
61 case BluetoothAudioCtrlAck::FAILURE:
62 return os << "FAILURE";
63 default:
64 return os << "UNDEFINED " << static_cast<int8_t>(ack);
65 }
66 }
67
68 // Internal class within BluetoothAudioClientInterfaceace to implement
69 // IBluetoothAudioPort (control interface used by Bluetooth Audio HAL)
70 class BluetoothAudioPortImpl : public IBluetoothAudioPort {
71 public:
BluetoothAudioPortImpl(IBluetoothTransportInstance * sink,const android::sp<IBluetoothAudioProvider> & provider)72 BluetoothAudioPortImpl(IBluetoothTransportInstance* sink,
73 const android::sp<IBluetoothAudioProvider>& provider)
74 : sink_(sink), provider_(provider){};
75
startStream()76 Return<void> startStream() {
77 BluetoothAudioCtrlAck ack = sink_->StartRequest();
78 if (ack != BluetoothAudioCtrlAck::PENDING) {
79 auto hidl_retval =
80 provider_->streamStarted(BluetoothAudioCtrlAckToHalStatus(ack));
81 if (!hidl_retval.isOk()) {
82 LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
83 }
84 }
85 return Void();
86 }
87
suspendStream()88 Return<void> suspendStream() {
89 BluetoothAudioCtrlAck ack = sink_->SuspendRequest();
90 if (ack != BluetoothAudioCtrlAck::PENDING) {
91 auto hidl_retval =
92 provider_->streamSuspended(BluetoothAudioCtrlAckToHalStatus(ack));
93 if (!hidl_retval.isOk()) {
94 LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
95 }
96 }
97 return Void();
98 }
99
stopStream()100 Return<void> stopStream() {
101 sink_->StopRequest();
102 return Void();
103 }
104
getPresentationPosition(getPresentationPosition_cb _hidl_cb)105 Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
106 uint64_t remote_delay_report_ns;
107 uint64_t total_bytes_read;
108 timespec data_position;
109 bool retval = sink_->GetPresentationPosition(
110 &remote_delay_report_ns, &total_bytes_read, &data_position);
111
112 TimeSpec transmittedOctetsTimeStamp;
113 if (retval) {
114 transmittedOctetsTimeStamp = timespec_convert_to_hal(data_position);
115 } else {
116 remote_delay_report_ns = 0;
117 total_bytes_read = 0;
118 transmittedOctetsTimeStamp = {};
119 }
120 VLOG(2) << __func__ << ": result=" << retval
121 << ", delay=" << remote_delay_report_ns
122 << ", data=" << total_bytes_read
123 << " byte(s), timestamp=" << toString(transmittedOctetsTimeStamp);
124 _hidl_cb((retval ? BluetoothAudioStatus::SUCCESS
125 : BluetoothAudioStatus::FAILURE),
126 remote_delay_report_ns, total_bytes_read,
127 transmittedOctetsTimeStamp);
128 return Void();
129 }
130
updateMetadata(const SourceMetadata & sourceMetadata)131 Return<void> updateMetadata(const SourceMetadata& sourceMetadata) {
132 LOG(INFO) << __func__ << ": " << sourceMetadata.tracks.size()
133 << " track(s)";
134 // refer to StreamOut.impl.h within Audio HAL (AUDIO_HAL_VERSION_5_0)
135 std::vector<playback_track_metadata> metadata_vec;
136 metadata_vec.reserve(sourceMetadata.tracks.size());
137 for (const auto& metadata : sourceMetadata.tracks) {
138 metadata_vec.push_back({
139 .usage = static_cast<audio_usage_t>(metadata.usage),
140 .content_type =
141 static_cast<audio_content_type_t>(metadata.contentType),
142 .gain = metadata.gain,
143 });
144 }
145 const source_metadata_t source_metadata = {
146 .track_count = metadata_vec.size(), .tracks = metadata_vec.data()};
147 sink_->MetadataChanged(source_metadata);
148 return Void();
149 }
150
151 private:
152 IBluetoothTransportInstance* sink_;
153 const android::sp<IBluetoothAudioProvider> provider_;
timespec_convert_to_hal(const timespec & ts)154 TimeSpec timespec_convert_to_hal(const timespec& ts) {
155 return {.tvSec = static_cast<uint64_t>(ts.tv_sec),
156 .tvNSec = static_cast<uint64_t>(ts.tv_nsec)};
157 }
158 };
159
160 class BluetoothAudioDeathRecipient
161 : public ::android::hardware::hidl_death_recipient {
162 public:
BluetoothAudioDeathRecipient(BluetoothAudioClientInterface * clientif,bluetooth::common::MessageLoopThread * message_loop)163 BluetoothAudioDeathRecipient(
164 BluetoothAudioClientInterface* clientif,
165 bluetooth::common::MessageLoopThread* message_loop)
166 : bluetooth_audio_clientif_(clientif), message_loop_(message_loop) {}
serviceDied(uint64_t,const::android::wp<::android::hidl::base::V1_0::IBase> &)167 void serviceDied(
168 uint64_t /*cookie*/,
169 const ::android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
170 LOG(WARNING) << __func__ << ": restarting connection with new Audio Hal";
171 if (bluetooth_audio_clientif_ != nullptr && message_loop_ != nullptr) {
172 // restart the session on the correct thread
173 message_loop_->DoInThread(
174 FROM_HERE,
175 base::BindOnce(
176 &BluetoothAudioClientInterface::RenewAudioProviderAndSession,
177 base::Unretained(bluetooth_audio_clientif_)));
178 } else {
179 LOG(ERROR) << __func__ << ": BluetoothAudioClientInterface corrupted";
180 }
181 }
182
183 private:
184 BluetoothAudioClientInterface* bluetooth_audio_clientif_;
185 bluetooth::common::MessageLoopThread* message_loop_;
186 };
187
BluetoothAudioClientInterface(IBluetoothTransportInstance * sink,bluetooth::common::MessageLoopThread * message_loop)188 BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransportInstance* sink,
189 bluetooth::common::MessageLoopThread* message_loop)
190 : sink_(sink), provider_(nullptr), session_started_(false), mDataMQ(nullptr),
191 death_recipient_(new BluetoothAudioDeathRecipient(this, message_loop)) {
192 auto service_manager = android::hardware::defaultServiceManager1_2();
193 CHECK(service_manager != nullptr);
194 size_t instance_count = 0;
195 auto listManifestByInterface_cb = [&instance_count](const hidl_vec<android::hardware::hidl_string>& instanceNames) {
196 instance_count = instanceNames.size();
197 LOG(INFO) << "listManifestByInterface_cb returns " << instance_count << " instance(s)";
198 };
199 auto hidl_retval = service_manager->listManifestByInterface(kFullyQualifiedInterfaceName, listManifestByInterface_cb);
200 if (!hidl_retval.isOk()) {
201 LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " << hidl_retval.description();
202 }
203 if (instance_count > 0) {
204 fetch_audio_provider();
205 } else {
206 LOG(WARNING) << "IBluetoothAudioProvidersFactory not declared";
207 }
208 }
209
~BluetoothAudioClientInterface()210 BluetoothAudioClientInterface::~BluetoothAudioClientInterface() {
211 if (provider_ != nullptr) {
212 auto hidl_retval = provider_->unlinkToDeath(death_recipient_);
213 if (!hidl_retval.isOk()) {
214 LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " << hidl_retval.description();
215 }
216 }
217 }
218
219 std::vector<AudioCapabilities>
GetAudioCapabilities() const220 BluetoothAudioClientInterface::GetAudioCapabilities() const {
221 return capabilities_;
222 }
223
fetch_audio_provider()224 void BluetoothAudioClientInterface::fetch_audio_provider() {
225 if (provider_ != nullptr) {
226 LOG(WARNING) << __func__ << ": reflash";
227 }
228
229 android::sp<IBluetoothAudioProvidersFactory> providersFactory =
230 IBluetoothAudioProvidersFactory::getService();
231 CHECK(providersFactory != nullptr) << "IBluetoothAudioProvidersFactory::getService() failed";
232 LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned "
233 << providersFactory.get()
234 << (providersFactory->isRemote() ? " (remote)" : " (local)");
235
236 std::promise<void> getProviderCapabilities_promise;
237 auto getProviderCapabilities_future =
238 getProviderCapabilities_promise.get_future();
239 auto getProviderCapabilities_cb =
240 [& capabilities = this->capabilities_, &getProviderCapabilities_promise](
241 const hidl_vec<AudioCapabilities>& audioCapabilities) {
242 for (auto capability : audioCapabilities) {
243 capabilities.push_back(capability);
244 }
245 getProviderCapabilities_promise.set_value();
246 };
247 auto hidl_retval = providersFactory->getProviderCapabilities(
248 sink_->GetSessionType(), getProviderCapabilities_cb);
249 getProviderCapabilities_future.get();
250 if (!hidl_retval.isOk()) {
251 LOG(FATAL) << __func__ << ": BluetoothAudioHal::getProviderCapabilities failure: " << hidl_retval.description();
252 return;
253 }
254 if (capabilities_.empty()) {
255 LOG(WARNING) << __func__
256 << ": SessionType=" << toString(sink_->GetSessionType())
257 << " Not supported by BluetoothAudioHal";
258 return;
259 }
260 LOG(INFO) << __func__ << ": BluetoothAudioHal SessionType="
261 << toString(sink_->GetSessionType()) << " has "
262 << capabilities_.size() << " AudioCapabilities";
263
264 std::promise<void> openProvider_promise;
265 auto openProvider_future = openProvider_promise.get_future();
266 auto openProvider_cb =
267 [& provider_ = this->provider_, &openProvider_promise](
268 BluetoothAudioStatus status,
269 const android::sp<IBluetoothAudioProvider>& provider) {
270 LOG(INFO) << "openProvider_cb(" << toString(status) << ")";
271 if (status == BluetoothAudioStatus::SUCCESS) {
272 provider_ = provider;
273 }
274 ALOGE_IF(!provider_, "Failed to open BluetoothAudio provider");
275 openProvider_promise.set_value();
276 };
277 hidl_retval =
278 providersFactory->openProvider(sink_->GetSessionType(), openProvider_cb);
279 openProvider_future.get();
280 if (!hidl_retval.isOk()) {
281 LOG(FATAL) << __func__ << ": BluetoothAudioHal::openProvider failure: " << hidl_retval.description();
282 }
283 CHECK(provider_ != nullptr);
284
285 if (!provider_->linkToDeath(death_recipient_, 0).isOk()) {
286 LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " << hidl_retval.description();
287 }
288
289 LOG(INFO) << "IBluetoothAudioProvidersFactory::openProvider() returned "
290 << provider_.get()
291 << (provider_->isRemote() ? " (remote)" : " (local)");
292 }
293
UpdateAudioConfig(const AudioConfiguration & audio_config)294 bool BluetoothAudioClientInterface::UpdateAudioConfig(
295 const AudioConfiguration& audio_config) {
296 bool is_software_session =
297 (sink_->GetSessionType() ==
298 SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
299 sink_->GetSessionType() ==
300 SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
301 bool is_offload_session =
302 (sink_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
303 auto audio_config_discriminator = audio_config.getDiscriminator();
304 bool is_software_audio_config =
305 (is_software_session &&
306 audio_config_discriminator ==
307 AudioConfiguration::hidl_discriminator::pcmConfig);
308 bool is_offload_audio_config =
309 (is_offload_session &&
310 audio_config_discriminator ==
311 AudioConfiguration::hidl_discriminator::codecConfig);
312 if (!is_software_audio_config && !is_offload_audio_config) {
313 return false;
314 }
315 sink_->UpdateAudioConfiguration(audio_config);
316 return true;
317 }
318
StartSession()319 int BluetoothAudioClientInterface::StartSession() {
320 std::lock_guard<std::mutex> guard(internal_mutex_);
321 if (provider_ == nullptr) {
322 LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
323 session_started_ = false;
324 return -EINVAL;
325 }
326 if (session_started_) {
327 LOG(ERROR) << __func__ << ": session started already";
328 return -EBUSY;
329 }
330
331 android::sp<IBluetoothAudioPort> stack_if =
332 new BluetoothAudioPortImpl(sink_, provider_);
333 std::unique_ptr<DataMQ> tempDataMQ;
334 BluetoothAudioStatus session_status;
335
336 std::promise<void> hidl_startSession_promise;
337 auto hidl_startSession_future = hidl_startSession_promise.get_future();
338 auto hidl_cb = [&session_status, &tempDataMQ, &hidl_startSession_promise](
339 BluetoothAudioStatus status,
340 const DataMQ::Descriptor& dataMQ) {
341 LOG(INFO) << "startSession_cb(" << toString(status) << ")";
342 session_status = status;
343 if (status == BluetoothAudioStatus::SUCCESS && dataMQ.isHandleValid()) {
344 tempDataMQ.reset(new DataMQ(dataMQ));
345 }
346 hidl_startSession_promise.set_value();
347 };
348 auto hidl_retval = provider_->startSession(
349 stack_if, sink_->GetAudioConfiguration(), hidl_cb);
350 hidl_startSession_future.get();
351 if (!hidl_retval.isOk()) {
352 LOG(FATAL) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
353 return -EPROTO;
354 }
355
356 if (tempDataMQ && tempDataMQ->isValid()) {
357 mDataMQ = std::move(tempDataMQ);
358 } else if (sink_->GetSessionType() ==
359 SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH &&
360 session_status == BluetoothAudioStatus::SUCCESS) {
361 sink_->ResetPresentationPosition();
362 session_started_ = true;
363 return 0;
364 }
365 if (mDataMQ && mDataMQ->isValid()) {
366 sink_->ResetPresentationPosition();
367 session_started_ = true;
368 return 0;
369 } else {
370 ALOGE_IF(!mDataMQ, "Failed to obtain audio data path");
371 ALOGE_IF(mDataMQ && !mDataMQ->isValid(), "Audio data path is invalid");
372 session_started_ = false;
373 return -EIO;
374 }
375 }
376
StreamStarted(const BluetoothAudioCtrlAck & ack)377 void BluetoothAudioClientInterface::StreamStarted(
378 const BluetoothAudioCtrlAck& ack) {
379 if (provider_ == nullptr) {
380 LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
381 return;
382 }
383 if (ack == BluetoothAudioCtrlAck::PENDING) {
384 LOG(INFO) << __func__ << ": " << ack << " ignored";
385 return;
386 }
387 BluetoothAudioStatus status = BluetoothAudioCtrlAckToHalStatus(ack);
388 auto hidl_retval = provider_->streamStarted(status);
389 if (!hidl_retval.isOk()) {
390 LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
391 }
392 }
393
StreamSuspended(const BluetoothAudioCtrlAck & ack)394 void BluetoothAudioClientInterface::StreamSuspended(
395 const BluetoothAudioCtrlAck& ack) {
396 if (provider_ == nullptr) {
397 LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
398 return;
399 }
400 if (ack == BluetoothAudioCtrlAck::PENDING) {
401 LOG(INFO) << __func__ << ": " << ack << " ignored";
402 return;
403 }
404 BluetoothAudioStatus status = BluetoothAudioCtrlAckToHalStatus(ack);
405 auto hidl_retval = provider_->streamSuspended(status);
406 if (!hidl_retval.isOk()) {
407 LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
408 }
409 }
410
EndSession()411 int BluetoothAudioClientInterface::EndSession() {
412 std::lock_guard<std::mutex> guard(internal_mutex_);
413 if (!session_started_) {
414 LOG(INFO) << __func__ << ": sessoin ended already";
415 return 0;
416 }
417
418 session_started_ = false;
419 if (provider_ == nullptr) {
420 LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
421 return -EINVAL;
422 }
423 mDataMQ = nullptr;
424 auto hidl_retval = provider_->endSession();
425 if (!hidl_retval.isOk()) {
426 LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
427 return -EPROTO;
428 }
429 return 0;
430 }
431
ReadAudioData(uint8_t * p_buf,uint32_t len)432 size_t BluetoothAudioClientInterface::ReadAudioData(uint8_t* p_buf,
433 uint32_t len) {
434 if (provider_ == nullptr) {
435 LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
436 return 0;
437 }
438 if (p_buf == nullptr || len == 0) return 0;
439
440 std::lock_guard<std::mutex> guard(internal_mutex_);
441
442 size_t total_read = 0;
443 int timeout_ms = kDefaultDataReadTimeoutMs;
444 do {
445 if (mDataMQ == nullptr || !mDataMQ->isValid()) break;
446
447 size_t avail_to_read = mDataMQ->availableToRead();
448 if (avail_to_read) {
449 if (avail_to_read > len - total_read) {
450 avail_to_read = len - total_read;
451 }
452 if (mDataMQ->read(p_buf + total_read, avail_to_read) == 0) {
453 LOG(WARNING) << __func__ << ": len=" << len
454 << " total_read=" << total_read << " failed";
455 break;
456 }
457 total_read += avail_to_read;
458 } else if (timeout_ms >= kDefaultDataReadPollIntervalMs) {
459 std::this_thread::sleep_for(
460 std::chrono::milliseconds(kDefaultDataReadPollIntervalMs));
461 timeout_ms -= kDefaultDataReadPollIntervalMs;
462 continue;
463 } else {
464 LOG(WARNING) << __func__ << ": " << (len - total_read) << "/" << len
465 << " no data " << (kDefaultDataReadTimeoutMs - timeout_ms)
466 << " ms";
467 break;
468 }
469 } while (total_read < len);
470
471 if (timeout_ms <
472 (kDefaultDataReadTimeoutMs - kDefaultDataReadPollIntervalMs) &&
473 timeout_ms >= kDefaultDataReadPollIntervalMs) {
474 VLOG(1) << __func__ << ": underflow " << len << " -> " << total_read
475 << " read " << (kDefaultDataReadTimeoutMs - timeout_ms) << " ms";
476 } else {
477 VLOG(2) << __func__ << ": " << len << " -> " << total_read << " read";
478 }
479
480 sink_->LogBytesRead(total_read);
481 return total_read;
482 }
483
WriteAudioData(uint8_t * p_buf,uint32_t len)484 size_t BluetoothAudioClientInterface::WriteAudioData(uint8_t* p_buf,
485 uint32_t len) {
486 // Not implemented!
487 return 0;
488 }
489
RenewAudioProviderAndSession()490 void BluetoothAudioClientInterface::RenewAudioProviderAndSession() {
491 // NOTE: must be invoked on the same thread where this
492 // BluetoothAudioClientInterface is running
493 fetch_audio_provider();
494 session_started_ = false;
495 StartSession();
496 }
497
498 } // namespace audio
499 } // namespace bluetooth
500