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