1/****************************************************************************** 2 * 3 * Copyright (C) 2004-2012 Broadcom Corporation 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19/****************************************************************************** 20 * 21 * This is the advanced audio/video call-out function implementation for 22 * BTIF. 23 * 24 ******************************************************************************/ 25 26#include "bta_av_co.h" 27#include <base/logging.h> 28#include <string.h> 29#include "a2dp_api.h" 30#include "a2dp_sbc.h" 31#include "bt_target.h" 32#include "bta_av_api.h" 33#include "bta_av_ci.h" 34#include "bta_sys.h" 35 36#include "btif_av.h" 37#include "btif_av_co.h" 38#include "btif_util.h" 39#include "osi/include/mutex.h" 40#include "osi/include/osi.h" 41 42/***************************************************************************** 43 ** Constants 44 *****************************************************************************/ 45 46/* Macro to retrieve the number of elements in a statically allocated array */ 47#define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a) / sizeof((__a)[0])) 48 49/* Macro to convert audio handle to index and vice versa */ 50#define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1) 51#define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO) 52 53/* SCMS-T protect info */ 54const uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00}; 55 56/***************************************************************************** 57 * Local data 58 ****************************************************************************/ 59typedef struct { 60 uint8_t sep_info_idx; /* local SEP index (in BTA tables) */ 61 uint8_t seid; /* peer SEP index (in peer tables) */ 62 uint8_t codec_caps[AVDT_CODEC_SIZE]; /* peer SEP codec capabilities */ 63 uint8_t num_protect; /* peer SEP number of CP elements */ 64 uint8_t protect_info[AVDT_CP_INFO_LEN]; /* peer SEP content protection info */ 65} tBTA_AV_CO_SINK; 66 67typedef struct { 68 RawAddress addr; /* address of audio/video peer */ 69 tBTA_AV_CO_SINK 70 sinks[BTAV_A2DP_CODEC_INDEX_MAX]; /* array of supported sinks */ 71 tBTA_AV_CO_SINK srcs[BTAV_A2DP_CODEC_INDEX_MAX]; /* array of supported srcs */ 72 uint8_t num_sinks; /* total number of sinks at peer */ 73 uint8_t num_srcs; /* total number of srcs at peer */ 74 uint8_t num_seps; /* total number of seids at peer */ 75 uint8_t num_rx_sinks; /* number of received sinks */ 76 uint8_t num_rx_srcs; /* number of received srcs */ 77 uint8_t num_sup_sinks; /* number of supported sinks in the sinks array */ 78 uint8_t num_sup_srcs; /* number of supported srcs in the srcs array */ 79 const tBTA_AV_CO_SINK* p_sink; /* currently selected sink */ 80 const tBTA_AV_CO_SINK* p_src; /* currently selected src */ 81 uint8_t codec_config[AVDT_CODEC_SIZE]; /* current codec configuration */ 82 bool cp_active; /* current CP configuration */ 83 bool acp; /* acceptor */ 84 bool reconfig_needed; /* reconfiguration is needed */ 85 bool opened; /* opened */ 86 uint16_t mtu; /* maximum transmit unit size */ 87 uint16_t uuid_to_connect; /* uuid of peer device */ 88 tBTA_AV_HNDL handle; /* handle to use */ 89} tBTA_AV_CO_PEER; 90 91typedef struct { 92 bool active; 93 uint8_t flag; 94} tBTA_AV_CO_CP; 95 96class BtaAvCoCb { 97 public: 98 BtaAvCoCb() : codecs(nullptr) { reset(); } 99 100 /* Connected peer information */ 101 tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS]; 102 /* Current codec configuration - access to this variable must be protected */ 103 uint8_t codec_config[AVDT_CODEC_SIZE]; 104 A2dpCodecs* codecs; /* Locally supported codecs */ 105 tBTA_AV_CO_CP cp; 106 107 void reset() { 108 delete codecs; 109 codecs = nullptr; 110 // TODO: Ugly leftover reset from the original C code. Should go away once 111 // the rest of the code in this file migrates to C++. 112 memset(peers, 0, sizeof(peers)); 113 memset(codec_config, 0, sizeof(codec_config)); 114 memset(&cp, 0, sizeof(cp)); 115 116 // Initialize the handles 117 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers); i++) { 118 tBTA_AV_CO_PEER* p_peer = &peers[i]; 119 p_peer->handle = BTA_AV_CO_AUDIO_INDX_TO_HNDL(i); 120 } 121 } 122}; 123 124/* Control block instance */ 125static BtaAvCoCb bta_av_co_cb; 126 127static bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info); 128static bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect, 129 const uint8_t* p_protect_info); 130static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( 131 const tBTA_AV_CO_PEER* p_peer); 132static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer); 133static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( 134 A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer); 135static bool bta_av_co_audio_update_selectable_codec( 136 A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer); 137static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer, 138 const uint8_t* new_codec_config, 139 uint8_t num_protect, 140 const uint8_t* p_protect_info); 141static bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer, 142 const uint8_t* p_ota_codec_config, 143 uint8_t num_protect, 144 const uint8_t* p_protect_info, 145 bool* p_restart_output); 146 147/******************************************************************************* 148 ** 149 ** Function bta_av_co_cp_get_flag 150 ** 151 ** Description Get content protection flag 152 ** AVDT_CP_SCMS_COPY_NEVER 153 ** AVDT_CP_SCMS_COPY_ONCE 154 ** AVDT_CP_SCMS_COPY_FREE 155 ** 156 ** Returns The current flag value 157 ** 158 ******************************************************************************/ 159static uint8_t bta_av_co_cp_get_flag(void) { return bta_av_co_cb.cp.flag; } 160 161/******************************************************************************* 162 ** 163 ** Function bta_av_co_cp_set_flag 164 ** 165 ** Description Set content protection flag 166 ** AVDT_CP_SCMS_COPY_NEVER 167 ** AVDT_CP_SCMS_COPY_ONCE 168 ** AVDT_CP_SCMS_COPY_FREE 169 ** 170 ** Returns true if setting the SCMS flag is supported else false 171 ** 172 ******************************************************************************/ 173static bool bta_av_co_cp_set_flag(uint8_t cp_flag) { 174 APPL_TRACE_DEBUG("%s: cp_flag = %d", __func__, cp_flag); 175 176#if (BTA_AV_CO_CP_SCMS_T == TRUE) 177#else 178 if (cp_flag != AVDT_CP_SCMS_COPY_FREE) { 179 return false; 180 } 181#endif 182 bta_av_co_cb.cp.flag = cp_flag; 183 return true; 184} 185 186/******************************************************************************* 187 ** 188 ** Function bta_av_co_get_peer 189 ** 190 ** Description find the peer entry for a given handle 191 ** 192 ** Returns the control block 193 ** 194 ******************************************************************************/ 195static tBTA_AV_CO_PEER* bta_av_co_get_peer(tBTA_AV_HNDL hndl) { 196 uint8_t index; 197 198 index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl); 199 200 APPL_TRACE_DEBUG("%s: handle = %d index = %d", __func__, hndl, index); 201 202 /* Sanity check */ 203 if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers)) { 204 APPL_TRACE_ERROR("%s: peer index out of bounds: %d", __func__, index); 205 return NULL; 206 } 207 208 return &bta_av_co_cb.peers[index]; 209} 210 211/******************************************************************************* 212 ** 213 ** Function bta_av_co_audio_init 214 ** 215 ** Description This callout function is executed by AV when it is 216 ** started by calling BTA_AvRegister(). This function can be 217 ** used by the phone to initialize audio paths or for other 218 ** initialization purposes. 219 ** 220 ** 221 ** Returns Stream codec and content protection capabilities info. 222 ** 223 ******************************************************************************/ 224bool bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index, 225 tAVDT_CFG* p_cfg) { 226 return A2DP_InitCodecConfig(codec_index, p_cfg); 227} 228 229/******************************************************************************* 230 ** 231 ** Function bta_av_co_audio_disc_res 232 ** 233 ** Description This callout function is executed by AV to report the 234 ** number of stream end points (SEP) were found during the 235 ** AVDT stream discovery process. 236 ** 237 ** 238 ** Returns void. 239 ** 240 ******************************************************************************/ 241void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps, 242 uint8_t num_sink, uint8_t num_src, 243 const RawAddress& addr, uint16_t uuid_local) { 244 tBTA_AV_CO_PEER* p_peer; 245 246 APPL_TRACE_DEBUG("%s: h:x%x num_seps:%d num_sink:%d num_src:%d", __func__, 247 hndl, num_seps, num_sink, num_src); 248 249 /* Find the peer info */ 250 p_peer = bta_av_co_get_peer(hndl); 251 if (p_peer == NULL) { 252 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 253 return; 254 } 255 256 /* Sanity check : this should never happen */ 257 if (p_peer->opened) { 258 APPL_TRACE_ERROR("%s: peer already opened", __func__); 259 } 260 261 /* Copy the discovery results */ 262 p_peer->addr = addr; 263 p_peer->num_sinks = num_sink; 264 p_peer->num_srcs = num_src; 265 p_peer->num_seps = num_seps; 266 p_peer->num_rx_sinks = 0; 267 p_peer->num_rx_srcs = 0; 268 p_peer->num_sup_sinks = 0; 269 if (uuid_local == UUID_SERVCLASS_AUDIO_SINK) 270 p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE; 271 else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE) 272 p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK; 273} 274 275/******************************************************************************* 276 ** 277 ** Function bta_av_audio_sink_getconfig 278 ** 279 ** Description This callout function is executed by AV to retrieve the 280 ** desired codec and content protection configuration for the 281 ** A2DP Sink audio stream in Initiator. 282 ** 283 ** 284 ** Returns Pass or Fail for current getconfig. 285 ** 286 ******************************************************************************/ 287static tA2DP_STATUS bta_av_audio_sink_getconfig( 288 tBTA_AV_HNDL hndl, uint8_t* p_codec_info, uint8_t* p_sep_info_idx, 289 uint8_t seid, uint8_t* p_num_protect, uint8_t* p_protect_info) { 290 tA2DP_STATUS result = A2DP_FAIL; 291 tBTA_AV_CO_PEER* p_peer; 292 293 APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl, 294 A2DP_CodecName(p_codec_info), seid); 295 APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x", 296 __func__, *p_num_protect, p_protect_info[0], 297 p_protect_info[1], p_protect_info[2]); 298 299 /* Retrieve the peer info */ 300 p_peer = bta_av_co_get_peer(hndl); 301 if (p_peer == NULL) { 302 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 303 return A2DP_FAIL; 304 } 305 306 APPL_TRACE_DEBUG("%s: peer(o=%d,n_sinks=%d,n_rx_sinks=%d,n_sup_sinks=%d)", 307 __func__, p_peer->opened, p_peer->num_srcs, 308 p_peer->num_rx_srcs, p_peer->num_sup_srcs); 309 310 p_peer->num_rx_srcs++; 311 312 /* Check the peer's SOURCE codec */ 313 if (A2DP_IsPeerSourceCodecValid(p_codec_info)) { 314 /* If there is room for a new one */ 315 if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)) { 316 tBTA_AV_CO_SINK* p_src = &p_peer->srcs[p_peer->num_sup_srcs++]; 317 318 APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__, 319 p_codec_info[1], p_codec_info[2], p_codec_info[3], 320 p_codec_info[4], p_codec_info[5], p_codec_info[6]); 321 322 memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE); 323 p_src->sep_info_idx = *p_sep_info_idx; 324 p_src->seid = seid; 325 p_src->num_protect = *p_num_protect; 326 memcpy(p_src->protect_info, p_protect_info, AVDT_CP_INFO_LEN); 327 } else { 328 APPL_TRACE_ERROR("%s: no more room for SRC info", __func__); 329 } 330 } 331 332 /* If last SINK get capabilities or all supported codec caps retrieved */ 333 if ((p_peer->num_rx_srcs == p_peer->num_srcs) || 334 (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))) { 335 APPL_TRACE_DEBUG("%s: last SRC reached", __func__); 336 337 /* Protect access to bta_av_co_cb.codec_config */ 338 mutex_global_lock(); 339 340 /* Find a src that matches the codec config */ 341 const tBTA_AV_CO_SINK* p_src = 342 bta_av_co_find_peer_src_supports_codec(p_peer); 343 if (p_src != NULL) { 344 uint8_t pref_config[AVDT_CODEC_SIZE]; 345 APPL_TRACE_DEBUG("%s: codec supported", __func__); 346 347 /* Build the codec configuration for this sink */ 348 /* Save the new configuration */ 349 p_peer->p_src = p_src; 350 /* get preferred config from src_caps */ 351 if (A2DP_BuildSrc2SinkConfig(p_src->codec_caps, pref_config) != 352 A2DP_SUCCESS) { 353 mutex_global_unlock(); 354 return A2DP_FAIL; 355 } 356 memcpy(p_peer->codec_config, pref_config, AVDT_CODEC_SIZE); 357 358 APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__, 359 p_peer->codec_config[1], p_peer->codec_config[2], 360 p_peer->codec_config[3], p_peer->codec_config[4], 361 p_peer->codec_config[5], p_peer->codec_config[6]); 362 /* By default, no content protection */ 363 *p_num_protect = 0; 364 365#if (BTA_AV_CO_CP_SCMS_T == TRUE) 366 p_peer->cp_active = false; 367 bta_av_co_cb.cp.active = false; 368#endif 369 370 *p_sep_info_idx = p_src->sep_info_idx; 371 memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE); 372 result = A2DP_SUCCESS; 373 } 374 /* Protect access to bta_av_co_cb.codec_config */ 375 mutex_global_unlock(); 376 } 377 return result; 378} 379/******************************************************************************* 380 ** 381 ** Function bta_av_co_audio_getconfig 382 ** 383 ** Description This callout function is executed by AV to retrieve the 384 ** desired codec and content protection configuration for the 385 ** audio stream. 386 ** 387 ** 388 ** Returns Stream codec and content protection configuration info. 389 ** 390 ******************************************************************************/ 391tA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info, 392 uint8_t* p_sep_info_idx, uint8_t seid, 393 uint8_t* p_num_protect, 394 uint8_t* p_protect_info) { 395 tBTA_AV_CO_PEER* p_peer; 396 397 APPL_TRACE_DEBUG("%s", __func__); 398 A2DP_DumpCodecInfo(p_codec_info); 399 400 /* Retrieve the peer info */ 401 p_peer = bta_av_co_get_peer(hndl); 402 if (p_peer == NULL) { 403 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 404 return A2DP_FAIL; 405 } 406 407 if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE) { 408 return bta_av_audio_sink_getconfig(hndl, p_codec_info, p_sep_info_idx, seid, 409 p_num_protect, p_protect_info); 410 } 411 APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl, 412 A2DP_CodecName(p_codec_info), seid); 413 APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x", 414 __func__, *p_num_protect, p_protect_info[0], 415 p_protect_info[1], p_protect_info[2]); 416 APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)", 417 __func__, p_peer->opened, p_peer->num_sinks, 418 p_peer->num_rx_sinks, p_peer->num_sup_sinks); 419 420 p_peer->num_rx_sinks++; 421 422 /* Check the peer's SINK codec */ 423 if (A2DP_IsPeerSinkCodecValid(p_codec_info)) { 424 /* If there is room for a new one */ 425 if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) { 426 tBTA_AV_CO_SINK* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++]; 427 428 APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__, 429 p_codec_info[1], p_codec_info[2], p_codec_info[3], 430 p_codec_info[4], p_codec_info[5], p_codec_info[6]); 431 432 memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE); 433 p_sink->sep_info_idx = *p_sep_info_idx; 434 p_sink->seid = seid; 435 p_sink->num_protect = *p_num_protect; 436 memcpy(p_sink->protect_info, p_protect_info, AVDT_CP_INFO_LEN); 437 } else { 438 APPL_TRACE_ERROR("%s: no more room for SINK info", __func__); 439 } 440 } 441 442 // Check if this is the last SINK get capabilities or all supported codec 443 // capabilities are retrieved. 444 if ((p_peer->num_rx_sinks != p_peer->num_sinks) && 445 (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) { 446 return A2DP_FAIL; 447 } 448 APPL_TRACE_DEBUG("%s: last sink reached", __func__); 449 450 const tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_set_codec(p_peer); 451 if (p_sink == NULL) { 452 APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__); 453 return A2DP_FAIL; 454 } 455 456 // By default, no content protection 457 *p_num_protect = 0; 458#if (BTA_AV_CO_CP_SCMS_T == TRUE) 459 if (p_peer->cp_active) { 460 *p_num_protect = AVDT_CP_INFO_LEN; 461 memcpy(p_protect_info, bta_av_co_cp_scmst, AVDT_CP_INFO_LEN); 462 } 463#endif 464 465 // If acceptor -> reconfig otherwise reply for configuration. 466 if (p_peer->acp) { 467 // Stop fetching caps once we retrieved a supported codec. 468 APPL_TRACE_EVENT("%s: no need to fetch more SEPs", __func__); 469 *p_sep_info_idx = p_peer->num_seps; 470 if (p_peer->reconfig_needed) { 471 APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, hndl); 472 BTA_AvReconfig(hndl, true, p_sink->sep_info_idx, p_peer->codec_config, 473 *p_num_protect, bta_av_co_cp_scmst); 474 } 475 } else { 476 *p_sep_info_idx = p_sink->sep_info_idx; 477 memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE); 478 } 479 480 return A2DP_SUCCESS; 481} 482 483/******************************************************************************* 484 ** 485 ** Function bta_av_co_audio_setconfig 486 ** 487 ** Description This callout function is executed by AV to set the codec 488 ** and content protection configuration of the audio stream. 489 ** 490 ** 491 ** Returns void 492 ** 493 ******************************************************************************/ 494void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, const uint8_t* p_codec_info, 495 UNUSED_ATTR uint8_t seid, 496 UNUSED_ATTR const RawAddress& addr, 497 uint8_t num_protect, 498 const uint8_t* p_protect_info, 499 uint8_t t_local_sep, uint8_t avdt_handle) { 500 tBTA_AV_CO_PEER* p_peer; 501 tA2DP_STATUS status = A2DP_SUCCESS; 502 uint8_t category = A2DP_SUCCESS; 503 bool reconfig_needed = false; 504 505 APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__, 506 p_codec_info[1], p_codec_info[2], p_codec_info[3], 507 p_codec_info[4], p_codec_info[5], p_codec_info[6]); 508 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x", 509 num_protect, p_protect_info[0], p_protect_info[1], 510 p_protect_info[2]); 511 A2DP_DumpCodecInfo(p_codec_info); 512 513 /* Retrieve the peer info */ 514 p_peer = bta_av_co_get_peer(hndl); 515 if (p_peer == NULL) { 516 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 517 /* Call call-in rejecting the configuration */ 518 bta_av_ci_setconfig(hndl, A2DP_BUSY, AVDT_ASC_CODEC, 0, NULL, false, 519 avdt_handle); 520 return; 521 } 522 523 APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)", 524 __func__, p_peer->opened, p_peer->num_sinks, 525 p_peer->num_rx_sinks, p_peer->num_sup_sinks); 526 527 /* Sanity check: should not be opened at this point */ 528 if (p_peer->opened) { 529 APPL_TRACE_ERROR("%s: peer already in use", __func__); 530 } 531 532 if (num_protect != 0) { 533#if (BTA_AV_CO_CP_SCMS_T == TRUE) 534 /* If CP is supported */ 535 if ((num_protect != 1) || 536 (bta_av_co_cp_is_scmst(p_protect_info) == false)) { 537 APPL_TRACE_ERROR("%s: wrong CP configuration", __func__); 538 status = A2DP_BAD_CP_TYPE; 539 category = AVDT_ASC_PROTECT; 540 } 541#else 542 /* Do not support content protection for the time being */ 543 APPL_TRACE_ERROR("%s: wrong CP configuration", __func__); 544 status = A2DP_BAD_CP_TYPE; 545 category = AVDT_ASC_PROTECT; 546#endif 547 } 548 549 if (status == A2DP_SUCCESS) { 550 bool codec_config_supported = false; 551 552 if (t_local_sep == AVDT_TSEP_SNK) { 553 APPL_TRACE_DEBUG("%s: peer is A2DP SRC", __func__); 554 codec_config_supported = A2DP_IsSinkCodecSupported(p_codec_info); 555 if (codec_config_supported) { 556 // If Peer is SRC, and our config subset matches with what is 557 // requested by peer, then just accept what peer wants. 558 bta_av_co_save_new_codec_config(p_peer, p_codec_info, num_protect, 559 p_protect_info); 560 } 561 } 562 if (t_local_sep == AVDT_TSEP_SRC) { 563 APPL_TRACE_DEBUG("%s: peer is A2DP SINK", __func__); 564 bool restart_output = false; 565 if ((bta_av_co_cb.codecs == nullptr) || 566 !bta_av_co_set_codec_ota_config(p_peer, p_codec_info, num_protect, 567 p_protect_info, &restart_output)) { 568 APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__, 569 A2DP_CodecName(p_codec_info)); 570 } else { 571 codec_config_supported = true; 572 // Check if reconfiguration is needed 573 if (restart_output || 574 ((num_protect == 1) && (!bta_av_co_cb.cp.active))) { 575 reconfig_needed = true; 576 } 577 } 578 } 579 580 /* Check if codec configuration is supported */ 581 if (!codec_config_supported) { 582 category = AVDT_ASC_CODEC; 583 status = A2DP_WRONG_CODEC; 584 } 585 } 586 587 if (status != A2DP_SUCCESS) { 588 APPL_TRACE_DEBUG("%s: reject s=%d c=%d", __func__, status, category); 589 /* Call call-in rejecting the configuration */ 590 bta_av_ci_setconfig(hndl, status, category, 0, NULL, false, avdt_handle); 591 return; 592 } 593 594 /* Mark that this is an acceptor peer */ 595 p_peer->acp = true; 596 p_peer->reconfig_needed = reconfig_needed; 597 APPL_TRACE_DEBUG("%s: accept reconf=%d", __func__, reconfig_needed); 598 /* Call call-in accepting the configuration */ 599 bta_av_ci_setconfig(hndl, A2DP_SUCCESS, A2DP_SUCCESS, 0, NULL, 600 reconfig_needed, avdt_handle); 601} 602 603/******************************************************************************* 604 ** 605 ** Function bta_av_co_audio_open 606 ** 607 ** Description This function is called by AV when the audio stream 608 ** connection is opened. 609 ** 610 ** 611 ** Returns void 612 ** 613 ******************************************************************************/ 614void bta_av_co_audio_open(tBTA_AV_HNDL hndl, uint16_t mtu) { 615 tBTA_AV_CO_PEER* p_peer; 616 617 APPL_TRACE_DEBUG("%s: handle: %d mtu:%d", __func__, hndl, mtu); 618 619 /* Retrieve the peer info */ 620 p_peer = bta_av_co_get_peer(hndl); 621 if (p_peer == NULL) { 622 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 623 } else { 624 p_peer->opened = true; 625 p_peer->mtu = mtu; 626 } 627} 628 629/******************************************************************************* 630 ** 631 ** Function bta_av_co_audio_close 632 ** 633 ** Description This function is called by AV when the audio stream 634 ** connection is closed. 635 ** 636 ** 637 ** Returns void 638 ** 639 ******************************************************************************/ 640void bta_av_co_audio_close(tBTA_AV_HNDL hndl) { 641 tBTA_AV_CO_PEER* p_peer; 642 643 APPL_TRACE_DEBUG("%s", __func__); 644 645 /* Retrieve the peer info */ 646 p_peer = bta_av_co_get_peer(hndl); 647 if (p_peer) { 648 /* Mark the peer closed and clean the peer info */ 649 memset(p_peer, 0, sizeof(*p_peer)); 650 } else { 651 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 652 } 653} 654 655/******************************************************************************* 656 ** 657 ** Function bta_av_co_audio_start 658 ** 659 ** Description This function is called by AV when the audio streaming data 660 ** transfer is started. 661 ** 662 ** 663 ** Returns void 664 ** 665 ******************************************************************************/ 666void bta_av_co_audio_start(UNUSED_ATTR tBTA_AV_HNDL hndl, 667 UNUSED_ATTR uint8_t* p_codec_info, 668 UNUSED_ATTR bool* p_no_rtp_hdr) { 669 APPL_TRACE_DEBUG("%s", __func__); 670} 671 672/******************************************************************************* 673 ** 674 ** Function bta_av_co_audio_stop 675 ** 676 ** Description This function is called by AV when the audio streaming data 677 ** transfer is stopped. 678 ** 679 ** 680 ** Returns void 681 ** 682 ******************************************************************************/ 683void bta_av_co_audio_stop(UNUSED_ATTR tBTA_AV_HNDL hndl) { 684 APPL_TRACE_DEBUG("%s", __func__); 685} 686 687/******************************************************************************* 688 ** 689 ** Function bta_av_co_audio_src_data_path 690 ** 691 ** Description This function is called to manage data transfer from 692 ** the audio codec to AVDTP. 693 ** 694 ** Returns Pointer to the GKI buffer to send, NULL if no buffer to 695 ** send 696 ** 697 ******************************************************************************/ 698void* bta_av_co_audio_src_data_path(const uint8_t* p_codec_info, 699 uint32_t* p_timestamp) { 700 BT_HDR* p_buf; 701 702 APPL_TRACE_DEBUG("%s: codec: %s", __func__, A2DP_CodecName(p_codec_info)); 703 704 p_buf = btif_a2dp_source_audio_readbuf(); 705 if (p_buf == NULL) return NULL; 706 707 /* 708 * Retrieve the timestamp information from the media packet, 709 * and set up the packet header. 710 * 711 * In media packet, the following information is available: 712 * p_buf->layer_specific : number of audio frames in the packet 713 * p_buf->word[0] : timestamp 714 */ 715 if (!A2DP_GetPacketTimestamp(p_codec_info, (const uint8_t*)(p_buf + 1), 716 p_timestamp) || 717 !A2DP_BuildCodecHeader(p_codec_info, p_buf, p_buf->layer_specific)) { 718 APPL_TRACE_ERROR("%s: unsupported codec type (%d)", __func__, 719 A2DP_GetCodecType(p_codec_info)); 720 } 721 722#if (BTA_AV_CO_CP_SCMS_T == TRUE) 723 if (bta_av_co_cb.cp.active) { 724 p_buf->len++; 725 p_buf->offset--; 726 uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset; 727 *p = bta_av_co_cp_get_flag(); 728 } 729#endif 730 731 return p_buf; 732} 733 734/******************************************************************************* 735 ** 736 ** Function bta_av_co_audio_drop 737 ** 738 ** Description An Audio packet is dropped. . 739 ** It's very likely that the connected headset with this 740 ** handle is moved far away. The implementation may want to 741 ** reduce the encoder bit rate setting to reduce the packet 742 ** size. 743 ** 744 ** Returns void 745 ** 746 ******************************************************************************/ 747void bta_av_co_audio_drop(tBTA_AV_HNDL hndl) { 748 APPL_TRACE_ERROR("%s: dropped audio packet on handle 0x%x", __func__, hndl); 749} 750 751/******************************************************************************* 752 ** 753 ** Function bta_av_co_audio_delay 754 ** 755 ** Description This function is called by AV when the audio stream 756 ** connection needs to send the initial delay report to the 757 ** connected SRC. 758 ** 759 ** 760 ** Returns void 761 ** 762 ******************************************************************************/ 763void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay) { 764 APPL_TRACE_ERROR("%s: handle: x%x, delay:0x%x", __func__, hndl, delay); 765} 766 767void bta_av_co_audio_update_mtu(tBTA_AV_HNDL hndl, uint16_t mtu) { 768 tBTA_AV_CO_PEER* p_peer; 769 770 APPL_TRACE_DEBUG("%s: handle: %d mtu: %d", __func__, hndl, mtu); 771 772 /* Retrieve the peer info */ 773 p_peer = bta_av_co_get_peer(hndl); 774 if (p_peer == NULL) { 775 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 776 return; 777 } 778 p_peer->mtu = mtu; 779} 780 781/******************************************************************************* 782 ** 783 ** Function bta_av_co_cp_is_scmst 784 ** 785 ** Description Check if a content protection service is SCMS-T 786 ** 787 ** Returns true if this CP is SCMS-T, false otherwise 788 ** 789 ******************************************************************************/ 790static bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info) { 791 APPL_TRACE_DEBUG("%s", __func__); 792 793 if (*p_protect_info >= AVDT_CP_LOSC) { 794 uint16_t cp_id; 795 796 p_protect_info++; 797 STREAM_TO_UINT16(cp_id, p_protect_info); 798 if (cp_id == AVDT_CP_SCMS_T_ID) { 799 APPL_TRACE_DEBUG("%s: SCMS-T found", __func__); 800 return true; 801 } 802 } 803 804 return false; 805} 806 807// Check if audio protect info contains SCMS-T Copy Protection 808// Returns true if |p_protect_info| contains SCMS-T, otherwise false. 809static bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect, 810 const uint8_t* p_protect_info) { 811 APPL_TRACE_DEBUG("%s", __func__); 812 813 while (num_protect--) { 814 if (bta_av_co_cp_is_scmst(p_protect_info)) return true; 815 /* Move to the next SC */ 816 p_protect_info += *p_protect_info + 1; 817 } 818 APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__); 819 return false; 820} 821 822/******************************************************************************* 823 ** 824 ** Function bta_av_co_audio_sink_supports_cp 825 ** 826 ** Description Check if a sink supports the current content protection 827 ** 828 ** Returns true if the sink supports this CP, false otherwise 829 ** 830 ******************************************************************************/ 831static bool bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK* p_sink) { 832 APPL_TRACE_DEBUG("%s", __func__); 833 834 /* Check if content protection is enabled for this stream */ 835 if (bta_av_co_cp_get_flag() != AVDT_CP_SCMS_COPY_FREE) { 836 return bta_av_co_audio_protect_has_scmst(p_sink->num_protect, 837 p_sink->protect_info); 838 } 839 840 APPL_TRACE_DEBUG("%s: not required", __func__); 841 return true; 842} 843 844/******************************************************************************* 845 ** 846 ** Function bta_av_co_find_peer_src_supports_codec 847 ** 848 ** Description Find a peer acting as src that supports codec config 849 ** 850 ** Returns The peer source that supports the codec, otherwise NULL. 851 ** 852 ******************************************************************************/ 853static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( 854 const tBTA_AV_CO_PEER* p_peer) { 855 APPL_TRACE_DEBUG("%s: peer num_sup_srcs = %d", __func__, 856 p_peer->num_sup_srcs); 857 858 for (size_t index = 0; index < p_peer->num_sup_srcs; index++) { 859 const uint8_t* p_codec_caps = p_peer->srcs[index].codec_caps; 860 if (A2DP_CodecTypeEquals(bta_av_co_cb.codec_config, p_codec_caps) && 861 A2DP_IsPeerSourceCodecSupported(p_codec_caps)) { 862 return &p_peer->srcs[index]; 863 } 864 } 865 return NULL; 866} 867 868// 869// Select the current codec configuration based on peer codec support. 870// Furthermore, the local state for the remaining non-selected codecs is 871// updated to reflect whether the codec is selectable. 872// Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry 873// on success, otherwise NULL. 874// 875static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) { 876 tBTA_AV_CO_SINK* p_sink = NULL; 877 878 // Update all selectable codecs. 879 // This is needed to update the selectable parameters for each codec. 880 // NOTE: The selectable codec info is used only for informational purpose. 881 for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) { 882 APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__, 883 iter->name().c_str()); 884 bta_av_co_audio_update_selectable_codec(*iter, p_peer); 885 } 886 887 // Select the codec 888 for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) { 889 APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str()); 890 p_sink = bta_av_co_audio_codec_selected(*iter, p_peer); 891 if (p_sink != NULL) { 892 APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str()); 893 break; 894 } 895 APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str()); 896 } 897 898 // NOTE: Unconditionally dispatch the event to make sure a callback with 899 // the most recent codec info is generated. 900 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 901 902 return p_sink; 903} 904 905// Select an open device for the preferred codec specified by |codec_config|. 906// Return the corresponding peer that supports the codec, otherwise NULL. 907static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( 908 A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer) { 909 uint8_t new_codec_config[AVDT_CODEC_SIZE]; 910 911 APPL_TRACE_DEBUG("%s", __func__); 912 913 // Find the peer sink for the codec 914 tBTA_AV_CO_SINK* p_sink = NULL; 915 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { 916 btav_a2dp_codec_index_t peer_codec_index = 917 A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); 918 if (peer_codec_index != codec_config.codecIndex()) { 919 continue; 920 } 921 if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) { 922 APPL_TRACE_DEBUG( 923 "%s: peer sink for codec %s does not support " 924 "Copy Protection", 925 __func__, codec_config.name().c_str()); 926 continue; 927 } 928 p_sink = &p_peer->sinks[index]; 929 break; 930 } 931 if (p_sink == NULL) { 932 APPL_TRACE_DEBUG("%s: peer sink for codec %s not found", __func__, 933 codec_config.name().c_str()); 934 return NULL; 935 } 936 if (!bta_av_co_cb.codecs->setCodecConfig( 937 p_sink->codec_caps, true /* is_capability */, new_codec_config, 938 true /* select_current_codec */)) { 939 APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__, 940 codec_config.name().c_str()); 941 return NULL; 942 } 943 p_peer->p_sink = p_sink; 944 945 bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect, 946 p_sink->protect_info); 947 // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller 948 949 return p_sink; 950} 951 952// Update a selectable codec |codec_config| with the corresponding codec 953// information from a peer device |p_peer|. 954// Returns true if the codec is updated, otherwise false. 955static bool bta_av_co_audio_update_selectable_codec( 956 A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) { 957 uint8_t new_codec_config[AVDT_CODEC_SIZE]; 958 959 APPL_TRACE_DEBUG("%s", __func__); 960 961 // Find the peer sink for the codec 962 const tBTA_AV_CO_SINK* p_sink = NULL; 963 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { 964 btav_a2dp_codec_index_t peer_codec_index = 965 A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); 966 if (peer_codec_index != codec_config.codecIndex()) { 967 continue; 968 } 969 if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) { 970 APPL_TRACE_DEBUG( 971 "%s: peer sink for codec %s does not support " 972 "Copy Protection", 973 __func__, codec_config.name().c_str()); 974 continue; 975 } 976 p_sink = &p_peer->sinks[index]; 977 break; 978 } 979 if (p_sink == NULL) { 980 // The peer sink device does not support this codec 981 return false; 982 } 983 if (!bta_av_co_cb.codecs->setCodecConfig( 984 p_sink->codec_caps, true /* is_capability */, new_codec_config, 985 false /* select_current_codec */)) { 986 APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__, 987 codec_config.name().c_str()); 988 return false; 989 } 990 return true; 991} 992 993static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer, 994 const uint8_t* new_codec_config, 995 uint8_t num_protect, 996 const uint8_t* p_protect_info) { 997 APPL_TRACE_DEBUG("%s", __func__); 998 A2DP_DumpCodecInfo(new_codec_config); 999 1000 // Protect access to bta_av_co_cb.codec_config 1001 mutex_global_lock(); 1002 1003 memcpy(bta_av_co_cb.codec_config, new_codec_config, 1004 sizeof(bta_av_co_cb.codec_config)); 1005 memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE); 1006 1007#if (BTA_AV_CO_CP_SCMS_T == TRUE) 1008 /* Check if this sink supports SCMS */ 1009 bool cp_active = 1010 bta_av_co_audio_protect_has_scmst(num_protect, p_protect_info); 1011 bta_av_co_cb.cp.active = cp_active; 1012 p_peer->cp_active = cp_active; 1013#endif 1014 1015 // Protect access to bta_av_co_cb.codec_config 1016 mutex_global_unlock(); 1017} 1018 1019void bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) { 1020 uint16_t min_mtu = 0xFFFF; 1021 1022 APPL_TRACE_DEBUG("%s", __func__); 1023 CHECK(p_peer_params != nullptr); 1024 1025 /* Protect access to bta_av_co_cb.codec_config */ 1026 mutex_global_lock(); 1027 1028 /* Compute the MTU */ 1029 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) { 1030 const tBTA_AV_CO_PEER* p_peer = &bta_av_co_cb.peers[i]; 1031 if (!p_peer->opened) continue; 1032 if (p_peer->mtu < min_mtu) min_mtu = p_peer->mtu; 1033 } 1034 p_peer_params->peer_mtu = min_mtu; 1035 p_peer_params->is_peer_edr = btif_av_is_peer_edr(); 1036 p_peer_params->peer_supports_3mbps = btif_av_peer_supports_3mbps(); 1037 1038 /* Protect access to bta_av_co_cb.codec_config */ 1039 mutex_global_unlock(); 1040} 1041 1042const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) { 1043 /* Protect access to bta_av_co_cb.codec_config */ 1044 mutex_global_lock(); 1045 1046 const tA2DP_ENCODER_INTERFACE* encoder_interface = 1047 A2DP_GetEncoderInterface(bta_av_co_cb.codec_config); 1048 1049 /* Protect access to bta_av_co_cb.codec_config */ 1050 mutex_global_unlock(); 1051 1052 return encoder_interface; 1053} 1054 1055bool bta_av_co_set_codec_user_config( 1056 const btav_a2dp_codec_config_t& codec_user_config) { 1057 uint8_t result_codec_config[AVDT_CODEC_SIZE]; 1058 const tBTA_AV_CO_SINK* p_sink = nullptr; 1059 bool restart_input = false; 1060 bool restart_output = false; 1061 bool config_updated = false; 1062 bool success = true; 1063 1064 // Find the peer that is currently open 1065 tBTA_AV_CO_PEER* p_peer = nullptr; 1066 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) { 1067 tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i]; 1068 if (p_peer_tmp->opened) { 1069 p_peer = p_peer_tmp; 1070 break; 1071 } 1072 } 1073 if (p_peer == nullptr) { 1074 APPL_TRACE_ERROR("%s: no open peer to configure", __func__); 1075 success = false; 1076 goto done; 1077 } 1078 1079 // Find the peer SEP codec to use 1080 if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) { 1081 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { 1082 btav_a2dp_codec_index_t peer_codec_index = 1083 A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); 1084 if (peer_codec_index != codec_user_config.codec_type) continue; 1085 if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue; 1086 p_sink = &p_peer->sinks[index]; 1087 break; 1088 } 1089 } else { 1090 // Use the current sink codec 1091 p_sink = p_peer->p_sink; 1092 } 1093 if (p_sink == nullptr) { 1094 APPL_TRACE_ERROR("%s: cannot find peer SEP to configure for codec type %d", 1095 __func__, codec_user_config.codec_type); 1096 success = false; 1097 goto done; 1098 } 1099 1100 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; 1101 bta_av_co_get_peer_params(&peer_params); 1102 if (!bta_av_co_cb.codecs->setCodecUserConfig( 1103 codec_user_config, &peer_params, p_sink->codec_caps, 1104 result_codec_config, &restart_input, &restart_output, 1105 &config_updated)) { 1106 success = false; 1107 goto done; 1108 } 1109 1110 if (restart_output) { 1111 uint8_t num_protect = 0; 1112#if (BTA_AV_CO_CP_SCMS_T == TRUE) 1113 if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN; 1114#endif 1115 1116 p_sink = bta_av_co_audio_set_codec(p_peer); 1117 if (p_sink == NULL) { 1118 APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__); 1119 success = false; 1120 goto done; 1121 } 1122 // Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities 1123 if ((p_peer->num_rx_sinks != p_peer->num_sinks) && 1124 (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) { 1125 APPL_TRACE_WARNING("%s: not all peer's capabilities have been retrieved", 1126 __func__); 1127 success = false; 1128 goto done; 1129 } 1130 1131 APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, p_peer->handle); 1132 BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx, 1133 p_peer->codec_config, num_protect, bta_av_co_cp_scmst); 1134 } 1135 1136done: 1137 // NOTE: We uncoditionally send the upcall even if there is no change 1138 // or the user config failed. Thus, the caller would always know whether the 1139 // request succeeded or failed. 1140 // NOTE: Currently, the input is restarted by sending an upcall 1141 // and informing the Media Framework about the change. 1142 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 1143 1144 return success; 1145} 1146 1147// Sets the Over-The-Air preferred codec configuration. 1148// The OTA prefered codec configuration is ignored if the current 1149// codec configuration contains explicit user configuration, or if the 1150// codec configuration for the same codec contains explicit user 1151// configuration. 1152// |p_peer| is the peer device that sent the OTA codec configuration. 1153// |p_ota_codec_config| contains the received OTA A2DP codec configuration 1154// from the remote peer. Note: this is not the peer codec capability, 1155// but the codec configuration that the peer would like to use. 1156// |num_protect| is the number of content protection methods to use. 1157// |p_protect_info| contains the content protection information to use. 1158// If there is a change in the encoder configuration tht requires restarting 1159// of the A2DP connection, flag |p_restart_output| is set to true. 1160// Returns true on success, otherwise false. 1161static bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer, 1162 const uint8_t* p_ota_codec_config, 1163 uint8_t num_protect, 1164 const uint8_t* p_protect_info, 1165 bool* p_restart_output) { 1166 uint8_t result_codec_config[AVDT_CODEC_SIZE]; 1167 bool restart_input = false; 1168 bool restart_output = false; 1169 bool config_updated = false; 1170 1171 APPL_TRACE_DEBUG("%s", __func__); 1172 A2DP_DumpCodecInfo(p_ota_codec_config); 1173 1174 *p_restart_output = false; 1175 1176 // Find the peer SEP codec to use 1177 btav_a2dp_codec_index_t ota_codec_index = 1178 A2DP_SourceCodecIndex(p_ota_codec_config); 1179 if (ota_codec_index == BTAV_A2DP_CODEC_INDEX_MAX) { 1180 APPL_TRACE_WARNING("%s: invalid peer codec config", __func__); 1181 return false; 1182 } 1183 const tBTA_AV_CO_SINK* p_sink = nullptr; 1184 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { 1185 btav_a2dp_codec_index_t peer_codec_index = 1186 A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); 1187 if (peer_codec_index != ota_codec_index) continue; 1188 if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue; 1189 p_sink = &p_peer->sinks[index]; 1190 break; 1191 } 1192 if ((p_peer->num_sup_sinks > 0) && (p_sink == nullptr)) { 1193 // There are no peer SEPs if we didn't do the discovery procedure yet. 1194 // We have all the information we need from the peer, so we can 1195 // proceed with the OTA codec configuration. 1196 APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__); 1197 return false; 1198 } 1199 1200 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; 1201 bta_av_co_get_peer_params(&peer_params); 1202 if (!bta_av_co_cb.codecs->setCodecOtaConfig( 1203 p_ota_codec_config, &peer_params, result_codec_config, &restart_input, 1204 &restart_output, &config_updated)) { 1205 APPL_TRACE_ERROR("%s: cannot set OTA config", __func__); 1206 return false; 1207 } 1208 1209 if (restart_output) { 1210 APPL_TRACE_DEBUG("%s: restart output", __func__); 1211 A2DP_DumpCodecInfo(result_codec_config); 1212 1213 *p_restart_output = true; 1214 p_peer->p_sink = p_sink; 1215 bta_av_co_save_new_codec_config(p_peer, result_codec_config, num_protect, 1216 p_protect_info); 1217 } 1218 1219 if (restart_input || config_updated) { 1220 // NOTE: Currently, the input is restarted by sending an upcall 1221 // and informing the Media Framework about the change. 1222 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 1223 } 1224 1225 return true; 1226} 1227 1228bool bta_av_co_set_codec_audio_config( 1229 const btav_a2dp_codec_config_t& codec_audio_config) { 1230 uint8_t result_codec_config[AVDT_CODEC_SIZE]; 1231 bool restart_output = false; 1232 bool config_updated = false; 1233 1234 // Find the peer that is currently open 1235 tBTA_AV_CO_PEER* p_peer = nullptr; 1236 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) { 1237 tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i]; 1238 if (p_peer_tmp->opened) { 1239 p_peer = p_peer_tmp; 1240 break; 1241 } 1242 } 1243 if (p_peer == nullptr) { 1244 APPL_TRACE_ERROR("%s: no open peer to configure", __func__); 1245 return false; 1246 } 1247 1248 // Use the current sink codec 1249 const tBTA_AV_CO_SINK* p_sink = p_peer->p_sink; 1250 if (p_sink == nullptr) { 1251 APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__); 1252 return false; 1253 } 1254 1255 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; 1256 bta_av_co_get_peer_params(&peer_params); 1257 if (!bta_av_co_cb.codecs->setCodecAudioConfig( 1258 codec_audio_config, &peer_params, p_sink->codec_caps, 1259 result_codec_config, &restart_output, &config_updated)) { 1260 return false; 1261 } 1262 1263 if (restart_output) { 1264 uint8_t num_protect = 0; 1265#if (BTA_AV_CO_CP_SCMS_T == TRUE) 1266 if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN; 1267#endif 1268 1269 bta_av_co_save_new_codec_config(p_peer, result_codec_config, 1270 p_sink->num_protect, p_sink->protect_info); 1271 1272 // Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities 1273 if ((p_peer->num_rx_sinks != p_peer->num_sinks) && 1274 (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) { 1275 APPL_TRACE_WARNING("%s: not all peer's capabilities have been retrieved", 1276 __func__); 1277 } else { 1278 APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, 1279 p_peer->handle); 1280 BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx, 1281 p_peer->codec_config, num_protect, bta_av_co_cp_scmst); 1282 } 1283 } 1284 1285 if (config_updated) { 1286 // NOTE: Currently, the input is restarted by sending an upcall 1287 // and informing the Media Framework about the change. 1288 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 1289 } 1290 1291 return true; 1292} 1293 1294A2dpCodecs* bta_av_get_a2dp_codecs(void) { return bta_av_co_cb.codecs; } 1295 1296A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) { 1297 A2dpCodecConfig* current_codec; 1298 1299 mutex_global_lock(); 1300 if (bta_av_co_cb.codecs == nullptr) { 1301 mutex_global_unlock(); 1302 return nullptr; 1303 } 1304 current_codec = bta_av_co_cb.codecs->getCurrentCodecConfig(); 1305 mutex_global_unlock(); 1306 1307 return current_codec; 1308} 1309 1310void bta_av_co_init( 1311 const std::vector<btav_a2dp_codec_config_t>& codec_priorities) { 1312 APPL_TRACE_DEBUG("%s", __func__); 1313 1314 /* Reset the control block */ 1315 bta_av_co_cb.reset(); 1316 1317#if (BTA_AV_CO_CP_SCMS_T == TRUE) 1318 bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_NEVER); 1319#else 1320 bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_FREE); 1321#endif 1322 1323 /* Reset the current config */ 1324 /* Protect access to bta_av_co_cb.codec_config */ 1325 mutex_global_lock(); 1326 bta_av_co_cb.codecs = new A2dpCodecs(codec_priorities); 1327 bta_av_co_cb.codecs->init(); 1328 A2DP_InitDefaultCodec(bta_av_co_cb.codec_config); 1329 mutex_global_unlock(); 1330 1331 // NOTE: Unconditionally dispatch the event to make sure a callback with 1332 // the most recent codec info is generated. 1333 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 1334} 1335