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