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