1 /*
2 * Copyright 2023 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 #include <cstdint>
18
19 #define LOG_TAG "BTAudioClientHfpStub"
20
21 #include <bluetooth/log.h>
22
23 #include "aidl/client_interface_aidl.h"
24 #include "aidl/hfp_client_interface_aidl.h"
25 #include "hal_version_manager.h"
26 #include "hfp_client_interface.h"
27 #include "os/log.h"
28 #include "osi/include/properties.h"
29
30 using ::bluetooth::audio::aidl::hfp::HfpDecodingTransport;
31 using ::bluetooth::audio::aidl::hfp::HfpEncodingTransport;
32 using AudioConfiguration =
33 ::aidl::android::hardware::bluetooth::audio::AudioConfiguration;
34 using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
35 using ::aidl::android::hardware::bluetooth::audio::CodecId;
36 using ::aidl::android::hardware::bluetooth::audio::HfpConfiguration;
37 using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
38
39 namespace bluetooth {
40 namespace audio {
41 namespace hfp {
42
43 // Helper functions
get_decode_client_interface()44 aidl::BluetoothAudioSinkClientInterface* get_decode_client_interface() {
45 return HfpDecodingTransport::active_hal_interface;
46 }
47
get_encode_client_interface()48 aidl::BluetoothAudioSourceClientInterface* get_encode_client_interface() {
49 return HfpEncodingTransport::active_hal_interface;
50 }
51
get_decode_transport_instance()52 HfpDecodingTransport* get_decode_transport_instance() {
53 return HfpDecodingTransport::instance_;
54 }
55
get_encode_transport_instance()56 HfpDecodingTransport* get_encode_transport_instance() {
57 return HfpDecodingTransport::instance_;
58 }
59
get_default_pcm_configuration()60 PcmConfiguration get_default_pcm_configuration() {
61 PcmConfiguration pcm_config{
62 .sampleRateHz = 8000,
63 .channelMode = ChannelMode::MONO,
64 .bitsPerSample = 16,
65 .dataIntervalUs = 7500,
66 };
67 return pcm_config;
68 }
69
get_default_hfp_configuration()70 HfpConfiguration get_default_hfp_configuration() {
71 HfpConfiguration hfp_config{
72 .codecId = CodecId::Core::CVSD,
73 .connectionHandle = 6,
74 .nrec = false,
75 .controllerCodec = true,
76 };
77 return hfp_config;
78 }
79
get_codec_id_by_peer_codec(tBTA_AG_PEER_CODEC sco_codec)80 CodecId get_codec_id_by_peer_codec(tBTA_AG_PEER_CODEC sco_codec) {
81 if (sco_codec & BTM_SCO_CODEC_LC3) return CodecId::Core::LC3;
82 if (sco_codec & BTM_SCO_CODEC_MSBC) return CodecId::Core::MSBC;
83 if (sco_codec & BTM_SCO_CODEC_CVSD) return CodecId::Core::CVSD;
84 // Unknown vendor codec otherwise
85 CodecId codec_id = CodecId::Vendor();
86 return codec_id;
87 }
88
offload_config_to_hal_audio_config(const::hfp::offload_config & offload_config)89 AudioConfiguration offload_config_to_hal_audio_config(
90 const ::hfp::offload_config& offload_config) {
91 HfpConfiguration hfp_config{
92 .codecId = get_codec_id_by_peer_codec(offload_config.sco_codec),
93 .connectionHandle = offload_config.connection_handle,
94 .nrec = offload_config.is_nrec,
95 .controllerCodec = offload_config.is_controller_codec,
96 };
97 return AudioConfiguration(hfp_config);
98 }
99
is_hal_enabled()100 bool is_hal_enabled() {
101 return !osi_property_get_bool(BLUETOOTH_AUDIO_HAL_PROP_DISABLED, false);
102 }
103
is_aidl_support_hfp()104 bool is_aidl_support_hfp() {
105 return HalVersionManager::GetHalTransport() ==
106 BluetoothAudioHalTransport::AIDL &&
107 HalVersionManager::GetHalVersion() >=
108 BluetoothAudioHalVersion::VERSION_AIDL_V4;
109 }
110
111 // Parent client implementation
112 HfpClientInterface* HfpClientInterface::interface = nullptr;
Get()113 HfpClientInterface* HfpClientInterface::Get() {
114 if (!is_hal_enabled()) {
115 log::error("BluetoothAudio HAL is disabled");
116 return nullptr;
117 }
118 if (!is_aidl_support_hfp()) {
119 log::warn("Unsupported HIDL or AIDL version");
120 return nullptr;
121 }
122 if (HfpClientInterface::interface == nullptr) {
123 HfpClientInterface::interface = new HfpClientInterface();
124 }
125 return HfpClientInterface::interface;
126 }
127
128 // Decode client implementation
Cleanup()129 void HfpClientInterface::Decode::Cleanup() {
130 log::info("decode");
131 StopSession();
132 if (HfpDecodingTransport::instance_) {
133 delete HfpDecodingTransport::software_hal_interface;
134 HfpDecodingTransport::software_hal_interface = nullptr;
135 delete HfpDecodingTransport::instance_;
136 HfpDecodingTransport::instance_ = nullptr;
137 }
138 }
139
StartSession()140 void HfpClientInterface::Decode::StartSession() {
141 if (!is_aidl_support_hfp()) {
142 log::warn("Unsupported HIDL or AIDL version");
143 return;
144 }
145 log::info("decode");
146 AudioConfiguration audio_config;
147 audio_config.set<AudioConfiguration::pcmConfig>(
148 get_default_pcm_configuration());
149 if (!get_decode_client_interface()->UpdateAudioConfig(audio_config)) {
150 log::error("cannot update audio config to HAL");
151 return;
152 }
153 get_decode_client_interface()->StartSession();
154 }
155
StopSession()156 void HfpClientInterface::Decode::StopSession() {
157 if (!is_aidl_support_hfp()) {
158 log::warn("Unsupported HIDL or AIDL version");
159 return;
160 }
161 log::info("decode");
162 get_decode_client_interface()->EndSession();
163 if (get_decode_transport_instance()) {
164 get_decode_transport_instance()->ResetPendingCmd();
165 get_decode_transport_instance()->ResetPresentationPosition();
166 }
167 }
168
UpdateAudioConfigToHal(const::hfp::offload_config & offload_config)169 void HfpClientInterface::Decode::UpdateAudioConfigToHal(
170 const ::hfp::offload_config& offload_config) {
171 if (!is_aidl_support_hfp()) {
172 log::warn("Unsupported HIDL or AIDL version");
173 return;
174 }
175
176 log::warn("decode - Unsupported update audio config for software session");
177 return;
178 }
179
Read(uint8_t * p_buf,uint32_t len)180 size_t HfpClientInterface::Decode::Read(uint8_t* p_buf, uint32_t len) {
181 if (!is_aidl_support_hfp()) {
182 log::warn("Unsupported HIDL or AIDL version");
183 return 0;
184 }
185 log::info("decode");
186 return get_decode_client_interface()->ReadAudioData(p_buf, len);
187 }
188
ConfirmStreamingRequest()189 void HfpClientInterface::Decode::ConfirmStreamingRequest() {
190 auto instance = aidl::hfp::HfpDecodingTransport::instance_;
191 auto pending_cmd = instance->GetPendingCmd();
192 switch (pending_cmd) {
193 case aidl::hfp::HFP_CTRL_CMD_START:
194 aidl::hfp::HfpDecodingTransport::software_hal_interface->StreamStarted(
195 aidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED);
196 instance->ResetPendingCmd();
197 return;
198 case aidl::hfp::HFP_CTRL_CMD_NONE:
199 log::warn("no pending start stream request");
200 return;
201 default:
202 log::warn("Invalid state, {}", pending_cmd);
203 }
204 }
205
CancelStreamingRequest()206 void HfpClientInterface::Decode::CancelStreamingRequest() {
207 auto instance = aidl::hfp::HfpDecodingTransport::instance_;
208 auto pending_cmd = instance->GetPendingCmd();
209 switch (pending_cmd) {
210 case aidl::hfp::HFP_CTRL_CMD_START:
211 aidl::hfp::HfpDecodingTransport::software_hal_interface->StreamStarted(
212 aidl::BluetoothAudioCtrlAck::FAILURE);
213 instance->ResetPendingCmd();
214 return;
215 case aidl::hfp::HFP_CTRL_CMD_NONE:
216 log::warn("no pending start stream request");
217 return;
218 default:
219 log::warn("Invalid state, {}", pending_cmd);
220 }
221 }
222
GetDecode(bluetooth::common::MessageLoopThread *)223 HfpClientInterface::Decode* HfpClientInterface::GetDecode(
224 bluetooth::common::MessageLoopThread* /*message_loop*/) {
225 if (!is_aidl_support_hfp()) {
226 log::warn("Unsupported HIDL or AIDL version");
227 return nullptr;
228 }
229
230 if (decode_ == nullptr) {
231 decode_ = new Decode();
232 } else {
233 log::warn("Decode is already acquired");
234 return nullptr;
235 }
236
237 log::info("decode");
238
239 HfpDecodingTransport::instance_ = new HfpDecodingTransport(
240 aidl::SessionType::HFP_SOFTWARE_DECODING_DATAPATH);
241 HfpDecodingTransport::software_hal_interface =
242 new aidl::BluetoothAudioSinkClientInterface(
243 HfpDecodingTransport::instance_);
244 if (!HfpDecodingTransport::software_hal_interface->IsValid()) {
245 log::warn("BluetoothAudio HAL for HFP is invalid");
246 delete HfpDecodingTransport::software_hal_interface;
247 HfpDecodingTransport::software_hal_interface = nullptr;
248 delete HfpDecodingTransport::instance_;
249 HfpDecodingTransport::instance_ = nullptr;
250 return nullptr;
251 }
252
253 HfpDecodingTransport::active_hal_interface =
254 HfpDecodingTransport::software_hal_interface;
255
256 return decode_;
257 }
258
ReleaseDecode(HfpClientInterface::Decode * decode)259 bool HfpClientInterface::ReleaseDecode(HfpClientInterface::Decode* decode) {
260 if (decode != decode_) {
261 log::warn("can't release not acquired decode");
262 return false;
263 }
264
265 log::info("decode");
266 if (get_decode_client_interface()) decode->Cleanup();
267
268 delete decode_;
269 decode_ = nullptr;
270
271 return true;
272 }
273
274 // Encoding client implementation
Cleanup()275 void HfpClientInterface::Encode::Cleanup() {
276 log::info("encode");
277 StopSession();
278 if (HfpEncodingTransport::instance_) {
279 delete HfpEncodingTransport::software_hal_interface;
280 HfpEncodingTransport::software_hal_interface = nullptr;
281 delete HfpEncodingTransport::instance_;
282 HfpEncodingTransport::instance_ = nullptr;
283 }
284 }
285
StartSession()286 void HfpClientInterface::Encode::StartSession() {
287 if (!is_aidl_support_hfp()) {
288 log::warn("Unsupported HIDL or AIDL version");
289 return;
290 }
291 log::info("encode");
292 AudioConfiguration audio_config;
293 audio_config.set<AudioConfiguration::pcmConfig>(
294 get_default_pcm_configuration());
295 if (!get_encode_client_interface()->UpdateAudioConfig(audio_config)) {
296 log::error("cannot update audio config to HAL");
297 return;
298 }
299 get_encode_client_interface()->StartSession();
300 }
301
StopSession()302 void HfpClientInterface::Encode::StopSession() {
303 if (!is_aidl_support_hfp()) {
304 log::warn("Unsupported HIDL or AIDL version");
305 return;
306 }
307 log::info("encode");
308 get_encode_client_interface()->EndSession();
309 if (get_encode_transport_instance()) {
310 get_encode_transport_instance()->ResetPendingCmd();
311 get_encode_transport_instance()->ResetPresentationPosition();
312 }
313 }
314
UpdateAudioConfigToHal(const::hfp::offload_config & offload_config)315 void HfpClientInterface::Encode::UpdateAudioConfigToHal(
316 const ::hfp::offload_config& offload_config) {
317 if (!is_aidl_support_hfp()) {
318 log::warn("Unsupported HIDL or AIDL version");
319 return;
320 }
321
322 log::warn("encode - Unsupported update audio config for software session");
323 return;
324 }
325
Write(const uint8_t * p_buf,uint32_t len)326 size_t HfpClientInterface::Encode::Write(const uint8_t* p_buf, uint32_t len) {
327 if (!is_aidl_support_hfp()) {
328 log::warn("Unsupported HIDL or AIDL version");
329 return 0;
330 }
331 log::info("encode");
332 return get_encode_client_interface()->WriteAudioData(p_buf, len);
333 }
334
ConfirmStreamingRequest()335 void HfpClientInterface::Encode::ConfirmStreamingRequest() {
336 auto instance = aidl::hfp::HfpEncodingTransport::instance_;
337 auto pending_cmd = instance->GetPendingCmd();
338 switch (pending_cmd) {
339 case aidl::hfp::HFP_CTRL_CMD_START:
340 aidl::hfp::HfpEncodingTransport::software_hal_interface->StreamStarted(
341 aidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED);
342 instance->ResetPendingCmd();
343 return;
344 case aidl::hfp::HFP_CTRL_CMD_NONE:
345 log::warn("no pending start stream request");
346 return;
347 default:
348 log::warn("Invalid state, {}", pending_cmd);
349 }
350 }
351
CancelStreamingRequest()352 void HfpClientInterface::Encode::CancelStreamingRequest() {
353 auto instance = aidl::hfp::HfpEncodingTransport::instance_;
354 auto pending_cmd = instance->GetPendingCmd();
355 switch (pending_cmd) {
356 case aidl::hfp::HFP_CTRL_CMD_START:
357 aidl::hfp::HfpEncodingTransport::software_hal_interface->StreamStarted(
358 aidl::BluetoothAudioCtrlAck::FAILURE);
359 instance->ResetPendingCmd();
360 return;
361 case aidl::hfp::HFP_CTRL_CMD_NONE:
362 log::warn("no pending start stream request");
363 return;
364 default:
365 log::warn("Invalid state, {}", pending_cmd);
366 }
367 }
368
GetEncode(bluetooth::common::MessageLoopThread *)369 HfpClientInterface::Encode* HfpClientInterface::GetEncode(
370 bluetooth::common::MessageLoopThread* /*message_loop*/) {
371 if (!is_aidl_support_hfp()) {
372 log::warn("Unsupported HIDL or AIDL version");
373 return nullptr;
374 }
375
376 if (encode_ == nullptr) {
377 encode_ = new Encode();
378 } else {
379 log::warn("Encoding is already acquired");
380 return nullptr;
381 }
382
383 log::info("encode");
384
385 HfpEncodingTransport::instance_ = new HfpEncodingTransport(
386 aidl::SessionType::HFP_SOFTWARE_ENCODING_DATAPATH);
387 HfpEncodingTransport::software_hal_interface =
388 new aidl::BluetoothAudioSourceClientInterface(
389 HfpEncodingTransport::instance_);
390 if (!HfpEncodingTransport::software_hal_interface->IsValid()) {
391 log::warn("BluetoothAudio HAL for HFP is invalid");
392 delete HfpEncodingTransport::software_hal_interface;
393 HfpEncodingTransport::software_hal_interface = nullptr;
394 delete HfpEncodingTransport::instance_;
395 HfpEncodingTransport::instance_ = nullptr;
396 return nullptr;
397 }
398
399 HfpEncodingTransport::active_hal_interface =
400 HfpEncodingTransport::software_hal_interface;
401
402 return encode_;
403 }
404
ReleaseEncode(HfpClientInterface::Encode * encode)405 bool HfpClientInterface::ReleaseEncode(HfpClientInterface::Encode* encode) {
406 if (encode != encode_) {
407 log::warn("can't release not acquired encode");
408 return false;
409 }
410
411 if (get_encode_client_interface()) encode->Cleanup();
412
413 delete encode_;
414 encode_ = nullptr;
415
416 return true;
417 }
418
419 // Offload client implementation
420 // Based on HfpEncodingTransport
Cleanup()421 void HfpClientInterface::Offload::Cleanup() {
422 log::info("offload");
423 StopSession();
424 if (HfpEncodingTransport::instance_) {
425 delete HfpEncodingTransport::offloading_hal_interface;
426 HfpEncodingTransport::offloading_hal_interface = nullptr;
427 delete HfpEncodingTransport::instance_;
428 HfpEncodingTransport::instance_ = nullptr;
429 }
430 }
431
StartSession()432 void HfpClientInterface::Offload::StartSession() {
433 if (!is_aidl_support_hfp()) {
434 log::warn("Unsupported HIDL or AIDL version");
435 return;
436 }
437 log::info("offload");
438 AudioConfiguration audio_config;
439 audio_config.set<AudioConfiguration::hfpConfig>(
440 get_default_hfp_configuration());
441 if (!get_encode_client_interface()->UpdateAudioConfig(audio_config)) {
442 log::error("cannot update audio config to HAL");
443 return;
444 }
445 get_encode_client_interface()->StartSession();
446 }
447
StopSession()448 void HfpClientInterface::Offload::StopSession() {
449 if (!is_aidl_support_hfp()) {
450 log::warn("Unsupported HIDL or AIDL version");
451 return;
452 }
453 log::info("offload");
454 get_encode_client_interface()->EndSession();
455 if (get_encode_transport_instance()) {
456 get_encode_transport_instance()->ResetPendingCmd();
457 get_encode_transport_instance()->ResetPresentationPosition();
458 }
459 }
460
UpdateAudioConfigToHal(const::hfp::offload_config & offload_config)461 void HfpClientInterface::Offload::UpdateAudioConfigToHal(
462 const ::hfp::offload_config& offload_config) {
463 if (!is_aidl_support_hfp()) {
464 log::warn("Unsupported HIDL or AIDL version");
465 return;
466 }
467
468 log::info("offload");
469 get_encode_client_interface()->UpdateAudioConfig(
470 offload_config_to_hal_audio_config(offload_config));
471 }
472
ConfirmStreamingRequest()473 void HfpClientInterface::Offload::ConfirmStreamingRequest() {
474 auto instance = aidl::hfp::HfpEncodingTransport::instance_;
475 auto pending_cmd = instance->GetPendingCmd();
476 switch (pending_cmd) {
477 case aidl::hfp::HFP_CTRL_CMD_START:
478 aidl::hfp::HfpEncodingTransport::offloading_hal_interface->StreamStarted(
479 aidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED);
480 instance->ResetPendingCmd();
481 return;
482 case aidl::hfp::HFP_CTRL_CMD_NONE:
483 log::warn("no pending start stream request");
484 return;
485 default:
486 log::warn("Invalid state, {}", pending_cmd);
487 }
488 }
489
CancelStreamingRequest()490 void HfpClientInterface::Offload::CancelStreamingRequest() {
491 auto instance = aidl::hfp::HfpEncodingTransport::instance_;
492 auto pending_cmd = instance->GetPendingCmd();
493 switch (pending_cmd) {
494 case aidl::hfp::HFP_CTRL_CMD_START:
495 aidl::hfp::HfpEncodingTransport::offloading_hal_interface->StreamStarted(
496 aidl::BluetoothAudioCtrlAck::FAILURE);
497 instance->ResetPendingCmd();
498 return;
499 case aidl::hfp::HFP_CTRL_CMD_NONE:
500 log::warn("no pending start stream request");
501 return;
502 default:
503 log::warn("Invalid state, {}", pending_cmd);
504 }
505 }
506
507 std::unordered_map<int, ::hfp::sco_config>
GetHfpScoConfig()508 HfpClientInterface::Offload::GetHfpScoConfig() {
509 return aidl::hfp::HfpTransport::GetHfpScoConfig(
510 aidl::SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH);
511 }
512
GetOffload(bluetooth::common::MessageLoopThread *)513 HfpClientInterface::Offload* HfpClientInterface::GetOffload(
514 bluetooth::common::MessageLoopThread* /*message_loop*/) {
515 if (!is_aidl_support_hfp()) {
516 log::warn("Unsupported HIDL or AIDL version");
517 return nullptr;
518 }
519
520 if (offload_ == nullptr) {
521 offload_ = new Offload();
522 } else {
523 log::warn("Offload is already acquired");
524 return nullptr;
525 }
526
527 log::info("offload");
528
529 // Prepare offload hal interface.
530 if (bta_ag_get_sco_offload_enabled()) {
531 HfpEncodingTransport::instance_ = new HfpEncodingTransport(
532 aidl::SessionType::HFP_HARDWARE_OFFLOAD_DATAPATH);
533 HfpEncodingTransport::offloading_hal_interface =
534 new aidl::BluetoothAudioSourceClientInterface(
535 HfpEncodingTransport::instance_);
536 if (!HfpEncodingTransport::offloading_hal_interface->IsValid()) {
537 log::fatal("BluetoothAudio HAL for HFP offloading is invalid");
538 delete HfpEncodingTransport::offloading_hal_interface;
539 HfpEncodingTransport::offloading_hal_interface = nullptr;
540 delete HfpEncodingTransport::instance_;
541 HfpEncodingTransport::instance_ = static_cast<HfpEncodingTransport*>(
542 HfpEncodingTransport::software_hal_interface->GetTransportInstance());
543 delete HfpEncodingTransport::software_hal_interface;
544 HfpEncodingTransport::software_hal_interface = nullptr;
545 delete HfpEncodingTransport::instance_;
546 return nullptr;
547 }
548 }
549
550 HfpEncodingTransport::active_hal_interface =
551 HfpEncodingTransport::offloading_hal_interface;
552
553 return offload_;
554 }
555
ReleaseOffload(HfpClientInterface::Offload * offload)556 bool HfpClientInterface::ReleaseOffload(HfpClientInterface::Offload* offload) {
557 if (offload != offload_) {
558 log::warn("can't release not acquired offload");
559 return false;
560 }
561
562 if (get_encode_client_interface()) offload->Cleanup();
563
564 delete offload_;
565 offload_ = nullptr;
566
567 return true;
568 }
569
570 } // namespace hfp
571 } // namespace audio
572 } // namespace bluetooth
573