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() : sep_info_idx(0), seid(0), codec_caps{}, num_protect(0), protect_info{} { Reset(); }
29 
30   /**
31    * Reset the state.
32    */
Reset()33   void Reset() {
34     sep_info_idx = 0;
35     seid = 0;
36     memset(codec_caps, 0, sizeof(codec_caps));
37     num_protect = 0;
38     memset(protect_info, 0, sizeof(protect_info));
39   }
40 
41   uint8_t sep_info_idx;                    // Local SEP index (in BTA tables)
42   uint8_t seid;                            // Peer SEP index (in peer tables)
43   uint8_t codec_caps[AVDT_CODEC_SIZE];     // Peer SEP codec capabilities
44   uint8_t num_protect;                     // Peer SEP number of CP elements
45   uint8_t protect_info[AVDT_CP_INFO_LEN];  // Peer SEP content protection info
46 };
47 
48 class BtaAvCoPeer {
49 public:
50   /**
51    * Default constructor to initialize the state of the member variables.
52    */
53   BtaAvCoPeer();
54 
55   /**
56    * Initialize the state.
57    *
58    * @param codec_priorities the codec priorities to use for the initialization
59    */
60   void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
61 
62   /**
63    * Reset the state.
64    *
65    * @param bta_av_handle the BTA AV handle to use
66    */
67   void Reset(tBTA_AV_HNDL bta_av_handle);
68 
69   /**
70    * Get the BTA AV handle.
71    *
72    * @return the BTA AV handle
73    */
BtaAvHandle()74   tBTA_AV_HNDL BtaAvHandle() const { return bta_av_handle_; }
75 
76   /**
77    * Get the A2DP codecs.
78    *
79    * @return the A2DP codecs
80    */
GetCodecs()81   A2dpCodecs* GetCodecs() const { return codecs_; }
82 
ContentProtectActive()83   bool ContentProtectActive() const { return content_protect_active_; }
SetContentProtectActive(bool cp_active)84   void SetContentProtectActive(bool cp_active) { content_protect_active_ = cp_active; }
85 
86   /**
87    * Gets the codec config for the state.
88    * @return the active codec config.
89    */
90   uint8_t* getCodecConfig();
91 
92   /**
93    * Updates the codec config
94    * @param new_codec_config codec config that needs to be updated.
95    */
96   void setCodecConfig(const uint8_t* new_codec_config);
97 
98   RawAddress addr;                                // Peer address
99   BtaAvCoSep sinks[BTAV_A2DP_CODEC_INDEX_MAX];    // Supported sinks
100   BtaAvCoSep sources[BTAV_A2DP_CODEC_INDEX_MAX];  // Supported sources
101   uint8_t num_sinks;                              // Total number of sinks at peer
102   uint8_t num_sources;                            // Total number of sources at peer
103   uint8_t num_seps;                               // Total number of SEPs at peer
104   uint8_t num_rx_sinks;                           // Number of received sinks
105   uint8_t num_rx_sources;                         // Number of received sources
106   uint8_t num_sup_sinks;                          // Number of supported sinks
107   uint8_t num_sup_sources;                        // Number of supported sources
108   const BtaAvCoSep* p_sink;                       // Currently selected sink
109   const BtaAvCoSep* p_source;                     // Currently selected source
110   uint8_t codec_config[AVDT_CODEC_SIZE];          // Current codec configuration
111   bool acceptor;                                  // True if acceptor
112   bool reconfig_needed;                           // True if reconfiguration is needed
113   bool opened;                                    // True if opened
114   uint16_t mtu;                                   // Maximum Transmit Unit size
115   uint16_t uuid_to_connect;                       // UUID of peer device
116 
117 private:
118   tBTA_AV_HNDL bta_av_handle_;   // BTA AV handle to use
119   A2dpCodecs* codecs_;           // Locally supported codecs
120   bool content_protect_active_;  // True if Content Protect is active
121 };
122 
123 /**
124  * Cache to store all the peer and codec information.
125  * It provides different APIs to retrieve the peer and update the peer data.
126  */
127 class BtaAvCoPeerCache {
128 public:
129   BtaAvCoPeerCache() = default;
130   std::recursive_mutex codec_lock_;                         // Protect access to the codec state
131   std::vector<btav_a2dp_codec_config_t> codec_priorities_;  // Configured
132   BtaAvCoPeer peers_[BTA_AV_NUM_STRS];                      // Connected peer information
133 
134   /**
135    * Inits the cache with the appropriate data.
136    * @param codec_priorities codec priorities.
137    */
138   void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
139 
140   /**
141    * Resets the cache and the peer data.
142    */
143   void Reset();
144 
145   /**
146    * Find the peer entry for a given peer address.
147    *
148    * @param peer_address the peer address to use
149    * @return the peer entry if found, otherwise nullptr
150    */
151   BtaAvCoPeer* FindPeer(const RawAddress& peer_address);
152 
153   /**
154    * Find the peer Source SEP entry for a given codec index.
155    *
156    * @param p_peer the peer to use
157    * @param codec_config the codec index to use
158    * @return the peer Source SEP for the codec index if found, otherwise nullptr
159    */
160   BtaAvCoSep* FindPeerSource(BtaAvCoPeer* p_peer, btav_a2dp_codec_index_t codec_index,
161                              const uint8_t content_protect_flag);
162 
163   /**
164    * Find the peer Sink SEP entry for a given codec index.
165    *
166    * @param p_peer the peer to use
167    * @param codec_index the codec index to use
168    * @return the peer Sink SEP for the codec index if found, otherwise nullptr
169    */
170   BtaAvCoSep* FindPeerSink(BtaAvCoPeer* p_peer, btav_a2dp_codec_index_t codec_index,
171                            const uint8_t content_protect_flag);
172 
173   /**
174    * Find the peer entry for a given BTA AV handle.
175    *
176    * @param bta_av_handle the BTA AV handle to use
177    * @return the peer entry if found, otherwise nullptr
178    */
179   BtaAvCoPeer* FindPeer(tBTA_AV_HNDL bta_av_handle);
180 
181   /**
182    * Find the peer entry for a given BTA AV handle and update it with the
183    * peer address.
184    *
185    * @param bta_av_handle the BTA AV handle to use
186    * @param peer_address the peer address
187    * @return the peer entry if found, otherwise nullptr
188    */
189   BtaAvCoPeer* FindPeerAndUpdate(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address);
190 
191   /**
192    * Find the peer UUID for a given BTA AV handle.
193    *
194    * @param bta_av_handle the BTA AV handle to use
195    * @return the peer UUID if found, otherwise 0
196    */
197   uint16_t FindPeerUuid(tBTA_AV_HNDL bta_av_handle);
198 };
199 
200 /**
201  * Check if a content protection service is SCMS-T.
202  *
203  * @param p_orotect_info the content protection info to check
204  * @return true if the Contention Protection in @param p_protect_info
205  * is SCMS-T, otherwise false
206  */
207 bool ContentProtectIsScmst(const uint8_t* p_protect_info);
208 
209 /**
210  * Check if audio protect info contains SCMS-T Content Protection.
211  *
212  * @param num_protect number of protect schemes
213  * @param p_protect_info the protect info to check
214  * @return true if @param p_protect_info contains SCMS-T, otherwise false
215  */
216 bool AudioProtectHasScmst(uint8_t num_protect, const uint8_t* p_protect_info);
217 
218 /**
219  * Check if a peer SEP has content protection enabled.
220  *
221  * @param p_sep the peer SEP to check
222  * @param content_protect_flag flag to check if content protect is enabled or
223  * not.
224  * @return true if the peer SEP has content protection enabled,
225  * otherwise false
226  */
227 bool AudioSepHasContentProtection(const BtaAvCoSep* p_sep, const uint8_t content_protect_flag);
228