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