1 /*
2 * Copyright 2022 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 "BTAudioClientAIDL"
18
19 #include "aidl/a2dp/client_interface_aidl.h"
20
21 #include <android/binder_manager.h>
22 #include <bluetooth/log.h>
23 #include <com_android_bluetooth_flags.h>
24
25 #include <memory>
26 #include <set>
27 #include <thread>
28 #include <utility>
29 #include <vector>
30
31 #include "bta/ag/bta_ag_int.h"
32
33 const uint8_t kFetchAudioProviderRetryNumber = 3;
34
35 namespace bluetooth {
36 namespace audio {
37 namespace aidl {
38 namespace a2dp {
39
BluetoothAudioClientInterface(IBluetoothTransportInstance * instance)40 BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransportInstance* instance)
41 : provider_(nullptr),
42 provider_factory_(nullptr),
43 session_started_(false),
44 data_mq_(nullptr),
45 transport_(instance),
46 latency_modes_({LatencyMode::FREE}) {
47 death_recipient_ =
48 ::ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(binderDiedCallbackAidl));
49 FetchAudioProvider();
50 }
51
~BluetoothAudioClientInterface()52 BluetoothAudioClientInterface::~BluetoothAudioClientInterface() {
53 if (provider_factory_ != nullptr) {
54 AIBinder_unlinkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), nullptr);
55 }
56 }
57
IsValid() const58 bool BluetoothAudioClientInterface::IsValid() const { return provider_ != nullptr; }
59
is_aidl_available()60 bool BluetoothAudioClientInterface::is_aidl_available() {
61 return AServiceManager_isDeclared(kDefaultAudioProviderFactoryInterface.c_str());
62 }
63
GetAudioCapabilities() const64 std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabilities() const {
65 return capabilities_;
66 }
67
GetAudioCapabilities(SessionType session_type)68 std::vector<AudioCapabilities> BluetoothAudioClientInterface::GetAudioCapabilities(
69 SessionType session_type) {
70 std::vector<AudioCapabilities> capabilities(0);
71 if (!is_aidl_available()) {
72 return capabilities;
73 }
74 auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
75 AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
76
77 if (provider_factory == nullptr) {
78 log::error("can't get capability from unknown factory");
79 return capabilities;
80 }
81
82 auto aidl_retval = provider_factory->getProviderCapabilities(session_type, &capabilities);
83 if (!aidl_retval.isOk()) {
84 log::fatal("BluetoothAudioHal::getProviderCapabilities failure: {}",
85 aidl_retval.getDescription());
86 }
87 return capabilities;
88 }
89
90 std::optional<IBluetoothAudioProviderFactory::ProviderInfo>
GetProviderInfo(SessionType session_type,std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory)91 BluetoothAudioClientInterface::GetProviderInfo(
92 SessionType session_type,
93 std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory) {
94 if (!is_aidl_available()) {
95 return std::nullopt;
96 }
97
98 if (provider_factory == nullptr) {
99 provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
100 AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
101 }
102
103 if (provider_factory == nullptr) {
104 log::error("can't get provider info from unknown factory");
105 return std::nullopt;
106 }
107
108 std::optional<IBluetoothAudioProviderFactory::ProviderInfo> provider_info = {};
109 auto aidl_retval = provider_factory->getProviderInfo(session_type, &provider_info);
110
111 if (!aidl_retval.isOk()) {
112 log::error("BluetoothAudioHal::getProviderInfo failure: {}", aidl_retval.getDescription());
113 return std::nullopt;
114 }
115
116 return provider_info;
117 }
118
GetA2dpConfiguration(std::vector<A2dpRemoteCapabilities> const & remote_capabilities,A2dpConfigurationHint const & hint) const119 std::optional<A2dpConfiguration> BluetoothAudioClientInterface::GetA2dpConfiguration(
120 std::vector<A2dpRemoteCapabilities> const& remote_capabilities,
121 A2dpConfigurationHint const& hint) const {
122 if (!is_aidl_available()) {
123 return std::nullopt;
124 }
125
126 if (provider_ == nullptr) {
127 log::error("can't get a2dp configuration from unknown provider");
128 return std::nullopt;
129 }
130
131 std::optional<A2dpConfiguration> configuration = std::nullopt;
132 auto aidl_retval = provider_->getA2dpConfiguration(remote_capabilities, hint, &configuration);
133
134 if (!aidl_retval.isOk()) {
135 log::error("getA2dpConfiguration failure: {}", aidl_retval.getDescription());
136 return std::nullopt;
137 }
138
139 return configuration;
140 }
141
ParseA2dpConfiguration(const CodecId & codec_id,const std::vector<uint8_t> & configuration,CodecParameters * codec_parameters) const142 std::optional<A2dpStatus> BluetoothAudioClientInterface::ParseA2dpConfiguration(
143 const CodecId& codec_id, const std::vector<uint8_t>& configuration,
144 CodecParameters* codec_parameters) const {
145 A2dpStatus a2dp_status;
146
147 if (provider_ == nullptr) {
148 log::error("can not parse A2DP configuration because of unknown provider");
149 return std::nullopt;
150 }
151
152 auto aidl_retval = provider_->parseA2dpConfiguration(codec_id, configuration, codec_parameters,
153 &a2dp_status);
154
155 if (!aidl_retval.isOk()) {
156 log::error("parseA2dpConfiguration failure: {}", aidl_retval.getDescription());
157 return std::nullopt;
158 }
159
160 return std::make_optional(a2dp_status);
161 }
162
FetchAudioProvider()163 void BluetoothAudioClientInterface::FetchAudioProvider() {
164 if (!is_aidl_available()) {
165 log::error("aidl is not supported on this platform.");
166 return;
167 }
168 if (provider_ != nullptr) {
169 log::warn("refetch");
170 }
171 // Retry if audioserver restarts in the middle of fetching.
172 // When audioserver restarts, IBluetoothAudioProviderFactory service is also
173 // re-registered, so we need to re-fetch the service.
174 for (int retry_no = 0; retry_no < kFetchAudioProviderRetryNumber; ++retry_no) {
175 auto provider_factory = IBluetoothAudioProviderFactory::fromBinder(::ndk::SpAIBinder(
176 AServiceManager_waitForService(kDefaultAudioProviderFactoryInterface.c_str())));
177
178 if (provider_factory == nullptr) {
179 log::error("can't get capability from unknown factory");
180 return;
181 }
182
183 capabilities_.clear();
184 auto aidl_retval =
185 provider_factory->getProviderCapabilities(transport_->GetSessionType(), &capabilities_);
186 if (!aidl_retval.isOk()) {
187 log::error("BluetoothAudioHal::getProviderCapabilities failure: {}, retry number {}",
188 aidl_retval.getDescription(), retry_no + 1);
189 continue;
190 }
191 if (capabilities_.empty()) {
192 log::warn("SessionType={} Not supported by BluetoothAudioHal",
193 toString(transport_->GetSessionType()));
194 return;
195 }
196 log::info("BluetoothAudioHal SessionType={} has {} AudioCapabilities",
197 toString(transport_->GetSessionType()), capabilities_.size());
198
199 aidl_retval = provider_factory->openProvider(transport_->GetSessionType(), &provider_);
200 if (!aidl_retval.isOk() || provider_ == nullptr) {
201 log::error("BluetoothAudioHal::openProvider failure: {}, retry number {}",
202 aidl_retval.getDescription(), retry_no + 1);
203 } else {
204 provider_factory_ = std::move(provider_factory);
205 break;
206 }
207 }
208 log::assert_that(provider_factory_ != nullptr, "assert failed: provider_factory_ != nullptr");
209 log::assert_that(provider_ != nullptr, "assert failed: provider_ != nullptr");
210
211 binder_status_t binder_status =
212 AIBinder_linkToDeath(provider_factory_->asBinder().get(), death_recipient_.get(), this);
213 if (binder_status != STATUS_OK) {
214 log::error("Failed to linkToDeath {}", static_cast<int>(binder_status));
215 }
216
217 log::info("IBluetoothAudioProvidersFactory::openProvider() returned {}{}",
218 std::format_ptr(provider_.get()), (provider_->isRemote() ? " (remote)" : " (local)"));
219 }
220
binderDiedCallbackAidl(void * ptr)221 void BluetoothAudioClientInterface::binderDiedCallbackAidl(void* ptr) {
222 log::warn("restarting connection with new Audio Hal");
223 auto client = static_cast<BluetoothAudioClientInterface*>(ptr);
224 if (client == nullptr) {
225 log::error("null audio HAL died!");
226 return;
227 }
228 client->RenewAudioProviderAndSession();
229 }
230
UpdateAudioConfig(const AudioConfiguration & audio_config)231 bool BluetoothAudioClientInterface::UpdateAudioConfig(const AudioConfiguration& audio_config) {
232 bool is_software_session =
233 (transport_->GetSessionType() == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
234 transport_->GetSessionType() == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
235 transport_->GetSessionType() == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
236 transport_->GetSessionType() == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
237 transport_->GetSessionType() ==
238 SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
239 (bta_ag_is_sco_managed_by_audio() &&
240 (transport_->GetSessionType() == SessionType::HFP_SOFTWARE_ENCODING_DATAPATH ||
241 transport_->GetSessionType() == SessionType::HFP_SOFTWARE_DECODING_DATAPATH)));
242 bool is_a2dp_offload_session =
243 (transport_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
244 bool is_leaudio_unicast_offload_session =
245 (transport_->GetSessionType() ==
246 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
247 transport_->GetSessionType() ==
248 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
249 bool is_leaudio_broadcast_offload_session =
250 (transport_->GetSessionType() ==
251 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
252 auto audio_config_tag = audio_config.getTag();
253 bool is_software_audio_config =
254 (is_software_session && audio_config_tag == AudioConfiguration::pcmConfig);
255 bool is_a2dp_offload_audio_config =
256 (is_a2dp_offload_session && (audio_config_tag == AudioConfiguration::a2dpConfig ||
257 audio_config_tag == AudioConfiguration::a2dp));
258 bool is_leaudio_unicast_offload_audio_config =
259 (is_leaudio_unicast_offload_session &&
260 audio_config_tag == AudioConfiguration::leAudioConfig);
261 bool is_leaudio_broadcast_offload_audio_config =
262 (is_leaudio_broadcast_offload_session &&
263 audio_config_tag == AudioConfiguration::leAudioBroadcastConfig);
264 bool is_hfp_offload_audio_config =
265 (bta_ag_is_sco_managed_by_audio() &&
266 transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH &&
267 audio_config_tag == AudioConfiguration::hfpConfig);
268 if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
269 !is_leaudio_unicast_offload_audio_config && !is_leaudio_broadcast_offload_audio_config &&
270 !is_hfp_offload_audio_config) {
271 return false;
272 }
273 transport_->UpdateAudioConfiguration(audio_config);
274
275 if (provider_ == nullptr) {
276 log::info("BluetoothAudioHal nullptr, update it as session started");
277 return true;
278 }
279
280 if (!session_started_) {
281 log::info("BluetoothAudioHal session has not started");
282 return true;
283 }
284
285 auto aidl_retval = provider_->updateAudioConfiguration(audio_config);
286 if (!aidl_retval.isOk()) {
287 if (audio_config.getTag() != transport_->GetAudioConfiguration().getTag()) {
288 log::warn(
289 "BluetoothAudioHal audio config type: {} doesn't "
290 "match provider's audio config type: {}",
291 ::aidl::android::hardware::bluetooth::audio::toString(audio_config.getTag()),
292 ::aidl::android::hardware::bluetooth::audio::toString(
293 transport_->GetAudioConfiguration().getTag()));
294 } else {
295 log::warn("BluetoothAudioHal is not ready: {} ", aidl_retval.getDescription());
296 }
297 }
298 return true;
299 }
300
SetAllowedLatencyModes(std::vector<LatencyMode> latency_modes)301 bool BluetoothAudioClientInterface::SetAllowedLatencyModes(std::vector<LatencyMode> latency_modes) {
302 if (provider_ == nullptr) {
303 log::info("BluetoothAudioHal nullptr");
304 return false;
305 }
306
307 if (latency_modes.empty()) {
308 latency_modes_.clear();
309 latency_modes_.push_back(LatencyMode::FREE);
310 } else {
311 /* Ensure that FREE is always included and remove duplicates if any */
312 std::set<LatencyMode> temp_set(latency_modes.begin(), latency_modes.end());
313 temp_set.insert(LatencyMode::FREE);
314 latency_modes_.clear();
315 latency_modes_.assign(temp_set.begin(), temp_set.end());
316 }
317
318 for (auto latency_mode : latency_modes) {
319 log::info("Latency mode allowed: {}",
320 ::aidl::android::hardware::bluetooth::audio::toString(latency_mode));
321 }
322
323 /* Low latency mode is used if modes other than FREE are present */
324 bool allowed = (latency_modes_.size() > 1);
325 log::info("Latency mode allowed: {}", allowed);
326 auto aidl_retval = provider_->setLowLatencyModeAllowed(allowed);
327 if (!aidl_retval.isOk()) {
328 log::warn(
329 "BluetoothAudioHal is not ready: {}. latency_modes_ is saved and it "
330 "will be sent to BluetoothAudioHal at StartSession.",
331 aidl_retval.getDescription());
332 }
333 return true;
334 }
335
StartSession()336 int BluetoothAudioClientInterface::StartSession() {
337 std::lock_guard<std::mutex> guard(internal_mutex_);
338 if (provider_ == nullptr) {
339 log::error("BluetoothAudioHal nullptr");
340 session_started_ = false;
341 return -EINVAL;
342 }
343 if (session_started_) {
344 log::error("session started already");
345 return -EBUSY;
346 }
347
348 std::shared_ptr<IBluetoothAudioPort> stack_if =
349 ndk::SharedRefBase::make<BluetoothAudioPortImpl>(transport_, provider_);
350
351 std::unique_ptr<DataMQ> data_mq;
352 DataMQDesc mq_desc;
353
354 auto aidl_retval = provider_->startSession(stack_if, transport_->GetAudioConfiguration(),
355 latency_modes_, &mq_desc);
356 if (!aidl_retval.isOk()) {
357 if (aidl_retval.getExceptionCode() == EX_ILLEGAL_ARGUMENT) {
358 log::error("BluetoothAudioHal Error: {}, audioConfig={}", aidl_retval.getDescription(),
359 transport_->GetAudioConfiguration().toString());
360 } else {
361 log::fatal("BluetoothAudioHal failure: {}", aidl_retval.getDescription());
362 }
363 return -EPROTO;
364 }
365 data_mq.reset(new DataMQ(mq_desc));
366
367 if (data_mq && data_mq->isValid()) {
368 data_mq_ = std::move(data_mq);
369 } else if (transport_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
370 transport_->GetSessionType() ==
371 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
372 transport_->GetSessionType() ==
373 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
374 transport_->GetSessionType() ==
375 SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
376 (bta_ag_is_sco_managed_by_audio() &&
377 transport_->GetSessionType() == SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH)) {
378 transport_->ResetPresentationPosition();
379 session_started_ = true;
380 return 0;
381 }
382 if (data_mq_ && data_mq_->isValid()) {
383 transport_->ResetPresentationPosition();
384 session_started_ = true;
385 return 0;
386 } else {
387 if (!data_mq_) {
388 log::error("Failed to obtain audio data path");
389 }
390 if (data_mq_ && !data_mq_->isValid()) {
391 log::error("Audio data path is invalid");
392 }
393 session_started_ = false;
394 return -EIO;
395 }
396 }
397
StreamStarted(const Status & ack)398 void BluetoothAudioClientInterface::StreamStarted(const Status& ack) {
399 if (provider_ == nullptr) {
400 log::error("BluetoothAudioHal nullptr");
401 return;
402 }
403 if (ack == Status::PENDING) {
404 log::info("{} ignored", ack);
405 return;
406 }
407
408 auto status = StatusToHalStatus(ack);
409 auto aidl_retval = provider_->streamStarted(status);
410
411 if (!aidl_retval.isOk()) {
412 log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription());
413 }
414 }
415
StreamSuspended(const Status & ack)416 void BluetoothAudioClientInterface::StreamSuspended(const Status& ack) {
417 if (provider_ == nullptr) {
418 log::error("BluetoothAudioHal nullptr");
419 return;
420 }
421 if (ack == Status::PENDING) {
422 log::info("{} ignored", ack);
423 return;
424 }
425
426 auto status = StatusToHalStatus(ack);
427 auto aidl_retval = provider_->streamSuspended(status);
428
429 if (!aidl_retval.isOk()) {
430 log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription());
431 }
432 }
433
EndSession()434 int BluetoothAudioClientInterface::EndSession() {
435 std::lock_guard<std::mutex> guard(internal_mutex_);
436 if (!session_started_) {
437 log::info("session ended already");
438 return 0;
439 }
440
441 session_started_ = false;
442 if (provider_ == nullptr) {
443 log::error("BluetoothAudioHal nullptr");
444 return -EINVAL;
445 }
446 data_mq_ = nullptr;
447
448 auto aidl_retval = provider_->endSession();
449
450 if (!aidl_retval.isOk()) {
451 log::error("BluetoothAudioHal failure: {}", aidl_retval.getDescription());
452 return -EPROTO;
453 }
454 return 0;
455 }
456
ReadAudioData(uint8_t * p_buf,uint32_t len)457 size_t BluetoothAudioClientInterface::ReadAudioData(uint8_t* p_buf, uint32_t len) {
458 if (!IsValid()) {
459 log::error("BluetoothAudioHal is not valid");
460 return 0;
461 }
462 if (p_buf == nullptr || len == 0) {
463 return 0;
464 }
465
466 std::lock_guard<std::mutex> guard(internal_mutex_);
467
468 size_t total_read = 0;
469 int timeout_ms = kDefaultDataReadTimeoutMs;
470 do {
471 if (data_mq_ == nullptr || !data_mq_->isValid()) {
472 break;
473 }
474
475 size_t avail_to_read = data_mq_->availableToRead();
476 if (avail_to_read) {
477 if (avail_to_read > len - total_read) {
478 avail_to_read = len - total_read;
479 }
480 if (data_mq_->read(reinterpret_cast<MqDataType*>(p_buf) + total_read, avail_to_read) == 0) {
481 log::warn("len={} total_read={} failed", len, total_read);
482 break;
483 }
484 total_read += avail_to_read;
485 } else if (timeout_ms >= kDefaultDataReadPollIntervalMs) {
486 std::this_thread::sleep_for(std::chrono::milliseconds(kDefaultDataReadPollIntervalMs));
487 timeout_ms -= kDefaultDataReadPollIntervalMs;
488 continue;
489 } else {
490 log::warn("{}/{} no data {} ms", len - total_read, len,
491 kDefaultDataReadTimeoutMs - timeout_ms);
492 break;
493 }
494 } while (total_read < len);
495
496 if (timeout_ms < (kDefaultDataReadTimeoutMs - kDefaultDataReadPollIntervalMs) &&
497 timeout_ms >= kDefaultDataReadPollIntervalMs) {
498 log::verbose("underflow {} -> {} read {} ms", len, total_read,
499 kDefaultDataReadTimeoutMs - timeout_ms);
500 } else {
501 log::verbose("{} -> {} read", len, total_read);
502 }
503
504 transport_->LogBytesRead(total_read);
505 return total_read;
506 }
507
RenewAudioProviderAndSession()508 void BluetoothAudioClientInterface::RenewAudioProviderAndSession() {
509 // NOTE: must be invoked on the same thread where this
510 // BluetoothAudioClientInterface is running
511 FetchAudioProvider();
512
513 if (session_started_) {
514 log::info("Restart the session while audio HAL recovering");
515 session_started_ = false;
516
517 StartSession();
518 }
519 }
520
521 } // namespace a2dp
522 } // namespace aidl
523 } // namespace audio
524 } // namespace bluetooth
525