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