• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 /**
18  * A2DP Codecs Configuration
19  */
20 
21 #define LOG_TAG "a2dp_codec"
22 
23 #include "a2dp_codec_api.h"
24 
25 #include <base/logging.h>
26 #include <inttypes.h>
27 
28 #include "a2dp_aac.h"
29 #include "a2dp_sbc.h"
30 #include "a2dp_vendor.h"
31 #include "a2dp_vendor_aptx.h"
32 #include "a2dp_vendor_aptx_hd.h"
33 #include "a2dp_vendor_ldac.h"
34 #include "bta/av/bta_av_int.h"
35 #include "osi/include/log.h"
36 #include "osi/include/properties.h"
37 
38 /* The Media Type offset within the codec info byte array */
39 #define A2DP_MEDIA_TYPE_OFFSET 1
40 
41 /* A2DP Offload enabled in stack */
42 static bool a2dp_offload_status;
43 
44 // Initializes the codec config.
45 // |codec_config| is the codec config to initialize.
46 // |codec_index| and |codec_priority| are the codec type and priority to use
47 // for the initialization.
48 
init_btav_a2dp_codec_config(btav_a2dp_codec_config_t * codec_config,btav_a2dp_codec_index_t codec_index,btav_a2dp_codec_priority_t codec_priority)49 static void init_btav_a2dp_codec_config(
50     btav_a2dp_codec_config_t* codec_config, btav_a2dp_codec_index_t codec_index,
51     btav_a2dp_codec_priority_t codec_priority) {
52   memset(codec_config, 0, sizeof(btav_a2dp_codec_config_t));
53   codec_config->codec_type = codec_index;
54   codec_config->codec_priority = codec_priority;
55 }
56 
A2dpCodecConfig(btav_a2dp_codec_index_t codec_index,const std::string & name,btav_a2dp_codec_priority_t codec_priority)57 A2dpCodecConfig::A2dpCodecConfig(btav_a2dp_codec_index_t codec_index,
58                                  const std::string& name,
59                                  btav_a2dp_codec_priority_t codec_priority)
60     : codec_index_(codec_index),
61       name_(name),
62       default_codec_priority_(codec_priority) {
63   setCodecPriority(codec_priority);
64 
65   init_btav_a2dp_codec_config(&codec_config_, codec_index_, codecPriority());
66   init_btav_a2dp_codec_config(&codec_capability_, codec_index_,
67                               codecPriority());
68   init_btav_a2dp_codec_config(&codec_local_capability_, codec_index_,
69                               codecPriority());
70   init_btav_a2dp_codec_config(&codec_selectable_capability_, codec_index_,
71                               codecPriority());
72   init_btav_a2dp_codec_config(&codec_user_config_, codec_index_,
73                               BTAV_A2DP_CODEC_PRIORITY_DEFAULT);
74   init_btav_a2dp_codec_config(&codec_audio_config_, codec_index_,
75                               BTAV_A2DP_CODEC_PRIORITY_DEFAULT);
76 
77   memset(ota_codec_config_, 0, sizeof(ota_codec_config_));
78   memset(ota_codec_peer_capability_, 0, sizeof(ota_codec_peer_capability_));
79   memset(ota_codec_peer_config_, 0, sizeof(ota_codec_peer_config_));
80 }
81 
~A2dpCodecConfig()82 A2dpCodecConfig::~A2dpCodecConfig() {}
83 
setCodecPriority(btav_a2dp_codec_priority_t codec_priority)84 void A2dpCodecConfig::setCodecPriority(
85     btav_a2dp_codec_priority_t codec_priority) {
86   if (codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) {
87     // Compute the default codec priority
88     setDefaultCodecPriority();
89   } else {
90     codec_priority_ = codec_priority;
91   }
92   codec_config_.codec_priority = codec_priority_;
93 }
94 
setDefaultCodecPriority()95 void A2dpCodecConfig::setDefaultCodecPriority() {
96   if (default_codec_priority_ != BTAV_A2DP_CODEC_PRIORITY_DEFAULT) {
97     codec_priority_ = default_codec_priority_;
98   } else {
99     // Compute the default codec priority
100     uint32_t priority = 1000 * (codec_index_ + 1) + 1;
101     codec_priority_ = static_cast<btav_a2dp_codec_priority_t>(priority);
102   }
103   codec_config_.codec_priority = codec_priority_;
104 }
105 
createCodec(btav_a2dp_codec_index_t codec_index,btav_a2dp_codec_priority_t codec_priority)106 A2dpCodecConfig* A2dpCodecConfig::createCodec(
107     btav_a2dp_codec_index_t codec_index,
108     btav_a2dp_codec_priority_t codec_priority) {
109   LOG_DEBUG(LOG_TAG, "%s: codec %s", __func__, A2DP_CodecIndexStr(codec_index));
110 
111   A2dpCodecConfig* codec_config = nullptr;
112   switch (codec_index) {
113     case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
114       codec_config = new A2dpCodecConfigSbcSource(codec_priority);
115       break;
116     case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
117       codec_config = new A2dpCodecConfigSbcSink(codec_priority);
118       break;
119     case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
120       codec_config = new A2dpCodecConfigAacSource(codec_priority);
121       break;
122     case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
123       codec_config = new A2dpCodecConfigAacSink(codec_priority);
124       break;
125     case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
126       codec_config = new A2dpCodecConfigAptx(codec_priority);
127       break;
128     case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD:
129       codec_config = new A2dpCodecConfigAptxHd(codec_priority);
130       break;
131     case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
132       codec_config = new A2dpCodecConfigLdacSource(codec_priority);
133       break;
134     case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
135       codec_config = new A2dpCodecConfigLdacSink(codec_priority);
136       break;
137     case BTAV_A2DP_CODEC_INDEX_MAX:
138       break;
139   }
140 
141   if (codec_config != nullptr) {
142     if (!codec_config->init()) {
143       delete codec_config;
144       codec_config = nullptr;
145     }
146   }
147 
148   return codec_config;
149 }
150 
getTrackBitRate() const151 int A2dpCodecConfig::getTrackBitRate() const {
152   uint8_t p_codec_info[AVDT_CODEC_SIZE];
153   memcpy(p_codec_info, ota_codec_config_, sizeof(ota_codec_config_));
154   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
155 
156   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
157 
158   switch (codec_type) {
159     case A2DP_MEDIA_CT_SBC:
160       return A2DP_GetBitrateSbc();
161     case A2DP_MEDIA_CT_AAC:
162       return A2DP_GetBitRateAac(p_codec_info);
163     case A2DP_MEDIA_CT_NON_A2DP:
164       return A2DP_VendorGetBitRate(p_codec_info);
165     default:
166       break;
167   }
168 
169   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
170   return -1;
171 }
172 
getCodecSpecificConfig(tBT_A2DP_OFFLOAD * p_a2dp_offload)173 bool A2dpCodecConfig::getCodecSpecificConfig(tBT_A2DP_OFFLOAD* p_a2dp_offload) {
174   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
175 
176   uint8_t codec_config[AVDT_CODEC_SIZE];
177   uint32_t vendor_id;
178   uint16_t codec_id;
179 
180   memset(p_a2dp_offload->codec_info, 0, sizeof(p_a2dp_offload->codec_info));
181 
182   if (!A2DP_IsSourceCodecValid(ota_codec_config_)) {
183     return false;
184   }
185 
186   memcpy(codec_config, ota_codec_config_, sizeof(ota_codec_config_));
187   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(codec_config);
188   switch (codec_type) {
189     case A2DP_MEDIA_CT_SBC:
190       p_a2dp_offload->codec_info[0] =
191           codec_config[4];  // blk_len | subbands | Alloc Method
192       p_a2dp_offload->codec_info[1] = codec_config[5];  // Min bit pool
193       p_a2dp_offload->codec_info[2] = codec_config[6];  // Max bit pool
194       p_a2dp_offload->codec_info[3] =
195           codec_config[3];  // Sample freq | channel mode
196       break;
197     case A2DP_MEDIA_CT_AAC:
198       p_a2dp_offload->codec_info[0] = codec_config[3];  // object type
199       p_a2dp_offload->codec_info[1] = codec_config[6];  // VBR | BR
200       break;
201     case A2DP_MEDIA_CT_NON_A2DP:
202       vendor_id = A2DP_VendorCodecGetVendorId(codec_config);
203       codec_id = A2DP_VendorCodecGetCodecId(codec_config);
204       p_a2dp_offload->codec_info[0] = (vendor_id & 0x000000FF);
205       p_a2dp_offload->codec_info[1] = (vendor_id & 0x0000FF00) >> 8;
206       p_a2dp_offload->codec_info[2] = (vendor_id & 0x00FF0000) >> 16;
207       p_a2dp_offload->codec_info[3] = (vendor_id & 0xFF000000) >> 24;
208       p_a2dp_offload->codec_info[4] = (codec_id & 0x000000FF);
209       p_a2dp_offload->codec_info[5] = (codec_id & 0x0000FF00) >> 8;
210       if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
211         if (codec_config_.codec_specific_1 == 0) {  // default is 0, ABR
212           p_a2dp_offload->codec_info[6] =
213               A2DP_LDAC_QUALITY_ABR_OFFLOAD;  // ABR in offload
214         } else {
215           switch (codec_config_.codec_specific_1 % 10) {
216             case 0:
217               p_a2dp_offload->codec_info[6] =
218                   A2DP_LDAC_QUALITY_HIGH;  // High bitrate
219               break;
220             case 1:
221               p_a2dp_offload->codec_info[6] =
222                   A2DP_LDAC_QUALITY_MID;  // Mid birate
223               break;
224             case 2:
225               p_a2dp_offload->codec_info[6] =
226                   A2DP_LDAC_QUALITY_LOW;  // Low birate
227               break;
228             case 3:
229               FALLTHROUGH_INTENDED; /* FALLTHROUGH */
230             default:
231               p_a2dp_offload->codec_info[6] =
232                   A2DP_LDAC_QUALITY_ABR_OFFLOAD;  // ABR in offload
233               break;
234           }
235         }
236         p_a2dp_offload->codec_info[7] =
237             codec_config[10];  // LDAC specific channel mode
238         LOG_VERBOSE(LOG_TAG, "%s: Ldac specific channelmode =%d", __func__,
239                     p_a2dp_offload->codec_info[7]);
240       }
241       break;
242     default:
243       break;
244   }
245   return true;
246 }
247 
isValid() const248 bool A2dpCodecConfig::isValid() const { return true; }
249 
copyOutOtaCodecConfig(uint8_t * p_codec_info)250 bool A2dpCodecConfig::copyOutOtaCodecConfig(uint8_t* p_codec_info) {
251   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
252 
253   // TODO: We should use a mechanism to verify codec config,
254   // not codec capability.
255   if (!A2DP_IsSourceCodecValid(ota_codec_config_)) {
256     return false;
257   }
258   memcpy(p_codec_info, ota_codec_config_, sizeof(ota_codec_config_));
259   return true;
260 }
261 
getCodecConfig()262 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecConfig() {
263   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
264 
265   // TODO: We should check whether the codec config is valid
266   return codec_config_;
267 }
268 
getCodecCapability()269 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecCapability() {
270   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
271 
272   // TODO: We should check whether the codec capability is valid
273   return codec_capability_;
274 }
275 
getCodecLocalCapability()276 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecLocalCapability() {
277   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
278 
279   // TODO: We should check whether the codec capability is valid
280   return codec_local_capability_;
281 }
282 
getCodecSelectableCapability()283 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecSelectableCapability() {
284   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
285 
286   // TODO: We should check whether the codec capability is valid
287   return codec_selectable_capability_;
288 }
289 
getCodecUserConfig()290 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecUserConfig() {
291   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
292 
293   return codec_user_config_;
294 }
295 
getCodecAudioConfig()296 btav_a2dp_codec_config_t A2dpCodecConfig::getCodecAudioConfig() {
297   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
298 
299   return codec_audio_config_;
300 }
301 
getAudioBitsPerSample()302 uint8_t A2dpCodecConfig::getAudioBitsPerSample() {
303   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
304 
305   switch (codec_config_.bits_per_sample) {
306     case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
307       return 16;
308     case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
309       return 24;
310     case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
311       return 32;
312     case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
313       break;
314   }
315   return 0;
316 }
317 
isCodecConfigEmpty(const btav_a2dp_codec_config_t & codec_config)318 bool A2dpCodecConfig::isCodecConfigEmpty(
319     const btav_a2dp_codec_config_t& codec_config) {
320   return (
321       (codec_config.codec_priority == BTAV_A2DP_CODEC_PRIORITY_DEFAULT) &&
322       (codec_config.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) &&
323       (codec_config.bits_per_sample == BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) &&
324       (codec_config.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE) &&
325       (codec_config.codec_specific_1 == 0) &&
326       (codec_config.codec_specific_2 == 0) &&
327       (codec_config.codec_specific_3 == 0) &&
328       (codec_config.codec_specific_4 == 0));
329 }
330 
setCodecUserConfig(const btav_a2dp_codec_config_t & codec_user_config,const btav_a2dp_codec_config_t & codec_audio_config,const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,const uint8_t * p_peer_codec_info,bool is_capability,uint8_t * p_result_codec_config,bool * p_restart_input,bool * p_restart_output,bool * p_config_updated)331 bool A2dpCodecConfig::setCodecUserConfig(
332     const btav_a2dp_codec_config_t& codec_user_config,
333     const btav_a2dp_codec_config_t& codec_audio_config,
334     const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
335     const uint8_t* p_peer_codec_info, bool is_capability,
336     uint8_t* p_result_codec_config, bool* p_restart_input,
337     bool* p_restart_output, bool* p_config_updated) {
338   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
339   *p_restart_input = false;
340   *p_restart_output = false;
341   *p_config_updated = false;
342 
343   // Save copies of the current codec config, and the OTA codec config, so they
344   // can be compared for changes.
345   btav_a2dp_codec_config_t saved_codec_config = getCodecConfig();
346   uint8_t saved_ota_codec_config[AVDT_CODEC_SIZE];
347   memcpy(saved_ota_codec_config, ota_codec_config_, sizeof(ota_codec_config_));
348 
349   btav_a2dp_codec_config_t saved_codec_user_config = codec_user_config_;
350   codec_user_config_ = codec_user_config;
351   btav_a2dp_codec_config_t saved_codec_audio_config = codec_audio_config_;
352   codec_audio_config_ = codec_audio_config;
353   bool success =
354       setCodecConfig(p_peer_codec_info, is_capability, p_result_codec_config);
355   if (!success) {
356     // Restore the local copy of the user and audio config
357     codec_user_config_ = saved_codec_user_config;
358     codec_audio_config_ = saved_codec_audio_config;
359     return false;
360   }
361 
362   //
363   // The input (audio data) should be restarted if the audio format has changed
364   //
365   btav_a2dp_codec_config_t new_codec_config = getCodecConfig();
366   if ((saved_codec_config.sample_rate != new_codec_config.sample_rate) ||
367       (saved_codec_config.bits_per_sample !=
368        new_codec_config.bits_per_sample) ||
369       (saved_codec_config.channel_mode != new_codec_config.channel_mode)) {
370     *p_restart_input = true;
371   }
372 
373   //
374   // The output (the connection) should be restarted if OTA codec config
375   // has changed.
376   //
377   if (!A2DP_CodecEquals(saved_ota_codec_config, p_result_codec_config)) {
378     *p_restart_output = true;
379   }
380 
381   bool encoder_restart_input = *p_restart_input;
382   bool encoder_restart_output = *p_restart_output;
383   bool encoder_config_updated = *p_config_updated;
384 
385   if (!a2dp_offload_status) {
386     if (updateEncoderUserConfig(p_peer_params, &encoder_restart_input,
387                                 &encoder_restart_output,
388                                 &encoder_config_updated)) {
389       if (encoder_restart_input) *p_restart_input = true;
390       if (encoder_restart_output) *p_restart_output = true;
391       if (encoder_config_updated) *p_config_updated = true;
392     }
393   }
394   if (*p_restart_input || *p_restart_output) *p_config_updated = true;
395 
396   return true;
397 }
398 
codecConfigIsValid(const btav_a2dp_codec_config_t & codec_config)399 bool A2dpCodecConfig::codecConfigIsValid(
400     const btav_a2dp_codec_config_t& codec_config) {
401   return (codec_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) &&
402          (codec_config.sample_rate != BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) &&
403          (codec_config.bits_per_sample !=
404           BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) &&
405          (codec_config.channel_mode != BTAV_A2DP_CODEC_CHANNEL_MODE_NONE);
406 }
407 
codecConfig2Str(const btav_a2dp_codec_config_t & codec_config)408 std::string A2dpCodecConfig::codecConfig2Str(
409     const btav_a2dp_codec_config_t& codec_config) {
410   std::string result;
411 
412   if (!codecConfigIsValid(codec_config)) return "Invalid";
413 
414   result.append("Rate=");
415   result.append(codecSampleRate2Str(codec_config.sample_rate));
416   result.append(" Bits=");
417   result.append(codecBitsPerSample2Str(codec_config.bits_per_sample));
418   result.append(" Mode=");
419   result.append(codecChannelMode2Str(codec_config.channel_mode));
420 
421   return result;
422 }
423 
codecSampleRate2Str(btav_a2dp_codec_sample_rate_t codec_sample_rate)424 std::string A2dpCodecConfig::codecSampleRate2Str(
425     btav_a2dp_codec_sample_rate_t codec_sample_rate) {
426   std::string result;
427 
428   if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_44100) {
429     if (!result.empty()) result += "|";
430     result += "44100";
431   }
432   if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_48000) {
433     if (!result.empty()) result += "|";
434     result += "48000";
435   }
436   if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_88200) {
437     if (!result.empty()) result += "|";
438     result += "88200";
439   }
440   if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_96000) {
441     if (!result.empty()) result += "|";
442     result += "96000";
443   }
444   if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_176400) {
445     if (!result.empty()) result += "|";
446     result += "176400";
447   }
448   if (codec_sample_rate & BTAV_A2DP_CODEC_SAMPLE_RATE_192000) {
449     if (!result.empty()) result += "|";
450     result += "192000";
451   }
452   if (result.empty()) {
453     std::stringstream ss;
454     ss << "UnknownSampleRate(0x" << std::hex << codec_sample_rate << ")";
455     ss >> result;
456   }
457 
458   return result;
459 }
460 
codecBitsPerSample2Str(btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample)461 std::string A2dpCodecConfig::codecBitsPerSample2Str(
462     btav_a2dp_codec_bits_per_sample_t codec_bits_per_sample) {
463   std::string result;
464 
465   if (codec_bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16) {
466     if (!result.empty()) result += "|";
467     result += "16";
468   }
469   if (codec_bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24) {
470     if (!result.empty()) result += "|";
471     result += "24";
472   }
473   if (codec_bits_per_sample & BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32) {
474     if (!result.empty()) result += "|";
475     result += "32";
476   }
477   if (result.empty()) {
478     std::stringstream ss;
479     ss << "UnknownBitsPerSample(0x" << std::hex << codec_bits_per_sample << ")";
480     ss >> result;
481   }
482 
483   return result;
484 }
485 
codecChannelMode2Str(btav_a2dp_codec_channel_mode_t codec_channel_mode)486 std::string A2dpCodecConfig::codecChannelMode2Str(
487     btav_a2dp_codec_channel_mode_t codec_channel_mode) {
488   std::string result;
489 
490   if (codec_channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_MONO) {
491     if (!result.empty()) result += "|";
492     result += "MONO";
493   }
494   if (codec_channel_mode & BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO) {
495     if (!result.empty()) result += "|";
496     result += "STEREO";
497   }
498   if (result.empty()) {
499     std::stringstream ss;
500     ss << "UnknownChannelMode(0x" << std::hex << codec_channel_mode << ")";
501     ss >> result;
502   }
503 
504   return result;
505 }
506 
debug_codec_dump(int fd)507 void A2dpCodecConfig::debug_codec_dump(int fd) {
508   std::string result;
509   dprintf(fd, "\nA2DP %s State:\n", name().c_str());
510   dprintf(fd, "  Priority: %d\n", codecPriority());
511   dprintf(fd, "  Encoder interval (ms): %" PRIu64 "\n", encoderIntervalMs());
512   dprintf(fd, "  Effective MTU: %d\n", getEffectiveMtu());
513 
514   result = codecConfig2Str(getCodecConfig());
515   dprintf(fd, "  Config: %s\n", result.c_str());
516 
517   result = codecConfig2Str(getCodecSelectableCapability());
518   dprintf(fd, "  Selectable: %s\n", result.c_str());
519 
520   result = codecConfig2Str(getCodecLocalCapability());
521   dprintf(fd, "  Local capability: %s\n", result.c_str());
522 }
523 
524 //
525 // Compares two codecs |lhs| and |rhs| based on their priority.
526 // Returns true if |lhs| has higher priority (larger priority value).
527 // If |lhs| and |rhs| have same priority, the unique codec index is used
528 // as a tie-breaker: larger codec index value means higher priority.
529 //
compare_codec_priority(const A2dpCodecConfig * lhs,const A2dpCodecConfig * rhs)530 static bool compare_codec_priority(const A2dpCodecConfig* lhs,
531                                    const A2dpCodecConfig* rhs) {
532   if (lhs->codecPriority() > rhs->codecPriority()) return true;
533   if (lhs->codecPriority() < rhs->codecPriority()) return false;
534   return (lhs->codecIndex() > rhs->codecIndex());
535 }
536 
A2dpCodecs(const std::vector<btav_a2dp_codec_config_t> & codec_priorities)537 A2dpCodecs::A2dpCodecs(
538     const std::vector<btav_a2dp_codec_config_t>& codec_priorities)
539     : current_codec_config_(nullptr) {
540   for (auto config : codec_priorities) {
541     codec_priorities_.insert(
542         std::make_pair(config.codec_type, config.codec_priority));
543   }
544 }
545 
~A2dpCodecs()546 A2dpCodecs::~A2dpCodecs() {
547   std::unique_lock<std::recursive_mutex> lock(codec_mutex_);
548   for (const auto& iter : indexed_codecs_) {
549     delete iter.second;
550   }
551   for (const auto& iter : disabled_codecs_) {
552     delete iter.second;
553   }
554   lock.unlock();
555 }
556 
init()557 bool A2dpCodecs::init() {
558   LOG_DEBUG(LOG_TAG, "%s", __func__);
559   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
560   char* tok = NULL;
561   char* tmp_token = NULL;
562   bool offload_codec_support[BTAV_A2DP_CODEC_INDEX_MAX] = {false};
563   char value_sup[PROPERTY_VALUE_MAX], value_dis[PROPERTY_VALUE_MAX];
564 
565   osi_property_get("ro.bluetooth.a2dp_offload.supported", value_sup, "false");
566   osi_property_get("persist.bluetooth.a2dp_offload.disabled", value_dis,
567                    "false");
568   a2dp_offload_status =
569       (strcmp(value_sup, "true") == 0) && (strcmp(value_dis, "false") == 0);
570 
571   if (a2dp_offload_status) {
572     char value_cap[PROPERTY_VALUE_MAX];
573     osi_property_get("persist.bluetooth.a2dp_offload.cap", value_cap, "");
574     tok = strtok_r((char*)value_cap, "-", &tmp_token);
575     while (tok != NULL) {
576       if (strcmp(tok, "sbc") == 0) {
577         LOG_INFO(LOG_TAG, "%s: SBC offload supported", __func__);
578         offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_SBC] = true;
579       } else if (strcmp(tok, "aac") == 0) {
580         LOG_INFO(LOG_TAG, "%s: AAC offload supported", __func__);
581         offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_AAC] = true;
582       } else if (strcmp(tok, "aptx") == 0) {
583         LOG_INFO(LOG_TAG, "%s: APTX offload supported", __func__);
584         offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_APTX] = true;
585       } else if (strcmp(tok, "aptxhd") == 0) {
586         LOG_INFO(LOG_TAG, "%s: APTXHD offload supported", __func__);
587         offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD] = true;
588       } else if (strcmp(tok, "ldac") == 0) {
589         LOG_INFO(LOG_TAG, "%s: LDAC offload supported", __func__);
590         offload_codec_support[BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC] = true;
591       }
592       tok = strtok_r(NULL, "-", &tmp_token);
593     };
594   }
595 
596   for (int i = BTAV_A2DP_CODEC_INDEX_MIN; i < BTAV_A2DP_CODEC_INDEX_MAX; i++) {
597     btav_a2dp_codec_index_t codec_index =
598         static_cast<btav_a2dp_codec_index_t>(i);
599 
600     // Select the codec priority if explicitly configured
601     btav_a2dp_codec_priority_t codec_priority =
602         BTAV_A2DP_CODEC_PRIORITY_DEFAULT;
603     auto cp_iter = codec_priorities_.find(codec_index);
604     if (cp_iter != codec_priorities_.end()) {
605       codec_priority = cp_iter->second;
606     }
607 
608     // In offload mode, disable the codecs based on the property
609     if ((codec_index < BTAV_A2DP_CODEC_INDEX_SOURCE_MAX) &&
610         a2dp_offload_status && (offload_codec_support[i] != true)) {
611       codec_priority = BTAV_A2DP_CODEC_PRIORITY_DISABLED;
612     }
613 
614     A2dpCodecConfig* codec_config =
615         A2dpCodecConfig::createCodec(codec_index, codec_priority);
616     if (codec_config == nullptr) continue;
617 
618     if (codec_priority != BTAV_A2DP_CODEC_PRIORITY_DEFAULT) {
619       LOG_INFO(LOG_TAG, "%s: updated %s codec priority to %d", __func__,
620                codec_config->name().c_str(), codec_priority);
621     }
622 
623     // Test if the codec is disabled
624     if (codec_config->codecPriority() == BTAV_A2DP_CODEC_PRIORITY_DISABLED) {
625       disabled_codecs_.insert(std::make_pair(codec_index, codec_config));
626       continue;
627     }
628 
629     indexed_codecs_.insert(std::make_pair(codec_index, codec_config));
630 
631     if (codec_index < BTAV_A2DP_CODEC_INDEX_SOURCE_MAX) {
632       ordered_source_codecs_.push_back(codec_config);
633       ordered_source_codecs_.sort(compare_codec_priority);
634     } else {
635       ordered_sink_codecs_.push_back(codec_config);
636       ordered_sink_codecs_.sort(compare_codec_priority);
637     }
638   }
639 
640   if (ordered_source_codecs_.empty()) {
641     LOG_ERROR(LOG_TAG, "%s: no Source codecs were initialized", __func__);
642   } else {
643     for (auto iter : ordered_source_codecs_) {
644       LOG_INFO(LOG_TAG, "%s: initialized Source codec %s", __func__,
645                iter->name().c_str());
646     }
647   }
648   if (ordered_sink_codecs_.empty()) {
649     LOG_ERROR(LOG_TAG, "%s: no Sink codecs were initialized", __func__);
650   } else {
651     for (auto iter : ordered_sink_codecs_) {
652       LOG_INFO(LOG_TAG, "%s: initialized Sink codec %s", __func__,
653                iter->name().c_str());
654     }
655   }
656 
657   return (!ordered_source_codecs_.empty() && !ordered_sink_codecs_.empty());
658 }
659 
findSourceCodecConfig(const uint8_t * p_codec_info)660 A2dpCodecConfig* A2dpCodecs::findSourceCodecConfig(
661     const uint8_t* p_codec_info) {
662   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
663   btav_a2dp_codec_index_t codec_index = A2DP_SourceCodecIndex(p_codec_info);
664   if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) return nullptr;
665 
666   auto iter = indexed_codecs_.find(codec_index);
667   if (iter == indexed_codecs_.end()) return nullptr;
668   return iter->second;
669 }
670 
findSinkCodecConfig(const uint8_t * p_codec_info)671 A2dpCodecConfig* A2dpCodecs::findSinkCodecConfig(const uint8_t* p_codec_info) {
672   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
673   btav_a2dp_codec_index_t codec_index = A2DP_SinkCodecIndex(p_codec_info);
674   if (codec_index == BTAV_A2DP_CODEC_INDEX_MAX) return nullptr;
675 
676   auto iter = indexed_codecs_.find(codec_index);
677   if (iter == indexed_codecs_.end()) return nullptr;
678   return iter->second;
679 }
680 
isSupportedCodec(btav_a2dp_codec_index_t codec_index)681 bool A2dpCodecs::isSupportedCodec(btav_a2dp_codec_index_t codec_index) {
682   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
683   return indexed_codecs_.find(codec_index) != indexed_codecs_.end();
684 }
685 
setCodecConfig(const uint8_t * p_peer_codec_info,bool is_capability,uint8_t * p_result_codec_config,bool select_current_codec)686 bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info,
687                                 bool is_capability,
688                                 uint8_t* p_result_codec_config,
689                                 bool select_current_codec) {
690   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
691   A2dpCodecConfig* a2dp_codec_config = findSourceCodecConfig(p_peer_codec_info);
692   if (a2dp_codec_config == nullptr) return false;
693   if (!a2dp_codec_config->setCodecConfig(p_peer_codec_info, is_capability,
694                                          p_result_codec_config)) {
695     return false;
696   }
697   if (select_current_codec) {
698     current_codec_config_ = a2dp_codec_config;
699   }
700   return true;
701 }
702 
setSinkCodecConfig(const uint8_t * p_peer_codec_info,bool is_capability,uint8_t * p_result_codec_config,bool select_current_codec)703 bool A2dpCodecs::setSinkCodecConfig(const uint8_t* p_peer_codec_info,
704                                     bool is_capability,
705                                     uint8_t* p_result_codec_config,
706                                     bool select_current_codec) {
707   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
708   A2dpCodecConfig* a2dp_codec_config = findSinkCodecConfig(p_peer_codec_info);
709   if (a2dp_codec_config == nullptr) return false;
710   if (!a2dp_codec_config->setCodecConfig(p_peer_codec_info, is_capability,
711                                          p_result_codec_config)) {
712     return false;
713   }
714   if (select_current_codec) {
715     current_codec_config_ = a2dp_codec_config;
716   }
717   return true;
718 }
719 
setCodecUserConfig(const btav_a2dp_codec_config_t & codec_user_config,const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,const uint8_t * p_peer_sink_capabilities,uint8_t * p_result_codec_config,bool * p_restart_input,bool * p_restart_output,bool * p_config_updated)720 bool A2dpCodecs::setCodecUserConfig(
721     const btav_a2dp_codec_config_t& codec_user_config,
722     const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
723     const uint8_t* p_peer_sink_capabilities, uint8_t* p_result_codec_config,
724     bool* p_restart_input, bool* p_restart_output, bool* p_config_updated) {
725   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
726   btav_a2dp_codec_config_t codec_audio_config;
727   A2dpCodecConfig* a2dp_codec_config = nullptr;
728   A2dpCodecConfig* last_codec_config = current_codec_config_;
729   *p_restart_input = false;
730   *p_restart_output = false;
731   *p_config_updated = false;
732 
733   LOG_DEBUG(LOG_TAG, "%s: Configuring: %s", __func__,
734             codec_user_config.ToString().c_str());
735 
736   if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) {
737     auto iter = indexed_codecs_.find(codec_user_config.codec_type);
738     if (iter == indexed_codecs_.end()) goto fail;
739     a2dp_codec_config = iter->second;
740   } else {
741     // Update the default codec
742     a2dp_codec_config = current_codec_config_;
743   }
744   if (a2dp_codec_config == nullptr) goto fail;
745 
746   // Reuse the existing codec audio config
747   codec_audio_config = a2dp_codec_config->getCodecAudioConfig();
748   if (!a2dp_codec_config->setCodecUserConfig(
749           codec_user_config, codec_audio_config, p_peer_params,
750           p_peer_sink_capabilities, true, p_result_codec_config,
751           p_restart_input, p_restart_output, p_config_updated)) {
752     goto fail;
753   }
754 
755   // Update the codec priorities, and eventually restart the connection
756   // if a new codec needs to be selected.
757   do {
758     // Update the codec priority
759     btav_a2dp_codec_priority_t old_priority =
760         a2dp_codec_config->codecPriority();
761     btav_a2dp_codec_priority_t new_priority = codec_user_config.codec_priority;
762     a2dp_codec_config->setCodecPriority(new_priority);
763     // Get the actual (recomputed) priority
764     new_priority = a2dp_codec_config->codecPriority();
765 
766     // Check if there was no previous codec
767     if (last_codec_config == nullptr) {
768       current_codec_config_ = a2dp_codec_config;
769       *p_restart_input = true;
770       *p_restart_output = true;
771       break;
772     }
773 
774     // Check if the priority of the current codec was updated
775     if (a2dp_codec_config == last_codec_config) {
776       if (old_priority == new_priority) break;  // No change in priority
777 
778       *p_config_updated = true;
779       if (new_priority < old_priority) {
780         // The priority has become lower - restart the connection to
781         // select a new codec.
782         *p_restart_output = true;
783       }
784       break;
785     }
786 
787     if (new_priority <= old_priority) {
788       // No change in priority, or the priority has become lower.
789       // This wasn't the current codec, so we shouldn't select a new codec.
790       if (*p_restart_input || *p_restart_output ||
791           (old_priority != new_priority)) {
792         *p_config_updated = true;
793       }
794       *p_restart_input = false;
795       *p_restart_output = false;
796       break;
797     }
798 
799     *p_config_updated = true;
800     if (new_priority >= last_codec_config->codecPriority()) {
801       // The new priority is higher than the current codec. Restart the
802       // connection to select a new codec.
803       current_codec_config_ = a2dp_codec_config;
804       last_codec_config->setDefaultCodecPriority();
805       *p_restart_input = true;
806       *p_restart_output = true;
807     }
808   } while (false);
809   ordered_source_codecs_.sort(compare_codec_priority);
810 
811   if (*p_restart_input || *p_restart_output) *p_config_updated = true;
812 
813   LOG_DEBUG(LOG_TAG,
814             "%s: Configured: restart_input = %d restart_output = %d "
815             "config_updated = %d",
816             __func__, *p_restart_input, *p_restart_output, *p_config_updated);
817 
818   return true;
819 
820 fail:
821   current_codec_config_ = last_codec_config;
822   return false;
823 }
824 
setCodecAudioConfig(const btav_a2dp_codec_config_t & codec_audio_config,const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,const uint8_t * p_peer_sink_capabilities,uint8_t * p_result_codec_config,bool * p_restart_output,bool * p_config_updated)825 bool A2dpCodecs::setCodecAudioConfig(
826     const btav_a2dp_codec_config_t& codec_audio_config,
827     const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
828     const uint8_t* p_peer_sink_capabilities, uint8_t* p_result_codec_config,
829     bool* p_restart_output, bool* p_config_updated) {
830   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
831   btav_a2dp_codec_config_t codec_user_config;
832   A2dpCodecConfig* a2dp_codec_config = current_codec_config_;
833   *p_restart_output = false;
834   *p_config_updated = false;
835 
836   if (a2dp_codec_config == nullptr) return false;
837 
838   // Reuse the existing codec user config
839   codec_user_config = a2dp_codec_config->getCodecUserConfig();
840   bool restart_input = false;  // Flag ignored - input was just restarted
841   if (!a2dp_codec_config->setCodecUserConfig(
842           codec_user_config, codec_audio_config, p_peer_params,
843           p_peer_sink_capabilities, true, p_result_codec_config, &restart_input,
844           p_restart_output, p_config_updated)) {
845     return false;
846   }
847 
848   return true;
849 }
850 
setCodecOtaConfig(const uint8_t * p_ota_codec_config,const tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params,uint8_t * p_result_codec_config,bool * p_restart_input,bool * p_restart_output,bool * p_config_updated)851 bool A2dpCodecs::setCodecOtaConfig(
852     const uint8_t* p_ota_codec_config,
853     const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
854     uint8_t* p_result_codec_config, bool* p_restart_input,
855     bool* p_restart_output, bool* p_config_updated) {
856   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
857   btav_a2dp_codec_index_t codec_type;
858   btav_a2dp_codec_config_t codec_user_config;
859   btav_a2dp_codec_config_t codec_audio_config;
860   A2dpCodecConfig* a2dp_codec_config = nullptr;
861   A2dpCodecConfig* last_codec_config = current_codec_config_;
862   *p_restart_input = false;
863   *p_restart_output = false;
864   *p_config_updated = false;
865 
866   // Check whether the current codec config is explicitly configured by
867   // user configuration. If yes, then the OTA codec configuration is ignored.
868   if (current_codec_config_ != nullptr) {
869     codec_user_config = current_codec_config_->getCodecUserConfig();
870     if (!A2dpCodecConfig::isCodecConfigEmpty(codec_user_config)) {
871       LOG_WARN(LOG_TAG,
872                "%s: ignoring peer OTA configuration for codec %s: "
873                "existing user configuration for current codec %s",
874                __func__, A2DP_CodecName(p_ota_codec_config),
875                current_codec_config_->name().c_str());
876       goto fail;
877     }
878   }
879 
880   // Check whether the codec config for the same codec is explicitly configured
881   // by user configuration. If yes, then the OTA codec configuration is
882   // ignored.
883   codec_type = A2DP_SourceCodecIndex(p_ota_codec_config);
884   if (codec_type == BTAV_A2DP_CODEC_INDEX_MAX) {
885     LOG_WARN(LOG_TAG,
886              "%s: ignoring peer OTA codec configuration: "
887              "invalid codec",
888              __func__);
889     goto fail;  // Invalid codec
890   } else {
891     auto iter = indexed_codecs_.find(codec_type);
892     if (iter == indexed_codecs_.end()) {
893       LOG_WARN(LOG_TAG,
894                "%s: cannot find codec configuration for peer OTA codec %s",
895                __func__, A2DP_CodecName(p_ota_codec_config));
896       goto fail;
897     }
898     a2dp_codec_config = iter->second;
899   }
900   if (a2dp_codec_config == nullptr) goto fail;
901   codec_user_config = a2dp_codec_config->getCodecUserConfig();
902   if (!A2dpCodecConfig::isCodecConfigEmpty(codec_user_config)) {
903     LOG_WARN(LOG_TAG,
904              "%s: ignoring peer OTA configuration for codec %s: "
905              "existing user configuration for same codec",
906              __func__, A2DP_CodecName(p_ota_codec_config));
907     goto fail;
908   }
909   current_codec_config_ = a2dp_codec_config;
910 
911   // Reuse the existing codec user config and codec audio config
912   codec_audio_config = a2dp_codec_config->getCodecAudioConfig();
913   if (!a2dp_codec_config->setCodecUserConfig(
914           codec_user_config, codec_audio_config, p_peer_params,
915           p_ota_codec_config, false, p_result_codec_config, p_restart_input,
916           p_restart_output, p_config_updated)) {
917     LOG_WARN(LOG_TAG,
918              "%s: cannot set codec configuration for peer OTA codec %s",
919              __func__, A2DP_CodecName(p_ota_codec_config));
920     goto fail;
921   }
922   CHECK(current_codec_config_ != nullptr);
923 
924   if (*p_restart_input || *p_restart_output) *p_config_updated = true;
925 
926   return true;
927 
928 fail:
929   current_codec_config_ = last_codec_config;
930   return false;
931 }
932 
setPeerSinkCodecCapabilities(const uint8_t * p_peer_codec_capabilities)933 bool A2dpCodecs::setPeerSinkCodecCapabilities(
934     const uint8_t* p_peer_codec_capabilities) {
935   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
936 
937   if (!A2DP_IsPeerSinkCodecValid(p_peer_codec_capabilities)) return false;
938   A2dpCodecConfig* a2dp_codec_config =
939       findSourceCodecConfig(p_peer_codec_capabilities);
940   if (a2dp_codec_config == nullptr) return false;
941   return a2dp_codec_config->setPeerCodecCapabilities(p_peer_codec_capabilities);
942 }
943 
setPeerSourceCodecCapabilities(const uint8_t * p_peer_codec_capabilities)944 bool A2dpCodecs::setPeerSourceCodecCapabilities(
945     const uint8_t* p_peer_codec_capabilities) {
946   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
947 
948   if (!A2DP_IsPeerSourceCodecValid(p_peer_codec_capabilities)) return false;
949   A2dpCodecConfig* a2dp_codec_config =
950       findSinkCodecConfig(p_peer_codec_capabilities);
951   if (a2dp_codec_config == nullptr) return false;
952   return a2dp_codec_config->setPeerCodecCapabilities(p_peer_codec_capabilities);
953 }
954 
getCodecConfigAndCapabilities(btav_a2dp_codec_config_t * p_codec_config,std::vector<btav_a2dp_codec_config_t> * p_codecs_local_capabilities,std::vector<btav_a2dp_codec_config_t> * p_codecs_selectable_capabilities)955 bool A2dpCodecs::getCodecConfigAndCapabilities(
956     btav_a2dp_codec_config_t* p_codec_config,
957     std::vector<btav_a2dp_codec_config_t>* p_codecs_local_capabilities,
958     std::vector<btav_a2dp_codec_config_t>* p_codecs_selectable_capabilities) {
959   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
960 
961   if (current_codec_config_ != nullptr) {
962     *p_codec_config = current_codec_config_->getCodecConfig();
963   } else {
964     btav_a2dp_codec_config_t codec_config;
965     memset(&codec_config, 0, sizeof(codec_config));
966     *p_codec_config = codec_config;
967   }
968 
969   std::vector<btav_a2dp_codec_config_t> codecs_capabilities;
970   for (auto codec : orderedSourceCodecs()) {
971     codecs_capabilities.push_back(codec->getCodecLocalCapability());
972   }
973   *p_codecs_local_capabilities = codecs_capabilities;
974 
975   codecs_capabilities.clear();
976   for (auto codec : orderedSourceCodecs()) {
977     btav_a2dp_codec_config_t codec_capability =
978         codec->getCodecSelectableCapability();
979     // Don't add entries that cannot be used
980     if ((codec_capability.sample_rate == BTAV_A2DP_CODEC_SAMPLE_RATE_NONE) ||
981         (codec_capability.bits_per_sample ==
982          BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE) ||
983         (codec_capability.channel_mode == BTAV_A2DP_CODEC_CHANNEL_MODE_NONE)) {
984       continue;
985     }
986     codecs_capabilities.push_back(codec_capability);
987   }
988   *p_codecs_selectable_capabilities = codecs_capabilities;
989 
990   return true;
991 }
992 
debug_codec_dump(int fd)993 void A2dpCodecs::debug_codec_dump(int fd) {
994   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
995   dprintf(fd, "\nA2DP Codecs State:\n");
996 
997   // Print the current codec name
998   if (current_codec_config_ != nullptr) {
999     dprintf(fd, "  Current Codec: %s\n", current_codec_config_->name().c_str());
1000   } else {
1001     dprintf(fd, "  Current Codec: None\n");
1002   }
1003 
1004   // Print the codec-specific state
1005   for (auto codec_config : ordered_source_codecs_) {
1006     codec_config->debug_codec_dump(fd);
1007   }
1008 }
1009 
A2DP_GetCodecType(const uint8_t * p_codec_info)1010 tA2DP_CODEC_TYPE A2DP_GetCodecType(const uint8_t* p_codec_info) {
1011   return (tA2DP_CODEC_TYPE)(p_codec_info[AVDT_CODEC_TYPE_INDEX]);
1012 }
1013 
A2DP_IsSourceCodecValid(const uint8_t * p_codec_info)1014 bool A2DP_IsSourceCodecValid(const uint8_t* p_codec_info) {
1015   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1016 
1017   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1018 
1019   switch (codec_type) {
1020     case A2DP_MEDIA_CT_SBC:
1021       return A2DP_IsSourceCodecValidSbc(p_codec_info);
1022     case A2DP_MEDIA_CT_AAC:
1023       return A2DP_IsSourceCodecValidAac(p_codec_info);
1024     case A2DP_MEDIA_CT_NON_A2DP:
1025       return A2DP_IsVendorSourceCodecValid(p_codec_info);
1026     default:
1027       break;
1028   }
1029 
1030   return false;
1031 }
1032 
A2DP_IsSinkCodecValid(const uint8_t * p_codec_info)1033 bool A2DP_IsSinkCodecValid(const uint8_t* p_codec_info) {
1034   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1035 
1036   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1037 
1038   switch (codec_type) {
1039     case A2DP_MEDIA_CT_SBC:
1040       return A2DP_IsSinkCodecValidSbc(p_codec_info);
1041     case A2DP_MEDIA_CT_AAC:
1042       return A2DP_IsSinkCodecValidAac(p_codec_info);
1043     case A2DP_MEDIA_CT_NON_A2DP:
1044       return A2DP_IsVendorSinkCodecValid(p_codec_info);
1045     default:
1046       break;
1047   }
1048 
1049   return false;
1050 }
1051 
A2DP_IsPeerSourceCodecValid(const uint8_t * p_codec_info)1052 bool A2DP_IsPeerSourceCodecValid(const uint8_t* p_codec_info) {
1053   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1054 
1055   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1056 
1057   switch (codec_type) {
1058     case A2DP_MEDIA_CT_SBC:
1059       return A2DP_IsPeerSourceCodecValidSbc(p_codec_info);
1060     case A2DP_MEDIA_CT_AAC:
1061       return A2DP_IsPeerSourceCodecValidAac(p_codec_info);
1062     case A2DP_MEDIA_CT_NON_A2DP:
1063       return A2DP_IsVendorPeerSourceCodecValid(p_codec_info);
1064     default:
1065       break;
1066   }
1067 
1068   return false;
1069 }
1070 
A2DP_IsPeerSinkCodecValid(const uint8_t * p_codec_info)1071 bool A2DP_IsPeerSinkCodecValid(const uint8_t* p_codec_info) {
1072   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1073 
1074   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1075 
1076   switch (codec_type) {
1077     case A2DP_MEDIA_CT_SBC:
1078       return A2DP_IsPeerSinkCodecValidSbc(p_codec_info);
1079     case A2DP_MEDIA_CT_AAC:
1080       return A2DP_IsPeerSinkCodecValidAac(p_codec_info);
1081     case A2DP_MEDIA_CT_NON_A2DP:
1082       return A2DP_IsVendorPeerSinkCodecValid(p_codec_info);
1083     default:
1084       break;
1085   }
1086 
1087   return false;
1088 }
1089 
A2DP_IsSinkCodecSupported(const uint8_t * p_codec_info)1090 bool A2DP_IsSinkCodecSupported(const uint8_t* p_codec_info) {
1091   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1092 
1093   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1094 
1095   switch (codec_type) {
1096     case A2DP_MEDIA_CT_SBC:
1097       return A2DP_IsSinkCodecSupportedSbc(p_codec_info);
1098     case A2DP_MEDIA_CT_AAC:
1099       return A2DP_IsSinkCodecSupportedAac(p_codec_info);
1100     case A2DP_MEDIA_CT_NON_A2DP:
1101       return A2DP_IsVendorSinkCodecSupported(p_codec_info);
1102     default:
1103       break;
1104   }
1105 
1106   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1107   return false;
1108 }
1109 
A2DP_IsPeerSourceCodecSupported(const uint8_t * p_codec_info)1110 bool A2DP_IsPeerSourceCodecSupported(const uint8_t* p_codec_info) {
1111   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1112 
1113   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1114 
1115   switch (codec_type) {
1116     case A2DP_MEDIA_CT_SBC:
1117       return A2DP_IsPeerSourceCodecSupportedSbc(p_codec_info);
1118     case A2DP_MEDIA_CT_AAC:
1119       return A2DP_IsPeerSourceCodecSupportedAac(p_codec_info);
1120     case A2DP_MEDIA_CT_NON_A2DP:
1121       return A2DP_IsVendorPeerSourceCodecSupported(p_codec_info);
1122     default:
1123       break;
1124   }
1125 
1126   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1127   return false;
1128 }
1129 
A2DP_InitDefaultCodec(uint8_t * p_codec_info)1130 void A2DP_InitDefaultCodec(uint8_t* p_codec_info) {
1131   A2DP_InitDefaultCodecSbc(p_codec_info);
1132 }
1133 
A2DP_UsesRtpHeader(bool content_protection_enabled,const uint8_t * p_codec_info)1134 bool A2DP_UsesRtpHeader(bool content_protection_enabled,
1135                         const uint8_t* p_codec_info) {
1136   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1137 
1138   if (codec_type != A2DP_MEDIA_CT_NON_A2DP) return true;
1139 
1140   return A2DP_VendorUsesRtpHeader(content_protection_enabled, p_codec_info);
1141 }
1142 
A2DP_GetMediaType(const uint8_t * p_codec_info)1143 uint8_t A2DP_GetMediaType(const uint8_t* p_codec_info) {
1144   uint8_t media_type = (p_codec_info[A2DP_MEDIA_TYPE_OFFSET] >> 4) & 0x0f;
1145   return media_type;
1146 }
1147 
A2DP_CodecName(const uint8_t * p_codec_info)1148 const char* A2DP_CodecName(const uint8_t* p_codec_info) {
1149   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1150 
1151   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1152 
1153   switch (codec_type) {
1154     case A2DP_MEDIA_CT_SBC:
1155       return A2DP_CodecNameSbc(p_codec_info);
1156     case A2DP_MEDIA_CT_AAC:
1157       return A2DP_CodecNameAac(p_codec_info);
1158     case A2DP_MEDIA_CT_NON_A2DP:
1159       return A2DP_VendorCodecName(p_codec_info);
1160     default:
1161       break;
1162   }
1163 
1164   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1165   return "UNKNOWN CODEC";
1166 }
1167 
A2DP_CodecTypeEquals(const uint8_t * p_codec_info_a,const uint8_t * p_codec_info_b)1168 bool A2DP_CodecTypeEquals(const uint8_t* p_codec_info_a,
1169                           const uint8_t* p_codec_info_b) {
1170   tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a);
1171   tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b);
1172 
1173   if (codec_type_a != codec_type_b) return false;
1174 
1175   switch (codec_type_a) {
1176     case A2DP_MEDIA_CT_SBC:
1177       return A2DP_CodecTypeEqualsSbc(p_codec_info_a, p_codec_info_b);
1178     case A2DP_MEDIA_CT_AAC:
1179       return A2DP_CodecTypeEqualsAac(p_codec_info_a, p_codec_info_b);
1180     case A2DP_MEDIA_CT_NON_A2DP:
1181       return A2DP_VendorCodecTypeEquals(p_codec_info_a, p_codec_info_b);
1182     default:
1183       break;
1184   }
1185 
1186   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type_a);
1187   return false;
1188 }
1189 
A2DP_CodecEquals(const uint8_t * p_codec_info_a,const uint8_t * p_codec_info_b)1190 bool A2DP_CodecEquals(const uint8_t* p_codec_info_a,
1191                       const uint8_t* p_codec_info_b) {
1192   tA2DP_CODEC_TYPE codec_type_a = A2DP_GetCodecType(p_codec_info_a);
1193   tA2DP_CODEC_TYPE codec_type_b = A2DP_GetCodecType(p_codec_info_b);
1194 
1195   if (codec_type_a != codec_type_b) return false;
1196 
1197   switch (codec_type_a) {
1198     case A2DP_MEDIA_CT_SBC:
1199       return A2DP_CodecEqualsSbc(p_codec_info_a, p_codec_info_b);
1200     case A2DP_MEDIA_CT_AAC:
1201       return A2DP_CodecEqualsAac(p_codec_info_a, p_codec_info_b);
1202     case A2DP_MEDIA_CT_NON_A2DP:
1203       return A2DP_VendorCodecEquals(p_codec_info_a, p_codec_info_b);
1204     default:
1205       break;
1206   }
1207 
1208   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type_a);
1209   return false;
1210 }
1211 
A2DP_GetTrackSampleRate(const uint8_t * p_codec_info)1212 int A2DP_GetTrackSampleRate(const uint8_t* p_codec_info) {
1213   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1214 
1215   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1216 
1217   switch (codec_type) {
1218     case A2DP_MEDIA_CT_SBC:
1219       return A2DP_GetTrackSampleRateSbc(p_codec_info);
1220     case A2DP_MEDIA_CT_AAC:
1221       return A2DP_GetTrackSampleRateAac(p_codec_info);
1222     case A2DP_MEDIA_CT_NON_A2DP:
1223       return A2DP_VendorGetTrackSampleRate(p_codec_info);
1224     default:
1225       break;
1226   }
1227 
1228   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1229   return -1;
1230 }
1231 
A2DP_GetTrackBitsPerSample(const uint8_t * p_codec_info)1232 int A2DP_GetTrackBitsPerSample(const uint8_t* p_codec_info) {
1233   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1234 
1235   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1236 
1237   switch (codec_type) {
1238     case A2DP_MEDIA_CT_SBC:
1239       return A2DP_GetTrackBitsPerSampleSbc(p_codec_info);
1240     case A2DP_MEDIA_CT_AAC:
1241       return A2DP_GetTrackBitsPerSampleAac(p_codec_info);
1242     case A2DP_MEDIA_CT_NON_A2DP:
1243       return A2DP_VendorGetTrackBitsPerSample(p_codec_info);
1244     default:
1245       break;
1246   }
1247 
1248   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1249   return -1;
1250 }
1251 
A2DP_GetTrackChannelCount(const uint8_t * p_codec_info)1252 int A2DP_GetTrackChannelCount(const uint8_t* p_codec_info) {
1253   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1254 
1255   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1256 
1257   switch (codec_type) {
1258     case A2DP_MEDIA_CT_SBC:
1259       return A2DP_GetTrackChannelCountSbc(p_codec_info);
1260     case A2DP_MEDIA_CT_AAC:
1261       return A2DP_GetTrackChannelCountAac(p_codec_info);
1262     case A2DP_MEDIA_CT_NON_A2DP:
1263       return A2DP_VendorGetTrackChannelCount(p_codec_info);
1264     default:
1265       break;
1266   }
1267 
1268   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1269   return -1;
1270 }
1271 
A2DP_GetSinkTrackChannelType(const uint8_t * p_codec_info)1272 int A2DP_GetSinkTrackChannelType(const uint8_t* p_codec_info) {
1273   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1274 
1275   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1276 
1277   switch (codec_type) {
1278     case A2DP_MEDIA_CT_SBC:
1279       return A2DP_GetSinkTrackChannelTypeSbc(p_codec_info);
1280     case A2DP_MEDIA_CT_AAC:
1281       return A2DP_GetSinkTrackChannelTypeAac(p_codec_info);
1282     case A2DP_MEDIA_CT_NON_A2DP:
1283       return A2DP_VendorGetSinkTrackChannelType(p_codec_info);
1284     default:
1285       break;
1286   }
1287 
1288   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1289   return -1;
1290 }
1291 
A2DP_GetPacketTimestamp(const uint8_t * p_codec_info,const uint8_t * p_data,uint32_t * p_timestamp)1292 bool A2DP_GetPacketTimestamp(const uint8_t* p_codec_info, const uint8_t* p_data,
1293                              uint32_t* p_timestamp) {
1294   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1295 
1296   switch (codec_type) {
1297     case A2DP_MEDIA_CT_SBC:
1298       return A2DP_GetPacketTimestampSbc(p_codec_info, p_data, p_timestamp);
1299     case A2DP_MEDIA_CT_AAC:
1300       return A2DP_GetPacketTimestampAac(p_codec_info, p_data, p_timestamp);
1301     case A2DP_MEDIA_CT_NON_A2DP:
1302       return A2DP_VendorGetPacketTimestamp(p_codec_info, p_data, p_timestamp);
1303     default:
1304       break;
1305   }
1306 
1307   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1308   return false;
1309 }
1310 
A2DP_BuildCodecHeader(const uint8_t * p_codec_info,BT_HDR * p_buf,uint16_t frames_per_packet)1311 bool A2DP_BuildCodecHeader(const uint8_t* p_codec_info, BT_HDR* p_buf,
1312                            uint16_t frames_per_packet) {
1313   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1314 
1315   switch (codec_type) {
1316     case A2DP_MEDIA_CT_SBC:
1317       return A2DP_BuildCodecHeaderSbc(p_codec_info, p_buf, frames_per_packet);
1318     case A2DP_MEDIA_CT_AAC:
1319       return A2DP_BuildCodecHeaderAac(p_codec_info, p_buf, frames_per_packet);
1320     case A2DP_MEDIA_CT_NON_A2DP:
1321       return A2DP_VendorBuildCodecHeader(p_codec_info, p_buf,
1322                                          frames_per_packet);
1323     default:
1324       break;
1325   }
1326 
1327   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1328   return false;
1329 }
1330 
A2DP_GetEncoderInterface(const uint8_t * p_codec_info)1331 const tA2DP_ENCODER_INTERFACE* A2DP_GetEncoderInterface(
1332     const uint8_t* p_codec_info) {
1333   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1334 
1335   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1336 
1337   switch (codec_type) {
1338     case A2DP_MEDIA_CT_SBC:
1339       return A2DP_GetEncoderInterfaceSbc(p_codec_info);
1340     case A2DP_MEDIA_CT_AAC:
1341       return A2DP_GetEncoderInterfaceAac(p_codec_info);
1342     case A2DP_MEDIA_CT_NON_A2DP:
1343       return A2DP_VendorGetEncoderInterface(p_codec_info);
1344     default:
1345       break;
1346   }
1347 
1348   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1349   return NULL;
1350 }
1351 
A2DP_GetDecoderInterface(const uint8_t * p_codec_info)1352 const tA2DP_DECODER_INTERFACE* A2DP_GetDecoderInterface(
1353     const uint8_t* p_codec_info) {
1354   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1355 
1356   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1357 
1358   switch (codec_type) {
1359     case A2DP_MEDIA_CT_SBC:
1360       return A2DP_GetDecoderInterfaceSbc(p_codec_info);
1361     case A2DP_MEDIA_CT_AAC:
1362       return A2DP_GetDecoderInterfaceAac(p_codec_info);
1363     case A2DP_MEDIA_CT_NON_A2DP:
1364       return A2DP_VendorGetDecoderInterface(p_codec_info);
1365     default:
1366       break;
1367   }
1368 
1369   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1370   return NULL;
1371 }
1372 
A2DP_AdjustCodec(uint8_t * p_codec_info)1373 bool A2DP_AdjustCodec(uint8_t* p_codec_info) {
1374   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1375 
1376   switch (codec_type) {
1377     case A2DP_MEDIA_CT_SBC:
1378       return A2DP_AdjustCodecSbc(p_codec_info);
1379     case A2DP_MEDIA_CT_AAC:
1380       return A2DP_AdjustCodecAac(p_codec_info);
1381     case A2DP_MEDIA_CT_NON_A2DP:
1382       return A2DP_VendorAdjustCodec(p_codec_info);
1383     default:
1384       break;
1385   }
1386 
1387   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1388   return false;
1389 }
1390 
A2DP_SourceCodecIndex(const uint8_t * p_codec_info)1391 btav_a2dp_codec_index_t A2DP_SourceCodecIndex(const uint8_t* p_codec_info) {
1392   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1393 
1394   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1395 
1396   switch (codec_type) {
1397     case A2DP_MEDIA_CT_SBC:
1398       return A2DP_SourceCodecIndexSbc(p_codec_info);
1399     case A2DP_MEDIA_CT_AAC:
1400       return A2DP_SourceCodecIndexAac(p_codec_info);
1401     case A2DP_MEDIA_CT_NON_A2DP:
1402       return A2DP_VendorSourceCodecIndex(p_codec_info);
1403     default:
1404       break;
1405   }
1406 
1407   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1408   return BTAV_A2DP_CODEC_INDEX_MAX;
1409 }
1410 
A2DP_SinkCodecIndex(const uint8_t * p_codec_info)1411 btav_a2dp_codec_index_t A2DP_SinkCodecIndex(const uint8_t* p_codec_info) {
1412   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1413 
1414   LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
1415 
1416   switch (codec_type) {
1417     case A2DP_MEDIA_CT_SBC:
1418       return A2DP_SinkCodecIndexSbc(p_codec_info);
1419     case A2DP_MEDIA_CT_AAC:
1420       return A2DP_SinkCodecIndexAac(p_codec_info);
1421     case A2DP_MEDIA_CT_NON_A2DP:
1422       return A2DP_VendorSinkCodecIndex(p_codec_info);
1423     default:
1424       break;
1425   }
1426 
1427   LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
1428   return BTAV_A2DP_CODEC_INDEX_MAX;
1429 }
1430 
A2DP_CodecIndexStr(btav_a2dp_codec_index_t codec_index)1431 const char* A2DP_CodecIndexStr(btav_a2dp_codec_index_t codec_index) {
1432   switch (codec_index) {
1433     case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
1434       return A2DP_CodecIndexStrSbc();
1435     case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
1436       return A2DP_CodecIndexStrSbcSink();
1437     case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
1438       return A2DP_CodecIndexStrAac();
1439     case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
1440       return A2DP_CodecIndexStrAacSink();
1441     default:
1442       break;
1443   }
1444 
1445   if (codec_index < BTAV_A2DP_CODEC_INDEX_MAX)
1446     return A2DP_VendorCodecIndexStr(codec_index);
1447 
1448   return "UNKNOWN CODEC INDEX";
1449 }
1450 
A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,AvdtpSepConfig * p_cfg)1451 bool A2DP_InitCodecConfig(btav_a2dp_codec_index_t codec_index,
1452                           AvdtpSepConfig* p_cfg) {
1453   LOG_VERBOSE(LOG_TAG, "%s: codec %s", __func__,
1454               A2DP_CodecIndexStr(codec_index));
1455 
1456   /* Default: no content protection info */
1457   p_cfg->num_protect = 0;
1458   p_cfg->protect_info[0] = 0;
1459 
1460   switch (codec_index) {
1461     case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
1462       return A2DP_InitCodecConfigSbc(p_cfg);
1463     case BTAV_A2DP_CODEC_INDEX_SINK_SBC:
1464       return A2DP_InitCodecConfigSbcSink(p_cfg);
1465     case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
1466       return A2DP_InitCodecConfigAac(p_cfg);
1467     case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
1468       return A2DP_InitCodecConfigAacSink(p_cfg);
1469     default:
1470       break;
1471   }
1472 
1473   if (codec_index < BTAV_A2DP_CODEC_INDEX_MAX)
1474     return A2DP_VendorInitCodecConfig(codec_index, p_cfg);
1475 
1476   return false;
1477 }
1478 
A2DP_CodecInfoString(const uint8_t * p_codec_info)1479 std::string A2DP_CodecInfoString(const uint8_t* p_codec_info) {
1480   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
1481 
1482   switch (codec_type) {
1483     case A2DP_MEDIA_CT_SBC:
1484       return A2DP_CodecInfoStringSbc(p_codec_info);
1485     case A2DP_MEDIA_CT_AAC:
1486       return A2DP_CodecInfoStringAac(p_codec_info);
1487     case A2DP_MEDIA_CT_NON_A2DP:
1488       return A2DP_VendorCodecInfoString(p_codec_info);
1489     default:
1490       break;
1491   }
1492 
1493   return "Unsupported codec type: " + loghex(codec_type);
1494 }
1495