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