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 #define LOG_TAG "AIDLA2dpProviderInfo"
18 
19 #include "a2dp_provider_info.h"
20 
21 #include <android/binder_manager.h>
22 #include <bluetooth/log.h>
23 #include <com_android_bluetooth_flags.h>
24 
25 #include <optional>
26 #include <vector>
27 
28 #include "a2dp_codec_api.h"
29 #include "a2dp_constants.h"
30 #include "a2dp_vendor.h"
31 #include "a2dp_vendor_aptx_constants.h"
32 #include "a2dp_vendor_aptx_hd_constants.h"
33 #include "a2dp_vendor_ldac_constants.h"
34 #include "a2dp_vendor_opus_constants.h"
35 #include "client_interface_aidl.h"
36 #include "os/log.h"
37 
38 namespace bluetooth::audio::aidl::a2dp {
39 
40 using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
41 using ::aidl::android::hardware::bluetooth::audio::CodecId;
42 using ::aidl::android::hardware::bluetooth::audio::CodecInfo;
43 using ::aidl::android::hardware::bluetooth::audio::
44     IBluetoothAudioProviderFactory;
45 using ::aidl::android::hardware::bluetooth::audio::SessionType;
46 
47 /***
48  * Reads the provider information from the HAL.
49  * May return nullptr if the HAL does not implement
50  * getProviderInfo, or if the feature flag for codec
51  * extensibility is disabled.
52  ***/
GetProviderInfo(bool supports_a2dp_hw_offload_v2)53 std::unique_ptr<ProviderInfo> ProviderInfo::GetProviderInfo(
54     bool supports_a2dp_hw_offload_v2) {
55   if (!com::android::bluetooth::flags::a2dp_offload_codec_extensibility()) {
56     log::info(
57         "a2dp offload codec extensibility is disabled,"
58         " not going to load the ProviderInfo");
59     return nullptr;
60   }
61 
62   if (!supports_a2dp_hw_offload_v2) {
63     log::info(
64         "a2dp hw offload v2 is not supported by the controller,"
65         " not going to load the ProviderInfo");
66     return nullptr;
67   }
68 
69   auto source_provider_info = BluetoothAudioClientInterface::GetProviderInfo(
70       SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH, nullptr);
71 
72   auto sink_provider_info = BluetoothAudioClientInterface::GetProviderInfo(
73       SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH, nullptr);
74 
75   if (!source_provider_info.has_value() && !sink_provider_info.has_value()) {
76     log::info(
77         "a2dp offload codec extensibility is enabled,"
78         " but the provider info is empty");
79     return nullptr;
80   }
81 
82   std::vector<CodecInfo> source_codecs;
83   std::vector<CodecInfo> sink_codecs;
84 
85   if (source_provider_info.has_value()) {
86     source_codecs = std::move(source_provider_info->codecInfos);
87   }
88 
89   if (sink_provider_info.has_value()) {
90     sink_codecs = std::move(sink_provider_info->codecInfos);
91   }
92 
93   log::info("successfully loaded provider info");
94   return std::make_unique<ProviderInfo>(std::move(source_codecs),
95                                         std::move(sink_codecs));
96 }
97 
98 /***
99  * Returns the codec with the selected index if supported
100  * by the provider.
101  ***/
GetCodec(btav_a2dp_codec_index_t codec_index) const102 std::optional<CodecInfo const*> ProviderInfo::GetCodec(
103     btav_a2dp_codec_index_t codec_index) const {
104   auto it = assigned_codec_indexes.find(codec_index);
105   return it == assigned_codec_indexes.end() ? std::nullopt
106                                             : std::make_optional(it->second);
107 }
108 
109 /***
110  * Return the assigned source codec index if the codec
111  * matches a known codec, or pick a new codec index starting from
112  * ext_index.
113  ***/
assignSourceCodecIndex(CodecInfo const & codec,btav_a2dp_codec_index_t * ext_index)114 static std::optional<btav_a2dp_codec_index_t> assignSourceCodecIndex(
115     CodecInfo const& codec, btav_a2dp_codec_index_t* ext_index) {
116   switch (codec.id.getTag()) {
117     case CodecId::core:
118     default:
119       return std::nullopt;
120     case CodecId::a2dp:
121       switch (codec.id.get<CodecId::a2dp>()) {
122         case CodecId::A2dp::SBC:
123           return BTAV_A2DP_CODEC_INDEX_SOURCE_SBC;
124         case CodecId::A2dp::AAC:
125           return BTAV_A2DP_CODEC_INDEX_SOURCE_AAC;
126         default:
127           return std::nullopt;
128       }
129       break;
130     case CodecId::vendor: {
131       int vendor_id = codec.id.get<CodecId::vendor>().id;
132       int codec_id = codec.id.get<CodecId::vendor>().codecId;
133 
134       /* match know vendor codecs */
135       if (vendor_id == A2DP_APTX_VENDOR_ID &&
136           codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
137         return BTAV_A2DP_CODEC_INDEX_SOURCE_APTX;
138       }
139       if (vendor_id == A2DP_APTX_HD_VENDOR_ID &&
140           codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
141         return BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD;
142       }
143       if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
144         return BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC;
145       }
146       if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
147         return BTAV_A2DP_CODEC_INDEX_SOURCE_OPUS;
148       }
149 
150       /* out of extension codec indexes */
151       if (*ext_index >= BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX) {
152         log::error(
153             "unable to assign a source codec index for vendorId={}, codecId={}",
154             vendor_id, codec_id);
155       }
156 
157       /* assign a new codec index for the
158          unknown vendor codec */
159       return *(ext_index++);
160     }
161   }
162 }
163 
164 /***
165  * Return the assigned source codec index if the codec
166  * matches a known codec, or pick a new codec index starting from
167  * ext_index.
168  ***/
assignSinkCodecIndex(CodecInfo const & codec,btav_a2dp_codec_index_t * ext_index)169 static std::optional<btav_a2dp_codec_index_t> assignSinkCodecIndex(
170     CodecInfo const& codec, btav_a2dp_codec_index_t* ext_index) {
171   switch (codec.id.getTag()) {
172     case CodecId::core:
173     default:
174       return std::nullopt;
175     case CodecId::a2dp:
176       switch (codec.id.get<CodecId::a2dp>()) {
177         case CodecId::A2dp::SBC:
178           return BTAV_A2DP_CODEC_INDEX_SINK_SBC;
179         case CodecId::A2dp::AAC:
180           return BTAV_A2DP_CODEC_INDEX_SINK_AAC;
181         default:
182           return std::nullopt;
183       }
184       break;
185     case CodecId::vendor: {
186       int vendor_id = codec.id.get<CodecId::vendor>().id;
187       int codec_id = codec.id.get<CodecId::vendor>().codecId;
188 
189       /* match know vendor codecs */
190       if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
191         return BTAV_A2DP_CODEC_INDEX_SINK_LDAC;
192       }
193       if (vendor_id == A2DP_OPUS_VENDOR_ID && codec_id == A2DP_OPUS_CODEC_ID) {
194         return BTAV_A2DP_CODEC_INDEX_SINK_OPUS;
195       }
196 
197       /* out of extension codec indexes */
198       if (*ext_index >= BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX) {
199         log::error(
200             "unable to assign a sink codec index for vendorId={}, codecId={}",
201             vendor_id, codec_id);
202       }
203 
204       /* assign a new codec index for the
205          unknown vendor codec */
206       return *(ext_index++);
207     }
208   }
209 }
210 
ProviderInfo(std::vector<CodecInfo> source_codecs,std::vector<CodecInfo> sink_codecs)211 ProviderInfo::ProviderInfo(std::vector<CodecInfo> source_codecs,
212                            std::vector<CodecInfo> sink_codecs)
213     : source_codecs(std::move(source_codecs)),
214       sink_codecs(std::move(sink_codecs)) {
215   btav_a2dp_codec_index_t ext_source_index =
216       BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MIN;
217   for (size_t i = 0; i < this->source_codecs.size(); i++) {
218     auto& codec = this->source_codecs[i];
219     log::info("supported source codec {}", codec.name);
220     auto index = assignSourceCodecIndex(codec, &ext_source_index);
221     if (index.has_value()) {
222       assigned_codec_indexes[index.value()] = &codec;
223     }
224   }
225 
226   btav_a2dp_codec_index_t ext_sink_index = BTAV_A2DP_CODEC_INDEX_SINK_EXT_MIN;
227   for (size_t i = 0; i < this->sink_codecs.size(); i++) {
228     auto& codec = this->sink_codecs[i];
229     log::info("supports sink codec {}", codec.name);
230     auto index = assignSinkCodecIndex(codec, &ext_sink_index);
231     if (index.has_value()) {
232       assigned_codec_indexes[index.value()] = &codec;
233     }
234   }
235 }
236 
SourceCodecIndex(CodecId const & codec_id) const237 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SourceCodecIndex(
238     CodecId const& codec_id) const {
239   for (auto const& [index, codec] : assigned_codec_indexes) {
240     if (codec->id == codec_id && index >= BTAV_A2DP_CODEC_INDEX_SOURCE_MIN &&
241         index < BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX) {
242       return index;
243     }
244   }
245   return std::nullopt;
246 }
247 
SourceCodecIndex(uint32_t vendor_id,uint16_t codec_id) const248 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SourceCodecIndex(
249     uint32_t vendor_id, uint16_t codec_id) const {
250   for (auto const& [index, codec] : assigned_codec_indexes) {
251     if (codec->id.getTag() == CodecId::vendor &&
252         codec->id.get<CodecId::vendor>().id == (int)vendor_id &&
253         codec->id.get<CodecId::vendor>().codecId == codec_id &&
254         index >= BTAV_A2DP_CODEC_INDEX_SOURCE_MIN &&
255         index < BTAV_A2DP_CODEC_INDEX_SOURCE_EXT_MAX) {
256       return index;
257     }
258   }
259   return std::nullopt;
260 }
261 
SourceCodecIndex(uint8_t const * codec_info) const262 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SourceCodecIndex(
263     uint8_t const* codec_info) const {
264   log::assert_that(codec_info != nullptr, "codec_info is unexpectedly null");
265   auto codec_type = A2DP_GetCodecType(codec_info);
266   switch (codec_type) {
267     case A2DP_MEDIA_CT_SBC: {
268       return SourceCodecIndex(CodecId::A2dp(CodecId::A2dp::SBC));
269     }
270     case A2DP_MEDIA_CT_AAC: {
271       return SourceCodecIndex(CodecId::A2dp(CodecId::A2dp::AAC));
272     }
273     case A2DP_MEDIA_CT_NON_A2DP: {
274       uint32_t vendor_id = A2DP_VendorCodecGetVendorId(codec_info);
275       uint16_t codec_id = A2DP_VendorCodecGetCodecId(codec_info);
276       return SourceCodecIndex(vendor_id, codec_id);
277     }
278     default: {
279       return std::nullopt;
280     }
281   }
282 }
283 
SinkCodecIndex(CodecId const & codec_id) const284 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SinkCodecIndex(
285     CodecId const& codec_id) const {
286   for (auto const& [index, codec] : assigned_codec_indexes) {
287     if (codec->id == codec_id && index >= BTAV_A2DP_CODEC_INDEX_SINK_MIN &&
288         index < BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX) {
289       return index;
290     }
291   }
292   return std::nullopt;
293 }
294 
SinkCodecIndex(uint32_t vendor_id,uint16_t codec_id) const295 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SinkCodecIndex(
296     uint32_t vendor_id, uint16_t codec_id) const {
297   for (auto const& [index, codec] : assigned_codec_indexes) {
298     if (codec->id.getTag() == CodecId::vendor &&
299         codec->id.get<CodecId::vendor>().id == (int)vendor_id &&
300         codec->id.get<CodecId::vendor>().codecId == codec_id &&
301         index >= BTAV_A2DP_CODEC_INDEX_SINK_MIN &&
302         index < BTAV_A2DP_CODEC_INDEX_SINK_EXT_MAX) {
303       return index;
304     }
305   }
306   return std::nullopt;
307 }
308 
SinkCodecIndex(uint8_t const * codec_info) const309 std::optional<btav_a2dp_codec_index_t> ProviderInfo::SinkCodecIndex(
310     uint8_t const* codec_info) const {
311   log::assert_that(codec_info != nullptr, "codec_info is unexpectedly null");
312   auto codec_type = A2DP_GetCodecType(codec_info);
313   switch (codec_type) {
314     case A2DP_MEDIA_CT_SBC: {
315       return SinkCodecIndex(CodecId::A2dp(CodecId::A2dp::SBC));
316     }
317     case A2DP_MEDIA_CT_AAC: {
318       return SinkCodecIndex(CodecId::A2dp(CodecId::A2dp::AAC));
319     }
320     case A2DP_MEDIA_CT_NON_A2DP: {
321       uint32_t vendor_id = A2DP_VendorCodecGetVendorId(codec_info);
322       uint16_t codec_id = A2DP_VendorCodecGetCodecId(codec_info);
323       return SinkCodecIndex(vendor_id, codec_id);
324     }
325     default: {
326       return std::nullopt;
327     }
328   }
329 }
330 
CodecIndexStr(btav_a2dp_codec_index_t codec_index) const331 std::optional<const char*> ProviderInfo::CodecIndexStr(
332     btav_a2dp_codec_index_t codec_index) const {
333   auto it = assigned_codec_indexes.find(codec_index);
334   return it != assigned_codec_indexes.end()
335              ? std::make_optional(it->second->name.c_str())
336              : std::nullopt;
337 }
338 
SupportsCodec(btav_a2dp_codec_index_t codec_index) const339 bool ProviderInfo::SupportsCodec(btav_a2dp_codec_index_t codec_index) const {
340   return assigned_codec_indexes.find(codec_index) !=
341          assigned_codec_indexes.end();
342 }
343 
BuildCodecCapabilities(CodecId const & codec_id,std::vector<uint8_t> const & capabilities,uint8_t * codec_info)344 bool ProviderInfo::BuildCodecCapabilities(
345     CodecId const& codec_id, std::vector<uint8_t> const& capabilities,
346     uint8_t* codec_info) {
347   switch (codec_id.getTag()) {
348     case CodecId::a2dp: {
349       auto id = codec_id.get<CodecId::a2dp>();
350       codec_info[0] = 2 + capabilities.size();
351       codec_info[1] = AVDT_MEDIA_TYPE_AUDIO << 4;
352       codec_info[2] = static_cast<uint8_t>(id);
353       memcpy(codec_info + 3, capabilities.data(), capabilities.size());
354       return true;
355     }
356     case CodecId::vendor: {
357       auto id = codec_id.get<CodecId::vendor>();
358       uint32_t vendor_id = static_cast<uint32_t>(id.id);
359       uint16_t codec_id = static_cast<uint16_t>(id.codecId);
360       codec_info[0] = 8 + capabilities.size();
361       codec_info[1] = AVDT_MEDIA_TYPE_AUDIO << 4;
362       codec_info[2] = A2DP_MEDIA_CT_NON_A2DP;
363       codec_info[3] = static_cast<uint8_t>(vendor_id >> 0);
364       codec_info[4] = static_cast<uint8_t>(vendor_id >> 8);
365       codec_info[5] = static_cast<uint8_t>(vendor_id >> 16);
366       codec_info[6] = static_cast<uint8_t>(vendor_id >> 24);
367       codec_info[7] = static_cast<uint8_t>(codec_id >> 0);
368       codec_info[8] = static_cast<uint8_t>(codec_id >> 8);
369       memcpy(codec_info + 9, capabilities.data(), capabilities.size());
370       return true;
371     }
372     case CodecId::core:
373     default:
374       break;
375   }
376   return false;
377 }
378 
CodecCapabilities(btav_a2dp_codec_index_t codec_index,uint64_t * codec_id,uint8_t * codec_info,btav_a2dp_codec_config_t * codec_config) const379 bool ProviderInfo::CodecCapabilities(
380     btav_a2dp_codec_index_t codec_index, uint64_t* codec_id,
381     uint8_t* codec_info, btav_a2dp_codec_config_t* codec_config) const {
382   auto it = assigned_codec_indexes.find(codec_index);
383   if (it == assigned_codec_indexes.end()) {
384     return false;
385   }
386 
387   CodecInfo const* codec = it->second;
388   auto transport = codec->transport.get<CodecInfo::Transport::a2dp>();
389 
390   if (codec_id != nullptr) {
391     switch (codec->id.getTag()) {
392       case CodecId::a2dp: {
393         auto id = codec->id.get<CodecId::a2dp>();
394         *codec_id = static_cast<uint8_t>(id);
395         break;
396       }
397       case CodecId::vendor: {
398         auto id = codec->id.get<CodecId::vendor>();
399         *codec_id = 0xff | (static_cast<uint64_t>(id.id) << 8) |
400                     (static_cast<uint64_t>(id.codecId) << 24);
401         break;
402       }
403       default:
404         break;
405     }
406   }
407   if (codec_config != nullptr) {
408     memset(codec_config, 0, sizeof(*codec_config));
409     for (auto const& channel_mode : transport.channelMode) {
410       switch (channel_mode) {
411         case ChannelMode::MONO:
412           codec_config->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
413           break;
414         case ChannelMode::STEREO:
415           codec_config->channel_mode |= BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO;
416           break;
417         case ChannelMode::DUALMONO:
418         case ChannelMode::UNKNOWN:
419         default:
420           break;
421       }
422     }
423     for (auto const& sample_rate : transport.samplingFrequencyHz) {
424       switch (sample_rate) {
425         case 44100:
426           codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
427           break;
428         case 48000:
429           codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_48000;
430           break;
431         case 88200:
432           codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_88200;
433           break;
434         case 96000:
435           codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_96000;
436           break;
437         case 176400:
438           codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_176400;
439           break;
440         case 192000:
441           codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_192000;
442           break;
443         case 16000:
444           codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_16000;
445           break;
446         case 24000:
447           codec_config->sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_24000;
448           break;
449         default:
450           break;
451       }
452     }
453     for (auto const& bitdepth : transport.bitdepth) {
454       switch (bitdepth) {
455         case 16:
456           codec_config->bits_per_sample |= BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16;
457           break;
458         case 24:
459           codec_config->bits_per_sample |= BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24;
460           break;
461         case 32:
462           codec_config->bits_per_sample |= BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32;
463           break;
464         default:
465           break;
466       }
467     }
468   }
469 
470   return codec_info == nullptr ||
471          BuildCodecCapabilities(codec->id, transport.capabilities, codec_info);
472 }
473 
474 }  // namespace bluetooth::audio::aidl::a2dp
475