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 
19 #include <audio_hal_interface/a2dp_encoding.h>
20 
21 #include "btif/include/bta_av_co_peer.h"
22 
23 /**
24  * BTA AV codec callouts state.
25  */
26 class BtaAvCoState {
27  public:
28   BtaAvCoState() = default;
29 
30   /**
31    * Set the active peer for the state.
32    * @param peer
33    */
34   void setActivePeer(BtaAvCoPeer* peer);
35 
36   /**
37    * Gets the active peer for the state.
38    * @return pointer to the active peer.
39    */
40   BtaAvCoPeer* getActivePeer() const;
41 
42   /**
43    * Gets the codec config for the state.
44    * @return the active codec config.
45    */
46   uint8_t* getCodecConfig();
47 
48   /**
49    * Updates the codec config
50    * @param codec_config codec config that needs to be updated.
51    */
52   void setCodecConfig(const uint8_t* codec_config);
53 
54   /**
55    * Clears the codec config.
56    */
57   void clearCodecConfig();
58 
59   /**
60    * Resets the state.
61    */
62   void Reset();
63   virtual ~BtaAvCoState() = default;
64 
65  private:
66   // The current active peer
67   BtaAvCoPeer* active_peer_;
68   // Current codec configuration
69   uint8_t codec_config_[AVDT_CODEC_SIZE];
70 };
71 
72 class BtaAvCo {
73  public:
BtaAvCo(bool content_protect_enabled,BtaAvCoPeerCache * bta_av_co_peer_bank)74   BtaAvCo(bool content_protect_enabled, BtaAvCoPeerCache* bta_av_co_peer_bank)
75       : peer_cache_(bta_av_co_peer_bank),
76         content_protect_enabled_(content_protect_enabled),
77         content_protect_flag_(0) {
78     Reset();
79   }
80 
81   virtual ~BtaAvCo() = default;
82 
83   /**
84    * Initialize the state.
85    *
86    * @param codec_priorities the codec priorities to use for the initialization
87    * @param supported_codecs return the list of supported codecs
88    */
89   void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities,
90             std::vector<btav_a2dp_codec_info_t>* supported_codecs);
91 
92   /**
93    * Checks whether a codec is supported.
94    *
95    * @param codec_index the index of the codec to check
96    * @return true if the codec is supported, otherwise false
97    */
98   bool IsSupportedCodec(btav_a2dp_codec_index_t codec_index);
99 
100   /**
101    * Get the current codec configuration for the active peer.
102    *
103    * @return the current codec configuration if found, otherwise nullptr
104    */
105   A2dpCodecConfig* GetActivePeerCurrentCodec();
106 
107   /**
108    * Get the current codec configuration for a peer.
109    *
110    * @param peer_address the peer address
111    * @return the current codec configuration if found, otherwise nullptr
112    */
113   A2dpCodecConfig* GetPeerCurrentCodec(const RawAddress& peer_address);
114 
115   /**
116    * Process the AVDTP discovery result: number of Stream End Points (SEP)
117    * found during the AVDTP stream discovery process.
118    *
119    * @param bta_av_handle the BTA AV handle to identify the peer
120    * @param peer_address the peer address
121    * @param num_seps the number of discovered SEPs
122    * @param num_sinks number of discovered Sink SEPs
123    * @param num_sources number of discovered Source SEPs
124    * @param uuid_local local UUID
125    */
126   void ProcessDiscoveryResult(tBTA_AV_HNDL bta_av_handle,
127                               const RawAddress& peer_address, uint8_t num_seps,
128                               uint8_t num_sinks, uint8_t num_sources,
129                               uint16_t uuid_local);
130 
131   /**
132    * Process retrieved codec configuration and content protection from
133    * Peer Sink SEP.
134    *
135    * @param bta_av_handle the BTA AV handle to identify the peer
136    * @param peer_address the peer address
137    * @param p_codec_info the peer sink capability filled-in by the caller.
138    * On success, it will contain the current codec configuration for the peer.
139    * @param p_sep_info_idx the peer SEP index for the corresponding peer
140    * sink capability filled-in by the caller. On success, it will contain
141    * the SEP index for the current codec configuration for the peer.
142    * @param seid the peer SEP index in peer tables
143    * @param p_num_protect the peer SEP number of content protection elements
144    * filled-in by the caller. On success, it will contain the SEP number of
145    * content protection elements for the current codec configuration for the
146    * peer.
147    * @param p_protect_info the peer SEP content protection info filled-in by
148    * the caller. On success, it will contain the SEP content protection info
149    * for the current codec configuration for the peer.
150    * @return A2DP_SUCCESS on success, otherwise A2DP_FAIL
151    */
152   tA2DP_STATUS ProcessSourceGetConfig(tBTA_AV_HNDL bta_av_handle,
153                                       const RawAddress& peer_address,
154                                       uint8_t* p_codec_info,
155                                       uint8_t* p_sep_info_idx, uint8_t seid,
156                                       uint8_t* p_num_protect,
157                                       uint8_t* p_protect_info);
158 
159   /**
160    * Process retrieved codec configuration and content protection from
161    * Peer Source SEP.
162    *
163    * @param bta_av_handle the BTA AV handle to identify the peer
164    * @param peer_address the peer address
165    * @param p_codec_info the peer source capability filled-in by the caller.
166    * On success, it will contain the current codec configuration for the peer.
167    * @param p_sep_info_idx the peer SEP index for the corresponding peer
168    * source capability filled-in by the caller. On success, it will contain
169    * the SEP index for the current codec configuration for the peer.
170    * @param seid the peer SEP index in peer tables
171    * @param p_num_protect the peer SEP number of content protection elements
172    * filled-in by the caller. On success, it will contain the SEP number of
173    * content protection elements for the current codec configuration for the
174    * peer.
175    * @param p_protect_info the peer SEP content protection info filled-in by
176    * the caller. On success, it will contain the SEP content protection info
177    * for the current codec configuration for the peer.
178    * @return A2DP_SUCCESS on success, otherwise A2DP_FAIL
179    */
180   tA2DP_STATUS ProcessSinkGetConfig(tBTA_AV_HNDL bta_av_handle,
181                                     const RawAddress& peer_address,
182                                     uint8_t* p_codec_info,
183                                     uint8_t* p_sep_info_idx, uint8_t seid,
184                                     uint8_t* p_num_protect,
185                                     uint8_t* p_protect_info);
186 
187   /**
188    * Process AVDTP Set Config to set the codec and content protection
189    * configuration of the audio stream.
190    *
191    * @param bta_av_handle the BTA AV handle to identify the peer
192    * @param peer_address the peer address
193    * @param p_codec_info the codec configuration to set
194    * @param seid stream endpoint ID of stream initiating the operation
195    * @param peer_address the peer address
196    * @param num_protect the peer SEP number of content protection elements
197    * @param p_protect_info the peer SEP content protection info
198    * @param t_local_sep the local SEP: AVDT_TSEP_SRC or AVDT_TSEP_SNK
199    * @param avdt_handle the AVDTP handle
200    */
201   void ProcessSetConfig(tBTA_AV_HNDL bta_av_handle,
202                         const RawAddress& peer_address,
203                         const uint8_t* p_codec_info, uint8_t seid,
204                         uint8_t num_protect, const uint8_t* p_protect_info,
205                         uint8_t t_local_sep, uint8_t avdt_handle);
206 
207   /**
208    * Process AVDTP Open when the stream connection is opened.
209    *
210    * @param bta_av_handle the BTA AV handle to identify the peer
211    * @param peer_address the peer address
212    * @param mtu the MTU of the connection
213    */
214   void ProcessOpen(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
215                    uint16_t mtu);
216 
217   /**
218    * Process AVDTP Close when the stream connection is closed.
219    *
220    * @param bta_av_handle the BTA AV handle to identify the peer
221    * @param peer_address the peer address
222    */
223   void ProcessClose(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address);
224 
225   /**
226    * Process AVDTP Start when the audio data streaming is started.
227    *
228    * @param bta_av_handle the BTA AV handle to identify the peer
229    * @param peer_address the peer address
230    * @param p_codec_info the codec configuration
231    * @param p_no_rtp_header on return, set to true if the audio data packets
232    * should not contain RTP header
233    */
234   void ProcessStart(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
235                     const uint8_t* p_codec_info, bool* p_no_rtp_header);
236 
237   /**
238    * Process AVDTP Stop when the audio data streaming is stopped.
239    *
240    * @param bta_av_handle the BTA AV handle to identify the peer
241    * @param peer_address the peer address
242    */
243   void ProcessStop(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address);
244 
245   /**
246    * Get the next encoded audio data packet to send.
247    *
248    * @param p_codec_info the codec configuration
249    * @param p_timestamp on return, set to the timestamp of the data packet
250    * @return the next encoded data packet or nullptr if no encoded data to send
251    */
252   BT_HDR* GetNextSourceDataPacket(const uint8_t* p_codec_info,
253                                   uint32_t* p_timestamp);
254 
255   /**
256    * An audio packet has been dropped.
257    * This signal can be used by the encoder to reduce the encoder bit rate
258    * setting.
259    *
260    * @param bta_av_handle the BTA AV handle to identify the peer
261    * @param peer_address the peer address
262    */
263   void DataPacketWasDropped(tBTA_AV_HNDL bta_av_handle,
264                             const RawAddress& peer_address);
265 
266   /**
267    * Process AVDTP Audio Delay when the initial delay report is received by
268    * the Source.
269    *
270    * @param bta_av_handle the BTA AV handle to identify the peer
271    * @param peer_address the peer address
272    * @param delay the reported delay in 1/10th of a millisecond
273    */
274   void ProcessAudioDelay(tBTA_AV_HNDL bta_av_handle,
275                          const RawAddress& peer_address, uint16_t delay);
276 
277   /**
278    * Update the MTU of the audio data connection.
279    *
280    * @param bta_av_handle the BTA AV handle to identify the peer
281    * @param peer_address the peer address
282    * @param mtu the new MTU of the audio data connection
283    */
284   void UpdateMtu(tBTA_AV_HNDL bta_av_handle, const RawAddress& peer_address,
285                  uint16_t mtu);
286 
287   /**
288    * Set the active peer.
289    *
290    * @param peer_address the peer address
291    * @param t_local_sep update the active peer for the profile type.
292    * @return true on success, otherwise false
293    */
294   bool SetActivePeer(const RawAddress& peer_address, const uint8_t t_local_sep);
295 
296   /**
297    * Save the reconfig codec
298    *
299    * @param new_codec_config the new codec config
300    */
301   void SaveCodec(const uint8_t* new_codec_config);
302 
303   /**
304    * Get the encoder parameters for a peer.
305    *
306    * @param peer_address the peer address
307    * @param p_peer_params on return, set to the peer's encoder parameters
308    */
309   void GetPeerEncoderParameters(const RawAddress& peer_address,
310                                 tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params);
311 
312   /**
313    * Get the Source encoder interface for the current codec.
314    *
315    * @return the Source encoder interface for the current codec
316    */
317   const tA2DP_ENCODER_INTERFACE* GetSourceEncoderInterface();
318 
319   /**
320    * Set the codec user configuration.
321    *
322    * @param peer_address the peer address
323    * @param codec_user_config the codec user configuration to set
324    * @param p_restart_output if there is a change in the encoder configuration
325    * that requires restarting of the A2DP connection, flag |p_restart_output|
326    * will be set to true.
327    * @return true on success, otherwise false
328    */
329   bool SetCodecUserConfig(const RawAddress& peer_address,
330                           const btav_a2dp_codec_config_t& codec_user_config,
331                           bool* p_restart_output);
332 
333   /**
334    * Set the codec audio configuration.
335    *
336    * @param codec_audio_config the codec audio configuration to set
337    * @return true on success, otherwise false
338    */
339   bool SetCodecAudioConfig(const btav_a2dp_codec_config_t& codec_audio_config);
340 
341   /**
342    * Get the Source encoder maximum frame size for the current codec.
343    *
344    * @return the effective frame size for the current codec
345    */
346   int GetSourceEncoderEffectiveFrameSize();
347 
348   /**
349    * Report the source codec state for a peer
350    *
351    * @param p_peer the peer to report
352    * @return true on success, otherwise false
353    */
354   bool ReportSourceCodecState(BtaAvCoPeer* p_peer);
355 
356   /**
357    * Report the sink codec state for a peer
358    *
359    * @param p_peer the peer to report
360    * @return true on success, otherwise false
361    */
362   bool ReportSinkCodecState(BtaAvCoPeer* p_peer);
363 
364   /**
365    * Get the content protection flag.
366    *
367    * @return the content protection flag. It should be one of the following:
368    * AVDT_CP_SCMS_COPY_NEVER, AVDT_CP_SCMS_COPY_ONCE, AVDT_CP_SCMS_COPY_FREE
369    */
ContentProtectFlag()370   uint8_t ContentProtectFlag() const { return content_protect_flag_; }
371 
372   /**
373    * Set the content protection flag.
374    *
375    * @param cp_flag the content protection flag. It should be one of the
376    * following:
377    * AVDT_CP_SCMS_COPY_NEVER, AVDT_CP_SCMS_COPY_ONCE, AVDT_CP_SCMS_COPY_FREE
378    * NOTE: If Content Protection is not enabled on the system, then
379    * the only acceptable vailue is AVDT_CP_SCMS_COPY_FREE.
380    */
SetContentProtectFlag(uint8_t cp_flag)381   void SetContentProtectFlag(uint8_t cp_flag) {
382     if (!ContentProtectEnabled() && (cp_flag != AVDT_CP_SCMS_COPY_FREE)) {
383       return;
384     }
385     content_protect_flag_ = cp_flag;
386   }
387 
388   /**
389    * Dump debug-related information.
390    *
391    * @param fd the file descritor to use for writing the ASCII formatted
392    * information
393    */
394   void DebugDump(int fd);
395 
396   /**
397    * Access peer data via cache.
398    */
399   BtaAvCoPeerCache* peer_cache_;
400 
401  private:
402   /**
403    * Reset the state.
404    */
405   void Reset();
406 
407   /**
408    * Select the Source codec configuration based on peer codec support.
409    *
410    * Furthermore, the local state for the remaining non-selected codecs is
411    * updated to reflect whether the codec is selectable.
412    *
413    * @param p_peer the peer to use
414    * @return a pointer to the corresponding SEP Sink entry on success,
415    * otherwise nullptr
416    */
417   const BtaAvCoSep* SelectSourceCodec(BtaAvCoPeer* p_peer);
418 
419   /**
420    * Select the Sink codec configuration based on peer codec support.
421    *
422    * Furthermore, the local state for the remaining non-selected codecs is
423    * updated to reflect whether the codec is selectable.
424    *
425    * @param p_peer the peer to use
426    * @return a pointer to the corresponding SEP Source entry on success,
427    * otherwise nullptr
428    */
429   const BtaAvCoSep* SelectSinkCodec(BtaAvCoPeer* p_peer);
430 
431   /**
432    * Save new codec configuration.
433    *
434    * @param p_peer the peer to use
435    * @param new_codec_config the new codec configuration to use
436    * @param num_protect the number of content protection elements
437    * @param p_protect_info the content protection info to use
438    * @param t_local_sep the profile for which the codec config needs to be
439    * saved.
440    */
441   void SaveNewCodecConfig(BtaAvCoPeer* p_peer, const uint8_t* new_codec_config,
442                           uint8_t num_protect, const uint8_t* p_protect_info,
443                           const uint8_t t_local_sep);
444 
445   /**
446    * Set the Over-The-Air preferred codec configuration.
447    *
448    * The OTA preferred codec configuration is ignored if the current
449    * codec configuration contains explicit user configuration, or if the
450    * codec configuration for the same codec contains explicit user
451    * configuration.
452    *
453    * @param p_peer is the peer device that sent the OTA codec configuration
454    * @param p_ota_codec_config contains the received OTA A2DP codec
455    * configuration from the remote peer. Note: this is not the peer codec
456    * capability, but the codec configuration that the peer would like to use.
457    * @param num_protect is the number of content protection methods to use
458    * @param p_protect_info contains the content protection information to use.
459    * @param p_restart_output if there is a change in the encoder configuration
460    * that requires restarting of the A2DP connection, flag |p_restart_output|
461    * is set to true.
462    * @param t_local_sep the profile for which ota config needs to be set.
463    * @return true on success, otherwise false
464    */
465   bool SetCodecOtaConfig(BtaAvCoPeer* p_peer, const uint8_t* p_ota_codec_config,
466                          uint8_t num_protect, const uint8_t* p_protect_info,
467                          bool* p_restart_output, const uint8_t t_local_sep);
468 
469   /**
470    * Update all selectable Source codecs with the corresponding codec
471    * information from a Sink peer.
472    *
473    * @param p_peer the peer Sink SEP to use
474    * @return the number of codecs that have been updated
475    */
476   size_t UpdateAllSelectableSourceCodecs(BtaAvCoPeer* p_peer);
477 
478   /**
479    * Update a selectable Source codec with the corresponding codec information
480    * from a Sink peer.
481    *
482    * @param codec_config the codec config info to identify the codec to update
483    * @param p_peer the peer Sink SEP to use
484    * @return true if the codec is updated, otherwise false
485    */
486   bool UpdateSelectableSourceCodec(const A2dpCodecConfig& codec_config,
487                                    BtaAvCoPeer* p_peer);
488 
489   /**
490    * Update all selectable Sink codecs with the corresponding codec
491    * information from a Source peer.
492    *
493    * @param p_peer the peer Source SEP to use
494    * @return the number of codecs that have been updated
495    */
496   size_t UpdateAllSelectableSinkCodecs(BtaAvCoPeer* p_peer);
497 
498   /**
499    * Update a selectable Sink codec with the corresponding codec information
500    * from a Source peer.
501    *
502    * @param codec_config the codec config info to identify the codec to update
503    * @param p_peer the peer Source SEP to use
504    * @return true if the codec is updated, otherwise false
505    */
506   bool UpdateSelectableSinkCodec(const A2dpCodecConfig& codec_config,
507                                  BtaAvCoPeer* p_peer);
508 
509   /**
510    * Attempt to select Source codec configuration for a Sink peer.
511    *
512    * @param codec_config the codec configuration to use
513    * @param p_peer the Sink peer to use
514    * @return a pointer to the corresponding SEP Sink entry on success,
515    * otnerwise nullptr
516    */
517   const BtaAvCoSep* AttemptSourceCodecSelection(
518       const A2dpCodecConfig& codec_config, BtaAvCoPeer* p_peer);
519 
520   /**
521    * Attempt to select Sink codec configuration for a Source peer.
522    *
523    * @param codec_config the codec configuration to use
524    * @param p_peer the Source peer to use
525    * @return a pointer to the corresponding SEP Source entry on success,
526    * otnerwise nullptr
527    */
528   const BtaAvCoSep* AttemptSinkCodecSelection(
529       const A2dpCodecConfig& codec_config, BtaAvCoPeer* p_peer);
530 
531   /**
532    * Let the HAL offload provider select codec configuration.
533    *
534    * @param p_peer the peer to use
535    * @param configuration configuration from the offload provider
536    */
537   std::optional<::bluetooth::audio::a2dp::provider::a2dp_configuration>
538   GetProviderCodecConfiguration(BtaAvCoPeer* p_peer);
539 
540   /**
541    * Select the HAL proposed configuration.
542    */
543   BtaAvCoSep* SelectProviderCodecConfiguration(
544       BtaAvCoPeer* p_peer,
545       const ::bluetooth::audio::a2dp::provider::a2dp_configuration&
546           provider_codec_config);
547 
548   /**
549    * Returns the state that needs to be accessed.
550    * @param p_peer peer address.
551    * @return state of the profile.
552    */
553   BtaAvCoState* getStateFromPeer(const BtaAvCoPeer* p_peer);
554 
555   /**
556    * Returns the state based on the local profile of the stack.
557    * @param t_local_sep local sep type
558    * @return state of the profile.
559    */
560   BtaAvCoState* getStateFromLocalProfile(const uint8_t t_local_sep);
561 
ContentProtectEnabled()562   bool ContentProtectEnabled() const { return content_protect_enabled_; }
563 
564   const bool content_protect_enabled_;  // True if Content Protect is enabled
565   uint8_t content_protect_flag_;        // Content Protect flag
566   BtaAvCoState bta_av_legacy_state_;    // Legacy state
567   BtaAvCoState bta_av_source_state_;    // Source profile state
568   BtaAvCoState bta_av_sink_state_;      // Sink profile state
569 };
570