blob: d554f539637500c1ffa1a5d979c668bf9441a24c [file] [log] [blame]
The Android Open Source Project5738f832012-12-12 16:00:35 -08001/******************************************************************************
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
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -070026#include <string.h>
The Android Open Source Project5738f832012-12-12 16:00:35 -080027#include "a2d_api.h"
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -070028#include "bt_target.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080029#include "bta_sys.h"
30#include "bta_av_api.h"
31#include "bta_av_co.h"
32#include "bta_av_ci.h"
33#include "bta_av_sbc.h"
34
35#include "btif_media.h"
36#include "sbc_encoder.h"
37#include "btif_av_co.h"
Mike J. Chen5cd8bff2014-01-31 18:16:59 -080038#include "btif_util.h"
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -070039#include "osi/include/mutex.h"
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -070040#include "osi/include/osi.h"
The Android Open Source Project5738f832012-12-12 16:00:35 -080041
42
43/*****************************************************************************
44 ** Constants
45 *****************************************************************************/
46
The Android Open Source Project5738f832012-12-12 16:00:35 -080047/* Macro to retrieve the number of elements in a statically allocated array */
48#define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a)/sizeof((__a)[0]))
49
50/* MIN and MAX macros */
51#define BTA_AV_CO_MIN(X,Y) ((X) < (Y) ? (X) : (Y))
52#define BTA_AV_CO_MAX(X,Y) ((X) > (Y) ? (X) : (Y))
53
54/* Macro to convert audio handle to index and vice versa */
55#define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1)
56#define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO)
57
The Android Open Source Project5738f832012-12-12 16:00:35 -080058/* SCMS-T protect info */
Marie Janssenb7f64bc2016-06-22 12:52:19 -070059const uint8_t bta_av_co_cp_scmst[BTA_AV_CP_INFO_LEN] = {0x02, 0x02, 0x00};
The Android Open Source Project5738f832012-12-12 16:00:35 -080060
The Android Open Source Project5738f832012-12-12 16:00:35 -080061
62/*****************************************************************************
63** Local data
64*****************************************************************************/
65typedef struct
66{
Marie Janssenb7f64bc2016-06-22 12:52:19 -070067 uint8_t sep_info_idx; /* local SEP index (in BTA tables) */
68 uint8_t seid; /* peer SEP index (in peer tables) */
69 uint8_t codec_type; /* peer SEP codec type */
70 uint8_t codec_caps[AVDT_CODEC_SIZE]; /* peer SEP codec capabilities */
71 uint8_t num_protect; /* peer SEP number of CP elements */
72 uint8_t protect_info[BTA_AV_CP_INFO_LEN]; /* peer SEP content protection info */
The Android Open Source Project5738f832012-12-12 16:00:35 -080073} tBTA_AV_CO_SINK;
74
75typedef struct
76{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -070077 BD_ADDR addr; /* address of audio/video peer */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -070078 tBTA_AV_CO_SINK sinks[A2D_CODEC_SEP_INDEX_MAX]; /* array of supported sinks */
79 tBTA_AV_CO_SINK srcs[A2D_CODEC_SEP_INDEX_MAX]; /* array of supported srcs */
80 uint8_t num_sinks; /* total number of sinks at peer */
Marie Janssenb7f64bc2016-06-22 12:52:19 -070081 uint8_t num_srcs; /* total number of srcs at peer */
82 uint8_t num_seps; /* total number of seids at peer */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -070083 uint8_t num_rx_sinks; /* number of received sinks */
Marie Janssenb7f64bc2016-06-22 12:52:19 -070084 uint8_t num_rx_srcs; /* number of received srcs */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -070085 uint8_t num_sup_sinks; /* number of supported sinks in the sinks array */
Marie Janssenb7f64bc2016-06-22 12:52:19 -070086 uint8_t num_sup_srcs; /* number of supported srcs in the srcs array */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -070087 const tBTA_AV_CO_SINK *p_sink; /* currently selected sink */
88 const tBTA_AV_CO_SINK *p_src; /* currently selected src */
Marie Janssenb7f64bc2016-06-22 12:52:19 -070089 uint8_t codec_cfg[AVDT_CODEC_SIZE]; /* current codec configuration */
90 bool cp_active; /* current CP configuration */
91 bool acp; /* acceptor */
92 bool recfg_needed; /* reconfiguration is needed */
93 bool opened; /* opened */
94 uint16_t mtu; /* maximum transmit unit size */
95 uint16_t uuid_to_connect; /* uuid of peer device */
The Android Open Source Project5738f832012-12-12 16:00:35 -080096} tBTA_AV_CO_PEER;
97
98typedef struct
99{
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700100 bool active;
101 uint8_t flag;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800102} tBTA_AV_CO_CP;
103
104typedef struct
105{
106 /* Connected peer information */
107 tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
108 /* Current codec configuration - access to this variable must be protected */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700109 uint8_t codec_cfg[AVDT_CODEC_SIZE];
110 uint8_t codec_cfg_setconfig[AVDT_CODEC_SIZE]; /* remote peer setconfig preference */
The Android Open Source Project5738f832012-12-12 16:00:35 -0800111
112 tBTA_AV_CO_CP cp;
113} tBTA_AV_CO_CB;
114
115/* Control block instance */
116static tBTA_AV_CO_CB bta_av_co_cb;
117
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700118static bool bta_av_co_cp_is_scmst(const uint8_t *p_protectinfo);
119static bool bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700120static const tBTA_AV_CO_SINK* bta_av_co_find_peer_sink_supports_codec(
121 const tBTA_AV_CO_PEER *p_peer);
122static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
123 const tBTA_AV_CO_PEER *p_peer);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800124
125/*******************************************************************************
126 **
127 ** Function bta_av_co_cp_get_flag
128 **
129 ** Description Get content protection flag
130 ** BTA_AV_CP_SCMS_COPY_NEVER
131 ** BTA_AV_CP_SCMS_COPY_ONCE
132 ** BTA_AV_CP_SCMS_COPY_FREE
133 **
134 ** Returns The current flag value
135 **
136 *******************************************************************************/
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700137static uint8_t bta_av_co_cp_get_flag(void)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800138{
The Android Open Source Project5738f832012-12-12 16:00:35 -0800139 return bta_av_co_cb.cp.flag;
140}
141
142/*******************************************************************************
143 **
144 ** Function bta_av_co_cp_set_flag
145 **
146 ** Description Set content protection flag
147 ** BTA_AV_CP_SCMS_COPY_NEVER
148 ** BTA_AV_CP_SCMS_COPY_ONCE
149 ** BTA_AV_CP_SCMS_COPY_FREE
150 **
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700151 ** Returns true if setting the SCMS flag is supported else false
The Android Open Source Project5738f832012-12-12 16:00:35 -0800152 **
153 *******************************************************************************/
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700154static bool bta_av_co_cp_set_flag(uint8_t cp_flag)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800155{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700156 APPL_TRACE_DEBUG("%s: cp_flag = %d", __func__, cp_flag);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800157
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700158#if (BTA_AV_CO_CP_SCMS_T == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800159#else
160 if (cp_flag != BTA_AV_CP_SCMS_COPY_FREE)
161 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700162 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800163 }
164#endif
165 bta_av_co_cb.cp.flag = cp_flag;
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700166 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800167}
168
169/*******************************************************************************
170 **
171 ** Function bta_av_co_get_peer
172 **
173 ** Description find the peer entry for a given handle
174 **
175 ** Returns the control block
176 **
177 *******************************************************************************/
178static tBTA_AV_CO_PEER *bta_av_co_get_peer(tBTA_AV_HNDL hndl)
179{
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700180 uint8_t index;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800181
182 index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl);
183
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700184 APPL_TRACE_DEBUG("%s: handle = %d index = %d", __func__, hndl, index);
185
The Android Open Source Project5738f832012-12-12 16:00:35 -0800186 /* Sanity check */
187 if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers))
188 {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700189 APPL_TRACE_ERROR("%s: peer index out of bounds: %d", __func__, index);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800190 return NULL;
191 }
192
193 return &bta_av_co_cb.peers[index];
194}
195
196/*******************************************************************************
197 **
198 ** Function bta_av_co_audio_init
199 **
200 ** Description This callout function is executed by AV when it is
201 ** started by calling BTA_AvRegister(). This function can be
202 ** used by the phone to initialize audio paths or for other
203 ** initialization purposes.
204 **
205 **
206 ** Returns Stream codec and content protection capabilities info.
207 **
208 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700209bool bta_av_co_audio_init(tA2D_CODEC_SEP_INDEX codec_sep_index,
210 tAVDT_CFG *p_cfg)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800211{
Anubhav Guptad81bd012014-06-19 16:50:11 +0530212 /* reset remote preference through setconfig */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700213 memset(bta_av_co_cb.codec_cfg_setconfig, 0,
214 sizeof(bta_av_co_cb.codec_cfg_setconfig));
Anubhav Guptad81bd012014-06-19 16:50:11 +0530215
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700216 return A2D_InitCodecConfig(codec_sep_index, p_cfg);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800217}
218
219/*******************************************************************************
220 **
221 ** Function bta_av_co_audio_disc_res
222 **
223 ** Description This callout function is executed by AV to report the
224 ** number of stream end points (SEP) were found during the
225 ** AVDT stream discovery process.
226 **
227 **
228 ** Returns void.
229 **
230 *******************************************************************************/
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700231void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps,
232 uint8_t num_sink, uint8_t num_src, BD_ADDR addr,
233 uint16_t uuid_local)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800234{
235 tBTA_AV_CO_PEER *p_peer;
236
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700237 APPL_TRACE_DEBUG("%s: h:x%x num_seps:%d num_sink:%d num_src:%d",
238 __func__, hndl, num_seps, num_sink, num_src);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800239
240 /* Find the peer info */
241 p_peer = bta_av_co_get_peer(hndl);
242 if (p_peer == NULL)
243 {
Pavlin Radoslavov89330a32016-08-24 11:46:58 -0700244 APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800245 return;
246 }
247
248 /* Sanity check : this should never happen */
249 if (p_peer->opened)
250 {
Pavlin Radoslavov89330a32016-08-24 11:46:58 -0700251 APPL_TRACE_ERROR("%s: peer already opened", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800252 }
253
254 /* Copy the discovery results */
255 bdcpy(p_peer->addr, addr);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700256 p_peer->num_sinks = num_sink;
Hemant Guptacc355592013-10-24 15:37:17 +0530257 p_peer->num_srcs = num_src;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800258 p_peer->num_seps = num_seps;
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700259 p_peer->num_rx_sinks = 0;
Hemant Guptacc355592013-10-24 15:37:17 +0530260 p_peer->num_rx_srcs = 0;
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700261 p_peer->num_sup_sinks = 0;
Hemant Guptacc355592013-10-24 15:37:17 +0530262 if (uuid_local == UUID_SERVCLASS_AUDIO_SINK)
263 p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE;
264 else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE)
265 p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800266}
267
268/*******************************************************************************
269 **
Hemant Guptacc355592013-10-24 15:37:17 +0530270 ** Function bta_av_audio_sink_getconfig
271 **
272 ** Description This callout function is executed by AV to retrieve the
273 ** desired codec and content protection configuration for the
274 ** A2DP Sink audio stream in Initiator.
275 **
276 **
277 ** Returns Pass or Fail for current getconfig.
278 **
279 *******************************************************************************/
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700280static tA2D_STATUS bta_av_audio_sink_getconfig(tBTA_AV_HNDL hndl,
281 tA2D_CODEC_TYPE codec_type,
282 uint8_t *p_codec_info,
283 uint8_t *p_sep_info_idx,
284 uint8_t seid,
285 uint8_t *p_num_protect,
286 uint8_t *p_protect_info)
Hemant Guptacc355592013-10-24 15:37:17 +0530287{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700288 tA2D_STATUS result = A2D_FAIL;
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700289 bool supported;
Hemant Guptacc355592013-10-24 15:37:17 +0530290 tBTA_AV_CO_PEER *p_peer;
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700291 uint8_t pref_cfg[AVDT_CODEC_SIZE];
Hemant Guptacc355592013-10-24 15:37:17 +0530292
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700293 APPL_TRACE_DEBUG("%s: handle:0x%x codec_type:%d seid:%d",
294 __func__, hndl, codec_type, 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]);
Hemant Guptacc355592013-10-24 15:37:17 +0530298
299 /* Retrieve the peer info */
300 p_peer = bta_av_co_get_peer(hndl);
301 if (p_peer == NULL)
302 {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700303 APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
Hemant Guptacc355592013-10-24 15:37:17 +0530304 return A2D_FAIL;
305 }
306
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700307 APPL_TRACE_DEBUG("%s: peer(o=%d,n_sinks=%d,n_rx_sinks=%d,n_sup_sinks=%d)",
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700308 __func__, p_peer->opened, p_peer->num_srcs,
309 p_peer->num_rx_srcs, p_peer->num_sup_srcs);
Hemant Guptacc355592013-10-24 15:37:17 +0530310
311 p_peer->num_rx_srcs++;
312
313 /* Check if this is a supported configuration */
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700314 supported = false;
Hemant Guptacc355592013-10-24 15:37:17 +0530315 switch (codec_type)
316 {
Pavlin Radoslavov89330a32016-08-24 11:46:58 -0700317 case A2D_MEDIA_CT_SBC:
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700318 supported = true;
Hemant Guptacc355592013-10-24 15:37:17 +0530319 break;
320
321 default:
322 break;
323 }
324
325 if (supported)
326 {
327 /* If there is room for a new one */
328 if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))
329 {
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700330 tBTA_AV_CO_SINK *p_src = &p_peer->srcs[p_peer->num_sup_srcs++];
Hemant Guptacc355592013-10-24 15:37:17 +0530331
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700332 APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]",
333 __func__, p_codec_info[1], p_codec_info[2],
334 p_codec_info[3], p_codec_info[4], p_codec_info[5],
335 p_codec_info[6]);
Hemant Guptacc355592013-10-24 15:37:17 +0530336
337 memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
338 p_src->codec_type = codec_type;
339 p_src->sep_info_idx = *p_sep_info_idx;
340 p_src->seid = seid;
341 p_src->num_protect = *p_num_protect;
342 memcpy(p_src->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
343 }
344 else
345 {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700346 APPL_TRACE_ERROR("%s: no more room for SRC info", __func__);
Hemant Guptacc355592013-10-24 15:37:17 +0530347 }
348 }
349
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700350 /* If last SINK get capabilities or all supported codec caps retrieved */
Hemant Guptacc355592013-10-24 15:37:17 +0530351 if ((p_peer->num_rx_srcs == p_peer->num_srcs) ||
352 (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)))
353 {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700354 APPL_TRACE_DEBUG("%s: last SRC reached", __func__);
Hemant Guptacc355592013-10-24 15:37:17 +0530355
356 /* Protect access to bta_av_co_cb.codec_cfg */
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -0700357 mutex_global_lock();
Hemant Guptacc355592013-10-24 15:37:17 +0530358
359 /* Find a src that matches the codec config */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700360 const tBTA_AV_CO_SINK *p_src =
361 bta_av_co_find_peer_src_supports_codec(p_peer);
362 if (p_src != NULL) {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700363 APPL_TRACE_DEBUG("%s: codec supported", __func__);
Hemant Guptacc355592013-10-24 15:37:17 +0530364
365 /* Build the codec configuration for this sink */
366 {
367 /* Save the new configuration */
368 p_peer->p_src = p_src;
369 /* get preferred config from src_caps */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700370 if (A2D_BuildSrc2SinkConfig(p_src->codec_caps, pref_cfg) !=
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700371 A2D_SUCCESS) {
372 mutex_global_unlock();
373 return A2D_FAIL;
374 }
Hemant Guptacc355592013-10-24 15:37:17 +0530375 memcpy(p_peer->codec_cfg, pref_cfg, AVDT_CODEC_SIZE);
376
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700377 APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]",
378 __func__, p_peer->codec_cfg[1],
379 p_peer->codec_cfg[2], p_peer->codec_cfg[3],
380 p_peer->codec_cfg[4], p_peer->codec_cfg[5],
381 p_peer->codec_cfg[6]);
Hemant Guptacc355592013-10-24 15:37:17 +0530382 /* By default, no content protection */
383 *p_num_protect = 0;
384
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700385#if (BTA_AV_CO_CP_SCMS_T == TRUE)
386 p_peer->cp_active = false;
387 bta_av_co_cb.cp.active = false;
Hemant Guptacc355592013-10-24 15:37:17 +0530388#endif
389
390 *p_sep_info_idx = p_src->sep_info_idx;
391 memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE);
392 result = A2D_SUCCESS;
393 }
394 }
395 /* Protect access to bta_av_co_cb.codec_cfg */
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -0700396 mutex_global_unlock();
Hemant Guptacc355592013-10-24 15:37:17 +0530397 }
398 return result;
399}
400/*******************************************************************************
401 **
The Android Open Source Project5738f832012-12-12 16:00:35 -0800402 ** Function bta_av_co_audio_getconfig
403 **
404 ** Description This callout function is executed by AV to retrieve the
405 ** desired codec and content protection configuration for the
406 ** audio stream.
407 **
408 **
409 ** Returns Stream codec and content protection configuration info.
410 **
411 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700412tA2D_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl,
413 tA2D_CODEC_TYPE codec_type,
414 uint8_t *p_codec_info,
415 uint8_t *p_sep_info_idx, uint8_t seid,
416 uint8_t *p_num_protect,
417 uint8_t *p_protect_info)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800418{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700419 tA2D_STATUS result = A2D_FAIL;
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700420 bool supported;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800421 tBTA_AV_CO_PEER *p_peer;
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700422 uint8_t codec_cfg[AVDT_CODEC_SIZE];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800423
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700424 APPL_TRACE_DEBUG("%s: codec_type = %d", __func__, codec_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800425
The Android Open Source Project5738f832012-12-12 16:00:35 -0800426 /* Retrieve the peer info */
427 p_peer = bta_av_co_get_peer(hndl);
428 if (p_peer == NULL)
429 {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700430 APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800431 return A2D_FAIL;
432 }
433
Hemant Guptacc355592013-10-24 15:37:17 +0530434 if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE)
435 {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700436 result = bta_av_audio_sink_getconfig(hndl, codec_type, p_codec_info,
437 p_sep_info_idx, seid,
438 p_num_protect, p_protect_info);
Hemant Guptacc355592013-10-24 15:37:17 +0530439 return result;
440 }
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700441 APPL_TRACE_DEBUG("%s: handle:0x%x codec_type:%d seid:%d",
442 __func__, hndl, codec_type, seid);
443 APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
444 __func__, *p_num_protect, p_protect_info[0],
445 p_protect_info[1], p_protect_info[2]);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700446 APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
447 __func__, p_peer->opened, p_peer->num_sinks,
448 p_peer->num_rx_sinks, p_peer->num_sup_sinks);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800449
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700450 p_peer->num_rx_sinks++;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800451
452 /* Check if this is a supported configuration */
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700453 supported = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800454 switch (codec_type)
455 {
Pavlin Radoslavov89330a32016-08-24 11:46:58 -0700456 case A2D_MEDIA_CT_SBC:
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700457 supported = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800458 break;
459
460 default:
461 break;
462 }
463
464 if (supported)
465 {
466 /* If there is room for a new one */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700467 if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) {
468 tBTA_AV_CO_SINK *p_sink = &p_peer->sinks[p_peer->num_sup_sinks++];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800469
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700470 APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800471 p_codec_info[1], p_codec_info[2], p_codec_info[3],
472 p_codec_info[4], p_codec_info[5], p_codec_info[6]);
473
474 memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
475 p_sink->codec_type = codec_type;
476 p_sink->sep_info_idx = *p_sep_info_idx;
477 p_sink->seid = seid;
478 p_sink->num_protect = *p_num_protect;
479 memcpy(p_sink->protect_info, p_protect_info, BTA_AV_CP_INFO_LEN);
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700480 } else {
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700481 APPL_TRACE_ERROR("%s: no more room for SINK info", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800482 }
483 }
484
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700485 /* If last SINK get capabilities or all supported codec capa retrieved */
486 if ((p_peer->num_rx_sinks == p_peer->num_sinks) ||
487 (p_peer->num_sup_sinks == BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700488 APPL_TRACE_DEBUG("%s: last sink reached", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800489
490 /* Protect access to bta_av_co_cb.codec_cfg */
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -0700491 mutex_global_lock();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800492
493 /* Find a sink that matches the codec config */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700494 const tBTA_AV_CO_SINK *p_sink =
495 bta_av_co_find_peer_sink_supports_codec(p_peer);
496 if (p_sink != NULL) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800497 /* stop fetching caps once we retrieved a supported codec */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700498 if (p_peer->acp) {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700499 APPL_TRACE_EVENT("%s: no need to fetch more SEPs", __func__);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700500 *p_sep_info_idx = p_peer->num_seps;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800501 }
502
The Android Open Source Project5738f832012-12-12 16:00:35 -0800503 /* Build the codec configuration for this sink */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700504 memset(codec_cfg, 0, AVDT_CODEC_SIZE);
505 if (A2D_BuildSinkConfig(bta_av_co_cb.codec_cfg,
506 p_sink->codec_caps, codec_cfg) ==
507 A2D_SUCCESS) {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700508 APPL_TRACE_DEBUG("%s: reconfig codec_cfg[%x:%x:%x:%x:%x:%x]",
509 __func__,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800510 codec_cfg[1], codec_cfg[2], codec_cfg[3],
511 codec_cfg[4], codec_cfg[5], codec_cfg[6]);
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700512 for (int i = 0; i < AVDT_CODEC_SIZE; i++) {
513 APPL_TRACE_DEBUG("%s: p_codec_info[%d]: %x",
514 __func__, i, p_codec_info[i]);
515 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800516
517 /* Save the new configuration */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700518 p_peer->p_sink = p_sink;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800519 memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
520
521 /* By default, no content protection */
522 *p_num_protect = 0;
523
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700524#if (BTA_AV_CO_CP_SCMS_T == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800525 /* Check if this sink supports SCMS */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700526 p_peer->cp_active = bta_av_co_audio_sink_has_scmst(p_sink);
527 bta_av_co_cb.cp.active = p_peer->cp_active;
528 if (p_peer->cp_active) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800529 *p_num_protect = BTA_AV_CP_INFO_LEN;
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700530 memcpy(p_protect_info, bta_av_co_cp_scmst,
531 BTA_AV_CP_INFO_LEN);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800532 }
533#endif
534
535 /* If acceptor -> reconfig otherwise reply for configuration */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700536 if (p_peer->acp) {
537 if (p_peer->recfg_needed) {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700538 APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)",
539 __func__, hndl);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700540 BTA_AvReconfig(hndl, true, p_sink->sep_info_idx,
541 p_peer->codec_cfg, *p_num_protect,
542 bta_av_co_cp_scmst);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800543 }
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700544 } else {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800545 *p_sep_info_idx = p_sink->sep_info_idx;
546 memcpy(p_codec_info, p_peer->codec_cfg, AVDT_CODEC_SIZE);
547 }
548 result = A2D_SUCCESS;
549 }
550 }
551 /* Protect access to bta_av_co_cb.codec_cfg */
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -0700552 mutex_global_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800553 }
554 return result;
555}
556
557/*******************************************************************************
558 **
559 ** Function bta_av_co_audio_setconfig
560 **
561 ** Description This callout function is executed by AV to set the codec and
562 ** content protection configuration of the audio stream.
563 **
564 **
565 ** Returns void
566 **
567 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700568void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type,
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700569 uint8_t *p_codec_info, UNUSED_ATTR uint8_t seid,
570 UNUSED_ATTR BD_ADDR addr, uint8_t num_protect,
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700571 uint8_t *p_protect_info, uint8_t t_local_sep,
572 uint8_t avdt_handle)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800573{
574 tBTA_AV_CO_PEER *p_peer;
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700575 tA2D_STATUS status = A2D_SUCCESS;
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700576 uint8_t category = A2D_SUCCESS;
577 bool recfg_needed = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800578
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700579 APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]",
580 __func__,
The Android Open Source Project5738f832012-12-12 16:00:35 -0800581 p_codec_info[1], p_codec_info[2], p_codec_info[3],
582 p_codec_info[4], p_codec_info[5], p_codec_info[6]);
Sharvil Nanavatie8c3d752014-05-04 10:12:26 -0700583 APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
The Android Open Source Project5738f832012-12-12 16:00:35 -0800584 num_protect, p_protect_info[0], p_protect_info[1], p_protect_info[2]);
585
586 /* Retrieve the peer info */
587 p_peer = bta_av_co_get_peer(hndl);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700588 if (p_peer == NULL) {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700589 APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800590 /* Call call-in rejecting the configuration */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700591 bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, false,
592 avdt_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800593 return;
594 }
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700595
596 APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
597 __func__, p_peer->opened, p_peer->num_sinks,
598 p_peer->num_rx_sinks, p_peer->num_sup_sinks);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800599
600 /* Sanity check: should not be opened at this point */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700601 if (p_peer->opened) {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700602 APPL_TRACE_ERROR("%s: peer already in use", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800603 }
604
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700605 if (num_protect != 0) {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700606#if (BTA_AV_CO_CP_SCMS_T == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800607 /* If CP is supported */
608 if ((num_protect != 1) ||
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700609 (bta_av_co_cp_is_scmst(p_protect_info) == false)) {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700610 APPL_TRACE_ERROR("%s: wrong CP configuration", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800611 status = A2D_BAD_CP_TYPE;
612 category = AVDT_ASC_PROTECT;
613 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800614#else
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700615 /* Do not support content protection for the time being */
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700616 APPL_TRACE_ERROR("%s: wrong CP configuration", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800617 status = A2D_BAD_CP_TYPE;
618 category = AVDT_ASC_PROTECT;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800619#endif
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700620 }
621
622 if (status == A2D_SUCCESS) {
623 bool codec_cfg_supported = false;
624 if (t_local_sep == AVDT_TSEP_SNK) {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700625 APPL_TRACE_DEBUG("%s: peer is A2DP SRC", __func__);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700626 codec_cfg_supported = A2D_IsSinkCodecSupported(p_codec_info);
Hemant Guptacc355592013-10-24 15:37:17 +0530627 }
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700628 if (t_local_sep == AVDT_TSEP_SRC) {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700629 APPL_TRACE_DEBUG("%s: peer is A2DP SINK", __func__);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700630 codec_cfg_supported = A2D_IsSourceCodecSupported(p_codec_info);
Hemant Guptacc355592013-10-24 15:37:17 +0530631 }
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700632
Hemant Guptacc355592013-10-24 15:37:17 +0530633 /* Check if codec configuration is supported */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700634 if (codec_cfg_supported) {
Hemant Guptacc355592013-10-24 15:37:17 +0530635
The Android Open Source Project5738f832012-12-12 16:00:35 -0800636 /* Protect access to bta_av_co_cb.codec_cfg */
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -0700637 mutex_global_lock();
The Android Open Source Project5738f832012-12-12 16:00:35 -0800638
639 /* Check if the configuration matches the current codec config */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700640 if (A2D_CodecRequiresReconfig(p_codec_info,
641 bta_av_co_cb.codec_cfg)) {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700642 recfg_needed = true;
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700643 } else if ((num_protect == 1) && (!bta_av_co_cb.cp.active)) {
644 recfg_needed = true;
645 }
646 memcpy(bta_av_co_cb.codec_cfg_setconfig, p_codec_info,
647 AVDT_CODEC_SIZE);
648 if (t_local_sep == AVDT_TSEP_SNK) {
649 /*
650 * If Peer is SRC, and our cfg subset matches with what is
651 * requested by peer, then just accept what peer wants.
652 */
653 memcpy(bta_av_co_cb.codec_cfg, p_codec_info, AVDT_CODEC_SIZE);
654 recfg_needed = false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800655 }
656 /* Protect access to bta_av_co_cb.codec_cfg */
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -0700657 mutex_global_unlock();
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700658 } else {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800659 category = AVDT_ASC_CODEC;
660 status = A2D_WRONG_CODEC;
661 }
662 }
663
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700664 if (status != A2D_SUCCESS) {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700665 APPL_TRACE_DEBUG("%s: reject s=%d c=%d", __func__, status, category);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800666 /* Call call-in rejecting the configuration */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700667 bta_av_ci_setconfig(hndl, status, category, 0, NULL, false,
668 avdt_handle);
669 return;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800670 }
The Android Open Source Project5738f832012-12-12 16:00:35 -0800671
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700672 /* Mark that this is an acceptor peer */
673 p_peer->acp = true;
674 p_peer->recfg_needed = recfg_needed;
675 APPL_TRACE_DEBUG("%s: accept reconf=%d", __func__, recfg_needed);
676 /* Call call-in accepting the configuration */
677 bta_av_ci_setconfig(hndl, A2D_SUCCESS, A2D_SUCCESS, 0, NULL, recfg_needed,
678 avdt_handle);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800679}
680
681/*******************************************************************************
682 **
683 ** Function bta_av_co_audio_open
684 **
685 ** Description This function is called by AV when the audio stream connection
686 ** is opened.
687 **
688 **
689 ** Returns void
690 **
691 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700692void bta_av_co_audio_open(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type,
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700693 uint8_t *p_codec_info, uint16_t mtu)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800694{
695 tBTA_AV_CO_PEER *p_peer;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800696 UNUSED(p_codec_info);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800697
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700698 APPL_TRACE_DEBUG("%s: mtu:%d codec_type:%d", __func__, mtu, codec_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800699
700 /* Retrieve the peer info */
701 p_peer = bta_av_co_get_peer(hndl);
702 if (p_peer == NULL)
703 {
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700704 APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800705 }
706 else
707 {
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700708 p_peer->opened = true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800709 p_peer->mtu = mtu;
710 }
711}
712
713/*******************************************************************************
714 **
715 ** Function bta_av_co_audio_close
716 **
717 ** Description This function is called by AV when the audio stream connection
718 ** is closed.
719 **
720 **
721 ** Returns void
722 **
723 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700724void bta_av_co_audio_close(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type,
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700725 uint16_t mtu)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800726
727{
728 tBTA_AV_CO_PEER *p_peer;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800729 UNUSED(codec_type);
730 UNUSED(mtu);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800731
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700732 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800733
734 /* Retrieve the peer info */
735 p_peer = bta_av_co_get_peer(hndl);
736 if (p_peer)
737 {
738 /* Mark the peer closed and clean the peer info */
739 memset(p_peer, 0, sizeof(*p_peer));
740 }
741 else
742 {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700743 APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800744 }
745
746 /* reset remote preference through setconfig */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700747 memset(bta_av_co_cb.codec_cfg_setconfig, 0,
748 sizeof(bta_av_co_cb.codec_cfg_setconfig));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800749}
750
751/*******************************************************************************
752 **
753 ** Function bta_av_co_audio_start
754 **
755 ** Description This function is called by AV when the audio streaming data
756 ** transfer is started.
757 **
758 **
759 ** Returns void
760 **
761 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700762void bta_av_co_audio_start(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type,
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700763 uint8_t *p_codec_info, bool *p_no_rtp_hdr)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800764{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800765 UNUSED(hndl);
766 UNUSED(codec_type);
767 UNUSED(p_codec_info);
768 UNUSED(p_no_rtp_hdr);
769
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700770 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800771}
772
773/*******************************************************************************
774 **
775 ** Function bta_av_co_audio_stop
776 **
777 ** Description This function is called by AV when the audio streaming data
778 ** transfer is stopped.
779 **
780 **
781 ** Returns void
782 **
783 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700784void bta_av_co_audio_stop(tBTA_AV_HNDL hndl, tA2D_CODEC_TYPE codec_type)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800785{
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800786 UNUSED(hndl);
787 UNUSED(codec_type);
788
Pavlin Radoslavov7aaf7c62016-08-23 12:24:03 -0700789 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800790}
791
792/*******************************************************************************
793 **
794 ** Function bta_av_co_audio_src_data_path
795 **
796 ** Description This function is called to manage data transfer from
797 ** the audio codec to AVDTP.
798 **
799 ** Returns Pointer to the GKI buffer to send, NULL if no buffer to send
800 **
801 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700802void * bta_av_co_audio_src_data_path(tA2D_CODEC_TYPE codec_type,
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700803 UNUSED_ATTR uint32_t *p_len,
804 uint32_t *p_timestamp)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800805{
806 BT_HDR *p_buf;
Mike J. Chen5cd8bff2014-01-31 18:16:59 -0800807
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700808 APPL_TRACE_DEBUG("%s: codec_type = %d", __func__, codec_type);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800809
810 p_buf = btif_media_aa_readbuf();
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700811 if (p_buf == NULL)
812 return NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800813
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700814 switch (codec_type) {
815 case A2D_MEDIA_CT_SBC:
816 /* In media packet SBC, the following information is available:
817 * p_buf->layer_specific : number of SBC frames in the packet
818 * p_buf->word[0] : timestamp
819 */
820 /* Retrieve the timestamp information from the media packet */
821 *p_timestamp = *((uint32_t *) (p_buf + 1));
The Android Open Source Project5738f832012-12-12 16:00:35 -0800822
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700823 /* Set up packet header */
824 bta_av_sbc_bld_hdr(p_buf, p_buf->layer_specific);
825 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800826
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700827 default:
828 APPL_TRACE_ERROR("%s: unsupported codec type (%d)", __func__,
829 codec_type);
830 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800831 }
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700832
833#if (BTA_AV_CO_CP_SCMS_T == TRUE)
834 if (bta_av_co_cb.cp.active) {
835 p_buf->len++;
836 p_buf->offset--;
837 uint8_t *p = (uint8_t *)(p_buf + 1) + p_buf->offset;
838 *p = bta_av_co_cp_get_flag();
839 }
840#endif
841
The Android Open Source Project5738f832012-12-12 16:00:35 -0800842 return p_buf;
843}
844
845/*******************************************************************************
846 **
847 ** Function bta_av_co_audio_drop
848 **
849 ** Description An Audio packet is dropped. .
850 ** It's very likely that the connected headset with this handle
851 ** is moved far away. The implementation may want to reduce
852 ** the encoder bit rate setting to reduce the packet size.
853 **
854 ** Returns void
855 **
856 *******************************************************************************/
857void bta_av_co_audio_drop(tBTA_AV_HNDL hndl)
858{
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700859 APPL_TRACE_ERROR("%s: dropped audio packet on handle 0x%x",
860 __func__, hndl);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800861}
862
863/*******************************************************************************
864 **
865 ** Function bta_av_co_audio_delay
866 **
867 ** Description This function is called by AV when the audio stream connection
868 ** needs to send the initial delay report to the connected SRC.
869 **
870 **
871 ** Returns void
872 **
873 *******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700874void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800875{
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700876 APPL_TRACE_ERROR("%s: handle: x%x, delay:0x%x", __func__, hndl, delay);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800877}
878
The Android Open Source Project5738f832012-12-12 16:00:35 -0800879/*******************************************************************************
880 **
881 ** Function bta_av_co_cp_is_scmst
882 **
883 ** Description Check if a content protection service is SCMS-T
884 **
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700885 ** Returns true if this CP is SCMS-T, false otherwise
The Android Open Source Project5738f832012-12-12 16:00:35 -0800886 **
887 *******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700888static bool bta_av_co_cp_is_scmst(const uint8_t *p_protectinfo)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800889{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700890 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800891
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700892 if (*p_protectinfo >= BTA_AV_CP_LOSC) {
893 uint16_t cp_id;
894
The Android Open Source Project5738f832012-12-12 16:00:35 -0800895 p_protectinfo++;
896 STREAM_TO_UINT16(cp_id, p_protectinfo);
897 if (cp_id == BTA_AV_CP_SCMS_T_ID)
898 {
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700899 APPL_TRACE_DEBUG("%s: SCMS-T found", __func__);
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700900 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800901 }
902 }
903
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700904 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800905}
906
907/*******************************************************************************
908 **
909 ** Function bta_av_co_audio_sink_has_scmst
910 **
911 ** Description Check if a sink supports SCMS-T
912 **
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700913 ** Returns true if the sink supports this CP, false otherwise
The Android Open Source Project5738f832012-12-12 16:00:35 -0800914 **
915 *******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700916static bool bta_av_co_audio_sink_has_scmst(const tBTA_AV_CO_SINK *p_sink)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800917{
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700918 uint8_t index;
919 const uint8_t *p;
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700920
921 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800922
923 /* Check if sink supports SCMS-T */
924 index = p_sink->num_protect;
925 p = &p_sink->protect_info[0];
926
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700927 while (index) {
The Android Open Source Project5738f832012-12-12 16:00:35 -0800928 if (bta_av_co_cp_is_scmst(p))
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700929 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800930 /* Move to the next SC */
931 p += *p + 1;
932 /* Decrement the SC counter */
933 index--;
934 }
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -0700935 APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__);
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700936 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800937}
938
939/*******************************************************************************
940 **
941 ** Function bta_av_co_audio_sink_supports_cp
942 **
943 ** Description Check if a sink supports the current content protection
944 **
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700945 ** Returns true if the sink supports this CP, false otherwise
The Android Open Source Project5738f832012-12-12 16:00:35 -0800946 **
947 *******************************************************************************/
Marie Janssenb7f64bc2016-06-22 12:52:19 -0700948static bool bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK *p_sink)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800949{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700950 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800951
952 /* Check if content protection is enabled for this stream */
953 if (bta_av_co_cp_get_flag() != BTA_AV_CP_SCMS_COPY_FREE)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800954 return bta_av_co_audio_sink_has_scmst(p_sink);
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700955
956 APPL_TRACE_DEBUG("%s: not required", __func__);
957 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800958}
959
960/*******************************************************************************
961 **
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700962 ** Function bta_av_co_find_peer_sink_supports_codec
The Android Open Source Project5738f832012-12-12 16:00:35 -0800963 **
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700964 ** Description Find a peer acting as a sink that suppors codec config
The Android Open Source Project5738f832012-12-12 16:00:35 -0800965 **
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700966 ** Returns The peer sink that supports the codec, otherwise NULL.
The Android Open Source Project5738f832012-12-12 16:00:35 -0800967 **
968 *******************************************************************************/
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700969static const tBTA_AV_CO_SINK* bta_av_co_find_peer_sink_supports_codec(
970 const tBTA_AV_CO_PEER *p_peer)
The Android Open Source Project5738f832012-12-12 16:00:35 -0800971{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700972 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -0800973
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700974 for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
975 if (A2D_CodecConfigMatchesCapabilities(bta_av_co_cb.codec_cfg,
976 p_peer->sinks[index].codec_caps)) {
977 return &p_peer->sinks[index];
The Android Open Source Project5738f832012-12-12 16:00:35 -0800978 }
979 }
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700980 return NULL;
The Android Open Source Project5738f832012-12-12 16:00:35 -0800981}
982
983/*******************************************************************************
984 **
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700985 ** Function bta_av_co_find_peer_src_supports_codec
Hemant Guptacc355592013-10-24 15:37:17 +0530986 **
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700987 ** Description Find a peer acting as src that supports codec config
Hemant Guptacc355592013-10-24 15:37:17 +0530988 **
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700989 ** Returns The peer source that supports the codec, otherwise NULL.
Hemant Guptacc355592013-10-24 15:37:17 +0530990 **
991 *******************************************************************************/
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700992static const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
993 const tBTA_AV_CO_PEER *p_peer)
Hemant Guptacc355592013-10-24 15:37:17 +0530994{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -0700995 APPL_TRACE_DEBUG("%s", __func__);
Hemant Guptacc355592013-10-24 15:37:17 +0530996
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -0700997 for (size_t index = 0; index < p_peer->num_sup_srcs; index++) {
998 const uint8_t *p_codec_caps = p_peer->srcs[index].codec_caps;
999 if (A2D_CodecTypeEquals(bta_av_co_cb.codec_cfg, p_codec_caps) &&
1000 A2D_IsPeerSourceCodecSupported(p_codec_caps)) {
1001 return &p_peer->srcs[index];
Hemant Guptacc355592013-10-24 15:37:17 +05301002 }
1003 }
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001004 return NULL;
Hemant Guptacc355592013-10-24 15:37:17 +05301005}
1006
1007/*******************************************************************************
1008 **
The Android Open Source Project5738f832012-12-12 16:00:35 -08001009 ** Function bta_av_co_audio_codec_supported
1010 **
1011 ** Description Check if all opened connections are compatible with a codec
1012 ** configuration and content protection
1013 **
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001014 ** Returns true if all opened devices support this codec, false otherwise
The Android Open Source Project5738f832012-12-12 16:00:35 -08001015 **
1016 *******************************************************************************/
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001017static bool bta_av_co_audio_codec_supported(void)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001018{
Pavlin Radoslavov89330a32016-08-24 11:46:58 -07001019 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001020
1021 /* Check AV feeding is supported */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001022 for (uint8_t index = 0; index < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers);
1023 index++) {
1024 uint8_t codec_cfg[AVDT_CODEC_SIZE];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001025
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001026 tBTA_AV_CO_PEER *p_peer = &bta_av_co_cb.peers[index];
1027 if (!p_peer->opened)
1028 continue;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001029
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001030 const tBTA_AV_CO_SINK *p_sink =
1031 bta_av_co_find_peer_sink_supports_codec(p_peer);
1032 if (p_sink == NULL) {
1033 APPL_TRACE_DEBUG("%s: index %d doesn't support codec",
1034 __func__, index);
1035 return false;
1036 }
1037
1038 /* Check that this sink is compatible with the CP */
1039 if (!bta_av_co_audio_sink_supports_cp(p_sink)) {
1040 APPL_TRACE_DEBUG("%s: sink of peer %d doesn't support cp",
1041 __func__, index);
1042 return false;
1043 }
1044
1045 /* Build the codec configuration for this sink */
1046 memset(codec_cfg, 0, AVDT_CODEC_SIZE);
1047 if (A2D_BuildSinkConfig(bta_av_co_cb.codec_cfg, p_sink->codec_caps,
1048 codec_cfg) != A2D_SUCCESS) {
1049 continue;
1050 }
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001051#if (BTA_AV_CO_CP_SCMS_T == TRUE)
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001052 /* Check if this sink supports SCMS */
1053 bool cp_active = bta_av_co_audio_sink_has_scmst(p_sink);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001054#endif
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001055 /* Check if this is a new configuration (new sink or new config) */
1056 if ((p_sink != p_peer->p_sink) ||
1057 (!A2D_CodecEquals(codec_cfg, p_peer->codec_cfg))
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001058#if (BTA_AV_CO_CP_SCMS_T == TRUE)
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001059 || (p_peer->cp_active != cp_active)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001060#endif
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001061 ) {
1062 uint8_t num_protect = 0;
1063
1064 /* Save the new configuration */
1065 p_peer->p_sink = p_sink;
1066 memcpy(p_peer->codec_cfg, codec_cfg, AVDT_CODEC_SIZE);
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001067#if (BTA_AV_CO_CP_SCMS_T == TRUE)
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001068 bta_av_co_cb.cp.active = cp_active;
1069 p_peer->cp_active = cp_active;
1070 if (p_peer->cp_active)
1071 num_protect = BTA_AV_CP_INFO_LEN;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001072#endif
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001073 APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(0x%x)", __func__,
1074 BTA_AV_CO_AUDIO_INDX_TO_HNDL(index));
1075 BTA_AvReconfig(BTA_AV_CO_AUDIO_INDX_TO_HNDL(index), true,
1076 p_sink->sep_info_idx, p_peer->codec_cfg,
1077 num_protect, bta_av_co_cp_scmst);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001078 }
1079 }
1080
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001081 return true;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001082}
1083
1084/*******************************************************************************
1085 **
1086 ** Function bta_av_co_audio_codec_reset
1087 **
1088 ** Description Reset the current codec configuration
1089 **
1090 ** Returns void
1091 **
1092 *******************************************************************************/
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001093static void bta_av_co_audio_codec_reset(void)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001094{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -07001095 APPL_TRACE_DEBUG("%s", __func__);
1096
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -07001097 mutex_global_lock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001098
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001099 /* Reset the current configuration to the default codec */
1100 A2D_InitDefaultCodec(bta_av_co_cb.codec_cfg);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001101
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -07001102 mutex_global_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001103}
1104
1105/*******************************************************************************
1106 **
1107 ** Function bta_av_co_audio_set_codec
1108 **
1109 ** Description Set the current codec configuration from the feeding type.
1110 ** This function is starting to modify the configuration, it
1111 ** should be protected.
1112 **
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001113 ** Returns true if successful, false otherwise
The Android Open Source Project5738f832012-12-12 16:00:35 -08001114 **
1115 *******************************************************************************/
Pavlin Radoslavov79506e82016-09-07 21:57:47 -07001116bool bta_av_co_audio_set_codec(const tA2D_AV_MEDIA_FEEDINGS *p_feeding)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001117{
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001118 uint8_t new_cfg[AVDT_CODEC_SIZE];
The Android Open Source Project5738f832012-12-12 16:00:35 -08001119
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001120 if (!A2D_SetCodec(p_feeding, new_cfg))
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001121 return false;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001122
1123 /* The new config was correctly built */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001124 memcpy(bta_av_co_cb.codec_cfg, new_cfg, sizeof(new_cfg));
The Android Open Source Project5738f832012-12-12 16:00:35 -08001125
The Android Open Source Project5738f832012-12-12 16:00:35 -08001126 /* Check all devices support it */
Pavlin Radoslavova62c5a32016-08-25 15:34:57 -07001127 return bta_av_co_audio_codec_supported();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001128}
1129
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001130void bta_av_co_audio_encoder_init(tBTIF_MEDIA_INIT_AUDIO *msg)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001131{
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001132 uint16_t min_mtu = 0xFFFF;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001133
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001134 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001135
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001136 /* Protect access to bta_av_co_cb.codec_cfg */
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -07001137 mutex_global_lock();
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001138
1139 /* Compute the MTU */
1140 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
1141 const tBTA_AV_CO_PEER *p_peer = &bta_av_co_cb.peers[i];
1142 if (!p_peer->opened)
1143 continue;
1144 if (p_peer->mtu < min_mtu)
1145 min_mtu = p_peer->mtu;
1146 }
1147
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001148 const uint8_t *p_codec_info = bta_av_co_cb.codec_cfg;
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001149 msg->NumOfSubBands = A2D_GetNumberOfSubbands(p_codec_info);
1150 msg->NumOfBlocks = A2D_GetNumberOfBlocks(p_codec_info);
1151 msg->AllocationMethod = A2D_GetAllocationMethodCode(p_codec_info);
1152 msg->ChannelMode = A2D_GetChannelModeCode(p_codec_info);
1153 msg->SamplingFreq = A2D_GetSamplingFrequencyCode(p_codec_info);
1154 msg->MtuSize = min_mtu;
1155
1156 /* Protect access to bta_av_co_cb.codec_cfg */
1157 mutex_global_unlock();
1158}
1159
1160void bta_av_co_audio_encoder_update(tBTIF_MEDIA_UPDATE_AUDIO *msg)
1161{
1162 uint16_t min_mtu = 0xFFFF;
1163
1164 APPL_TRACE_DEBUG("%s", __func__);
1165
1166 /* Protect access to bta_av_co_cb.codec_cfg */
1167 mutex_global_lock();
1168
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001169 const uint8_t *p_codec_info = bta_av_co_cb.codec_cfg;
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001170 int min_bitpool = A2D_GetMinBitpool(p_codec_info);
1171 int max_bitpool = A2D_GetMaxBitpool(p_codec_info);
1172
1173 if ((min_bitpool < 0) || (max_bitpool < 0)) {
1174 APPL_TRACE_ERROR("%s: Invalid min/max bitpool: [%d, %d]",
1175 __func__, min_bitpool, max_bitpool);
1176 mutex_global_unlock();
1177 return;
1178 }
1179
1180 for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
1181 const tBTA_AV_CO_PEER *p_peer = &bta_av_co_cb.peers[i];
1182 if (!p_peer->opened)
1183 continue;
1184
1185 if (p_peer->mtu < min_mtu)
1186 min_mtu = p_peer->mtu;
1187
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001188 for (int j = 0; j < p_peer->num_sup_sinks; j++) {
1189 const tBTA_AV_CO_SINK *p_sink = &p_peer->sinks[j];
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001190 if (!A2D_CodecTypeEquals(p_codec_info, p_sink->codec_caps))
1191 continue;
1192 /* Update the bitpool boundaries of the current config */
1193 int peer_min_bitpool = A2D_GetMinBitpool(p_sink->codec_caps);
1194 int peer_max_bitpool = A2D_GetMaxBitpool(p_sink->codec_caps);
1195 if (peer_min_bitpool >= 0)
1196 min_bitpool = BTA_AV_CO_MAX(min_bitpool, peer_min_bitpool);
1197 if (peer_max_bitpool >= 0)
1198 max_bitpool = BTA_AV_CO_MIN(max_bitpool, peer_max_bitpool);
1199 APPL_TRACE_EVENT("%s: sink bitpool min %d, max %d",
1200 __func__, min_bitpool, max_bitpool);
1201 break;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001202 }
1203 }
1204
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001205 /*
1206 * Check if the remote Sink has a preferred bitpool range.
1207 * Adjust our preferred bitpool with the remote preference if within
1208 * our capable range.
1209 */
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001210 if (A2D_IsValidCodec(bta_av_co_cb.codec_cfg_setconfig) &&
1211 A2D_CodecTypeEquals(p_codec_info, bta_av_co_cb.codec_cfg_setconfig)) {
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001212 int setconfig_min_bitpool =
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001213 A2D_GetMinBitpool(bta_av_co_cb.codec_cfg_setconfig);
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001214 int setconfig_max_bitpool =
Pavlin Radoslavovc66edf32016-09-15 17:50:18 -07001215 A2D_GetMaxBitpool(bta_av_co_cb.codec_cfg_setconfig);
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001216 if (setconfig_min_bitpool >= 0)
1217 min_bitpool = BTA_AV_CO_MAX(min_bitpool, setconfig_min_bitpool);
1218 if (setconfig_max_bitpool >= 0)
1219 max_bitpool = BTA_AV_CO_MIN(max_bitpool, setconfig_max_bitpool);
1220 APPL_TRACE_EVENT("%s: sink adjusted bitpool min %d, max %d",
1221 __func__, min_bitpool, max_bitpool);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001222 }
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001223
1224 /* Protect access to bta_av_co_cb.codec_cfg */
Pavlin Radoslavov1eb1ea02015-09-24 22:07:53 -07001225 mutex_global_unlock();
The Android Open Source Project5738f832012-12-12 16:00:35 -08001226
Pavlin Radoslavovb18f03e2016-09-13 15:02:52 -07001227 if (min_bitpool > max_bitpool) {
1228 APPL_TRACE_ERROR("%s: Irrational min/max bitpool: [%d, %d]",
1229 __func__, min_bitpool, max_bitpool);
1230 return;
1231 }
1232
1233 msg->MinMtuSize = min_mtu;
1234 msg->MinBitPool = min_bitpool;
1235 msg->MaxBitPool = max_bitpool;
The Android Open Source Project5738f832012-12-12 16:00:35 -08001236}
1237
1238/*******************************************************************************
1239 **
The Android Open Source Project5738f832012-12-12 16:00:35 -08001240 ** Function bta_av_co_init
1241 **
1242 ** Description Initialization
1243 **
1244 ** Returns Nothing
1245 **
1246 *******************************************************************************/
1247void bta_av_co_init(void)
1248{
Pavlin Radoslavov79506e82016-09-07 21:57:47 -07001249 APPL_TRACE_DEBUG("%s", __func__);
The Android Open Source Project5738f832012-12-12 16:00:35 -08001250
1251 /* Reset the control block */
1252 memset(&bta_av_co_cb, 0, sizeof(bta_av_co_cb));
1253
Marie Janssenb7f64bc2016-06-22 12:52:19 -07001254#if (BTA_AV_CO_CP_SCMS_T == TRUE)
The Android Open Source Project5738f832012-12-12 16:00:35 -08001255 bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_NEVER);
1256#else
1257 bta_av_co_cp_set_flag(BTA_AV_CP_SCMS_COPY_FREE);
1258#endif
1259
1260 /* Reset the current config */
1261 bta_av_co_audio_codec_reset();
1262}