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