• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA
3  * - www.ehima.com
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 #pragma once
19 
20 #include <memory>
21 #include <utility>  // for std::pair
22 #include <vector>
23 
24 #include "audio_hal_client/audio_hal_client.h"
25 #include "bta_groups.h"
26 #include "gatt_api.h"
27 #include "gmap_client.h"
28 #include "le_audio_types.h"
29 #include "osi/include/alarm.h"
30 #include "stack/btm/btm_dev.h"
31 #include "types/raw_address.h"
32 
33 namespace bluetooth::le_audio {
34 
35 // Maps to BluetoothProfile#LE_AUDIO
36 #define LE_AUDIO_PROFILE_CONSTANT 22
37 #define LE_AUDIO_INVALID_CIS_HANDLE 0xFFFF
38 
39 /* Enums */
40 enum class DeviceConnectState : uint8_t {
41   /* Initial state */
42   DISCONNECTED,
43   /* When ACL connected, encrypted, CCC registered and initial characteristics
44      read is completed */
45   CONNECTED,
46   /* Used when device is unbonding (RemoveDevice() API is called) */
47   REMOVING,
48   /* Disconnecting */
49   DISCONNECTING,
50   /* Disconnecting for recover - after that we want direct connect to be
51      initiated */
52   DISCONNECTING_AND_RECOVER,
53   /* 2 states below are used when user creates connection. Connect API is
54      called. */
55   CONNECTING_BY_USER,
56   /* Always used after CONNECTING_BY_USER */
57   CONNECTED_BY_USER_GETTING_READY,
58   /* 2 states are used when autoconnect was used for the connection.*/
59   CONNECTING_AUTOCONNECT,
60   /* Always used after CONNECTING_AUTOCONNECT */
61   CONNECTED_AUTOCONNECT_GETTING_READY,
62 };
63 
64 std::ostream& operator<<(std::ostream& os, const DeviceConnectState& state);
65 
66 /* Class definitions */
67 
68 /* LeAudioDevice class represents GATT server device with ASCS, PAC services as
69  * mandatory. Device may contain multiple ASEs, PACs, audio locations. ASEs from
70  * multiple devices may be formed in group.
71  *
72  * Device is created after connection or after storage restoration.
73  *
74  * Active device means that device has at least one ASE which will participate
75  * in any state transition of state machine. ASEs and devices will be activated
76  * according to requested by upper context type.
77  */
78 class LeAudioDevice {
79 public:
80   RawAddress address_;
81 
82   DeviceConnectState connection_state_;
83   bool known_service_handles_;
84   bool notify_connected_after_read_;
85   bool closing_stream_for_disconnection_;
86   bool autoconnect_flag_;
87   tCONN_ID conn_id_;
88   uint16_t mtu_;
89   bool encrypted_;
90   int group_id_;
91   bool csis_member_;
92   int cis_failed_to_be_established_retry_cnt_;
93   std::bitset<16> tmap_role_;
94 
95   uint8_t audio_directions_;
96   types::BidirectionalPair<std::optional<types::hdl_pair_wrapper<types::AudioLocations>>>
97           audio_locations_;
98 
99   types::PublishedAudioCapabilities snk_pacs_;
100   types::PublishedAudioCapabilities src_pacs_;
101 
102   struct types::hdl_pair audio_avail_hdls_;
103   struct types::hdl_pair audio_supp_cont_hdls_;
104   std::vector<struct types::ase> ases_;
105   struct types::hdl_pair ctp_hdls_;
106   uint16_t tmap_role_hdl_;
107   std::string model_name_;
108   bool allowlist_flag_;
109   bool acl_asymmetric_;
110   bool acl_phy_update_done_;
111   std::unique_ptr<GmapClient> gmap_client_;
112 
113   alarm_t* link_quality_timer;
114   uint16_t link_quality_timer_data;
115 
116   uint8_t last_ase_ctp_command_sent;
117 
118   LeAudioDevice(const RawAddress& address, DeviceConnectState state,
119                 int group_id = bluetooth::groups::kGroupUnknown)
address_(address)120       : address_(address),
121         connection_state_(state),
122         known_service_handles_(false),
123         notify_connected_after_read_(false),
124         closing_stream_for_disconnection_(false),
125         autoconnect_flag_(false),
126         conn_id_(GATT_INVALID_CONN_ID),
127         mtu_(0),
128         encrypted_(false),
129         group_id_(group_id),
130         csis_member_(false),
131         cis_failed_to_be_established_retry_cnt_(0),
132         audio_directions_(0),
133         model_name_(""),
134         allowlist_flag_(false),
135         acl_asymmetric_(false),
136         acl_phy_update_done_(false),
137         link_quality_timer(nullptr),
138         last_ase_ctp_command_sent(0x00),
139         dsa_({{DsaMode::DISABLED},
140               types::DataPathState::IDLE,
141               LE_AUDIO_INVALID_CIS_HANDLE,
142               false}) {}
143   ~LeAudioDevice(void);
GetAddressWithType()144   inline tBLE_BD_ADDR GetAddressWithType() const { return BTM_Sec_GetAddressWithType(address_); }
145 
146   void SetConnectionState(DeviceConnectState state);
147   DeviceConnectState GetConnectionState(void);
148   void ClearPACs(void);
149   void RegisterPACs(std::vector<struct types::acs_ac_record>* apr_db,
150                     std::vector<struct types::acs_ac_record>* apr);
151   struct types::ase* GetAseByValHandle(uint16_t val_hdl);
152   int GetAseCount(uint8_t direction);
153   struct types::ase* GetFirstActiveAse(void);
154   struct types::ase* GetFirstActiveAseByDirection(uint8_t direction);
155   struct types::ase* GetNextActiveAseWithSameDirection(struct types::ase* base_ase);
156   struct types::ase* GetNextActiveAseWithDifferentDirection(struct types::ase* base_ase);
157   struct types::ase* GetFirstActiveAseByCisAndDataPathState(types::CisState cis_state,
158                                                             types::DataPathState data_path_state);
159   struct types::ase* GetFirstInactiveAse(uint8_t direction, bool reconnect = false);
160   struct types::ase* GetFirstAseWithState(uint8_t direction, types::AseState state);
161   struct types::ase* GetNextActiveAse(struct types::ase* ase);
162   struct types::ase* GetAseToMatchBidirectionCis(struct types::ase* ase);
163   types::BidirectionalPair<struct types::ase*> GetAsesByCisConnHdl(uint16_t conn_hdl);
164   types::BidirectionalPair<struct types::ase*> GetAsesByCisId(uint8_t cis_id);
165   bool HaveActiveAse(void);
166   bool HaveAllActiveAsesSameState(types::AseState state);
167   bool HaveAllActiveAsesSameDataPathState(types::DataPathState state) const;
168   bool HaveAnyUnconfiguredAses(void);
169   bool HaveAnyStreamingAses(void);
170   bool HaveAnyReleasingAse(void);
171   bool IsReadyToCreateStream(void);
IsReadyToStream(void)172   bool IsReadyToStream(void) const {
173     return HaveAllActiveAsesCisEst() &&
174            HaveAllActiveAsesSameDataPathState(types::DataPathState::CONFIGURED);
175   }
176   bool IsReadyToSuspendStream(void);
177   bool HaveAllActiveAsesCisEst(void) const;
178   bool HaveAnyCisConnected(void);
179   uint8_t GetSupportedAudioChannelCounts(uint8_t direction) const;
180   uint8_t GetPhyBitmask(void) const;
181   uint8_t GetPreferredPhyBitmask(uint8_t preferred_phy) const;
182   bool IsAudioSetConfigurationSupported(const types::AudioSetConfiguration* audio_set_conf) const;
183   bool ConfigureAses(const types::AudioSetConfiguration* audio_set_conf, uint8_t group_size,
184                      uint8_t direction, types::LeAudioContextType context_type,
185                      uint8_t* number_of_already_active_group_ase,
186                      types::AudioLocations& group_audio_locations_out,
187                      const types::AudioContexts& metadata_context_types,
188                      const std::vector<uint8_t>& ccid_lists, bool reuse_cis_id);
189 
190   inline types::AudioContexts GetSupportedContexts(
191           int direction = types::kLeAudioDirectionBoth) const {
192     log::assert_that(direction <= (types::kLeAudioDirectionBoth), "Invalid direction used.");
193 
194     if (direction < types::kLeAudioDirectionBoth) {
195       return supp_contexts_.get(direction);
196     } else {
197       return types::get_bidirectional(supp_contexts_);
198     }
199   }
SetSupportedContexts(types::BidirectionalPair<types::AudioContexts> contexts)200   inline void SetSupportedContexts(types::BidirectionalPair<types::AudioContexts> contexts) {
201     supp_contexts_ = contexts;
202   }
203 
204   inline types::AudioContexts GetAvailableContexts(
205           int direction = types::kLeAudioDirectionBoth) const {
206     log::assert_that(direction <= (types::kLeAudioDirectionBoth), "Invalid direction used.");
207 
208     if (direction < types::kLeAudioDirectionBoth) {
209       return avail_contexts_.get(direction);
210     } else {
211       return types::get_bidirectional(avail_contexts_);
212     }
213   }
214   void SetAvailableContexts(types::BidirectionalPair<types::AudioContexts> cont_val);
215 
216   void DeactivateAllAses(void);
217   bool ActivateConfiguredAses(
218           types::LeAudioContextType context_type,
219           const types::BidirectionalPair<types::AudioContexts>& metadata_context_types,
220           types::BidirectionalPair<std::vector<uint8_t>> ccid_lists);
221   void SetMetadataToAse(struct types::ase* ase, const types::LeAudioLtvMap& base_metadata,
222                         const types::AudioContexts& metadata_context_types,
223                         const std::vector<uint8_t>& ccid_lists);
224 
225   void PrintDebugState(void);
226   void DumpPacsDebugState(std::stringstream& stream);
227   void Dump(std::stringstream& stream);
228 
229   void DisconnectAcl(void);
230   types::LeAudioLtvMap GetMetadata(types::AudioContexts context_type,
231                                    const std::vector<uint8_t>& ccid_list);
232   bool IsMetadataChanged(const types::BidirectionalPair<types::AudioContexts>& context_types,
233                          const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists);
234 
235   void GetDeviceModelName(void);
236   void UpdateDeviceAllowlistFlag(void);
237   DsaModes GetDsaModes(void);
238   bool DsaReducedSduSizeSupported();
239   types::DataPathState GetDsaDataPathState(void);
240   void SetDsaDataPathState(types::DataPathState state);
241   uint16_t GetDsaCisHandle(void);
242   void SetDsaCisHandle(uint16_t cis_handle);
243 
244 private:
245   types::BidirectionalPair<types::AudioContexts> avail_contexts_;
246   types::BidirectionalPair<types::AudioContexts> supp_contexts_;
247   struct {
248     DsaModes modes;
249     types::DataPathState state;
250     uint16_t cis_handle;
251     bool reduced_sdu;  // TODO: Remove when earbud implementations move to approved DSA 2.0 standard
252   } dsa_;
253 
254   static constexpr char kLeAudioDeviceAllowListProp[] = "persist.bluetooth.leaudio.allow_list";
255 
256   void DumpPacsDebugState(std::stringstream& stream, types::PublishedAudioCapabilities pacs);
257   void ParseHeadtrackingCodec(const struct types::acs_ac_record& pac);
258 };
259 
260 /* LeAudioDevices class represents a wraper helper over all devices in le audio
261  * implementation. It allows to operate on device from a list (vector container)
262  * using determinants like address, connection id etc.
263  */
264 class LeAudioDevices {
265 public:
266   void Add(const RawAddress& address, bluetooth::le_audio::DeviceConnectState state,
267            int group_id = bluetooth::groups::kGroupUnknown);
268   void Remove(const RawAddress& address);
269   LeAudioDevice* FindByAddress(const RawAddress& address) const;
270   std::shared_ptr<LeAudioDevice> GetByAddress(const RawAddress& address) const;
271   LeAudioDevice* FindByConnId(tCONN_ID conn_id) const;
272   LeAudioDevice* FindByCisConnHdl(uint8_t cig_id, uint16_t conn_hdl) const;
273   void SetInitialGroupAutoconnectState(int group_id, int gatt_if,
274                                        tBTM_BLE_CONN_TYPE reconnection_mode,
275                                        bool current_dev_autoconnect_flag);
276   size_t Size(void) const;
277   void Dump(std::stringstream& stream, int group_id) const;
278   void Cleanup(tGATT_IF client_if);
279 
280 private:
281   std::vector<std::shared_ptr<LeAudioDevice>> leAudioDevices_;
282 };
283 
284 }  // namespace bluetooth::le_audio
285