15738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
25738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
35738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Copyright (C) 2004-2012 Broadcom Corporation
45738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
55738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Licensed under the Apache License, Version 2.0 (the "License");
65738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  you may not use this file except in compliance with the License.
75738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  You may obtain a copy of the License at:
85738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
95738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  http://www.apache.org/licenses/LICENSE-2.0
105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  See the License for the specific language governing permissions and
155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  limitations under the License.
165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/******************************************************************************
205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  This is the advanced audio/video call-out function implementation for
225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *  BTIF.
235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *
245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ******************************************************************************/
255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
266bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson#include "bta_av_co.h"
27f2af1c42ccb2f642b241c2261b42d0be61d45438Jack He#include <base/logging.h>
28b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov#include <string.h>
29f66f4e95f2b4bc8d36033f2d65b387e32601fcd8Pavlin Radoslavov#include "a2dp_api.h"
305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#include "a2dp_sbc.h"
31a62c5a302e54568a3d2c164a7dbef52f279512f2Pavlin Radoslavov#include "bt_target.h"
325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bta_av_api.h"
335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "bta_av_ci.h"
346bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson#include "bta_sys.h"
355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#include "btif_av.h"
375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#include "btif_av_co.h"
385cd8bff2dd0337cb52bf48f312e3d2d55a8882fbMike J. Chen#include "btif_util.h"
391eb1ea0cf2da992a3193506806e571dcbe3ec947Pavlin Radoslavov#include "osi/include/mutex.h"
40c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov#include "osi/include/osi.h"
415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **  Constants
445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project *****************************************************************************/
455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Macro to retrieve the number of elements in a statically allocated array */
476bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson#define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a) / sizeof((__a)[0]))
485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Macro to convert audio handle to index and vice versa */
505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl) (((hndl) & (~BTA_AV_CHNL_MSK)) - 1)
515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#define BTA_AV_CO_AUDIO_INDX_TO_HNDL(indx) (((indx) + 1) | BTA_AV_CHNL_AUDIO)
525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* SCMS-T protect info */
54feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavovconst uint8_t bta_av_co_cp_scmst[AVDT_CP_INFO_LEN] = {0x02, 0x02, 0x00};
555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*****************************************************************************
576bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson *  Local data
586bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson ****************************************************************************/
596bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsontypedef struct {
609008888d24407541aa383aa4bd363a40abbf954bMyles Watson  uint8_t sep_info_idx;                   /* local SEP index (in BTA tables) */
619008888d24407541aa383aa4bd363a40abbf954bMyles Watson  uint8_t seid;                           /* peer SEP index (in peer tables) */
629008888d24407541aa383aa4bd363a40abbf954bMyles Watson  uint8_t codec_caps[AVDT_CODEC_SIZE];    /* peer SEP codec capabilities */
639008888d24407541aa383aa4bd363a40abbf954bMyles Watson  uint8_t num_protect;                    /* peer SEP number of CP elements */
64feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov  uint8_t protect_info[AVDT_CP_INFO_LEN]; /* peer SEP content protection info */
655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} tBTA_AV_CO_SINK;
665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
676bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsontypedef struct {
689e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski  RawAddress addr; /* address of audio/video peer */
696bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_SINK
705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      sinks[BTAV_A2DP_CODEC_INDEX_MAX]; /* array of supported sinks */
715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  tBTA_AV_CO_SINK srcs[BTAV_A2DP_CODEC_INDEX_MAX]; /* array of supported srcs */
726bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t num_sinks;     /* total number of sinks at peer */
736bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t num_srcs;      /* total number of srcs at peer */
746bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t num_seps;      /* total number of seids at peer */
756bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t num_rx_sinks;  /* number of received sinks */
766bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t num_rx_srcs;   /* number of received srcs */
776bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t num_sup_sinks; /* number of supported sinks in the sinks array */
786bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t num_sup_srcs;  /* number of supported srcs in the srcs array */
799008888d24407541aa383aa4bd363a40abbf954bMyles Watson  const tBTA_AV_CO_SINK* p_sink;         /* currently selected sink */
809008888d24407541aa383aa4bd363a40abbf954bMyles Watson  const tBTA_AV_CO_SINK* p_src;          /* currently selected src */
8182fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  uint8_t codec_config[AVDT_CODEC_SIZE]; /* current codec configuration */
829008888d24407541aa383aa4bd363a40abbf954bMyles Watson  bool cp_active;                        /* current CP configuration */
839008888d24407541aa383aa4bd363a40abbf954bMyles Watson  bool acp;                              /* acceptor */
849008888d24407541aa383aa4bd363a40abbf954bMyles Watson  bool reconfig_needed;                  /* reconfiguration is needed */
859008888d24407541aa383aa4bd363a40abbf954bMyles Watson  bool opened;                           /* opened */
869008888d24407541aa383aa4bd363a40abbf954bMyles Watson  uint16_t mtu;                          /* maximum transmit unit size */
879008888d24407541aa383aa4bd363a40abbf954bMyles Watson  uint16_t uuid_to_connect;              /* uuid of peer device */
885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  tBTA_AV_HNDL handle;                   /* handle to use */
895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} tBTA_AV_CO_PEER;
905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
916bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsontypedef struct {
926bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  bool active;
936bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t flag;
945738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project} tBTA_AV_CO_CP;
955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovclass BtaAvCoCb {
975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov public:
985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  BtaAvCoCb() : codecs(nullptr) { reset(); }
995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
1006bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Connected peer information */
1016bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_PEER peers[BTA_AV_NUM_STRS];
1026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Current codec configuration - access to this variable must be protected */
10382fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  uint8_t codec_config[AVDT_CODEC_SIZE];
1045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  A2dpCodecs* codecs; /* Locally supported codecs */
1056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_CP cp;
1065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
1075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  void reset() {
1085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    delete codecs;
1095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    codecs = nullptr;
1105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // TODO: Ugly leftover reset from the original C code. Should go away once
1115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // the rest of the code in this file migrates to C++.
1125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    memset(peers, 0, sizeof(peers));
1135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    memset(codec_config, 0, sizeof(codec_config));
1145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    memset(&cp, 0, sizeof(cp));
1155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
1165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // Initialize the handles
1175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers); i++) {
1185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      tBTA_AV_CO_PEER* p_peer = &peers[i];
1195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      p_peer->handle = BTA_AV_CO_AUDIO_INDX_TO_HNDL(i);
1205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    }
1215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
1225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov};
1235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/* Control block instance */
1255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic BtaAvCoCb bta_av_co_cb;
1265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
127cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info);
128cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect,
129cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                              const uint8_t* p_protect_info);
130c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavovstatic const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
1316bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    const tBTA_AV_CO_PEER* p_peer);
132cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer);
133cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
1345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer);
135494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavovstatic bool bta_av_co_audio_update_selectable_codec(
136494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer);
137cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
138cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                            const uint8_t* new_codec_config,
139cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                            uint8_t num_protect,
140cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                            const uint8_t* p_protect_info);
1415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer,
1425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                           const uint8_t* p_ota_codec_config,
1435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                           uint8_t num_protect,
1445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                           const uint8_t* p_protect_info,
1455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                           bool* p_restart_output);
1465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1475738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1485738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
1495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_cp_get_flag
1505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
1515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      Get content protection flag
152feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov **                  AVDT_CP_SCMS_COPY_NEVER
153feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov **                  AVDT_CP_SCMS_COPY_ONCE
154feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov **                  AVDT_CP_SCMS_COPY_FREE
1555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
1565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          The current flag value
1575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
158ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1596bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic uint8_t bta_av_co_cp_get_flag(void) { return bta_av_co_cb.cp.flag; }
1605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
1635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_cp_set_flag
1645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
1655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      Set content protection flag
166feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov **                  AVDT_CP_SCMS_COPY_NEVER
167feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov **                  AVDT_CP_SCMS_COPY_ONCE
168feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov **                  AVDT_CP_SCMS_COPY_FREE
1695738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
170b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen ** Returns          true if setting the SCMS flag is supported else false
1715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
172ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1736bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic bool bta_av_co_cp_set_flag(uint8_t cp_flag) {
1746bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: cp_flag = %d", __func__, cp_flag);
1755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
176b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen#if (BTA_AV_CO_CP_SCMS_T == TRUE)
1775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
178feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov  if (cp_flag != AVDT_CP_SCMS_COPY_FREE) {
1796bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    return false;
1806bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
1815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
1826bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  bta_av_co_cb.cp.flag = cp_flag;
1836bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return true;
1845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
1875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
1885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_get_peer
1895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
1905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      find the peer entry for a given handle
1915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
1925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          the control block
1935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
194ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
1956bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic tBTA_AV_CO_PEER* bta_av_co_get_peer(tBTA_AV_HNDL hndl) {
1966bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t index;
1975738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1986bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  index = BTA_AV_CO_AUDIO_HNDL_TO_INDX(hndl);
1995738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2006bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: handle = %d index = %d", __func__, hndl, index);
20179506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
2026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Sanity check */
2036bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (index >= BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers)) {
2046bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: peer index out of bounds: %d", __func__, index);
2056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    return NULL;
2066bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
2075738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2086bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return &bta_av_co_cb.peers[index];
2095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
2135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_init
2145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
2155738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      This callout function is executed by AV when it is
2165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  started by calling BTA_AvRegister().  This function can be
2175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  used by the phone to initialize audio paths or for other
2185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  initialization purposes.
2195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
2205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
2215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          Stream codec and content protection capabilities info.
2225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
223ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool bta_av_co_audio_init(btav_a2dp_codec_index_t codec_index,
2256bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                          tAVDT_CFG* p_cfg) {
2265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  return A2DP_InitCodecConfig(codec_index, p_cfg);
2275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
2315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_disc_res
2325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
2335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      This callout function is executed by AV to report the
2345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  number of stream end points (SEP) were found during the
2355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  AVDT stream discovery process.
2365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
2375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
2385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          void.
2395738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
240ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
241c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavovvoid bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, uint8_t num_seps,
242903c16685e62e7721d44460b9171e020f38609f5Jakub Pawlowski                              uint8_t num_sink, uint8_t num_src,
2439e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski                              const RawAddress& addr, uint16_t uuid_local) {
2446bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_PEER* p_peer;
2456bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
2466bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: h:x%x num_seps:%d num_sink:%d num_src:%d", __func__,
2476bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   hndl, num_seps, num_sink, num_src);
2486bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
2496bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Find the peer info */
2506bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer = bta_av_co_get_peer(hndl);
2516bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer == NULL) {
2526bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
2536bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    return;
2546bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
2556bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
2566bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Sanity check : this should never happen */
2576bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer->opened) {
2586bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: peer already opened", __func__);
2596bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
2606bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
2616bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Copy the discovery results */
262903c16685e62e7721d44460b9171e020f38609f5Jakub Pawlowski  p_peer->addr = addr;
2636bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->num_sinks = num_sink;
2646bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->num_srcs = num_src;
2656bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->num_seps = num_seps;
2666bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->num_rx_sinks = 0;
2676bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->num_rx_srcs = 0;
2686bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->num_sup_sinks = 0;
2696bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (uuid_local == UUID_SERVCLASS_AUDIO_SINK)
2706bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SOURCE;
2716bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  else if (uuid_local == UUID_SERVCLASS_AUDIO_SOURCE)
2726bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    p_peer->uuid_to_connect = UUID_SERVCLASS_AUDIO_SINK;
2735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
2745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
2755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
2765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
277cc35559160745c60b42ae182002a59337d844d09Hemant Gupta ** Function         bta_av_audio_sink_getconfig
278cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **
279cc35559160745c60b42ae182002a59337d844d09Hemant Gupta ** Description      This callout function is executed by AV to retrieve the
280cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **                  desired codec and content protection configuration for the
281cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **                  A2DP Sink audio stream in Initiator.
282cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **
283cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **
284cc35559160745c60b42ae182002a59337d844d09Hemant Gupta ** Returns          Pass or Fail for current getconfig.
285cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **
286ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
2876bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic tA2DP_STATUS bta_av_audio_sink_getconfig(
2886bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    tBTA_AV_HNDL hndl, uint8_t* p_codec_info, uint8_t* p_sep_info_idx,
2896bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    uint8_t seid, uint8_t* p_num_protect, uint8_t* p_protect_info) {
2906bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tA2DP_STATUS result = A2DP_FAIL;
2916bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_PEER* p_peer;
2926bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
2936bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl,
2946bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   A2DP_CodecName(p_codec_info), seid);
2956bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
2966bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   __func__, *p_num_protect, p_protect_info[0],
2976bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_protect_info[1], p_protect_info[2]);
2986bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
2996bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Retrieve the peer info */
3006bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer = bta_av_co_get_peer(hndl);
3016bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer == NULL) {
3026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
3036bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    return A2DP_FAIL;
3046bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
3056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
3066bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: peer(o=%d,n_sinks=%d,n_rx_sinks=%d,n_sup_sinks=%d)",
3076bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   __func__, p_peer->opened, p_peer->num_srcs,
3086bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_peer->num_rx_srcs, p_peer->num_sup_srcs);
3096bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
3106bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->num_rx_srcs++;
3116bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
3126bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Check the peer's SOURCE codec */
3136bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (A2DP_IsPeerSourceCodecValid(p_codec_info)) {
3146bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* If there is room for a new one */
3156bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    if (p_peer->num_sup_srcs < BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs)) {
3166bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      tBTA_AV_CO_SINK* p_src = &p_peer->srcs[p_peer->num_sup_srcs++];
3176bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
3186bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
3196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                       p_codec_info[1], p_codec_info[2], p_codec_info[3],
3206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                       p_codec_info[4], p_codec_info[5], p_codec_info[6]);
3216bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
3226bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      memcpy(p_src->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
3236bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      p_src->sep_info_idx = *p_sep_info_idx;
3246bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      p_src->seid = seid;
3256bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      p_src->num_protect = *p_num_protect;
326feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov      memcpy(p_src->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
3276bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    } else {
3286bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_ERROR("%s: no more room for SRC info", __func__);
329cc35559160745c60b42ae182002a59337d844d09Hemant Gupta    }
3306bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
331cc35559160745c60b42ae182002a59337d844d09Hemant Gupta
3326bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* If last SINK get capabilities or all supported codec caps retrieved */
3336bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if ((p_peer->num_rx_srcs == p_peer->num_srcs) ||
3346bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      (p_peer->num_sup_srcs == BTA_AV_CO_NUM_ELEMENTS(p_peer->srcs))) {
3356bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_DEBUG("%s: last SRC reached", __func__);
3366bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
33782fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov    /* Protect access to bta_av_co_cb.codec_config */
3386bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    mutex_global_lock();
3396bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
3406bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* Find a src that matches the codec config */
3416bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    const tBTA_AV_CO_SINK* p_src =
3426bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson        bta_av_co_find_peer_src_supports_codec(p_peer);
3436bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    if (p_src != NULL) {
3445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      uint8_t pref_config[AVDT_CODEC_SIZE];
3456bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_DEBUG("%s: codec supported", __func__);
3466bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
3476bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      /* Build the codec configuration for this sink */
3485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      /* Save the new configuration */
3495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      p_peer->p_src = p_src;
3505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      /* get preferred config from src_caps */
3515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      if (A2DP_BuildSrc2SinkConfig(p_src->codec_caps, pref_config) !=
3525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          A2DP_SUCCESS) {
3535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov        mutex_global_unlock();
3545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov        return A2DP_FAIL;
3555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      }
3565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      memcpy(p_peer->codec_config, pref_config, AVDT_CODEC_SIZE);
357cc35559160745c60b42ae182002a59337d844d09Hemant Gupta
3585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__,
3595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                       p_peer->codec_config[1], p_peer->codec_config[2],
3605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                       p_peer->codec_config[3], p_peer->codec_config[4],
3615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                       p_peer->codec_config[5], p_peer->codec_config[6]);
3625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      /* By default, no content protection */
3635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      *p_num_protect = 0;
364cc35559160745c60b42ae182002a59337d844d09Hemant Gupta
365b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen#if (BTA_AV_CO_CP_SCMS_T == TRUE)
3665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      p_peer->cp_active = false;
3675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      bta_av_co_cb.cp.active = false;
368cc35559160745c60b42ae182002a59337d844d09Hemant Gupta#endif
369cc35559160745c60b42ae182002a59337d844d09Hemant Gupta
3705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      *p_sep_info_idx = p_src->sep_info_idx;
3715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE);
3725ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      result = A2DP_SUCCESS;
373cc35559160745c60b42ae182002a59337d844d09Hemant Gupta    }
37482fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov    /* Protect access to bta_av_co_cb.codec_config */
3756bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    mutex_global_unlock();
3766bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
3776bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return result;
378cc35559160745c60b42ae182002a59337d844d09Hemant Gupta}
379cc35559160745c60b42ae182002a59337d844d09Hemant Gupta/*******************************************************************************
380cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **
3815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_getconfig
3825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
3835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      This callout function is executed by AV to retrieve the
3845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  desired codec and content protection configuration for the
3855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  audio stream.
3865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
3875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
3885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          Stream codec and content protection configuration info.
3895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
390ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
3916bd442f543972b072ef2cbbcf2f7c91202de1045Myles WatsontA2DP_STATUS bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, uint8_t* p_codec_info,
3926bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                       uint8_t* p_sep_info_idx, uint8_t seid,
3936bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                       uint8_t* p_num_protect,
3946bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                       uint8_t* p_protect_info) {
3956bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_PEER* p_peer;
3966bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
3976bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
398c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov  A2DP_DumpCodecInfo(p_codec_info);
3996bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
4006bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Retrieve the peer info */
4016bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer = bta_av_co_get_peer(hndl);
4026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer == NULL) {
4036bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
4046bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    return A2DP_FAIL;
4056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
4066bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
4076bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer->uuid_to_connect == UUID_SERVCLASS_AUDIO_SOURCE) {
408cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    return bta_av_audio_sink_getconfig(hndl, p_codec_info, p_sep_info_idx, seid,
409cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                       p_num_protect, p_protect_info);
4106bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
4116bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: handle:0x%x codec:%s seid:%d", __func__, hndl,
4126bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   A2DP_CodecName(p_codec_info), seid);
4136bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: num_protect:0x%02x protect_info:0x%02x%02x%02x",
4146bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   __func__, *p_num_protect, p_protect_info[0],
4156bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_protect_info[1], p_protect_info[2]);
4166bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
4176bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   __func__, p_peer->opened, p_peer->num_sinks,
4186bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_peer->num_rx_sinks, p_peer->num_sup_sinks);
4196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
4206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->num_rx_sinks++;
4216bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
4226bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Check the peer's SINK codec */
4236bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (A2DP_IsPeerSinkCodecValid(p_codec_info)) {
4246bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* If there is room for a new one */
4256bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    if (p_peer->num_sup_sinks < BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks)) {
4266bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      tBTA_AV_CO_SINK* p_sink = &p_peer->sinks[p_peer->num_sup_sinks++];
4276bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
4286bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_DEBUG("%s: saved caps[%x:%x:%x:%x:%x:%x]", __func__,
4296bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                       p_codec_info[1], p_codec_info[2], p_codec_info[3],
4306bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                       p_codec_info[4], p_codec_info[5], p_codec_info[6]);
4316bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
4326bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      memcpy(p_sink->codec_caps, p_codec_info, AVDT_CODEC_SIZE);
4336bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      p_sink->sep_info_idx = *p_sep_info_idx;
4346bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      p_sink->seid = seid;
4356bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      p_sink->num_protect = *p_num_protect;
436feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov      memcpy(p_sink->protect_info, p_protect_info, AVDT_CP_INFO_LEN);
4376bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    } else {
4386bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_ERROR("%s: no more room for SINK info", __func__);
4396bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    }
4406bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
4415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
442cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  // Check if this is the last SINK get capabilities or all supported codec
443cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  // capabilities are retrieved.
444cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
445cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
446cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    return A2DP_FAIL;
447cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  }
448cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  APPL_TRACE_DEBUG("%s: last sink reached", __func__);
4495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
450cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  const tBTA_AV_CO_SINK* p_sink = bta_av_co_audio_set_codec(p_peer);
451cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  if (p_sink == NULL) {
4522073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov    APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__);
453cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    return A2DP_FAIL;
454cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  }
4555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
456cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  // By default, no content protection
457cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  *p_num_protect = 0;
458b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen#if (BTA_AV_CO_CP_SCMS_T == TRUE)
459cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  if (p_peer->cp_active) {
460cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    *p_num_protect = AVDT_CP_INFO_LEN;
461cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    memcpy(p_protect_info, bta_av_co_cp_scmst, AVDT_CP_INFO_LEN);
462cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  }
4635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
4645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
465cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  // If acceptor -> reconfig otherwise reply for configuration.
466cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  if (p_peer->acp) {
467cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    // Stop fetching caps once we retrieved a supported codec.
468cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    APPL_TRACE_EVENT("%s: no need to fetch more SEPs", __func__);
469cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    *p_sep_info_idx = p_peer->num_seps;
470cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    if (p_peer->reconfig_needed) {
471cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, hndl);
472cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      BTA_AvReconfig(hndl, true, p_sink->sep_info_idx, p_peer->codec_config,
473cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                     *p_num_protect, bta_av_co_cp_scmst);
4745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
475cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  } else {
476cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    *p_sep_info_idx = p_sink->sep_info_idx;
477cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    memcpy(p_codec_info, p_peer->codec_config, AVDT_CODEC_SIZE);
4786bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
479cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov
480cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  return A2DP_SUCCESS;
4815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
4825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
4835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
4845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
4855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_setconfig
4865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
4876bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson ** Description      This callout function is executed by AV to set the codec
488f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  and content protection configuration of the audio stream.
4895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
4905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
4915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          void
4925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
493ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
4946bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonvoid bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, const uint8_t* p_codec_info,
495b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavov                               UNUSED_ATTR uint8_t seid,
4969e030fde05352ec4385d7baf6cc2af89e95e039cJakub Pawlowski                               UNUSED_ATTR const RawAddress& addr,
497903c16685e62e7721d44460b9171e020f38609f5Jakub Pawlowski                               uint8_t num_protect,
498cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                               const uint8_t* p_protect_info,
499cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                               uint8_t t_local_sep, uint8_t avdt_handle) {
5006bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_PEER* p_peer;
5016bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tA2DP_STATUS status = A2DP_SUCCESS;
5026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint8_t category = A2DP_SUCCESS;
50382fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  bool reconfig_needed = false;
5046bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
5056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: p_codec_info[%x:%x:%x:%x:%x:%x]", __func__,
5066bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_codec_info[1], p_codec_info[2], p_codec_info[3],
5076bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_codec_info[4], p_codec_info[5], p_codec_info[6]);
5086bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("num_protect:0x%02x protect_info:0x%02x%02x%02x",
5096bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   num_protect, p_protect_info[0], p_protect_info[1],
5106bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_protect_info[2]);
511c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov  A2DP_DumpCodecInfo(p_codec_info);
5126bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
5136bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Retrieve the peer info */
5146bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer = bta_av_co_get_peer(hndl);
5156bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer == NULL) {
5166bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
5176bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* Call call-in rejecting the configuration */
5186bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    bta_av_ci_setconfig(hndl, A2DP_BUSY, AVDT_ASC_CODEC, 0, NULL, false,
5196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                        avdt_handle);
5206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    return;
5216bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
522c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
5236bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: peer(o=%d, n_sinks=%d, n_rx_sinks=%d, n_sup_sinks=%d)",
5246bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   __func__, p_peer->opened, p_peer->num_sinks,
5256bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_peer->num_rx_sinks, p_peer->num_sup_sinks);
5265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5276bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Sanity check: should not be opened at this point */
5286bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer->opened) {
5296bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: peer already in use", __func__);
5306bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
5315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5326bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (num_protect != 0) {
533b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen#if (BTA_AV_CO_CP_SCMS_T == TRUE)
5346bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* If CP is supported */
5356bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    if ((num_protect != 1) ||
5366bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson        (bta_av_co_cp_is_scmst(p_protect_info) == false)) {
5376bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_ERROR("%s: wrong CP configuration", __func__);
5386bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      status = A2DP_BAD_CP_TYPE;
5396bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      category = AVDT_ASC_PROTECT;
5406bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    }
5415738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
5426bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* Do not support content protection for the time being */
5436bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: wrong CP configuration", __func__);
5446bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    status = A2DP_BAD_CP_TYPE;
5456bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    category = AVDT_ASC_PROTECT;
5465738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
5476bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
548c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
5496bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (status == A2DP_SUCCESS) {
55082fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov    bool codec_config_supported = false;
551cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov
5526bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    if (t_local_sep == AVDT_TSEP_SNK) {
5536bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_DEBUG("%s: peer is A2DP SRC", __func__);
55482fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov      codec_config_supported = A2DP_IsSinkCodecSupported(p_codec_info);
555cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      if (codec_config_supported) {
556cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov        // If Peer is SRC, and our config subset matches with what is
557cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov        // requested by peer, then just accept what peer wants.
5585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov        bta_av_co_save_new_codec_config(p_peer, p_codec_info, num_protect,
5595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                        p_protect_info);
560cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      }
5615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5626bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    if (t_local_sep == AVDT_TSEP_SRC) {
5636bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_DEBUG("%s: peer is A2DP SINK", __func__);
5645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      bool restart_output = false;
5655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      if ((bta_av_co_cb.codecs == nullptr) ||
5665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          !bta_av_co_set_codec_ota_config(p_peer, p_codec_info, num_protect,
5675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                          p_protect_info, &restart_output)) {
5685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov        APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
569cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                         A2DP_CodecName(p_codec_info));
570cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      } else {
571cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov        codec_config_supported = true;
572cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov        // Check if reconfiguration is needed
5735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov        if (restart_output ||
574cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov            ((num_protect == 1) && (!bta_av_co_cb.cp.active))) {
575cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov          reconfig_needed = true;
576cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov        }
577cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      }
5785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
5795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
5806bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* Check if codec configuration is supported */
581cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    if (!codec_config_supported) {
5826bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      category = AVDT_ASC_CODEC;
5836bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      status = A2DP_WRONG_CODEC;
5846bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    }
5856bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
5866bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
5876bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (status != A2DP_SUCCESS) {
5886bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_DEBUG("%s: reject s=%d c=%d", __func__, status, category);
5896bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* Call call-in rejecting the configuration */
5906bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    bta_av_ci_setconfig(hndl, status, category, 0, NULL, false, avdt_handle);
5916bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    return;
5926bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
5936bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
5946bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Mark that this is an acceptor peer */
5956bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer->acp = true;
59682fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  p_peer->reconfig_needed = reconfig_needed;
59782fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  APPL_TRACE_DEBUG("%s: accept reconf=%d", __func__, reconfig_needed);
5986bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Call call-in accepting the configuration */
59982fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  bta_av_ci_setconfig(hndl, A2DP_SUCCESS, A2DP_SUCCESS, 0, NULL,
60082fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov                      reconfig_needed, avdt_handle);
6015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6025738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
6045738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_open
6065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6076bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson ** Description      This function is called by AV when the audio stream
608f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  connection is opened.
6095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6105738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6115738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          void
6125738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
613ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
614cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovvoid bta_av_co_audio_open(tBTA_AV_HNDL hndl, uint16_t mtu) {
6156bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_PEER* p_peer;
6166bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
617cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  APPL_TRACE_DEBUG("%s: handle: %d mtu:%d", __func__, hndl, mtu);
6186bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
6196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Retrieve the peer info */
6206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer = bta_av_co_get_peer(hndl);
6216bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer == NULL) {
6226bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
6236bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  } else {
6246bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    p_peer->opened = true;
6256bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    p_peer->mtu = mtu;
6266bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
6275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6285738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
6305738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6315738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_close
6325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6336bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson ** Description      This function is called by AV when the audio stream
634f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  connection is closed.
6355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          void
6385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
639ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
640cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovvoid bta_av_co_audio_close(tBTA_AV_HNDL hndl) {
6416bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  tBTA_AV_CO_PEER* p_peer;
6426bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
6436bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
6446bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
6456bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Retrieve the peer info */
6466bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_peer = bta_av_co_get_peer(hndl);
6476bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_peer) {
6486bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* Mark the peer closed and clean the peer info */
6496bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    memset(p_peer, 0, sizeof(*p_peer));
6506bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  } else {
6516bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
6526bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
6535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6555738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
6565738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6575738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_start
6585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      This function is called by AV when the audio streaming data
6605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  transfer is started.
6615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6625738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          void
6645738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
665ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
666b3e5af36e9e396eafab3001728ecbc1d8d36a339Pavlin Radoslavovvoid bta_av_co_audio_start(UNUSED_ATTR tBTA_AV_HNDL hndl,
6676bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                           UNUSED_ATTR uint8_t* p_codec_info,
6686bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                           UNUSED_ATTR bool* p_no_rtp_hdr) {
6696bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
6705738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6715738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6725738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
6735738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6745738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_stop
6755738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6765738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      This function is called by AV when the audio streaming data
6775738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  transfer is stopped.
6785738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6795738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6805738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          void
6815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
682ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
6836bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonvoid bta_av_co_audio_stop(UNUSED_ATTR tBTA_AV_HNDL hndl) {
6846bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
6855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
6865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
6875738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
6885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6895738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_src_data_path
6905738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6915738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      This function is called to manage data transfer from
6925738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **                  the audio codec to AVDTP.
6935738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
6946bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson ** Returns          Pointer to the GKI buffer to send, NULL if no buffer to
695f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  send
6965738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
697ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
6986bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonvoid* bta_av_co_audio_src_data_path(const uint8_t* p_codec_info,
6996bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                                    uint32_t* p_timestamp) {
7006bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  BT_HDR* p_buf;
7016bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
7026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: codec: %s", __func__, A2DP_CodecName(p_codec_info));
7036bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
7046bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  p_buf = btif_a2dp_source_audio_readbuf();
7056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (p_buf == NULL) return NULL;
7066bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
7076bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /*
7086bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson   * Retrieve the timestamp information from the media packet,
7096bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson   * and set up the packet header.
7106bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson   *
7116bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson   * In media packet, the following information is available:
7126bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson   * p_buf->layer_specific : number of audio frames in the packet
7136bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson   * p_buf->word[0] : timestamp
7146bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson   */
7156bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (!A2DP_GetPacketTimestamp(p_codec_info, (const uint8_t*)(p_buf + 1),
7166bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                               p_timestamp) ||
7176bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      !A2DP_BuildCodecHeader(p_codec_info, p_buf, p_buf->layer_specific)) {
7186bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    APPL_TRACE_ERROR("%s: unsupported codec type (%d)", __func__,
7196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                     A2DP_GetCodecType(p_codec_info));
7206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
7215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
722b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen#if (BTA_AV_CO_CP_SCMS_T == TRUE)
7236bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  if (bta_av_co_cb.cp.active) {
7246bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    p_buf->len++;
7256bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    p_buf->offset--;
7266bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
7276bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    *p = bta_av_co_cp_get_flag();
7286bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
729c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov#endif
730c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
7316bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return p_buf;
7325738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
7355738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7365738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_drop
7375738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7385738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      An Audio packet is dropped. .
7396bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson **                  It's very likely that the connected headset with this
740f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  handle is moved far away. The implementation may want to
741f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  reduce the encoder bit rate setting to reduce the packet
742f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  size.
7435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          void
7455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
746ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
7476bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonvoid bta_av_co_audio_drop(tBTA_AV_HNDL hndl) {
7486bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_ERROR("%s: dropped audio packet on handle 0x%x", __func__, hndl);
7495738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7505738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
7515738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
7525738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7535738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_delay
7545738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7556bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson ** Description      This function is called by AV when the audio stream
756f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  connection needs to send the initial delay report to the
757f45481678af0694902b5200ba69ced4cb61d73f0Myles Watson **                  connected SRC.
7585738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7595738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7605738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Returns          void
7615738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
762ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
7636bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonvoid bta_av_co_audio_delay(tBTA_AV_HNDL hndl, uint16_t delay) {
7646bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_ERROR("%s: handle: x%x, delay:0x%x", __func__, hndl, delay);
7655738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
7665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
76731d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavovvoid bta_av_co_audio_update_mtu(tBTA_AV_HNDL hndl, uint16_t mtu) {
76831d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov  tBTA_AV_CO_PEER* p_peer;
76931d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov
77031d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov  APPL_TRACE_DEBUG("%s: handle: %d mtu: %d", __func__, hndl, mtu);
77131d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov
77231d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov  /* Retrieve the peer info */
77331d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov  p_peer = bta_av_co_get_peer(hndl);
77431d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov  if (p_peer == NULL) {
77531d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov    APPL_TRACE_ERROR("%s: could not find peer entry", __func__);
77631d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov    return;
77731d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov  }
77831d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov  p_peer->mtu = mtu;
77931d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov}
78031d373be957f094092b9dc94f0b41de23f69fd2aPavlin Radoslavov
7815738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
7825738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7835738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_cp_is_scmst
7845738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
7855738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      Check if a content protection service is SCMS-T
7865738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
787b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen ** Returns          true if this CP is SCMS-T, false otherwise
7885738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
789ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
790cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic bool bta_av_co_cp_is_scmst(const uint8_t* p_protect_info) {
7916bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
79279506e8fcd91d066db1c8aa71008a7b53b0e9172Pavlin Radoslavov
793cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  if (*p_protect_info >= AVDT_CP_LOSC) {
7946bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    uint16_t cp_id;
7955738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
796cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    p_protect_info++;
797cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    STREAM_TO_UINT16(cp_id, p_protect_info);
798feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov    if (cp_id == AVDT_CP_SCMS_T_ID) {
7996bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      APPL_TRACE_DEBUG("%s: SCMS-T found", __func__);
8006bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      return true;
8015738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
8026bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
8035738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8046bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return false;
8055738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8065738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
807cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// Check if audio protect info contains SCMS-T Copy Protection
808cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// Returns true if |p_protect_info| contains SCMS-T, otherwise false.
809cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic bool bta_av_co_audio_protect_has_scmst(uint8_t num_protect,
810cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                              const uint8_t* p_protect_info) {
8116bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
8126bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
813cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  while (num_protect--) {
814cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    if (bta_av_co_cp_is_scmst(p_protect_info)) return true;
8156bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    /* Move to the next SC */
816cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    p_protect_info += *p_protect_info + 1;
8176bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
8186bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: SCMS-T not found", __func__);
8196bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return false;
8205738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
8235738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
8245738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Function         bta_av_co_audio_sink_supports_cp
8255738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
8265738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project ** Description      Check if a sink supports the current content protection
8275738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
828b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen ** Returns          true if the sink supports this CP, false otherwise
8295738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
830ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
8316bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watsonstatic bool bta_av_co_audio_sink_supports_cp(const tBTA_AV_CO_SINK* p_sink) {
8326bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
8335738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8346bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Check if content protection is enabled for this stream */
835cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  if (bta_av_co_cp_get_flag() != AVDT_CP_SCMS_COPY_FREE) {
836cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    return bta_av_co_audio_protect_has_scmst(p_sink->num_protect,
837cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                             p_sink->protect_info);
838cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  }
839c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
8406bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: not required", __func__);
8416bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return true;
8425738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8435738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
8445738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project/*******************************************************************************
8455738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project **
846c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov ** Function         bta_av_co_find_peer_src_supports_codec
847cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **
848c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov ** Description      Find a peer acting as src that supports codec config
849cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **
850c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov ** Returns          The peer source that supports the codec, otherwise NULL.
851cc35559160745c60b42ae182002a59337d844d09Hemant Gupta **
852ee96a3c60fca590d38025925c072d264e06493c4Myles Watson ******************************************************************************/
853c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavovstatic const tBTA_AV_CO_SINK* bta_av_co_find_peer_src_supports_codec(
8546bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    const tBTA_AV_CO_PEER* p_peer) {
8556bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s: peer num_sup_srcs = %d", __func__,
8566bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson                   p_peer->num_sup_srcs);
8576bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
8586bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  for (size_t index = 0; index < p_peer->num_sup_srcs; index++) {
8596bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    const uint8_t* p_codec_caps = p_peer->srcs[index].codec_caps;
86082fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov    if (A2DP_CodecTypeEquals(bta_av_co_cb.codec_config, p_codec_caps) &&
8616bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson        A2DP_IsPeerSourceCodecSupported(p_codec_caps)) {
8626bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson      return &p_peer->srcs[index];
8635738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project    }
8646bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
8656bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  return NULL;
8665738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
8675738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
868cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov//
869cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// Select the current codec configuration based on peer codec support.
870494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov// Furthermore, the local state for the remaining non-selected codecs is
871494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov// updated to reflect whether the codec is selectable.
872494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov// Return a pointer to the corresponding |tBTA_AV_CO_SINK| sink entry
873494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov// on success, otherwise NULL.
874cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov//
875cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic tBTA_AV_CO_SINK* bta_av_co_audio_set_codec(tBTA_AV_CO_PEER* p_peer) {
876494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  tBTA_AV_CO_SINK* p_sink = NULL;
877494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov
878494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // Update all selectable codecs.
879494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // This is needed to update the selectable parameters for each codec.
880494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // NOTE: The selectable codec info is used only for informational purpose.
881494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
882494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    APPL_TRACE_DEBUG("%s: updating selectable codec %s", __func__,
883494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov                     iter->name().c_str());
884494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    bta_av_co_audio_update_selectable_codec(*iter, p_peer);
885494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  }
886494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov
887494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // Select the codec
8885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  for (const auto& iter : bta_av_co_cb.codecs->orderedSourceCodecs()) {
8895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_DEBUG("%s: trying codec %s", __func__, iter->name().c_str());
890494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    p_sink = bta_av_co_audio_codec_selected(*iter, p_peer);
891cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    if (p_sink != NULL) {
8925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      APPL_TRACE_DEBUG("%s: selected codec %s", __func__, iter->name().c_str());
893494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov      break;
89482fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov    }
8955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_DEBUG("%s: cannot use codec %s", __func__, iter->name().c_str());
89682fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  }
89782fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov
898494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // NOTE: Unconditionally dispatch the event to make sure a callback with
899494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // the most recent codec info is generated.
900494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
901494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov
902494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  return p_sink;
903cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov}
904c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
9055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Select an open device for the preferred codec specified by |codec_config|.
906cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov// Return the corresponding peer that supports the codec, otherwise NULL.
907cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic tBTA_AV_CO_SINK* bta_av_co_audio_codec_selected(
9085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    A2dpCodecConfig& codec_config, tBTA_AV_CO_PEER* p_peer) {
909cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  uint8_t new_codec_config[AVDT_CODEC_SIZE];
910c66edf3144f19eb7bc174f39a17c16f8ad49b64bPavlin Radoslavov
911cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  APPL_TRACE_DEBUG("%s", __func__);
9126bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
913cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  // Find the peer sink for the codec
914cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  tBTA_AV_CO_SINK* p_sink = NULL;
915cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
9165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    btav_a2dp_codec_index_t peer_codec_index =
9175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov        A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
9185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    if (peer_codec_index != codec_config.codecIndex()) {
91982fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov      continue;
9206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    }
921cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) {
922cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      APPL_TRACE_DEBUG(
923cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov          "%s: peer sink for codec %s does not support "
924cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov          "Copy Protection",
9255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          __func__, codec_config.name().c_str());
92682fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov      continue;
9276bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    }
928cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    p_sink = &p_peer->sinks[index];
929cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    break;
930cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  }
931cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  if (p_sink == NULL) {
932cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    APPL_TRACE_DEBUG("%s: peer sink for codec %s not found", __func__,
9335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                     codec_config.name().c_str());
934cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    return NULL;
935cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  }
936494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  if (!bta_av_co_cb.codecs->setCodecConfig(
937494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov          p_sink->codec_caps, true /* is_capability */, new_codec_config,
938494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov          true /* select_current_codec */)) {
9395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_DEBUG("%s: cannot set source codec %s", __func__,
9405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                     codec_config.name().c_str());
941cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov    return NULL;
942cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  }
943cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  p_peer->p_sink = p_sink;
9446bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
945cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  bta_av_co_save_new_codec_config(p_peer, new_codec_config, p_sink->num_protect,
946cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                  p_sink->protect_info);
947494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // NOTE: Event BTIF_AV_SOURCE_CONFIG_UPDATED_EVT is dispatched by the caller
948d43a901c579ef08a1b5d7cfe18f759aad0a14f1aPavlin Radoslavov
949cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  return p_sink;
950cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov}
951cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov
952494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov// Update a selectable codec |codec_config| with the corresponding codec
953494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov// information from a peer device |p_peer|.
954494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov// Returns true if the codec is updated, otherwise false.
955494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavovstatic bool bta_av_co_audio_update_selectable_codec(
956494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    A2dpCodecConfig& codec_config, const tBTA_AV_CO_PEER* p_peer) {
957494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  uint8_t new_codec_config[AVDT_CODEC_SIZE];
958494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov
959494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  APPL_TRACE_DEBUG("%s", __func__);
960494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov
961494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // Find the peer sink for the codec
962494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  const tBTA_AV_CO_SINK* p_sink = NULL;
963494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
964494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    btav_a2dp_codec_index_t peer_codec_index =
965494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov        A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
966494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    if (peer_codec_index != codec_config.codecIndex()) {
967494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov      continue;
968494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    }
969494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) {
970494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov      APPL_TRACE_DEBUG(
971494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov          "%s: peer sink for codec %s does not support "
972494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov          "Copy Protection",
973494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov          __func__, codec_config.name().c_str());
974494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov      continue;
975494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    }
976494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    p_sink = &p_peer->sinks[index];
977494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    break;
978494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  }
979494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  if (p_sink == NULL) {
980494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    // The peer sink device does not support this codec
981494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    return false;
982494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  }
983494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  if (!bta_av_co_cb.codecs->setCodecConfig(
984494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov          p_sink->codec_caps, true /* is_capability */, new_codec_config,
985494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov          false /* select_current_codec */)) {
986494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    APPL_TRACE_DEBUG("%s: cannot update source codec %s", __func__,
987494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov                     codec_config.name().c_str());
988494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    return false;
989494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  }
990494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  return true;
991494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov}
992494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov
993cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavovstatic void bta_av_co_save_new_codec_config(tBTA_AV_CO_PEER* p_peer,
994cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                            const uint8_t* new_codec_config,
995cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                            uint8_t num_protect,
996cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov                                            const uint8_t* p_protect_info) {
997c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov  APPL_TRACE_DEBUG("%s", __func__);
998c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov  A2DP_DumpCodecInfo(new_codec_config);
999c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov
1000cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  // Protect access to bta_av_co_cb.codec_config
1001cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  mutex_global_lock();
100282fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov
1003cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  memcpy(bta_av_co_cb.codec_config, new_codec_config,
1004cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov         sizeof(bta_av_co_cb.codec_config));
1005cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  memcpy(p_peer->codec_config, new_codec_config, AVDT_CODEC_SIZE);
100682fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov
1007b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen#if (BTA_AV_CO_CP_SCMS_T == TRUE)
1008cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  /* Check if this sink supports SCMS */
1009cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  bool cp_active =
1010cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov      bta_av_co_audio_protect_has_scmst(num_protect, p_protect_info);
1011cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  bta_av_co_cb.cp.active = cp_active;
1012cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  p_peer->cp_active = cp_active;
10135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
10145738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1015cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  // Protect access to bta_av_co_cb.codec_config
1016cd02ce9c60da962a7981320b26aada8744718941Pavlin Radoslavov  mutex_global_unlock();
10175738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
10185738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovvoid bta_av_co_get_peer_params(tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params) {
10206bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  uint16_t min_mtu = 0xFFFF;
10215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
10226bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
10235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  CHECK(p_peer_params != nullptr);
1024b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
102582fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  /* Protect access to bta_av_co_cb.codec_config */
10266bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  mutex_global_lock();
1027b18f03ecb0ac258985025b5b19273a187a66e87ePavlin Radoslavov
10286bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Compute the MTU */
10296bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
10306bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    const tBTA_AV_CO_PEER* p_peer = &bta_av_co_cb.peers[i];
10316bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    if (!p_peer->opened) continue;
10326bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson    if (p_peer->mtu < min_mtu) min_mtu = p_peer->mtu;
10336bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  }
10345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  p_peer_params->peer_mtu = min_mtu;
10355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  p_peer_params->is_peer_edr = btif_av_is_peer_edr();
10365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  p_peer_params->peer_supports_3mbps = btif_av_peer_supports_3mbps();
10376bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson
103882fcd30ee39420e8702e3d2499d638d9a946beabPavlin Radoslavov  /* Protect access to bta_av_co_cb.codec_config */
10396bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  mutex_global_unlock();
10404ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov}
10414ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov
10425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovconst tA2DP_ENCODER_INTERFACE* bta_av_co_get_encoder_interface(void) {
10434ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov  /* Protect access to bta_av_co_cb.codec_config */
10444ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov  mutex_global_lock();
10454ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov
10465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  const tA2DP_ENCODER_INTERFACE* encoder_interface =
10475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      A2DP_GetEncoderInterface(bta_av_co_cb.codec_config);
10485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
10495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  /* Protect access to bta_av_co_cb.codec_config */
10505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  mutex_global_unlock();
10515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
10525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  return encoder_interface;
10535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov}
10545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
10555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool bta_av_co_set_codec_user_config(
10565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    const btav_a2dp_codec_config_t& codec_user_config) {
10575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  uint8_t result_codec_config[AVDT_CODEC_SIZE];
1058494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  const tBTA_AV_CO_SINK* p_sink = nullptr;
10595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bool restart_input = false;
10605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bool restart_output = false;
10615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bool config_updated = false;
1062494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  bool success = true;
10635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
10645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  // Find the peer that is currently open
10655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  tBTA_AV_CO_PEER* p_peer = nullptr;
10665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
10675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i];
10685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    if (p_peer_tmp->opened) {
10695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      p_peer = p_peer_tmp;
10705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      break;
10715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    }
10724ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov  }
10735ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (p_peer == nullptr) {
10745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_ERROR("%s: no open peer to configure", __func__);
1075494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    success = false;
1076494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    goto done;
10774ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov  }
10785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
10795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  // Find the peer SEP codec to use
10805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (codec_user_config.codec_type < BTAV_A2DP_CODEC_INDEX_MAX) {
10815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
10825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      btav_a2dp_codec_index_t peer_codec_index =
10835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
10845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      if (peer_codec_index != codec_user_config.codec_type) continue;
10855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue;
10865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      p_sink = &p_peer->sinks[index];
10875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      break;
10885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    }
10894ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov  } else {
10905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // Use the current sink codec
10915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    p_sink = p_peer->p_sink;
10925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
10935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (p_sink == nullptr) {
10942073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov    APPL_TRACE_ERROR("%s: cannot find peer SEP to configure for codec type %d",
10952073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov                     __func__, codec_user_config.codec_type);
1096494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    success = false;
1097494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    goto done;
10984ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov  }
10994ebaa86a3ab1ea390d238e1f6dee62cd837c60edPavlin Radoslavov
11005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
11015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bta_av_co_get_peer_params(&peer_params);
11025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (!bta_av_co_cb.codecs->setCodecUserConfig(
11035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          codec_user_config, &peer_params, p_sink->codec_caps,
11045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          result_codec_config, &restart_input, &restart_output,
11055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          &config_updated)) {
1106494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    success = false;
1107494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov    goto done;
11085ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
11095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
11105ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (restart_output) {
11115ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    uint8_t num_protect = 0;
11125ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE)
11135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN;
11145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#endif
11155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
11162073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov    p_sink = bta_av_co_audio_set_codec(p_peer);
11172073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov    if (p_sink == NULL) {
11182073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov      APPL_TRACE_ERROR("%s: cannot set up codec for the peer SINK", __func__);
11192073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov      success = false;
11202073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov      goto done;
11212073c3eb61f69864e645c50005f11c4e8b5e2588Pavlin Radoslavov    }
1122c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    // Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
1123c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
1124c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov        (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
1125c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov      APPL_TRACE_WARNING("%s: not all peer's capabilities have been retrieved",
1126c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov                         __func__);
1127c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov      success = false;
1128c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov      goto done;
1129c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    }
1130c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov
11315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__, p_peer->handle);
11325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx,
11335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                   p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
11345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
11355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
1136494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavovdone:
1137494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // NOTE: We uncoditionally send the upcall even if there is no change
1138494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // or the user config failed. Thus, the caller would always know whether the
1139494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // request succeeded or failed.
1140494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // NOTE: Currently, the input is restarted by sending an upcall
1141494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // and informing the Media Framework about the change.
1142494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
11435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
1144494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  return success;
11451394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov}
11461394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov
11475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Sets the Over-The-Air preferred codec configuration.
11485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// The OTA prefered codec configuration is ignored if the current
11495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// codec configuration contains explicit user configuration, or if the
11505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// codec configuration for the same codec contains explicit user
11515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// configuration.
11525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |p_peer| is the peer device that sent the OTA codec configuration.
11535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |p_ota_codec_config| contains the received OTA A2DP codec configuration
11545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// from the remote peer. Note: this is not the peer codec capability,
11555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// but the codec configuration that the peer would like to use.
11565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |num_protect| is the number of content protection methods to use.
11575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// |p_protect_info| contains the content protection information to use.
11585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// If there is a change in the encoder configuration tht requires restarting
11595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// of the A2DP connection, flag |p_restart_output| is set to true.
11605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov// Returns true on success, otherwise false.
11615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovstatic bool bta_av_co_set_codec_ota_config(tBTA_AV_CO_PEER* p_peer,
11625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                           const uint8_t* p_ota_codec_config,
11635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                           uint8_t num_protect,
11645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                           const uint8_t* p_protect_info,
11655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                           bool* p_restart_output) {
11665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  uint8_t result_codec_config[AVDT_CODEC_SIZE];
11675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bool restart_input = false;
11685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bool restart_output = false;
11695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bool config_updated = false;
11705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
1171c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov  APPL_TRACE_DEBUG("%s", __func__);
1172c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov  A2DP_DumpCodecInfo(p_ota_codec_config);
1173c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov
11745ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  *p_restart_output = false;
11755ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
11765ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  // Find the peer SEP codec to use
11775ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  btav_a2dp_codec_index_t ota_codec_index =
11785ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      A2DP_SourceCodecIndex(p_ota_codec_config);
11795ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (ota_codec_index == BTAV_A2DP_CODEC_INDEX_MAX) {
11805ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_WARNING("%s: invalid peer codec config", __func__);
11815ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    return false;
11825ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
11835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  const tBTA_AV_CO_SINK* p_sink = nullptr;
11845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  for (size_t index = 0; index < p_peer->num_sup_sinks; index++) {
11855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    btav_a2dp_codec_index_t peer_codec_index =
11865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov        A2DP_SourceCodecIndex(p_peer->sinks[index].codec_caps);
11875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    if (peer_codec_index != ota_codec_index) continue;
11885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    if (!bta_av_co_audio_sink_supports_cp(&p_peer->sinks[index])) continue;
11895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    p_sink = &p_peer->sinks[index];
11905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    break;
11915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
11925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if ((p_peer->num_sup_sinks > 0) && (p_sink == nullptr)) {
11935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // There are no peer SEPs if we didn't do the discovery procedure yet.
11945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // We have all the information we need from the peer, so we can
11955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // proceed with the OTA codec configuration.
11965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__);
11975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    return false;
11985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
11991394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov
12005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
12015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bta_av_co_get_peer_params(&peer_params);
12025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (!bta_av_co_cb.codecs->setCodecOtaConfig(
12035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          p_ota_codec_config, &peer_params, result_codec_config, &restart_input,
12045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          &restart_output, &config_updated)) {
12055ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_ERROR("%s: cannot set OTA config", __func__);
12065ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    return false;
12075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12081394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov
12095ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (restart_output) {
1210c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    APPL_TRACE_DEBUG("%s: restart output", __func__);
1211c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    A2DP_DumpCodecInfo(result_codec_config);
1212c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov
12135ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    *p_restart_output = true;
12145ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    p_peer->p_sink = p_sink;
12155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    bta_av_co_save_new_codec_config(p_peer, result_codec_config, num_protect,
12165ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                    p_protect_info);
12175ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12185ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12195ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (restart_input || config_updated) {
12205ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // NOTE: Currently, the input is restarted by sending an upcall
12215ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // and informing the Media Framework about the change.
12225ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
12235ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  return true;
12265ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov}
12275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavovbool bta_av_co_set_codec_audio_config(
12295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    const btav_a2dp_codec_config_t& codec_audio_config) {
12305ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  uint8_t result_codec_config[AVDT_CODEC_SIZE];
12315ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bool restart_output = false;
12325ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bool config_updated = false;
12335ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12345ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  // Find the peer that is currently open
12355ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  tBTA_AV_CO_PEER* p_peer = nullptr;
12365ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(bta_av_co_cb.peers); i++) {
12375ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    tBTA_AV_CO_PEER* p_peer_tmp = &bta_av_co_cb.peers[i];
12385ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    if (p_peer_tmp->opened) {
12395ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      p_peer = p_peer_tmp;
12405ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov      break;
12415ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    }
12425ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12435ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (p_peer == nullptr) {
12445ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_ERROR("%s: no open peer to configure", __func__);
12455ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    return false;
12465ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12475ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12485ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  // Use the current sink codec
12495ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  const tBTA_AV_CO_SINK* p_sink = p_peer->p_sink;
12505ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (p_sink == nullptr) {
12515ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    APPL_TRACE_ERROR("%s: cannot find peer SEP to configure", __func__);
12525ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    return false;
12535ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12545ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12555ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  tA2DP_ENCODER_INIT_PEER_PARAMS peer_params;
12565ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bta_av_co_get_peer_params(&peer_params);
12575ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (!bta_av_co_cb.codecs->setCodecAudioConfig(
12585ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          codec_audio_config, &peer_params, p_sink->codec_caps,
12595ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov          result_codec_config, &restart_output, &config_updated)) {
12605ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    return false;
12615ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12625ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12635ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (restart_output) {
12645ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    uint8_t num_protect = 0;
12655ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#if (BTA_AV_CO_CP_SCMS_T == TRUE)
12665ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    if (p_peer->cp_active) num_protect = AVDT_CP_INFO_LEN;
12675ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov#endif
12685ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12695ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    bta_av_co_save_new_codec_config(p_peer, result_codec_config,
12705ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov                                    p_sink->num_protect, p_sink->protect_info);
12715ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
1272c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    // Don't call BTA_AvReconfig() prior to retrieving all peer's capabilities
1273c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    if ((p_peer->num_rx_sinks != p_peer->num_sinks) &&
1274c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov        (p_peer->num_sup_sinks != BTA_AV_CO_NUM_ELEMENTS(p_peer->sinks))) {
1275c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov      APPL_TRACE_WARNING("%s: not all peer's capabilities have been retrieved",
1276c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov                         __func__);
1277c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    } else {
1278c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov      APPL_TRACE_DEBUG("%s: call BTA_AvReconfig(x%x)", __func__,
1279c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov                       p_peer->handle);
1280c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov      BTA_AvReconfig(p_peer->handle, true, p_sink->sep_info_idx,
1281c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov                     p_peer->codec_config, num_protect, bta_av_co_cp_scmst);
1282c64dc1d28496b5e917d0f82317d40d3c60e6495dPavlin Radoslavov    }
12835ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12845ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12855ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (config_updated) {
12865ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // NOTE: Currently, the input is restarted by sending an upcall
12875ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    // and informing the Media Framework about the change.
12885ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
12895ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
12905ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12915ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  return true;
12925ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov}
12935ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12945ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecs* bta_av_get_a2dp_codecs(void) { return bta_av_co_cb.codecs; }
12955ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12965ce0116fbf5b530d5b93f11312096eade1021c1ePavlin RadoslavovA2dpCodecConfig* bta_av_get_a2dp_current_codec(void) {
12975ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  A2dpCodecConfig* current_codec;
12985ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov
12995ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  mutex_global_lock();
13005ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  if (bta_av_co_cb.codecs == nullptr) {
13015ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    mutex_global_unlock();
13025ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov    return nullptr;
13035ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  }
13045ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  current_codec = bta_av_co_cb.codecs->getCurrentCodecConfig();
13056bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  mutex_global_unlock();
13061394c197027c0907932a814a786cc033870eb1c9Pavlin Radoslavov
13075ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  return current_codec;
13085738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
13095738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1310a6ba5aca4e8c1a200b8cc29fb60d390a7196416aPavlin Radoslavovvoid bta_av_co_init(
1311a6ba5aca4e8c1a200b8cc29fb60d390a7196416aPavlin Radoslavov    const std::vector<btav_a2dp_codec_config_t>& codec_priorities) {
13126bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  APPL_TRACE_DEBUG("%s", __func__);
13135738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13146bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Reset the control block */
13155ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bta_av_co_cb.reset();
13165738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
1317b7f64bc45dec7f7fec74ceb04874f322b9434bbfMarie Janssen#if (BTA_AV_CO_CP_SCMS_T == TRUE)
1318feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov  bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_NEVER);
13195738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#else
1320feee26c3dae12b53773b31f57cf2533a3d993979Pavlin Radoslavov  bta_av_co_cp_set_flag(AVDT_CP_SCMS_COPY_FREE);
13215738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project#endif
13225738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project
13236bd442f543972b072ef2cbbcf2f7c91202de1045Myles Watson  /* Reset the current config */
13245ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  /* Protect access to bta_av_co_cb.codec_config */
13255ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  mutex_global_lock();
1326a6ba5aca4e8c1a200b8cc29fb60d390a7196416aPavlin Radoslavov  bta_av_co_cb.codecs = new A2dpCodecs(codec_priorities);
13275ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  bta_av_co_cb.codecs->init();
13285ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  A2DP_InitDefaultCodec(bta_av_co_cb.codec_config);
13295ce0116fbf5b530d5b93f11312096eade1021c1ePavlin Radoslavov  mutex_global_unlock();
1330494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov
1331494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // NOTE: Unconditionally dispatch the event to make sure a callback with
1332494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  // the most recent codec info is generated.
1333494e53e904e8aecc28178fda5856071776b2caf0Pavlin Radoslavov  btif_dispatch_sm_event(BTIF_AV_SOURCE_CONFIG_UPDATED_EVT, NULL, 0);
13345738f83aeb59361a0a2eda2460113f6dc919427The Android Open Source Project}
1335