• 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 #include "devices.h"
19 
20 #include <base/strings/string_number_conversions.h>
21 #include <bluetooth/log.h>
22 #include <com_android_bluetooth_flags.h>
23 #include <stdio.h>
24 
25 #include <algorithm>
26 #include <cstddef>
27 #include <cstdint>
28 #include <iomanip>
29 #include <ios>
30 #include <iterator>
31 #include <memory>
32 #include <optional>
33 #include <ostream>
34 #include <sstream>
35 #include <string>
36 #include <vector>
37 
38 #include "acl_api.h"
39 #include "bta_gatt_api.h"
40 #include "bta_gatt_queue.h"
41 #include "btif/include/btif_storage.h"
42 #include "btm_ble_api_types.h"
43 #include "btm_iso_api_types.h"
44 #include "common/strings.h"
45 #include "gatt_api.h"
46 #include "hardware/bluetooth.h"
47 #include "hci/controller_interface.h"
48 #include "hci_error_code.h"
49 #include "hcidefs.h"
50 #include "internal_include/bt_trace.h"
51 #include "le_audio/codec_manager.h"
52 #include "le_audio/le_audio_types.h"
53 #include "le_audio_log_history.h"
54 #include "le_audio_utils.h"
55 #include "main/shim/entry.h"
56 #include "osi/include/alarm.h"
57 #include "osi/include/properties.h"
58 #include "stack/include/btm_client_interface.h"
59 #include "types/bt_transport.h"
60 #include "types/raw_address.h"
61 
62 using bluetooth::hci::kIsoCigPhy1M;
63 using bluetooth::hci::kIsoCigPhy2M;
64 using bluetooth::le_audio::DeviceConnectState;
65 using bluetooth::le_audio::types::ase;
66 using bluetooth::le_audio::types::AseState;
67 using bluetooth::le_audio::types::AudioContexts;
68 using bluetooth::le_audio::types::AudioLocations;
69 using bluetooth::le_audio::types::BidirectionalPair;
70 using bluetooth::le_audio::types::CisState;
71 using bluetooth::le_audio::types::DataPathState;
72 using bluetooth::le_audio::types::LeAudioContextType;
73 
74 namespace bluetooth::le_audio {
operator <<(std::ostream & os,const DeviceConnectState & state)75 std::ostream& operator<<(std::ostream& os, const DeviceConnectState& state) {
76   const char* char_value_ = "UNKNOWN";
77 
78   switch (state) {
79     case DeviceConnectState::CONNECTED:
80       char_value_ = "CONNECTED";
81       break;
82     case DeviceConnectState::DISCONNECTED:
83       char_value_ = "DISCONNECTED";
84       break;
85     case DeviceConnectState::REMOVING:
86       char_value_ = "REMOVING";
87       break;
88     case DeviceConnectState::DISCONNECTING:
89       char_value_ = "DISCONNECTING";
90       break;
91     case DeviceConnectState::DISCONNECTING_AND_RECOVER:
92       char_value_ = "DISCONNECTING_AND_RECOVER";
93       break;
94     case DeviceConnectState::CONNECTING_BY_USER:
95       char_value_ = "CONNECTING_BY_USER";
96       break;
97     case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
98       char_value_ = "CONNECTED_BY_USER_GETTING_READY";
99       break;
100     case DeviceConnectState::CONNECTING_AUTOCONNECT:
101       char_value_ = "CONNECTING_AUTOCONNECT";
102       break;
103     case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
104       char_value_ = "CONNECTED_AUTOCONNECT_GETTING_READY";
105       break;
106   }
107 
108   os << char_value_ << " (" << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
109      << ")";
110   return os;
111 }
112 
GetFirstLeft(const AudioLocations & audio_locations)113 static uint32_t GetFirstLeft(const AudioLocations& audio_locations) {
114   uint32_t audio_location_ulong = audio_locations.to_ulong();
115 
116   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeft) {
117     return codec_spec_conf::kLeAudioLocationFrontLeft;
118   }
119 
120   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBackLeft) {
121     return codec_spec_conf::kLeAudioLocationBackLeft;
122   }
123 
124   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeftOfCenter) {
125     return codec_spec_conf::kLeAudioLocationFrontLeftOfCenter;
126   }
127 
128   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationSideLeft) {
129     return codec_spec_conf::kLeAudioLocationSideLeft;
130   }
131 
132   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopFrontLeft) {
133     return codec_spec_conf::kLeAudioLocationTopFrontLeft;
134   }
135 
136   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopBackLeft) {
137     return codec_spec_conf::kLeAudioLocationTopBackLeft;
138   }
139 
140   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopSideLeft) {
141     return codec_spec_conf::kLeAudioLocationTopSideLeft;
142   }
143 
144   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBottomFrontLeft) {
145     return codec_spec_conf::kLeAudioLocationBottomFrontLeft;
146   }
147 
148   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeftWide) {
149     return codec_spec_conf::kLeAudioLocationFrontLeftWide;
150   }
151 
152   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationLeftSurround) {
153     return codec_spec_conf::kLeAudioLocationLeftSurround;
154   }
155 
156   return 0;
157 }
158 
GetFirstRight(const AudioLocations & audio_locations)159 static uint32_t GetFirstRight(const AudioLocations& audio_locations) {
160   uint32_t audio_location_ulong = audio_locations.to_ulong();
161 
162   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRight) {
163     return codec_spec_conf::kLeAudioLocationFrontRight;
164   }
165 
166   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBackRight) {
167     return codec_spec_conf::kLeAudioLocationBackRight;
168   }
169 
170   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRightOfCenter) {
171     return codec_spec_conf::kLeAudioLocationFrontRightOfCenter;
172   }
173 
174   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationSideRight) {
175     return codec_spec_conf::kLeAudioLocationSideRight;
176   }
177 
178   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopFrontRight) {
179     return codec_spec_conf::kLeAudioLocationTopFrontRight;
180   }
181 
182   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopBackRight) {
183     return codec_spec_conf::kLeAudioLocationTopBackRight;
184   }
185 
186   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopSideRight) {
187     return codec_spec_conf::kLeAudioLocationTopSideRight;
188   }
189 
190   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBottomFrontRight) {
191     return codec_spec_conf::kLeAudioLocationBottomFrontRight;
192   }
193 
194   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRightWide) {
195     return codec_spec_conf::kLeAudioLocationFrontRightWide;
196   }
197 
198   if (audio_location_ulong & codec_spec_conf::kLeAudioLocationRightSurround) {
199     return codec_spec_conf::kLeAudioLocationRightSurround;
200   }
201 
202   return 0;
203 }
204 
PickAudioLocation(types::LeAudioConfigurationStrategy strategy,uint8_t direction,const types::BidirectionalPair<std::optional<types::hdl_pair_wrapper<types::AudioLocations>>> & device_audio_locations,AudioLocations & group_locations)205 static uint32_t PickAudioLocation(
206         types::LeAudioConfigurationStrategy strategy, uint8_t direction,
207         const types::BidirectionalPair<
208                 std::optional<types::hdl_pair_wrapper<types::AudioLocations>>>&
209                 device_audio_locations,
210         AudioLocations& group_locations) {
211   if (!device_audio_locations.get(direction)) {
212     log::error("No valid location is available for direction {}", +direction);
213     return 0;
214   }
215   auto const device_locations = device_audio_locations.get(direction)->value;
216 
217   log::debug("strategy: {}, locations: 0x{:x}, input group locations: 0x{:x}", (int)strategy,
218              device_locations.to_ulong(), group_locations.to_ulong());
219 
220   auto is_left_not_yet_assigned =
221           !(group_locations.to_ulong() & codec_spec_conf::kLeAudioLocationAnyLeft);
222   auto is_right_not_yet_assigned =
223           !(group_locations.to_ulong() & codec_spec_conf::kLeAudioLocationAnyRight);
224   uint32_t left_device_loc = GetFirstLeft(device_locations);
225   uint32_t right_device_loc = GetFirstRight(device_locations);
226 
227   /* Sink locations should be either Left or Right - TMAP 1.0 Sec. 3.5.1.2.1 */
228   if (direction == le_audio::types::kLeAudioDirectionSink && left_device_loc == 0 &&
229       right_device_loc == 0) {
230     log::warn("Can't find device able to render left  and right audio channel");
231   }
232 
233   switch (strategy) {
234     case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
235     case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
236       if (left_device_loc && is_left_not_yet_assigned) {
237         group_locations |= left_device_loc;
238         return left_device_loc;
239       }
240 
241       if (right_device_loc && is_right_not_yet_assigned) {
242         group_locations |= right_device_loc;
243         return right_device_loc;
244       }
245       break;
246 
247     case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
248       if (left_device_loc && right_device_loc) {
249         group_locations |= left_device_loc | right_device_loc;
250         return left_device_loc | right_device_loc;
251       }
252       break;
253     default:
254       log::fatal("Unknown strategy: {}", strategy);
255       return 0;
256   }
257 
258   /* Return either any left or any right audio location. It might result with
259    * multiple devices within the group having the same location.
260    */
261   auto location = left_device_loc ? left_device_loc : right_device_loc;
262 
263   if (direction == le_audio::types::kLeAudioDirectionSink) {
264     log::error(
265             "Can't find device for left/right channel. Strategy: {}, device_locations: {:x}, "
266             "output group_locations: {:x}, chosen location: {}.",
267             strategy, device_locations.to_ulong(), group_locations.to_ulong(), location);
268   } else {
269     log::debug(
270             "No left or right audio location available. Strategy: {}, device_locations: {:x}, "
271             "output group_locations: {:x}, chosen location: {}.",
272             strategy, device_locations.to_ulong(), group_locations.to_ulong(), location);
273   }
274   return location;
275 }
276 
IsAudioSetConfigurationSupported(const types::AudioSetConfiguration * audio_set_conf) const277 bool LeAudioDevice::IsAudioSetConfigurationSupported(
278         const types::AudioSetConfiguration* audio_set_conf) const {
279   for (auto direction :
280        {le_audio::types::kLeAudioDirectionSink, le_audio::types::kLeAudioDirectionSource}) {
281     const auto& confs = audio_set_conf->confs.get(direction);
282     if (confs.size() == 0) {
283       continue;
284     }
285 
286     log::info("Looking for requirements: {} - {}", audio_set_conf->name,
287               direction == 1 ? "snk" : "src");
288 
289     auto const& pacs = (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_;
290     for (const auto& ent : confs) {
291       if (!utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
292         log::info("Configuration is NOT supported by device {}", address_);
293         return false;
294       }
295     }
296   }
297 
298   log::info("Configuration is supported by device {}", address_);
299   return true;
300 }
301 
ConfigureAses(const types::AudioSetConfiguration * audio_set_conf,uint8_t num_of_devices,uint8_t direction,LeAudioContextType context_type,uint8_t * number_of_already_active_group_ase,AudioLocations & group_audio_locations_memo,const AudioContexts & metadata_context_types,const std::vector<uint8_t> & ccid_lists,bool reuse_cis_id)302 bool LeAudioDevice::ConfigureAses(const types::AudioSetConfiguration* audio_set_conf,
303                                   uint8_t num_of_devices, uint8_t direction,
304                                   LeAudioContextType context_type,
305                                   uint8_t* number_of_already_active_group_ase,
306                                   AudioLocations& group_audio_locations_memo,
307                                   const AudioContexts& metadata_context_types,
308                                   const std::vector<uint8_t>& ccid_lists, bool reuse_cis_id) {
309   if (num_of_devices == 0) {
310     log::error("No devices available for configuration.");
311     return false;
312   }
313 
314   auto direction_str = (direction == types::kLeAudioDirectionSink ? "Sink" : "Source");
315   /* First try to use the already configured ASE */
316   auto ase = GetFirstActiveAseByDirection(direction);
317   if (ase) {
318     log::info("{}, using an already active {} ASE id={}", address_, direction_str, ase->id);
319   } else {
320     ase = GetFirstInactiveAse(direction, reuse_cis_id);
321   }
322 
323   if (!ase) {
324     log::error("{}, unable to find a {} ASE to configure", address_, direction_str);
325     PrintDebugState();
326     return false;
327   }
328 
329   if (!audio_locations_.get(direction)) {
330     log::error("{}, unable to find a {} audio allocation", address_, direction_str);
331     return false;
332   }
333 
334   auto const& audio_locations = audio_locations_.get(direction)->value;
335   auto const& group_ase_configs = audio_set_conf->confs.get(direction);
336   std::vector<types::AseConfiguration> ase_configs;
337   std::copy_if(group_ase_configs.cbegin(), group_ase_configs.cend(),
338                std::back_inserter(ase_configs), [&audio_locations](auto const& cfg) {
339                  /* Pass as matching if config has no allocation to match
340                   * (the legacy json config provider). Otherwise, with the codec
341                   * extensibility feature enabled, we receive ASE configurations
342                   * for the whole group and we should filter them by audio
343                   * allocations to match with the locations supported by a
344                   * particular device.
345                   */
346                  auto config = cfg.codec.params.GetAsCoreCodecConfig();
347                  if (!config.audio_channel_allocation.has_value()) {
348                    return true;
349                  }
350 
351                  // No locations bits means mono audio
352                  if (audio_locations.none()) {
353                    return true;
354                  }
355 
356                  // Filter-out not matching audio locations
357                  return (cfg.codec.params.GetAsCoreCodecConfig().audio_channel_allocation.value() &
358                          audio_locations.to_ulong()) != 0;
359                });
360 
361   auto const& pacs = (direction == types::kLeAudioDirectionSink) ? snk_pacs_ : src_pacs_;
362   for (size_t i = 0; i < ase_configs.size() && ase; ++i) {
363     auto const& ase_cfg = ase_configs.at(i);
364     if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) &&
365         !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
366       log::error("{}, No {} PAC found matching codec: {}. Stop the activation.", address_,
367                  direction_str, common::ToString(ase_cfg.codec));
368       return false;
369     }
370   }
371 
372   /* The number_of_already_active_group_ase keeps all the active ases
373    * in other devices in the group for the given direction.
374    * This function counts active ases only for this device, and we count here
375    * new active ases and already active ases which we want to reuse in the
376    * scenario
377    */
378   uint8_t active_ases = *number_of_already_active_group_ase;
379 
380   // Before we activate the ASEs, make sure we have the right configuration
381   // Check for matching PACs only if we know that the LTV format is being used.
382   uint8_t max_required_ase_per_dev =
383           ase_configs.size() / num_of_devices + (ase_configs.size() % num_of_devices);
384   int needed_ase = std::min((int)(max_required_ase_per_dev), (int)(ase_configs.size()));
385   log::debug("{}, {} {} ASE(s) required for this configuration.", address_, needed_ase,
386              direction_str);
387 
388   for (int i = 0; i < needed_ase; ++i) {
389     auto const& ase_cfg = ase_configs.at(i);
390     if (utils::IsCodecUsingLtvFormat(ase_cfg.codec.id) &&
391         !utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)) {
392       log::error("{}, No {} PAC found matching codec: {}. Stop the activation.", address_,
393                  direction_str, common::ToString(ase_cfg.codec));
394       return false;
395     }
396   }
397 
398   auto strategy = utils::GetStrategyForAseConfig(group_ase_configs, num_of_devices);
399 
400   // Make sure we configure a single microphone if Dual Bidir SWB is not
401   // supported.
402   if (direction == types::kLeAudioDirectionSource &&
403       !CodecManager::GetInstance()->IsDualBiDirSwbSupported() && (active_ases != 0)) {
404     if (CodecManager::GetInstance()->CheckCodecConfigIsDualBiDirSwb(*audio_set_conf)) {
405       log::error(
406               "{}, trying to configure the dual bidir SWB, but the feature is "
407               "disabled. This should not happen! Skipping ASE activation.",
408               address_);
409       return true;
410     }
411   }
412 
413   for (int i = 0; i < needed_ase && ase; ++i) {
414     auto const& ase_cfg = ase_configs.at(i);
415     ase->active = true;
416     ase->configured_for_context_type = context_type;
417     ase->data_path_configuration = ase_cfg.data_path_configuration;
418     active_ases++;
419 
420     /* In case of late connect, we could be here for STREAMING ase.
421      * in such case, it is needed to mark ase as known active ase which
422      * is important to validate scenario and is done already few lines above.
423      * Nothing more to do is needed here.
424      */
425     if (ase->state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
426       if (ase->state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) {
427         ase->reconfigure = true;
428       }
429 
430       ase->target_latency = ase_cfg.qos.target_latency;
431       ase->codec_config = ase_cfg.codec;
432 
433       /* Let's choose audio channel allocation if not set */
434       ase->codec_config.params.Add(
435               codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
436               PickAudioLocation(strategy, direction, audio_locations_, group_audio_locations_memo));
437 
438       /* Get default value if no requirement for specific frame blocks per sdu
439        */
440       if (utils::IsCodecUsingLtvFormat(ase->codec_config.id) &&
441           !ase->codec_config.params.Find(codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu)) {
442         ase->codec_config.params.Add(
443                 codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
444                 GetMaxCodecFramesPerSduFromPac(
445                         utils::GetConfigurationSupportedPac(pacs, ase_cfg.codec)));
446       }
447 
448       ase->qos_config.sdu_interval = ase_cfg.qos.sduIntervalUs;
449       ase->qos_config.max_sdu_size = ase_cfg.qos.maxSdu;
450       ase->qos_config.retrans_nb = ase_cfg.qos.retransmission_number;
451       ase->qos_config.max_transport_latency = ase_cfg.qos.max_transport_latency;
452 
453       SetMetadataToAse(ase, ase_cfg.metadata, metadata_context_types, ccid_lists);
454     }
455 
456     log::debug(
457             "device={}, activated ASE id={}, direction={}, max_sdu_size={}, "
458             "cis_id={}, target_latency={}",
459             address_, ase->id, direction_str, ase->qos_config.max_sdu_size, ase->cis_id,
460             ase_cfg.qos.target_latency);
461 
462     /* Try to use the already active ASE */
463     ase = GetNextActiveAseWithSameDirection(ase);
464     if (ase == nullptr) {
465       ase = GetFirstInactiveAse(direction, reuse_cis_id);
466     }
467   }
468 
469   *number_of_already_active_group_ase = active_ases;
470   return true;
471 }
472 
473 /* LeAudioDevice Class methods implementation */
SetConnectionState(DeviceConnectState state)474 void LeAudioDevice::SetConnectionState(DeviceConnectState state) {
475   log::debug("{}, {} --> {}", address_, bluetooth::common::ToString(connection_state_),
476              bluetooth::common::ToString(state));
477   LeAudioLogHistory::Get()->AddLogHistory(kLogConnectionTag, group_id_, address_,
478                                           bluetooth::common::ToString(connection_state_) + " -> ",
479                                           "->" + bluetooth::common::ToString(state));
480   connection_state_ = state;
481 }
482 
GetConnectionState(void)483 DeviceConnectState LeAudioDevice::GetConnectionState(void) { return connection_state_; }
484 
ClearPACs(void)485 void LeAudioDevice::ClearPACs(void) {
486   snk_pacs_.clear();
487   src_pacs_.clear();
488 }
489 
~LeAudioDevice(void)490 LeAudioDevice::~LeAudioDevice(void) {
491   alarm_free(link_quality_timer);
492   this->ClearPACs();
493 }
494 
ParseHeadtrackingCodec(const struct types::acs_ac_record & pac)495 void LeAudioDevice::ParseHeadtrackingCodec(const struct types::acs_ac_record& pac) {
496   if (pac.codec_id == types::kLeAudioCodecHeadtracking) {
497     log::info("Headtracking supported");
498 
499     // Assume LE-ISO is supported if metadata is not available
500     dsa_.modes = {
501             DsaMode::DISABLED,
502             DsaMode::ISO_SW,
503             DsaMode::ISO_HW,
504     };
505 
506     /*
507      * Android Headtracker Codec Metadata description
508      *   length: 5
509      *   type: 0xFF
510      *   value: {
511      *     vendorId: 0x00E0 (Google)
512      *     vendorSpecificMetadata: {
513      *       length: 1
514      *       type: 1 (Headtracker supported transports)
515      *       value: x
516      *     }
517      *   }
518      */
519     std::vector<uint8_t> ltv = pac.metadata.RawPacket();
520     if (ltv.size() < 7) {
521       log::info("{}, headtracker codec does not have metadata", address_);
522       return;
523     }
524 
525     if (ltv[0] < 5 || ltv[1] != types::kLeAudioMetadataTypeVendorSpecific ||
526         ltv[2] != (types::kLeAudioVendorCompanyIdGoogle & 0xFF) ||
527         ltv[3] != (types::kLeAudioVendorCompanyIdGoogle >> 8) ||
528         ltv[4] != types::kLeAudioMetadataHeadtrackerTransportLen ||
529         ltv[5] != types::kLeAudioMetadataHeadtrackerTransportVal) {
530       log::warn("{}, headtracker codec metadata invalid", address_);
531       return;
532     }
533 
534     // Valid headtracker codec metadata available, so it must support reduced sdu size
535     dsa_.reduced_sdu = true;
536 
537     uint8_t supported_transports = ltv[6];
538     DsaModes dsa_modes = {DsaMode::DISABLED};
539 
540     if ((supported_transports & types::kLeAudioMetadataHeadtrackerTransportLeAcl) != 0) {
541       log::debug("{}, headtracking supported over LE-ACL", address_);
542       dsa_modes.push_back(DsaMode::ACL);
543     }
544 
545     if ((supported_transports & types::kLeAudioMetadataHeadtrackerTransportLeIso) != 0) {
546       log::debug("{}, headtracking supported over LE-ISO", address_);
547       dsa_modes.push_back(DsaMode::ISO_SW);
548       dsa_modes.push_back(DsaMode::ISO_HW);
549     }
550 
551     dsa_.modes = dsa_modes;
552   }
553 }
554 
RegisterPACs(std::vector<struct types::acs_ac_record> * pac_db,std::vector<struct types::acs_ac_record> * pac_recs)555 void LeAudioDevice::RegisterPACs(std::vector<struct types::acs_ac_record>* pac_db,
556                                  std::vector<struct types::acs_ac_record>* pac_recs) {
557   /* Clear PAC database for characteristic in case if re-read, indicated */
558   if (!pac_db->empty()) {
559     log::debug("{}, upgrade PACs for characteristic", address_);
560     pac_db->clear();
561   }
562 
563   dsa_.modes = {DsaMode::DISABLED};
564 
565   /* TODO wrap this logging part with debug flag */
566   for (const struct types::acs_ac_record& pac : *pac_recs) {
567     std::stringstream debug_str;
568     debug_str << "Registering PAC" << "\n\tCoding format: " << loghex(pac.codec_id.coding_format)
569               << "\n\tVendor codec company ID: " << loghex(pac.codec_id.vendor_company_id)
570               << "\n\tVendor codec ID: " << loghex(pac.codec_id.vendor_codec_id)
571               << "\n\tCodec spec caps:\n";
572     if (utils::IsCodecUsingLtvFormat(pac.codec_id) && !pac.codec_spec_caps.IsEmpty()) {
573       debug_str << pac.codec_spec_caps.ToString("", types::CodecCapabilitiesLtvFormat);
574     } else {
575       debug_str << base::HexEncode(pac.codec_spec_caps_raw.data(), pac.codec_spec_caps_raw.size());
576     }
577 
578     debug_str << "\n\tMetadata: " << pac.metadata.ToString();
579     log::debug("{}", debug_str.str());
580 
581     ParseHeadtrackingCodec(pac);
582   }
583 
584   pac_db->insert(pac_db->begin(), pac_recs->begin(), pac_recs->end());
585 }
586 
GetAseByValHandle(uint16_t val_hdl)587 struct ase* LeAudioDevice::GetAseByValHandle(uint16_t val_hdl) {
588   auto iter = std::find_if(ases_.begin(), ases_.end(),
589                            [&val_hdl](const auto& ase) { return ase.hdls.val_hdl == val_hdl; });
590 
591   return (iter == ases_.end()) ? nullptr : &(*iter);
592 }
593 
GetAseCount(uint8_t direction)594 int LeAudioDevice::GetAseCount(uint8_t direction) {
595   return std::count_if(ases_.begin(), ases_.end(),
596                        [direction](const auto& a) { return a.direction == direction; });
597 }
598 
GetFirstAseWithState(uint8_t direction,AseState state)599 struct ase* LeAudioDevice::GetFirstAseWithState(uint8_t direction, AseState state) {
600   auto iter = std::find_if(ases_.begin(), ases_.end(), [direction, state](const auto& ase) {
601     return (ase.direction == direction) && (ase.state == state);
602   });
603 
604   return (iter == ases_.end()) ? nullptr : &(*iter);
605 }
606 
GetFirstActiveAse(void)607 struct ase* LeAudioDevice::GetFirstActiveAse(void) {
608   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) { return ase.active; });
609 
610   return (iter == ases_.end()) ? nullptr : &(*iter);
611 }
612 
GetFirstActiveAseByDirection(uint8_t direction)613 struct ase* LeAudioDevice::GetFirstActiveAseByDirection(uint8_t direction) {
614   auto iter = std::find_if(ases_.begin(), ases_.end(), [direction](const auto& ase) {
615     return ase.active && (ase.direction == direction);
616   });
617 
618   return (iter == ases_.end()) ? nullptr : &(*iter);
619 }
620 
GetNextActiveAseWithSameDirection(struct ase * base_ase)621 struct ase* LeAudioDevice::GetNextActiveAseWithSameDirection(struct ase* base_ase) {
622   auto iter = std::find_if(ases_.begin(), ases_.end(),
623                            [&base_ase](auto& ase) { return base_ase == &ase; });
624 
625   /* Invalid ase given */
626   if (iter == ases_.end() || std::distance(iter, ases_.end()) < 1) {
627     return nullptr;
628   }
629 
630   iter = std::find_if(std::next(iter, 1), ases_.end(), [&iter](const auto& ase) {
631     return ase.active && (*iter).direction == ase.direction;
632   });
633 
634   return (iter == ases_.end()) ? nullptr : &(*iter);
635 }
636 
GetNextActiveAseWithDifferentDirection(struct ase * base_ase)637 struct ase* LeAudioDevice::GetNextActiveAseWithDifferentDirection(struct ase* base_ase) {
638   auto iter = std::find_if(ases_.begin(), ases_.end(),
639                            [&base_ase](auto& ase) { return base_ase == &ase; });
640 
641   /* Invalid ase given */
642   if (std::distance(iter, ases_.end()) < 1) {
643     log::debug("{}, ASE {} does not use bidirectional CIS", address_, base_ase->id);
644     return nullptr;
645   }
646 
647   iter = std::find_if(std::next(iter, 1), ases_.end(), [&iter](const auto& ase) {
648     return ase.active && iter->direction != ase.direction;
649   });
650 
651   if (iter == ases_.end()) {
652     return nullptr;
653   }
654 
655   return &(*iter);
656 }
657 
GetFirstActiveAseByCisAndDataPathState(CisState cis_state,DataPathState data_path_state)658 struct ase* LeAudioDevice::GetFirstActiveAseByCisAndDataPathState(CisState cis_state,
659                                                                   DataPathState data_path_state) {
660   auto iter =
661           std::find_if(ases_.begin(), ases_.end(), [cis_state, data_path_state](const auto& ase) {
662             return ase.active && (ase.data_path_state == data_path_state) &&
663                    (ase.cis_state == cis_state);
664           });
665 
666   return (iter == ases_.end()) ? nullptr : &(*iter);
667 }
668 
GetFirstInactiveAse(uint8_t direction,bool reuse_cis_id)669 struct ase* LeAudioDevice::GetFirstInactiveAse(uint8_t direction, bool reuse_cis_id) {
670   auto iter = std::find_if(ases_.begin(), ases_.end(), [direction, reuse_cis_id](const auto& ase) {
671     if (ase.active || (ase.direction != direction)) {
672       return false;
673     }
674 
675     if (!reuse_cis_id) {
676       return true;
677     }
678 
679     return ase.cis_id != kInvalidCisId;
680   });
681   /* If ASE is found, return it */
682   if (iter != ases_.end()) {
683     return &(*iter);
684   }
685 
686   /* If reuse was not set, that means there is no inactive ASE available. */
687   if (!reuse_cis_id) {
688     return nullptr;
689   }
690 
691   /* Since there is no ASE with assigned CIS ID, it means new configuration
692    * needs more ASEs then it was configured before.
693    * Let's find just inactive one */
694   iter = std::find_if(ases_.begin(), ases_.end(), [direction](const auto& ase) {
695     if (ase.active || (ase.direction != direction)) {
696       return false;
697     }
698     return true;
699   });
700 
701   return (iter == ases_.end()) ? nullptr : &(*iter);
702 }
703 
GetNextActiveAse(struct ase * base_ase)704 struct ase* LeAudioDevice::GetNextActiveAse(struct ase* base_ase) {
705   auto iter = std::find_if(ases_.begin(), ases_.end(),
706                            [&base_ase](auto& ase) { return base_ase == &ase; });
707 
708   /* Invalid ase given */
709   if (iter == ases_.end() || std::distance(iter, ases_.end()) < 1) {
710     return nullptr;
711   }
712 
713   iter = std::find_if(std::next(iter, 1), ases_.end(), [](const auto& ase) { return ase.active; });
714 
715   return (iter == ases_.end()) ? nullptr : &(*iter);
716 }
717 
GetAseToMatchBidirectionCis(struct ase * base_ase)718 struct ase* LeAudioDevice::GetAseToMatchBidirectionCis(struct ase* base_ase) {
719   auto iter = std::find_if(ases_.begin(), ases_.end(), [&base_ase](auto& ase) {
720     return (base_ase->cis_conn_hdl == ase.cis_conn_hdl) && (base_ase->direction != ase.direction);
721   });
722   return (iter == ases_.end()) ? nullptr : &(*iter);
723 }
724 
GetAsesByCisConnHdl(uint16_t conn_hdl)725 BidirectionalPair<struct ase*> LeAudioDevice::GetAsesByCisConnHdl(uint16_t conn_hdl) {
726   BidirectionalPair<struct ase*> ases = {nullptr, nullptr};
727 
728   for (auto& ase : ases_) {
729     if (ase.cis_conn_hdl == conn_hdl) {
730       if (ase.direction == types::kLeAudioDirectionSink) {
731         ases.sink = &ase;
732       } else {
733         ases.source = &ase;
734       }
735     }
736   }
737 
738   return ases;
739 }
740 
GetAsesByCisId(uint8_t cis_id)741 BidirectionalPair<struct ase*> LeAudioDevice::GetAsesByCisId(uint8_t cis_id) {
742   BidirectionalPair<struct ase*> ases = {nullptr, nullptr};
743 
744   for (auto& ase : ases_) {
745     if (ase.cis_id == cis_id) {
746       if (ase.direction == types::kLeAudioDirectionSink) {
747         ases.sink = &ase;
748       } else {
749         ases.source = &ase;
750       }
751     }
752   }
753 
754   return ases;
755 }
756 
HaveActiveAse(void)757 bool LeAudioDevice::HaveActiveAse(void) {
758   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) { return ase.active; });
759 
760   return iter != ases_.end();
761 }
762 
HaveAnyReleasingAse(void)763 bool LeAudioDevice::HaveAnyReleasingAse(void) {
764   /* In configuring state when active in Idle or Configured and reconfigure */
765   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
766     if (!ase.active) {
767       return false;
768     }
769     return ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING;
770   });
771 
772   return iter != ases_.end();
773 }
774 
HaveAnyStreamingAses(void)775 bool LeAudioDevice::HaveAnyStreamingAses(void) {
776   /* In configuring state when active in Idle or Configured and reconfigure */
777   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
778     if (!ase.active) {
779       return false;
780     }
781 
782     if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
783       return true;
784     }
785 
786     return false;
787   });
788 
789   return iter != ases_.end();
790 }
791 
HaveAnyUnconfiguredAses(void)792 bool LeAudioDevice::HaveAnyUnconfiguredAses(void) {
793   /* In configuring state when active in Idle or Configured and reconfigure */
794   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
795     if (!ase.active) {
796       return false;
797     }
798 
799     if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE ||
800         ((ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) && ase.reconfigure)) {
801       return true;
802     }
803 
804     return false;
805   });
806 
807   return iter != ases_.end();
808 }
809 
HaveAllActiveAsesSameState(AseState state)810 bool LeAudioDevice::HaveAllActiveAsesSameState(AseState state) {
811   log::verbose("{}", address_);
812   auto iter = std::find_if(ases_.begin(), ases_.end(), [&state](const auto& ase) {
813     log::verbose("ASE id: {}, active: {}, state: {}", ase.id, ase.active,
814                  bluetooth::common::ToString(ase.state));
815     return ase.active && (ase.state != state);
816   });
817 
818   return iter == ases_.end();
819 }
820 
HaveAllActiveAsesSameDataPathState(types::DataPathState state) const821 bool LeAudioDevice::HaveAllActiveAsesSameDataPathState(types::DataPathState state) const {
822   log::verbose("{}", address_);
823   auto iter = std::find_if(ases_.begin(), ases_.end(), [&state](const auto& ase) {
824     log::verbose("ASE id: {}, active: {}, state: {}", ase.id, ase.active,
825                  bluetooth::common::ToString(ase.data_path_state));
826     return ase.active && (ase.data_path_state != state);
827   });
828 
829   return iter == ases_.end();
830 }
831 
IsReadyToCreateStream(void)832 bool LeAudioDevice::IsReadyToCreateStream(void) {
833   log::verbose("{}", address_);
834   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
835     if (!ase.active) {
836       return false;
837     }
838 
839     log::verbose("ASE id: {}, state: {}, direction: {}", ase.id,
840                  bluetooth::common::ToString(ase.state), ase.direction);
841     if (ase.direction == types::kLeAudioDirectionSink &&
842         (ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING &&
843          ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING)) {
844       return true;
845     }
846 
847     if (ase.direction == types::kLeAudioDirectionSource &&
848         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING) {
849       return true;
850     }
851 
852     return false;
853   });
854 
855   return iter == ases_.end();
856 }
857 
IsReadyToSuspendStream(void)858 bool LeAudioDevice::IsReadyToSuspendStream(void) {
859   auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
860     if (!ase.active) {
861       return false;
862     }
863 
864     if (ase.direction == types::kLeAudioDirectionSink &&
865         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED) {
866       return true;
867     }
868 
869     if (ase.direction == types::kLeAudioDirectionSource &&
870         ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING) {
871       return true;
872     }
873 
874     return false;
875   });
876 
877   return iter == ases_.end();
878 }
879 
HaveAllActiveAsesCisEst(void) const880 bool LeAudioDevice::HaveAllActiveAsesCisEst(void) const {
881   if (ases_.empty()) {
882     log::warn("No ases for device {}", address_);
883     /* If there is no ASEs at all, it means we are good here - meaning, it is
884      * not waiting for any CIS to be established.
885      */
886     return true;
887   }
888 
889   log::verbose("{}", address_);
890 
891   bool has_active_ase = false;
892   auto iter = std::find_if(ases_.begin(), ases_.end(), [&](const auto& ase) {
893     if (!has_active_ase && ase.active) {
894       has_active_ase = true;
895     }
896     log::verbose("ASE id: {}, cis_state: {}, direction: {}", ase.id,
897                  bluetooth::common::ToString(ase.cis_state), ase.direction);
898 
899     return ase.active && (ase.cis_state != CisState::CONNECTED);
900   });
901 
902   return iter == ases_.end() && has_active_ase;
903 }
904 
HaveAnyCisConnected(void)905 bool LeAudioDevice::HaveAnyCisConnected(void) {
906   /* Pending and Disconnecting is considered as connected in this function */
907   for (auto const ase : ases_) {
908     if (ase.cis_state == CisState::CONNECTED || ase.cis_state == CisState::CONNECTING ||
909         ase.cis_state == CisState::DISCONNECTING) {
910       return true;
911     }
912   }
913   return false;
914 }
915 
GetSupportedAudioChannelCounts(uint8_t direction) const916 uint8_t LeAudioDevice::GetSupportedAudioChannelCounts(uint8_t direction) const {
917   auto& pacs = direction == types::kLeAudioDirectionSink ? snk_pacs_ : src_pacs_;
918 
919   if (pacs.size() == 0) {
920     log::error("{}, missing PAC for direction {}", address_, direction);
921     return 0;
922   }
923 
924   for (const auto& pac_tuple : pacs) {
925     /* Get PAC records from tuple as second element from tuple */
926     auto& pac_recs = std::get<1>(pac_tuple);
927 
928     for (const auto pac : pac_recs) {
929       if (!utils::IsCodecUsingLtvFormat(pac.codec_id)) {
930         log::warn(" {} Unknown codec PAC record for codec: {}", address_,
931                   bluetooth::common::ToString(pac.codec_id));
932         continue;
933       }
934       log::assert_that(!pac.codec_spec_caps.IsEmpty(),
935                        "Codec specific capabilities are not parsed appropriately.");
936 
937       auto supported_channel_count_ltv =
938               pac.codec_spec_caps.Find(codec_spec_caps::kLeAudioLtvTypeSupportedAudioChannelCounts);
939 
940       if (supported_channel_count_ltv == std::nullopt ||
941           supported_channel_count_ltv->size() == 0L) {
942         return 1;
943       }
944 
945       return VEC_UINT8_TO_UINT8(supported_channel_count_ltv.value());
946     };
947   }
948 
949   return 0;
950 }
951 
952 /**
953  * Returns supported PHY's bitfield
954  */
GetPhyBitmask(void) const955 uint8_t LeAudioDevice::GetPhyBitmask(void) const {
956   uint8_t phy_bitfield = kIsoCigPhy1M;
957 
958   if (get_btm_client_interface().peer.BTM_IsPhy2mSupported(address_, BT_TRANSPORT_LE)) {
959     phy_bitfield |= kIsoCigPhy2M;
960   }
961 
962   return phy_bitfield;
963 }
964 
PrintDebugState(void)965 void LeAudioDevice::PrintDebugState(void) {
966   std::stringstream debug_str;
967 
968   debug_str << " Address: " << address_ << ", " << bluetooth::common::ToString(connection_state_)
969             << ", conn_id: " << +conn_id_ << ", mtu: " << +mtu_
970             << ", num_of_ase: " << static_cast<int>(ases_.size());
971 
972   if (ases_.size() > 0) {
973     debug_str << "\n  == ASEs == ";
974     for (auto& ase : ases_) {
975       debug_str << "  id: " << +ase.id << ", active: " << ase.active
976                 << ", dir: " << (ase.direction == types::kLeAudioDirectionSink ? "sink" : "source")
977                 << ", state: " << bluetooth::common::ToString(ase.state)
978                 << ", cis_id: " << +ase.cis_id << ", cis_handle: " << +ase.cis_conn_hdl
979                 << ", cis_state: " << bluetooth::common::ToString(ase.cis_state)
980                 << ", data_path_state: " << bluetooth::common::ToString(ase.data_path_state)
981                 << "\n ase max_latency: " << +ase.qos_config.max_transport_latency
982                 << ", rtn: " << +ase.qos_config.retrans_nb
983                 << ", max_sdu: " << +ase.qos_config.max_sdu_size
984                 << ", sdu_interval: " << +ase.qos_config.sdu_interval
985                 << ", presentation_delay: " << +ase.qos_config.presentation_delay
986                 << ", framing: " << +ase.qos_config.framing << ", phy: " << +ase.qos_config.phy
987                 << ", target latency: " << +ase.target_latency
988                 << ", reconfigure: " << ase.reconfigure << "\n\n";
989     }
990   }
991 
992   log::info("{}", debug_str.str());
993 }
994 
GetPreferredPhyBitmask(uint8_t preferred_phy) const995 uint8_t LeAudioDevice::GetPreferredPhyBitmask(uint8_t preferred_phy) const {
996   // Start with full local phy support
997   uint8_t phy_bitmask = bluetooth::hci::kIsoCigPhy1M;
998   if (bluetooth::shim::GetController()->SupportsBle2mPhy()) {
999     phy_bitmask |= bluetooth::hci::kIsoCigPhy2M;
1000   }
1001   if (bluetooth::shim::GetController()->SupportsBleCodedPhy()) {
1002     phy_bitmask |= bluetooth::hci::kIsoCigPhyC;
1003   }
1004 
1005   // Check against the remote device support
1006   phy_bitmask &= GetPhyBitmask();
1007 
1008   // Take the preferences if possible
1009   if (preferred_phy && (phy_bitmask & preferred_phy)) {
1010     phy_bitmask &= preferred_phy;
1011     log::debug("{},  using ASE preferred phy 0x{:02x}", address_, static_cast<int>(phy_bitmask));
1012   } else {
1013     log::warn(
1014             " {}, ASE preferred 0x{:02x} has nothing common with phy_bitfield  "
1015             "0x{:02x}",
1016             address_, static_cast<int>(preferred_phy), static_cast<int>(phy_bitmask));
1017   }
1018   return phy_bitmask;
1019 }
1020 
DumpPacsDebugState(std::stringstream & stream,types::PublishedAudioCapabilities pacs)1021 void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream,
1022                                        types::PublishedAudioCapabilities pacs) {
1023   if (pacs.size() > 0) {
1024     for (auto& pac : pacs) {
1025       stream << "\t    • Value handle: " << loghex(std::get<0>(pac).val_hdl)
1026              << ", CCC handle: " << loghex(std::get<0>(pac).ccc_hdl);
1027 
1028       for (auto& record : std::get<1>(pac)) {
1029         stream << "\n\t\t· CodecId (Coding format: " << loghex(record.codec_id.coding_format)
1030                << ", Vendor company ID: " << loghex(record.codec_id.vendor_company_id)
1031                << ", Vendor codec ID: " << loghex(record.codec_id.vendor_codec_id) << ")";
1032         stream << "\n\t\t    Codec specific capabilities:\n";
1033         if (utils::IsCodecUsingLtvFormat(record.codec_id)) {
1034           stream << record.codec_spec_caps.ToString("\t\t\t", types::CodecCapabilitiesLtvFormat);
1035         } else {
1036           stream << "\t\t\t"
1037                  << base::HexEncode(record.codec_spec_caps_raw.data(),
1038                                     record.codec_spec_caps_raw.size())
1039                  << "\n";
1040         }
1041         stream << "\t\t    Metadata: " << record.metadata.ToString();
1042       }
1043       stream << "\n";
1044     }
1045   }
1046 }
1047 
DumpPacsDebugState(std::stringstream & stream)1048 void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream) {
1049   stream << "      ● Device PACS, address: " << address_.ToRedactedStringForLogging() << "\n";
1050   stream << "\t  == Sink PACs:\n";
1051   DumpPacsDebugState(stream, snk_pacs_);
1052   stream << "\t  == Source PACs:\n";
1053   DumpPacsDebugState(stream, src_pacs_);
1054 }
1055 
locationToString(uint32_t location)1056 static std::string locationToString(uint32_t location) {
1057   if (location & codec_spec_conf::kLeAudioLocationAnyLeft &&
1058       location & codec_spec_conf::kLeAudioLocationAnyRight) {
1059     return "left/right";
1060   } else if (location & codec_spec_conf::kLeAudioLocationAnyLeft) {
1061     return "left";
1062   } else if (location & codec_spec_conf::kLeAudioLocationAnyRight) {
1063     return "right";
1064   } else if (location == codec_spec_conf::kLeAudioLocationMonoAudio) {
1065     return "mono";
1066   }
1067   return "unknown location";
1068 }
1069 
Dump(std::stringstream & stream)1070 void LeAudioDevice::Dump(std::stringstream& stream) {
1071   uint16_t acl_handle =
1072           get_btm_client_interface().peer.BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE);
1073   std::string snk_location = audio_locations_.sink
1074                                      ? locationToString(audio_locations_.sink->value.to_ulong())
1075                                      : "None";
1076   std::string src_location = audio_locations_.source
1077                                      ? locationToString(audio_locations_.source->value.to_ulong())
1078                                      : "None";
1079 
1080   stream << "      ● Device address: " << address_.ToRedactedStringForLogging() << ", "
1081          << connection_state_
1082          << ", conn_id: " << (conn_id_ == GATT_INVALID_CONN_ID ? "-1" : std::to_string(conn_id_))
1083          << ", acl_handle: " << std::to_string(acl_handle) << ", snk_location: " << snk_location
1084          << ", src_location: " << src_location << ", mtu: " << std::to_string(mtu_) << ", "
1085          << (encrypted_ ? "Encrypted" : "Unecrypted")
1086          << "\n\t  Sink avail. contexts: " << common::ToString(avail_contexts_.sink)
1087          << "\n\t  Source avail. contexts: " << common::ToString(avail_contexts_.source) << "\n";
1088 
1089   if (gmap_client_ != nullptr) {
1090     stream << "\t  ";
1091     gmap_client_->DebugDump(stream);
1092   } else {
1093     stream << "\t  ";
1094     stream << "GmapClient not initialized\n";
1095   }
1096 
1097   if (ases_.size() > 0) {
1098     stream << "\t  == ASEs (" << static_cast<int>(ases_.size()) << "):\n";
1099     stream << "\t    id  active dir     cis_id  cis_handle  sdu  latency rtn  "
1100               "cis_state            data_path_state\n";
1101     for (auto& ase : ases_) {
1102       stream << std::setfill('\x20') << "\t    " << std::left << std::setw(4)
1103              << static_cast<int>(ase.id) << std::left << std::setw(7)
1104              << (ase.active ? "true" : "false") << std::left << std::setw(8)
1105              << (ase.direction == types::kLeAudioDirectionSink ? "sink" : "source") << std::left
1106              << std::setw(8) << static_cast<int>(ase.cis_id) << std::left << std::setw(12)
1107              << ase.cis_conn_hdl << std::left << std::setw(5) << ase.qos_config.max_sdu_size
1108              << std::left << std::setw(8) << ase.qos_config.max_transport_latency << std::left
1109              << std::setw(5) << static_cast<int>(ase.qos_config.retrans_nb) << std::left
1110              << std::setw(21) << bluetooth::common::ToString(ase.cis_state) << std::setw(19)
1111              << bluetooth::common::ToString(ase.data_path_state) << "\n";
1112     }
1113   }
1114 }
1115 
DisconnectAcl(void)1116 void LeAudioDevice::DisconnectAcl(void) {
1117   if (conn_id_ == GATT_INVALID_CONN_ID) {
1118     return;
1119   }
1120 
1121   uint16_t acl_handle =
1122           get_btm_client_interface().peer.BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE);
1123   if (acl_handle != HCI_INVALID_HANDLE) {
1124     acl_disconnect_from_handle(acl_handle, HCI_ERR_PEER_USER,
1125                                "bta::bluetooth::le_audio::client disconnect");
1126   }
1127 }
1128 
SetAvailableContexts(BidirectionalPair<AudioContexts> contexts)1129 void LeAudioDevice::SetAvailableContexts(BidirectionalPair<AudioContexts> contexts) {
1130   log::debug(
1131           "{}: \n\t previous_contexts_.sink: {} \n\t previous_contexts_.source: {} "
1132           " "
1133           "\n\t new_contexts.sink: {} \n\t new_contexts.source: {} \n\t",
1134           address_, avail_contexts_.sink.to_string(), avail_contexts_.source.to_string(),
1135           contexts.sink.to_string(), contexts.source.to_string());
1136 
1137   avail_contexts_.sink = contexts.sink;
1138   avail_contexts_.source = contexts.source;
1139 }
1140 
SetMetadataToAse(struct types::ase * ase,const types::LeAudioLtvMap & base_metadata,const AudioContexts & metadata_context_types,const std::vector<uint8_t> & ccid_lists)1141 void LeAudioDevice::SetMetadataToAse(struct types::ase* ase,
1142                                      const types::LeAudioLtvMap& base_metadata,
1143                                      const AudioContexts& metadata_context_types,
1144                                      const std::vector<uint8_t>& ccid_lists) {
1145   /* Filter multidirectional audio context for each ase direction */
1146   auto directional_audio_context = metadata_context_types & GetAvailableContexts(ase->direction);
1147   /* Tha base metadata will be extended (or partially overridden if any key already exist) */
1148   ase->metadata = base_metadata;
1149   if (directional_audio_context.any()) {
1150     ase->metadata.Append(GetMetadata(directional_audio_context, ccid_lists));
1151   } else {
1152     ase->metadata.Append(
1153             GetMetadata(AudioContexts(LeAudioContextType::UNSPECIFIED), std::vector<uint8_t>()));
1154   }
1155 }
1156 
ActivateConfiguredAses(LeAudioContextType context_type,const BidirectionalPair<AudioContexts> & metadata_context_types,BidirectionalPair<std::vector<uint8_t>> ccid_lists)1157 bool LeAudioDevice::ActivateConfiguredAses(
1158         LeAudioContextType context_type,
1159         const BidirectionalPair<AudioContexts>& metadata_context_types,
1160         BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
1161   if (conn_id_ == GATT_INVALID_CONN_ID) {
1162     log::warn("Device {} is not connected", address_);
1163     return false;
1164   }
1165 
1166   bool ret = false;
1167 
1168   log::info("Configuring device {}", address_);
1169   for (auto& ase : ases_) {
1170     if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED &&
1171         ase.configured_for_context_type == context_type) {
1172       log::info(
1173               "conn_id: {}, ase id {}, cis id {}, cis_handle 0x{:04x} is "
1174               "activated.",
1175               conn_id_, ase.id, ase.cis_id, ase.cis_conn_hdl);
1176       ase.active = true;
1177       ret = true;
1178       /* update the already set metadata */
1179       SetMetadataToAse(&ase, ase.metadata, metadata_context_types.get(ase.direction),
1180                        ccid_lists.get(ase.direction));
1181     }
1182   }
1183 
1184   return ret;
1185 }
1186 
DeactivateAllAses(void)1187 void LeAudioDevice::DeactivateAllAses(void) {
1188   for (auto& ase : ases_) {
1189     if (ase.active == false && ase.cis_state != CisState::IDLE &&
1190         ase.data_path_state != DataPathState::IDLE) {
1191       log::warn(
1192               "{}, ase_id: {}, ase.cis_id: {}, cis_handle: 0x{:02x}, "
1193               "ase.cis_state={}, ase.data_path_state={}",
1194               address_, ase.id, ase.cis_id, ase.cis_conn_hdl,
1195               bluetooth::common::ToString(ase.cis_state),
1196               bluetooth::common::ToString(ase.data_path_state));
1197     }
1198 
1199     log::verbose("{}, ase_id {}", address_, ase.id);
1200 
1201     ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
1202     ase.cis_state = CisState::IDLE;
1203     ase.data_path_state = DataPathState::IDLE;
1204     ase.active = false;
1205     ase.reconfigure = 0;
1206     ase.cis_id = bluetooth::le_audio::kInvalidCisId;
1207     ase.cis_conn_hdl = bluetooth::le_audio::kInvalidCisConnHandle;
1208   }
1209 }
1210 
GetMetadata(AudioContexts context_type,const std::vector<uint8_t> & ccid_list)1211 types::LeAudioLtvMap LeAudioDevice::GetMetadata(AudioContexts context_type,
1212                                                 const std::vector<uint8_t>& ccid_list) {
1213   types::LeAudioLtvMap metadata;
1214   metadata.Add(types::kLeAudioMetadataTypeStreamingAudioContext, context_type.value());
1215   if (ccid_list.size()) {
1216     metadata.Add(types::kLeAudioMetadataTypeCcidList, ccid_list);
1217   }
1218   return metadata;
1219 }
1220 
IsMetadataChanged(const BidirectionalPair<AudioContexts> & context_types,const BidirectionalPair<std::vector<uint8_t>> & ccid_lists)1221 bool LeAudioDevice::IsMetadataChanged(const BidirectionalPair<AudioContexts>& context_types,
1222                                       const BidirectionalPair<std::vector<uint8_t>>& ccid_lists) {
1223   for (auto* ase = this->GetFirstActiveAse(); ase; ase = this->GetNextActiveAse(ase)) {
1224     if (this->GetMetadata(context_types.get(ase->direction), ccid_lists.get(ase->direction)) !=
1225         ase->metadata) {
1226       return true;
1227     }
1228   }
1229 
1230   return false;
1231 }
1232 
GetDeviceModelName(void)1233 void LeAudioDevice::GetDeviceModelName(void) {
1234   bt_property_t prop_name;
1235   bt_bdname_t prop_value = {0};
1236   // Retrieve model name from storage
1237   BTIF_STORAGE_FILL_PROPERTY(&prop_name, BT_PROPERTY_REMOTE_MODEL_NUM, sizeof(bt_bdname_t),
1238                              &prop_value);
1239   if (btif_storage_get_remote_device_property(&address_, &prop_name) == BT_STATUS_SUCCESS) {
1240     model_name_.assign((char*)prop_value.name);
1241   }
1242 }
1243 
UpdateDeviceAllowlistFlag(void)1244 void LeAudioDevice::UpdateDeviceAllowlistFlag(void) {
1245   char allow_list[PROPERTY_VALUE_MAX] = {0};
1246   GetDeviceModelName();
1247   osi_property_get(kLeAudioDeviceAllowListProp, allow_list, "");
1248   if (allow_list[0] == '\0' || model_name_ == "") {
1249     // if device allow list is empty or no remote model name available
1250     // return allowlist_flag_ as default false
1251     return;
1252   }
1253 
1254   std::istringstream stream(allow_list);
1255   std::string token;
1256   while (std::getline(stream, token, ',')) {
1257     if (token.compare(model_name_) == 0) {
1258       allowlist_flag_ = true;
1259       return;
1260     }
1261   }
1262 }
1263 
GetDsaModes(void)1264 DsaModes LeAudioDevice::GetDsaModes(void) { return dsa_.modes; }
1265 
DsaReducedSduSizeSupported()1266 bool LeAudioDevice::DsaReducedSduSizeSupported() { return dsa_.reduced_sdu; }
1267 
GetDsaDataPathState(void)1268 types::DataPathState LeAudioDevice::GetDsaDataPathState(void) { return dsa_.state; }
1269 
SetDsaDataPathState(types::DataPathState state)1270 void LeAudioDevice::SetDsaDataPathState(types::DataPathState state) { dsa_.state = state; }
1271 
GetDsaCisHandle(void)1272 uint16_t LeAudioDevice::GetDsaCisHandle(void) { return dsa_.cis_handle; }
1273 
SetDsaCisHandle(uint16_t cis_handle)1274 void LeAudioDevice::SetDsaCisHandle(uint16_t cis_handle) { dsa_.cis_handle = cis_handle; }
1275 
1276 /* LeAudioDevices Class methods implementation */
Add(const RawAddress & address,DeviceConnectState state,int group_id)1277 void LeAudioDevices::Add(const RawAddress& address, DeviceConnectState state, int group_id) {
1278   auto device = FindByAddress(address);
1279   if (device != nullptr) {
1280     log::error("address: {} is already assigned to group: {}", address, device->group_id_);
1281     return;
1282   }
1283 
1284   leAudioDevices_.emplace_back(std::make_shared<LeAudioDevice>(address, state, group_id));
1285 }
1286 
Remove(const RawAddress & address)1287 void LeAudioDevices::Remove(const RawAddress& address) {
1288   auto iter = std::find_if(
1289           leAudioDevices_.begin(), leAudioDevices_.end(),
1290           [&address](auto const& leAudioDevice) { return leAudioDevice->address_ == address; });
1291 
1292   if (iter == leAudioDevices_.end()) {
1293     log::error("no such address: {}", address);
1294     return;
1295   }
1296 
1297   leAudioDevices_.erase(iter);
1298 }
1299 
FindByAddress(const RawAddress & address) const1300 LeAudioDevice* LeAudioDevices::FindByAddress(const RawAddress& address) const {
1301   auto iter = std::find_if(
1302           leAudioDevices_.begin(), leAudioDevices_.end(),
1303           [&address](auto const& leAudioDevice) { return leAudioDevice->address_ == address; });
1304 
1305   return (iter == leAudioDevices_.end()) ? nullptr : iter->get();
1306 }
1307 
GetByAddress(const RawAddress & address) const1308 std::shared_ptr<LeAudioDevice> LeAudioDevices::GetByAddress(const RawAddress& address) const {
1309   auto iter = std::find_if(
1310           leAudioDevices_.begin(), leAudioDevices_.end(),
1311           [&address](auto const& leAudioDevice) { return leAudioDevice->address_ == address; });
1312 
1313   return (iter == leAudioDevices_.end()) ? nullptr : *iter;
1314 }
1315 
FindByConnId(tCONN_ID conn_id) const1316 LeAudioDevice* LeAudioDevices::FindByConnId(tCONN_ID conn_id) const {
1317   auto iter = std::find_if(
1318           leAudioDevices_.begin(), leAudioDevices_.end(),
1319           [&conn_id](auto const& leAudioDevice) { return leAudioDevice->conn_id_ == conn_id; });
1320 
1321   return (iter == leAudioDevices_.end()) ? nullptr : iter->get();
1322 }
1323 
FindByCisConnHdl(uint8_t cig_id,uint16_t conn_hdl) const1324 LeAudioDevice* LeAudioDevices::FindByCisConnHdl(uint8_t cig_id, uint16_t conn_hdl) const {
1325   auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
1326                            [&conn_hdl, &cig_id](auto& d) {
1327                              LeAudioDevice* dev;
1328                              BidirectionalPair<struct ase*> ases;
1329 
1330                              dev = d.get();
1331                              if (dev->group_id_ != cig_id) {
1332                                return false;
1333                              }
1334 
1335                              ases = dev->GetAsesByCisConnHdl(conn_hdl);
1336                              if (ases.sink || ases.source) {
1337                                return true;
1338                              } else {
1339                                return false;
1340                              }
1341                            });
1342 
1343   if (iter == leAudioDevices_.end()) {
1344     return nullptr;
1345   }
1346 
1347   return iter->get();
1348 }
1349 
SetInitialGroupAutoconnectState(int group_id,int gatt_if,tBTM_BLE_CONN_TYPE,bool current_dev_autoconnect_flag)1350 void LeAudioDevices::SetInitialGroupAutoconnectState(int group_id, int gatt_if,
1351                                                      tBTM_BLE_CONN_TYPE /*reconnection_mode*/,
1352                                                      bool current_dev_autoconnect_flag) {
1353   if (!current_dev_autoconnect_flag) {
1354     /* If current device autoconnect flag is false, check if there is other
1355      * device in the group which is in autoconnect mode.
1356      * If yes, assume whole group is in autoconnect.
1357      */
1358     auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [&group_id](auto& d) {
1359       LeAudioDevice* dev;
1360       dev = d.get();
1361       if (dev->group_id_ != group_id) {
1362         return false;
1363       }
1364       return dev->autoconnect_flag_;
1365     });
1366 
1367     current_dev_autoconnect_flag = !(iter == leAudioDevices_.end());
1368   }
1369 
1370   if (!current_dev_autoconnect_flag) {
1371     return;
1372   }
1373 
1374   /* This function is called when bluetooth started, therefore here we will
1375    * try direct connection, if that failes, we fallback to background connection
1376    */
1377   for (auto dev : leAudioDevices_) {
1378     if ((dev->group_id_ == group_id) &&
1379         (dev->GetConnectionState() == DeviceConnectState::DISCONNECTED)) {
1380       dev->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
1381       dev->autoconnect_flag_ = true;
1382       btif_storage_set_leaudio_autoconnect(dev->address_, true);
1383       BTA_GATTC_Open(gatt_if, dev->address_, BTM_BLE_DIRECT_CONNECTION, false);
1384     }
1385   }
1386 }
1387 
Size() const1388 size_t LeAudioDevices::Size() const { return leAudioDevices_.size(); }
1389 
Dump(std::stringstream & stream,int group_id) const1390 void LeAudioDevices::Dump(std::stringstream& stream, int group_id) const {
1391   for (auto const& device : leAudioDevices_) {
1392     if (device->group_id_ == group_id) {
1393       device->Dump(stream);
1394 
1395       stream << "\tAddress: " << device->address_ << "\n";
1396       device->DumpPacsDebugState(stream);
1397       stream << "\n";
1398     }
1399   }
1400 }
1401 
Cleanup(tGATT_IF client_if)1402 void LeAudioDevices::Cleanup(tGATT_IF client_if) {
1403   for (auto const& device : leAudioDevices_) {
1404     auto connection_state = device->GetConnectionState();
1405     if (connection_state == DeviceConnectState::DISCONNECTED ||
1406         connection_state == DeviceConnectState::DISCONNECTING) {
1407       continue;
1408     }
1409 
1410     // For connecting or connected device always remove background connect
1411     BTA_GATTC_CancelOpen(client_if, device->address_, false);
1412 
1413     if (connection_state == DeviceConnectState::CONNECTING_BY_USER) {
1414       // When connecting by user, remove direct connect
1415       BTA_GATTC_CancelOpen(client_if, device->address_, true);
1416     } else if (connection_state != DeviceConnectState::CONNECTING_AUTOCONNECT) {
1417       // If connected, close the connection
1418       BtaGattQueue::Clean(device->conn_id_);
1419       BTA_GATTC_Close(device->conn_id_);
1420       device->DisconnectAcl();
1421     }
1422   }
1423   leAudioDevices_.clear();
1424 }
1425 
1426 }  // namespace bluetooth::le_audio
1427