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
22 #include <map>
23
24 #include "audio_hal_client/audio_hal_client.h"
25 #include "bta_csis_api.h"
26 #include "bta_gatt_queue.h"
27 #include "bta_groups.h"
28 #include "bta_le_audio_api.h"
29 #include "btif_storage.h"
30 #include "btm_iso_api.h"
31 #include "btm_iso_api_types.h"
32 #include "device/include/controller.h"
33 #include "gd/common/strings.h"
34 #include "le_audio_log_history.h"
35 #include "le_audio_set_configuration_provider.h"
36 #include "metrics_collector.h"
37 #include "osi/include/log.h"
38 #include "stack/include/acl_api.h"
39
40 using bluetooth::hci::kIsoCigFramingFramed;
41 using bluetooth::hci::kIsoCigFramingUnframed;
42 using bluetooth::hci::kIsoCigPackingSequential;
43 using bluetooth::hci::kIsoCigPhy1M;
44 using bluetooth::hci::kIsoCigPhy2M;
45 using bluetooth::hci::iso_manager::kIsoSca0To20Ppm;
46 using le_audio::AudioSetConfigurationProvider;
47 using le_audio::DeviceConnectState;
48 using le_audio::set_configurations::CodecCapabilitySetting;
49 using le_audio::types::ase;
50 using le_audio::types::AseState;
51 using le_audio::types::AudioContexts;
52 using le_audio::types::AudioLocations;
53 using le_audio::types::AudioStreamDataPathState;
54 using le_audio::types::BidirectAsesPair;
55 using le_audio::types::BidirectionalPair;
56 using le_audio::types::CisType;
57 using le_audio::types::LeAudioCodecId;
58 using le_audio::types::LeAudioContextType;
59 using le_audio::types::LeAudioLc3Config;
60
61 namespace le_audio {
operator <<(std::ostream & os,const DeviceConnectState & state)62 std::ostream& operator<<(std::ostream& os, const DeviceConnectState& state) {
63 const char* char_value_ = "UNKNOWN";
64
65 switch (state) {
66 case DeviceConnectState::CONNECTED:
67 char_value_ = "CONNECTED";
68 break;
69 case DeviceConnectState::DISCONNECTED:
70 char_value_ = "DISCONNECTED";
71 break;
72 case DeviceConnectState::REMOVING:
73 char_value_ = "REMOVING";
74 break;
75 case DeviceConnectState::DISCONNECTING:
76 char_value_ = "DISCONNECTING";
77 break;
78 case DeviceConnectState::DISCONNECTING_AND_RECOVER:
79 char_value_ = "DISCONNECTING_AND_RECOVER";
80 break;
81 case DeviceConnectState::PENDING_REMOVAL:
82 char_value_ = "PENDING_REMOVAL";
83 break;
84 case DeviceConnectState::CONNECTING_BY_USER:
85 char_value_ = "CONNECTING_BY_USER";
86 break;
87 case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
88 char_value_ = "CONNECTED_BY_USER_GETTING_READY";
89 break;
90 case DeviceConnectState::CONNECTING_AUTOCONNECT:
91 char_value_ = "CONNECTING_AUTOCONNECT";
92 break;
93 case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
94 char_value_ = "CONNECTED_AUTOCONNECT_GETTING_READY";
95 break;
96 }
97
98 os << char_value_ << " ("
99 << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
100 << ")";
101 return os;
102 }
103
104 /* LeAudioDeviceGroup Class methods implementation */
AddNode(const std::shared_ptr<LeAudioDevice> & leAudioDevice)105 void LeAudioDeviceGroup::AddNode(
106 const std::shared_ptr<LeAudioDevice>& leAudioDevice) {
107 leAudioDevice->group_id_ = group_id_;
108 leAudioDevices_.push_back(std::weak_ptr<LeAudioDevice>(leAudioDevice));
109 MetricsCollector::Get()->OnGroupSizeUpdate(group_id_, leAudioDevices_.size());
110 }
111
RemoveNode(const std::shared_ptr<LeAudioDevice> & leAudioDevice)112 void LeAudioDeviceGroup::RemoveNode(
113 const std::shared_ptr<LeAudioDevice>& leAudioDevice) {
114 /* Group information cleaning in the device. */
115 leAudioDevice->group_id_ = bluetooth::groups::kGroupUnknown;
116 for (auto ase : leAudioDevice->ases_) {
117 ase.active = false;
118 ase.cis_conn_hdl = 0;
119 }
120
121 leAudioDevices_.erase(
122 std::remove_if(
123 leAudioDevices_.begin(), leAudioDevices_.end(),
124 [&leAudioDevice](auto& d) { return d.lock() == leAudioDevice; }),
125 leAudioDevices_.end());
126 MetricsCollector::Get()->OnGroupSizeUpdate(group_id_, leAudioDevices_.size());
127 }
128
IsEmpty(void)129 bool LeAudioDeviceGroup::IsEmpty(void) { return leAudioDevices_.size() == 0; }
130
IsAnyDeviceConnected(void)131 bool LeAudioDeviceGroup::IsAnyDeviceConnected(void) {
132 return (NumOfConnected() != 0);
133 }
134
Size(void)135 int LeAudioDeviceGroup::Size(void) { return leAudioDevices_.size(); }
136
NumOfConnected(types::LeAudioContextType context_type)137 int LeAudioDeviceGroup::NumOfConnected(types::LeAudioContextType context_type) {
138 if (leAudioDevices_.empty()) return 0;
139
140 bool check_context_type = (context_type != LeAudioContextType::RFU);
141 AudioContexts type_set(context_type);
142
143 /* return number of connected devices from the set*/
144 return std::count_if(
145 leAudioDevices_.begin(), leAudioDevices_.end(),
146 [type_set, check_context_type](auto& iter) {
147 if (iter.expired()) return false;
148 if (iter.lock()->conn_id_ == GATT_INVALID_CONN_ID) return false;
149 if (iter.lock()->GetConnectionState() != DeviceConnectState::CONNECTED)
150 return false;
151
152 if (!check_context_type) return true;
153
154 return iter.lock()->GetAvailableContexts().test_any(type_set);
155 });
156 }
157
ClearSinksFromConfiguration(void)158 void LeAudioDeviceGroup::ClearSinksFromConfiguration(void) {
159 LOG_INFO("Group %p, group_id %d", this, group_id_);
160 stream_conf.sink_streams.clear();
161 stream_conf.sink_offloader_streams_target_allocation.clear();
162 stream_conf.sink_offloader_streams_current_allocation.clear();
163 stream_conf.sink_audio_channel_allocation = 0;
164 stream_conf.sink_num_of_channels = 0;
165 stream_conf.sink_num_of_devices = 0;
166 stream_conf.sink_sample_frequency_hz = 0;
167 stream_conf.sink_codec_frames_blocks_per_sdu = 0;
168 stream_conf.sink_octets_per_codec_frame = 0;
169 stream_conf.sink_frame_duration_us = 0;
170 }
171
ClearSourcesFromConfiguration(void)172 void LeAudioDeviceGroup::ClearSourcesFromConfiguration(void) {
173 LOG_INFO("Group %p, group_id %d", this, group_id_);
174 stream_conf.source_streams.clear();
175 stream_conf.source_offloader_streams_target_allocation.clear();
176 stream_conf.source_offloader_streams_current_allocation.clear();
177 stream_conf.source_audio_channel_allocation = 0;
178 stream_conf.source_num_of_channels = 0;
179 stream_conf.source_num_of_devices = 0;
180 stream_conf.source_sample_frequency_hz = 0;
181 stream_conf.source_codec_frames_blocks_per_sdu = 0;
182 stream_conf.source_octets_per_codec_frame = 0;
183 stream_conf.source_frame_duration_us = 0;
184 }
185
CigClearCis(void)186 void LeAudioDeviceGroup::CigClearCis(void) {
187 LOG_INFO("group_id: %d", group_id_);
188 cises_.clear();
189 ClearSinksFromConfiguration();
190 ClearSourcesFromConfiguration();
191 }
192
Cleanup(void)193 void LeAudioDeviceGroup::Cleanup(void) {
194 /* Bluetooth is off while streaming - disconnect CISes and remove CIG */
195 if (GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
196 if (!stream_conf.sink_streams.empty()) {
197 for (auto [cis_handle, audio_location] : stream_conf.sink_streams) {
198 bluetooth::hci::IsoManager::GetInstance()->DisconnectCis(
199 cis_handle, HCI_ERR_PEER_USER);
200
201 if (stream_conf.source_streams.empty()) {
202 continue;
203 }
204 uint16_t cis_hdl = cis_handle;
205 stream_conf.source_streams.erase(
206 std::remove_if(
207 stream_conf.source_streams.begin(),
208 stream_conf.source_streams.end(),
209 [cis_hdl](auto& pair) { return pair.first == cis_hdl; }),
210 stream_conf.source_streams.end());
211 }
212 }
213
214 if (!stream_conf.source_streams.empty()) {
215 for (auto [cis_handle, audio_location] : stream_conf.source_streams) {
216 bluetooth::hci::IsoManager::GetInstance()->DisconnectCis(
217 cis_handle, HCI_ERR_PEER_USER);
218 }
219 }
220 }
221
222 /* Note: CIG will stay in the controller. We cannot remove it here, because
223 * Cises are not yet disconnected.
224 * When user start Bluetooth, HCI Reset should remove it
225 */
226
227 leAudioDevices_.clear();
228 this->CigClearCis();
229 }
230
Deactivate(void)231 void LeAudioDeviceGroup::Deactivate(void) {
232 for (auto* leAudioDevice = GetFirstActiveDevice(); leAudioDevice;
233 leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
234 for (auto* ase = leAudioDevice->GetFirstActiveAse(); ase;
235 ase = leAudioDevice->GetNextActiveAse(ase)) {
236 ase->active = false;
237 }
238 }
239 }
240
GetCigState(void)241 le_audio::types::CigState LeAudioDeviceGroup::GetCigState(void) {
242 return cig_state_;
243 }
244
SetCigState(le_audio::types::CigState state)245 void LeAudioDeviceGroup::SetCigState(le_audio::types::CigState state) {
246 LOG_VERBOSE("%s -> %s", bluetooth::common::ToString(cig_state_).c_str(),
247 bluetooth::common::ToString(state).c_str());
248 cig_state_ = state;
249 }
250
Activate(LeAudioContextType context_type)251 bool LeAudioDeviceGroup::Activate(LeAudioContextType context_type) {
252 bool is_activate = false;
253 for (auto leAudioDevice : leAudioDevices_) {
254 if (leAudioDevice.expired()) continue;
255
256 bool activated = leAudioDevice.lock()->ActivateConfiguredAses(context_type);
257 LOG_INFO("Device %s is %s",
258 ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice.lock().get()->address_),
259 activated ? "activated" : " not activated");
260 if (activated) {
261 if (!CigAssignCisIds(leAudioDevice.lock().get())) {
262 return false;
263 }
264 is_activate = true;
265 }
266 }
267 return is_activate;
268 }
269
GetFirstDevice(void)270 LeAudioDevice* LeAudioDeviceGroup::GetFirstDevice(void) {
271 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
272 [](auto& iter) { return !iter.expired(); });
273
274 if (iter == leAudioDevices_.end()) return nullptr;
275
276 return (iter->lock()).get();
277 }
278
GetFirstDeviceWithActiveContext(types::LeAudioContextType context_type)279 LeAudioDevice* LeAudioDeviceGroup::GetFirstDeviceWithActiveContext(
280 types::LeAudioContextType context_type) {
281 auto iter = std::find_if(
282 leAudioDevices_.begin(), leAudioDevices_.end(),
283 [&context_type](auto& iter) {
284 if (iter.expired()) return false;
285 return iter.lock()->GetAvailableContexts().test(context_type);
286 });
287
288 if ((iter == leAudioDevices_.end()) || (iter->expired())) return nullptr;
289
290 return (iter->lock()).get();
291 }
292
GetNextDevice(LeAudioDevice * leAudioDevice)293 LeAudioDevice* LeAudioDeviceGroup::GetNextDevice(LeAudioDevice* leAudioDevice) {
294 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
295 [&leAudioDevice](auto& d) {
296 if (d.expired())
297 return false;
298 else
299 return (d.lock()).get() == leAudioDevice;
300 });
301
302 /* If reference device not found */
303 if (iter == leAudioDevices_.end()) return nullptr;
304
305 std::advance(iter, 1);
306 /* If reference device is last in group */
307 if (iter == leAudioDevices_.end()) return nullptr;
308
309 if (iter->expired()) return nullptr;
310
311 return (iter->lock()).get();
312 }
313
GetNextDeviceWithActiveContext(LeAudioDevice * leAudioDevice,types::LeAudioContextType context_type)314 LeAudioDevice* LeAudioDeviceGroup::GetNextDeviceWithActiveContext(
315 LeAudioDevice* leAudioDevice, types::LeAudioContextType context_type) {
316 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
317 [&leAudioDevice](auto& d) {
318 if (d.expired())
319 return false;
320 else
321 return (d.lock()).get() == leAudioDevice;
322 });
323
324 /* If reference device not found */
325 if (iter == leAudioDevices_.end()) return nullptr;
326
327 std::advance(iter, 1);
328 /* If reference device is last in group */
329 if (iter == leAudioDevices_.end()) return nullptr;
330
331 iter = std::find_if(iter, leAudioDevices_.end(), [&context_type](auto& d) {
332 if (d.expired())
333 return false;
334 else
335 return d.lock()->GetAvailableContexts().test(context_type);
336 ;
337 });
338
339 return (iter == leAudioDevices_.end()) ? nullptr : (iter->lock()).get();
340 }
341
IsDeviceInTheGroup(LeAudioDevice * leAudioDevice)342 bool LeAudioDeviceGroup::IsDeviceInTheGroup(LeAudioDevice* leAudioDevice) {
343 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
344 [&leAudioDevice](auto& d) {
345 if (d.expired())
346 return false;
347 else
348 return (d.lock()).get() == leAudioDevice;
349 });
350
351 if ((iter == leAudioDevices_.end()) || (iter->expired())) return false;
352
353 return true;
354 }
355
IsGroupReadyToCreateStream(void)356 bool LeAudioDeviceGroup::IsGroupReadyToCreateStream(void) {
357 auto iter =
358 std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
359 if (d.expired())
360 return false;
361 else
362 return !(((d.lock()).get())->IsReadyToCreateStream());
363 });
364
365 return iter == leAudioDevices_.end();
366 }
367
IsGroupReadyToSuspendStream(void)368 bool LeAudioDeviceGroup::IsGroupReadyToSuspendStream(void) {
369 auto iter =
370 std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
371 if (d.expired())
372 return false;
373 else
374 return !(((d.lock()).get())->IsReadyToSuspendStream());
375 });
376
377 return iter == leAudioDevices_.end();
378 }
379
HaveAnyActiveDeviceInUnconfiguredState()380 bool LeAudioDeviceGroup::HaveAnyActiveDeviceInUnconfiguredState() {
381 auto iter =
382 std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
383 if (d.expired())
384 return false;
385 else
386 return (((d.lock()).get())->HaveAnyUnconfiguredAses());
387 });
388
389 return iter != leAudioDevices_.end();
390 }
391
HaveAllActiveDevicesAsesTheSameState(AseState state)392 bool LeAudioDeviceGroup::HaveAllActiveDevicesAsesTheSameState(AseState state) {
393 auto iter = std::find_if(
394 leAudioDevices_.begin(), leAudioDevices_.end(), [&state](auto& d) {
395 if (d.expired())
396 return false;
397 else
398 return !(((d.lock()).get())->HaveAllActiveAsesSameState(state));
399 });
400
401 return iter == leAudioDevices_.end();
402 }
403
GetFirstActiveDevice(void)404 LeAudioDevice* LeAudioDeviceGroup::GetFirstActiveDevice(void) {
405 auto iter =
406 std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
407 if (d.expired())
408 return false;
409 else
410 return ((d.lock()).get())->HaveActiveAse();
411 });
412
413 if (iter == leAudioDevices_.end() || iter->expired()) return nullptr;
414
415 return (iter->lock()).get();
416 }
417
GetNextActiveDevice(LeAudioDevice * leAudioDevice)418 LeAudioDevice* LeAudioDeviceGroup::GetNextActiveDevice(
419 LeAudioDevice* leAudioDevice) {
420 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
421 [&leAudioDevice](auto& d) {
422 if (d.expired())
423 return false;
424 else
425 return (d.lock()).get() == leAudioDevice;
426 });
427
428 if (iter == leAudioDevices_.end() ||
429 std::distance(iter, leAudioDevices_.end()) < 1)
430 return nullptr;
431
432 iter = std::find_if(std::next(iter, 1), leAudioDevices_.end(), [](auto& d) {
433 if (d.expired())
434 return false;
435 else
436 return ((d.lock()).get())->HaveActiveAse();
437 });
438
439 return (iter == leAudioDevices_.end()) ? nullptr : (iter->lock()).get();
440 }
441
GetFirstActiveDeviceByDataPathState(AudioStreamDataPathState data_path_state)442 LeAudioDevice* LeAudioDeviceGroup::GetFirstActiveDeviceByDataPathState(
443 AudioStreamDataPathState data_path_state) {
444 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
445 [&data_path_state](auto& d) {
446 if (d.expired()) {
447 return false;
448 }
449
450 return (((d.lock()).get())
451 ->GetFirstActiveAseByDataPathState(
452 data_path_state) != nullptr);
453 });
454
455 if (iter == leAudioDevices_.end()) {
456 return nullptr;
457 }
458
459 return iter->lock().get();
460 }
461
GetNextActiveDeviceByDataPathState(LeAudioDevice * leAudioDevice,AudioStreamDataPathState data_path_state)462 LeAudioDevice* LeAudioDeviceGroup::GetNextActiveDeviceByDataPathState(
463 LeAudioDevice* leAudioDevice, AudioStreamDataPathState data_path_state) {
464 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
465 [&leAudioDevice](auto& d) {
466 if (d.expired()) {
467 return false;
468 }
469
470 return d.lock().get() == leAudioDevice;
471 });
472
473 if (std::distance(iter, leAudioDevices_.end()) < 1) {
474 return nullptr;
475 }
476
477 iter = std::find_if(
478 std::next(iter, 1), leAudioDevices_.end(), [&data_path_state](auto& d) {
479 if (d.expired()) {
480 return false;
481 }
482
483 return (((d.lock()).get())
484 ->GetFirstActiveAseByDataPathState(data_path_state) !=
485 nullptr);
486 });
487
488 if (iter == leAudioDevices_.end()) {
489 return nullptr;
490 }
491
492 return iter->lock().get();
493 }
494
GetSduInterval(uint8_t direction)495 uint32_t LeAudioDeviceGroup::GetSduInterval(uint8_t direction) {
496 for (LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
497 leAudioDevice != nullptr;
498 leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
499 struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
500 if (!ase) continue;
501
502 return ase->codec_config.GetFrameDurationUs();
503 }
504
505 return 0;
506 }
507
GetSCA(void)508 uint8_t LeAudioDeviceGroup::GetSCA(void) {
509 uint8_t sca = kIsoSca0To20Ppm;
510
511 for (const auto& leAudioDevice : leAudioDevices_) {
512 uint8_t dev_sca =
513 BTM_GetPeerSCA(leAudioDevice.lock()->address_, BT_TRANSPORT_LE);
514
515 /* If we could not read SCA from the peer device or sca is 0,
516 * then there is no reason to continue.
517 */
518 if ((dev_sca == 0xFF) || (dev_sca == 0)) return 0;
519
520 /* The Slaves_Clock_Accuracy parameter shall be the worst-case sleep clock
521 *accuracy of all the slaves that will participate in the CIG.
522 */
523 if (dev_sca < sca) {
524 sca = dev_sca;
525 }
526 }
527
528 return sca;
529 }
530
GetPacking(void)531 uint8_t LeAudioDeviceGroup::GetPacking(void) {
532 /* TODO: Decide about packing */
533 return kIsoCigPackingSequential;
534 }
535
GetFraming(void)536 uint8_t LeAudioDeviceGroup::GetFraming(void) {
537 LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
538 LOG_ASSERT(leAudioDevice)
539 << __func__ << " Shouldn't be called without an active device.";
540
541 do {
542 struct ase* ase = leAudioDevice->GetFirstActiveAse();
543 if (!ase) continue;
544
545 do {
546 if (ase->framing == types::kFramingUnframedPduUnsupported)
547 return kIsoCigFramingFramed;
548 } while ((ase = leAudioDevice->GetNextActiveAse(ase)));
549 } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
550
551 return kIsoCigFramingUnframed;
552 }
553
554 /* TODO: Preferred parameter may be other than minimum */
find_max_transport_latency(LeAudioDeviceGroup * group,uint8_t direction)555 static uint16_t find_max_transport_latency(LeAudioDeviceGroup* group,
556 uint8_t direction) {
557 uint16_t max_transport_latency = 0;
558
559 for (LeAudioDevice* leAudioDevice = group->GetFirstActiveDevice();
560 leAudioDevice != nullptr;
561 leAudioDevice = group->GetNextActiveDevice(leAudioDevice)) {
562 for (ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
563 ase != nullptr;
564 ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)) {
565 if (!ase) break;
566
567 if (!max_transport_latency)
568 // first assignment
569 max_transport_latency = ase->max_transport_latency;
570 else if (ase->max_transport_latency < max_transport_latency)
571 max_transport_latency = ase->max_transport_latency;
572 }
573 }
574
575 if (max_transport_latency < types::kMaxTransportLatencyMin)
576 max_transport_latency = types::kMaxTransportLatencyMin;
577 else if (max_transport_latency > types::kMaxTransportLatencyMax)
578 max_transport_latency = types::kMaxTransportLatencyMax;
579
580 return max_transport_latency;
581 }
582
GetMaxTransportLatencyStom(void)583 uint16_t LeAudioDeviceGroup::GetMaxTransportLatencyStom(void) {
584 return find_max_transport_latency(this, types::kLeAudioDirectionSource);
585 }
586
GetMaxTransportLatencyMtos(void)587 uint16_t LeAudioDeviceGroup::GetMaxTransportLatencyMtos(void) {
588 return find_max_transport_latency(this, types::kLeAudioDirectionSink);
589 }
590
GetTransportLatencyUs(uint8_t direction)591 uint32_t LeAudioDeviceGroup::GetTransportLatencyUs(uint8_t direction) {
592 if (direction == types::kLeAudioDirectionSink) {
593 return transport_latency_mtos_us_;
594 } else if (direction == types::kLeAudioDirectionSource) {
595 return transport_latency_stom_us_ ;
596 } else {
597 LOG(ERROR) << __func__ << ", invalid direction";
598 return 0;
599 }
600 }
601
SetTransportLatency(uint8_t direction,uint32_t new_transport_latency_us)602 void LeAudioDeviceGroup::SetTransportLatency(uint8_t direction,
603 uint32_t new_transport_latency_us) {
604 uint32_t* transport_latency_us;
605
606 if (direction == types::kLeAudioDirectionSink) {
607 transport_latency_us = &transport_latency_mtos_us_;
608 } else if (direction == types::kLeAudioDirectionSource) {
609 transport_latency_us = &transport_latency_stom_us_;
610 } else {
611 LOG(ERROR) << __func__ << ", invalid direction";
612 return;
613 }
614
615 if (*transport_latency_us == new_transport_latency_us) return;
616
617 if ((*transport_latency_us != 0) &&
618 (*transport_latency_us != new_transport_latency_us)) {
619 LOG(WARNING) << __func__ << ", Different transport latency for group: "
620 << " old: " << static_cast<int>(*transport_latency_us)
621 << " [us], new: " << static_cast<int>(new_transport_latency_us)
622 << " [us]";
623 return;
624 }
625
626 LOG(INFO) << __func__ << ", updated group " << static_cast<int>(group_id_)
627 << " transport latency: " << static_cast<int>(new_transport_latency_us)
628 << " [us]";
629 *transport_latency_us = new_transport_latency_us;
630 }
631
GetRtn(uint8_t direction,uint8_t cis_id)632 uint8_t LeAudioDeviceGroup::GetRtn(uint8_t direction, uint8_t cis_id) {
633 LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
634 LOG_ASSERT(leAudioDevice)
635 << __func__ << " Shouldn't be called without an active device.";
636
637 do {
638 auto ases_pair = leAudioDevice->GetAsesByCisId(cis_id);
639
640 if (ases_pair.sink && direction == types::kLeAudioDirectionSink) {
641 return ases_pair.sink->retrans_nb;
642 } else if (ases_pair.source &&
643 direction == types::kLeAudioDirectionSource) {
644 return ases_pair.source->retrans_nb;
645 }
646 } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
647
648 return 0;
649 }
650
GetMaxSduSize(uint8_t direction,uint8_t cis_id)651 uint16_t LeAudioDeviceGroup::GetMaxSduSize(uint8_t direction, uint8_t cis_id) {
652 LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
653 LOG_ASSERT(leAudioDevice)
654 << __func__ << " Shouldn't be called without an active device.";
655
656 do {
657 auto ases_pair = leAudioDevice->GetAsesByCisId(cis_id);
658
659 if (ases_pair.sink && direction == types::kLeAudioDirectionSink) {
660 return ases_pair.sink->max_sdu_size;
661 } else if (ases_pair.source &&
662 direction == types::kLeAudioDirectionSource) {
663 return ases_pair.source->max_sdu_size;
664 }
665 } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
666
667 return 0;
668 }
669
GetPhyBitmask(uint8_t direction)670 uint8_t LeAudioDeviceGroup::GetPhyBitmask(uint8_t direction) {
671 LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
672 LOG_ASSERT(leAudioDevice)
673 << __func__ << " Shouldn't be called without an active device.";
674
675 // local supported PHY's
676 uint8_t phy_bitfield = kIsoCigPhy1M;
677 if (controller_get_interface()->supports_ble_2m_phy())
678 phy_bitfield |= kIsoCigPhy2M;
679
680 if (!leAudioDevice) {
681 LOG(ERROR) << "No active leaudio device for direction?: " << +direction;
682 return phy_bitfield;
683 }
684
685 do {
686 struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
687 if (!ase) return phy_bitfield;
688
689 do {
690 if (direction == ase->direction) {
691 phy_bitfield &= leAudioDevice->GetPhyBitmask();
692
693 // A value of 0x00 denotes no preference
694 if (ase->preferred_phy && (phy_bitfield & ase->preferred_phy)) {
695 phy_bitfield &= ase->preferred_phy;
696 LOG_DEBUG("Using ASE preferred phy 0x%02x",
697 static_cast<int>(phy_bitfield));
698 } else {
699 LOG_WARN(
700 "ASE preferred 0x%02x has nothing common with phy_bitfield "
701 "0x%02x ",
702 static_cast<int>(ase->preferred_phy),
703 static_cast<int>(phy_bitfield));
704 }
705 }
706 } while ((ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)));
707 } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
708
709 return phy_bitfield;
710 }
711
GetTargetPhy(uint8_t direction)712 uint8_t LeAudioDeviceGroup::GetTargetPhy(uint8_t direction) {
713 uint8_t phy_bitfield = GetPhyBitmask(direction);
714
715 // prefer to use 2M if supported
716 if (phy_bitfield & kIsoCigPhy2M)
717 return types::kTargetPhy2M;
718 else if (phy_bitfield & kIsoCigPhy1M)
719 return types::kTargetPhy1M;
720 else
721 return 0;
722 }
723
GetPresentationDelay(uint32_t * delay,uint8_t direction)724 bool LeAudioDeviceGroup::GetPresentationDelay(uint32_t* delay,
725 uint8_t direction) {
726 uint32_t delay_min = 0;
727 uint32_t delay_max = UINT32_MAX;
728 uint32_t preferred_delay_min = delay_min;
729 uint32_t preferred_delay_max = delay_max;
730
731 LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
732 LOG_ASSERT(leAudioDevice)
733 << __func__ << " Shouldn't be called without an active device.";
734
735 do {
736 struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
737 if (!ase) continue; // device has no active ASEs in this direction
738
739 do {
740 /* No common range check */
741 if (ase->pres_delay_min > delay_max || ase->pres_delay_max < delay_min)
742 return false;
743
744 if (ase->pres_delay_min > delay_min) delay_min = ase->pres_delay_min;
745 if (ase->pres_delay_max < delay_max) delay_max = ase->pres_delay_max;
746 if (ase->preferred_pres_delay_min > preferred_delay_min)
747 preferred_delay_min = ase->preferred_pres_delay_min;
748 if (ase->preferred_pres_delay_max < preferred_delay_max &&
749 ase->preferred_pres_delay_max != types::kPresDelayNoPreference)
750 preferred_delay_max = ase->preferred_pres_delay_max;
751 } while ((ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)));
752 } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
753
754 if (preferred_delay_min <= preferred_delay_max &&
755 preferred_delay_min > delay_min && preferred_delay_min < delay_max) {
756 *delay = preferred_delay_min;
757 } else {
758 *delay = delay_min;
759 }
760
761 return true;
762 }
763
GetRemoteDelay(uint8_t direction)764 uint16_t LeAudioDeviceGroup::GetRemoteDelay(uint8_t direction) {
765 uint16_t remote_delay_ms = 0;
766 uint32_t presentation_delay;
767
768 if (!GetPresentationDelay(&presentation_delay, direction)) {
769 /* This should never happens at stream request time but to be safe return
770 * some sample value to not break streaming
771 */
772 return 100;
773 }
774
775 /* us to ms */
776 remote_delay_ms = presentation_delay / 1000;
777 remote_delay_ms += GetTransportLatencyUs(direction) / 1000;
778
779 return remote_delay_ms;
780 }
781
UpdateAudioContextTypeAvailability(void)782 void LeAudioDeviceGroup::UpdateAudioContextTypeAvailability(void) {
783 LOG_DEBUG(" group id: %d, available contexts: %s", group_id_,
784 group_available_contexts_.to_string().c_str());
785 UpdateAudioContextTypeAvailability(group_available_contexts_);
786 }
787
788 /* Returns true if support for any type in the whole group has changed,
789 * otherwise false. */
UpdateAudioContextTypeAvailability(AudioContexts update_contexts)790 bool LeAudioDeviceGroup::UpdateAudioContextTypeAvailability(
791 AudioContexts update_contexts) {
792 auto new_contexts = AudioContexts();
793 bool active_contexts_has_been_modified = false;
794
795 if (update_contexts.none()) {
796 LOG_DEBUG("No context updated");
797 return false;
798 }
799
800 LOG_DEBUG("Updated context: %s", update_contexts.to_string().c_str());
801
802 for (LeAudioContextType ctx_type : types::kLeAudioContextAllTypesArray) {
803 LOG_DEBUG("Checking context: %s", ToHexString(ctx_type).c_str());
804
805 if (!update_contexts.test(ctx_type)) {
806 LOG_DEBUG("Configuration not in updated context");
807 /* Fill context bitset for possible returned value if updated */
808 if (available_context_to_configuration_map.count(ctx_type) > 0)
809 new_contexts.set(ctx_type);
810
811 continue;
812 }
813
814 auto new_conf = FindFirstSupportedConfiguration(ctx_type);
815
816 bool ctx_previously_not_supported =
817 (available_context_to_configuration_map.count(ctx_type) == 0 ||
818 available_context_to_configuration_map[ctx_type] == nullptr);
819 /* Check if support for context type has changed */
820 if (ctx_previously_not_supported) {
821 /* Current configuration for context type is empty */
822 if (new_conf == nullptr) {
823 /* Configuration remains empty */
824 continue;
825 } else {
826 /* Configuration changes from empty to some */
827 new_contexts.set(ctx_type);
828 active_contexts_has_been_modified = true;
829 }
830 } else {
831 /* Current configuration for context type is not empty */
832 if (new_conf == nullptr) {
833 /* Configuration changed to empty */
834 new_contexts.unset(ctx_type);
835 active_contexts_has_been_modified = true;
836 } else if (new_conf != available_context_to_configuration_map[ctx_type]) {
837 /* Configuration changed to any other */
838 new_contexts.set(ctx_type);
839 active_contexts_has_been_modified = true;
840 } else {
841 /* Configuration is the same */
842 new_contexts.set(ctx_type);
843 continue;
844 }
845 }
846
847 LOG_INFO(
848 "%s(%s), %s -> %s", types::contextTypeToStr(ctx_type).c_str(),
849 ToHexString(ctx_type).c_str(),
850 (ctx_previously_not_supported
851 ? "empty"
852 : available_context_to_configuration_map[ctx_type]->name.c_str()),
853 (new_conf != nullptr ? new_conf->name.c_str() : "empty"));
854
855 available_context_to_configuration_map[ctx_type] = new_conf;
856 }
857
858 /* Some contexts have changed, return new available context bitset */
859 if (active_contexts_has_been_modified) {
860 group_available_contexts_ = new_contexts;
861 }
862
863 return active_contexts_has_been_modified;
864 }
865
ReloadAudioLocations(void)866 bool LeAudioDeviceGroup::ReloadAudioLocations(void) {
867 AudioLocations updated_snk_audio_locations_ =
868 codec_spec_conf::kLeAudioLocationNotAllowed;
869 AudioLocations updated_src_audio_locations_ =
870 codec_spec_conf::kLeAudioLocationNotAllowed;
871
872 for (const auto& device : leAudioDevices_) {
873 if (device.expired() || (device.lock().get()->GetConnectionState() !=
874 DeviceConnectState::CONNECTED))
875 continue;
876 updated_snk_audio_locations_ |= device.lock().get()->snk_audio_locations_;
877 updated_src_audio_locations_ |= device.lock().get()->src_audio_locations_;
878 }
879
880 /* Nothing has changed */
881 if ((updated_snk_audio_locations_ == snk_audio_locations_) &&
882 (updated_src_audio_locations_ == src_audio_locations_))
883 return false;
884
885 snk_audio_locations_ = updated_snk_audio_locations_;
886 src_audio_locations_ = updated_src_audio_locations_;
887
888 return true;
889 }
890
ReloadAudioDirections(void)891 bool LeAudioDeviceGroup::ReloadAudioDirections(void) {
892 uint8_t updated_audio_directions = 0x00;
893
894 for (const auto& device : leAudioDevices_) {
895 if (device.expired() || (device.lock().get()->GetConnectionState() !=
896 DeviceConnectState::CONNECTED))
897 continue;
898 updated_audio_directions |= device.lock().get()->audio_directions_;
899 }
900
901 /* Nothing has changed */
902 if (updated_audio_directions == audio_directions_) return false;
903
904 audio_directions_ = updated_audio_directions;
905
906 return true;
907 }
908
IsInTransition(void)909 bool LeAudioDeviceGroup::IsInTransition(void) {
910 return target_state_ != current_state_;
911 }
912
IsStreaming(void)913 bool LeAudioDeviceGroup::IsStreaming(void) {
914 return current_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
915 }
916
IsReleasingOrIdle(void)917 bool LeAudioDeviceGroup::IsReleasingOrIdle(void) {
918 return (target_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) ||
919 (current_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
920 }
921
IsGroupStreamReady(void)922 bool LeAudioDeviceGroup::IsGroupStreamReady(void) {
923 auto iter =
924 std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(), [](auto& d) {
925 if (d.expired())
926 return false;
927 else
928 return !(((d.lock()).get())->HaveAllActiveAsesCisEst());
929 });
930
931 return iter == leAudioDevices_.end();
932 }
933
HaveAllCisesDisconnected(void)934 bool LeAudioDeviceGroup::HaveAllCisesDisconnected(void) {
935 for (auto const dev : leAudioDevices_) {
936 if (dev.expired()) continue;
937 if (dev.lock().get()->HaveAnyCisConnected()) return false;
938 }
939 return true;
940 }
941
GetFirstFreeCisId(void)942 uint8_t LeAudioDeviceGroup::GetFirstFreeCisId(void) {
943 for (uint8_t id = 0; id < UINT8_MAX; id++) {
944 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
945 [id](auto& d) {
946 if (d.expired())
947 return false;
948 else
949 return ((d.lock()).get())->HasCisId(id);
950 });
951
952 if (iter == leAudioDevices_.end()) return id;
953 }
954
955 return kInvalidCisId;
956 }
957
GetFirstFreeCisId(CisType cis_type)958 uint8_t LeAudioDeviceGroup::GetFirstFreeCisId(CisType cis_type) {
959 LOG_INFO("Group: %p, group_id: %d cis_type: %d", this, group_id_,
960 static_cast<int>(cis_type));
961 for (size_t id = 0; id < cises_.size(); id++) {
962 if (cises_[id].addr.IsEmpty() && cises_[id].type == cis_type) {
963 return id;
964 }
965 }
966 return kInvalidCisId;
967 }
968
GetGroupStrategy(int expected_group_size)969 types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupStrategy(
970 int expected_group_size) {
971 /* Simple strategy picker */
972 LOG_DEBUG(" Group %d size %d", group_id_, expected_group_size);
973 if (expected_group_size > 1) {
974 return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
975 }
976
977 LOG_DEBUG("audio location 0x%04lx", snk_audio_locations_.to_ulong());
978 if (!(snk_audio_locations_.to_ulong() &
979 codec_spec_conf::kLeAudioLocationAnyLeft) ||
980 !(snk_audio_locations_.to_ulong() &
981 codec_spec_conf::kLeAudioLocationAnyRight)) {
982 return types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE;
983 }
984
985 auto device = GetFirstDevice();
986 auto channel_cnt =
987 device->GetLc3SupportedChannelCount(types::kLeAudioDirectionSink);
988 LOG_DEBUG("Channel count for group %d is %d (device %s)", group_id_,
989 channel_cnt, ADDRESS_TO_LOGGABLE_CSTR(device->address_));
990 if (channel_cnt == 1) {
991 return types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE;
992 }
993
994 return types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE;
995 }
996
GetAseCount(uint8_t direction)997 int LeAudioDeviceGroup::GetAseCount(uint8_t direction) {
998 int result = 0;
999 for (const auto& device_iter : leAudioDevices_) {
1000 result += device_iter.lock()->GetAseCount(direction);
1001 }
1002
1003 return result;
1004 }
1005
CigGenerateCisIds(types::LeAudioContextType context_type)1006 void LeAudioDeviceGroup::CigGenerateCisIds(
1007 types::LeAudioContextType context_type) {
1008 LOG_INFO("Group %p, group_id: %d, context_type: %s", this, group_id_,
1009 bluetooth::common::ToString(context_type).c_str());
1010
1011 if (cises_.size() > 0) {
1012 LOG_INFO("CIS IDs already generated");
1013 return;
1014 }
1015
1016 const set_configurations::AudioSetConfigurations* confs =
1017 AudioSetConfigurationProvider::Get()->GetConfigurations(context_type);
1018
1019 uint8_t cis_count_bidir = 0;
1020 uint8_t cis_count_unidir_sink = 0;
1021 uint8_t cis_count_unidir_source = 0;
1022 int csis_group_size =
1023 bluetooth::csis::CsisClient::Get()->GetDesiredSize(group_id_);
1024 /* If this is CSIS group, the csis_group_size will be > 0, otherwise -1.
1025 * If the last happen it means, group size is 1 */
1026 int group_size = csis_group_size > 0 ? csis_group_size : 1;
1027
1028 get_cis_count(*confs, group_size, GetGroupStrategy(group_size),
1029 GetAseCount(types::kLeAudioDirectionSink),
1030 GetAseCount(types::kLeAudioDirectionSource), cis_count_bidir,
1031 cis_count_unidir_sink, cis_count_unidir_source);
1032
1033 uint8_t idx = 0;
1034 while (cis_count_bidir > 0) {
1035 struct le_audio::types::cis cis_entry = {
1036 .id = idx,
1037 .addr = RawAddress::kEmpty,
1038 .type = CisType::CIS_TYPE_BIDIRECTIONAL,
1039 .conn_handle = 0,
1040 };
1041 cises_.push_back(cis_entry);
1042 cis_count_bidir--;
1043 idx++;
1044 }
1045
1046 while (cis_count_unidir_sink > 0) {
1047 struct le_audio::types::cis cis_entry = {
1048 .id = idx,
1049 .addr = RawAddress::kEmpty,
1050 .type = CisType::CIS_TYPE_UNIDIRECTIONAL_SINK,
1051 .conn_handle = 0,
1052 };
1053 cises_.push_back(cis_entry);
1054 cis_count_unidir_sink--;
1055 idx++;
1056 }
1057
1058 while (cis_count_unidir_source > 0) {
1059 struct le_audio::types::cis cis_entry = {
1060 .id = idx,
1061 .addr = RawAddress::kEmpty,
1062 .type = CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE,
1063 .conn_handle = 0,
1064 };
1065 cises_.push_back(cis_entry);
1066 cis_count_unidir_source--;
1067 idx++;
1068 }
1069 }
1070
CigAssignCisIds(LeAudioDevice * leAudioDevice)1071 bool LeAudioDeviceGroup::CigAssignCisIds(LeAudioDevice* leAudioDevice) {
1072 ASSERT_LOG(leAudioDevice, "invalid device");
1073 LOG_INFO("device: %s", ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
1074
1075 struct ase* ase = leAudioDevice->GetFirstActiveAse();
1076 if (!ase) {
1077 LOG_ERROR(" Device %s shouldn't be called without an active ASE",
1078 ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
1079 return false;
1080 }
1081
1082 for (; ase != nullptr; ase = leAudioDevice->GetNextActiveAse(ase)) {
1083 uint8_t cis_id = kInvalidCisId;
1084 /* CIS ID already set */
1085 if (ase->cis_id != kInvalidCisId) {
1086 LOG_INFO("ASE ID: %d, is already assigned CIS ID: %d, type %d", ase->id,
1087 ase->cis_id, cises_[ase->cis_id].type);
1088 if (!cises_[ase->cis_id].addr.IsEmpty()) {
1089 LOG_INFO("Bi-Directional CIS already assigned");
1090 continue;
1091 }
1092 /* Reuse existing CIS ID if available*/
1093 cis_id = ase->cis_id;
1094 }
1095
1096 /* First check if we have bidirectional ASEs. If so, assign same CIS ID.*/
1097 struct ase* matching_bidir_ase =
1098 leAudioDevice->GetNextActiveAseWithDifferentDirection(ase);
1099
1100 for (; matching_bidir_ase != nullptr;
1101 matching_bidir_ase = leAudioDevice->GetNextActiveAseWithSameDirection(
1102 matching_bidir_ase)) {
1103 if ((matching_bidir_ase->cis_id != kInvalidCisId) &&
1104 (matching_bidir_ase->cis_id != cis_id)) {
1105 LOG_INFO("Bi-Directional CIS is already used. ASE Id: %d cis_id=%d",
1106 matching_bidir_ase->id, matching_bidir_ase->cis_id);
1107 continue;
1108 }
1109 break;
1110 }
1111
1112 if (matching_bidir_ase) {
1113 if (cis_id == kInvalidCisId) {
1114 cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1115 }
1116
1117 if (cis_id != kInvalidCisId) {
1118 ase->cis_id = cis_id;
1119 matching_bidir_ase->cis_id = cis_id;
1120 cises_[cis_id].addr = leAudioDevice->address_;
1121
1122 LOG_INFO(
1123 " ASE ID: %d and ASE ID: %d, assigned Bi-Directional CIS ID: %d",
1124 +ase->id, +matching_bidir_ase->id, +ase->cis_id);
1125 continue;
1126 }
1127
1128 LOG_WARN(
1129 " ASE ID: %d, unable to get free Bi-Directional CIS ID but maybe "
1130 "thats fine. Try using unidirectional.",
1131 ase->id);
1132 }
1133
1134 if (ase->direction == types::kLeAudioDirectionSink) {
1135 if (cis_id == kInvalidCisId) {
1136 cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_UNIDIRECTIONAL_SINK);
1137 }
1138
1139 if (cis_id == kInvalidCisId) {
1140 LOG_WARN(
1141 " Unable to get free Uni-Directional Sink CIS ID - maybe there is "
1142 "bi-directional available");
1143 /* This could happen when scenarios for given context type allows for
1144 * Sink and Source configuration but also only Sink configuration.
1145 */
1146 cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1147 if (cis_id == kInvalidCisId) {
1148 LOG_ERROR("Unable to get free Uni-Directional Sink CIS ID");
1149 return false;
1150 }
1151 }
1152
1153 ase->cis_id = cis_id;
1154 cises_[cis_id].addr = leAudioDevice->address_;
1155 LOG_INFO("ASE ID: %d, assigned Uni-Directional Sink CIS ID: %d", ase->id,
1156 ase->cis_id);
1157 continue;
1158 }
1159
1160 /* Source direction */
1161 ASSERT_LOG(ase->direction == types::kLeAudioDirectionSource,
1162 "Expected Source direction, actual=%d", ase->direction);
1163
1164 if (cis_id == kInvalidCisId) {
1165 cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE);
1166 }
1167
1168 if (cis_id == kInvalidCisId) {
1169 /* This could happen when scenarios for given context type allows for
1170 * Sink and Source configuration but also only Sink configuration.
1171 */
1172 LOG_WARN(
1173 "Unable to get free Uni-Directional Source CIS ID - maybe there "
1174 "is bi-directional available");
1175 cis_id = GetFirstFreeCisId(CisType::CIS_TYPE_BIDIRECTIONAL);
1176 if (cis_id == kInvalidCisId) {
1177 LOG_ERROR("Unable to get free Uni-Directional Source CIS ID");
1178 return false;
1179 }
1180 }
1181
1182 ase->cis_id = cis_id;
1183 cises_[cis_id].addr = leAudioDevice->address_;
1184 LOG_INFO("ASE ID: %d, assigned Uni-Directional Source CIS ID: %d", ase->id,
1185 ase->cis_id);
1186 }
1187
1188 return true;
1189 }
1190
CigAssignCisConnHandles(const std::vector<uint16_t> & conn_handles)1191 void LeAudioDeviceGroup::CigAssignCisConnHandles(
1192 const std::vector<uint16_t>& conn_handles) {
1193 LOG_INFO("num of cis handles %d", static_cast<int>(conn_handles.size()));
1194 for (size_t i = 0; i < cises_.size(); i++) {
1195 cises_[i].conn_handle = conn_handles[i];
1196 LOG_INFO("assigning cis[%d] conn_handle: %d", cises_[i].id,
1197 cises_[i].conn_handle);
1198 }
1199 }
1200
CigAssignCisConnHandlesToAses(LeAudioDevice * leAudioDevice)1201 void LeAudioDeviceGroup::CigAssignCisConnHandlesToAses(
1202 LeAudioDevice* leAudioDevice) {
1203 ASSERT_LOG(leAudioDevice, "Invalid device");
1204 LOG_INFO("group: %p, group_id: %d, device: %s", this, group_id_,
1205 ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
1206
1207 /* Assign all CIS connection handles to ases */
1208 struct le_audio::types::ase* ase =
1209 leAudioDevice->GetFirstActiveAseByDataPathState(
1210 AudioStreamDataPathState::IDLE);
1211 if (!ase) {
1212 LOG_WARN("No active ASE with AudioStreamDataPathState IDLE");
1213 return;
1214 }
1215
1216 for (; ase != nullptr; ase = leAudioDevice->GetFirstActiveAseByDataPathState(
1217 AudioStreamDataPathState::IDLE)) {
1218 auto ases_pair = leAudioDevice->GetAsesByCisId(ase->cis_id);
1219
1220 if (ases_pair.sink && ases_pair.sink->active) {
1221 ases_pair.sink->cis_conn_hdl = cises_[ase->cis_id].conn_handle;
1222 ases_pair.sink->data_path_state = AudioStreamDataPathState::CIS_ASSIGNED;
1223 }
1224 if (ases_pair.source && ases_pair.source->active) {
1225 ases_pair.source->cis_conn_hdl = cises_[ase->cis_id].conn_handle;
1226 ases_pair.source->data_path_state =
1227 AudioStreamDataPathState::CIS_ASSIGNED;
1228 }
1229 }
1230 }
1231
CigAssignCisConnHandlesToAses(void)1232 void LeAudioDeviceGroup::CigAssignCisConnHandlesToAses(void) {
1233 LeAudioDevice* leAudioDevice = GetFirstActiveDevice();
1234 ASSERT_LOG(leAudioDevice, "Shouldn't be called without an active device.");
1235
1236 LOG_INFO("Group %p, group_id %d", this, group_id_);
1237
1238 /* Assign all CIS connection handles to ases */
1239 for (; leAudioDevice != nullptr;
1240 leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
1241 CigAssignCisConnHandlesToAses(leAudioDevice);
1242 }
1243 }
1244
CigUnassignCis(LeAudioDevice * leAudioDevice)1245 void LeAudioDeviceGroup::CigUnassignCis(LeAudioDevice* leAudioDevice) {
1246 ASSERT_LOG(leAudioDevice, "Invalid device");
1247
1248 LOG_INFO("Group %p, group_id %d, device: %s", this, group_id_,
1249 ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
1250
1251 for (struct le_audio::types::cis& cis_entry : cises_) {
1252 if (cis_entry.addr == leAudioDevice->address_) {
1253 cis_entry.addr = RawAddress::kEmpty;
1254 }
1255 }
1256 }
1257
CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,types::AudioLocations audio_locations,uint8_t requested_channel_count,uint8_t channel_count_mask)1258 bool CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,
1259 types::AudioLocations audio_locations,
1260 uint8_t requested_channel_count,
1261 uint8_t channel_count_mask) {
1262 DLOG(INFO) << __func__ << " strategy: " << (int)strategy
1263 << " locations: " << +audio_locations.to_ulong();
1264
1265 switch (strategy) {
1266 case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
1267 return audio_locations.any();
1268 case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
1269 if ((audio_locations.to_ulong() &
1270 codec_spec_conf::kLeAudioLocationAnyLeft) &&
1271 (audio_locations.to_ulong() &
1272 codec_spec_conf::kLeAudioLocationAnyRight))
1273 return true;
1274 else
1275 return false;
1276 case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
1277 if (!(audio_locations.to_ulong() &
1278 codec_spec_conf::kLeAudioLocationAnyLeft) ||
1279 !(audio_locations.to_ulong() &
1280 codec_spec_conf::kLeAudioLocationAnyRight))
1281 return false;
1282
1283 DLOG(INFO) << __func__ << " requested chan cnt "
1284 << +requested_channel_count
1285 << " chan mask: " << loghex(channel_count_mask);
1286
1287 /* Return true if requested channel count is set in the channel count
1288 * mask. In the channel_count_mask, bit0 is set when 1 channel is
1289 * supported.
1290 */
1291 return ((1 << (requested_channel_count - 1)) & channel_count_mask);
1292 default:
1293 return false;
1294 }
1295
1296 return false;
1297 }
1298
1299 /* This method check if group support given audio configuration
1300 * requirement for connected devices in the group and available ASEs
1301 * (no matter on the ASE state) and for given context type
1302 */
IsConfigurationSupported(const set_configurations::AudioSetConfiguration * audio_set_conf,types::LeAudioContextType context_type,types::LeAudioConfigurationStrategy required_snk_strategy)1303 bool LeAudioDeviceGroup::IsConfigurationSupported(
1304 const set_configurations::AudioSetConfiguration* audio_set_conf,
1305 types::LeAudioContextType context_type,
1306 types::LeAudioConfigurationStrategy required_snk_strategy) {
1307 if (!set_configurations::check_if_may_cover_scenario(
1308 audio_set_conf, NumOfConnected(context_type))) {
1309 LOG_DEBUG(" cannot cover scenario %s: size of for context type %d",
1310 bluetooth::common::ToString(context_type).c_str(),
1311 +NumOfConnected(context_type));
1312 return false;
1313 }
1314
1315 /* TODO For now: set ase if matching with first pac.
1316 * 1) We assume as well that devices will match requirements in order
1317 * e.g. 1 Device - 1 Requirement, 2 Device - 2 Requirement etc.
1318 * 2) ASEs should be active only if best (according to priority list) full
1319 * scenarion will be covered.
1320 * 3) ASEs should be filled according to performance profile.
1321 */
1322 for (const auto& ent : (*audio_set_conf).confs) {
1323 LOG_DEBUG(" Looking for configuration: %s - %s",
1324 audio_set_conf->name.c_str(),
1325 (ent.direction == types::kLeAudioDirectionSink ? "snk" : "src"));
1326
1327 uint8_t required_device_cnt = ent.device_cnt;
1328 uint8_t max_required_ase_per_dev =
1329 ent.ase_cnt / ent.device_cnt + (ent.ase_cnt % ent.device_cnt);
1330 uint8_t active_ase_num = 0;
1331 auto strategy = ent.strategy;
1332
1333 LOG_DEBUG(
1334 " Number of devices: %d, number of ASEs: %d, Max ASE per device: %d "
1335 "strategy: %d",
1336 +required_device_cnt, +ent.ase_cnt, +max_required_ase_per_dev,
1337 static_cast<int>(strategy));
1338
1339 if (ent.direction == types::kLeAudioDirectionSink &&
1340 strategy != required_snk_strategy) {
1341 LOG_DEBUG(" Sink strategy mismatch group!=cfg.entry (%d!=%d)",
1342 static_cast<int>(required_snk_strategy),
1343 static_cast<int>(strategy));
1344 return false;
1345 }
1346
1347 for (auto* device = GetFirstDeviceWithActiveContext(context_type);
1348 device != nullptr && required_device_cnt > 0;
1349 device = GetNextDeviceWithActiveContext(device, context_type)) {
1350 /* Skip if device has ASE configured in this direction already */
1351
1352 if (device->ases_.empty()) continue;
1353
1354 if (!device->GetCodecConfigurationSupportedPac(ent.direction, ent.codec))
1355 continue;
1356
1357 int needed_ase = std::min(static_cast<int>(max_required_ase_per_dev),
1358 static_cast<int>(ent.ase_cnt - active_ase_num));
1359
1360 /* If we required more ASEs per device which means we would like to
1361 * create more CISes to one device, we should also check the allocation
1362 * if it allows us to do this.
1363 */
1364
1365 types::AudioLocations audio_locations = 0;
1366 /* Check direction and if audio location allows to create more cise */
1367 if (ent.direction == types::kLeAudioDirectionSink)
1368 audio_locations = device->snk_audio_locations_;
1369 else
1370 audio_locations = device->src_audio_locations_;
1371
1372 /* TODO Make it no Lc3 specific */
1373 if (!CheckIfStrategySupported(
1374 strategy, audio_locations,
1375 std::get<LeAudioLc3Config>(ent.codec.config).GetChannelCount(),
1376 device->GetLc3SupportedChannelCount(ent.direction))) {
1377 LOG_DEBUG(" insufficient device audio allocation: %lu",
1378 audio_locations.to_ulong());
1379 continue;
1380 }
1381
1382 for (auto& ase : device->ases_) {
1383 if (ase.direction != ent.direction) continue;
1384
1385 active_ase_num++;
1386 needed_ase--;
1387
1388 if (needed_ase == 0) break;
1389 }
1390
1391 if (needed_ase > 0) {
1392 LOG_DEBUG("Device has too less ASEs. Still needed ases %d", needed_ase);
1393 return false;
1394 }
1395
1396 required_device_cnt--;
1397 }
1398
1399 if (required_device_cnt > 0) {
1400 /* Don't left any active devices if requirements are not met */
1401 LOG_DEBUG(" could not configure all the devices");
1402 return false;
1403 }
1404 }
1405
1406 LOG_DEBUG("Chosen ASE Configuration for group: %d, configuration: %s",
1407 this->group_id_, audio_set_conf->name.c_str());
1408 return true;
1409 }
1410
GetFirstLeft(const types::AudioLocations & audio_locations)1411 static uint32_t GetFirstLeft(const types::AudioLocations& audio_locations) {
1412 uint32_t audio_location_ulong = audio_locations.to_ulong();
1413
1414 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeft)
1415 return codec_spec_conf::kLeAudioLocationFrontLeft;
1416
1417 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBackLeft)
1418 return codec_spec_conf::kLeAudioLocationBackLeft;
1419
1420 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeftOfCenter)
1421 return codec_spec_conf::kLeAudioLocationFrontLeftOfCenter;
1422
1423 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationSideLeft)
1424 return codec_spec_conf::kLeAudioLocationSideLeft;
1425
1426 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopFrontLeft)
1427 return codec_spec_conf::kLeAudioLocationTopFrontLeft;
1428
1429 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopBackLeft)
1430 return codec_spec_conf::kLeAudioLocationTopBackLeft;
1431
1432 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopSideLeft)
1433 return codec_spec_conf::kLeAudioLocationTopSideLeft;
1434
1435 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBottomFrontLeft)
1436 return codec_spec_conf::kLeAudioLocationBottomFrontLeft;
1437
1438 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontLeftWide)
1439 return codec_spec_conf::kLeAudioLocationFrontLeftWide;
1440
1441 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationLeftSurround)
1442 return codec_spec_conf::kLeAudioLocationLeftSurround;
1443
1444 return 0;
1445 }
1446
GetFirstRight(const types::AudioLocations & audio_locations)1447 static uint32_t GetFirstRight(const types::AudioLocations& audio_locations) {
1448 uint32_t audio_location_ulong = audio_locations.to_ulong();
1449
1450 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRight)
1451 return codec_spec_conf::kLeAudioLocationFrontRight;
1452
1453 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBackRight)
1454 return codec_spec_conf::kLeAudioLocationBackRight;
1455
1456 if (audio_location_ulong &
1457 codec_spec_conf::kLeAudioLocationFrontRightOfCenter)
1458 return codec_spec_conf::kLeAudioLocationFrontRightOfCenter;
1459
1460 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationSideRight)
1461 return codec_spec_conf::kLeAudioLocationSideRight;
1462
1463 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopFrontRight)
1464 return codec_spec_conf::kLeAudioLocationTopFrontRight;
1465
1466 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopBackRight)
1467 return codec_spec_conf::kLeAudioLocationTopBackRight;
1468
1469 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationTopSideRight)
1470 return codec_spec_conf::kLeAudioLocationTopSideRight;
1471
1472 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationBottomFrontRight)
1473 return codec_spec_conf::kLeAudioLocationBottomFrontRight;
1474
1475 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationFrontRightWide)
1476 return codec_spec_conf::kLeAudioLocationFrontRightWide;
1477
1478 if (audio_location_ulong & codec_spec_conf::kLeAudioLocationRightSurround)
1479 return codec_spec_conf::kLeAudioLocationRightSurround;
1480
1481 return 0;
1482 }
1483
PickAudioLocation(types::LeAudioConfigurationStrategy strategy,const types::AudioLocations & device_locations,types::AudioLocations & group_locations)1484 uint32_t PickAudioLocation(types::LeAudioConfigurationStrategy strategy,
1485 const types::AudioLocations& device_locations,
1486 types::AudioLocations& group_locations) {
1487 LOG_DEBUG("strategy: %d, locations: 0x%lx, input group locations: 0x%lx",
1488 (int)strategy, device_locations.to_ulong(),
1489 group_locations.to_ulong());
1490
1491 auto is_left_not_yet_assigned =
1492 !(group_locations.to_ulong() & codec_spec_conf::kLeAudioLocationAnyLeft);
1493 auto is_right_not_yet_assigned =
1494 !(group_locations.to_ulong() & codec_spec_conf::kLeAudioLocationAnyRight);
1495 uint32_t left_device_loc = GetFirstLeft(device_locations);
1496 uint32_t right_device_loc = GetFirstRight(device_locations);
1497
1498 if (left_device_loc == 0 && right_device_loc == 0) {
1499 LOG_WARN("Can't find device able to render left and right audio channel");
1500 }
1501
1502 switch (strategy) {
1503 case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
1504 case types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE:
1505 if (left_device_loc && is_left_not_yet_assigned) {
1506 group_locations |= left_device_loc;
1507 return left_device_loc;
1508 }
1509
1510 if (right_device_loc && is_right_not_yet_assigned) {
1511 group_locations |= right_device_loc;
1512 return right_device_loc;
1513 }
1514 break;
1515
1516 case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
1517 if (left_device_loc && right_device_loc) {
1518 group_locations |= left_device_loc | right_device_loc;
1519 return left_device_loc | right_device_loc;
1520 }
1521 break;
1522 default:
1523 LOG_ALWAYS_FATAL("%s: Unknown strategy: %hhu", __func__, strategy);
1524 return 0;
1525 }
1526
1527 LOG_ERROR(
1528 "Can't find device for left/right channel. Strategy: %hhu, "
1529 "device_locations: %lx, output group_locations: %lx.",
1530 strategy, device_locations.to_ulong(), group_locations.to_ulong());
1531
1532 /* Return either any left or any right audio location. It might result with
1533 * multiple devices within the group having the same location.
1534 */
1535 return left_device_loc ? left_device_loc : right_device_loc;
1536 }
1537
ConfigureAses(const le_audio::set_configurations::SetConfiguration & ent,types::LeAudioContextType context_type,uint8_t * number_of_already_active_group_ase,BidirectionalPair<AudioLocations> & group_audio_locations_memo,const BidirectionalPair<AudioContexts> & metadata_context_types,const BidirectionalPair<std::vector<uint8_t>> & ccid_lists,bool reuse_cis_id)1538 bool LeAudioDevice::ConfigureAses(
1539 const le_audio::set_configurations::SetConfiguration& ent,
1540 types::LeAudioContextType context_type,
1541 uint8_t* number_of_already_active_group_ase,
1542 BidirectionalPair<AudioLocations>& group_audio_locations_memo,
1543 const BidirectionalPair<AudioContexts>& metadata_context_types,
1544 const BidirectionalPair<std::vector<uint8_t>>& ccid_lists,
1545 bool reuse_cis_id) {
1546 /* First try to use the already configured ASE */
1547 auto ase = GetFirstActiveAseByDirection(ent.direction);
1548 if (ase) {
1549 LOG_INFO("Using an already active ASE id=%d", ase->id);
1550 } else {
1551 ase = GetFirstInactiveAse(ent.direction, reuse_cis_id);
1552 }
1553
1554 if (!ase) {
1555 LOG_ERROR("Unable to find an ASE to configure");
1556 return false;
1557 }
1558
1559 /* The number_of_already_active_group_ase keeps all the active ases
1560 * in other devices in the group.
1561 * This function counts active ases only for this device, and we count here
1562 * new active ases and already active ases which we want to reuse in the
1563 * scenario
1564 */
1565 uint8_t active_ases = *number_of_already_active_group_ase;
1566 uint8_t max_required_ase_per_dev =
1567 ent.ase_cnt / ent.device_cnt + (ent.ase_cnt % ent.device_cnt);
1568 le_audio::types::LeAudioConfigurationStrategy strategy = ent.strategy;
1569
1570 auto pac = GetCodecConfigurationSupportedPac(ent.direction, ent.codec);
1571 if (!pac) return false;
1572
1573 int needed_ase = std::min((int)(max_required_ase_per_dev),
1574 (int)(ent.ase_cnt - active_ases));
1575
1576 types::AudioLocations audio_locations = 0;
1577
1578 /* Check direction and if audio location allows to create more cise */
1579 if (ent.direction == types::kLeAudioDirectionSink) {
1580 audio_locations = snk_audio_locations_;
1581 } else {
1582 audio_locations = src_audio_locations_;
1583 }
1584
1585 for (; needed_ase && ase; needed_ase--) {
1586 ase->active = true;
1587 ase->configured_for_context_type = context_type;
1588 active_ases++;
1589
1590 /* In case of late connect, we could be here for STREAMING ase.
1591 * in such case, it is needed to mark ase as known active ase which
1592 * is important to validate scenario and is done already few lines above.
1593 * Nothing more to do is needed here.
1594 */
1595 if (ase->state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
1596 if (ase->state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED)
1597 ase->reconfigure = true;
1598
1599 ase->target_latency = ent.qos.target_latency;
1600 ase->codec_id = ent.codec.id;
1601 /* TODO: find better way to not use LC3 explicitly */
1602 ase->codec_config = std::get<LeAudioLc3Config>(ent.codec.config);
1603
1604 /*Let's choose audio channel allocation if not set */
1605 ase->codec_config.audio_channel_allocation =
1606 PickAudioLocation(strategy, audio_locations,
1607 group_audio_locations_memo.get_ref(ent.direction));
1608
1609 /* Get default value if no requirement for specific frame blocks per sdu
1610 */
1611 if (!ase->codec_config.codec_frames_blocks_per_sdu) {
1612 ase->codec_config.codec_frames_blocks_per_sdu =
1613 GetMaxCodecFramesPerSduFromPac(pac);
1614 }
1615 ase->max_sdu_size = codec_spec_caps::GetAudioChannelCounts(
1616 *ase->codec_config.audio_channel_allocation) *
1617 *ase->codec_config.octets_per_codec_frame *
1618 *ase->codec_config.codec_frames_blocks_per_sdu;
1619
1620 ase->retrans_nb = ent.qos.retransmission_number;
1621 ase->max_transport_latency = ent.qos.max_transport_latency;
1622
1623 /* Filter multidirectional audio context for each ase direction */
1624 auto directional_audio_context =
1625 metadata_context_types.get(ase->direction) &
1626 GetAvailableContexts(ase->direction);
1627 if (directional_audio_context.any()) {
1628 ase->metadata = GetMetadata(directional_audio_context,
1629 ccid_lists.get(ase->direction));
1630 } else {
1631 ase->metadata =
1632 GetMetadata(AudioContexts(LeAudioContextType::UNSPECIFIED),
1633 std::vector<uint8_t>());
1634 }
1635 }
1636
1637 LOG_DEBUG(
1638 "device=%s, activated ASE id=%d, direction=%s, max_sdu_size=%d, "
1639 "cis_id=%d, target_latency=%d",
1640 ADDRESS_TO_LOGGABLE_CSTR(address_), ase->id,
1641 (ent.direction == 1 ? "snk" : "src"), ase->max_sdu_size, ase->cis_id,
1642 ent.qos.target_latency);
1643
1644 /* Try to use the already active ASE */
1645 ase = GetNextActiveAseWithSameDirection(ase);
1646 if (ase == nullptr) {
1647 ase = GetFirstInactiveAse(ent.direction, reuse_cis_id);
1648 }
1649 }
1650
1651 *number_of_already_active_group_ase = active_ases;
1652 return true;
1653 }
1654
1655 /* This method should choose aproperiate ASEs to be active and set a cached
1656 * configuration for codec and qos.
1657 */
ConfigureAses(const set_configurations::AudioSetConfiguration * audio_set_conf,types::LeAudioContextType context_type,const types::BidirectionalPair<AudioContexts> & metadata_context_types,const types::BidirectionalPair<std::vector<uint8_t>> & ccid_lists)1658 bool LeAudioDeviceGroup::ConfigureAses(
1659 const set_configurations::AudioSetConfiguration* audio_set_conf,
1660 types::LeAudioContextType context_type,
1661 const types::BidirectionalPair<AudioContexts>& metadata_context_types,
1662 const types::BidirectionalPair<std::vector<uint8_t>>& ccid_lists) {
1663 if (!set_configurations::check_if_may_cover_scenario(
1664 audio_set_conf, NumOfConnected(context_type)))
1665 return false;
1666
1667 bool reuse_cis_id =
1668 GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED;
1669
1670 /* TODO For now: set ase if matching with first pac.
1671 * 1) We assume as well that devices will match requirements in order
1672 * e.g. 1 Device - 1 Requirement, 2 Device - 2 Requirement etc.
1673 * 2) ASEs should be active only if best (according to priority list) full
1674 * scenarion will be covered.
1675 * 3) ASEs should be filled according to performance profile.
1676 */
1677
1678 // WARNING: This may look like the results stored here are unused, but it
1679 // actually shares the intermediate values between the multiple
1680 // configuration calls within the configuration loop.
1681 BidirectionalPair<types::AudioLocations> group_audio_locations_memo = {
1682 .sink = 0, .source = 0};
1683
1684 for (const auto& ent : (*audio_set_conf).confs) {
1685 LOG_DEBUG(" Looking for requirements: %s, - %s",
1686 audio_set_conf->name.c_str(),
1687 (ent.direction == 1 ? "snk" : "src"));
1688
1689 uint8_t required_device_cnt = ent.device_cnt;
1690 uint8_t max_required_ase_per_dev =
1691 ent.ase_cnt / ent.device_cnt + (ent.ase_cnt % ent.device_cnt);
1692 uint8_t active_ase_num = 0;
1693 le_audio::types::LeAudioConfigurationStrategy strategy = ent.strategy;
1694
1695 LOG_DEBUG(
1696 "Number of devices: %d number of ASEs: %d, Max ASE per device: %d "
1697 "strategy: %d",
1698 required_device_cnt, ent.ase_cnt, max_required_ase_per_dev,
1699 (int)strategy);
1700
1701 for (auto* device = GetFirstDeviceWithActiveContext(context_type);
1702 device != nullptr && required_device_cnt > 0;
1703 device = GetNextDeviceWithActiveContext(device, context_type)) {
1704 /* For the moment, we configure only connected devices and when it is
1705 * ready to stream i.e. All ASEs are discovered and device is reported as
1706 * connected
1707 */
1708 if (device->GetConnectionState() != DeviceConnectState::CONNECTED) {
1709 LOG_WARN(
1710 "Device %s, in the state %s",
1711 ADDRESS_TO_LOGGABLE_CSTR(device->address_),
1712 bluetooth::common::ToString(device->GetConnectionState()).c_str());
1713 continue;
1714 }
1715
1716 if (!device->ConfigureAses(
1717 ent, context_type, &active_ase_num, group_audio_locations_memo,
1718 metadata_context_types, ccid_lists, reuse_cis_id))
1719 continue;
1720
1721 required_device_cnt--;
1722 }
1723
1724 if (required_device_cnt > 0) {
1725 /* Don't left any active devices if requirements are not met */
1726 LOG_ERROR(" could not configure all the devices");
1727 Deactivate();
1728 return false;
1729 }
1730 }
1731
1732 LOG_INFO("Choosed ASE Configuration for group: %d, configuration: %s",
1733 group_id_, audio_set_conf->name.c_str());
1734
1735 configuration_context_type_ = context_type;
1736 metadata_context_type_ = metadata_context_types;
1737 return true;
1738 }
1739
1740 const set_configurations::AudioSetConfiguration*
GetActiveConfiguration(void)1741 LeAudioDeviceGroup::GetActiveConfiguration(void) {
1742 return available_context_to_configuration_map[configuration_context_type_];
1743 }
1744
1745 std::optional<LeAudioCodecConfiguration>
GetCodecConfigurationByDirection(types::LeAudioContextType group_context_type,uint8_t direction) const1746 LeAudioDeviceGroup::GetCodecConfigurationByDirection(
1747 types::LeAudioContextType group_context_type, uint8_t direction) const {
1748 if (available_context_to_configuration_map.count(group_context_type) == 0) {
1749 LOG_DEBUG("Context type %s, not supported",
1750 bluetooth::common::ToString(group_context_type).c_str());
1751 return std::nullopt;
1752 }
1753
1754 const set_configurations::AudioSetConfiguration* audio_set_conf =
1755 available_context_to_configuration_map.at(group_context_type);
1756 LeAudioCodecConfiguration group_config = {0, 0, 0, 0};
1757 if (!audio_set_conf) return std::nullopt;
1758
1759 for (const auto& conf : audio_set_conf->confs) {
1760 if (conf.direction != direction) continue;
1761
1762 if (group_config.sample_rate != 0 &&
1763 conf.codec.GetConfigSamplingFrequency() != group_config.sample_rate) {
1764 LOG(WARNING) << __func__
1765 << ", stream configuration could not be "
1766 "determined (sampling frequency differs) for direction: "
1767 << loghex(direction);
1768 return std::nullopt;
1769 }
1770 group_config.sample_rate = conf.codec.GetConfigSamplingFrequency();
1771
1772 if (group_config.data_interval_us != 0 &&
1773 conf.codec.GetConfigDataIntervalUs() != group_config.data_interval_us) {
1774 LOG(WARNING) << __func__
1775 << ", stream configuration could not be "
1776 "determined (data interval differs) for direction: "
1777 << loghex(direction);
1778 return std::nullopt;
1779 }
1780 group_config.data_interval_us = conf.codec.GetConfigDataIntervalUs();
1781
1782 if (group_config.bits_per_sample != 0 &&
1783 conf.codec.GetConfigBitsPerSample() != group_config.bits_per_sample) {
1784 LOG(WARNING) << __func__
1785 << ", stream configuration could not be "
1786 "determined (bits per sample differs) for direction: "
1787 << loghex(direction);
1788 return std::nullopt;
1789 }
1790 group_config.bits_per_sample = conf.codec.GetConfigBitsPerSample();
1791
1792 group_config.num_channels +=
1793 conf.codec.GetConfigChannelCount() * conf.device_cnt;
1794 }
1795
1796 if (group_config.IsInvalid()) return std::nullopt;
1797
1798 return group_config;
1799 }
1800
IsContextSupported(types::LeAudioContextType group_context_type)1801 bool LeAudioDeviceGroup::IsContextSupported(
1802 types::LeAudioContextType group_context_type) {
1803 auto iter = available_context_to_configuration_map.find(group_context_type);
1804 if (iter == available_context_to_configuration_map.end()) return false;
1805
1806 return available_context_to_configuration_map[group_context_type] != nullptr;
1807 }
1808
IsMetadataChanged(const BidirectionalPair<AudioContexts> & context_types,const BidirectionalPair<std::vector<uint8_t>> & ccid_lists)1809 bool LeAudioDeviceGroup::IsMetadataChanged(
1810 const BidirectionalPair<AudioContexts>& context_types,
1811 const BidirectionalPair<std::vector<uint8_t>>& ccid_lists) {
1812 for (auto* leAudioDevice = GetFirstActiveDevice(); leAudioDevice;
1813 leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
1814 if (leAudioDevice->IsMetadataChanged(context_types, ccid_lists))
1815 return true;
1816 }
1817
1818 return false;
1819 }
1820
StreamOffloaderUpdated(uint8_t direction)1821 void LeAudioDeviceGroup::StreamOffloaderUpdated(uint8_t direction) {
1822 if (direction == le_audio::types::kLeAudioDirectionSource) {
1823 stream_conf.source_is_initial = false;
1824 } else {
1825 stream_conf.sink_is_initial = false;
1826 }
1827 }
1828
CreateStreamVectorForOffloader(uint8_t direction)1829 void LeAudioDeviceGroup::CreateStreamVectorForOffloader(uint8_t direction) {
1830 if (CodecManager::GetInstance()->GetCodecLocation() !=
1831 le_audio::types::CodecLocation::ADSP) {
1832 return;
1833 }
1834
1835 CisType cis_type;
1836 std::vector<std::pair<uint16_t, uint32_t>>* streams;
1837 std::vector<stream_map_info>* offloader_streams_target_allocation;
1838 std::vector<stream_map_info>* offloader_streams_current_allocation;
1839 std::string tag;
1840 uint32_t available_allocations = 0;
1841 bool* changed_flag;
1842 bool* is_initial;
1843 if (direction == le_audio::types::kLeAudioDirectionSource) {
1844 changed_flag = &stream_conf.source_offloader_changed;
1845 is_initial = &stream_conf.source_is_initial;
1846 cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE;
1847 streams = &stream_conf.source_streams;
1848 offloader_streams_target_allocation =
1849 &stream_conf.source_offloader_streams_target_allocation;
1850 offloader_streams_current_allocation =
1851 &stream_conf.source_offloader_streams_current_allocation;
1852 tag = "Source";
1853 available_allocations = AdjustAllocationForOffloader(
1854 stream_conf.source_audio_channel_allocation);
1855 } else {
1856 changed_flag = &stream_conf.sink_offloader_changed;
1857 is_initial = &stream_conf.sink_is_initial;
1858 cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SINK;
1859 streams = &stream_conf.sink_streams;
1860 offloader_streams_target_allocation =
1861 &stream_conf.sink_offloader_streams_target_allocation;
1862 offloader_streams_current_allocation =
1863 &stream_conf.sink_offloader_streams_current_allocation;
1864 tag = "Sink";
1865 available_allocations =
1866 AdjustAllocationForOffloader(stream_conf.sink_audio_channel_allocation);
1867 }
1868
1869 if (available_allocations == 0) {
1870 LOG_ERROR("There is no CIS connected");
1871 return;
1872 }
1873
1874 if (offloader_streams_target_allocation->size() == 0) {
1875 *is_initial = true;
1876 } else if (*is_initial ||
1877 CodecManager::GetInstance()->GetAidlVersionInUsed() >=
1878 AIDL_VERSION_SUPPORT_STREAM_ACTIVE) {
1879 // As multiple CISes phone call case, the target_allocation already have the
1880 // previous data, but the is_initial flag not be cleared. We need to clear
1881 // here to avoid make duplicated target allocation stream map.
1882 offloader_streams_target_allocation->clear();
1883 }
1884
1885 offloader_streams_current_allocation->clear();
1886 *changed_flag = true;
1887 bool not_all_cises_connected = false;
1888 if (available_allocations != codec_spec_conf::kLeAudioLocationStereo) {
1889 not_all_cises_connected = true;
1890 }
1891
1892 /* If the all cises are connected as stream started, reset changed_flag that
1893 * the bt stack wouldn't send another audio configuration for the connection
1894 * status */
1895 if (*is_initial && !not_all_cises_connected) {
1896 *changed_flag = false;
1897 }
1898 for (auto& cis_entry : cises_) {
1899 if ((cis_entry.type == CisType::CIS_TYPE_BIDIRECTIONAL ||
1900 cis_entry.type == cis_type) &&
1901 cis_entry.conn_handle != 0) {
1902 uint32_t target_allocation = 0;
1903 uint32_t current_allocation = 0;
1904 bool is_active = false;
1905 for (const auto& s : *streams) {
1906 if (s.first == cis_entry.conn_handle) {
1907 is_active = true;
1908 target_allocation = AdjustAllocationForOffloader(s.second);
1909 current_allocation = target_allocation;
1910 if (not_all_cises_connected) {
1911 /* Tell offloader to mix on this CIS.*/
1912 current_allocation = codec_spec_conf::kLeAudioLocationStereo;
1913 }
1914 break;
1915 }
1916 }
1917
1918 if (target_allocation == 0) {
1919 /* Take missing allocation for that one .*/
1920 target_allocation =
1921 codec_spec_conf::kLeAudioLocationStereo & ~available_allocations;
1922 }
1923
1924 LOG_INFO(
1925 "%s: Cis handle 0x%04x, target allocation 0x%08x, current "
1926 "allocation 0x%08x, active: %d",
1927 tag.c_str(), cis_entry.conn_handle, target_allocation,
1928 current_allocation, is_active);
1929
1930 if (*is_initial || CodecManager::GetInstance()->GetAidlVersionInUsed() >=
1931 AIDL_VERSION_SUPPORT_STREAM_ACTIVE) {
1932 offloader_streams_target_allocation->emplace_back(stream_map_info(
1933 cis_entry.conn_handle, target_allocation, is_active));
1934 }
1935 offloader_streams_current_allocation->emplace_back(stream_map_info(
1936 cis_entry.conn_handle, current_allocation, is_active));
1937 }
1938 }
1939 }
1940
IsPendingConfiguration(void)1941 bool LeAudioDeviceGroup::IsPendingConfiguration(void) {
1942 return stream_conf.pending_configuration;
1943 }
1944
SetPendingConfiguration(void)1945 void LeAudioDeviceGroup::SetPendingConfiguration(void) {
1946 stream_conf.pending_configuration = true;
1947 }
1948
ClearPendingConfiguration(void)1949 void LeAudioDeviceGroup::ClearPendingConfiguration(void) {
1950 stream_conf.pending_configuration = false;
1951 }
1952
Disable(int gatt_if)1953 void LeAudioDeviceGroup::Disable(int gatt_if) {
1954 enabled_ = false;
1955
1956 for (auto& device_iter : leAudioDevices_) {
1957 if (!device_iter.lock()->autoconnect_flag_) {
1958 continue;
1959 }
1960
1961 auto connection_state = device_iter.lock()->GetConnectionState();
1962 auto address = device_iter.lock()->address_;
1963
1964 btif_storage_set_leaudio_autoconnect(address, false);
1965 device_iter.lock()->autoconnect_flag_ = false;
1966
1967 LOG_INFO("Group %d in state %s. Removing %s from background connect",
1968 group_id_, bluetooth::common::ToString(GetState()).c_str(),
1969 ADDRESS_TO_LOGGABLE_CSTR(address));
1970
1971 BTA_GATTC_CancelOpen(gatt_if, address, false);
1972
1973 if (connection_state == DeviceConnectState::CONNECTING_AUTOCONNECT) {
1974 device_iter.lock()->SetConnectionState(DeviceConnectState::DISCONNECTED);
1975 }
1976 }
1977 }
1978
Enable(int gatt_if,tBTM_BLE_CONN_TYPE reconnection_mode)1979 void LeAudioDeviceGroup::Enable(int gatt_if,
1980 tBTM_BLE_CONN_TYPE reconnection_mode) {
1981 enabled_ = true;
1982 for (auto& device_iter : leAudioDevices_) {
1983 if (device_iter.lock()->autoconnect_flag_) {
1984 continue;
1985 }
1986
1987 auto address = device_iter.lock()->address_;
1988 auto connection_state = device_iter.lock()->GetConnectionState();
1989
1990 btif_storage_set_leaudio_autoconnect(address, true);
1991 device_iter.lock()->autoconnect_flag_ = true;
1992
1993 LOG_INFO("Group %d in state %s. Adding %s from background connect",
1994 group_id_, bluetooth::common::ToString(GetState()).c_str(),
1995 ADDRESS_TO_LOGGABLE_CSTR(address));
1996
1997 if (connection_state == DeviceConnectState::DISCONNECTED) {
1998 BTA_GATTC_Open(gatt_if, address, reconnection_mode, false);
1999 device_iter.lock()->SetConnectionState(
2000 DeviceConnectState::CONNECTING_AUTOCONNECT);
2001 }
2002 }
2003 }
2004
IsEnabled(void)2005 bool LeAudioDeviceGroup::IsEnabled(void) { return enabled_; };
2006
AddToAllowListNotConnectedGroupMembers(int gatt_if)2007 void LeAudioDeviceGroup::AddToAllowListNotConnectedGroupMembers(int gatt_if) {
2008 for (const auto& device_iter : leAudioDevices_) {
2009 auto connection_state = device_iter.lock()->GetConnectionState();
2010 if (connection_state == DeviceConnectState::CONNECTED ||
2011 connection_state == DeviceConnectState::CONNECTING_BY_USER ||
2012 connection_state ==
2013 DeviceConnectState::CONNECTED_BY_USER_GETTING_READY ||
2014 connection_state ==
2015 DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY) {
2016 continue;
2017 }
2018
2019 auto address = device_iter.lock()->address_;
2020 LOG_INFO("Group %d in state %s. Adding %s to allow list ", group_id_,
2021 bluetooth::common::ToString(GetState()).c_str(),
2022 ADDRESS_TO_LOGGABLE_CSTR(address));
2023
2024 BTA_GATTC_CancelOpen(gatt_if, address, false);
2025 BTA_GATTC_Open(gatt_if, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
2026 device_iter.lock()->SetConnectionState(
2027 DeviceConnectState::CONNECTING_AUTOCONNECT);
2028 }
2029 }
2030
IsConfigurationSupported(LeAudioDevice * leAudioDevice,const set_configurations::AudioSetConfiguration * audio_set_conf)2031 bool LeAudioDeviceGroup::IsConfigurationSupported(
2032 LeAudioDevice* leAudioDevice,
2033 const set_configurations::AudioSetConfiguration* audio_set_conf) {
2034 for (const auto& ent : (*audio_set_conf).confs) {
2035 LOG_INFO("Looking for requirements: %s - %s", audio_set_conf->name.c_str(),
2036 (ent.direction == 1 ? "snk" : "src"));
2037 auto pac = leAudioDevice->GetCodecConfigurationSupportedPac(ent.direction,
2038 ent.codec);
2039 if (pac != nullptr) {
2040 LOG_INFO("Configuration is supported by device %s",
2041 ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
2042 return true;
2043 }
2044 }
2045
2046 LOG_INFO("Configuration is NOT supported by device %s",
2047 ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_));
2048 return false;
2049 }
2050
2051 const set_configurations::AudioSetConfiguration*
FindFirstSupportedConfiguration(LeAudioContextType context_type)2052 LeAudioDeviceGroup::FindFirstSupportedConfiguration(
2053 LeAudioContextType context_type) {
2054 const set_configurations::AudioSetConfigurations* confs =
2055 AudioSetConfigurationProvider::Get()->GetConfigurations(context_type);
2056
2057 LOG_DEBUG("context type: %s, number of connected devices: %d",
2058 bluetooth::common::ToString(context_type).c_str(),
2059 +NumOfConnected());
2060
2061 /* Filter out device set for all scenarios */
2062 if (!set_configurations::check_if_may_cover_scenario(confs,
2063 NumOfConnected())) {
2064 LOG_DEBUG(", group is unable to cover scenario");
2065 return nullptr;
2066 }
2067
2068 /* Filter out device set for each end every scenario */
2069
2070 auto required_snk_strategy = GetGroupStrategy(Size());
2071 for (const auto& conf : *confs) {
2072 if (IsConfigurationSupported(conf, context_type, required_snk_strategy)) {
2073 LOG_DEBUG("found: %s", conf->name.c_str());
2074 return conf;
2075 }
2076 }
2077
2078 return nullptr;
2079 }
2080
2081 /* This method should choose aproperiate ASEs to be active and set a cached
2082 * configuration for codec and qos.
2083 */
Configure(LeAudioContextType context_type,const types::BidirectionalPair<AudioContexts> & metadata_context_types,types::BidirectionalPair<std::vector<uint8_t>> ccid_lists)2084 bool LeAudioDeviceGroup::Configure(
2085 LeAudioContextType context_type,
2086 const types::BidirectionalPair<AudioContexts>& metadata_context_types,
2087 types::BidirectionalPair<std::vector<uint8_t>> ccid_lists) {
2088 const set_configurations::AudioSetConfiguration* conf =
2089 available_context_to_configuration_map[context_type];
2090
2091 if (!conf) {
2092 LOG_ERROR(
2093 ", requested context type: %s , is in mismatch with cached available "
2094 "contexts ",
2095 bluetooth::common::ToString(context_type).c_str());
2096 return false;
2097 }
2098
2099 LOG_DEBUG(" setting context type: %s",
2100 bluetooth::common::ToString(context_type).c_str());
2101
2102 if (!ConfigureAses(conf, context_type, metadata_context_types, ccid_lists)) {
2103 LOG_ERROR(
2104 ", requested context type: %s , is in mismatch with cached available "
2105 "contexts",
2106 bluetooth::common::ToString(context_type).c_str());
2107 return false;
2108 }
2109
2110 /* Store selected configuration at once it is chosen.
2111 * It might happen it will get unavailable in some point of time
2112 */
2113 stream_conf.conf = conf;
2114 return true;
2115 }
2116
~LeAudioDeviceGroup(void)2117 LeAudioDeviceGroup::~LeAudioDeviceGroup(void) { this->Cleanup(); }
2118
PrintDebugState(void)2119 void LeAudioDeviceGroup::PrintDebugState(void) {
2120 auto* active_conf = GetActiveConfiguration();
2121 std::stringstream debug_str;
2122
2123 debug_str << "\n Groupd id: " << group_id_
2124 << (enabled_ ? " enabled" : " disabled")
2125 << ", state: " << bluetooth::common::ToString(GetState())
2126 << ", target state: "
2127 << bluetooth::common::ToString(GetTargetState())
2128 << ", cig state: " << bluetooth::common::ToString(cig_state_)
2129 << ", \n group available contexts: "
2130 << bluetooth::common::ToString(GetAvailableContexts())
2131 << ", \n configuration context type: "
2132 << bluetooth::common::ToString(GetConfigurationContextType())
2133 << ", \n active configuration name: "
2134 << (active_conf ? active_conf->name : " not set");
2135
2136 if (cises_.size() > 0) {
2137 LOG_INFO("\n Allocated CISes: %d", static_cast<int>(cises_.size()));
2138 for (auto cis : cises_) {
2139 LOG_INFO("\n cis id: %d, type: %d, conn_handle %d, addr: %s", cis.id,
2140 cis.type, cis.conn_handle, cis.addr.ToString().c_str());
2141 }
2142 }
2143
2144 if (GetFirstActiveDevice() != nullptr) {
2145 uint32_t sink_delay = 0;
2146 uint32_t source_delay = 0;
2147 GetPresentationDelay(&sink_delay, le_audio::types::kLeAudioDirectionSink);
2148 GetPresentationDelay(&source_delay,
2149 le_audio::types::kLeAudioDirectionSource);
2150 auto phy_mtos = GetPhyBitmask(le_audio::types::kLeAudioDirectionSink);
2151 auto phy_stom = GetPhyBitmask(le_audio::types::kLeAudioDirectionSource);
2152 auto max_transport_latency_mtos = GetMaxTransportLatencyMtos();
2153 auto max_transport_latency_stom = GetMaxTransportLatencyStom();
2154 auto sdu_mts = GetSduInterval(le_audio::types::kLeAudioDirectionSink);
2155 auto sdu_stom = GetSduInterval(le_audio::types::kLeAudioDirectionSource);
2156
2157 debug_str << "\n presentation_delay for sink (speaker): " << +sink_delay
2158 << " us, presentation_delay for source (microphone): "
2159 << +source_delay << "us, \n MtoS transport latency: "
2160 << +max_transport_latency_mtos
2161 << ", StoM transport latency: " << +max_transport_latency_stom
2162 << ", \n MtoS Phy: " << loghex(phy_mtos)
2163 << ", MtoS sdu: " << loghex(phy_stom)
2164 << " \n MtoS sdu: " << +sdu_mts << ", StoM sdu: " << +sdu_stom;
2165 }
2166
2167 LOG_INFO("%s", debug_str.str().c_str());
2168
2169 for (const auto& device_iter : leAudioDevices_) {
2170 device_iter.lock()->PrintDebugState();
2171 }
2172 }
2173
Dump(int fd,int active_group_id)2174 void LeAudioDeviceGroup::Dump(int fd, int active_group_id) {
2175 bool is_active = (group_id_ == active_group_id);
2176 std::stringstream stream, stream_pacs;
2177 auto* active_conf = GetActiveConfiguration();
2178
2179 stream << "\n == Group id: " << group_id_
2180 << (enabled_ ? " enabled" : " disabled")
2181 << " == " << (is_active ? ",\tActive\n" : ",\tInactive\n")
2182 << " state: " << GetState()
2183 << ",\ttarget state: " << GetTargetState()
2184 << ",\tcig state: " << cig_state_ << "\n"
2185 << " group available contexts: " << GetAvailableContexts() << "\n"
2186 << " configuration context type: "
2187 << bluetooth::common::ToString(GetConfigurationContextType()).c_str()
2188 << "\n"
2189 << " active configuration name: "
2190 << (active_conf ? active_conf->name : " not set") << "\n"
2191 << " stream configuration: "
2192 << (stream_conf.conf != nullptr ? stream_conf.conf->name : " unknown ")
2193 << "\n"
2194 << " codec id: " << +(stream_conf.id.coding_format)
2195 << ",\tpending_configuration: " << stream_conf.pending_configuration
2196 << "\n"
2197 << " num of devices(connected): " << Size() << "("
2198 << NumOfConnected() << ")\n"
2199 << ", num of sinks(connected): " << stream_conf.sink_num_of_devices
2200 << "(" << stream_conf.sink_streams.size() << ")\n"
2201 << " num of sources(connected): "
2202 << stream_conf.source_num_of_devices << "("
2203 << stream_conf.source_streams.size() << ")\n"
2204 << " allocated CISes: " << static_cast<int>(cises_.size());
2205
2206 if (cises_.size() > 0) {
2207 stream << "\n\t == CISes == ";
2208 for (auto cis : cises_) {
2209 stream << "\n\t cis id: " << static_cast<int>(cis.id)
2210 << ",\ttype: " << static_cast<int>(cis.type)
2211 << ",\tconn_handle: " << static_cast<int>(cis.conn_handle)
2212 << ",\taddr: " << ADDRESS_TO_LOGGABLE_STR(cis.addr);
2213 }
2214 stream << "\n\t ====";
2215 }
2216
2217 if (GetFirstActiveDevice() != nullptr) {
2218 uint32_t sink_delay;
2219 if (GetPresentationDelay(&sink_delay,
2220 le_audio::types::kLeAudioDirectionSink)) {
2221 stream << "\n presentation_delay for sink (speaker): " << sink_delay
2222 << " us";
2223 }
2224
2225 uint32_t source_delay;
2226 if (GetPresentationDelay(&source_delay,
2227 le_audio::types::kLeAudioDirectionSource)) {
2228 stream << "\n presentation_delay for source (microphone): "
2229 << source_delay << " us";
2230 }
2231 }
2232
2233 stream << "\n == devices: ==";
2234
2235 dprintf(fd, "%s", stream.str().c_str());
2236
2237 for (const auto& device_iter : leAudioDevices_) {
2238 device_iter.lock()->Dump(fd);
2239 }
2240
2241 for (const auto& device_iter : leAudioDevices_) {
2242 auto device = device_iter.lock();
2243 stream_pacs << "\n\taddress: " << device->address_;
2244 device->DumpPacsDebugState(stream_pacs);
2245 }
2246 dprintf(fd, "%s", stream_pacs.str().c_str());
2247 }
2248
2249 /* LeAudioDevice Class methods implementation */
SetConnectionState(DeviceConnectState state)2250 void LeAudioDevice::SetConnectionState(DeviceConnectState state) {
2251 LOG_DEBUG("%s, %s --> %s", ADDRESS_TO_LOGGABLE_CSTR(address_),
2252 bluetooth::common::ToString(connection_state_).c_str(),
2253 bluetooth::common::ToString(state).c_str());
2254 LeAudioLogHistory::Get()->AddLogHistory(
2255 kLogConnectionTag, group_id_, address_,
2256 bluetooth::common::ToString(connection_state_) + " -> ",
2257 "->" + bluetooth::common::ToString(state));
2258 connection_state_ = state;
2259 }
2260
GetConnectionState(void)2261 DeviceConnectState LeAudioDevice::GetConnectionState(void) {
2262 return connection_state_;
2263 }
2264
ClearPACs(void)2265 void LeAudioDevice::ClearPACs(void) {
2266 snk_pacs_.clear();
2267 src_pacs_.clear();
2268 }
2269
~LeAudioDevice(void)2270 LeAudioDevice::~LeAudioDevice(void) {
2271 alarm_free(link_quality_timer);
2272 this->ClearPACs();
2273 }
2274
RegisterPACs(std::vector<struct types::acs_ac_record> * pac_db,std::vector<struct types::acs_ac_record> * pac_recs)2275 void LeAudioDevice::RegisterPACs(
2276 std::vector<struct types::acs_ac_record>* pac_db,
2277 std::vector<struct types::acs_ac_record>* pac_recs) {
2278 /* Clear PAC database for characteristic in case if re-read, indicated */
2279 if (!pac_db->empty()) {
2280 DLOG(INFO) << __func__ << ", upgrade PACs for characteristic";
2281 pac_db->clear();
2282 }
2283
2284 /* TODO wrap this logging part with debug flag */
2285 for (const struct types::acs_ac_record& pac : *pac_recs) {
2286 LOG(INFO) << "Registering PAC"
2287 << "\n\tCoding format: " << loghex(pac.codec_id.coding_format)
2288 << "\n\tVendor codec company ID: "
2289 << loghex(pac.codec_id.vendor_company_id)
2290 << "\n\tVendor codec ID: " << loghex(pac.codec_id.vendor_codec_id)
2291 << "\n\tCodec spec caps:\n"
2292 << pac.codec_spec_caps.ToString("",
2293 types::CodecCapabilitiesLtvFormat)
2294 << "\n\tMetadata: "
2295 << base::HexEncode(pac.metadata.data(), pac.metadata.size());
2296 }
2297
2298 pac_db->insert(pac_db->begin(), pac_recs->begin(), pac_recs->end());
2299 }
2300
GetAseByValHandle(uint16_t val_hdl)2301 struct ase* LeAudioDevice::GetAseByValHandle(uint16_t val_hdl) {
2302 auto iter = std::find_if(
2303 ases_.begin(), ases_.end(),
2304 [&val_hdl](const auto& ase) { return ase.hdls.val_hdl == val_hdl; });
2305
2306 return (iter == ases_.end()) ? nullptr : &(*iter);
2307 }
2308
GetAseCount(uint8_t direction)2309 int LeAudioDevice::GetAseCount(uint8_t direction) {
2310 return std::count_if(ases_.begin(), ases_.end(), [direction](const auto& a) {
2311 return a.direction == direction;
2312 });
2313 }
2314
GetFirstAseWithState(uint8_t direction,AseState state)2315 struct ase* LeAudioDevice::GetFirstAseWithState(uint8_t direction,
2316 AseState state) {
2317 auto iter = std::find_if(
2318 ases_.begin(), ases_.end(), [direction, state](const auto& ase) {
2319 return ((ase.direction == direction) && (ase.state == state));
2320 });
2321
2322 return (iter == ases_.end()) ? nullptr : &(*iter);
2323 }
2324
GetFirstActiveAse(void)2325 struct ase* LeAudioDevice::GetFirstActiveAse(void) {
2326 auto iter = std::find_if(ases_.begin(), ases_.end(),
2327 [](const auto& ase) { return ase.active; });
2328
2329 return (iter == ases_.end()) ? nullptr : &(*iter);
2330 }
2331
GetFirstActiveAseByDirection(uint8_t direction)2332 struct ase* LeAudioDevice::GetFirstActiveAseByDirection(uint8_t direction) {
2333 auto iter =
2334 std::find_if(ases_.begin(), ases_.end(), [direction](const auto& ase) {
2335 return (ase.active && (ase.direction == direction));
2336 });
2337
2338 return (iter == ases_.end()) ? nullptr : &(*iter);
2339 }
2340
GetNextActiveAseWithSameDirection(struct ase * base_ase)2341 struct ase* LeAudioDevice::GetNextActiveAseWithSameDirection(
2342 struct ase* base_ase) {
2343 auto iter = std::find_if(ases_.begin(), ases_.end(),
2344 [&base_ase](auto& ase) { return base_ase == &ase; });
2345
2346 /* Invalid ase given */
2347 if (iter == ases_.end() || std::distance(iter, ases_.end()) < 1)
2348 return nullptr;
2349
2350 iter =
2351 std::find_if(std::next(iter, 1), ases_.end(), [&iter](const auto& ase) {
2352 return ase.active && (*iter).direction == ase.direction;
2353 });
2354
2355 return (iter == ases_.end()) ? nullptr : &(*iter);
2356 }
2357
GetNextActiveAseWithDifferentDirection(struct ase * base_ase)2358 struct ase* LeAudioDevice::GetNextActiveAseWithDifferentDirection(
2359 struct ase* base_ase) {
2360 auto iter = std::find_if(ases_.begin(), ases_.end(),
2361 [&base_ase](auto& ase) { return base_ase == &ase; });
2362
2363 /* Invalid ase given */
2364 if (std::distance(iter, ases_.end()) < 1) {
2365 LOG_DEBUG("ASE %d does not use bidirectional CIS", base_ase->id);
2366 return nullptr;
2367 }
2368
2369 iter =
2370 std::find_if(std::next(iter, 1), ases_.end(), [&iter](const auto& ase) {
2371 return ase.active && iter->direction != ase.direction;
2372 });
2373
2374 if (iter == ases_.end()) {
2375 return nullptr;
2376 }
2377
2378 return &(*iter);
2379 }
2380
GetFirstActiveAseByDataPathState(types::AudioStreamDataPathState state)2381 struct ase* LeAudioDevice::GetFirstActiveAseByDataPathState(
2382 types::AudioStreamDataPathState state) {
2383 auto iter =
2384 std::find_if(ases_.begin(), ases_.end(), [state](const auto& ase) {
2385 return (ase.active && (ase.data_path_state == state));
2386 });
2387
2388 return (iter == ases_.end()) ? nullptr : &(*iter);
2389 }
2390
GetFirstInactiveAse(uint8_t direction,bool reuse_cis_id)2391 struct ase* LeAudioDevice::GetFirstInactiveAse(uint8_t direction,
2392 bool reuse_cis_id) {
2393 auto iter = std::find_if(ases_.begin(), ases_.end(),
2394 [direction, reuse_cis_id](const auto& ase) {
2395 if (ase.active || (ase.direction != direction))
2396 return false;
2397
2398 if (!reuse_cis_id) return true;
2399
2400 return (ase.cis_id != kInvalidCisId);
2401 });
2402 /* If ASE is found, return it */
2403 if (iter != ases_.end()) return &(*iter);
2404
2405 /* If reuse was not set, that means there is no inactive ASE available. */
2406 if (!reuse_cis_id) return nullptr;
2407
2408 /* Since there is no ASE with assigned CIS ID, it means new configuration
2409 * needs more ASEs then it was configured before.
2410 * Let's find just inactive one */
2411 iter = std::find_if(ases_.begin(), ases_.end(),
2412 [direction](const auto& ase) {
2413 if (ase.active || (ase.direction != direction))
2414 return false;
2415 return true;
2416 });
2417
2418 return (iter == ases_.end()) ? nullptr : &(*iter);
2419 }
2420
GetNextActiveAse(struct ase * base_ase)2421 struct ase* LeAudioDevice::GetNextActiveAse(struct ase* base_ase) {
2422 auto iter = std::find_if(ases_.begin(), ases_.end(),
2423 [&base_ase](auto& ase) { return base_ase == &ase; });
2424
2425 /* Invalid ase given */
2426 if (iter == ases_.end() || std::distance(iter, ases_.end()) < 1)
2427 return nullptr;
2428
2429 iter = std::find_if(std::next(iter, 1), ases_.end(),
2430 [](const auto& ase) { return ase.active; });
2431
2432 return (iter == ases_.end()) ? nullptr : &(*iter);
2433 }
2434
GetAseToMatchBidirectionCis(struct ase * base_ase)2435 struct ase* LeAudioDevice::GetAseToMatchBidirectionCis(struct ase* base_ase) {
2436 auto iter = std::find_if(ases_.begin(), ases_.end(), [&base_ase](auto& ase) {
2437 return (base_ase->cis_conn_hdl == ase.cis_conn_hdl) &&
2438 (base_ase->direction != ase.direction);
2439 });
2440 return (iter == ases_.end()) ? nullptr : &(*iter);
2441 }
2442
GetAsesByCisConnHdl(uint16_t conn_hdl)2443 BidirectAsesPair LeAudioDevice::GetAsesByCisConnHdl(uint16_t conn_hdl) {
2444 BidirectAsesPair ases = {nullptr, nullptr};
2445
2446 for (auto& ase : ases_) {
2447 if (ase.cis_conn_hdl == conn_hdl) {
2448 if (ase.direction == types::kLeAudioDirectionSink) {
2449 ases.sink = &ase;
2450 } else {
2451 ases.source = &ase;
2452 }
2453 }
2454 }
2455
2456 return ases;
2457 }
2458
GetAsesByCisId(uint8_t cis_id)2459 BidirectAsesPair LeAudioDevice::GetAsesByCisId(uint8_t cis_id) {
2460 BidirectAsesPair ases = {nullptr, nullptr};
2461
2462 for (auto& ase : ases_) {
2463 if (ase.cis_id == cis_id) {
2464 if (ase.direction == types::kLeAudioDirectionSink) {
2465 ases.sink = &ase;
2466 } else {
2467 ases.source = &ase;
2468 }
2469 }
2470 }
2471
2472 return ases;
2473 }
2474
HaveActiveAse(void)2475 bool LeAudioDevice::HaveActiveAse(void) {
2476 auto iter = std::find_if(ases_.begin(), ases_.end(),
2477 [](const auto& ase) { return ase.active; });
2478
2479 return iter != ases_.end();
2480 }
2481
HaveAnyUnconfiguredAses(void)2482 bool LeAudioDevice::HaveAnyUnconfiguredAses(void) {
2483 /* In configuring state when active in Idle or Configured and reconfigure */
2484 auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
2485 if (!ase.active) return false;
2486
2487 if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE ||
2488 ((ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) &&
2489 ase.reconfigure))
2490 return true;
2491
2492 return false;
2493 });
2494
2495 return iter != ases_.end();
2496 }
2497
HaveAllActiveAsesSameState(AseState state)2498 bool LeAudioDevice::HaveAllActiveAsesSameState(AseState state) {
2499 auto iter = std::find_if(
2500 ases_.begin(), ases_.end(),
2501 [&state](const auto& ase) { return ase.active && (ase.state != state); });
2502
2503 return iter == ases_.end();
2504 }
2505
IsReadyToCreateStream(void)2506 bool LeAudioDevice::IsReadyToCreateStream(void) {
2507 auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
2508 if (!ase.active) return false;
2509
2510 if (ase.direction == types::kLeAudioDirectionSink &&
2511 (ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING &&
2512 ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING))
2513 return true;
2514
2515 if (ase.direction == types::kLeAudioDirectionSource &&
2516 ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING)
2517 return true;
2518
2519 return false;
2520 });
2521
2522 return iter == ases_.end();
2523 }
2524
IsReadyToSuspendStream(void)2525 bool LeAudioDevice::IsReadyToSuspendStream(void) {
2526 auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
2527 if (!ase.active) return false;
2528
2529 if (ase.direction == types::kLeAudioDirectionSink &&
2530 ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED)
2531 return true;
2532
2533 if (ase.direction == types::kLeAudioDirectionSource &&
2534 ase.state != AseState::BTA_LE_AUDIO_ASE_STATE_DISABLING)
2535 return true;
2536
2537 return false;
2538 });
2539
2540 return iter == ases_.end();
2541 }
2542
HaveAllActiveAsesCisEst(void)2543 bool LeAudioDevice::HaveAllActiveAsesCisEst(void) {
2544 if (ases_.empty()) {
2545 LOG_WARN("No ases for device %s", ADDRESS_TO_LOGGABLE_CSTR(address_));
2546 return false;
2547 }
2548
2549 auto iter = std::find_if(ases_.begin(), ases_.end(), [](const auto& ase) {
2550 return ase.active &&
2551 (ase.data_path_state != AudioStreamDataPathState::CIS_ESTABLISHED);
2552 });
2553
2554 return iter == ases_.end();
2555 }
2556
HaveAnyCisConnected(void)2557 bool LeAudioDevice::HaveAnyCisConnected(void) {
2558 /* Pending and Disconnecting is considered as connected in this function */
2559 for (auto const ase : ases_) {
2560 if (ase.data_path_state != AudioStreamDataPathState::CIS_ASSIGNED &&
2561 ase.data_path_state != AudioStreamDataPathState::IDLE) {
2562 return true;
2563 }
2564 }
2565 return false;
2566 }
2567
HasCisId(uint8_t id)2568 bool LeAudioDevice::HasCisId(uint8_t id) {
2569 struct ase* ase = GetFirstActiveAse();
2570
2571 while (ase) {
2572 if (ase->cis_id == id) return true;
2573 ase = GetNextActiveAse(ase);
2574 }
2575
2576 return false;
2577 }
2578
GetMatchingBidirectionCisId(const struct types::ase * base_ase)2579 uint8_t LeAudioDevice::GetMatchingBidirectionCisId(
2580 const struct types::ase* base_ase) {
2581 for (auto& ase : ases_) {
2582 auto& cis = ase.cis_id;
2583 if (!ase.active) continue;
2584
2585 int num_cises =
2586 std::count_if(ases_.begin(), ases_.end(), [&cis](const auto& iter_ase) {
2587 return iter_ase.active && iter_ase.cis_id == cis;
2588 });
2589
2590 /*
2591 * If there is only one ASE for device with unique CIS ID and opposite to
2592 * direction - it may be bi-directional/completive.
2593 */
2594 if (num_cises == 1 &&
2595 ((base_ase->direction == types::kLeAudioDirectionSink &&
2596 ase.direction == types::kLeAudioDirectionSource) ||
2597 (base_ase->direction == types::kLeAudioDirectionSource &&
2598 ase.direction == types::kLeAudioDirectionSink))) {
2599 return ase.cis_id;
2600 }
2601 }
2602
2603 return kInvalidCisId;
2604 }
2605
GetLc3SupportedChannelCount(uint8_t direction)2606 uint8_t LeAudioDevice::GetLc3SupportedChannelCount(uint8_t direction) {
2607 auto& pacs =
2608 direction == types::kLeAudioDirectionSink ? snk_pacs_ : src_pacs_;
2609
2610 if (pacs.size() == 0) {
2611 LOG(ERROR) << __func__ << " missing PAC for direction " << +direction;
2612 return 0;
2613 }
2614
2615 for (const auto& pac_tuple : pacs) {
2616 /* Get PAC records from tuple as second element from tuple */
2617 auto& pac_recs = std::get<1>(pac_tuple);
2618
2619 for (const auto pac : pac_recs) {
2620 if (pac.codec_id.coding_format != types::kLeAudioCodingFormatLC3)
2621 continue;
2622
2623 auto supported_channel_count_ltv = pac.codec_spec_caps.Find(
2624 codec_spec_caps::kLeAudioCodecLC3TypeAudioChannelCounts);
2625
2626 if (supported_channel_count_ltv == std::nullopt ||
2627 supported_channel_count_ltv->size() == 0L) {
2628 return 1;
2629 }
2630
2631 return VEC_UINT8_TO_UINT8(supported_channel_count_ltv.value());
2632 };
2633 }
2634
2635 return 0;
2636 }
2637
2638 const struct types::acs_ac_record*
GetCodecConfigurationSupportedPac(uint8_t direction,const CodecCapabilitySetting & codec_capability_setting)2639 LeAudioDevice::GetCodecConfigurationSupportedPac(
2640 uint8_t direction, const CodecCapabilitySetting& codec_capability_setting) {
2641 auto& pacs =
2642 direction == types::kLeAudioDirectionSink ? snk_pacs_ : src_pacs_;
2643
2644 if (pacs.size() == 0) {
2645 LOG_ERROR("missing PAC for direction %d", direction);
2646 return nullptr;
2647 }
2648
2649 /* TODO: Validate channel locations */
2650
2651 for (const auto& pac_tuple : pacs) {
2652 /* Get PAC records from tuple as second element from tuple */
2653 auto& pac_recs = std::get<1>(pac_tuple);
2654
2655 for (const auto& pac : pac_recs) {
2656 if (!IsCodecCapabilitySettingSupported(pac, codec_capability_setting))
2657 continue;
2658
2659 return &pac;
2660 };
2661 }
2662
2663 /* Doesn't match required configuration with any PAC */
2664 return nullptr;
2665 }
2666
2667 /**
2668 * Returns supported PHY's bitfield
2669 */
GetPhyBitmask(void)2670 uint8_t LeAudioDevice::GetPhyBitmask(void) {
2671 uint8_t phy_bitfield = kIsoCigPhy1M;
2672
2673 if (BTM_IsPhy2mSupported(address_, BT_TRANSPORT_LE))
2674 phy_bitfield |= kIsoCigPhy2M;
2675
2676 return phy_bitfield;
2677 }
2678
SetSupportedContexts(AudioContexts snk_contexts,AudioContexts src_contexts)2679 void LeAudioDevice::SetSupportedContexts(AudioContexts snk_contexts,
2680 AudioContexts src_contexts) {
2681 supp_contexts_.sink = snk_contexts;
2682 supp_contexts_.source = src_contexts;
2683 }
2684
PrintDebugState(void)2685 void LeAudioDevice::PrintDebugState(void) {
2686 std::stringstream debug_str;
2687
2688 debug_str << " address: " << address_ << ", "
2689 << bluetooth::common::ToString(connection_state_)
2690 << ", conn_id: " << +conn_id_ << ", mtu: " << +mtu_
2691 << ", num_of_ase: " << static_cast<int>(ases_.size());
2692
2693 if (ases_.size() > 0) {
2694 debug_str << "\n == ASEs == ";
2695 for (auto& ase : ases_) {
2696 debug_str << "\n id: " << +ase.id << ", active: " << ase.active
2697 << ", dir: "
2698 << (ase.direction == types::kLeAudioDirectionSink ? "sink"
2699 : "source")
2700 << ", cis_id: " << +ase.cis_id
2701 << ", cis_handle: " << +ase.cis_conn_hdl << ", state: "
2702 << bluetooth::common::ToString(ase.data_path_state)
2703 << "\n ase max_latency: " << +ase.max_transport_latency
2704 << ", rtn: " << +ase.retrans_nb
2705 << ", max_sdu: " << +ase.max_sdu_size
2706 << ", target latency: " << +ase.target_latency;
2707 }
2708 }
2709
2710 LOG_INFO("%s", debug_str.str().c_str());
2711 }
2712
DumpPacsDebugState(std::stringstream & stream,types::PublishedAudioCapabilities pacs)2713 void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream,
2714 types::PublishedAudioCapabilities pacs) {
2715 if (pacs.size() > 0) {
2716 for (auto& pac : pacs) {
2717 stream << "\n\t\tvalue handle: " << loghex(std::get<0>(pac).val_hdl)
2718 << " / CCC handle: " << loghex(std::get<0>(pac).ccc_hdl);
2719
2720 for (auto& record : std::get<1>(pac)) {
2721 stream << "\n\n\t\tCodecId(Coding format: "
2722 << static_cast<int>(record.codec_id.coding_format)
2723 << ", Vendor company ID: "
2724 << static_cast<int>(record.codec_id.vendor_company_id)
2725 << ", Vendor codec ID: "
2726 << static_cast<int>(record.codec_id.vendor_codec_id) << ")";
2727 stream << "\n\t\tCodec specific capabilities:\n"
2728 << record.codec_spec_caps.ToString(
2729 "\t\t\t", types::CodecCapabilitiesLtvFormat);
2730 stream << "\t\tMetadata: "
2731 << base::HexEncode(record.metadata.data(),
2732 record.metadata.size());
2733 }
2734 }
2735 }
2736 }
2737
DumpPacsDebugState(std::stringstream & stream)2738 void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream) {
2739 stream << "\n\tSink PACs";
2740 DumpPacsDebugState(stream, snk_pacs_);
2741 stream << "\n\tSource PACs";
2742 DumpPacsDebugState(stream, src_pacs_);
2743 }
2744
Dump(int fd)2745 void LeAudioDevice::Dump(int fd) {
2746 uint16_t acl_handle = BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE);
2747 std::string location = "unknown location";
2748
2749 if (snk_audio_locations_.to_ulong() &
2750 codec_spec_conf::kLeAudioLocationAnyLeft &&
2751 snk_audio_locations_.to_ulong() &
2752 codec_spec_conf::kLeAudioLocationAnyRight) {
2753 std::string location_left_right = "left/right";
2754 location.swap(location_left_right);
2755 } else if (snk_audio_locations_.to_ulong() &
2756 codec_spec_conf::kLeAudioLocationAnyLeft) {
2757 std::string location_left = "left";
2758 location.swap(location_left);
2759 } else if (snk_audio_locations_.to_ulong() &
2760 codec_spec_conf::kLeAudioLocationAnyRight) {
2761 std::string location_right = "right";
2762 location.swap(location_right);
2763 }
2764
2765 std::stringstream stream;
2766 stream << "\n\taddress: " << ADDRESS_TO_LOGGABLE_STR(address_) << ": "
2767 << connection_state_ << ": "
2768 << (conn_id_ == GATT_INVALID_CONN_ID ? "" : std::to_string(conn_id_))
2769 << ", acl_handle: " << std::to_string(acl_handle) << ", " << location
2770 << ",\t" << (encrypted_ ? "Encrypted" : "Unecrypted")
2771 << ",mtu: " << std::to_string(mtu_)
2772 << "\n\tnumber of ases_: " << static_cast<int>(ases_.size());
2773
2774 if (ases_.size() > 0) {
2775 stream << "\n\t== ASEs == \n\t";
2776 stream
2777 << "id active dir cis_id cis_handle sdu latency rtn state";
2778 for (auto& ase : ases_) {
2779 stream << std::setfill('\x20') << "\n\t" << std::left << std::setw(4)
2780 << static_cast<int>(ase.id) << std::left << std::setw(7)
2781 << (ase.active ? "true" : "false") << std::left << std::setw(8)
2782 << (ase.direction == types::kLeAudioDirectionSink ? "sink"
2783 : "source")
2784 << std::left << std::setw(8) << static_cast<int>(ase.cis_id)
2785 << std::left << std::setw(12) << ase.cis_conn_hdl << std::left
2786 << std::setw(5) << ase.max_sdu_size << std::left << std::setw(8)
2787 << ase.max_transport_latency << std::left << std::setw(5)
2788 << static_cast<int>(ase.retrans_nb) << std::left << std::setw(12)
2789 << bluetooth::common::ToString(ase.data_path_state);
2790 }
2791 }
2792
2793 stream << "\n\t====";
2794
2795 dprintf(fd, "%s", stream.str().c_str());
2796 }
2797
DisconnectAcl(void)2798 void LeAudioDevice::DisconnectAcl(void) {
2799 if (conn_id_ == GATT_INVALID_CONN_ID) return;
2800
2801 uint16_t acl_handle =
2802 BTM_GetHCIConnHandle(address_, BT_TRANSPORT_LE);
2803 if (acl_handle != HCI_INVALID_HANDLE) {
2804 acl_disconnect_from_handle(acl_handle, HCI_ERR_PEER_USER,
2805 "bta::le_audio::client disconnect");
2806 }
2807 }
2808
2809 /* Returns XOR of updated sink and source bitset context types */
SetAvailableContexts(AudioContexts snk_contexts,AudioContexts src_contexts)2810 AudioContexts LeAudioDevice::SetAvailableContexts(AudioContexts snk_contexts,
2811 AudioContexts src_contexts) {
2812 AudioContexts updated_contexts;
2813
2814 updated_contexts = snk_contexts ^ avail_contexts_.sink;
2815 updated_contexts |= src_contexts ^ avail_contexts_.source;
2816
2817 LOG_DEBUG(
2818 "\n\t avail_contexts_.sink: %s \n\t avail_contexts_.source: %s \n\t "
2819 "snk_contexts: %s \n\t src_contexts: %s \n\t updated_contexts: %s",
2820 avail_contexts_.sink.to_string().c_str(),
2821 avail_contexts_.source.to_string().c_str(),
2822 snk_contexts.to_string().c_str(), src_contexts.to_string().c_str(),
2823 updated_contexts.to_string().c_str());
2824
2825 avail_contexts_.sink = snk_contexts;
2826 avail_contexts_.source = src_contexts;
2827
2828 return updated_contexts;
2829 }
2830
ActivateConfiguredAses(LeAudioContextType context_type)2831 bool LeAudioDevice::ActivateConfiguredAses(LeAudioContextType context_type) {
2832 if (conn_id_ == GATT_INVALID_CONN_ID) {
2833 LOG_WARN(" Device %s is not connected ",
2834 ADDRESS_TO_LOGGABLE_CSTR(address_));
2835 return false;
2836 }
2837
2838 bool ret = false;
2839
2840 LOG_INFO(" Configuring device %s", ADDRESS_TO_LOGGABLE_CSTR(address_));
2841 for (auto& ase : ases_) {
2842 if (ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED &&
2843 ase.configured_for_context_type == context_type) {
2844 LOG_INFO(
2845 " conn_id: %d, ase id %d, cis id %d, cis_handle 0x%04x is activated.",
2846 conn_id_, ase.id, ase.cis_id, ase.cis_conn_hdl);
2847 ase.active = true;
2848 ret = true;
2849 }
2850 }
2851
2852 return ret;
2853 }
2854
DeactivateAllAses(void)2855 void LeAudioDevice::DeactivateAllAses(void) {
2856 for (auto& ase : ases_) {
2857 if (ase.active == false &&
2858 ase.data_path_state != AudioStreamDataPathState::IDLE) {
2859 LOG_WARN(
2860 " %s, ase_id: %d, ase.cis_id: %d, cis_handle: 0x%02x, "
2861 "ase.data_path=%s",
2862 ADDRESS_TO_LOGGABLE_CSTR(address_), ase.id, ase.cis_id,
2863 ase.cis_conn_hdl,
2864 bluetooth::common::ToString(ase.data_path_state).c_str());
2865 }
2866 ase.state = AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
2867 ase.data_path_state = AudioStreamDataPathState::IDLE;
2868 ase.active = false;
2869 ase.cis_id = le_audio::kInvalidCisId;
2870 ase.cis_conn_hdl = 0;
2871 }
2872 }
2873
GetMetadata(AudioContexts context_type,const std::vector<uint8_t> & ccid_list)2874 std::vector<uint8_t> LeAudioDevice::GetMetadata(
2875 AudioContexts context_type, const std::vector<uint8_t>& ccid_list) {
2876 std::vector<uint8_t> metadata;
2877
2878 AppendMetadataLtvEntryForStreamingContext(metadata, context_type);
2879 AppendMetadataLtvEntryForCcidList(metadata, ccid_list);
2880
2881 return std::move(metadata);
2882 }
2883
IsMetadataChanged(const BidirectionalPair<AudioContexts> & context_types,const BidirectionalPair<std::vector<uint8_t>> & ccid_lists)2884 bool LeAudioDevice::IsMetadataChanged(
2885 const BidirectionalPair<AudioContexts>& context_types,
2886 const BidirectionalPair<std::vector<uint8_t>>& ccid_lists) {
2887 for (auto* ase = this->GetFirstActiveAse(); ase;
2888 ase = this->GetNextActiveAse(ase)) {
2889 if (this->GetMetadata(context_types.get(ase->direction),
2890 ccid_lists.get(ase->direction)) != ase->metadata)
2891 return true;
2892 }
2893
2894 return false;
2895 }
2896
Add(int group_id)2897 LeAudioDeviceGroup* LeAudioDeviceGroups::Add(int group_id) {
2898 /* Get first free group id */
2899 if (FindById(group_id)) {
2900 LOG(ERROR) << __func__
2901 << ", group already exists, id: " << loghex(group_id);
2902 return nullptr;
2903 }
2904
2905 return (groups_.emplace_back(std::make_unique<LeAudioDeviceGroup>(group_id)))
2906 .get();
2907 }
2908
Remove(int group_id)2909 void LeAudioDeviceGroups::Remove(int group_id) {
2910 auto iter = std::find_if(
2911 groups_.begin(), groups_.end(),
2912 [&group_id](auto const& group) { return group->group_id_ == group_id; });
2913
2914 if (iter == groups_.end()) {
2915 LOG(ERROR) << __func__ << ", no such group_id: " << group_id;
2916 return;
2917 }
2918
2919 groups_.erase(iter);
2920 }
2921
FindById(int group_id)2922 LeAudioDeviceGroup* LeAudioDeviceGroups::FindById(int group_id) {
2923 auto iter = std::find_if(
2924 groups_.begin(), groups_.end(),
2925 [&group_id](auto const& group) { return group->group_id_ == group_id; });
2926
2927 return (iter == groups_.end()) ? nullptr : iter->get();
2928 }
2929
Cleanup(void)2930 void LeAudioDeviceGroups::Cleanup(void) {
2931 for (auto& g : groups_) {
2932 g->Cleanup();
2933 }
2934
2935 groups_.clear();
2936 }
2937
Dump(int fd,int active_group_id)2938 void LeAudioDeviceGroups::Dump(int fd, int active_group_id) {
2939 /* Dump first active group */
2940 for (auto& g : groups_) {
2941 if (g->group_id_ == active_group_id) {
2942 g->Dump(fd, active_group_id);
2943 break;
2944 }
2945 }
2946
2947 /* Dump non active group */
2948 for (auto& g : groups_) {
2949 if (g->group_id_ != active_group_id) {
2950 g->Dump(fd, active_group_id);
2951 }
2952 }
2953 }
2954
IsAnyInTransition(void)2955 bool LeAudioDeviceGroups::IsAnyInTransition(void) {
2956 for (auto& g : groups_) {
2957 if (g->IsInTransition()) {
2958 DLOG(INFO) << __func__ << " group: " << g->group_id_
2959 << " is in transition";
2960 return true;
2961 }
2962 }
2963 return false;
2964 }
2965
Size()2966 size_t LeAudioDeviceGroups::Size() { return (groups_.size()); }
2967
GetGroupsIds(void)2968 std::vector<int> LeAudioDeviceGroups::GetGroupsIds(void) {
2969 std::vector<int> result;
2970
2971 for (auto const& group : groups_) {
2972 result.push_back(group->group_id_);
2973 }
2974
2975 return result;
2976 }
2977
2978 /* LeAudioDevices Class methods implementation */
Add(const RawAddress & address,DeviceConnectState state,int group_id)2979 void LeAudioDevices::Add(const RawAddress& address, DeviceConnectState state,
2980 int group_id) {
2981 auto device = FindByAddress(address);
2982 if (device != nullptr) {
2983 LOG(ERROR) << __func__ << ", address: " << ADDRESS_TO_LOGGABLE_STR(address)
2984 << " is already assigned to group: " << device->group_id_;
2985 return;
2986 }
2987
2988 leAudioDevices_.emplace_back(
2989 std::make_shared<LeAudioDevice>(address, state, group_id));
2990 }
2991
Remove(const RawAddress & address)2992 void LeAudioDevices::Remove(const RawAddress& address) {
2993 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
2994 [&address](auto const& leAudioDevice) {
2995 return leAudioDevice->address_ == address;
2996 });
2997
2998 if (iter == leAudioDevices_.end()) {
2999 LOG(ERROR) << __func__ << ", no such address: "
3000 << ADDRESS_TO_LOGGABLE_STR(address);
3001 return;
3002 }
3003
3004 leAudioDevices_.erase(iter);
3005 }
3006
FindByAddress(const RawAddress & address)3007 LeAudioDevice* LeAudioDevices::FindByAddress(const RawAddress& address) {
3008 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
3009 [&address](auto const& leAudioDevice) {
3010 return leAudioDevice->address_ == address;
3011 });
3012
3013 return (iter == leAudioDevices_.end()) ? nullptr : iter->get();
3014 }
3015
GetByAddress(const RawAddress & address)3016 std::shared_ptr<LeAudioDevice> LeAudioDevices::GetByAddress(
3017 const RawAddress& address) {
3018 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
3019 [&address](auto const& leAudioDevice) {
3020 return leAudioDevice->address_ == address;
3021 });
3022
3023 return (iter == leAudioDevices_.end()) ? nullptr : *iter;
3024 }
3025
FindByConnId(uint16_t conn_id)3026 LeAudioDevice* LeAudioDevices::FindByConnId(uint16_t conn_id) {
3027 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
3028 [&conn_id](auto const& leAudioDevice) {
3029 return leAudioDevice->conn_id_ == conn_id;
3030 });
3031
3032 return (iter == leAudioDevices_.end()) ? nullptr : iter->get();
3033 }
3034
FindByCisConnHdl(uint8_t cig_id,uint16_t conn_hdl)3035 LeAudioDevice* LeAudioDevices::FindByCisConnHdl(uint8_t cig_id,
3036 uint16_t conn_hdl) {
3037 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
3038 [&conn_hdl, &cig_id](auto& d) {
3039 LeAudioDevice* dev;
3040 BidirectAsesPair ases;
3041
3042 dev = d.get();
3043 if (dev->group_id_ != cig_id) {
3044 return false;
3045 }
3046
3047 ases = dev->GetAsesByCisConnHdl(conn_hdl);
3048 if (ases.sink || ases.source)
3049 return true;
3050 else
3051 return false;
3052 });
3053
3054 if (iter == leAudioDevices_.end()) return nullptr;
3055
3056 return iter->get();
3057 }
3058
SetInitialGroupAutoconnectState(int group_id,int gatt_if,tBTM_BLE_CONN_TYPE reconnection_mode,bool current_dev_autoconnect_flag)3059 void LeAudioDevices::SetInitialGroupAutoconnectState(
3060 int group_id, int gatt_if, tBTM_BLE_CONN_TYPE reconnection_mode,
3061 bool current_dev_autoconnect_flag) {
3062 if (!current_dev_autoconnect_flag) {
3063 /* If current device autoconnect flag is false, check if there is other
3064 * device in the group which is in autoconnect mode.
3065 * If yes, assume whole group is in autoconnect.
3066 */
3067 auto iter = std::find_if(leAudioDevices_.begin(), leAudioDevices_.end(),
3068 [&group_id](auto& d) {
3069 LeAudioDevice* dev;
3070 dev = d.get();
3071 if (dev->group_id_ != group_id) {
3072 return false;
3073 }
3074 return dev->autoconnect_flag_;
3075 });
3076
3077 current_dev_autoconnect_flag = !(iter == leAudioDevices_.end());
3078 }
3079
3080 if (!current_dev_autoconnect_flag) {
3081 return;
3082 }
3083
3084 /* This function is called when bluetooth started, therefore here we will
3085 * try direct connection, if that failes, we fallback to background connection
3086 */
3087 for (auto dev : leAudioDevices_) {
3088 if ((dev->group_id_ == group_id) &&
3089 (dev->GetConnectionState() == DeviceConnectState::DISCONNECTED)) {
3090 dev->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
3091 dev->autoconnect_flag_ = true;
3092 btif_storage_set_leaudio_autoconnect(dev->address_, true);
3093 BTA_GATTC_Open(gatt_if, dev->address_, BTM_BLE_DIRECT_CONNECTION, false);
3094 }
3095 }
3096 }
3097
Size()3098 size_t LeAudioDevices::Size() { return (leAudioDevices_.size()); }
3099
Dump(int fd,int group_id)3100 void LeAudioDevices::Dump(int fd, int group_id) {
3101 std::stringstream stream, stream_pacs;
3102
3103 for (auto const& device : leAudioDevices_) {
3104 if (device->group_id_ == group_id) {
3105 device->Dump(fd);
3106
3107 stream_pacs << "\n\taddress: " << device->address_;
3108 device->DumpPacsDebugState(stream_pacs);
3109 dprintf(fd, "%s", stream_pacs.str().c_str());
3110 }
3111 }
3112 }
3113
Cleanup(tGATT_IF client_if)3114 void LeAudioDevices::Cleanup(tGATT_IF client_if) {
3115 for (auto const& device : leAudioDevices_) {
3116 auto connection_state = device->GetConnectionState();
3117 if (connection_state == DeviceConnectState::DISCONNECTED) {
3118 continue;
3119 }
3120
3121 if (connection_state == DeviceConnectState::CONNECTING_AUTOCONNECT) {
3122 BTA_GATTC_CancelOpen(client_if, device->address_, false);
3123 } else {
3124 BtaGattQueue::Clean(device->conn_id_);
3125 BTA_GATTC_Close(device->conn_id_);
3126 device->DisconnectAcl();
3127 }
3128 }
3129 leAudioDevices_.clear();
3130 }
3131
3132 } // namespace le_audio
3133