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