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 */ 54 const uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00}; 55 56 /***************************************************************************** 57 * Local data 58 ****************************************************************************/ 59 typedef 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 67 typedef struct { 68 BD_ADDR 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 91 typedef struct { 92 bool active; 93 uint8_t flag; 94 } tBTA_AV_CO_CP; 95 96 class 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 */ 125 static BtaAvCoCb bta_av_co_cb; 126 127 static bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info); 128 static bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect, 129 const uint8_t* p_protect_info); 130 static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( 131 const tBTA_AV_CO_PEER* p_peer); 132 static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer); 133 static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( 134 A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer); 135 static bool bta_av_co_audio_update_selectable_codec( 136 A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer); 137 static 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); 141 static 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 ******************************************************************************/ 159 static 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 ******************************************************************************/ 173 static 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 ******************************************************************************/ 195 static 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 ******************************************************************************/ 224 bool 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 ******************************************************************************/ 241 void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps, 242 uint8_t num_sink, uint8_t num_src, BD_ADDR addr, 243 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 bdcpy(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 ******************************************************************************/ 287 static 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 ******************************************************************************/ 391 tA2DP_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 399 /* Retrieve the peer info */ 400 p_peer = bta_av_co_get_peer(hndl); 401 if (p_peer == NULL) { 402 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 403 return A2DP_FAIL; 404 } 405 406 if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE) { 407 return bta_av_audio_sink_getconfig(hndl, p_codec_info, p_sep_info_idx, seid, 408 p_num_protect, p_protect_info); 409 } 410 APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl, 411 A2DP_CodecName(p_codec_info), seid); 412 APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x", 413 __func__, *p_num_protect, p_protect_info[0], 414 p_protect_info[1], p_protect_info[2]); 415 APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)", 416 __func__, p_peer->opened, p_peer->num_sinks, 417 p_peer->num_rx_sinks, p_peer->num_sup_sinks); 418 419 p_peer->num_rx_sinks++; 420 421 /* Check the peer's SINK codec */ 422 if (A2DP_IsPeerSinkCodecValid(p_codec_info)) { 423 /* If there is room for a new one */ 424 if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) { 425 tBTA_AV_CO_SINK* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++]; 426 427 APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__, 428 p_codec_info[1], p_codec_info[2], p_codec_info[3], 429 p_codec_info[4], p_codec_info[5], p_codec_info[6]); 430 431 memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE); 432 p_sink->sep_info_idx = *p_sep_info_idx; 433 p_sink->seid = seid; 434 p_sink->num_protect = *p_num_protect; 435 memcpy(p_sink->protect_info, p_protect_info, AVDT_CP_INFO_LEN); 436 } else { 437 APPL_TRACE_ERROR("%s: no more room for SINK info", __func__); 438 } 439 } 440 441 // Check if this is the last SINK get capabilities or all supported codec 442 // capabilities are retrieved. 443 if ((p_peer->num_rx_sinks != p_peer->num_sinks) && 444 (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) { 445 return A2DP_FAIL; 446 } 447 APPL_TRACE_DEBUG("%s: last sink reached", __func__); 448 449 const tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_set_codec(p_peer); 450 if (p_sink == NULL) { 451 APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__); 452 return A2DP_FAIL; 453 } 454 455 // By default, no content protection 456 *p_num_protect = 0; 457 #if (BTA_AV_CO_CP_SCMS_T == TRUE) 458 if (p_peer->cp_active) { 459 *p_num_protect = AVDT_CP_INFO_LEN; 460 memcpy(p_protect_info, bta_av_co_cp_scmst, AVDT_CP_INFO_LEN); 461 } 462 #endif 463 464 // If acceptor -> reconfig otherwise reply for configuration. 465 if (p_peer->acp) { 466 // Stop fetching caps once we retrieved a supported codec. 467 APPL_TRACE_EVENT("%s: no need to fetch more SEPs", __func__); 468 *p_sep_info_idx = p_peer->num_seps; 469 if (p_peer->reconfig_needed) { 470 APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, hndl); 471 BTA_AvReconfig(hndl, true, p_sink->sep_info_idx, p_peer->codec_config, 472 *p_num_protect, bta_av_co_cp_scmst); 473 } 474 } else { 475 *p_sep_info_idx = p_sink->sep_info_idx; 476 memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE); 477 } 478 479 return A2DP_SUCCESS; 480 } 481 482 /******************************************************************************* 483 ** 484 ** Function bta_av_co_audio_setconfig 485 ** 486 ** Description This callout function is executed by AV to set the codec 487 ** and content protection configuration of the audio stream. 488 ** 489 ** 490 ** Returns void 491 ** 492 ******************************************************************************/ 493 void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, const uint8_t* p_codec_info, 494 UNUSED_ATTR uint8_t seid, 495 UNUSED_ATTR BD_ADDR addr, uint8_t num_protect, 496 const uint8_t* p_protect_info, 497 uint8_t t_local_sep, uint8_t avdt_handle) { 498 tBTA_AV_CO_PEER* p_peer; 499 tA2DP_STATUS status = A2DP_SUCCESS; 500 uint8_t category = A2DP_SUCCESS; 501 bool reconfig_needed = false; 502 503 APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__, 504 p_codec_info[1], p_codec_info[2], p_codec_info[3], 505 p_codec_info[4], p_codec_info[5], p_codec_info[6]); 506 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x", 507 num_protect, p_protect_info[0], p_protect_info[1], 508 p_protect_info[2]); 509 510 /* Retrieve the peer info */ 511 p_peer = bta_av_co_get_peer(hndl); 512 if (p_peer == NULL) { 513 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 514 /* Call call-in rejecting the configuration */ 515 bta_av_ci_setconfig(hndl, A2DP_BUSY, AVDT_ASC_CODEC, 0, NULL, false, 516 avdt_handle); 517 return; 518 } 519 520 APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)", 521 __func__, p_peer->opened, p_peer->num_sinks, 522 p_peer->num_rx_sinks, p_peer->num_sup_sinks); 523 524 /* Sanity check: should not be opened at this point */ 525 if (p_peer->opened) { 526 APPL_TRACE_ERROR("%s: peer already in use", __func__); 527 } 528 529 if (num_protect != 0) { 530 #if (BTA_AV_CO_CP_SCMS_T == TRUE) 531 /* If CP is supported */ 532 if ((num_protect != 1) || 533 (bta_av_co_cp_is_scmst(p_protect_info) == false)) { 534 APPL_TRACE_ERROR("%s: wrong CP configuration", __func__); 535 status = A2DP_BAD_CP_TYPE; 536 category = AVDT_ASC_PROTECT; 537 } 538 #else 539 /* Do not support content protection for the time being */ 540 APPL_TRACE_ERROR("%s: wrong CP configuration", __func__); 541 status = A2DP_BAD_CP_TYPE; 542 category = AVDT_ASC_PROTECT; 543 #endif 544 } 545 546 if (status == A2DP_SUCCESS) { 547 bool codec_config_supported = false; 548 549 if (t_local_sep == AVDT_TSEP_SNK) { 550 APPL_TRACE_DEBUG("%s: peer is A2DP SRC", __func__); 551 codec_config_supported = A2DP_IsSinkCodecSupported(p_codec_info); 552 if (codec_config_supported) { 553 // If Peer is SRC, and our config subset matches with what is 554 // requested by peer, then just accept what peer wants. 555 bta_av_co_save_new_codec_config(p_peer, p_codec_info, num_protect, 556 p_protect_info); 557 } 558 } 559 if (t_local_sep == AVDT_TSEP_SRC) { 560 APPL_TRACE_DEBUG("%s: peer is A2DP SINK", __func__); 561 bool restart_output = false; 562 if ((bta_av_co_cb.codecs == nullptr) || 563 !bta_av_co_set_codec_ota_config(p_peer, p_codec_info, num_protect, 564 p_protect_info, &restart_output)) { 565 APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__, 566 A2DP_CodecName(p_codec_info)); 567 } else { 568 codec_config_supported = true; 569 // Check if reconfiguration is needed 570 if (restart_output || 571 ((num_protect == 1) && (!bta_av_co_cb.cp.active))) { 572 reconfig_needed = true; 573 } 574 } 575 } 576 577 /* Check if codec configuration is supported */ 578 if (!codec_config_supported) { 579 category = AVDT_ASC_CODEC; 580 status = A2DP_WRONG_CODEC; 581 } 582 } 583 584 if (status != A2DP_SUCCESS) { 585 APPL_TRACE_DEBUG("%s: reject s=%d c=%d", __func__, status, category); 586 /* Call call-in rejecting the configuration */ 587 bta_av_ci_setconfig(hndl, status, category, 0, NULL, false, avdt_handle); 588 return; 589 } 590 591 /* Mark that this is an acceptor peer */ 592 p_peer->acp = true; 593 p_peer->reconfig_needed = reconfig_needed; 594 APPL_TRACE_DEBUG("%s: accept reconf=%d", __func__, reconfig_needed); 595 /* Call call-in accepting the configuration */ 596 bta_av_ci_setconfig(hndl, A2DP_SUCCESS, A2DP_SUCCESS, 0, NULL, 597 reconfig_needed, avdt_handle); 598 } 599 600 /******************************************************************************* 601 ** 602 ** Function bta_av_co_audio_open 603 ** 604 ** Description This function is called by AV when the audio stream 605 ** connection is opened. 606 ** 607 ** 608 ** Returns void 609 ** 610 ******************************************************************************/ 611 void bta_av_co_audio_open(tBTA_AV_HNDL hndl, uint16_t mtu) { 612 tBTA_AV_CO_PEER* p_peer; 613 614 APPL_TRACE_DEBUG("%s: handle: %d mtu:%d", __func__, hndl, mtu); 615 616 /* Retrieve the peer info */ 617 p_peer = bta_av_co_get_peer(hndl); 618 if (p_peer == NULL) { 619 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 620 } else { 621 p_peer->opened = true; 622 p_peer->mtu = mtu; 623 } 624 } 625 626 /******************************************************************************* 627 ** 628 ** Function bta_av_co_audio_close 629 ** 630 ** Description This function is called by AV when the audio stream 631 ** connection is closed. 632 ** 633 ** 634 ** Returns void 635 ** 636 ******************************************************************************/ 637 void bta_av_co_audio_close(tBTA_AV_HNDL hndl) { 638 tBTA_AV_CO_PEER* p_peer; 639 640 APPL_TRACE_DEBUG("%s", __func__); 641 642 /* Retrieve the peer info */ 643 p_peer = bta_av_co_get_peer(hndl); 644 if (p_peer) { 645 /* Mark the peer closed and clean the peer info */ 646 memset(p_peer, 0, sizeof(*p_peer)); 647 } else { 648 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 649 } 650 } 651 652 /******************************************************************************* 653 ** 654 ** Function bta_av_co_audio_start 655 ** 656 ** Description This function is called by AV when the audio streaming data 657 ** transfer is started. 658 ** 659 ** 660 ** Returns void 661 ** 662 ******************************************************************************/ 663 void bta_av_co_audio_start(UNUSED_ATTR tBTA_AV_HNDL hndl, 664 UNUSED_ATTR uint8_t* p_codec_info, 665 UNUSED_ATTR bool* p_no_rtp_hdr) { 666 APPL_TRACE_DEBUG("%s", __func__); 667 } 668 669 /******************************************************************************* 670 ** 671 ** Function bta_av_co_audio_stop 672 ** 673 ** Description This function is called by AV when the audio streaming data 674 ** transfer is stopped. 675 ** 676 ** 677 ** Returns void 678 ** 679 ******************************************************************************/ 680 void bta_av_co_audio_stop(UNUSED_ATTR tBTA_AV_HNDL hndl) { 681 APPL_TRACE_DEBUG("%s", __func__); 682 } 683 684 /******************************************************************************* 685 ** 686 ** Function bta_av_co_audio_src_data_path 687 ** 688 ** Description This function is called to manage data transfer from 689 ** the audio codec to AVDTP. 690 ** 691 ** Returns Pointer to the GKI buffer to send, NULL if no buffer to 692 ** send 693 ** 694 ******************************************************************************/ 695 void* bta_av_co_audio_src_data_path(const uint8_t* p_codec_info, 696 uint32_t* p_timestamp) { 697 BT_HDR* p_buf; 698 699 APPL_TRACE_DEBUG("%s: codec: %s", __func__, A2DP_CodecName(p_codec_info)); 700 701 p_buf = btif_a2dp_source_audio_readbuf(); 702 if (p_buf == NULL) return NULL; 703 704 /* 705 * Retrieve the timestamp information from the media packet, 706 * and set up the packet header. 707 * 708 * In media packet, the following information is available: 709 * p_buf->layer_specific : number of audio frames in the packet 710 * p_buf->word[0] : timestamp 711 */ 712 if (!A2DP_GetPacketTimestamp(p_codec_info, (const uint8_t*)(p_buf + 1), 713 p_timestamp) || 714 !A2DP_BuildCodecHeader(p_codec_info, p_buf, p_buf->layer_specific)) { 715 APPL_TRACE_ERROR("%s: unsupported codec type (%d)", __func__, 716 A2DP_GetCodecType(p_codec_info)); 717 } 718 719 #if (BTA_AV_CO_CP_SCMS_T == TRUE) 720 if (bta_av_co_cb.cp.active) { 721 p_buf->len++; 722 p_buf->offset--; 723 uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset; 724 *p = bta_av_co_cp_get_flag(); 725 } 726 #endif 727 728 return p_buf; 729 } 730 731 /******************************************************************************* 732 ** 733 ** Function bta_av_co_audio_drop 734 ** 735 ** Description An Audio packet is dropped. . 736 ** It's very likely that the connected headset with this 737 ** handle is moved far away. The implementation may want to 738 ** reduce the encoder bit rate setting to reduce the packet 739 ** size. 740 ** 741 ** Returns void 742 ** 743 ******************************************************************************/ 744 void bta_av_co_audio_drop(tBTA_AV_HNDL hndl) { 745 APPL_TRACE_ERROR("%s: dropped audio packet on handle 0x%x", __func__, hndl); 746 } 747 748 /******************************************************************************* 749 ** 750 ** Function bta_av_co_audio_delay 751 ** 752 ** Description This function is called by AV when the audio stream 753 ** connection needs to send the initial delay report to the 754 ** connected SRC. 755 ** 756 ** 757 ** Returns void 758 ** 759 ******************************************************************************/ 760 void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay) { 761 APPL_TRACE_ERROR("%s: handle: x%x, delay:0x%x", __func__, hndl, delay); 762 } 763 764 void bta_av_co_audio_update_mtu(tBTA_AV_HNDL hndl, uint16_t mtu) { 765 tBTA_AV_CO_PEER* p_peer; 766 767 APPL_TRACE_DEBUG("%s: handle: %d mtu: %d", __func__, hndl, mtu); 768 769 /* Retrieve the peer info */ 770 p_peer = bta_av_co_get_peer(hndl); 771 if (p_peer == NULL) { 772 APPL_TRACE_ERROR("%s: could not find peer entry", __func__); 773 return; 774 } 775 p_peer->mtu = mtu; 776 } 777 778 /******************************************************************************* 779 ** 780 ** Function bta_av_co_cp_is_scmst 781 ** 782 ** Description Check if a content protection service is SCMS-T 783 ** 784 ** Returns true if this CP is SCMS-T, false otherwise 785 ** 786 ******************************************************************************/ 787 static bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info) { 788 APPL_TRACE_DEBUG("%s", __func__); 789 790 if (*p_protect_info >= AVDT_CP_LOSC) { 791 uint16_t cp_id; 792 793 p_protect_info++; 794 STREAM_TO_UINT16(cp_id, p_protect_info); 795 if (cp_id == AVDT_CP_SCMS_T_ID) { 796 APPL_TRACE_DEBUG("%s: SCMS-T found", __func__); 797 return true; 798 } 799 } 800 801 return false; 802 } 803 804 // Check if audio protect info contains SCMS-T Copy Protection 805 // Returns true if |p_protect_info| contains SCMS-T, otherwise false. 806 static bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect, 807 const uint8_t* p_protect_info) { 808 APPL_TRACE_DEBUG("%s", __func__); 809 810 while (num_protect--) { 811 if (bta_av_co_cp_is_scmst(p_protect_info)) return true; 812 /* Move to the next SC */ 813 p_protect_info += *p_protect_info + 1; 814 } 815 APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__); 816 return false; 817 } 818 819 /******************************************************************************* 820 ** 821 ** Function bta_av_co_audio_sink_supports_cp 822 ** 823 ** Description Check if a sink supports the current content protection 824 ** 825 ** Returns true if the sink supports this CP, false otherwise 826 ** 827 ******************************************************************************/ 828 static bool bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK* p_sink) { 829 APPL_TRACE_DEBUG("%s", __func__); 830 831 /* Check if content protection is enabled for this stream */ 832 if (bta_av_co_cp_get_flag() != AVDT_CP_SCMS_COPY_FREE) { 833 return bta_av_co_audio_protect_has_scmst(p_sink->num_protect, 834 p_sink->protect_info); 835 } 836 837 APPL_TRACE_DEBUG("%s: not required", __func__); 838 return true; 839 } 840 841 /******************************************************************************* 842 ** 843 ** Function bta_av_co_find_peer_src_supports_codec 844 ** 845 ** Description Find a peer acting as src that supports codec config 846 ** 847 ** Returns The peer source that supports the codec, otherwise NULL. 848 ** 849 ******************************************************************************/ 850 static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec( 851 const tBTA_AV_CO_PEER* p_peer) { 852 APPL_TRACE_DEBUG("%s: peer num_sup_srcs = %d", __func__, 853 p_peer->num_sup_srcs); 854 855 for (size_t index = 0; index < p_peer->num_sup_srcs; index++) { 856 const uint8_t* p_codec_caps = p_peer->srcs[index].codec_caps; 857 if (A2DP_CodecTypeEquals(bta_av_co_cb.codec_config, p_codec_caps) && 858 A2DP_IsPeerSourceCodecSupported(p_codec_caps)) { 859 return &p_peer->srcs[index]; 860 } 861 } 862 return NULL; 863 } 864 865 // 866 // Select the current codec configuration based on peer codec support. 867 // Furthermore, the local state for the remaining non-selected codecs is 868 // updated to reflect whether the codec is selectable. 869 // Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry 870 // on success, otherwise NULL. 871 // 872 static tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) { 873 tBTA_AV_CO_SINK* p_sink = NULL; 874 875 // Update all selectable codecs. 876 // This is needed to update the selectable parameters for each codec. 877 // NOTE: The selectable codec info is used only for informational purpose. 878 for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) { 879 APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__, 880 iter->name().c_str()); 881 bta_av_co_audio_update_selectable_codec(*iter, p_peer); 882 } 883 884 // Select the codec 885 for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) { 886 APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str()); 887 p_sink = bta_av_co_audio_codec_selected(*iter, p_peer); 888 if (p_sink != NULL) { 889 APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str()); 890 break; 891 } 892 APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str()); 893 } 894 895 // NOTE: Unconditionally dispatch the event to make sure a callback with 896 // the most recent codec info is generated. 897 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 898 899 return p_sink; 900 } 901 902 // Select an open device for the preferred codec specified by |codec_config|. 903 // Return the corresponding peer that supports the codec, otherwise NULL. 904 static tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected( 905 A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer) { 906 uint8_t new_codec_config[AVDT_CODEC_SIZE]; 907 908 APPL_TRACE_DEBUG("%s", __func__); 909 910 // Find the peer sink for the codec 911 tBTA_AV_CO_SINK* p_sink = NULL; 912 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { 913 btav_a2dp_codec_index_t peer_codec_index = 914 A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); 915 if (peer_codec_index != codec_config.codecIndex()) { 916 continue; 917 } 918 if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) { 919 APPL_TRACE_DEBUG( 920 "%s: peer sink for codec %s does not support " 921 "Copy Protection", 922 __func__, codec_config.name().c_str()); 923 continue; 924 } 925 p_sink = &p_peer->sinks[index]; 926 break; 927 } 928 if (p_sink == NULL) { 929 APPL_TRACE_DEBUG("%s: peer sink for codec %s not found", __func__, 930 codec_config.name().c_str()); 931 return NULL; 932 } 933 if (!bta_av_co_cb.codecs->setCodecConfig( 934 p_sink->codec_caps, true /* is_capability */, new_codec_config, 935 true /* select_current_codec */)) { 936 APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__, 937 codec_config.name().c_str()); 938 return NULL; 939 } 940 p_peer->p_sink = p_sink; 941 942 bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect, 943 p_sink->protect_info); 944 // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller 945 946 return p_sink; 947 } 948 949 // Update a selectable codec |codec_config| with the corresponding codec 950 // information from a peer device |p_peer|. 951 // Returns true if the codec is updated, otherwise false. 952 static bool bta_av_co_audio_update_selectable_codec( 953 A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) { 954 uint8_t new_codec_config[AVDT_CODEC_SIZE]; 955 956 APPL_TRACE_DEBUG("%s", __func__); 957 958 // Find the peer sink for the codec 959 const tBTA_AV_CO_SINK* p_sink = NULL; 960 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { 961 btav_a2dp_codec_index_t peer_codec_index = 962 A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); 963 if (peer_codec_index != codec_config.codecIndex()) { 964 continue; 965 } 966 if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) { 967 APPL_TRACE_DEBUG( 968 "%s: peer sink for codec %s does not support " 969 "Copy Protection", 970 __func__, codec_config.name().c_str()); 971 continue; 972 } 973 p_sink = &p_peer->sinks[index]; 974 break; 975 } 976 if (p_sink == NULL) { 977 // The peer sink device does not support this codec 978 return false; 979 } 980 if (!bta_av_co_cb.codecs->setCodecConfig( 981 p_sink->codec_caps, true /* is_capability */, new_codec_config, 982 false /* select_current_codec */)) { 983 APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__, 984 codec_config.name().c_str()); 985 return false; 986 } 987 return true; 988 } 989 990 static void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer, 991 const uint8_t* new_codec_config, 992 uint8_t num_protect, 993 const uint8_t* p_protect_info) { 994 // Protect access to bta_av_co_cb.codec_config 995 mutex_global_lock(); 996 997 memcpy(bta_av_co_cb.codec_config, new_codec_config, 998 sizeof(bta_av_co_cb.codec_config)); 999 memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE); 1000 1001 #if (BTA_AV_CO_CP_SCMS_T == TRUE) 1002 /* Check if this sink supports SCMS */ 1003 bool cp_active = 1004 bta_av_co_audio_protect_has_scmst(num_protect, p_protect_info); 1005 bta_av_co_cb.cp.active = cp_active; 1006 p_peer->cp_active = cp_active; 1007 #endif 1008 1009 // Protect access to bta_av_co_cb.codec_config 1010 mutex_global_unlock(); 1011 } 1012 1013 void bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) { 1014 uint16_t min_mtu = 0xFFFF; 1015 1016 APPL_TRACE_DEBUG("%s", __func__); 1017 CHECK(p_peer_params != nullptr); 1018 1019 /* Protect access to bta_av_co_cb.codec_config */ 1020 mutex_global_lock(); 1021 1022 /* Compute the MTU */ 1023 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) { 1024 const tBTA_AV_CO_PEER* p_peer = &bta_av_co_cb.peers[i]; 1025 if (!p_peer->opened) continue; 1026 if (p_peer->mtu < min_mtu) min_mtu = p_peer->mtu; 1027 } 1028 p_peer_params->peer_mtu = min_mtu; 1029 p_peer_params->is_peer_edr = btif_av_is_peer_edr(); 1030 p_peer_params->peer_supports_3mbps = btif_av_peer_supports_3mbps(); 1031 1032 /* Protect access to bta_av_co_cb.codec_config */ 1033 mutex_global_unlock(); 1034 } 1035 1036 const tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) { 1037 /* Protect access to bta_av_co_cb.codec_config */ 1038 mutex_global_lock(); 1039 1040 const tA2DP_ENCODER_INTERFACE* encoder_interface = 1041 A2DP_GetEncoderInterface(bta_av_co_cb.codec_config); 1042 1043 /* Protect access to bta_av_co_cb.codec_config */ 1044 mutex_global_unlock(); 1045 1046 return encoder_interface; 1047 } 1048 1049 bool bta_av_co_set_codec_user_config( 1050 const btav_a2dp_codec_config_t& codec_user_config) { 1051 uint8_t result_codec_config[AVDT_CODEC_SIZE]; 1052 const tBTA_AV_CO_SINK* p_sink = nullptr; 1053 bool restart_input = false; 1054 bool restart_output = false; 1055 bool config_updated = false; 1056 bool success = true; 1057 1058 // Find the peer that is currently open 1059 tBTA_AV_CO_PEER* p_peer = nullptr; 1060 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) { 1061 tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i]; 1062 if (p_peer_tmp->opened) { 1063 p_peer = p_peer_tmp; 1064 break; 1065 } 1066 } 1067 if (p_peer == nullptr) { 1068 APPL_TRACE_ERROR("%s: no open peer to configure", __func__); 1069 success = false; 1070 goto done; 1071 } 1072 1073 // Find the peer SEP codec to use 1074 if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) { 1075 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { 1076 btav_a2dp_codec_index_t peer_codec_index = 1077 A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); 1078 if (peer_codec_index != codec_user_config.codec_type) continue; 1079 if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue; 1080 p_sink = &p_peer->sinks[index]; 1081 break; 1082 } 1083 } else { 1084 // Use the current sink codec 1085 p_sink = p_peer->p_sink; 1086 } 1087 if (p_sink == nullptr) { 1088 APPL_TRACE_ERROR("%s: cannot find peer SEP to configure for codec type %d", 1089 __func__, codec_user_config.codec_type); 1090 success = false; 1091 goto done; 1092 } 1093 1094 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; 1095 bta_av_co_get_peer_params(&peer_params); 1096 if (!bta_av_co_cb.codecs->setCodecUserConfig( 1097 codec_user_config, &peer_params, p_sink->codec_caps, 1098 result_codec_config, &restart_input, &restart_output, 1099 &config_updated)) { 1100 success = false; 1101 goto done; 1102 } 1103 1104 if (restart_output) { 1105 uint8_t num_protect = 0; 1106 #if (BTA_AV_CO_CP_SCMS_T == TRUE) 1107 if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN; 1108 #endif 1109 1110 p_sink = bta_av_co_audio_set_codec(p_peer); 1111 if (p_sink == NULL) { 1112 APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__); 1113 success = false; 1114 goto done; 1115 } 1116 APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, p_peer->handle); 1117 BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx, 1118 p_peer->codec_config, num_protect, bta_av_co_cp_scmst); 1119 } 1120 1121 done: 1122 // NOTE: We uncoditionally send the upcall even if there is no change 1123 // or the user config failed. Thus, the caller would always know whether the 1124 // request succeeded or failed. 1125 // NOTE: Currently, the input is restarted by sending an upcall 1126 // and informing the Media Framework about the change. 1127 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 1128 1129 return success; 1130 } 1131 1132 // Sets the Over-The-Air preferred codec configuration. 1133 // The OTA prefered codec configuration is ignored if the current 1134 // codec configuration contains explicit user configuration, or if the 1135 // codec configuration for the same codec contains explicit user 1136 // configuration. 1137 // |p_peer| is the peer device that sent the OTA codec configuration. 1138 // |p_ota_codec_config| contains the received OTA A2DP codec configuration 1139 // from the remote peer. Note: this is not the peer codec capability, 1140 // but the codec configuration that the peer would like to use. 1141 // |num_protect| is the number of content protection methods to use. 1142 // |p_protect_info| contains the content protection information to use. 1143 // If there is a change in the encoder configuration tht requires restarting 1144 // of the A2DP connection, flag |p_restart_output| is set to true. 1145 // Returns true on success, otherwise false. 1146 static bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer, 1147 const uint8_t* p_ota_codec_config, 1148 uint8_t num_protect, 1149 const uint8_t* p_protect_info, 1150 bool* p_restart_output) { 1151 uint8_t result_codec_config[AVDT_CODEC_SIZE]; 1152 bool restart_input = false; 1153 bool restart_output = false; 1154 bool config_updated = false; 1155 1156 *p_restart_output = false; 1157 1158 // Find the peer SEP codec to use 1159 btav_a2dp_codec_index_t ota_codec_index = 1160 A2DP_SourceCodecIndex(p_ota_codec_config); 1161 if (ota_codec_index == BTAV_A2DP_CODEC_INDEX_MAX) { 1162 APPL_TRACE_WARNING("%s: invalid peer codec config", __func__); 1163 return false; 1164 } 1165 const tBTA_AV_CO_SINK* p_sink = nullptr; 1166 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) { 1167 btav_a2dp_codec_index_t peer_codec_index = 1168 A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps); 1169 if (peer_codec_index != ota_codec_index) continue; 1170 if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue; 1171 p_sink = &p_peer->sinks[index]; 1172 break; 1173 } 1174 if ((p_peer->num_sup_sinks > 0) && (p_sink == nullptr)) { 1175 // There are no peer SEPs if we didn't do the discovery procedure yet. 1176 // We have all the information we need from the peer, so we can 1177 // proceed with the OTA codec configuration. 1178 APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__); 1179 return false; 1180 } 1181 1182 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; 1183 bta_av_co_get_peer_params(&peer_params); 1184 if (!bta_av_co_cb.codecs->setCodecOtaConfig( 1185 p_ota_codec_config, &peer_params, result_codec_config, &restart_input, 1186 &restart_output, &config_updated)) { 1187 APPL_TRACE_ERROR("%s: cannot set OTA config", __func__); 1188 return false; 1189 } 1190 1191 if (restart_output) { 1192 *p_restart_output = true; 1193 p_peer->p_sink = p_sink; 1194 bta_av_co_save_new_codec_config(p_peer, result_codec_config, num_protect, 1195 p_protect_info); 1196 } 1197 1198 if (restart_input || config_updated) { 1199 // NOTE: Currently, the input is restarted by sending an upcall 1200 // and informing the Media Framework about the change. 1201 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 1202 } 1203 1204 return true; 1205 } 1206 1207 bool bta_av_co_set_codec_audio_config( 1208 const btav_a2dp_codec_config_t& codec_audio_config) { 1209 uint8_t result_codec_config[AVDT_CODEC_SIZE]; 1210 bool restart_output = false; 1211 bool config_updated = false; 1212 1213 // Find the peer that is currently open 1214 tBTA_AV_CO_PEER* p_peer = nullptr; 1215 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) { 1216 tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i]; 1217 if (p_peer_tmp->opened) { 1218 p_peer = p_peer_tmp; 1219 break; 1220 } 1221 } 1222 if (p_peer == nullptr) { 1223 APPL_TRACE_ERROR("%s: no open peer to configure", __func__); 1224 return false; 1225 } 1226 1227 // Use the current sink codec 1228 const tBTA_AV_CO_SINK* p_sink = p_peer->p_sink; 1229 if (p_sink == nullptr) { 1230 APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__); 1231 return false; 1232 } 1233 1234 tA2DP_ENCODER_INIT_PEER_PARAMS peer_params; 1235 bta_av_co_get_peer_params(&peer_params); 1236 if (!bta_av_co_cb.codecs->setCodecAudioConfig( 1237 codec_audio_config, &peer_params, p_sink->codec_caps, 1238 result_codec_config, &restart_output, &config_updated)) { 1239 return false; 1240 } 1241 1242 if (restart_output) { 1243 uint8_t num_protect = 0; 1244 #if (BTA_AV_CO_CP_SCMS_T == TRUE) 1245 if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN; 1246 #endif 1247 1248 bta_av_co_save_new_codec_config(p_peer, result_codec_config, 1249 p_sink->num_protect, p_sink->protect_info); 1250 1251 APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, p_peer->handle); 1252 BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx, 1253 p_peer->codec_config, num_protect, bta_av_co_cp_scmst); 1254 } 1255 1256 if (config_updated) { 1257 // NOTE: Currently, the input is restarted by sending an upcall 1258 // and informing the Media Framework about the change. 1259 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 1260 } 1261 1262 return true; 1263 } 1264 1265 A2dpCodecs* bta_av_get_a2dp_codecs(void) { return bta_av_co_cb.codecs; } 1266 1267 A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) { 1268 A2dpCodecConfig* current_codec; 1269 1270 mutex_global_lock(); 1271 if (bta_av_co_cb.codecs == nullptr) { 1272 mutex_global_unlock(); 1273 return nullptr; 1274 } 1275 current_codec = bta_av_co_cb.codecs->getCurrentCodecConfig(); 1276 mutex_global_unlock(); 1277 1278 return current_codec; 1279 } 1280 1281 void bta_av_co_init( 1282 const std::vector<btav_a2dp_codec_config_t>& codec_priorities) { 1283 APPL_TRACE_DEBUG("%s", __func__); 1284 1285 /* Reset the control block */ 1286 bta_av_co_cb.reset(); 1287 1288 #if (BTA_AV_CO_CP_SCMS_T == TRUE) 1289 bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_NEVER); 1290 #else 1291 bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_FREE); 1292 #endif 1293 1294 /* Reset the current config */ 1295 /* Protect access to bta_av_co_cb.codec_config */ 1296 mutex_global_lock(); 1297 bta_av_co_cb.codecs = new A2dpCodecs(codec_priorities); 1298 bta_av_co_cb.codecs->init(); 1299 A2DP_InitDefaultCodec(bta_av_co_cb.codec_config); 1300 mutex_global_unlock(); 1301 1302 // NOTE: Unconditionally dispatch the event to make sure a callback with 1303 // the most recent codec info is generated. 1304 btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0); 1305 } 1306