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:
BtaAvCoCb()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
reset()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 ******************************************************************************/
bta_av_co_cp_get_flag(void)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 ******************************************************************************/
bta_av_co_cp_set_flag(uint8_t cp_flag)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 ******************************************************************************/
bta_av_co_get_peer(tBTA_AV_HNDL hndl)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 ******************************************************************************/
bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index,tAVDT_CFG * p_cfg)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 ******************************************************************************/
bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl,uint8_t num_seps,uint8_t num_sink,uint8_t num_src,BD_ADDR addr,uint16_t uuid_local)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 ******************************************************************************/
bta_av_audio_sink_getconfig(tBTA_AV_HNDL hndl,uint8_t * p_codec_info,uint8_t * p_sep_info_idx,uint8_t seid,uint8_t * p_num_protect,uint8_t * p_protect_info)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 ******************************************************************************/
bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl,uint8_t * p_codec_info,uint8_t * p_sep_info_idx,uint8_t seid,uint8_t * p_num_protect,uint8_t * p_protect_info)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 ******************************************************************************/
bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl,const uint8_t * p_codec_info,UNUSED_ATTR uint8_t seid,UNUSED_ATTR BD_ADDR addr,uint8_t num_protect,const uint8_t * p_protect_info,uint8_t t_local_sep,uint8_t avdt_handle)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 ******************************************************************************/
bta_av_co_audio_open(tBTA_AV_HNDL hndl,uint16_t mtu)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 ******************************************************************************/
bta_av_co_audio_close(tBTA_AV_HNDL hndl)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 ******************************************************************************/
bta_av_co_audio_start(UNUSED_ATTR tBTA_AV_HNDL hndl,UNUSED_ATTR uint8_t * p_codec_info,UNUSED_ATTR bool * p_no_rtp_hdr)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 ******************************************************************************/
bta_av_co_audio_stop(UNUSED_ATTR tBTA_AV_HNDL hndl)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 ******************************************************************************/
bta_av_co_audio_src_data_path(const uint8_t * p_codec_info,uint32_t * p_timestamp)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 ******************************************************************************/
bta_av_co_audio_drop(tBTA_AV_HNDL hndl)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 ******************************************************************************/
bta_av_co_audio_delay(tBTA_AV_HNDL hndl,uint16_t delay)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
bta_av_co_audio_update_mtu(tBTA_AV_HNDL hndl,uint16_t mtu)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 ******************************************************************************/
bta_av_co_cp_is_scmst(const uint8_t * p_protect_info)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.
bta_av_co_audio_protect_has_scmst(uint8_t num_protect,const uint8_t * p_protect_info)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 ******************************************************************************/
bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK * p_sink)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 ******************************************************************************/
bta_av_co_find_peer_src_supports_codec(const tBTA_AV_CO_PEER * p_peer)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 //
bta_av_co_audio_set_codec(tBTA_AV_CO_PEER * p_peer)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.
bta_av_co_audio_codec_selected(A2dpCodecConfig & codec_config,tBTA_AV_CO_PEER * p_peer)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.
bta_av_co_audio_update_selectable_codec(A2dpCodecConfig & codec_config,const tBTA_AV_CO_PEER * p_peer)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
bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER * p_peer,const uint8_t * new_codec_config,uint8_t num_protect,const uint8_t * p_protect_info)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
bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS * p_peer_params)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
bta_av_co_get_encoder_interface(void)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
bta_av_co_set_codec_user_config(const btav_a2dp_codec_config_t & codec_user_config)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.
bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER * p_peer,const uint8_t * p_ota_codec_config,uint8_t num_protect,const uint8_t * p_protect_info,bool * p_restart_output)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
bta_av_co_set_codec_audio_config(const btav_a2dp_codec_config_t & codec_audio_config)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
bta_av_get_a2dp_codecs(void)1265 A2dpCodecs* bta_av_get_a2dp_codecs(void) { return bta_av_co_cb.codecs; }
1266
bta_av_get_a2dp_current_codec(void)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
bta_av_co_init(const std::vector<btav_a2dp_codec_config_t> & codec_priorities)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