1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 #include "bta/include/bta_av_api.h"
19 #include "stack/include/a2dp_codec_api.h"
20 #include "stack/include/bt_types.h"
21 #include "types/raw_address.h"
22 
23 // Macro to retrieve the number of elements in a statically allocated array
24 #define BTA_AV_CO_NUM_ELEMENTS(__a) (sizeof(__a) / sizeof((__a)[0]))
25 
26 class BtaAvCoSep {
27  public:
BtaAvCoSep()28   BtaAvCoSep()
29       : sep_info_idx(0), seid(0), codec_caps{}, num_protect(0), protect_info{} {
30     Reset();
31   }
32 
33   /**
34    * Reset the state.
35    */
Reset()36   void Reset() {
37     sep_info_idx = 0;
38     seid = 0;
39     memset(codec_caps, 0, sizeof(codec_caps));
40     num_protect = 0;
41     memset(protect_info, 0, sizeof(protect_info));
42   }
43 
44   uint8_t sep_info_idx;                    // Local SEP index (in BTA tables)
45   uint8_t seid;                            // Peer SEP index (in peer tables)
46   uint8_t codec_caps[AVDT_CODEC_SIZE];     // Peer SEP codec capabilities
47   uint8_t num_protect;                     // Peer SEP number of CP elements
48   uint8_t protect_info[AVDT_CP_INFO_LEN];  // Peer SEP content protection info
49 };
50 
51 class BtaAvCoPeer {
52  public:
53   /**
54    * Default constructor to initialize the state of the member variables.
55    */
56   BtaAvCoPeer();
57 
58   /**
59    * Initialize the state.
60    *
61    * @param codec_priorities the codec priorities to use for the initialization
62    */
63   void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
64 
65   /**
66    * Reset the state.
67    *
68    * @param bta_av_handle the BTA AV handle to use
69    */
70   void Reset(tBTA_AV_HNDL bta_av_handle);
71 
72   /**
73    * Get the BTA AV handle.
74    *
75    * @return the BTA AV handle
76    */
BtaAvHandle()77   tBTA_AV_HNDL BtaAvHandle() const { return bta_av_handle_; }
78 
79   /**
80    * Get the A2DP codecs.
81    *
82    * @return the A2DP codecs
83    */
GetCodecs()84   A2dpCodecs* GetCodecs() const { return codecs_; }
85 
ContentProtectActive()86   bool ContentProtectActive() const { return content_protect_active_; }
SetContentProtectActive(bool cp_active)87   void SetContentProtectActive(bool cp_active) {
88     content_protect_active_ = cp_active;
89   }
90 
91   RawAddress addr;                                // Peer address
92   BtaAvCoSep sinks[BTAV_A2DP_CODEC_INDEX_MAX];    // Supported sinks
93   BtaAvCoSep sources[BTAV_A2DP_CODEC_INDEX_MAX];  // Supported sources
94   uint8_t num_sinks;                      // Total number of sinks at peer
95   uint8_t num_sources;                    // Total number of sources at peer
96   uint8_t num_seps;                       // Total number of SEPs at peer
97   uint8_t num_rx_sinks;                   // Number of received sinks
98   uint8_t num_rx_sources;                 // Number of received sources
99   uint8_t num_sup_sinks;                  // Number of supported sinks
100   uint8_t num_sup_sources;                // Number of supported sources
101   const BtaAvCoSep* p_sink;               // Currently selected sink
102   const BtaAvCoSep* p_source;             // Currently selected source
103   uint8_t codec_config[AVDT_CODEC_SIZE];  // Current codec configuration
104   bool acceptor;                          // True if acceptor
105   bool reconfig_needed;                   // True if reconfiguration is needed
106   bool opened;                            // True if opened
107   uint16_t mtu;                           // Maximum Transmit Unit size
108   uint16_t uuid_to_connect;               // UUID of peer device
109 
110  private:
111   tBTA_AV_HNDL bta_av_handle_;   // BTA AV handle to use
112   A2dpCodecs* codecs_;           // Locally supported codecs
113   bool content_protect_active_;  // True if Content Protect is active
114 };
115 
116 /**
117  * Cache to store all the peer and codec information.
118  * It provides different APIs to retrieve the peer and update the peer data.
119  */
120 class BtaAvCoPeerCache {
121  public:
122   BtaAvCoPeerCache() = default;
123   std::recursive_mutex codec_lock_;  // Protect access to the codec state
124   std::vector<btav_a2dp_codec_config_t> codec_priorities_;  // Configured
125   BtaAvCoPeer peers_[BTA_AV_NUM_STRS];  // Connected peer information
126 
127   /**
128    * Inits the cache with the appropriate data.
129    * @param codec_priorities codec priorities.
130    * @param supported_codecs supported codecs by the stack.
131    */
132   void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities,
133             std::vector<btav_a2dp_codec_info_t>* supported_codecs);
134 
135   /**
136    * Resets the cache and the peer data.
137    */
138   void Reset();
139 
140   /**
141    * Find the peer entry for a given peer address.
142    *
143    * @param peer_address the peer address to use
144    * @return the peer entry if found, otherwise nullptr
145    */
146   BtaAvCoPeer* FindPeer(const RawAddress& peer_address);
147 
148   /**
149    * Find the peer Source SEP entry for a given codec index.
150    *
151    * @param p_peer the peer to use
152    * @param codec_config the codec index to use
153    * @return the peer Source SEP for the codec index if found, otherwise nullptr
154    */
155   BtaAvCoSep* FindPeerSource(BtaAvCoPeer* p_peer,
156                              btav_a2dp_codec_index_t codec_index,
157                              const uint8_t content_protect_flag);
158 
159   /**
160    * Find the peer Sink SEP entry for a given codec index.
161    *
162    * @param p_peer the peer to use
163    * @param codec_index the codec index to use
164    * @return the peer Sink SEP for the codec index if found, otherwise nullptr
165    */
166   BtaAvCoSep* FindPeerSink(BtaAvCoPeer* p_peer,
167                            btav_a2dp_codec_index_t codec_index,
168                            const uint8_t content_protect_flag);
169 
170   /**
171    * Find the peer entry for a given BTA AV handle.
172    *
173    * @param bta_av_handle the BTA AV handle to use
174    * @return the peer entry if found, otherwise nullptr
175    */
176   BtaAvCoPeer* FindPeer(tBTA_AV_HNDL bta_av_handle);
177 
178   /**
179    * Find the peer entry for a given BTA AV handle and update it with the
180    * peer address.
181    *
182    * @param bta_av_handle the BTA AV handle to use
183    * @param peer_address the peer address
184    * @return the peer entry if found, otherwise nullptr
185    */
186   BtaAvCoPeer* FindPeerAndUpdate(tBTA_AV_HNDL bta_av_handle,
187                                  const RawAddress& peer_address);
188 
189   /**
190    * Find the peer UUID for a given BTA AV handle.
191    *
192    * @param bta_av_handle the BTA AV handle to use
193    * @return the peer UUID if found, otherwise 0
194    */
195   uint16_t FindPeerUuid(tBTA_AV_HNDL bta_av_handle);
196 };
197 
198 /**
199  * Check if a content protection service is SCMS-T.
200  *
201  * @param p_orotect_info the content protection info to check
202  * @return true if the Contention Protection in @param p_protect_info
203  * is SCMS-T, otherwise false
204  */
205 bool ContentProtectIsScmst(const uint8_t* p_protect_info);
206 
207 /**
208  * Check if audio protect info contains SCMS-T Content Protection.
209  *
210  * @param num_protect number of protect schemes
211  * @param p_protect_info the protect info to check
212  * @return true if @param p_protect_info contains SCMS-T, otherwise false
213  */
214 bool AudioProtectHasScmst(uint8_t num_protect, const uint8_t* p_protect_info);
215 
216 /**
217  * Check if a peer SEP has content protection enabled.
218  *
219  * @param p_sep the peer SEP to check
220  * @param content_protect_flag flag to check if content protect is enabled or
221  * not.
222  * @return true if the peer SEP has content protection enabled,
223  * otherwise false
224  */
225 bool AudioSepHasContentProtection(const BtaAvCoSep* p_sep,
226                                   const uint8_t content_protect_flag);
227