• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2021 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 <base/functional/bind.h>
19 #include <base/strings/string_number_conversions.h>
20 #include <bluetooth/log.h>
21 #include <com_android_bluetooth_flags.h>
22 #include <stdio.h>
23 
24 #include <algorithm>
25 #include <bitset>
26 #include <chrono>
27 #include <cstddef>
28 #include <cstdint>
29 #include <cstring>
30 #include <deque>
31 #include <functional>
32 #include <list>
33 #include <map>
34 #include <memory>
35 #include <mutex>
36 #include <optional>
37 #include <ostream>
38 #include <sstream>
39 #include <tuple>
40 #include <utility>
41 #include <vector>
42 
43 #include "audio_hal_client/audio_hal_client.h"
44 #include "audio_hal_interface/le_audio_software.h"
45 #include "bt_types.h"
46 #include "bta/csis/csis_types.h"
47 #include "bta_csis_api.h"
48 #include "bta_gatt_api.h"
49 #include "bta_gatt_queue.h"
50 #include "bta_groups.h"
51 #include "bta_le_audio_api.h"
52 #include "bta_le_audio_broadcaster_api.h"
53 #include "btif/include/btif_profile_storage.h"
54 #include "btm_api_types.h"
55 #include "btm_ble_api_types.h"
56 #include "btm_iso_api.h"
57 #include "btm_iso_api_types.h"
58 #include "btm_sec_api_types.h"
59 #include "client_parser.h"
60 #include "codec_interface.h"
61 #include "codec_manager.h"
62 #include "common/strings.h"
63 #include "common/time_util.h"
64 #include "content_control_id_keeper.h"
65 #include "devices.h"
66 #include "gatt/database.h"
67 #include "gatt_api.h"
68 #include "gattdefs.h"
69 #include "gmap_client.h"
70 #include "gmap_server.h"
71 #include "hardware/bt_le_audio.h"
72 #include "hci/controller_interface.h"
73 #include "hci_error_code.h"
74 #include "include/hardware/bt_gmap.h"
75 #include "internal_include/bt_trace.h"
76 #include "internal_include/stack_config.h"
77 #include "le_audio/device_groups.h"
78 #include "le_audio/le_audio_log_history.h"
79 #include "le_audio_health_status.h"
80 #include "le_audio_set_configuration_provider.h"
81 #include "le_audio_types.h"
82 #include "le_audio_utils.h"
83 #include "main/shim/entry.h"
84 #include "metrics_collector.h"
85 #include "osi/include/alarm.h"
86 #include "osi/include/osi.h"
87 #include "osi/include/properties.h"
88 #include "stack/btm/btm_sec.h"
89 #include "stack/gatt/gatt_int.h"
90 #include "stack/include/bt_types.h"
91 #include "stack/include/btm_client_interface.h"
92 #include "stack/include/btm_status.h"
93 #include "stack/include/l2cap_interface.h"
94 #include "stack/include/main_thread.h"
95 #include "state_machine.h"
96 #include "storage_helper.h"
97 #include "types/bluetooth/uuid.h"
98 #include "types/bt_transport.h"
99 #include "types/raw_address.h"
100 
101 #ifdef TARGET_FLOSS
102 #include <audio_hal_interface/audio_linux.h>
103 #else
104 #include <hardware/audio.h>
105 #endif  // TARGET_FLOSS
106 
107 using base::Closure;
108 using bluetooth::Uuid;
109 using bluetooth::common::ToString;
110 using bluetooth::groups::DeviceGroups;
111 using bluetooth::groups::DeviceGroupsCallbacks;
112 using bluetooth::hci::IsoManager;
113 using bluetooth::hci::iso_manager::cig_create_cmpl_evt;
114 using bluetooth::hci::iso_manager::cig_remove_cmpl_evt;
115 using bluetooth::hci::iso_manager::CigCallbacks;
116 using bluetooth::le_audio::CodecManager;
117 using bluetooth::le_audio::ConnectionState;
118 using bluetooth::le_audio::ContentControlIdKeeper;
119 using bluetooth::le_audio::DeviceConnectState;
120 using bluetooth::le_audio::DsaMode;
121 using bluetooth::le_audio::DsaModes;
122 using bluetooth::le_audio::GmapClient;
123 using bluetooth::le_audio::GmapServer;
124 using bluetooth::le_audio::GroupNodeStatus;
125 using bluetooth::le_audio::GroupStatus;
126 using bluetooth::le_audio::GroupStreamStatus;
127 using bluetooth::le_audio::LeAudioCodecConfiguration;
128 using bluetooth::le_audio::LeAudioDevice;
129 using bluetooth::le_audio::LeAudioDeviceGroup;
130 using bluetooth::le_audio::LeAudioDeviceGroups;
131 using bluetooth::le_audio::LeAudioDevices;
132 using bluetooth::le_audio::LeAudioGroupStateMachine;
133 using bluetooth::le_audio::LeAudioHealthBasedAction;
134 using bluetooth::le_audio::LeAudioHealthDeviceStatType;
135 using bluetooth::le_audio::LeAudioHealthGroupStatType;
136 using bluetooth::le_audio::LeAudioHealthStatus;
137 using bluetooth::le_audio::LeAudioRecommendationActionCb;
138 using bluetooth::le_audio::LeAudioSinkAudioHalClient;
139 using bluetooth::le_audio::LeAudioSourceAudioHalClient;
140 using bluetooth::le_audio::UnicastMonitorModeStatus;
141 using bluetooth::le_audio::types::ase;
142 using bluetooth::le_audio::types::AseState;
143 using bluetooth::le_audio::types::AudioContexts;
144 using bluetooth::le_audio::types::AudioLocations;
145 using bluetooth::le_audio::types::BidirectionalPair;
146 using bluetooth::le_audio::types::DataPathState;
147 using bluetooth::le_audio::types::hdl_pair;
148 using bluetooth::le_audio::types::hdl_pair_wrapper;
149 using bluetooth::le_audio::types::kLeAudioContextAllRemoteSource;
150 using bluetooth::le_audio::types::kLeAudioContextAllTypesArray;
151 using bluetooth::le_audio::types::LeAudioContextType;
152 using bluetooth::le_audio::types::PublishedAudioCapabilities;
153 using bluetooth::le_audio::utils::GetAudioContextsFromSinkMetadata;
154 using bluetooth::le_audio::utils::GetAudioContextsFromSourceMetadata;
155 
156 using namespace bluetooth;
157 
158 /* Enums */
159 enum class AudioReconfigurationResult {
160   RECONFIGURATION_NEEDED = 0x00,
161   RECONFIGURATION_NOT_NEEDED,
162   RECONFIGURATION_NOT_POSSIBLE
163 };
164 
165 enum class AudioState {
166   IDLE = 0x00,
167   READY_TO_START,
168   STARTED,
169   READY_TO_RELEASE,
170   RELEASING,
171 };
172 
operator <<(std::ostream & os,const AudioReconfigurationResult & state)173 static std::ostream& operator<<(std::ostream& os, const AudioReconfigurationResult& state) {
174   switch (state) {
175     case AudioReconfigurationResult::RECONFIGURATION_NEEDED:
176       os << "RECONFIGURATION_NEEDED";
177       break;
178     case AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED:
179       os << "RECONFIGURATION_NOT_NEEDED";
180       break;
181     case AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE:
182       os << "RECONFIGRATION_NOT_POSSIBLE";
183       break;
184     default:
185       os << "UNKNOWN";
186       break;
187   }
188   return os;
189 }
190 
operator <<(std::ostream & os,const AudioState & audio_state)191 static std::ostream& operator<<(std::ostream& os, const AudioState& audio_state) {
192   switch (audio_state) {
193     case AudioState::IDLE:
194       os << "IDLE";
195       break;
196     case AudioState::READY_TO_START:
197       os << "READY_TO_START";
198       break;
199     case AudioState::STARTED:
200       os << "STARTED";
201       break;
202     case AudioState::READY_TO_RELEASE:
203       os << "READY_TO_RELEASE";
204       break;
205     case AudioState::RELEASING:
206       os << "RELEASING";
207       break;
208     default:
209       os << "UNKNOWN";
210       break;
211   }
212   return os;
213 }
214 
215 namespace std {
216 template <>
217 struct formatter<AudioState> : ostream_formatter {};
218 }  // namespace std
219 
220 namespace {
221 void le_audio_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
222 
223 static void le_audio_health_status_callback(const RawAddress& addr, int group_id,
224                                             LeAudioHealthBasedAction action);
225 
226 class LeAudioClientImpl;
227 LeAudioClientImpl* instance;
228 std::mutex instance_mutex;
229 LeAudioSourceAudioHalClient::Callbacks* audioSinkReceiver;
230 LeAudioSinkAudioHalClient::Callbacks* audioSourceReceiver;
231 CigCallbacks* stateMachineHciCallbacks;
232 LeAudioGroupStateMachine::Callbacks* stateMachineCallbacks;
233 DeviceGroupsCallbacks* device_group_callbacks;
234 LeAudioIsoDataCallback* iso_data_callback;
235 
236 class StreamSpeedTracker {
237 public:
StreamSpeedTracker(void)238   StreamSpeedTracker(void)
239       : is_started_(false),
240         group_id_(bluetooth::groups::kGroupUnknown),
241         num_of_devices_(0),
242         context_type_(LeAudioContextType::UNSPECIFIED),
243         reconfig_start_ts_(0),
244         setup_start_ts_(0),
245         total_time_(0),
246         reconfig_time_(0),
247         stream_setup_time_(0) {}
248 
Init(int group_id,LeAudioContextType context_type,int num_of_devices)249   void Init(int group_id, LeAudioContextType context_type, int num_of_devices) {
250     Reset(bluetooth::groups::kGroupUnknown);
251     group_id_ = group_id;
252     context_type_ = context_type;
253     num_of_devices_ = num_of_devices;
254     log::verbose("StreamSpeedTracker group_id: {}, context: {} #{}", group_id_,
255                  ToString(context_type_), num_of_devices);
256   }
257 
Reset(int group_id)258   void Reset(int group_id) {
259     if (group_id != bluetooth::groups::kGroupUnknown && group_id != group_id_) {
260       log::verbose("StreamSpeedTracker Reset called for invalid group_id: {} != {}", group_id,
261                    group_id_);
262       return;
263     }
264 
265     log::verbose("StreamSpeedTracker group_id: {}", group_id_);
266     is_started_ = false;
267     group_id_ = bluetooth::groups::kGroupUnknown;
268     reconfig_start_ts_ = setup_start_ts_ = total_time_ = reconfig_time_ = stream_setup_time_ =
269             num_of_devices_ = 0;
270     context_type_ = LeAudioContextType::UNSPECIFIED;
271   }
272 
ReconfigStarted(void)273   void ReconfigStarted(void) {
274     log::verbose("StreamSpeedTracker group_id: {}", group_id_);
275     reconfig_time_ = 0;
276     is_started_ = true;
277     reconfig_start_ts_ = bluetooth::common::time_get_os_boottime_us();
278   }
279 
StartStream(void)280   void StartStream(void) {
281     log::verbose("StreamSpeedTracker group_id: {}", group_id_);
282     setup_start_ts_ = bluetooth::common::time_get_os_boottime_us();
283     is_started_ = true;
284   }
285 
ReconfigurationComplete(void)286   void ReconfigurationComplete(void) {
287     reconfig_time_ = (bluetooth::common::time_get_os_boottime_us() - reconfig_start_ts_) / 1000;
288     log::verbose("StreamSpeedTracker group_id: {}, {} reconfig time {} ms", group_id_,
289                  ToString(context_type_), reconfig_time_);
290   }
291 
StreamCreated(void)292   void StreamCreated(void) {
293     stream_setup_time_ = (bluetooth::common::time_get_os_boottime_us() - setup_start_ts_) / 1000;
294     log::verbose("StreamSpeedTracker group_id: {}, {} stream create  time {} ms", group_id_,
295                  ToString(context_type_), stream_setup_time_);
296   }
297 
StopStreamSetup(void)298   void StopStreamSetup(void) {
299     is_started_ = false;
300     uint64_t start_ts = reconfig_time_ != 0 ? reconfig_start_ts_ : setup_start_ts_;
301     total_time_ = (bluetooth::common::time_get_os_boottime_us() - start_ts) / 1000;
302     clock_gettime(CLOCK_REALTIME, &end_ts_);
303     log::verbose("StreamSpeedTracker group_id: {}, {} setup time {} ms", group_id_,
304                  ToString(context_type_), total_time_);
305   }
306 
IsStarted(int group_id)307   bool IsStarted(int group_id) {
308     if (is_started_ && group_id_ == group_id) {
309       log::verbose("StreamSpeedTracker group_id: {}, {} is_started_: {} ", group_id_,
310                    ToString(context_type_), is_started_);
311       return true;
312     }
313     log::verbose("StreamSpeedTracker not started {} or group_id does not match ({} ! = {}) ",
314                  is_started_, group_id, group_id_);
315     return false;
316   }
317 
Dump(std::stringstream & stream)318   void Dump(std::stringstream& stream) {
319     char ts[20];
320     std::strftime(ts, sizeof(ts), "%T", std::gmtime(&end_ts_.tv_sec));
321 
322     if (total_time_ < 900) {
323       stream << "[ �� ";
324     } else if (total_time_ < 1500) {
325       stream << "[ �� ";
326     } else if (total_time_ < 2500) {
327       stream << "[ �� ";
328     } else {
329       stream << "[ ❗ ";
330     }
331 
332     stream << ts << ": Gid: " << group_id_ << "(#" << num_of_devices_ << "), " << context_type_
333            << ", ";
334     auto hal_idle = total_time_ - stream_setup_time_ - reconfig_time_;
335     if (reconfig_time_ != 0) {
336       stream << "t:" << total_time_ << "ms (r:" << reconfig_time_ << "/s:" << stream_setup_time_
337              << "/hal:" << hal_idle << ")";
338     } else {
339       stream << "t:" << total_time_ << "ms (hal:" << hal_idle << ")";
340     }
341     stream << "]";
342   }
343 
344 private:
345   bool is_started_;
346   int group_id_;
347   int num_of_devices_;
348   LeAudioContextType context_type_;
349   struct timespec end_ts_;
350   uint64_t reconfig_start_ts_;
351   uint64_t setup_start_ts_;
352   uint64_t total_time_;
353   uint64_t reconfig_time_;
354   uint64_t stream_setup_time_;
355 };
356 
357 /*
358  * Coordinatet Set Identification Profile (CSIP) based on CSIP 1.0
359  * and Coordinatet Set Identification Service (CSIS) 1.0
360  *
361  * CSIP allows to organize audio servers into sets e.g. Stereo Set, 5.1 Set
362  * and speed up connecting it.
363  *
364  * Since leaudio has already grouping API it was decided to integrate here CSIS
365  * and allow it to group devices semi-automatically.
366  *
367  * Flow:
368  * If connected device contains CSIS services, and it is included into CAP
369  * service, implementation marks device as a set member and waits for the
370  * bta/csis to learn about groups and notify implementation about assigned
371  * group id.
372  *
373  */
374 /* LeAudioClientImpl class represents main implementation class for le audio
375  * feature in stack. This class implements GATT, le audio and ISO related parts.
376  *
377  * This class is represented in single instance and manages a group of devices,
378  * and devices. All devices calls back static method from it and are dispatched
379  * to target receivers (e.g. ASEs, devices).
380  *
381  * This instance also implements a LeAudioClient which is a upper layer API.
382  * Also LeAudioClientCallbacks are callbacks for upper layer.
383  *
384  * This class may be bonded with Test socket which allows to drive an instance
385  * for test purposes.
386  */
387 class LeAudioClientImpl : public LeAudioClient {
388 public:
~LeAudioClientImpl()389   ~LeAudioClientImpl() {
390     alarm_free(close_vbc_timeout_);
391     alarm_free(disable_timer_);
392     alarm_free(suspend_timeout_);
393     alarm_free(reconfiguration_timeout_);
394   }
395 
LeAudioClientImpl(bluetooth::le_audio::LeAudioClientCallbacks * callbacks,LeAudioGroupStateMachine::Callbacks * state_machine_callbacks,base::Closure initCb)396   LeAudioClientImpl(bluetooth::le_audio::LeAudioClientCallbacks* callbacks,
397                     LeAudioGroupStateMachine::Callbacks* state_machine_callbacks,
398                     base::Closure initCb)
399       : gatt_if_(0),
400         callbacks_(callbacks),
401         active_group_id_(bluetooth::groups::kGroupUnknown),
402         configuration_context_type_(LeAudioContextType::UNINITIALIZED),
403         in_call_metadata_context_types_({.sink = AudioContexts(), .source = AudioContexts()}),
404         local_metadata_context_types_({.sink = AudioContexts(), .source = AudioContexts()}),
405         audio_receiver_state_(AudioState::IDLE),
406         audio_sender_state_(AudioState::IDLE),
407         in_call_(false),
408         in_voip_call_(false),
409         sink_monitor_mode_(false),
410         sink_monitor_notified_status_(std::nullopt),
411         source_monitor_mode_(false),
412         source_monitor_notified_status_(std::nullopt),
413         le_audio_source_hal_client_(nullptr),
414         le_audio_sink_hal_client_(nullptr),
415         close_vbc_timeout_(alarm_new("LeAudioCloseVbcTimeout")),
416         suspend_timeout_(alarm_new("LeAudioSuspendTimeout")),
417         reconfiguration_timeout_(alarm_new("LeAudioReconfigurationTimeout")),
418         disable_timer_(alarm_new("LeAudioDisableTimer")) {
419     LeAudioGroupStateMachine::Initialize(state_machine_callbacks);
420     groupStateMachine_ = LeAudioGroupStateMachine::Get();
421 
422     log::info("Reconnection mode: TARGETED_ANNOUNCEMENTS");
423     reconnection_mode_ = BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS;
424 
425     log::info("Loading health status module");
426     leAudioHealthStatus_ = LeAudioHealthStatus::Get();
427     leAudioHealthStatus_->RegisterCallback(base::BindRepeating(le_audio_health_status_callback));
428 
429     BTA_GATTC_AppRegister(
430             "le_audio", le_audio_gattc_callback,
431             base::Bind(
__anon432cb1ce0202(base::Closure initCb, uint8_t client_id, uint8_t status) 432                     [](base::Closure initCb, uint8_t client_id, uint8_t status) {
433                       if (status != GATT_SUCCESS) {
434                         log::error("Can't start LeAudio profile - no gatt clients left!");
435                         return;
436                       }
437                       instance->gatt_if_ = client_id;
438                       initCb.Run();
439                     },
440                     initCb),
441             true);
442 
443     DeviceGroups::Get()->Initialize(device_group_callbacks);
444   }
445 
446   /* Helper function for update source local and in_call context metadata (if in call) */
UpdateSourceLocalMetadataContextTypes(AudioContexts contexts)447   void UpdateSourceLocalMetadataContextTypes(AudioContexts contexts) {
448     /* Update cached fallback contexts */
449     if (IsInCall()) {
450       in_call_metadata_context_types_.source = contexts;
451     }
452 
453     local_metadata_context_types_.source = contexts;
454   }
455 
456   /* Helper function for update sink local and in_call context metadata (if in call) */
UpdateSinkLocalMetadataContextTypes(AudioContexts contexts)457   void UpdateSinkLocalMetadataContextTypes(AudioContexts contexts) {
458     /* Update cached fallback contexts */
459     if (IsInCall()) {
460       in_call_metadata_context_types_.sink = contexts;
461     }
462 
463     local_metadata_context_types_.sink = contexts;
464   }
465 
ReconfigureAfterVbcClose()466   void ReconfigureAfterVbcClose() {
467     log::debug("VBC close timeout");
468 
469     if (IsInVoipCall()) {
470       SetInVoipCall(false);
471     }
472 
473     auto group = aseGroups_.FindById(active_group_id_);
474     if (!group) {
475       log::error("Invalid group: {}", active_group_id_);
476       return;
477     }
478 
479     /* Reconfiguration to non requiring source scenario */
480     if (sink_monitor_mode_) {
481       notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
482     }
483 
484     /* For sonification events we don't really need to reconfigure to HQ
485      * configuration, but if the previous configuration was for HQ Media,
486      * we might want to go back to that scenario.
487      */
488 
489     if ((configuration_context_type_ != LeAudioContextType::MEDIA) &&
490         (configuration_context_type_ != LeAudioContextType::GAME)) {
491       log::info("Keeping the old configuration as no HQ Media playback is needed right now.");
492       return;
493     }
494 
495     /* Test the existing metadata against the recent availability */
496     local_metadata_context_types_.source &=
497             group->GetAvailableContexts(bluetooth::le_audio::types::kLeAudioDirectionSink);
498     if (local_metadata_context_types_.source.none()) {
499       log::warn("invalid/unknown context metadata, using 'MEDIA' instead");
500       UpdateSourceLocalMetadataContextTypes(AudioContexts(LeAudioContextType::MEDIA));
501     }
502 
503     /* Choose the right configuration context */
504     auto new_configuration_context =
505             ChooseConfigurationContextType(local_metadata_context_types_.source);
506 
507     log::debug("new_configuration_context= {}", ToString(new_configuration_context));
508     ReconfigureOrUpdateMetadata(group, new_configuration_context,
509                                 {.sink = local_metadata_context_types_.source,
510                                  .source = local_metadata_context_types_.sink});
511   }
512 
StartVbcCloseTimeout()513   void StartVbcCloseTimeout() {
514     if (alarm_is_scheduled(close_vbc_timeout_)) {
515       StopVbcCloseTimeout();
516     }
517 
518     static const uint64_t timeoutMs = 2000;
519     log::debug("Start VBC close timeout with {} ms", timeoutMs);
520 
521     alarm_set_on_mloop(
522             close_vbc_timeout_, timeoutMs,
523             [](void*) {
524               if (instance) {
525                 log::debug("Reconfigure after VBC close");
526                 instance->ReconfigureAfterVbcClose();
527               }
528             },
529             nullptr);
530   }
531 
StopVbcCloseTimeout()532   void StopVbcCloseTimeout() {
533     if (alarm_is_scheduled(close_vbc_timeout_)) {
534       log::debug("Cancel VBC close timeout");
535       alarm_cancel(close_vbc_timeout_);
536     }
537   }
538 
IsReconfigurationTimeoutRunning(int group_id,uint8_t direction=bluetooth::le_audio::types::kLeAudioDirectionBoth)539   bool IsReconfigurationTimeoutRunning(
540           int group_id, uint8_t direction = bluetooth::le_audio::types::kLeAudioDirectionBoth) {
541     if (alarm_is_scheduled(reconfiguration_timeout_)) {
542       log::debug(" is {} group_id: {}, to check: {}, scheduled: {}",
543                  group_id == reconfiguration_group_ ? "running" : " not running", group_id,
544                  direction, reconfiguration_local_directions_);
545       return group_id == reconfiguration_group_ && (direction & reconfiguration_local_directions_);
546     }
547     return false;
548   }
549 
StartReconfigurationTimeout(int group_id)550   void StartReconfigurationTimeout(int group_id) {
551     log::debug("group_id: {}", group_id);
552 
553     /* This is called when Reconfiguration has been completed. This function starts
554      * timer which is a guard for unwanted reconfiguration which might happen when Audio HAL
555      * is sending to Bluetooth stack multiple metadata updates and suspends/resume commands.
556      * What we want to achieve with this timeout, that BT stack will resume the stream with
557      * configuration picked up when ReconfigurationComplete command was sent out to Audio HAL.
558      */
559 
560     if (alarm_is_scheduled(reconfiguration_timeout_)) {
561       log::info("Is already running for group {}", reconfiguration_group_);
562       return;
563     }
564 
565     auto group = aseGroups_.FindById(group_id);
566     if (group == nullptr) {
567       log::warn("This shall not happen, group_id: {} is not available.", group_id);
568       return;
569     }
570 
571     if (IsDirectionAvailableForCurrentConfiguration(
572                 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
573       reconfiguration_local_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource;
574     }
575     if (IsDirectionAvailableForCurrentConfiguration(
576                 group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
577       reconfiguration_local_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink;
578     }
579 
580     log::debug("reconfiguration_local_directions_ : {}", reconfiguration_local_directions_);
581 
582     reconfiguration_group_ = group_id;
583     alarm_set_on_mloop(
584             reconfiguration_timeout_, kAudioReconfigurationTimeoutMs,
585             [](void* data) {
586               if (instance) {
587                 instance->StopReconfigurationTimeout(
588                         PTR_TO_INT(data), bluetooth::le_audio::types::kLeAudioDirectionBoth);
589               }
590             },
591             INT_TO_PTR(group_id));
592   }
593 
StopReconfigurationTimeout(int group_id,uint8_t local_direction)594   void StopReconfigurationTimeout(int group_id, uint8_t local_direction) {
595     log::debug("group_id: {}, local_direction {}, reconfiguration directions {}", group_id,
596                local_direction, reconfiguration_local_directions_);
597 
598     reconfiguration_local_directions_ &= ~local_direction;
599 
600     if (reconfiguration_local_directions_ != 0) {
601       log::debug("Wait for remaining directions: {} ", reconfiguration_local_directions_);
602       return;
603     }
604 
605     if (alarm_is_scheduled(reconfiguration_timeout_)) {
606       log::debug("Canceling for group_id {}", reconfiguration_group_);
607       alarm_cancel(reconfiguration_timeout_);
608     }
609     reconfiguration_group_ = bluetooth::groups::kGroupUnknown;
610   }
611 
StartSuspendTimeout(void)612   void StartSuspendTimeout(void) {
613     StopSuspendTimeout();
614 
615     /* Group should tie in time to get requested status */
616     uint64_t timeoutMs = kAudioSuspentKeepIsoAliveTimeoutMs;
617     timeoutMs = osi_property_get_int32(kAudioSuspentKeepIsoAliveTimeoutMsProp, timeoutMs);
618 
619     if (stack_config_get_interface()->get_pts_le_audio_disable_ases_before_stopping()) {
620       timeoutMs += kAudioDisableTimeoutMs;
621     }
622 
623     log::debug("Stream suspend_timeout_ started: {} ms", static_cast<int>(timeoutMs));
624 
625     alarm_set_on_mloop(
626             suspend_timeout_, timeoutMs,
627             [](void* data) {
628               if (instance) {
629                 auto const group_id = PTR_TO_INT(data);
630                 log::debug("No resume request received. Stop the group ID: {}", group_id);
631                 instance->GroupStop(group_id);
632               }
633             },
634             INT_TO_PTR(active_group_id_));
635   }
636 
StopSuspendTimeout(void)637   void StopSuspendTimeout(void) {
638     if (alarm_is_scheduled(suspend_timeout_)) {
639       log::debug("Cancel suspend timeout");
640       alarm_cancel(suspend_timeout_);
641     }
642   }
643 
AseInitialStateReadRequest(LeAudioDevice * leAudioDevice)644   void AseInitialStateReadRequest(LeAudioDevice* leAudioDevice) {
645     int ases_num = leAudioDevice->ases_.size();
646     bool is_eatt_supported = gatt_profile_get_eatt_support_by_conn_id(leAudioDevice->conn_id_);
647 
648     void* notify_flag_ptr = NULL;
649 
650     tBTA_GATTC_MULTI multi_read{};
651 
652     for (int i = 0; i < ases_num; i++) {
653       /* Last read ase characteristic should issue connected state callback
654        * to upper layer
655        */
656 
657       if (leAudioDevice->notify_connected_after_read_ && (i == (ases_num - 1))) {
658         notify_flag_ptr = INT_TO_PTR(leAudioDevice->notify_connected_after_read_);
659       }
660 
661       if (!com::android::bluetooth::flags::le_ase_read_multiple_variable() || !is_eatt_supported) {
662         BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_,
663                                          leAudioDevice->ases_[i].hdls.val_hdl, OnGattReadRspStatic,
664                                          notify_flag_ptr);
665         continue;
666       }
667 
668       if (i != 0 && (i % GATT_MAX_READ_MULTI_HANDLES == 0)) {
669         multi_read.num_attr = GATT_MAX_READ_MULTI_HANDLES;
670         BtaGattQueue::ReadMultiCharacteristic(leAudioDevice->conn_id_, multi_read,
671                                               OnGattReadMultiRspStatic, notify_flag_ptr);
672         memset(multi_read.handles, 0, GATT_MAX_READ_MULTI_HANDLES * sizeof(uint16_t));
673       }
674       multi_read.handles[i % GATT_MAX_READ_MULTI_HANDLES] = leAudioDevice->ases_[i].hdls.val_hdl;
675     }
676 
677     if (com::android::bluetooth::flags::le_ase_read_multiple_variable() &&
678         (ases_num % GATT_MAX_READ_MULTI_HANDLES != 0)) {
679       multi_read.num_attr = ases_num % GATT_MAX_READ_MULTI_HANDLES;
680       BtaGattQueue::ReadMultiCharacteristic(leAudioDevice->conn_id_, multi_read,
681                                             OnGattReadMultiRspStatic, notify_flag_ptr);
682     }
683   }
684 
OnGroupAddedCb(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)685   void OnGroupAddedCb(const RawAddress& address, const bluetooth::Uuid& uuid, int group_id) {
686     log::info("address: {} group uuid {} group_id: {}", address, uuid, group_id);
687 
688     /* We are interested in the groups which are in the context of CAP */
689     if (uuid != bluetooth::le_audio::uuid::kCapServiceUuid) {
690       return;
691     }
692 
693     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
694     if (!leAudioDevice) {
695       return;
696     }
697     if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
698       log::info("group already set: {}", leAudioDevice->group_id_);
699       return;
700     }
701 
702     group_add_node(group_id, address);
703   }
704 
705   /* If device participates in streaming the group, it has to be stopped and
706    * group needs to be reconfigured if needed to new configuration without
707    * considering this removing device.
708    */
SetDeviceAsRemovePendingAndStopGroup(LeAudioDevice * leAudioDevice)709   void SetDeviceAsRemovePendingAndStopGroup(LeAudioDevice* leAudioDevice) {
710     log::info("device {}", leAudioDevice->address_);
711     leAudioDevice->SetConnectionState(DeviceConnectState::REMOVING);
712     leAudioDevice->closing_stream_for_disconnection_ = true;
713     GroupStop(leAudioDevice->group_id_);
714   }
715 
OnGroupMemberAddedCb(const RawAddress & address,int group_id)716   void OnGroupMemberAddedCb(const RawAddress& address, int group_id) {
717     log::info("address: {} group_id: {}", address, group_id);
718 
719     auto group = aseGroups_.FindById(group_id);
720     if (!group) {
721       log::error("Not interested in group id: {}", group_id);
722       return;
723     }
724 
725     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
726     if (!leAudioDevice) {
727       return;
728     }
729     if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
730       log::info("group already set: {}", leAudioDevice->group_id_);
731       return;
732     }
733 
734     if (leAudioHealthStatus_) {
735       leAudioHealthStatus_->AddStatisticForDevice(leAudioDevice,
736                                                   LeAudioHealthDeviceStatType::VALID_CSIS);
737     }
738 
739     group_add_node(group_id, address);
740   }
741 
OnGroupMemberRemovedCb(const RawAddress & address,int group_id)742   void OnGroupMemberRemovedCb(const RawAddress& address, int group_id) {
743     log::info("address: {} group_id: {}", address, group_id);
744 
745     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
746     if (!leAudioDevice) {
747       return;
748     }
749     if (leAudioDevice->group_id_ != group_id) {
750       log::warn("Device: {} not assigned to the group.", leAudioDevice->address_);
751       return;
752     }
753 
754     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
755     if (group == NULL) {
756       log::info("device not in the group: {}, {}", leAudioDevice->address_, group_id);
757       return;
758     }
759 
760     if (leAudioHealthStatus_) {
761       leAudioHealthStatus_->RemoveStatistics(address, group->group_id_);
762     }
763 
764     if (leAudioDevice->HaveActiveAse()) {
765       SetDeviceAsRemovePendingAndStopGroup(leAudioDevice);
766       return;
767     }
768 
769     group_remove_node(group, address);
770   }
771 
772   /* This callback happens if kLeAudioDeviceSetStateTimeoutMs timeout happens
773    * during transition from origin to target state
774    */
OnLeAudioDeviceSetStateTimeout(int group_id)775   void OnLeAudioDeviceSetStateTimeout(int group_id) {
776     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
777 
778     if (!group) {
779       /* Group removed */
780       return;
781     }
782 
783     bool check_if_recovery_needed =
784             group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_IDLE;
785 
786     if (leAudioHealthStatus_) {
787       leAudioHealthStatus_->AddStatisticForGroup(
788               group, LeAudioHealthGroupStatType::STREAM_CREATE_SIGNALING_FAILED);
789     }
790 
791     log::error(
792             "State not achieved on time for group: group id {}, current state {}, "
793             "target state: {}, check_if_recovery_needed: {}",
794             group_id, ToString(group->GetState()), ToString(group->GetTargetState()),
795             check_if_recovery_needed);
796     group->PrintDebugState();
797     group->SetTargetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
798     group->ClearAllCises();
799 
800     /* There is an issue with a setting up stream or any other operation which
801      * are gatt operations. It means peer is not responsible. Lets close ACL
802      */
803     CancelStreamingRequest();
804     LeAudioDevice* leAudioDevice = group->GetFirstActiveDevice();
805     if (leAudioDevice == nullptr) {
806       log::error("Shouldn't be called without an active device.");
807       leAudioDevice = group->GetFirstDevice();
808       if (leAudioDevice == nullptr) {
809         log::error("Front device is null. Number of devices: {}", group->Size());
810         return;
811       }
812     }
813 
814     /* If Timeout happens on stream close and stream is closing just for the
815      * purpose of device disconnection, do not bother with recovery mode
816      */
817     bool recovery = true;
818     if (check_if_recovery_needed) {
819       for (auto tmpDevice = leAudioDevice; tmpDevice != nullptr;
820            tmpDevice = group->GetNextActiveDevice(tmpDevice)) {
821         if (tmpDevice->closing_stream_for_disconnection_) {
822           recovery = false;
823           break;
824         }
825       }
826     }
827 
828     do {
829       DisconnectDevice(leAudioDevice, true, recovery);
830       leAudioDevice = group->GetNextActiveDevice(leAudioDevice);
831     } while (leAudioDevice);
832 
833     if (recovery && !group->NumOfConnected()) {
834       log::info("All devices disconnected, group becomes inactive");
835       /* Both devices will  be disconnected soon. Notify upper layer that group
836        * is inactive */
837       groupSetAndNotifyInactive();
838     }
839   }
840 
UpdateLocationsAndContextsAvailability(LeAudioDeviceGroup * group,bool available_contexts_changed=false)841   void UpdateLocationsAndContextsAvailability(LeAudioDeviceGroup* group,
842                                               bool available_contexts_changed = false) {
843     bool group_conf_changed = group->ReloadAudioLocations();
844     group_conf_changed |= group->ReloadAudioDirections();
845 
846     log::verbose("group_id: {}, group_conf_changed: {} available_contexts_changed: {}",
847                  group->group_id_, group_conf_changed, available_contexts_changed);
848     if (group_conf_changed || available_contexts_changed) {
849       /* All the configurations should be recalculated for the new conditions */
850       group->InvalidateCachedConfigurations();
851       group->InvalidateGroupStrategy();
852       callbacks_->OnAudioConf(group->audio_directions_, group->group_id_,
853                               group->audio_locations_.sink, group->audio_locations_.source,
854                               group->GetAvailableContexts().value());
855     }
856   }
857 
SuspendedForReconfiguration()858   void SuspendedForReconfiguration() {
859     if (audio_sender_state_ > AudioState::IDLE) {
860       LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
861                                               kLogAfSuspendForReconfig + "LocalSource",
862                                               "r_state: " + ToString(audio_receiver_state_) +
863                                                       "s_state: " + ToString(audio_sender_state_));
864       le_audio_source_hal_client_->SuspendedForReconfiguration();
865     }
866     if (audio_receiver_state_ > AudioState::IDLE) {
867       LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
868                                               kLogAfSuspendForReconfig + "LocalSink",
869                                               "r_state: " + ToString(audio_receiver_state_) +
870                                                       "s_state: " + ToString(audio_sender_state_));
871       le_audio_sink_hal_client_->SuspendedForReconfiguration();
872     }
873     StartReconfigurationTimeout(active_group_id_);
874   }
875 
ReconfigurationComplete(uint8_t directions)876   void ReconfigurationComplete(uint8_t directions) {
877     if (directions & bluetooth::le_audio::types::kLeAudioDirectionSink) {
878       LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
879                                               kLogAfReconfigComplete + "LocalSource",
880                                               "r_state: " + ToString(audio_receiver_state_) +
881                                                       "s_state: " + ToString(audio_sender_state_));
882 
883       le_audio_source_hal_client_->ReconfigurationComplete();
884     }
885     if (directions & bluetooth::le_audio::types::kLeAudioDirectionSource) {
886       LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
887                                               kLogAfReconfigComplete + "LocalSink",
888                                               "r_state: " + ToString(audio_receiver_state_) +
889                                                       "s_state: " + ToString(audio_sender_state_));
890 
891       le_audio_sink_hal_client_->ReconfigurationComplete();
892     }
893   }
894 
CancelLocalAudioSourceStreamingRequest()895   void CancelLocalAudioSourceStreamingRequest() {
896     le_audio_source_hal_client_->CancelStreamingRequest();
897 
898     LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
899                                             kLogAfCancel + "LocalSource",
900                                             "s_state: " + ToString(audio_sender_state_));
901 
902     audio_sender_state_ = AudioState::IDLE;
903   }
904 
CancelLocalAudioSinkStreamingRequest()905   void CancelLocalAudioSinkStreamingRequest() {
906     le_audio_sink_hal_client_->CancelStreamingRequest();
907 
908     LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
909                                             kLogAfCancel + "LocalSink",
910                                             "s_state: " + ToString(audio_receiver_state_));
911 
912     audio_receiver_state_ = AudioState::IDLE;
913   }
914 
CancelStreamingRequest()915   void CancelStreamingRequest() {
916     if (audio_sender_state_ >= AudioState::READY_TO_START) {
917       CancelLocalAudioSourceStreamingRequest();
918     }
919 
920     if (audio_receiver_state_ >= AudioState::READY_TO_START) {
921       CancelLocalAudioSinkStreamingRequest();
922     }
923   }
924 
group_add_node(const int group_id,const RawAddress & address,bool update_group_module=false)925   void group_add_node(const int group_id, const RawAddress& address,
926                       bool update_group_module = false) {
927     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
928     LeAudioDeviceGroup* new_group;
929     LeAudioDeviceGroup* old_group = nullptr;
930 
931     if (!leAudioDevice) {
932       /* TODO This part possible to remove as this is to handle adding device to
933        * the group which is unknown and not connected.
934        */
935       log::info("leAudioDevice unknown , address: {} group: 0x{:x}", address, group_id);
936 
937       if (group_id == bluetooth::groups::kGroupUnknown) {
938         return;
939       }
940 
941       log::info("Set member adding ...");
942       leAudioDevices_.Add(address, DeviceConnectState::CONNECTING_BY_USER);
943       leAudioDevice = leAudioDevices_.FindByAddress(address);
944     } else {
945       if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
946         old_group = aseGroups_.FindById(leAudioDevice->group_id_);
947       }
948     }
949 
950     auto id = DeviceGroups::Get()->GetGroupId(address, bluetooth::le_audio::uuid::kCapServiceUuid);
951     if (group_id == bluetooth::groups::kGroupUnknown) {
952       if (id == bluetooth::groups::kGroupUnknown) {
953         DeviceGroups::Get()->AddDevice(address, bluetooth::le_audio::uuid::kCapServiceUuid);
954         /* We will get back here when group will be created */
955         return;
956       }
957 
958       new_group = aseGroups_.Add(id);
959       if (!new_group) {
960         log::error("can't create group - group is already there?");
961         return;
962       }
963     } else {
964       log::assert_that(id == group_id, "group id missmatch? leaudio id: {}, groups module {}",
965                        group_id, id);
966       new_group = aseGroups_.FindById(group_id);
967       if (!new_group) {
968         new_group = aseGroups_.Add(group_id);
969       } else {
970         if (new_group->IsDeviceInTheGroup(leAudioDevice)) {
971           return;
972         }
973       }
974     }
975 
976     log::debug("New group {}, id: {}", std::format_ptr(new_group), new_group->group_id_);
977 
978     /* If device was in the group and it was not removed by the application,
979      * lets do it now
980      */
981     if (old_group) {
982       group_remove_node(old_group, address, update_group_module);
983     }
984 
985     new_group->AddNode(leAudioDevices_.GetByAddress(address));
986 
987     callbacks_->OnGroupNodeStatus(address, new_group->group_id_, GroupNodeStatus::ADDED);
988 
989     /* If device is connected and added to the group, lets read ASE states */
990     if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID) {
991       AseInitialStateReadRequest(leAudioDevice);
992     }
993 
994     if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
995       UpdateLocationsAndContextsAvailability(new_group);
996     }
997   }
998 
GroupAddNode(const int group_id,const RawAddress & address)999   void GroupAddNode(const int group_id, const RawAddress& address) override {
1000     auto id = DeviceGroups::Get()->GetGroupId(address, bluetooth::le_audio::uuid::kCapServiceUuid);
1001     if (id == group_id) {
1002       return;
1003     }
1004 
1005     if (id != bluetooth::groups::kGroupUnknown) {
1006       DeviceGroups::Get()->RemoveDevice(address, id);
1007     }
1008 
1009     DeviceGroups::Get()->AddDevice(address, bluetooth::le_audio::uuid::kCapServiceUuid, group_id);
1010   }
1011 
remove_group_if_possible(LeAudioDeviceGroup * group)1012   void remove_group_if_possible(LeAudioDeviceGroup* group) {
1013     if (!group) {
1014       log::debug("group is null");
1015       return;
1016     }
1017     log::debug("Group {}, id: {}, size: {}, is cig_state {}", std::format_ptr(group),
1018                group->group_id_, group->Size(), ToString(group->cig.GetState()));
1019     if (group->IsEmpty() && (group->cig.GetState() == bluetooth::le_audio::types::CigState::NONE)) {
1020       lastNotifiedGroupStreamStatusMap_.erase(group->group_id_);
1021       aseGroups_.Remove(group->group_id_);
1022     }
1023   }
1024 
group_remove_node(LeAudioDeviceGroup * group,const RawAddress & address,bool update_group_module=false)1025   void group_remove_node(LeAudioDeviceGroup* group, const RawAddress& address,
1026                          bool update_group_module = false) {
1027     int group_id = group->group_id_;
1028     group->RemoveNode(leAudioDevices_.GetByAddress(address));
1029 
1030     if (update_group_module) {
1031       int groups_group_id =
1032               DeviceGroups::Get()->GetGroupId(address, bluetooth::le_audio::uuid::kCapServiceUuid);
1033       if (groups_group_id == group_id) {
1034         DeviceGroups::Get()->RemoveDevice(address, group_id);
1035       }
1036     }
1037 
1038     callbacks_->OnGroupNodeStatus(address, group_id, GroupNodeStatus::REMOVED);
1039 
1040     /* Remove group if this was the last leAudioDevice in this group */
1041     if (group->IsEmpty()) {
1042       remove_group_if_possible(group);
1043       return;
1044     }
1045 
1046     /* Removing node from group requires updating group context availability */
1047     UpdateLocationsAndContextsAvailability(group);
1048   }
1049 
GroupRemoveNode(const int group_id,const RawAddress & address)1050   void GroupRemoveNode(const int group_id, const RawAddress& address) override {
1051     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1052     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1053 
1054     log::info("group_id: {} address: {}", group_id, address);
1055 
1056     if (!leAudioDevice) {
1057       log::error("Skipping unknown leAudioDevice, address: {}", address);
1058       return;
1059     }
1060 
1061     if (leAudioDevice->group_id_ != group_id) {
1062       log::error("Device is not in group_id: {}, but in group_id: {}", group_id,
1063                  leAudioDevice->group_id_);
1064       return;
1065     }
1066 
1067     if (group == NULL) {
1068       log::error("device not in the group ?!");
1069       return;
1070     }
1071 
1072     if (leAudioDevice->HaveActiveAse()) {
1073       SetDeviceAsRemovePendingAndStopGroup(leAudioDevice);
1074       return;
1075     }
1076 
1077     group_remove_node(group, address, true);
1078   }
1079 
ChooseMetadataContextType(AudioContexts metadata_context_type)1080   AudioContexts ChooseMetadataContextType(AudioContexts metadata_context_type) {
1081     /* This function takes already filtered contexts which we are plannig to use
1082      * in the Enable or UpdateMetadata command.
1083      * Note we are not changing stream configuration here, but just the list of
1084      * the contexts in the Metadata which will be provide to remote side.
1085      * Ideally, we should send all the bits we have, but not all headsets like
1086      * it.
1087      */
1088     if (osi_property_get_bool(kAllowMultipleContextsInMetadata, true)) {
1089       return metadata_context_type;
1090     }
1091 
1092     log::debug("Converting to single context type: {}", metadata_context_type.to_string());
1093 
1094     /* Mini policy */
1095     if (metadata_context_type.any()) {
1096       LeAudioContextType context_priority_list[] = {
1097               /* Highest priority first */
1098               LeAudioContextType::CONVERSATIONAL, LeAudioContextType::RINGTONE,
1099               LeAudioContextType::LIVE,           LeAudioContextType::VOICEASSISTANTS,
1100               LeAudioContextType::GAME,           LeAudioContextType::MEDIA,
1101               LeAudioContextType::EMERGENCYALARM, LeAudioContextType::ALERTS,
1102               LeAudioContextType::INSTRUCTIONAL,  LeAudioContextType::NOTIFICATIONS,
1103               LeAudioContextType::SOUNDEFFECTS,
1104       };
1105       for (auto ct : context_priority_list) {
1106         if (metadata_context_type.test(ct)) {
1107           log::debug("Converted to single context type: {}", ToString(ct));
1108           return AudioContexts(ct);
1109         }
1110       }
1111     }
1112 
1113     /* Fallback to BAP mandated context type */
1114     log::warn("Invalid/unknown context, using 'UNSPECIFIED'");
1115     return AudioContexts(LeAudioContextType::UNSPECIFIED);
1116   }
1117 
1118   /* Return true if stream is started */
GroupStream(LeAudioDeviceGroup * group,LeAudioContextType configuration_context_type,BidirectionalPair<AudioContexts> remote_contexts)1119   bool GroupStream(LeAudioDeviceGroup* group, LeAudioContextType configuration_context_type,
1120                    BidirectionalPair<AudioContexts> remote_contexts) {
1121     log::assert_that(group != nullptr, "Group shall not be null");
1122 
1123     log::debug(
1124             "configuration_context_type= {}, remote sink contexts= {}, remote source contexts= {}",
1125             ToString(configuration_context_type), ToString(remote_contexts.sink),
1126             ToString(remote_contexts.source));
1127 
1128     if (configuration_context_type >= LeAudioContextType::RFU) {
1129       log::error("stream context type is not supported: {}",
1130                  ToHexString(configuration_context_type));
1131       return false;
1132     }
1133 
1134     log::debug("group state={}, target_state={}", ToString(group->GetState()),
1135                ToString(group->GetTargetState()));
1136 
1137     if (!group->IsAnyDeviceConnected()) {
1138       log::error("group {} is not connected", group->group_id_);
1139       return false;
1140     }
1141 
1142     /* Check if any group is in the transition state. If so, we don't allow to
1143      * start new group to stream
1144      */
1145     if (group->IsInTransition()) {
1146       /* WARNING: Due to group state machine limitations, we should not
1147        * interrupt any ongoing transition. We will check if another
1148        * reconfiguration is needed once the group reaches streaming state.
1149        */
1150       log::warn(
1151               "Group is already in the transition state. Waiting for the target "
1152               "state to be reached.");
1153       return false;
1154     }
1155 
1156     /* Do not put the TBS CCID when not using Telecom for the VoIP calls. */
1157     auto ccid_contexts = remote_contexts;
1158     if (IsInVoipCall() && !IsInCall()) {
1159       ccid_contexts.sink.unset(LeAudioContextType::CONVERSATIONAL);
1160       ccid_contexts.source.unset(LeAudioContextType::CONVERSATIONAL);
1161     }
1162 
1163     bool group_is_streaming = group->IsStreaming();
1164 
1165     BidirectionalPair<std::vector<uint8_t>> ccids = {
1166             .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(ccid_contexts.sink),
1167             .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(ccid_contexts.source)};
1168     if (group->IsPendingConfiguration()) {
1169       return groupStateMachine_->ConfigureStream(group, configuration_context_type_,
1170                                                  remote_contexts, ccids);
1171     } else if (!group_is_streaming) {
1172       speed_start_setup(group->group_id_, configuration_context_type, group->NumOfConnected());
1173     }
1174 
1175     /* If assistant have some connected delegators that needs to be informed
1176      * when there would be request to stream unicast.
1177      */
1178     if (!sink_monitor_mode_ && source_monitor_mode_ && !group_is_streaming) {
1179       notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_REQUESTED);
1180     }
1181 
1182     bool result = groupStateMachine_->StartStream(group, configuration_context_type,
1183                                                   remote_contexts, ccids);
1184 
1185     if (result && !group_is_streaming) {
1186       /* Notify Java about new configuration when start stream has been accepted and
1187        * it is not metadata update
1188        */
1189       SendAudioGroupCurrentCodecConfigChanged(group);
1190     }
1191 
1192     return result;
1193   }
1194 
GroupStream(const int group_id,uint16_t context_type)1195   void GroupStream(const int group_id, uint16_t context_type) override {
1196     BidirectionalPair<AudioContexts> initial_contexts = {AudioContexts(context_type),
1197                                                          AudioContexts(context_type)};
1198     auto group = aseGroups_.FindById(group_id);
1199     if (!group) {
1200       log::error("unknown group id: {}", group_id);
1201       return;
1202     }
1203 
1204     GroupStream(group, LeAudioContextType(context_type), initial_contexts);
1205   }
1206 
GroupSuspend(const int group_id)1207   void GroupSuspend(const int group_id) override {
1208     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1209 
1210     if (!group) {
1211       log::error("unknown group id: {}", group_id);
1212       return;
1213     }
1214 
1215     if (!group->IsAnyDeviceConnected()) {
1216       log::error("group is not connected");
1217       return;
1218     }
1219 
1220     if (group->IsInTransition()) {
1221       log::info(", group is in transition from: {} to: {}", ToString(group->GetState()),
1222                 ToString(group->GetTargetState()));
1223       return;
1224     }
1225 
1226     if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
1227       log::error(", invalid current state of group: {}", ToString(group->GetState()));
1228       return;
1229     }
1230 
1231     groupStateMachine_->SuspendStream(group);
1232   }
1233 
GroupStop(const int group_id)1234   void GroupStop(const int group_id) override {
1235     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1236 
1237     if (!group) {
1238       log::error("unknown group id: {}", group_id);
1239       return;
1240     }
1241 
1242     if (group->IsEmpty()) {
1243       log::error("group is empty");
1244       return;
1245     }
1246 
1247     groupStateMachine_->StopStream(group);
1248   }
1249 
GroupDestroy(const int group_id)1250   void GroupDestroy(const int group_id) override {
1251     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1252 
1253     if (!group) {
1254       log::error("unknown group id: {}", group_id);
1255       return;
1256     }
1257 
1258     // Disconnect and remove each device within the group
1259     auto* dev = group->GetFirstDevice();
1260     while (dev) {
1261       auto* next_dev = group->GetNextDevice(dev);
1262       RemoveDevice(dev->address_);
1263       dev = next_dev;
1264     }
1265   }
1266 
SetCodecConfigPreference(int group_id,bluetooth::le_audio::btle_audio_codec_config_t input_codec_config,bluetooth::le_audio::btle_audio_codec_config_t output_codec_config)1267   void SetCodecConfigPreference(
1268           int group_id, bluetooth::le_audio::btle_audio_codec_config_t input_codec_config,
1269           bluetooth::le_audio::btle_audio_codec_config_t output_codec_config) override {
1270     if (!com::android::bluetooth::flags::leaudio_set_codec_config_preference()) {
1271       log::debug("leaudio_set_codec_config_preference flag is not enabled");
1272       return;
1273     }
1274 
1275     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1276 
1277     if (!group) {
1278       log::error("Unknown group id: %d", group_id);
1279     }
1280 
1281     if (group->SetPreferredAudioSetConfiguration(input_codec_config, output_codec_config)) {
1282       log::info("group id: {}, setting preferred codec is successful.", group_id);
1283     } else {
1284       log::warn("group id: {}, setting preferred codec is failed.", group_id);
1285       return;
1286     }
1287 
1288     if (group_id != active_group_id_) {
1289       log::warn("Selected group is not active.");
1290       return;
1291     }
1292 
1293     if (SetConfigurationAndStopStreamWhenNeeded(group, group->GetConfigurationContextType())) {
1294       log::debug("Group id {} do the reconfiguration based on preferred codec config", group_id);
1295     } else {
1296       log::debug("Group id {} preferred codec config is not changed", group_id);
1297     }
1298   }
1299 
IsUsingPreferredCodecConfig(int group_id,int context_type)1300   bool IsUsingPreferredCodecConfig(int group_id, int context_type) {
1301     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1302     if (!group) {
1303       log::error("Unknown group id: %d", group_id);
1304       return false;
1305     }
1306 
1307     return group->IsUsingPreferredAudioSetConfiguration(
1308             static_cast<LeAudioContextType>(context_type));
1309   }
1310 
SetCcidInformation(int ccid,int context_type)1311   void SetCcidInformation(int ccid, int context_type) override {
1312     log::debug("Ccid: {}, context type {}", ccid, context_type);
1313 
1314     ContentControlIdKeeper::GetInstance()->SetCcid(AudioContexts(context_type), ccid);
1315   }
1316 
initReconfiguration(LeAudioDeviceGroup * group,LeAudioContextType previous_context_type)1317   void initReconfiguration(LeAudioDeviceGroup* group, LeAudioContextType previous_context_type) {
1318     log::debug(" group_id: {}, previous context_type {}", group->group_id_,
1319                ToString(previous_context_type));
1320     pre_configuration_context_type_ = previous_context_type;
1321     group->SetPendingConfiguration();
1322     groupStateMachine_->StopStream(group);
1323     speed_start_setup(group->group_id_, configuration_context_type_, group->NumOfConnected(), true);
1324   }
1325 
SetInCall(bool in_call)1326   void SetInCall(bool in_call) override {
1327     log::debug("in_call: {}", in_call);
1328     if (in_call == in_call_) {
1329       log::verbose("no state change {}", in_call);
1330       return;
1331     }
1332 
1333     in_call_ = in_call;
1334 
1335     if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
1336       log::debug("There is no active group");
1337       return;
1338     }
1339 
1340     LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1341     if (!group || !group->IsStreaming()) {
1342       log::debug("{} is not streaming", active_group_id_);
1343       return;
1344     }
1345 
1346     bool reconfigure = false;
1347 
1348     if (in_call_) {
1349       in_call_metadata_context_types_ = local_metadata_context_types_;
1350 
1351       log::debug("in_call_metadata_context_types_ sink: {}  source: {}",
1352                  in_call_metadata_context_types_.sink.to_string(),
1353                  in_call_metadata_context_types_.source.to_string());
1354 
1355       auto audio_set_conf = group->GetConfiguration(LeAudioContextType::CONVERSATIONAL);
1356       if (audio_set_conf && group->IsGroupConfiguredTo(*audio_set_conf)) {
1357         log::info("Call is coming, but CIG already set for a call");
1358         return;
1359       }
1360       log::info("Call is coming, speed up reconfiguration for a call");
1361       local_metadata_context_types_.sink.clear();
1362       local_metadata_context_types_.source.clear();
1363       reconfigure = true;
1364     } else {
1365       if (configuration_context_type_ == LeAudioContextType::CONVERSATIONAL) {
1366         log::info("Call is ended, speed up reconfiguration for media");
1367         // Preemptively remove conversational context for reconfiguration speed up
1368         in_call_metadata_context_types_.sink.unset(LeAudioContextType::CONVERSATIONAL);
1369         in_call_metadata_context_types_.source.unset(LeAudioContextType::CONVERSATIONAL);
1370         if (in_call_metadata_context_types_.sink.none() &&
1371             in_call_metadata_context_types_.source.none()) {
1372           log::debug("No metadata, set default Media");
1373           in_call_metadata_context_types_.source.set(LeAudioContextType::MEDIA);
1374         }
1375         local_metadata_context_types_ = in_call_metadata_context_types_;
1376         log::debug("restored local_metadata_context_types_ sink: {}  source: {}",
1377                    local_metadata_context_types_.sink.to_string(),
1378                    local_metadata_context_types_.source.to_string());
1379         in_call_metadata_context_types_.sink.clear();
1380         in_call_metadata_context_types_.source.clear();
1381         reconfigure = true;
1382       }
1383 
1384       /* When inCall mode is disabled and remaining metadata is no longer supported by group -
1385        * stream should be stopped.
1386        */
1387       if (com::android::bluetooth::flags::leaudio_stop_updated_to_not_available_context_stream()) {
1388         if (stopStreamIfCurrentContextTypeIsNotAllowed(
1389                     bluetooth::le_audio::types::kLeAudioDirectionSource, group,
1390                     local_metadata_context_types_.sink)) {
1391           log::info(
1392                   "After disable InCall mode, updated sink metadata contexts are not allowed "
1393                   "context types: {} | configured: {} vs allowed context mask: {}",
1394                   ToString(local_metadata_context_types_.sink),
1395                   ToString(configuration_context_type_),
1396                   ToString(group->GetAllowedContextMask(
1397                           bluetooth::le_audio::types::kLeAudioDirectionSource)));
1398           return;
1399         }
1400 
1401         if (stopStreamIfCurrentContextTypeIsNotAllowed(
1402                            bluetooth::le_audio::types::kLeAudioDirectionSink, group,
1403                            local_metadata_context_types_.source)) {
1404           log::info(
1405                   "After disable InCall mode, updated source metadata contexts are not allowed "
1406                   "context types: {} | configured: {} vs allowed context mask: {}",
1407                   ToString(local_metadata_context_types_.source),
1408                   ToString(configuration_context_type_),
1409                   ToString(group->GetAllowedContextMask(
1410                           bluetooth::le_audio::types::kLeAudioDirectionSink)));
1411           return;
1412         }
1413       }
1414     }
1415 
1416     if (reconfigure) {
1417       ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSink);
1418     }
1419   }
1420 
IsInCall()1421   bool IsInCall() override { return in_call_; }
1422 
SetInVoipCall(bool in_call)1423   void SetInVoipCall(bool in_call) override {
1424     log::debug("in_voip_call: {}", in_call);
1425     in_voip_call_ = in_call;
1426   }
1427 
IsInVoipCall()1428   bool IsInVoipCall() override { return in_voip_call_; }
1429 
IsInVoipOrRegularCall()1430   bool IsInVoipOrRegularCall() { return IsInCall() || IsInVoipCall(); }
1431 
IsInStreaming()1432   bool IsInStreaming() override {
1433     return audio_sender_state_ == AudioState::STARTED ||
1434            audio_receiver_state_ == AudioState::STARTED;
1435   }
1436 
SetUnicastMonitorMode(uint8_t direction,bool enable)1437   void SetUnicastMonitorMode(uint8_t direction, bool enable) override {
1438     if (direction == bluetooth::le_audio::types::kLeAudioDirectionSink) {
1439       /* Cleanup Sink HAL client interface if listening mode is toggled off
1440        * before group activation (active group context would take care of
1441        * Sink HAL client cleanup).
1442        */
1443       if (!com::android::bluetooth::flags::leaudio_use_audio_recording_listener()) {
1444         if (sink_monitor_mode_ && !enable && le_audio_sink_hal_client_ &&
1445             active_group_id_ == bluetooth::groups::kGroupUnknown) {
1446           local_metadata_context_types_.sink.clear();
1447           le_audio_sink_hal_client_->Stop();
1448           le_audio_sink_hal_client_.reset();
1449         }
1450       }
1451 
1452       log::debug("enable: {}", enable);
1453       sink_monitor_mode_ = enable;
1454     } else if (direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
1455       log::debug("enable: {}", enable);
1456       source_monitor_mode_ = enable;
1457 
1458       if (!enable) {
1459         return;
1460       }
1461 
1462       LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1463       if (!group) {
1464         notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
1465 
1466         return;
1467       }
1468 
1469       if (group->IsStreaming()) {
1470         notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING);
1471       } else {
1472         notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
1473       }
1474     } else {
1475       log::error("invalid direction: 0x{:02x} monitor mode set", direction);
1476     }
1477   }
1478 
SendAudioProfilePreferences(const int group_id,bool is_output_preference_le_audio,bool is_duplex_preference_le_audio)1479   void SendAudioProfilePreferences(const int group_id, bool is_output_preference_le_audio,
1480                                    bool is_duplex_preference_le_audio) override {
1481     log::info(
1482             "group_id: {}, is_output_preference_le_audio: {}, "
1483             "is_duplex_preference_le_audio: {}",
1484             group_id, is_output_preference_le_audio, is_duplex_preference_le_audio);
1485     if (group_id == bluetooth::groups::kGroupUnknown) {
1486       log::warn("Unknown group_id");
1487       return;
1488     }
1489     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1490     if (!group) {
1491       log::warn("group_id {} does not exist", group_id);
1492       return;
1493     }
1494 
1495     group->is_output_preference_le_audio = is_output_preference_le_audio;
1496     group->is_duplex_preference_le_audio = is_duplex_preference_le_audio;
1497   }
1498 
SetGroupAllowedContextMask(int group_id,int sink_context_types,int source_context_types)1499   void SetGroupAllowedContextMask(int group_id, int sink_context_types,
1500                                   int source_context_types) override {
1501     log::info("group_id: {}, sink context types: {}, source context types: {}", group_id,
1502               sink_context_types, source_context_types);
1503 
1504     if (group_id == bluetooth::groups::kGroupUnknown) {
1505       log::warn("Unknown group_id");
1506       return;
1507     }
1508     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1509     if (!group) {
1510       log::warn("group_id {} does not exist", group_id);
1511       return;
1512     }
1513 
1514     BidirectionalPair<AudioContexts> allowed_contexts = {
1515             .sink = AudioContexts(sink_context_types),
1516             .source = AudioContexts(source_context_types),
1517     };
1518 
1519     group->SetAllowedContextMask(allowed_contexts);
1520   }
1521 
StartAudioSession(LeAudioDeviceGroup * group)1522   void StartAudioSession(LeAudioDeviceGroup* group) {
1523     /* This function is called when group is not yet set to active.
1524      * This is why we don't have to check if session is started already.
1525      * Just check if it is acquired.
1526      */
1527     log::assert_that(active_group_id_ == bluetooth::groups::kGroupUnknown,
1528                      "Active group is not set.");
1529     log::assert_that(le_audio_source_hal_client_ != nullptr, "Source session not acquired");
1530     log::assert_that(le_audio_sink_hal_client_ != nullptr, "Sink session not acquired");
1531 
1532     DsaModes dsa_modes = {DsaMode::DISABLED};
1533     dsa_modes = group->GetAllowedDsaModes();
1534 
1535     /* We assume that peer device always use same frame duration */
1536     uint32_t frame_duration_us = 0;
1537     if (!current_encoder_config_.IsInvalid()) {
1538       frame_duration_us = current_encoder_config_.data_interval_us;
1539     } else if (!current_decoder_config_.IsInvalid()) {
1540       frame_duration_us = current_decoder_config_.data_interval_us;
1541     } else {
1542       log::assert_that(true, "Both configs are invalid");
1543     }
1544 
1545     stack::l2cap::get_interface().L2CA_SetEcosystemBaseInterval(frame_duration_us / 1250);
1546 
1547     // Scale by the codec frame blocks per SDU if set
1548     uint8_t codec_frame_blocks_per_sdu =
1549             group->stream_conf.stream_params.source.stream_config.codec_frames_blocks_per_sdu ?: 1;
1550     audio_framework_source_config.data_interval_us = frame_duration_us * codec_frame_blocks_per_sdu;
1551 
1552     le_audio_source_hal_client_->Start(audio_framework_source_config, audioSinkReceiver, dsa_modes);
1553 
1554     /* We use same frame duration for sink/source */
1555     audio_framework_sink_config.data_interval_us = frame_duration_us * codec_frame_blocks_per_sdu;
1556 
1557     /* If group supports more than 16kHz for the microphone in converstional
1558      * case let's use that also for Audio Framework.
1559      */
1560     auto sink_configuration = group->GetAudioSessionCodecConfigForDirection(
1561             LeAudioContextType::CONVERSATIONAL,
1562             bluetooth::le_audio::types::kLeAudioDirectionSource);
1563     if (!sink_configuration.IsInvalid() &&
1564         sink_configuration.sample_rate > bluetooth::audio::le_audio::kSampleRate16000) {
1565       audio_framework_sink_config.sample_rate = sink_configuration.sample_rate;
1566     }
1567 
1568     le_audio_sink_hal_client_->Start(audio_framework_sink_config, audioSourceReceiver, dsa_modes);
1569   }
1570 
isOutputPreferenceLeAudio(const RawAddress & address)1571   bool isOutputPreferenceLeAudio(const RawAddress& address) {
1572     log::info("address: {}, active_group_id_: {}", address.ToStringForLogging(), active_group_id_);
1573     std::vector<RawAddress> active_leaudio_devices = GetGroupDevices(active_group_id_);
1574     if (std::find(active_leaudio_devices.begin(), active_leaudio_devices.end(), address) ==
1575         active_leaudio_devices.end()) {
1576       log::info("Device {} is not active for LE Audio", address.ToStringForLogging());
1577       return false;
1578     }
1579 
1580     LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1581     log::info("active_group_id: {}, is_output_preference_le_audio_: {}", group->group_id_,
1582               group->is_output_preference_le_audio);
1583     return group->is_output_preference_le_audio;
1584   }
1585 
isDuplexPreferenceLeAudio(const RawAddress & address)1586   bool isDuplexPreferenceLeAudio(const RawAddress& address) {
1587     log::info("address: {}, active_group_id_: {}", address.ToStringForLogging(), active_group_id_);
1588     std::vector<RawAddress> active_leaudio_devices = GetGroupDevices(active_group_id_);
1589     if (std::find(active_leaudio_devices.begin(), active_leaudio_devices.end(), address) ==
1590         active_leaudio_devices.end()) {
1591       log::info("Device {} is not active for LE Audio", address.ToStringForLogging());
1592       return false;
1593     }
1594 
1595     LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
1596     log::info("active_group_id: {}, is_duplex_preference_le_audio: {}", group->group_id_,
1597               group->is_duplex_preference_le_audio);
1598     return group->is_duplex_preference_le_audio;
1599   }
1600 
groupSetAndNotifyInactive(void)1601   void groupSetAndNotifyInactive(void) {
1602     if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
1603       return;
1604     }
1605     sink_monitor_notified_status_ = std::nullopt;
1606     source_monitor_notified_status_ = std::nullopt;
1607     log::info("Group id: {}", active_group_id_);
1608 
1609     StopSuspendTimeout();
1610 
1611     StopAudio();
1612     ClientAudioInterfaceRelease();
1613 
1614     callbacks_->OnGroupStatus(active_group_id_, GroupStatus::INACTIVE);
1615     active_group_id_ = bluetooth::groups::kGroupUnknown;
1616   }
1617 
ConfigureStream(LeAudioDeviceGroup * group,bool up_to_qos_configured)1618   bool ConfigureStream(LeAudioDeviceGroup* group, bool up_to_qos_configured) {
1619     log::debug("group_id: {}", group->group_id_);
1620 
1621     BidirectionalPair<std::vector<uint8_t>> ccids = {
1622             .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(
1623                     local_metadata_context_types_.sink),
1624             .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(
1625                     local_metadata_context_types_.source)};
1626 
1627     group->SetPendingConfiguration();
1628     if (!groupStateMachine_->ConfigureStream(group, configuration_context_type_,
1629                                              local_metadata_context_types_, ccids,
1630                                              up_to_qos_configured)) {
1631       group->ClearPendingConfiguration();
1632       return false;
1633     }
1634 
1635     return true;
1636   }
1637 
PrepareStreamForAConversational(LeAudioDeviceGroup * group)1638   void PrepareStreamForAConversational(LeAudioDeviceGroup* group) {
1639     log::debug("group_id: {}", group->group_id_);
1640 
1641     auto remote_direction = bluetooth::le_audio::types::kLeAudioDirectionSink;
1642     ReconfigureOrUpdateRemote(group, remote_direction);
1643 
1644     if (configuration_context_type_ != LeAudioContextType::CONVERSATIONAL) {
1645       log::error("Something went wrong {} != {} ", ToString(configuration_context_type_),
1646                  ToString(LeAudioContextType::CONVERSATIONAL));
1647       return;
1648     }
1649 
1650     if (!ConfigureStream(group, true)) {
1651       log::info("Reconfiguration is needed for group {}", group->group_id_);
1652       initReconfiguration(group, LeAudioContextType::UNSPECIFIED);
1653     }
1654   }
1655 
GroupSetActive(const int group_id)1656   void GroupSetActive(const int group_id) override {
1657     log::info("group_id: {}", group_id);
1658 
1659     if (group_id == bluetooth::groups::kGroupUnknown) {
1660       if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
1661         callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1662         /* Nothing to do */
1663         return;
1664       }
1665 
1666       log::info("Active group_id changed {} -> {}", active_group_id_, group_id);
1667       auto group_id_to_close = active_group_id_;
1668       groupSetAndNotifyInactive();
1669       GroupStop(group_id_to_close);
1670 
1671       return;
1672     }
1673 
1674     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1675     if (!group) {
1676       log::error("Invalid group: {}", static_cast<int>(group_id));
1677       callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1678       return;
1679     }
1680 
1681     if (group->NumOfConnected() == 0) {
1682       log::error("Group: {} is not connected anymore", static_cast<int>(group_id));
1683       callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1684       return;
1685     }
1686 
1687     if (active_group_id_ != bluetooth::groups::kGroupUnknown) {
1688       if (active_group_id_ == group_id) {
1689         log::info("Group is already active: {}", static_cast<int>(active_group_id_));
1690         callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
1691         return;
1692       }
1693       log::info("switching active group to: {}", group_id);
1694 
1695       auto result = CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
1696               le_audio_source_hal_client_.get(), le_audio_sink_hal_client_.get(), false);
1697       log::assert_that(result, "Could not update session to codec manager");
1698     }
1699 
1700     if (!le_audio_source_hal_client_) {
1701       le_audio_source_hal_client_ = LeAudioSourceAudioHalClient::AcquireUnicast();
1702       if (!le_audio_source_hal_client_) {
1703         log::error("could not acquire audio source interface");
1704         callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1705         return;
1706       }
1707     }
1708 
1709     if (!le_audio_sink_hal_client_) {
1710       le_audio_sink_hal_client_ = LeAudioSinkAudioHalClient::AcquireUnicast();
1711       if (!le_audio_sink_hal_client_) {
1712         log::error("could not acquire audio sink interface");
1713         callbacks_->OnGroupStatus(group_id, GroupStatus::INACTIVE);
1714         return;
1715       }
1716     }
1717 
1718     auto result = CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
1719             le_audio_source_hal_client_.get(), le_audio_sink_hal_client_.get(), true);
1720     log::assert_that(result, "Could not update session to codec manager");
1721 
1722     /* Mini policy: Try configure audio HAL sessions with most recent context.
1723      * If reconfiguration is not needed it means, context type is not supported.
1724      * If most recent scenario is not supported, try to find first supported.
1725      */
1726     LeAudioContextType default_context_type = configuration_context_type_;
1727     if (!group->IsAudioSetConfigurationAvailable(default_context_type)) {
1728       if (group->IsAudioSetConfigurationAvailable(LeAudioContextType::UNSPECIFIED)) {
1729         default_context_type = LeAudioContextType::UNSPECIFIED;
1730         default_context_type = LeAudioContextType::UNSPECIFIED;
1731       } else {
1732         for (LeAudioContextType context_type : kLeAudioContextAllTypesArray) {
1733           if (group->IsAudioSetConfigurationAvailable(context_type)) {
1734             default_context_type = context_type;
1735             break;
1736           }
1737         }
1738       }
1739     }
1740 
1741     /* Only update the configuration audio context and audio coding session
1742      * parameters if needed.
1743      */
1744     UpdateConfigAndCheckIfReconfigurationIsNeeded(group, default_context_type);
1745 
1746     auto previous_active_group = active_group_id_;
1747     log::info("Active group_id changed {} -> {}", previous_active_group, group_id);
1748 
1749     bool prepare_for_a_call = IsInVoipOrRegularCall();
1750 
1751     if (previous_active_group == bluetooth::groups::kGroupUnknown) {
1752       /* Expose audio sessions if there was no previous active group */
1753       StartAudioSession(group);
1754       active_group_id_ = group_id;
1755 
1756       /* For the fresh activated LeAudio device, do configuration ahead only when
1757        * phone is in a call.
1758        */
1759       if (prepare_for_a_call) {
1760         PrepareStreamForAConversational(group);
1761       }
1762 
1763     } else {
1764       /* In case there was an active group. Stop the stream, but before that, set
1765        * the new group so the group change is correctly handled in OnStateMachineStatusReportCb
1766        */
1767       active_group_id_ = group_id;
1768       SuspendedForReconfiguration();
1769       GroupStop(previous_active_group);
1770       /* Note: On purpose we are not sending INACTIVE status up to Java, because previous active
1771        * group will be provided in ACTIVE status. This is in order to have single call to audio
1772        * framework
1773        * If group become active while phone call, let's configure it right away up to
1774        * the QoS configured state so when audio framework resumes the stream,
1775        * only Enable will left.
1776        * Otherwise, if there is group switch, let's move ASEs to Configured state.
1777        */
1778 
1779       if (!ConfigureStream(group, prepare_for_a_call)) {
1780         log::info("Could not configure group {}", group->group_id_);
1781       }
1782     }
1783 
1784     /* Reset sink and source listener notified status */
1785     sink_monitor_notified_status_ = std::nullopt;
1786     source_monitor_notified_status_ = std::nullopt;
1787 
1788     SendAudioGroupSelectableCodecConfigChanged(group);
1789     SendAudioGroupCurrentCodecConfigChanged(group);
1790     callbacks_->OnGroupStatus(active_group_id_, GroupStatus::ACTIVE);
1791   }
1792 
SetEnableState(const RawAddress & address,bool enabled)1793   void SetEnableState(const RawAddress& address, bool enabled) override {
1794     log::info("{}: {}", address, enabled ? "enabled" : "disabled");
1795     auto leAudioDevice = leAudioDevices_.FindByAddress(address);
1796     if (leAudioDevice == nullptr) {
1797       log::warn("{} is null", address);
1798       return;
1799     }
1800 
1801     auto group_id = leAudioDevice->group_id_;
1802     auto group = aseGroups_.FindById(group_id);
1803     if (group == nullptr) {
1804       log::warn("Group {} is not available", group_id);
1805       return;
1806     }
1807 
1808     if (enabled) {
1809       group->Enable(gatt_if_, reconnection_mode_);
1810     } else {
1811       group->Disable(gatt_if_);
1812     }
1813   }
1814 
RemoveDevice(const RawAddress & address)1815   void RemoveDevice(const RawAddress& address) override {
1816     log::info(": {}", address);
1817     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1818     if (!leAudioDevice) {
1819       return;
1820     }
1821 
1822     /* Remove device from the background connect if it is there */
1823     BTA_GATTC_CancelOpen(gatt_if_, address, false);
1824     btif_storage_set_leaudio_autoconnect(address, false);
1825 
1826     log::info("{}, state: {}", address,
1827               bluetooth::common::ToString(leAudioDevice->GetConnectionState()));
1828     auto connection_state = leAudioDevice->GetConnectionState();
1829     switch (connection_state) {
1830       case DeviceConnectState::REMOVING:
1831         /* Just return, and let device disconnect */
1832         return;
1833       case DeviceConnectState::CONNECTED:
1834       case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
1835       case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
1836         /* ACL exist in this case, disconnect and mark as removing */
1837         Disconnect(address);
1838         [[fallthrough]];
1839       case DeviceConnectState::DISCONNECTING:
1840       case DeviceConnectState::DISCONNECTING_AND_RECOVER:
1841         /* Device is disconnecting, just mark it shall be removed after all. */
1842         leAudioDevice->SetConnectionState(DeviceConnectState::REMOVING);
1843         return;
1844       case DeviceConnectState::CONNECTING_AUTOCONNECT:
1845         /* Fallthrough as for AUTOCONNECT it might be that device is doing direct connect
1846          * in case of previous connection timeout.
1847          */
1848       case DeviceConnectState::CONNECTING_BY_USER:
1849         BTA_GATTC_CancelOpen(gatt_if_, address, true);
1850         leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
1851         break;
1852       case DeviceConnectState::DISCONNECTED:
1853         /* Do nothing, just remove device  */
1854         break;
1855     }
1856 
1857     /* Remove the group assignment if not yet removed. It might happen that the
1858      * group module has already called the appropriate callback and we have
1859      * already removed the group assignment.
1860      */
1861     if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
1862       auto group = aseGroups_.FindById(leAudioDevice->group_id_);
1863       group_remove_node(group, address, true);
1864     }
1865 
1866     leAudioDevices_.Remove(address);
1867   }
1868 
Connect(const RawAddress & address)1869   void Connect(const RawAddress& address) override {
1870     log::info(": {}", address);
1871 
1872     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1873     if (!leAudioDevice) {
1874       if (!BTM_IsBonded(address, BT_TRANSPORT_LE)) {
1875         log::error("Connecting  {} when not bonded", address);
1876         callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
1877         return;
1878       }
1879       leAudioDevices_.Add(address, DeviceConnectState::CONNECTING_BY_USER);
1880     } else {
1881       auto current_connect_state = leAudioDevice->GetConnectionState();
1882       if ((current_connect_state == DeviceConnectState::CONNECTED) ||
1883           (current_connect_state == DeviceConnectState::CONNECTING_BY_USER)) {
1884         log::error("Device {} is in invalid state: {}", leAudioDevice->address_,
1885                    bluetooth::common::ToString(current_connect_state));
1886 
1887         return;
1888       }
1889 
1890       if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
1891         auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
1892         if (!group) {
1893           log::warn("{}, trying to connect to disabled group id {}", address,
1894                     leAudioDevice->group_id_);
1895           callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
1896           return;
1897         }
1898       }
1899 
1900       leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_BY_USER);
1901 
1902       bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
1903               leAudioDevice->group_id_, address, ConnectionState::CONNECTING,
1904               bluetooth::le_audio::ConnectionStatus::SUCCESS);
1905     }
1906 
1907     BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
1908   }
1909 
GetGroupDevices(const int group_id)1910   std::vector<RawAddress> GetGroupDevices(const int group_id) override {
1911     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
1912     std::vector<RawAddress> all_group_device_addrs;
1913 
1914     if (group != nullptr) {
1915       LeAudioDevice* leAudioDevice = group->GetFirstDevice();
1916       while (leAudioDevice) {
1917         all_group_device_addrs.push_back(leAudioDevice->address_);
1918         leAudioDevice = group->GetNextDevice(leAudioDevice);
1919       };
1920     }
1921 
1922     return all_group_device_addrs;
1923   }
1924 
1925   /* Restore paired device from storage to recreate groups */
AddFromStorage(const RawAddress & address,bool autoconnect,std::optional<int> sink_audio_location,std::optional<int> source_audio_location,int sink_supported_context_types,int source_supported_context_types,const std::vector<uint8_t> & handles,const std::vector<uint8_t> & sink_pacs,const std::vector<uint8_t> & source_pacs,const std::vector<uint8_t> & ases,const std::vector<uint8_t> & gmap)1926   void AddFromStorage(const RawAddress& address, bool autoconnect,
1927                       std::optional<int> sink_audio_location,
1928                       std::optional<int> source_audio_location, int sink_supported_context_types,
1929                       int source_supported_context_types, const std::vector<uint8_t>& handles,
1930                       const std::vector<uint8_t>& sink_pacs,
1931                       const std::vector<uint8_t>& source_pacs, const std::vector<uint8_t>& ases,
1932                       const std::vector<uint8_t>& gmap) {
1933     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
1934 
1935     if (leAudioDevice) {
1936       log::error("Device is already loaded. Nothing to do.");
1937       return;
1938     }
1939 
1940     log::info(
1941             "restoring: {}, autoconnect {}, sink_audio_location: {}, "
1942             "source_audio_location: {}, sink_supported_context_types : 0x{:04x}, "
1943             "source_supported_context_types 0x{:04x}",
1944             address, autoconnect,
1945             sink_audio_location ? std::to_string(sink_audio_location.value()) : "none",
1946             source_audio_location ? std::to_string(source_audio_location.value()) : "none",
1947             sink_supported_context_types, source_supported_context_types);
1948 
1949     leAudioDevices_.Add(address, DeviceConnectState::DISCONNECTED);
1950     leAudioDevice = leAudioDevices_.FindByAddress(address);
1951 
1952     int group_id =
1953             DeviceGroups::Get()->GetGroupId(address, bluetooth::le_audio::uuid::kCapServiceUuid);
1954     if (group_id != bluetooth::groups::kGroupUnknown) {
1955       group_add_node(group_id, address);
1956     }
1957 
1958     BidirectionalPair<AudioContexts> supported_contexts = {
1959             .sink = AudioContexts(sink_supported_context_types),
1960             .source = AudioContexts(source_supported_context_types),
1961     };
1962 
1963     leAudioDevice->SetSupportedContexts(supported_contexts);
1964 
1965     /* Use same as supported ones for now. */
1966     leAudioDevice->SetAvailableContexts(supported_contexts);
1967 
1968     if (!DeserializeHandles(leAudioDevice, handles)) {
1969       log::warn("Could not load Handles");
1970     }
1971 
1972     if (sink_audio_location) {
1973       leAudioDevice->audio_locations_.sink->value = sink_audio_location.value();
1974     }
1975 
1976     if (source_audio_location) {
1977       leAudioDevice->audio_locations_.source->value = source_audio_location.value();
1978     }
1979 
1980     /* Presence of PAC characteristic for a direction means support for that direction */
1981     if (leAudioDevice->audio_locations_.source) {
1982       leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource;
1983     }
1984     if (leAudioDevice->audio_locations_.sink) {
1985       leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink;
1986       callbacks_->OnSinkAudioLocationAvailable(leAudioDevice->address_,
1987                                                leAudioDevice->audio_locations_.sink->value);
1988     }
1989 
1990     if (!DeserializeSinkPacs(leAudioDevice, sink_pacs)) {
1991       /* If PACs are invalid, just say whole cache is invalid */
1992       leAudioDevice->known_service_handles_ = false;
1993       log::warn("Could not load sink pacs");
1994     }
1995 
1996     if (!DeserializeSourcePacs(leAudioDevice, source_pacs)) {
1997       /* If PACs are invalid, just say whole cache is invalid */
1998       leAudioDevice->known_service_handles_ = false;
1999       log::warn("Could not load source pacs");
2000     }
2001 
2002     if (!DeserializeAses(leAudioDevice, ases)) {
2003       /* If ASEs are invalid, just say whole cache is invalid */
2004       leAudioDevice->known_service_handles_ = false;
2005       log::warn("Could not load ases");
2006     }
2007 
2008     if (gmap.size() != 0) {
2009       leAudioDevice->gmap_client_ = std::make_unique<GmapClient>(leAudioDevice->address_);
2010       if (!le_audio::DeserializeGmap(leAudioDevice->gmap_client_.get(), gmap)) {
2011         leAudioDevice->gmap_client_.reset();
2012         log::warn("Invalid GMAP storage for {}", leAudioDevice->address_);
2013       }
2014     }
2015 
2016     leAudioDevice->autoconnect_flag_ = autoconnect;
2017     /* When adding from storage, make sure that autoconnect is used
2018      * by all the devices in the group.
2019      */
2020     leAudioDevices_.SetInitialGroupAutoconnectState(group_id, gatt_if_, reconnection_mode_,
2021                                                     autoconnect);
2022   }
2023 
GetHandlesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)2024   bool GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
2025     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
2026     return SerializeHandles(leAudioDevice, out);
2027   }
2028 
GetGmapForStorage(const RawAddress & addr,std::vector<uint8_t> & out)2029   bool GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
2030     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
2031     return SerializeGmap(leAudioDevice->gmap_client_.get(), out);
2032   }
2033 
GetSinkPacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)2034   bool GetSinkPacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
2035     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
2036     return SerializeSinkPacs(leAudioDevice, out);
2037   }
2038 
GetSourcePacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)2039   bool GetSourcePacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
2040     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
2041     return SerializeSourcePacs(leAudioDevice, out);
2042   }
2043 
GetAsesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)2044   bool GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
2045     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
2046 
2047     return SerializeAses(leAudioDevice, out);
2048   }
2049 
BackgroundConnectIfNeeded(LeAudioDevice * leAudioDevice)2050   void BackgroundConnectIfNeeded(LeAudioDevice* leAudioDevice) {
2051     if (!leAudioDevice->autoconnect_flag_) {
2052       log::debug("Device {} not in the background connect", leAudioDevice->address_);
2053       return;
2054     }
2055     AddToBackgroundConnectCheckGroupConnected(leAudioDevice);
2056   }
2057 
Disconnect(const RawAddress & address)2058   void Disconnect(const RawAddress& address) override {
2059     log::info(": {}", address);
2060     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2061 
2062     if (!leAudioDevice) {
2063       log::warn("leAudioDevice not connected ( {} )", address);
2064       callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2065       return;
2066     }
2067 
2068     auto connection_state = leAudioDevice->GetConnectionState();
2069     log::info("{}, state: {}", address, bluetooth::common::ToString(connection_state));
2070 
2071     switch (connection_state) {
2072       case DeviceConnectState::CONNECTING_BY_USER:
2073         /* Timeout happen on the Java layer. Device probably not in the range.
2074          * Cancel just direct connection and keep background if it is there.
2075          */
2076         BTA_GATTC_CancelOpen(gatt_if_, address, true);
2077         /* If this is a device which is a part of the group which is connected,
2078          * lets start backgroup connect
2079          */
2080         BackgroundConnectIfNeeded(leAudioDevice);
2081         return;
2082       case DeviceConnectState::CONNECTED: {
2083         /* User is disconnecting the device, we shall remove the autoconnect
2084          * flag for this device and all others if not TA is used
2085          */
2086         /* If target announcement is used, do not remove autoconnect
2087          */
2088         bool remove_from_autoconnect =
2089                 (reconnection_mode_ != BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS);
2090 
2091         if (leAudioDevice->autoconnect_flag_ && remove_from_autoconnect) {
2092           log::info("Removing autoconnect flag for group_id {}", leAudioDevice->group_id_);
2093 
2094           /* Removes device from background connect */
2095           BTA_GATTC_CancelOpen(gatt_if_, address, false);
2096           btif_storage_set_leaudio_autoconnect(address, false);
2097           leAudioDevice->autoconnect_flag_ = false;
2098         }
2099 
2100         /* Make sure ACL is disconnected to avoid reconnecting immediately
2101          * when autoconnect with TA reconnection mechanism is used.
2102          */
2103         bool force_acl_disconnect = leAudioDevice->autoconnect_flag_;
2104 
2105         auto group = aseGroups_.FindById(leAudioDevice->group_id_);
2106         if (group) {
2107           /* Remove devices from auto connect mode */
2108           for (auto dev = group->GetFirstDevice(); dev; dev = group->GetNextDevice(dev)) {
2109             if (remove_from_autoconnect &&
2110                 (dev->GetConnectionState() == DeviceConnectState::CONNECTING_AUTOCONNECT)) {
2111               btif_storage_set_leaudio_autoconnect(dev->address_, false);
2112               dev->autoconnect_flag_ = false;
2113               BTA_GATTC_CancelOpen(gatt_if_, dev->address_, false);
2114               dev->SetConnectionState(DeviceConnectState::DISCONNECTED);
2115             }
2116           }
2117 
2118           /* If group is Streaming or is in transition for Streaming - lets stop it
2119            * and mark device to disconnect when stream is closed
2120            */
2121           if (group->IsStreaming() || !group->IsReleasingOrIdle()) {
2122             log::debug("group_id {} needs to stop streaming before {} disconnection",
2123                        group->group_id_, leAudioDevice->address_);
2124             leAudioDevice->closing_stream_for_disconnection_ = true;
2125             groupStateMachine_->StopStream(group);
2126             return;
2127           }
2128 
2129           if (group->IsReleasing()) {
2130             log::debug("group_id {} needs to stop streaming before {} disconnection",
2131                        group->group_id_, leAudioDevice->address_);
2132             /* Stream is releasing, wait till it is completed and then disconnect ACL. */
2133             leAudioDevice->closing_stream_for_disconnection_ = true;
2134             return;
2135           }
2136 
2137           force_acl_disconnect &= group->IsEnabled();
2138         }
2139 
2140         DisconnectDevice(leAudioDevice, force_acl_disconnect);
2141       }
2142         return;
2143       case DeviceConnectState::CONNECTED_BY_USER_GETTING_READY:
2144         /* Timeout happen on the Java layer before native got ready with the
2145          * device */
2146         DisconnectDevice(leAudioDevice);
2147         return;
2148       case DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY:
2149         /* Java is not aware about autoconnect actions,
2150          * therefore this should not happen.
2151          */
2152         log::warn("Should not happen - disconnect device");
2153         DisconnectDevice(leAudioDevice);
2154         return;
2155       case DeviceConnectState::DISCONNECTED:
2156       case DeviceConnectState::DISCONNECTING:
2157       case DeviceConnectState::DISCONNECTING_AND_RECOVER:
2158       case DeviceConnectState::CONNECTING_AUTOCONNECT:
2159       case DeviceConnectState::REMOVING:
2160         log::warn("{}, invalid state {}", address, bluetooth::common::ToString(connection_state));
2161         return;
2162     }
2163   }
2164 
DisconnectDevice(LeAudioDevice * leAudioDevice,bool acl_force_disconnect=false,bool recover=false)2165   void DisconnectDevice(LeAudioDevice* leAudioDevice, bool acl_force_disconnect = false,
2166                         bool recover = false) {
2167     if (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID) {
2168       return;
2169     }
2170 
2171     if (leAudioDevice->GetConnectionState() != DeviceConnectState::REMOVING) {
2172       leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING);
2173     }
2174 
2175     BtaGattQueue::Clean(leAudioDevice->conn_id_);
2176 
2177     /* Remote in bad state, force ACL Disconnection. */
2178     if (acl_force_disconnect) {
2179       leAudioDevice->DisconnectAcl();
2180       if (recover) {
2181         leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING_AND_RECOVER);
2182       }
2183     } else {
2184       BTA_GATTC_Close(leAudioDevice->conn_id_);
2185     }
2186   }
2187 
DeregisterNotifications(LeAudioDevice * leAudioDevice)2188   void DeregisterNotifications(LeAudioDevice* leAudioDevice) {
2189     /* GATTC will omit not registered previously handles */
2190     for (auto pac_tuple : leAudioDevice->snk_pacs_) {
2191       BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2192                                            std::get<0>(pac_tuple).val_hdl);
2193     }
2194     for (auto pac_tuple : leAudioDevice->src_pacs_) {
2195       BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2196                                            std::get<0>(pac_tuple).val_hdl);
2197     }
2198 
2199     if (leAudioDevice->audio_locations_.sink) {
2200       BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2201                                            leAudioDevice->audio_locations_.sink->handles.val_hdl);
2202     }
2203     if (leAudioDevice->audio_locations_.source) {
2204       BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2205                                            leAudioDevice->audio_locations_.source->handles.val_hdl);
2206     }
2207     if (leAudioDevice->audio_avail_hdls_.val_hdl != 0) {
2208       BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2209                                            leAudioDevice->audio_avail_hdls_.val_hdl);
2210     }
2211     if (leAudioDevice->audio_supp_cont_hdls_.val_hdl != 0) {
2212       BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2213                                            leAudioDevice->audio_supp_cont_hdls_.val_hdl);
2214     }
2215     if (leAudioDevice->ctp_hdls_.val_hdl != 0) {
2216       BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_,
2217                                            leAudioDevice->ctp_hdls_.val_hdl);
2218     }
2219 
2220     for (struct ase& ase : leAudioDevice->ases_) {
2221       BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_, ase.hdls.val_hdl);
2222     }
2223   }
2224 
handleInitialCtpCccRead(LeAudioDevice * leAudioDevice,uint16_t len,uint8_t * value)2225   void handleInitialCtpCccRead(LeAudioDevice* leAudioDevice, uint16_t len, uint8_t* value) {
2226     if (len != 2) {
2227       log::error("Could not read CCC for {}, disconnecting", leAudioDevice->address_);
2228       instance->Disconnect(leAudioDevice->address_);
2229       return;
2230     }
2231 
2232     uint16_t val = *(uint16_t*)value;
2233     if (val == 0) {
2234       log::warn("{} forgot CCC values. Re-subscribing", leAudioDevice->address_);
2235       RegisterKnownNotifications(leAudioDevice, false, true);
2236       return;
2237     }
2238 
2239     log::verbose("{}, ASCS ctp ccc: {:#x}", leAudioDevice->address_, val);
2240     connectionReady(leAudioDevice);
2241   }
2242 
2243   /* This is a generic read/notify/indicate handler for gatt. Here messages
2244    * are dispatched to correct elements e.g. ASEs, PACs, audio locations etc.
2245    */
LeAudioCharValueHandle(tCONN_ID conn_id,uint16_t hdl,uint16_t len,uint8_t * value,bool notify=false)2246   void LeAudioCharValueHandle(tCONN_ID conn_id, uint16_t hdl, uint16_t len, uint8_t* value,
2247                               bool notify = false) {
2248     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2249     struct ase* ase;
2250 
2251     if (!leAudioDevice) {
2252       log::error("no leAudioDevice assigned to connection id: {}", conn_id);
2253       return;
2254     }
2255 
2256     ase = leAudioDevice->GetAseByValHandle(hdl);
2257     LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
2258     if (ase) {
2259       groupStateMachine_->ProcessGattNotifEvent(value, len, ase, leAudioDevice, group);
2260       return;
2261     }
2262 
2263     /* Initial CCC read to check if remote device properly keeps CCC values */
2264     if (hdl == leAudioDevice->ctp_hdls_.ccc_hdl) {
2265       handleInitialCtpCccRead(leAudioDevice, len, value);
2266       return;
2267     }
2268 
2269     auto snk_pac_ent =
2270             std::find_if(leAudioDevice->snk_pacs_.begin(), leAudioDevice->snk_pacs_.end(),
2271                          [&hdl](auto& pac_ent) { return std::get<0>(pac_ent).val_hdl == hdl; });
2272     if (snk_pac_ent != leAudioDevice->snk_pacs_.end()) {
2273       std::vector<struct bluetooth::le_audio::types::acs_ac_record> pac_recs;
2274 
2275       /* Guard consistency of PAC records structure */
2276       if (!bluetooth::le_audio::client_parser::pacs::ParsePacs(pac_recs, len, value)) {
2277         log::error("Sink PACs corrupted");
2278         return;
2279       }
2280 
2281       log::info("Registering sink PACs");
2282       leAudioDevice->RegisterPACs(&std::get<1>(*snk_pac_ent), &pac_recs);
2283 
2284       /* Cached audio set configurations should be considered invalid when
2285        * PACs are updated.
2286        */
2287       if (group) {
2288         /* Changes in PAC record channel counts may change the strategy */
2289         group->InvalidateGroupStrategy();
2290         group->InvalidateCachedConfigurations();
2291       }
2292       if (notify) {
2293         btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
2294       }
2295       return;
2296     }
2297 
2298     auto src_pac_ent =
2299             std::find_if(leAudioDevice->src_pacs_.begin(), leAudioDevice->src_pacs_.end(),
2300                          [&hdl](auto& pac_ent) { return std::get<0>(pac_ent).val_hdl == hdl; });
2301     if (src_pac_ent != leAudioDevice->src_pacs_.end()) {
2302       std::vector<struct bluetooth::le_audio::types::acs_ac_record> pac_recs;
2303 
2304       /* Guard consistency of PAC records structure */
2305       if (!bluetooth::le_audio::client_parser::pacs::ParsePacs(pac_recs, len, value)) {
2306         log::error("Source PACs corrupted");
2307         return;
2308       }
2309 
2310       log::info("Registering source PACs");
2311       leAudioDevice->RegisterPACs(&std::get<1>(*src_pac_ent), &pac_recs);
2312 
2313       /* Cached audio set configurations should be considered invalid when
2314        * PACs are updated.
2315        */
2316       if (group) {
2317         /* Changes in PAC record channel counts may change the strategy */
2318         group->InvalidateGroupStrategy();
2319         group->InvalidateCachedConfigurations();
2320       }
2321       if (notify) {
2322         btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
2323       }
2324       return;
2325     }
2326 
2327     if (leAudioDevice->audio_locations_.sink &&
2328         hdl == leAudioDevice->audio_locations_.sink->handles.val_hdl) {
2329       AudioLocations snk_audio_locations;
2330       bluetooth::le_audio::client_parser::pacs::ParseAudioLocations(snk_audio_locations, len,
2331                                                                     value);
2332 
2333       /* Value may not change */
2334       if (!leAudioDevice->audio_locations_.sink ||
2335           (leAudioDevice->audio_locations_.sink->value ^ snk_audio_locations).none()) {
2336         return;
2337       }
2338 
2339       /* Presence of PAC characteristic for source means support for source
2340        * audio location. Value of 0x00000000 means mono/unspecified
2341        */
2342       leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSink;
2343       leAudioDevice->audio_locations_.sink->value = snk_audio_locations;
2344 
2345       callbacks_->OnSinkAudioLocationAvailable(leAudioDevice->address_, snk_audio_locations);
2346 
2347       if (notify) {
2348         btif_storage_set_leaudio_sink_audio_location(
2349                 leAudioDevice->address_, leAudioDevice->audio_locations_.sink->value.to_ulong());
2350         if (group && group->IsReleasingOrIdle()) {
2351           UpdateLocationsAndContextsAvailability(group);
2352         }
2353       }
2354     } else if (leAudioDevice->audio_locations_.source &&
2355                hdl == leAudioDevice->audio_locations_.source->handles.val_hdl) {
2356       AudioLocations src_audio_locations;
2357       bluetooth::le_audio::client_parser::pacs::ParseAudioLocations(src_audio_locations, len,
2358                                                                     value);
2359 
2360       /* Value may not change */
2361       if (!leAudioDevice->audio_locations_.source ||
2362           (leAudioDevice->audio_locations_.source->value ^ src_audio_locations).none()) {
2363         return;
2364       }
2365 
2366       /* Presence of PAC characteristic for source means support for source
2367        * audio location. Value of 0x00000000 means mono/unspecified
2368        */
2369       leAudioDevice->audio_directions_ |= bluetooth::le_audio::types::kLeAudioDirectionSource;
2370       leAudioDevice->audio_locations_.source->value = src_audio_locations;
2371 
2372       if (notify) {
2373         btif_storage_set_leaudio_source_audio_location(
2374                 leAudioDevice->address_, leAudioDevice->audio_locations_.source->value.to_ulong());
2375         if (group && group->IsReleasingOrIdle()) {
2376           UpdateLocationsAndContextsAvailability(group);
2377         }
2378       }
2379     } else if (hdl == leAudioDevice->audio_avail_hdls_.val_hdl) {
2380       BidirectionalPair<AudioContexts> contexts;
2381       if (!bluetooth::le_audio::client_parser::pacs::ParseAvailableAudioContexts(contexts, len,
2382                                                                                  value)) {
2383         return;
2384       }
2385 
2386       AudioContexts current_group_contexts;
2387 
2388       if (group) {
2389         current_group_contexts = group->GetAvailableContexts();
2390       }
2391 
2392       leAudioDevice->SetAvailableContexts(contexts);
2393 
2394       if (!group) {
2395         return;
2396       }
2397 
2398       if (group->IsInTransition()) {
2399         /* Group is in transition.
2400          * if group is going to stream, schedule attaching the device to the
2401          * group.
2402          */
2403 
2404         if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
2405           AttachToStreamingGroupIfNeeded(leAudioDevice);
2406         }
2407         return;
2408       }
2409 
2410       /* Whenever context type change, notify user about that.
2411        * Note: GetAvailableContexts() add streaming context as well
2412        */
2413       UpdateLocationsAndContextsAvailability(
2414               group, current_group_contexts != group->GetAvailableContexts());
2415 
2416       if (!group->IsStreaming()) {
2417         return;
2418       }
2419 
2420       AttachToStreamingGroupIfNeeded(leAudioDevice);
2421 
2422     } else if (hdl == leAudioDevice->audio_supp_cont_hdls_.val_hdl) {
2423       BidirectionalPair<AudioContexts> supp_audio_contexts;
2424       if (bluetooth::le_audio::client_parser::pacs::ParseSupportedAudioContexts(supp_audio_contexts,
2425                                                                                 len, value)) {
2426         /* Just store if for now */
2427         leAudioDevice->SetSupportedContexts(supp_audio_contexts);
2428 
2429         btif_storage_set_leaudio_supported_context_types(leAudioDevice->address_,
2430                                                          supp_audio_contexts.sink.value(),
2431                                                          supp_audio_contexts.source.value());
2432       }
2433     } else if (hdl == leAudioDevice->ctp_hdls_.val_hdl) {
2434       groupStateMachine_->ProcessGattCtpNotification(group, leAudioDevice, value, len);
2435     } else if (hdl == leAudioDevice->tmap_role_hdl_) {
2436       bluetooth::le_audio::client_parser::tmap::ParseTmapRole(leAudioDevice->tmap_role_, len,
2437                                                               value);
2438     } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() &&
2439                hdl == leAudioDevice->gmap_client_->getRoleHandle()) {
2440       leAudioDevice->gmap_client_->parseAndSaveGmapRole(len, value);
2441       btif_storage_leaudio_update_gmap_bin(leAudioDevice->address_);
2442     } else if (leAudioDevice->gmap_client_ != nullptr && GmapClient::IsGmapClientEnabled() &&
2443                hdl == leAudioDevice->gmap_client_->getUGTFeatureHandle()) {
2444       leAudioDevice->gmap_client_->parseAndSaveUGTFeature(len, value);
2445       btif_storage_leaudio_update_gmap_bin(leAudioDevice->address_);
2446     } else {
2447       log::error("Unknown attribute read: 0x{:x}", hdl);
2448     }
2449   }
2450 
OnGattReadRsp(tCONN_ID conn_id,tGATT_STATUS,uint16_t hdl,uint16_t len,uint8_t * value,void *)2451   void OnGattReadRsp(tCONN_ID conn_id, tGATT_STATUS /*status*/, uint16_t hdl, uint16_t len,
2452                      uint8_t* value, void* /*data*/) {
2453     LeAudioCharValueHandle(conn_id, hdl, len, value);
2454   }
2455 
GetGroupIfEnabled(int group_id)2456   LeAudioDeviceGroup* GetGroupIfEnabled(int group_id) {
2457     auto group = aseGroups_.FindById(group_id);
2458     if (group == nullptr) {
2459       log::info("Group {} does not exist", group_id);
2460       return nullptr;
2461     }
2462     if (!group->IsEnabled()) {
2463       log::info("Group {} is disabled", group_id);
2464       return nullptr;
2465     }
2466     return group;
2467   }
2468 
AddToBackgroundConnectCheckGroupConnected(LeAudioDevice * leAudioDevice)2469   void AddToBackgroundConnectCheckGroupConnected(LeAudioDevice* leAudioDevice) {
2470     /* If device belongs to streaming group, add it on allow list */
2471     auto address = leAudioDevice->address_;
2472     auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2473     if (group == nullptr) {
2474       log::info("Group {} is invalid or disabled", leAudioDevice->group_id_);
2475       return;
2476     }
2477 
2478     leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
2479 
2480     /* Cancel previous bakcground connect */
2481     BTA_GATTC_CancelOpen(gatt_if_, address, false);
2482     if (group->IsAnyDeviceConnected()) {
2483       log::info("Group {} in connected state. Adding {} to allow list", leAudioDevice->group_id_,
2484                 address);
2485       BTA_GATTC_Open(gatt_if_, address, BTM_BLE_BKG_CONNECT_ALLOW_LIST, false);
2486     } else {
2487       log::info("Adding {} to background connect (default reconnection_mode (0x{:02x}))", address,
2488                 reconnection_mode_);
2489       BTA_GATTC_Open(gatt_if_, address, reconnection_mode_, false);
2490     }
2491   }
2492 
OnGattConnected(tGATT_STATUS status,tCONN_ID conn_id,tGATT_IF,RawAddress address,tBT_TRANSPORT transport,uint16_t mtu)2493   void OnGattConnected(tGATT_STATUS status, tCONN_ID conn_id, tGATT_IF /*client_if*/,
2494                        RawAddress address, tBT_TRANSPORT transport, uint16_t mtu) {
2495     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2496 
2497     log::info("{}, conn_id=0x{:04x}, transport={}, status={} (0x{:02x})", address, conn_id,
2498               bt_transport_text(transport), gatt_status_text(status), status);
2499 
2500     if (transport != BT_TRANSPORT_LE) {
2501       log::warn("Only LE connection is allowed (transport {})", bt_transport_text(transport));
2502       BTA_GATTC_Close(conn_id);
2503       return;
2504     }
2505 
2506     if (!leAudioDevice) {
2507       return;
2508     }
2509 
2510     if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID) {
2511       log::debug("Already connected {}, conn_id=0x{:04x}", address, leAudioDevice->conn_id_);
2512       return;
2513     }
2514 
2515     if (status != GATT_SUCCESS) {
2516       /* Clear current connection request and let it be set again if needed */
2517       BTA_GATTC_CancelOpen(gatt_if_, address, false);
2518 
2519       /* autoconnect connection failed, that's ok */
2520       if (status != GATT_ILLEGAL_PARAMETER &&
2521           (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTING_AUTOCONNECT ||
2522            leAudioDevice->autoconnect_flag_)) {
2523         log::info("Device not available now, do background connect.");
2524         leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2525         AddToBackgroundConnectCheckGroupConnected(leAudioDevice);
2526         return;
2527       }
2528 
2529       leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2530 
2531       log::error("Failed to connect to LeAudio leAudioDevice, status: 0x{:02x}", status);
2532       callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2533       bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2534               leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2535               bluetooth::le_audio::ConnectionStatus::FAILED);
2536       return;
2537     }
2538 
2539     if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
2540       auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2541       if (group == nullptr) {
2542         BTA_GATTC_CancelOpen(gatt_if_, address, false);
2543 
2544         log::warn("LeAudio profile is disabled for group_id: {}. {} is not connected",
2545                   leAudioDevice->group_id_, address);
2546         return;
2547       }
2548     }
2549 
2550     leAudioDevice->conn_id_ = conn_id;
2551     leAudioDevice->mtu_ = mtu;
2552     if (com::android::bluetooth::flags::gatt_queue_cleanup_connected()) {
2553       BtaGattQueue::Clean(conn_id);
2554     }
2555 
2556     /* Remove device from the background connect (it might be either Allow list
2557      * or TA) and add it again with reconnection_mode_. In case it is TA, we are
2558      * sure that device will not be in the allow list for other applications
2559      * which are using background connect.
2560      */
2561     BTA_GATTC_CancelOpen(gatt_if_, address, false);
2562     BTA_GATTC_Open(gatt_if_, address, reconnection_mode_, false);
2563 
2564     if (bluetooth::shim::GetController()->SupportsBle2mPhy()) {
2565       log::info("{} set preferred PHY to 2M", address);
2566       get_btm_client_interface().ble.BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0);
2567     }
2568 
2569     get_btm_client_interface().peer.BTM_RequestPeerSCA(leAudioDevice->address_, transport);
2570 
2571     if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTING_AUTOCONNECT) {
2572       leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
2573     } else {
2574       leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
2575     }
2576 
2577     /* Check if the device is in allow list and update the flag */
2578     leAudioDevice->UpdateDeviceAllowlistFlag();
2579     if (BTM_SecIsLeSecurityPending(address)) {
2580       /* if security collision happened, wait for encryption done
2581        * (BTA_GATTC_ENC_CMPL_CB_EVT) */
2582       return;
2583     }
2584 
2585     /* verify bond */
2586     if (BTM_IsEncrypted(address, BT_TRANSPORT_LE)) {
2587       /* if link has been encrypted */
2588       OnEncryptionComplete(address, tBTM_STATUS::BTM_SUCCESS);
2589       return;
2590     }
2591 
2592     tBTM_STATUS result =
2593             BTM_SetEncryption(address, BT_TRANSPORT_LE, nullptr, nullptr, BTM_BLE_SEC_ENCRYPT);
2594 
2595     log::info("Encryption required for {}. Request result: 0x{:02x}", address, result);
2596 
2597     if (result == tBTM_STATUS::BTM_ERR_KEY_MISSING) {
2598       log::error("Link key unknown for {}, disconnect profile", address);
2599       bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2600               leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2601               bluetooth::le_audio::ConnectionStatus::FAILED);
2602 
2603       /* If link cannot be enctypted, disconnect profile */
2604       BTA_GATTC_Close(conn_id);
2605     }
2606   }
2607 
RegisterKnownNotifications(LeAudioDevice * leAudioDevice,bool gatt_register,bool write_ccc)2608   void RegisterKnownNotifications(LeAudioDevice* leAudioDevice, bool gatt_register,
2609                                   bool write_ccc) {
2610     log::info("device: {}", leAudioDevice->address_);
2611 
2612     if (leAudioDevice->ctp_hdls_.val_hdl == 0) {
2613       log::error("Control point characteristic is mandatory - disconnecting device {}",
2614                  leAudioDevice->address_);
2615       DisconnectDevice(leAudioDevice);
2616       return;
2617     }
2618 
2619     /* GATTC will omit not registered previously handles */
2620     for (auto pac_tuple : leAudioDevice->snk_pacs_) {
2621       subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2622                                  std::get<0>(pac_tuple), gatt_register, write_ccc);
2623     }
2624     for (auto pac_tuple : leAudioDevice->src_pacs_) {
2625       subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2626                                  std::get<0>(pac_tuple), gatt_register, write_ccc);
2627     }
2628 
2629     if (leAudioDevice->audio_locations_.sink) {
2630       subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2631                                  leAudioDevice->audio_locations_.sink->handles, gatt_register,
2632                                  write_ccc);
2633     }
2634     if (leAudioDevice->audio_locations_.source) {
2635       subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2636                                  leAudioDevice->audio_locations_.source->handles, gatt_register,
2637                                  write_ccc);
2638     }
2639 
2640     if (leAudioDevice->audio_avail_hdls_.val_hdl != 0) {
2641       subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2642                                  leAudioDevice->audio_avail_hdls_, gatt_register, write_ccc);
2643     }
2644 
2645     if (leAudioDevice->audio_supp_cont_hdls_.val_hdl != 0) {
2646       subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2647                                  leAudioDevice->audio_supp_cont_hdls_, gatt_register, write_ccc);
2648     }
2649 
2650     for (struct ase& ase : leAudioDevice->ases_) {
2651       subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_, ase.hdls,
2652                                  gatt_register, write_ccc);
2653     }
2654 
2655     subscribe_for_notification(leAudioDevice->conn_id_, leAudioDevice->address_,
2656                                leAudioDevice->ctp_hdls_, gatt_register, write_ccc);
2657   }
2658 
changeMtuIfPossible(LeAudioDevice * leAudioDevice)2659   void changeMtuIfPossible(LeAudioDevice* leAudioDevice) {
2660     if (leAudioDevice->mtu_ == GATT_DEF_BLE_MTU_SIZE) {
2661       log::info("Configure MTU");
2662       /* Use here kBapMinimumAttMtu, because we know that GATT will request
2663        * default ATT MTU anyways. We also know that GATT will use this
2664        * kBapMinimumAttMtu as an input for Data Length Update procedure in the controller.
2665        */
2666       BtaGattQueue::ConfigureMtu(leAudioDevice->conn_id_, kBapMinimumAttMtu);
2667     }
2668   }
2669 
ReadMustHaveAttributesOnReconnect(LeAudioDevice * leAudioDevice)2670   void ReadMustHaveAttributesOnReconnect(LeAudioDevice* leAudioDevice) {
2671     bool is_eatt_supported = gatt_profile_get_eatt_support_by_conn_id(leAudioDevice->conn_id_);
2672 
2673     log::verbose("{}, eatt supported {}", leAudioDevice->address_, is_eatt_supported);
2674     /* Here we read
2675      * 1) ASCS Control Point CCC descriptor in order to validate proper
2676      *    behavior of remote device which should store CCC values for bonded device.
2677      * 2) Available Context Types which normally should be notified by the server,
2678      *    but since it is crucial for proper streaming experiance, and in the same time
2679      *    it can change very often which, as we observed, might lead to not being sent by
2680      *    remote devices
2681      */
2682     if (!com::android::bluetooth::flags::le_ase_read_multiple_variable() || !is_eatt_supported) {
2683       BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_,
2684                                        leAudioDevice->audio_avail_hdls_.val_hdl,
2685                                        OnGattReadRspStatic, NULL);
2686       BtaGattQueue::ReadCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.ccc_hdl,
2687                                        OnGattReadRspStatic, NULL);
2688     } else {
2689       tBTA_GATTC_MULTI multi_read = {.num_attr = 2,
2690                                      .handles = {leAudioDevice->audio_avail_hdls_.val_hdl,
2691                                                  leAudioDevice->ctp_hdls_.ccc_hdl}};
2692 
2693       BtaGattQueue::ReadMultiCharacteristic(leAudioDevice->conn_id_, multi_read,
2694                                             OnGattReadMultiRspStatic, NULL);
2695     }
2696   }
2697 
OnEncryptionComplete(const RawAddress & address,tBTM_STATUS status)2698   void OnEncryptionComplete(const RawAddress& address, tBTM_STATUS status) {
2699     log::info("{} status 0x{:02x}", address, status);
2700     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2701     if (leAudioDevice == NULL || (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID)) {
2702       log::warn("Skipping device which is {}",
2703                 leAudioDevice ? " not connected by service." : " null");
2704       return;
2705     }
2706 
2707     if (status != tBTM_STATUS::BTM_SUCCESS) {
2708       log::error("Encryption failed status: {}", btm_status_text(status));
2709       if (leAudioDevice->GetConnectionState() ==
2710           DeviceConnectState::CONNECTED_BY_USER_GETTING_READY) {
2711         callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2712         bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2713                 leAudioDevice->group_id_, address, ConnectionState::CONNECTED,
2714                 bluetooth::le_audio::ConnectionStatus::FAILED);
2715       }
2716 
2717       leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING);
2718 
2719       BTA_GATTC_Close(leAudioDevice->conn_id_);
2720       return;
2721     }
2722 
2723     if (leAudioDevice->encrypted_) {
2724       log::info("link already encrypted, nothing to do");
2725       return;
2726     }
2727 
2728     /* If PHY update did not succeed after ACL connection, which can happen
2729      * when remote feature read was not that quick, lets try to change phy here
2730      * one more time
2731      */
2732     if (!leAudioDevice->acl_phy_update_done_ &&
2733         bluetooth::shim::GetController()->SupportsBle2mPhy()) {
2734       log::info("{} set preferred PHY to 2M", leAudioDevice->address_);
2735       get_btm_client_interface().ble.BTM_BleSetPhy(address, PHY_LE_2M, PHY_LE_2M, 0);
2736     }
2737 
2738     changeMtuIfPossible(leAudioDevice);
2739 
2740     leAudioDevice->encrypted_ = true;
2741 
2742     /* If we know services, register for notifications */
2743     if (leAudioDevice->known_service_handles_) {
2744       /* This registration will do subscribtion in local GATT as we
2745        * assume remote device keeps bonded CCC values.
2746        */
2747       RegisterKnownNotifications(leAudioDevice, true, false);
2748       ReadMustHaveAttributesOnReconnect(leAudioDevice);
2749     }
2750 
2751     /* If we know services and read is not ongoing, this is reconnection and
2752      * just notify connected  */
2753     if (leAudioDevice->known_service_handles_ && !leAudioDevice->notify_connected_after_read_) {
2754       log::info("Wait for CCC registration and MTU change request");
2755       return;
2756     }
2757 
2758     BTA_GATTC_ServiceSearchRequest(leAudioDevice->conn_id_,
2759                                    bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
2760   }
2761 
checkGroupConnectionStateAfterMemberDisconnect(int group_id)2762   void checkGroupConnectionStateAfterMemberDisconnect(int group_id) {
2763     /* This is fired t=kGroupConnectedWatchDelayMs after group member
2764      * got disconnected while either group members were connected.
2765      * We want to check here if there is any group member connected.
2766      * If so we should add other group members to allow list for better
2767      * reconnection experience. If  all group members are disconnected
2768      * i e.g. devices intentionally disconnected for other
2769      * purposes like pairing with other device, then we do nothing here and
2770      * device stay on the default reconnection policy (i.e. targeted
2771      * announcements)
2772      */
2773     auto group = aseGroups_.FindById(group_id);
2774     if (group == nullptr) {
2775       log::info("Group {} is destroyed.", group_id);
2776       return;
2777     }
2778 
2779     if (!group->IsAnyDeviceConnected()) {
2780       log::info("Group {} is not connected", group_id);
2781       /* Make sure all devices are in the default reconnection mode */
2782       group->ApplyReconnectionMode(gatt_if_, reconnection_mode_);
2783       return;
2784     }
2785 
2786     /* if group is still connected, make sure that other not connected
2787      * set members are in the allow list for the quick reconnect.
2788      * E.g. for the earbud case, probably one of the earbud is in the case now.
2789      */
2790     group->AddToAllowListNotConnectedGroupMembers(gatt_if_);
2791   }
2792 
scheduleGroupConnectedCheck(int group_id)2793   void scheduleGroupConnectedCheck(int group_id) {
2794     log::info("Schedule group_id {} connected check.", group_id);
2795     do_in_main_thread_delayed(
2796             base::BindOnce(&LeAudioClientImpl::checkGroupConnectionStateAfterMemberDisconnect,
2797                            weak_factory_.GetWeakPtr(), group_id),
2798             std::chrono::milliseconds(kGroupConnectedWatchDelayMs));
2799   }
2800 
autoConnect(RawAddress address)2801   void autoConnect(RawAddress address) {
2802     auto leAudioDevice = leAudioDevices_.FindByAddress(address);
2803     if (leAudioDevice == nullptr) {
2804       log::warn("Device {} not valid anymore", address);
2805       return;
2806     }
2807 
2808     BackgroundConnectIfNeeded(leAudioDevice);
2809   }
2810 
scheduleAutoConnect(RawAddress & address)2811   void scheduleAutoConnect(RawAddress& address) {
2812     log::info("Schedule auto connect {}", address);
2813     do_in_main_thread_delayed(
2814             base::BindOnce(&LeAudioClientImpl::autoConnect, weak_factory_.GetWeakPtr(), address),
2815             std::chrono::milliseconds(kAutoConnectAfterOwnDisconnectDelayMs));
2816   }
2817 
recoveryReconnect(RawAddress address)2818   void recoveryReconnect(RawAddress address) {
2819     log::info("Reconnecting to {} after timeout on state machine.", address);
2820     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2821 
2822     if (leAudioDevice == nullptr ||
2823         leAudioDevice->GetConnectionState() != DeviceConnectState::DISCONNECTING_AND_RECOVER) {
2824       log::warn("Device {}, not interested in recovery connect anymore", address);
2825       return;
2826     }
2827 
2828     auto group = GetGroupIfEnabled(leAudioDevice->group_id_);
2829 
2830     if (group != nullptr) {
2831       leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
2832       BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
2833     } else {
2834       leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2835     }
2836   }
2837 
scheduleRecoveryReconnect(RawAddress & address)2838   void scheduleRecoveryReconnect(RawAddress& address) {
2839     log::info("Schedule reconnecting to {} after timeout on state machine.", address);
2840     do_in_main_thread_delayed(base::BindOnce(&LeAudioClientImpl::recoveryReconnect,
2841                                              weak_factory_.GetWeakPtr(), address),
2842                               std::chrono::milliseconds(kRecoveryReconnectDelayMs));
2843   }
2844 
checkIfGroupMember(RawAddress address)2845   void checkIfGroupMember(RawAddress address) {
2846     log::info("checking being a group member: {}", address);
2847     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
2848 
2849     if (leAudioDevice == nullptr) {
2850       log::warn("Device {}, probably removed", address);
2851       return;
2852     }
2853 
2854     if (leAudioDevice->group_id_ == bluetooth::groups::kGroupUnknown) {
2855       disconnectInvalidDevice(leAudioDevice, ", device not a valid group member",
2856                               LeAudioHealthDeviceStatType::INVALID_CSIS);
2857       return;
2858     }
2859   }
2860 
2861   /* This is called, when CSIS native module is about to add device to the
2862    * group once the CSIS service will be verified on the remote side.
2863    * After some time (kCsisGroupMemberDelayMs)  a checkIfGroupMember will be
2864    * called and will verify if the remote device has a group_id properly set.
2865    * if not, it means there is something wrong with CSIS service on the remote
2866    * side.
2867    */
scheduleGuardForCsisAdd(RawAddress & address)2868   void scheduleGuardForCsisAdd(RawAddress& address) {
2869     log::info("Schedule reconnecting to {} after timeout on state machine.", address);
2870     do_in_main_thread_delayed(base::BindOnce(&LeAudioClientImpl::checkIfGroupMember,
2871                                              weak_factory_.GetWeakPtr(), address),
2872                               std::chrono::milliseconds(kCsisGroupMemberDelayMs));
2873   }
2874 
OnGattDisconnected(tCONN_ID conn_id,tGATT_IF,RawAddress address,tGATT_DISCONN_REASON reason)2875   void OnGattDisconnected(tCONN_ID conn_id, tGATT_IF /*client_if*/, RawAddress address,
2876                           tGATT_DISCONN_REASON reason) {
2877     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
2878 
2879     if (!leAudioDevice) {
2880       log::error(", skipping unknown leAudioDevice, address: {}", address);
2881       return;
2882     }
2883 
2884     leAudioDevice->acl_asymmetric_ = false;
2885     BtaGattQueue::Clean(leAudioDevice->conn_id_);
2886     LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
2887 
2888     DeregisterNotifications(leAudioDevice);
2889 
2890     callbacks_->OnConnectionState(ConnectionState::DISCONNECTED, address);
2891     leAudioDevice->conn_id_ = GATT_INVALID_CONN_ID;
2892     leAudioDevice->mtu_ = 0;
2893     leAudioDevice->closing_stream_for_disconnection_ = false;
2894     leAudioDevice->encrypted_ = false;
2895     leAudioDevice->acl_phy_update_done_ = false;
2896 
2897     auto connection_state = leAudioDevice->GetConnectionState();
2898 
2899     leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
2900 
2901     groupStateMachine_->ProcessHciNotifAclDisconnected(group, leAudioDevice);
2902 
2903     bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
2904             leAudioDevice->group_id_, address, ConnectionState::DISCONNECTED,
2905             bluetooth::le_audio::ConnectionStatus::SUCCESS);
2906 
2907     if (connection_state == DeviceConnectState::REMOVING) {
2908       if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
2909         auto group = aseGroups_.FindById(leAudioDevice->group_id_);
2910         group_remove_node(group, address, true);
2911       }
2912       leAudioDevices_.Remove(address);
2913       return;
2914     }
2915 
2916     log::info("{}, autoconnect {}, reason 0x{:02x}, connection state {}", leAudioDevice->address_,
2917               leAudioDevice->autoconnect_flag_, reason,
2918               bluetooth::common::ToString(connection_state));
2919 
2920     if (connection_state == DeviceConnectState::DISCONNECTING_AND_RECOVER) {
2921       /* We are back after disconnecting device which was in a bad state.
2922        * lets try to reconnected - 30 sec with direct connect and later fallback
2923        * to default background reconnection mode.
2924        * Since GATT notifies us before ACL was dropped, let's wait a bit
2925        * before we do reconnect.
2926        *
2927        * Also, make sure that device has state which allows to do recover
2928        */
2929       leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTING_AND_RECOVER);
2930       scheduleRecoveryReconnect(address);
2931       return;
2932     }
2933 
2934     /* Attempt background re-connect if disconnect was not initiated locally
2935      * or if autoconnect is set and device got disconnected because of some
2936      * issues
2937      */
2938     if (group == nullptr || !group->IsEnabled()) {
2939       log::error("Group id {} ({}) disabled or null", leAudioDevice->group_id_,
2940                  std::format_ptr(group));
2941       return;
2942     }
2943 
2944     if (reason == GATT_CONN_TERMINATE_LOCAL_HOST) {
2945       if (leAudioDevice->autoconnect_flag_) {
2946         /* In this case ACL might not yet been disconnected */
2947         scheduleAutoConnect(address);
2948       }
2949       return;
2950     }
2951 
2952     /* Remote disconnects from us or Timeout happens */
2953     /* In this case ACL is disconnected */
2954     if (reason == GATT_CONN_TIMEOUT) {
2955       leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTING_AUTOCONNECT);
2956 
2957       /* If timeout try to reconnect for 30 sec.*/
2958       BTA_GATTC_Open(gatt_if_, address, BTM_BLE_DIRECT_CONNECTION, false);
2959       return;
2960     }
2961 
2962     /* In other disconnect resons we act based on the autoconnect_flag_ */
2963     if (leAudioDevice->autoconnect_flag_) {
2964       if (group->IsAnyDeviceConnected()) {
2965         /* If all set is disconnecting, let's give it some time.
2966          * If not all get disconnected, and there will be group member
2967          * connected we want to put disconnected devices to allow list
2968          */
2969         scheduleGroupConnectedCheck(leAudioDevice->group_id_);
2970       } else {
2971         group->ApplyReconnectionMode(gatt_if_, reconnection_mode_);
2972       }
2973     }
2974   }
2975 
subscribe_for_notification(tCONN_ID conn_id,const RawAddress & address,const struct bluetooth::le_audio::types::hdl_pair & handle_pair,bool gatt_register=true,bool write_ccc=true)2976   bool subscribe_for_notification(tCONN_ID conn_id, const RawAddress& address,
2977                                   const struct bluetooth::le_audio::types::hdl_pair& handle_pair,
2978                                   bool gatt_register = true, bool write_ccc = true) {
2979     std::vector<uint8_t> value(2);
2980     uint8_t* ptr = value.data();
2981     uint16_t handle = handle_pair.val_hdl;
2982     uint16_t ccc_handle = handle_pair.ccc_hdl;
2983 
2984     log::info("conn id {}, gatt_register: {}, write_ccc: {}", conn_id, gatt_register, write_ccc);
2985     if (gatt_register &&
2986         BTA_GATTC_RegisterForNotifications(gatt_if_, address, handle) != GATT_SUCCESS) {
2987       log::error("cannot register for notification: {}", static_cast<int>(handle));
2988       return false;
2989     }
2990 
2991     if (write_ccc == false) {
2992       log::verbose("CCC is not written to {} (0x{:04x}), handle 0x{:04x}", address, conn_id,
2993                    ccc_handle);
2994       return true;
2995     }
2996 
2997     UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION);
2998 
2999     BtaGattQueue::WriteDescriptor(
3000             conn_id, ccc_handle, std::move(value), GATT_WRITE,
3001             [](tCONN_ID conn_id, tGATT_STATUS status, uint16_t handle, uint16_t /*len*/,
3002                const uint8_t* /*value*/, void* data) {
3003               if (instance) {
3004                 instance->OnGattWriteCcc(conn_id, status, handle, data);
3005               }
3006             },
3007             nullptr);
3008     return true;
3009   }
3010 
3011   /* Find the handle for the client characteristics configuration of a given
3012    * characteristics.
3013    */
find_ccc_handle(const gatt::Characteristic & charac)3014   uint16_t find_ccc_handle(const gatt::Characteristic& charac) {
3015     auto iter = std::find_if(charac.descriptors.begin(), charac.descriptors.end(),
3016                              [](const auto& desc) {
3017                                return desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG);
3018                              });
3019 
3020     return iter == charac.descriptors.end() ? 0 : (*iter).handle;
3021   }
3022 
ClearDeviceInformationAndStartSearch(LeAudioDevice * leAudioDevice)3023   void ClearDeviceInformationAndStartSearch(LeAudioDevice* leAudioDevice) {
3024     if (!leAudioDevice) {
3025       log::warn("leAudioDevice is null");
3026       return;
3027     }
3028 
3029     log::info("{}", leAudioDevice->address_);
3030 
3031     if (leAudioDevice->known_service_handles_ == false) {
3032       log::debug("Database already invalidated");
3033       return;
3034     }
3035 
3036     leAudioDevice->known_service_handles_ = false;
3037     leAudioDevice->csis_member_ = false;
3038     BtaGattQueue::Clean(leAudioDevice->conn_id_);
3039     DeregisterNotifications(leAudioDevice);
3040 
3041     if (leAudioDevice->GetConnectionState() == DeviceConnectState::CONNECTED) {
3042       leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
3043     }
3044 
3045     btif_storage_leaudio_clear_service_data(leAudioDevice->address_);
3046 
3047     BTA_GATTC_ServiceSearchRequest(leAudioDevice->conn_id_,
3048                                    bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
3049   }
3050 
OnServiceChangeEvent(const RawAddress & address)3051   void OnServiceChangeEvent(const RawAddress& address) {
3052     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
3053     if (!leAudioDevice) {
3054       log::warn("Skipping unknown leAudioDevice {} ({})", address, std::format_ptr(leAudioDevice));
3055       return;
3056     }
3057 
3058     if (leAudioDevice->conn_id_ != GATT_INVALID_CONN_ID) {
3059       ClearDeviceInformationAndStartSearch(leAudioDevice);
3060       return;
3061     }
3062 
3063     /* If device is not connected, just clear the handle information and this
3064      * will trigger service search onGattConnected */
3065     leAudioDevice->known_service_handles_ = false;
3066     btif_storage_leaudio_clear_service_data(address);
3067   }
3068 
OnMtuChanged(tCONN_ID conn_id,uint16_t mtu)3069   void OnMtuChanged(tCONN_ID conn_id, uint16_t mtu) {
3070     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
3071     if (!leAudioDevice) {
3072       log::debug("Unknown connectect id {}", conn_id);
3073       return;
3074     }
3075 
3076     /**
3077      * BAP 1.01. 3.6.1
3078      * ATT and EATT transport requirements
3079      * The Unicast Client shall support a minimum ATT_MTU of 64 octets for one
3080      * Unenhanced ATT bearer, or for at least one Enhanced ATT bearer if the
3081      * Unicast Client supports Enhanced ATT bearers.
3082      *
3083      */
3084     if (mtu < 64) {
3085       log::error("Device {} MTU is too low ({}). Disconnecting from LE Audio",
3086                  leAudioDevice->address_, mtu);
3087       Disconnect(leAudioDevice->address_);
3088       return;
3089     }
3090 
3091     leAudioDevice->mtu_ = mtu;
3092   }
3093 
OnPhyUpdate(tCONN_ID conn_id,uint8_t tx_phy,uint8_t rx_phy,tGATT_STATUS status)3094   void OnPhyUpdate(tCONN_ID conn_id, uint8_t tx_phy, uint8_t rx_phy, tGATT_STATUS status) {
3095     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
3096     if (leAudioDevice == nullptr) {
3097       log::debug("Unknown conn_id {:#x}", conn_id);
3098       return;
3099     }
3100 
3101     log::info("{}, tx_phy: {:#x}, rx_phy: {:#x} , status: {:#x}", leAudioDevice->address_, tx_phy,
3102               rx_phy, status);
3103 
3104     if (status == 0) {
3105       leAudioDevice->acl_phy_update_done_ = true;
3106     }
3107   }
3108 
OnGattServiceDiscoveryDone(const RawAddress & address)3109   void OnGattServiceDiscoveryDone(const RawAddress& address) {
3110     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(address);
3111     if (!leAudioDevice || (leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID)) {
3112       log::verbose("skipping unknown leAudioDevice, address {} ({})", address,
3113                    std::format_ptr(leAudioDevice));
3114       return;
3115     }
3116 
3117     if (!leAudioDevice->encrypted_) {
3118       log::debug("Wait for device to be encrypted");
3119       return;
3120     }
3121 
3122     if (!leAudioDevice->known_service_handles_) {
3123       BTA_GATTC_ServiceSearchRequest(
3124               leAudioDevice->conn_id_,
3125               bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid);
3126     }
3127   }
3128 
disconnectInvalidDevice(LeAudioDevice * leAudioDevice,std::string error_string,LeAudioHealthDeviceStatType stat)3129   void disconnectInvalidDevice(LeAudioDevice* leAudioDevice, std::string error_string,
3130                                LeAudioHealthDeviceStatType stat) {
3131     log::error("{}, {}", leAudioDevice->address_, error_string);
3132     if (leAudioHealthStatus_) {
3133       leAudioHealthStatus_->AddStatisticForDevice(leAudioDevice, stat);
3134     }
3135     DisconnectDevice(leAudioDevice);
3136   }
3137 
3138   /* This method is called after connection beginning to identify and initialize
3139    * a le audio device. Any missing mandatory attribute will result in reverting
3140    * and cleaning up device.
3141    */
OnServiceSearchComplete(tCONN_ID conn_id,tGATT_STATUS status)3142   void OnServiceSearchComplete(tCONN_ID conn_id, tGATT_STATUS status) {
3143     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
3144 
3145     if (!leAudioDevice) {
3146       log::error("skipping unknown leAudioDevice, conn_id: 0x{:x}", conn_id);
3147       return;
3148     }
3149 
3150     log::info("test csis_member {}", leAudioDevice->csis_member_);
3151 
3152     if (status != GATT_SUCCESS) {
3153       /* close connection and report service discovery complete with error */
3154       log::error("Service discovery failed");
3155 
3156       DisconnectDevice(leAudioDevice);
3157       return;
3158     }
3159 
3160     if (!leAudioDevice->encrypted_) {
3161       log::warn("Device not yet bonded - waiting for encryption");
3162       return;
3163     }
3164 
3165     const std::list<gatt::Service>* services = BTA_GATTC_GetServices(conn_id);
3166 
3167     const gatt::Service* pac_svc = nullptr;
3168     const gatt::Service* ase_svc = nullptr;
3169     const gatt::Service* tmas_svc = nullptr;
3170     const gatt::Service* gmap_svc = nullptr;
3171 
3172     std::vector<uint16_t> csis_primary_handles;
3173     uint16_t cas_csis_included_handle = 0;
3174 
3175     for (const gatt::Service& tmp : *services) {
3176       if (tmp.uuid == bluetooth::le_audio::uuid::kPublishedAudioCapabilityServiceUuid) {
3177         log::info("Found Audio Capability service, handle: 0x{:04x}, device: {}", tmp.handle,
3178                   leAudioDevice->address_);
3179         pac_svc = &tmp;
3180       } else if (tmp.uuid == bluetooth::le_audio::uuid::kAudioStreamControlServiceUuid) {
3181         log::info("Found Audio Stream Endpoint service, handle: 0x{:04x}, device: {}", tmp.handle,
3182                   leAudioDevice->address_);
3183         ase_svc = &tmp;
3184       } else if (tmp.uuid == bluetooth::csis::kCsisServiceUuid) {
3185         log::info("Found CSIS service, handle: 0x{:04x}, is primary: {}, device: {}", tmp.handle,
3186                   tmp.is_primary, leAudioDevice->address_);
3187         if (tmp.is_primary) {
3188           csis_primary_handles.push_back(tmp.handle);
3189         }
3190       } else if (tmp.uuid == bluetooth::le_audio::uuid::kCapServiceUuid) {
3191         log::info("Found CAP service, handle: 0x{:04x}, device: {}", tmp.handle,
3192                   leAudioDevice->address_);
3193 
3194         /* Try to find context for CSIS instances */
3195         for (auto& included_srvc : tmp.included_services) {
3196           if (included_srvc.uuid == bluetooth::csis::kCsisServiceUuid) {
3197             log::info("CSIS included into CAS");
3198             if (bluetooth::csis::CsisClient::IsCsisClientRunning()) {
3199               cas_csis_included_handle = included_srvc.start_handle;
3200             }
3201 
3202             break;
3203           }
3204         }
3205       } else if (tmp.uuid == bluetooth::le_audio::uuid::kTelephonyMediaAudioServiceUuid) {
3206         log::info("Found Telephony and Media Audio service, handle: 0x{:04x}, device: {}",
3207                   tmp.handle, leAudioDevice->address_);
3208         tmas_svc = &tmp;
3209       } else if (tmp.uuid == bluetooth::le_audio::uuid::kGamingAudioServiceUuid) {
3210         log::info("Found Gaming Audio service, handle: 0x{:04x}, device: {}", tmp.handle,
3211                   leAudioDevice->address_);
3212         gmap_svc = &tmp;
3213       }
3214     }
3215 
3216     /* Check if CAS includes primary CSIS service */
3217     if (!csis_primary_handles.empty() && cas_csis_included_handle) {
3218       auto iter = std::find(csis_primary_handles.begin(), csis_primary_handles.end(),
3219                             cas_csis_included_handle);
3220       if (iter != csis_primary_handles.end()) {
3221         leAudioDevice->csis_member_ = true;
3222       }
3223     }
3224 
3225     if (!pac_svc || !ase_svc) {
3226       disconnectInvalidDevice(leAudioDevice, "No mandatory le audio services found (pacs or ascs)",
3227                               LeAudioHealthDeviceStatType::INVALID_DB);
3228       return;
3229     }
3230 
3231     /* Refresh PACs handles */
3232     leAudioDevice->ClearPACs();
3233 
3234     for (const gatt::Characteristic& charac : pac_svc->characteristics) {
3235       if (charac.uuid ==
3236           bluetooth::le_audio::uuid::kSinkPublishedAudioCapabilityCharacteristicUuid) {
3237         struct hdl_pair hdl_pair;
3238         hdl_pair.val_hdl = charac.value_handle;
3239         hdl_pair.ccc_hdl = find_ccc_handle(charac);
3240 
3241         if (hdl_pair.ccc_hdl == 0) {
3242           log::info(", Sink PACs ccc not available");
3243         }
3244 
3245         if (hdl_pair.ccc_hdl != 0 &&
3246             !subscribe_for_notification(conn_id, leAudioDevice->address_, hdl_pair)) {
3247           disconnectInvalidDevice(leAudioDevice, ", could not subscribe for snk pac char",
3248                                   LeAudioHealthDeviceStatType::INVALID_DB);
3249           return;
3250         }
3251 
3252         /* Obtain initial state of sink PACs */
3253         BtaGattQueue::ReadCharacteristic(conn_id, hdl_pair.val_hdl, OnGattReadRspStatic, NULL);
3254 
3255         leAudioDevice->snk_pacs_.push_back(std::make_tuple(
3256                 hdl_pair, std::vector<struct bluetooth::le_audio::types::acs_ac_record>()));
3257 
3258         log::info("Found Sink PAC characteristic, handle: 0x{:04x}, ccc handle: 0x{:04x}, addr: {}",
3259                   charac.value_handle, hdl_pair.ccc_hdl, leAudioDevice->address_);
3260       } else if (charac.uuid ==
3261                  bluetooth::le_audio::uuid::kSourcePublishedAudioCapabilityCharacteristicUuid) {
3262         struct hdl_pair hdl_pair;
3263         hdl_pair.val_hdl = charac.value_handle;
3264         hdl_pair.ccc_hdl = find_ccc_handle(charac);
3265 
3266         if (hdl_pair.ccc_hdl == 0) {
3267           log::info(", Source PACs ccc not available");
3268         }
3269 
3270         if (hdl_pair.ccc_hdl != 0 &&
3271             !subscribe_for_notification(conn_id, leAudioDevice->address_, hdl_pair)) {
3272           disconnectInvalidDevice(leAudioDevice, ", could not subscribe for src pac char",
3273                                   LeAudioHealthDeviceStatType::INVALID_DB);
3274           return;
3275         }
3276 
3277         /* Obtain initial state of source PACs */
3278         BtaGattQueue::ReadCharacteristic(conn_id, hdl_pair.val_hdl, OnGattReadRspStatic, NULL);
3279 
3280         leAudioDevice->src_pacs_.push_back(std::make_tuple(
3281                 hdl_pair, std::vector<struct bluetooth::le_audio::types::acs_ac_record>()));
3282 
3283         log::info(
3284                 "Found Source PAC characteristic, handle: 0x{:04x}, ccc handle: 0x{:04x}, addr: {}",
3285                 charac.value_handle, hdl_pair.ccc_hdl, leAudioDevice->address_);
3286       } else if (charac.uuid == bluetooth::le_audio::uuid::kSinkAudioLocationCharacteristicUuid) {
3287         auto ccc_hdl = find_ccc_handle(charac);
3288         leAudioDevice->audio_locations_.sink.emplace(hdl_pair(charac.value_handle, ccc_hdl),
3289                                                      AudioLocations(0));
3290 
3291         if (ccc_hdl == 0) {
3292           log::info(", snk audio locations char doesn't have ccc");
3293         } else if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
3294                                                leAudioDevice->audio_locations_.sink->handles)) {
3295           disconnectInvalidDevice(leAudioDevice, ", could not subscribe for snk locations char",
3296                                   LeAudioHealthDeviceStatType::INVALID_DB);
3297           return;
3298         }
3299 
3300         /* Obtain initial state of sink audio locations */
3301         BtaGattQueue::ReadCharacteristic(conn_id,
3302                                          leAudioDevice->audio_locations_.sink->handles.val_hdl,
3303                                          OnGattReadRspStatic, NULL);
3304 
3305         log::info(
3306                 "Found Sink audio locations characteristic, handle: 0x{:04x}, ccc handle: "
3307                 "0x{:04x}, addr: {}",
3308                 charac.value_handle, ccc_hdl, leAudioDevice->address_);
3309       } else if (charac.uuid == bluetooth::le_audio::uuid::kSourceAudioLocationCharacteristicUuid) {
3310         auto ccc_hdl = find_ccc_handle(charac);
3311         leAudioDevice->audio_locations_.source.emplace(hdl_pair(charac.value_handle, ccc_hdl),
3312                                                        AudioLocations(0));
3313 
3314         if (ccc_hdl == 0) {
3315           log::info(", src audio locations char doesn't have ccc");
3316         } else if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
3317                                                leAudioDevice->audio_locations_.source->handles)) {
3318           disconnectInvalidDevice(leAudioDevice, ", could not subscribe for src locations char",
3319                                   LeAudioHealthDeviceStatType::INVALID_DB);
3320           return;
3321         }
3322 
3323         /* Obtain initial state of source audio locations */
3324         BtaGattQueue::ReadCharacteristic(conn_id,
3325                                          leAudioDevice->audio_locations_.source->handles.val_hdl,
3326                                          OnGattReadRspStatic, NULL);
3327 
3328         log::info(
3329                 "Found Source audio locations characteristic, handle: 0x{:04x}, ccc handle: "
3330                 "0x{:04x}, addr: {}",
3331                 charac.value_handle, ccc_hdl, leAudioDevice->address_);
3332       } else if (charac.uuid ==
3333                  bluetooth::le_audio::uuid::kAudioContextAvailabilityCharacteristicUuid) {
3334         leAudioDevice->audio_avail_hdls_.val_hdl = charac.value_handle;
3335         leAudioDevice->audio_avail_hdls_.ccc_hdl = find_ccc_handle(charac);
3336 
3337         if (leAudioDevice->audio_avail_hdls_.ccc_hdl == 0) {
3338           disconnectInvalidDevice(leAudioDevice, ", audio avails char doesn't have ccc",
3339                                   LeAudioHealthDeviceStatType::INVALID_DB);
3340           return;
3341         }
3342 
3343         if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
3344                                         leAudioDevice->audio_avail_hdls_)) {
3345           disconnectInvalidDevice(leAudioDevice, ", could not subscribe for audio avails char",
3346                                   LeAudioHealthDeviceStatType::INVALID_DB);
3347           return;
3348         }
3349 
3350         /* Obtain initial state */
3351         BtaGattQueue::ReadCharacteristic(conn_id, leAudioDevice->audio_avail_hdls_.val_hdl,
3352                                          OnGattReadRspStatic, NULL);
3353 
3354         log::info(
3355                 "Found Audio Availability Context characteristic, handle: "
3356                 "0x{:04x}, ccc handle: 0x{:04x}, addr: {}",
3357                 charac.value_handle, leAudioDevice->audio_avail_hdls_.ccc_hdl,
3358                 leAudioDevice->address_);
3359       } else if (charac.uuid ==
3360                  bluetooth::le_audio::uuid::kAudioSupportedContextCharacteristicUuid) {
3361         leAudioDevice->audio_supp_cont_hdls_.val_hdl = charac.value_handle;
3362         leAudioDevice->audio_supp_cont_hdls_.ccc_hdl = find_ccc_handle(charac);
3363 
3364         if (leAudioDevice->audio_supp_cont_hdls_.ccc_hdl == 0) {
3365           log::info(", audio supported char doesn't have ccc");
3366         }
3367 
3368         if (leAudioDevice->audio_supp_cont_hdls_.ccc_hdl != 0 &&
3369             !subscribe_for_notification(conn_id, leAudioDevice->address_,
3370                                         leAudioDevice->audio_supp_cont_hdls_)) {
3371           disconnectInvalidDevice(leAudioDevice,
3372                                   ", could not subscribe for audio supported ctx char",
3373                                   LeAudioHealthDeviceStatType::INVALID_DB);
3374           return;
3375         }
3376 
3377         /* Obtain initial state */
3378         BtaGattQueue::ReadCharacteristic(conn_id, leAudioDevice->audio_supp_cont_hdls_.val_hdl,
3379                                          OnGattReadRspStatic, NULL);
3380 
3381         log::info(
3382                 "Found Audio Supported Context characteristic, handle: 0x{:04x}, "
3383                 "ccc handle: 0x{:04x}, addr: {}",
3384                 charac.value_handle, leAudioDevice->audio_supp_cont_hdls_.ccc_hdl,
3385                 leAudioDevice->address_);
3386       }
3387     }
3388 
3389     /* Refresh ASE handles */
3390     leAudioDevice->ases_.clear();
3391 
3392     for (const gatt::Characteristic& charac : ase_svc->characteristics) {
3393       log::info("Found characteristic, uuid: {}", charac.uuid.ToString());
3394       if (charac.uuid == bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid ||
3395           charac.uuid == bluetooth::le_audio::uuid::kSourceAudioStreamEndpointUuid) {
3396         uint16_t ccc_handle = find_ccc_handle(charac);
3397         if (ccc_handle == 0) {
3398           disconnectInvalidDevice(leAudioDevice, ", ASE char doesn't have ccc",
3399                                   LeAudioHealthDeviceStatType::INVALID_DB);
3400           return;
3401         }
3402         struct bluetooth::le_audio::types::hdl_pair hdls(charac.value_handle, ccc_handle);
3403         if (!subscribe_for_notification(conn_id, leAudioDevice->address_, hdls)) {
3404           disconnectInvalidDevice(leAudioDevice, ", could not subscribe ASE char",
3405                                   LeAudioHealthDeviceStatType::INVALID_DB);
3406           return;
3407         }
3408 
3409         int direction = charac.uuid == bluetooth::le_audio::uuid::kSinkAudioStreamEndpointUuid
3410                                 ? bluetooth::le_audio::types::kLeAudioDirectionSink
3411                                 : bluetooth::le_audio::types::kLeAudioDirectionSource;
3412 
3413         leAudioDevice->ases_.emplace_back(charac.value_handle, ccc_handle, direction);
3414 
3415         log::info(
3416                 "Found ASE characteristic, handle: 0x{:04x}, ccc handle: 0x{:04x}, "
3417                 "direction: {}, addr: {}",
3418                 charac.value_handle, ccc_handle, direction, leAudioDevice->address_);
3419       } else if (charac.uuid ==
3420                  bluetooth::le_audio::uuid::kAudioStreamEndpointControlPointCharacteristicUuid) {
3421         leAudioDevice->ctp_hdls_.val_hdl = charac.value_handle;
3422         leAudioDevice->ctp_hdls_.ccc_hdl = find_ccc_handle(charac);
3423 
3424         if (leAudioDevice->ctp_hdls_.ccc_hdl == 0) {
3425           disconnectInvalidDevice(leAudioDevice, ", ASE ctp doesn't have ccc",
3426                                   LeAudioHealthDeviceStatType::INVALID_DB);
3427           return;
3428         }
3429 
3430         if (!subscribe_for_notification(conn_id, leAudioDevice->address_,
3431                                         leAudioDevice->ctp_hdls_)) {
3432           disconnectInvalidDevice(leAudioDevice, ", could not subscribe ASE char",
3433                                   LeAudioHealthDeviceStatType::INVALID_DB);
3434           return;
3435         }
3436 
3437         log::info(
3438                 "Found ASE Control Point characteristic, handle: 0x{:04x}, ccc "
3439                 "handle: 0x{:04x}, addr: {}",
3440                 charac.value_handle, leAudioDevice->ctp_hdls_.ccc_hdl, leAudioDevice->address_);
3441       }
3442     }
3443 
3444     if (tmas_svc) {
3445       for (const gatt::Characteristic& charac : tmas_svc->characteristics) {
3446         if (charac.uuid ==
3447             bluetooth::le_audio::uuid::kTelephonyMediaAudioProfileRoleCharacteristicUuid) {
3448           leAudioDevice->tmap_role_hdl_ = charac.value_handle;
3449 
3450           /* Obtain initial state of TMAP role */
3451           BtaGattQueue::ReadCharacteristic(conn_id, leAudioDevice->tmap_role_hdl_,
3452                                            OnGattReadRspStatic, NULL);
3453 
3454           log::info(
3455                   "Found Telephony and Media Profile characteristic, handle: 0x{:04x}, device: {}",
3456                   leAudioDevice->tmap_role_hdl_, leAudioDevice->address_);
3457         }
3458       }
3459     }
3460 
3461     if (gmap_svc && GmapClient::IsGmapClientEnabled()) {
3462       leAudioDevice->gmap_client_ = std::make_unique<GmapClient>(leAudioDevice->address_);
3463       for (const gatt::Characteristic& charac : gmap_svc->characteristics) {
3464         if (charac.uuid == bluetooth::le_audio::uuid::kRoleCharacteristicUuid) {
3465           uint16_t handle = charac.value_handle;
3466           leAudioDevice->gmap_client_->setRoleHandle(handle);
3467           BtaGattQueue::ReadCharacteristic(conn_id, handle, OnGattReadRspStatic, NULL);
3468           log::info("Found Gmap Role characteristic, handle: 0x{:04x}, device: {}",
3469                     leAudioDevice->gmap_client_->getRoleHandle(), leAudioDevice->address_);
3470         }
3471         if (charac.uuid == bluetooth::le_audio::uuid::kUnicastGameTerminalCharacteristicUuid) {
3472           uint16_t handle = charac.value_handle;
3473           leAudioDevice->gmap_client_->setUGTFeatureHandle(handle);
3474           BtaGattQueue::ReadCharacteristic(conn_id, handle, OnGattReadRspStatic, NULL);
3475           log::info("Found Gmap UGT Feature characteristic, handle: 0x{:04x}, device: {}",
3476                     leAudioDevice->gmap_client_->getUGTFeatureHandle(), leAudioDevice->address_);
3477         }
3478       }
3479     }
3480 
3481     leAudioDevice->known_service_handles_ = true;
3482     leAudioDevice->notify_connected_after_read_ = true;
3483     if (leAudioHealthStatus_) {
3484       leAudioHealthStatus_->AddStatisticForDevice(leAudioDevice,
3485                                                   LeAudioHealthDeviceStatType::VALID_DB);
3486     }
3487 
3488     /* If already known group id */
3489     if (leAudioDevice->group_id_ != bluetooth::groups::kGroupUnknown) {
3490       AseInitialStateReadRequest(leAudioDevice);
3491       return;
3492     }
3493 
3494     /* If device does not belong to any group yet we either add it to the
3495      * group by our self now or wait for Csis to do it. In both cases, let's
3496      * check if group is already assigned.
3497      */
3498     int group_id = DeviceGroups::Get()->GetGroupId(leAudioDevice->address_,
3499                                                    bluetooth::le_audio::uuid::kCapServiceUuid);
3500     if (group_id != bluetooth::groups::kGroupUnknown) {
3501       instance->group_add_node(group_id, leAudioDevice->address_);
3502       return;
3503     }
3504 
3505     /* CSIS will trigger adding to group */
3506     if (leAudioDevice->csis_member_) {
3507       log::info("{},  waiting for CSIS to create group for device", leAudioDevice->address_);
3508       scheduleGuardForCsisAdd(leAudioDevice->address_);
3509       return;
3510     }
3511 
3512     log::info("{} Not a CSIS member. Create group by our own", leAudioDevice->address_);
3513 
3514     /* If there is no Csis just add device by our own */
3515     DeviceGroups::Get()->AddDevice(leAudioDevice->address_,
3516                                    bluetooth::le_audio::uuid::kCapServiceUuid);
3517   }
3518 
OnGattWriteCcc(tCONN_ID conn_id,tGATT_STATUS status,uint16_t hdl,void *)3519   void OnGattWriteCcc(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hdl, void* /*data*/) {
3520     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByConnId(conn_id);
3521     std::vector<struct ase>::iterator ase_it;
3522 
3523     if (!leAudioDevice) {
3524       log::error("unknown conn_id=0x{:x}", conn_id);
3525       return;
3526     }
3527 
3528     if (status == GATT_DATABASE_OUT_OF_SYNC) {
3529       log::info("Database out of sync for {}, conn_id: 0x{:04x}", leAudioDevice->address_, conn_id);
3530       ClearDeviceInformationAndStartSearch(leAudioDevice);
3531       return;
3532     }
3533 
3534     if (status == GATT_SUCCESS) {
3535       log::info("Successfully registered on ccc: 0x{:04x}, device: {}", hdl,
3536                 leAudioDevice->address_);
3537 
3538       if (leAudioDevice->ctp_hdls_.ccc_hdl == hdl && leAudioDevice->known_service_handles_ &&
3539           !leAudioDevice->notify_connected_after_read_) {
3540         /* Reconnection case. Control point is the last CCC LeAudio is
3541          * registering for on reconnection */
3542         connectionReady(leAudioDevice);
3543       }
3544 
3545       return;
3546     }
3547 
3548     log::error("Failed to register for notifications: 0x{:04x}, device: {}, status: 0x{:02x}", hdl,
3549                leAudioDevice->address_, status);
3550 
3551     ase_it =
3552             std::find_if(leAudioDevice->ases_.begin(), leAudioDevice->ases_.end(),
3553                          [&hdl](const struct ase& ase) -> bool { return ase.hdls.ccc_hdl == hdl; });
3554 
3555     if (ase_it == leAudioDevice->ases_.end()) {
3556       log::error("Unknown ccc handle: 0x{:04x}, device: {}", hdl, leAudioDevice->address_);
3557       return;
3558     }
3559 
3560     BTA_GATTC_DeregisterForNotifications(gatt_if_, leAudioDevice->address_, ase_it->hdls.val_hdl);
3561   }
3562 
AttachToStreamingGroupIfNeeded(LeAudioDevice * leAudioDevice)3563   void AttachToStreamingGroupIfNeeded(LeAudioDevice* leAudioDevice) {
3564     if (leAudioDevice->group_id_ != active_group_id_) {
3565       log::info("group  {} is not streaming. Nothing to do", leAudioDevice->group_id_);
3566       return;
3567     }
3568 
3569     if (leAudioDevice->GetConnectionState() != DeviceConnectState::CONNECTED) {
3570       /* Do nothing, wait until device is connected */
3571       log::debug("{} is not yet connected", leAudioDevice->address_);
3572       return;
3573     }
3574 
3575     if (leAudioDevice->HaveActiveAse()) {
3576       log::debug("{} is already configured, nothing to do", leAudioDevice->address_);
3577       return;
3578     }
3579 
3580     LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3581 
3582     auto group_metadata_contexts = get_bidirectional(group->GetMetadataContexts());
3583     auto device_available_contexts = leAudioDevice->GetAvailableContexts();
3584     if (!group_metadata_contexts.test_any(device_available_contexts)) {
3585       log::info(
3586               "{} does not have required context type. Group Context type: {}, device available {}",
3587               leAudioDevice->address_, common::ToString(group_metadata_contexts),
3588               common::ToString(device_available_contexts));
3589       return;
3590     }
3591 
3592     /* Restore configuration */
3593     auto* stream_conf = &group->stream_conf;
3594 
3595     if (audio_sender_state_ == AudioState::IDLE && audio_receiver_state_ == AudioState::IDLE) {
3596       log::debug("Device not streaming but active - nothing to do");
3597       return;
3598     }
3599 
3600     if (!stream_conf->conf) {
3601       log::info("Configuration not yet set. Nothing to do now");
3602       return;
3603     }
3604 
3605     log::info("Attaching {} to group: {}", leAudioDevice->address_, leAudioDevice->group_id_);
3606 
3607     for (auto direction : {bluetooth::le_audio::types::kLeAudioDirectionSink,
3608                            bluetooth::le_audio::types::kLeAudioDirectionSource}) {
3609       log::info("Looking for requirements: {} - {}", stream_conf->conf->name,
3610                 (direction == 1 ? "snk" : "src"));
3611       const auto& pacs = (direction == bluetooth::le_audio::types::kLeAudioDirectionSink)
3612                                  ? leAudioDevice->snk_pacs_
3613                                  : leAudioDevice->src_pacs_;
3614       for (const auto& ent : stream_conf->conf->confs.get(direction)) {
3615         if (!bluetooth::le_audio::utils::GetConfigurationSupportedPac(pacs, ent.codec)) {
3616           log::info("Configuration is not supported by device {}", leAudioDevice->address_);
3617 
3618           /* Reconfigure if newly connected member device cannot support
3619            * current codec configuration */
3620           initReconfiguration(group, configuration_context_type_);
3621           return;
3622         }
3623       }
3624     }
3625 
3626     /* Do not put the TBS CCID when not using Telecom for the VoIP calls. */
3627     auto ccid_contexts = group->GetMetadataContexts();
3628     if (IsInVoipCall() && !IsInCall()) {
3629       ccid_contexts.sink.unset(LeAudioContextType::CONVERSATIONAL);
3630       ccid_contexts.source.unset(LeAudioContextType::CONVERSATIONAL);
3631     }
3632     BidirectionalPair<std::vector<uint8_t>> ccids = {
3633             .sink = ContentControlIdKeeper::GetInstance()->GetAllCcids(ccid_contexts.sink),
3634             .source = ContentControlIdKeeper::GetInstance()->GetAllCcids(ccid_contexts.source)};
3635 
3636     if (!groupStateMachine_->AttachToStream(group, leAudioDevice, std::move(ccids))) {
3637       log::warn("Could not add device {} to the group {} streaming.", leAudioDevice->address_,
3638                 group->group_id_);
3639       scheduleAttachDeviceToTheStream(leAudioDevice->address_);
3640     } else {
3641       speed_start_setup(group->group_id_, configuration_context_type_, 1);
3642     }
3643   }
3644 
restartAttachToTheStream(const RawAddress & addr)3645   void restartAttachToTheStream(const RawAddress& addr) {
3646     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByAddress(addr);
3647     if (leAudioDevice == nullptr || leAudioDevice->conn_id_ == GATT_INVALID_CONN_ID) {
3648       log::info("Device {} not available anymore", addr);
3649       return;
3650     }
3651     AttachToStreamingGroupIfNeeded(leAudioDevice);
3652   }
3653 
scheduleAttachDeviceToTheStream(const RawAddress & addr)3654   void scheduleAttachDeviceToTheStream(const RawAddress& addr) {
3655     log::info("Device {} is scheduled for streaming", addr);
3656     do_in_main_thread_delayed(base::BindOnce(&LeAudioClientImpl::restartAttachToTheStream,
3657                                              weak_factory_.GetWeakPtr(), addr),
3658                               std::chrono::milliseconds(kDeviceAttachDelayMs));
3659   }
3660 
SendAudioGroupSelectableCodecConfigChanged(LeAudioDeviceGroup * group)3661   void SendAudioGroupSelectableCodecConfigChanged(LeAudioDeviceGroup* group) {
3662     auto leAudioDevice = group->GetFirstDevice();
3663     callbacks_->OnAudioGroupSelectableCodecConf(
3664             group->group_id_,
3665             bluetooth::le_audio::utils::GetRemoteBtLeAudioCodecConfigFromPac(
3666                     leAudioDevice->src_pacs_),
3667             bluetooth::le_audio::utils::GetRemoteBtLeAudioCodecConfigFromPac(
3668                     leAudioDevice->snk_pacs_));
3669   }
3670 
SendAudioGroupCurrentCodecConfigChanged(LeAudioDeviceGroup * group)3671   void SendAudioGroupCurrentCodecConfigChanged(LeAudioDeviceGroup* group) {
3672     // This shall be called when configuration changes
3673     log::debug("{}", group->group_id_);
3674 
3675     auto audio_set_conf = group->GetConfiguration(configuration_context_type_);
3676     if (!audio_set_conf) {
3677       log::warn("Stream configuration is not valid for group id {}", group->group_id_);
3678       return;
3679     }
3680 
3681     bluetooth::le_audio::btle_audio_codec_config_t input_config{};
3682     bluetooth::le_audio::utils::fillStreamParamsToBtLeAudioCodecConfig(audio_set_conf->confs.source,
3683                                                                        input_config);
3684 
3685     bluetooth::le_audio::btle_audio_codec_config_t output_config{};
3686     bluetooth::le_audio::utils::fillStreamParamsToBtLeAudioCodecConfig(audio_set_conf->confs.sink,
3687                                                                        output_config);
3688 
3689     callbacks_->OnAudioGroupCurrentCodecConf(group->group_id_, input_config, output_config);
3690   }
3691 
connectionReady(LeAudioDevice * leAudioDevice)3692   void connectionReady(LeAudioDevice* leAudioDevice) {
3693     log::debug("{},  {}", leAudioDevice->address_,
3694                bluetooth::common::ToString(leAudioDevice->GetConnectionState()));
3695 
3696     stack::l2cap::get_interface().L2CA_LockBleConnParamsForProfileConnection(
3697             leAudioDevice->address_, false);
3698 
3699     if (leAudioDevice->GetConnectionState() ==
3700                 DeviceConnectState::CONNECTED_BY_USER_GETTING_READY &&
3701         (leAudioDevice->autoconnect_flag_ == false)) {
3702       btif_storage_set_leaudio_autoconnect(leAudioDevice->address_, true);
3703       leAudioDevice->autoconnect_flag_ = true;
3704     }
3705 
3706     leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
3707     bluetooth::le_audio::MetricsCollector::Get()->OnConnectionStateChanged(
3708             leAudioDevice->group_id_, leAudioDevice->address_, ConnectionState::CONNECTED,
3709             bluetooth::le_audio::ConnectionStatus::SUCCESS);
3710 
3711     if (leAudioDevice->group_id_ == bluetooth::groups::kGroupUnknown) {
3712       log::warn("LeAudio device {} connected with no group", leAudioDevice->address_);
3713       callbacks_->OnConnectionState(ConnectionState::CONNECTED, leAudioDevice->address_);
3714       return;
3715     }
3716 
3717     LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
3718     if (group) {
3719       UpdateLocationsAndContextsAvailability(group, true);
3720     }
3721 
3722     /* Notify connected after contexts are notified */
3723     callbacks_->OnConnectionState(ConnectionState::CONNECTED, leAudioDevice->address_);
3724 
3725     AttachToStreamingGroupIfNeeded(leAudioDevice);
3726 
3727     if (reconnection_mode_ == BTM_BLE_BKG_CONNECT_TARGETED_ANNOUNCEMENTS) {
3728       /* Add other devices to allow list if there are any not yet connected
3729        * from the group
3730        */
3731       group->AddToAllowListNotConnectedGroupMembers(gatt_if_);
3732     }
3733   }
3734 
IsAseAcceptingAudioData(struct ase * ase)3735   bool IsAseAcceptingAudioData(struct ase* ase) {
3736     if (ase == nullptr) {
3737       return false;
3738     }
3739     if (ase->state != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
3740       return false;
3741     }
3742     if (ase->data_path_state != DataPathState::CONFIGURED) {
3743       return false;
3744     }
3745 
3746     return true;
3747   }
3748 
3749   // mix stero signal into mono
mono_blend(const std::vector<uint8_t> & buf,int bytes_per_sample,size_t frames)3750   std::vector<uint8_t> mono_blend(const std::vector<uint8_t>& buf, int bytes_per_sample,
3751                                   size_t frames) {
3752     std::vector<uint8_t> mono_out;
3753     mono_out.resize(frames * bytes_per_sample);
3754 
3755     if (bytes_per_sample == 2) {
3756       int16_t* out = (int16_t*)mono_out.data();
3757       const int16_t* in = (int16_t*)(buf.data());
3758       for (size_t i = 0; i < frames; ++i) {
3759         int accum = 0;
3760         accum += *in++;
3761         accum += *in++;
3762         accum /= 2;  // round to 0
3763         *out++ = accum;
3764       }
3765     } else if (bytes_per_sample == 4) {
3766       int32_t* out = (int32_t*)mono_out.data();
3767       const int32_t* in = (int32_t*)(buf.data());
3768       for (size_t i = 0; i < frames; ++i) {
3769         int accum = 0;
3770         accum += *in++;
3771         accum += *in++;
3772         accum /= 2;  // round to 0
3773         *out++ = accum;
3774       }
3775     } else {
3776       log::error("Don't know how to mono blend that {}!", bytes_per_sample);
3777     }
3778     return mono_out;
3779   }
3780 
PrepareAndSendToTwoCises(const std::vector<uint8_t> & data,const struct bluetooth::le_audio::stream_parameters & stream_params)3781   void PrepareAndSendToTwoCises(
3782           const std::vector<uint8_t>& data,
3783           const struct bluetooth::le_audio::stream_parameters& stream_params) {
3784     uint16_t left_cis_handle = 0;
3785     uint16_t right_cis_handle = 0;
3786 
3787     uint16_t number_of_required_samples_per_channel = sw_enc_left->GetNumOfSamplesPerChannel();
3788     uint8_t bytes_per_sample = sw_enc_left->GetNumOfBytesPerSample();
3789     if (data.size() <
3790         bytes_per_sample * 2 /* channels */ * number_of_required_samples_per_channel) {
3791       log::error("Missing samples. Data size: {} expected: {}", data.size(),
3792                  bytes_per_sample * 2 * number_of_required_samples_per_channel);
3793       return;
3794     }
3795 
3796     for (auto const& info : stream_params.stream_config.stream_map) {
3797       if (info.audio_channel_allocation &
3798           bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyLeft) {
3799         left_cis_handle = info.stream_handle;
3800       }
3801       if (info.audio_channel_allocation &
3802           bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyRight) {
3803         right_cis_handle = info.stream_handle;
3804       }
3805     }
3806 
3807     if (stream_params.stream_config.codec_frames_blocks_per_sdu != 1) {
3808       log::error("Codec Frame Blocks of {} is not supported by the software encoding",
3809                  +stream_params.stream_config.codec_frames_blocks_per_sdu);
3810     }
3811 
3812     uint16_t byte_count = stream_params.stream_config.octets_per_codec_frame;
3813     bool mix_to_mono = (left_cis_handle == 0) || (right_cis_handle == 0);
3814     if (mix_to_mono) {
3815       std::vector<uint8_t> mono =
3816               mono_blend(data, bytes_per_sample, number_of_required_samples_per_channel);
3817       if (left_cis_handle) {
3818         sw_enc_left->Encode(mono.data(), 1, byte_count);
3819       }
3820 
3821       if (right_cis_handle) {
3822         sw_enc_left->Encode(mono.data(), 1, byte_count);
3823       }
3824     } else {
3825       sw_enc_left->Encode(data.data(), 2, byte_count);
3826       sw_enc_right->Encode(data.data() + bytes_per_sample, 2, byte_count);
3827     }
3828 
3829     log::debug("left_cis_handle: {} right_cis_handle: {}", left_cis_handle, right_cis_handle);
3830     /* Send data to the controller */
3831     if (left_cis_handle) {
3832       IsoManager::GetInstance()->SendIsoData(
3833               left_cis_handle, (const uint8_t*)sw_enc_left->GetDecodedSamples().data(),
3834               sw_enc_left->GetDecodedSamples().size() * 2);
3835     }
3836 
3837     if (right_cis_handle) {
3838       IsoManager::GetInstance()->SendIsoData(
3839               right_cis_handle, (const uint8_t*)sw_enc_right->GetDecodedSamples().data(),
3840               sw_enc_right->GetDecodedSamples().size() * 2);
3841     }
3842   }
3843 
PrepareAndSendToSingleCis(const std::vector<uint8_t> & data,const struct bluetooth::le_audio::stream_parameters & stream_params)3844   void PrepareAndSendToSingleCis(
3845           const std::vector<uint8_t>& data,
3846           const struct bluetooth::le_audio::stream_parameters& stream_params) {
3847     uint16_t num_channels = stream_params.num_of_channels;
3848     uint16_t cis_handle = stream_params.stream_config.stream_map.front().stream_handle;
3849 
3850     uint16_t number_of_required_samples_per_channel = sw_enc_left->GetNumOfSamplesPerChannel();
3851     uint8_t bytes_per_sample = sw_enc_left->GetNumOfBytesPerSample();
3852     if ((int)data.size() <
3853         (bytes_per_sample * num_channels * number_of_required_samples_per_channel)) {
3854       log::error("Missing samples");
3855       return;
3856     }
3857 
3858     if (stream_params.stream_config.codec_frames_blocks_per_sdu != 1) {
3859       log::error("Codec Frame Blocks of {} is not supported by the software encoding",
3860                  +stream_params.stream_config.codec_frames_blocks_per_sdu);
3861     }
3862 
3863     uint16_t byte_count = stream_params.stream_config.octets_per_codec_frame;
3864     bool mix_to_mono = (num_channels == 1);
3865     if (mix_to_mono) {
3866       /* Since we always get two channels from framework, lets make it mono here
3867        */
3868       std::vector<uint8_t> mono =
3869               mono_blend(data, bytes_per_sample, number_of_required_samples_per_channel);
3870       sw_enc_left->Encode(mono.data(), 1, byte_count);
3871     } else {
3872       sw_enc_left->Encode((const uint8_t*)data.data(), 2, byte_count);
3873       // Output to the left channel buffer with `byte_count` offset
3874       sw_enc_right->Encode((const uint8_t*)data.data() + 2, 2, byte_count,
3875                            &sw_enc_left->GetDecodedSamples(), byte_count);
3876     }
3877 
3878     IsoManager::GetInstance()->SendIsoData(cis_handle,
3879                                            (const uint8_t*)sw_enc_left->GetDecodedSamples().data(),
3880                                            sw_enc_left->GetDecodedSamples().size() * 2);
3881   }
3882 
GetStreamSinkConfiguration(LeAudioDeviceGroup * group)3883   const struct bluetooth::le_audio::stream_configuration* GetStreamSinkConfiguration(
3884           LeAudioDeviceGroup* group) {
3885     const struct bluetooth::le_audio::stream_configuration* stream_conf = &group->stream_conf;
3886     log::info("group_id: {}", group->group_id_);
3887     if (stream_conf->stream_params.sink.stream_config.stream_map.size() == 0) {
3888       return nullptr;
3889     }
3890 
3891     log::info("configuration: {}", stream_conf->conf->name);
3892     return stream_conf;
3893   }
3894 
OnAudioDataReady(const std::vector<uint8_t> & data)3895   void OnAudioDataReady(const std::vector<uint8_t>& data) {
3896     if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
3897         (audio_sender_state_ != AudioState::STARTED)) {
3898       return;
3899     }
3900 
3901     LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3902     if (!group) {
3903       log::error("There is no streaming group available");
3904       return;
3905     }
3906 
3907     auto stream_conf = group->stream_conf;
3908     if ((stream_conf.stream_params.sink.num_of_devices > 2) ||
3909         (stream_conf.stream_params.sink.num_of_devices == 0) ||
3910         stream_conf.stream_params.sink.stream_config.stream_map.empty()) {
3911       log::error("Stream configufation is not valid.");
3912       return;
3913     }
3914 
3915     if ((stream_conf.stream_params.sink.num_of_devices == 2) ||
3916         (stream_conf.stream_params.sink.stream_config.stream_map.size() == 2)) {
3917       /* Streaming to two devices or one device with 2 CISes */
3918       PrepareAndSendToTwoCises(data, stream_conf.stream_params.sink);
3919     } else {
3920       /* Streaming to one device and 1 CIS */
3921       PrepareAndSendToSingleCis(data, stream_conf.stream_params.sink);
3922     }
3923   }
3924 
CleanCachedMicrophoneData()3925   void CleanCachedMicrophoneData() {
3926     cached_channel_timestamp_ = 0;
3927     cached_channel_ = nullptr;
3928   }
3929 
3930   /* Handles audio data packets coming from the controller */
HandleIncomingCisData(uint8_t * data,uint16_t size,uint16_t cis_conn_hdl,uint32_t timestamp)3931   void HandleIncomingCisData(uint8_t* data, uint16_t size, uint16_t cis_conn_hdl,
3932                              uint32_t timestamp) {
3933     /* Get only one channel for MONO microphone */
3934     /* Gather data for channel */
3935     if ((active_group_id_ == bluetooth::groups::kGroupUnknown) ||
3936         (audio_receiver_state_ != AudioState::STARTED)) {
3937       return;
3938     }
3939 
3940     LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
3941     if (!group) {
3942       log::error("There is no streaming group available");
3943       return;
3944     }
3945 
3946     uint16_t left_cis_handle = 0;
3947     uint16_t right_cis_handle = 0;
3948     for (auto const& info : group->stream_conf.stream_params.source.stream_config.stream_map) {
3949       // Use the left channel decoder for the Mono Audio microphone
3950       auto is_mono = info.audio_channel_allocation ==
3951                      bluetooth::le_audio::codec_spec_conf::kLeAudioLocationMonoAudio;
3952       if (is_mono || (info.audio_channel_allocation &
3953                       bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyLeft)) {
3954         left_cis_handle = info.stream_handle;
3955       }
3956       if (info.audio_channel_allocation &
3957           bluetooth::le_audio::codec_spec_conf::kLeAudioLocationAnyRight) {
3958         right_cis_handle = info.stream_handle;
3959       }
3960     }
3961 
3962     auto decoder = sw_dec_left.get();
3963     if (cis_conn_hdl == left_cis_handle) {
3964       decoder = sw_dec_left.get();
3965     } else if (cis_conn_hdl == right_cis_handle) {
3966       decoder = sw_dec_right.get();
3967     } else {
3968       log::error("Received data for unknown handle: {:04x}", cis_conn_hdl);
3969       return;
3970     }
3971 
3972     if (!left_cis_handle || !right_cis_handle) {
3973       /* mono or just one device connected */
3974       decoder->Decode(data, size);
3975       SendAudioDataToAF(&decoder->GetDecodedSamples());
3976       return;
3977     }
3978     /* both devices are connected */
3979 
3980     if (cached_channel_ == nullptr || cached_channel_->GetDecodedSamples().empty()) {
3981       /* First packet received, cache it. We need both channel data to send it
3982        * to AF. */
3983       decoder->Decode(data, size);
3984       cached_channel_timestamp_ = timestamp;
3985       cached_channel_ = decoder;
3986       return;
3987     }
3988 
3989     /* We received either data for the other audio channel, or another
3990      * packet for same channel */
3991     if (cached_channel_ != decoder) {
3992       /* It's data for the 2nd channel */
3993       if (timestamp == cached_channel_timestamp_) {
3994         /* Ready to mix data and send out to AF */
3995         decoder->Decode(data, size);
3996         SendAudioDataToAF(&sw_dec_left->GetDecodedSamples(), &sw_dec_right->GetDecodedSamples());
3997 
3998         CleanCachedMicrophoneData();
3999         return;
4000       }
4001 
4002       /* 2nd Channel is in the future compared to the cached data.
4003        Send the cached data to AF, and keep the new channel data in cache.
4004        This should happen only during stream setup */
4005       SendAudioDataToAF(&decoder->GetDecodedSamples());
4006 
4007       decoder->Decode(data, size);
4008       cached_channel_timestamp_ = timestamp;
4009       cached_channel_ = decoder;
4010       return;
4011     }
4012 
4013     /* Data for same channel received. 2nd channel is down/not sending
4014      * data */
4015 
4016     /* Send the cached data out */
4017     SendAudioDataToAF(&decoder->GetDecodedSamples());
4018 
4019     /* Cache the data in case 2nd channel connects */
4020     decoder->Decode(data, size);
4021     cached_channel_timestamp_ = timestamp;
4022     cached_channel_ = decoder;
4023   }
4024 
SendAudioDataToAF(std::vector<int16_t> * left,std::vector<int16_t> * right=nullptr)4025   void SendAudioDataToAF(std::vector<int16_t>* left, std::vector<int16_t>* right = nullptr) {
4026     uint16_t to_write = 0;
4027     uint16_t written = 0;
4028 
4029     bool af_is_stereo = (audio_framework_sink_config.num_channels == 2);
4030     bool bt_got_stereo = (left != nullptr) & (right != nullptr);
4031 
4032     if (!af_is_stereo) {
4033       if (!bt_got_stereo) {
4034         std::vector<int16_t>* mono = left ? left : right;
4035         /* mono audio over bluetooth, audio framework expects mono */
4036         to_write = sizeof(int16_t) * mono->size();
4037         written = le_audio_sink_hal_client_->SendData((uint8_t*)mono->data(), to_write);
4038       } else {
4039         /* stereo audio over bluetooth, audio framework expects mono */
4040         for (size_t i = 0; i < left->size(); i++) {
4041           (*left)[i] = ((*left)[i] + (*right)[i]) / 2;
4042         }
4043         to_write = sizeof(int16_t) * left->size();
4044         written = le_audio_sink_hal_client_->SendData((uint8_t*)left->data(), to_write);
4045       }
4046     } else {
4047       /* mono audio over bluetooth, audio framework expects stereo
4048        * Here we handle stream without checking bt_got_stereo flag.
4049        */
4050       const size_t mono_size = left ? left->size() : right->size();
4051       std::vector<uint16_t> mixed(mono_size * 2);
4052 
4053       for (size_t i = 0; i < mono_size; i++) {
4054         mixed[2 * i] = left ? (*left)[i] : (*right)[i];
4055         mixed[2 * i + 1] = right ? (*right)[i] : (*left)[i];
4056       }
4057       to_write = sizeof(int16_t) * mixed.size();
4058       written = le_audio_sink_hal_client_->SendData((uint8_t*)mixed.data(), to_write);
4059     }
4060 
4061     /* TODO: What to do if not all data sinked ? */
4062     if (written != to_write) {
4063       log::error("not all data sinked");
4064     }
4065   }
4066 
ConfirmLocalAudioSourceStreamingRequest()4067   void ConfirmLocalAudioSourceStreamingRequest() {
4068     le_audio_source_hal_client_->ConfirmStreamingRequest();
4069 
4070     LeAudioLogHistory::Get()->AddLogHistory(
4071             kLogBtCallAf, active_group_id_, RawAddress::kEmpty, kLogAfResumeConfirm + "LocalSource",
4072             "s_state: " + ToString(audio_sender_state_) + "-> STARTED");
4073 
4074     audio_sender_state_ = AudioState::STARTED;
4075   }
4076 
ConfirmLocalAudioSinkStreamingRequest()4077   void ConfirmLocalAudioSinkStreamingRequest() {
4078     le_audio_sink_hal_client_->ConfirmStreamingRequest();
4079 
4080     LeAudioLogHistory::Get()->AddLogHistory(
4081             kLogBtCallAf, active_group_id_, RawAddress::kEmpty, kLogAfResumeConfirm + "LocalSink",
4082             "r_state: " + ToString(audio_receiver_state_) + "-> STARTED");
4083 
4084     audio_receiver_state_ = AudioState::STARTED;
4085   }
4086 
StartSendingAudio(int group_id)4087   void StartSendingAudio(int group_id) {
4088     log::info("");
4089 
4090     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
4091     LeAudioDevice* device = group->GetFirstActiveDevice();
4092     log::assert_that(device, "Shouldn't be called without an active device.");
4093 
4094     /* Assume 2 ases max just for now. */
4095     auto* stream_conf = GetStreamSinkConfiguration(group);
4096     if (stream_conf == nullptr) {
4097       log::error("could not get sink configuration");
4098       groupStateMachine_->StopStream(group);
4099       return;
4100     }
4101 
4102     log::debug("Sink stream config (#{}):\n",
4103                static_cast<int>(stream_conf->stream_params.sink.stream_config.stream_map.size()));
4104     for (auto info : stream_conf->stream_params.sink.stream_config.stream_map) {
4105       log::debug("Cis handle: 0x{:02x}, allocation 0x{:04x}\n", info.stream_handle,
4106                  info.audio_channel_allocation);
4107     }
4108     log::debug("Source stream config (#{}):\n",
4109                static_cast<int>(stream_conf->stream_params.source.stream_config.stream_map.size()));
4110     for (auto info : stream_conf->stream_params.source.stream_config.stream_map) {
4111       log::debug("Cis handle: 0x{:02x}, allocation 0x{:04x}\n", info.stream_handle,
4112                  info.audio_channel_allocation);
4113     }
4114 
4115     uint16_t remote_delay_ms =
4116             group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSink);
4117     if (CodecManager::GetInstance()->GetCodecLocation() ==
4118         bluetooth::le_audio::types::CodecLocation::HOST) {
4119       if (sw_enc_left || sw_enc_right) {
4120         log::warn("The encoder instance should have been already released.");
4121       }
4122       sw_enc_left = bluetooth::le_audio::CodecInterface::CreateInstance(stream_conf->codec_id);
4123       auto codec_status =
4124               sw_enc_left->InitEncoder(audio_framework_source_config, current_encoder_config_);
4125       if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
4126         log::error("Left channel codec setup failed with err: {}", codec_status);
4127         groupStateMachine_->StopStream(group);
4128         return;
4129       }
4130 
4131       sw_enc_right = bluetooth::le_audio::CodecInterface::CreateInstance(stream_conf->codec_id);
4132       codec_status =
4133               sw_enc_right->InitEncoder(audio_framework_source_config, current_encoder_config_);
4134       if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
4135         log::error("Right channel codec setup failed with err: {}", codec_status);
4136         groupStateMachine_->StopStream(group);
4137         return;
4138       }
4139     }
4140 
4141     le_audio_source_hal_client_->UpdateRemoteDelay(remote_delay_ms);
4142 
4143     /* We update the target audio allocation before streamStarted so that the CodecManager would
4144      * already know how to configure the encoder once we confirm the streaming request. */
4145     CodecManager::GetInstance()->UpdateActiveAudioConfig(
4146             group->stream_conf.stream_params,
4147             std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
4148                       std::placeholders::_1, std::placeholders::_2),
4149             ::bluetooth::le_audio::types::kLeAudioDirectionSink);
4150 
4151     ConfirmLocalAudioSourceStreamingRequest();
4152 
4153     /* After confirming the streaming request, if no Stream Active API is available, we need to
4154      * send an additional update with the currently active audio channel configuration (in case one
4155      * of the earbuds is not yet connected) so that the offloader would know if any channel mixing
4156      * (and sending joint-stereo to one CIS) is required until the other bud joins the stream.
4157      * NOTE: With the Stream Active API available, both information is passed with the initial call.
4158      */
4159     if (!LeAudioHalVerifier::SupportsStreamActiveApi()) {
4160       CodecManager::GetInstance()->UpdateActiveAudioConfig(
4161               group->stream_conf.stream_params,
4162               std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
4163                         std::placeholders::_1, std::placeholders::_2),
4164               bluetooth::le_audio::types::kLeAudioDirectionSink);
4165     }
4166   }
4167 
GetStreamSourceConfiguration(LeAudioDeviceGroup * group)4168   const struct bluetooth::le_audio::stream_configuration* GetStreamSourceConfiguration(
4169           LeAudioDeviceGroup* group) {
4170     const struct bluetooth::le_audio::stream_configuration* stream_conf = &group->stream_conf;
4171     if (stream_conf->stream_params.source.stream_config.stream_map.size() == 0) {
4172       return nullptr;
4173     }
4174     log::info("configuration: {}", stream_conf->conf->name);
4175     return stream_conf;
4176   }
4177 
StartReceivingAudio(int group_id)4178   void StartReceivingAudio(int group_id) {
4179     log::info("");
4180 
4181     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
4182 
4183     auto* stream_conf = GetStreamSourceConfiguration(group);
4184     if (!stream_conf) {
4185       log::warn(
4186               "Could not get source configuration for group {} probably microphone not configured",
4187               active_group_id_);
4188       groupStateMachine_->StopStream(group);
4189       return;
4190     }
4191 
4192     uint16_t remote_delay_ms =
4193             group->GetRemoteDelay(bluetooth::le_audio::types::kLeAudioDirectionSource);
4194 
4195     CleanCachedMicrophoneData();
4196 
4197     if (CodecManager::GetInstance()->GetCodecLocation() ==
4198         bluetooth::le_audio::types::CodecLocation::HOST) {
4199       if (sw_dec_left.get() || sw_dec_right.get()) {
4200         log::warn("The decoder instance should have been already released.");
4201       }
4202       sw_dec_left = bluetooth::le_audio::CodecInterface::CreateInstance(stream_conf->codec_id);
4203       auto codec_status =
4204               sw_dec_left->InitDecoder(current_decoder_config_, audio_framework_sink_config);
4205       if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
4206         log::error("Left channel codec setup failed with err: {}", codec_status);
4207         groupStateMachine_->StopStream(group);
4208         return;
4209       }
4210 
4211       sw_dec_right = bluetooth::le_audio::CodecInterface::CreateInstance(stream_conf->codec_id);
4212       codec_status =
4213               sw_dec_right->InitDecoder(current_decoder_config_, audio_framework_sink_config);
4214       if (codec_status != bluetooth::le_audio::CodecInterface::Status::STATUS_OK) {
4215         log::error("Right channel codec setup failed with err: {}", codec_status);
4216         groupStateMachine_->StopStream(group);
4217         return;
4218       }
4219     }
4220 
4221     le_audio_sink_hal_client_->UpdateRemoteDelay(remote_delay_ms);
4222 
4223     /* We update the target audio allocation before streamStarted so that the CodecManager would
4224      * already know how to configure the encoder once we confirm the streaming request. */
4225     CodecManager::GetInstance()->UpdateActiveAudioConfig(
4226             group->stream_conf.stream_params,
4227             std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
4228                       std::placeholders::_1, std::placeholders::_2),
4229             ::bluetooth::le_audio::types::kLeAudioDirectionSource);
4230 
4231     ConfirmLocalAudioSinkStreamingRequest();
4232 
4233     /* After confirming the streaming request, if no Stream Active API is available, we need to
4234      * send an additional update with the currently active audio channel configuration (in case one
4235      * of the earbuds is not yet connected) so that the offloader would know if any channel mixing
4236      * (and sending joint-stereo to one CIS) is required until the other bud joins the stream.
4237      * NOTE: With the Stream Active API available, both information is passed with the initial call.
4238      */
4239     if (!LeAudioHalVerifier::SupportsStreamActiveApi()) {
4240       CodecManager::GetInstance()->UpdateActiveAudioConfig(
4241               group->stream_conf.stream_params,
4242               std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
4243                         std::placeholders::_1, std::placeholders::_2),
4244               bluetooth::le_audio::types::kLeAudioDirectionSource);
4245     }
4246   }
4247 
SuspendAudio(void)4248   void SuspendAudio(void) {
4249     CancelStreamingRequest();
4250 
4251     if (sw_enc_left) {
4252       sw_enc_left.reset();
4253     }
4254     if (sw_enc_right) {
4255       sw_enc_right.reset();
4256     }
4257     if (sw_dec_left) {
4258       sw_dec_left.reset();
4259     }
4260     if (sw_dec_right) {
4261       sw_dec_right.reset();
4262     }
4263     CleanCachedMicrophoneData();
4264   }
4265 
StopAudio(void)4266   void StopAudio(void) {
4267     SuspendAudio();
4268     stack::l2cap::get_interface().L2CA_SetEcosystemBaseInterval(0 /* clear recommendation */);
4269   }
4270 
printCurrentStreamConfiguration(std::stringstream & stream)4271   void printCurrentStreamConfiguration(std::stringstream& stream) {
4272     auto config_printer = [&stream](LeAudioCodecConfiguration& conf) {
4273       stream << "\tsample rate: " << +conf.sample_rate << ", chan: " << +conf.num_channels
4274              << ", bits: " << +conf.bits_per_sample
4275              << ", data_interval_us: " << +conf.data_interval_us << "\n";
4276     };
4277 
4278     stream << "\n";
4279     stream << "  Speaker codec config (audio framework):\n";
4280     stream << "\taudio sender state: " << audio_sender_state_ << "\n";
4281     config_printer(audio_framework_source_config);
4282 
4283     stream << "  Microphone codec config (audio framework):\n";
4284     stream << "\taudio receiver state: " << audio_receiver_state_ << "\n";
4285     config_printer(audio_framework_sink_config);
4286 
4287     stream << "  Speaker codec config (SW encoder):\n";
4288     config_printer(current_encoder_config_);
4289 
4290     stream << "  Microphone codec config (SW decoder):\n";
4291     config_printer(current_decoder_config_);
4292   }
4293 
Dump(int fd)4294   void Dump(int fd) {
4295     std::stringstream stream;
4296 
4297     stream << "  APP ID: " << +gatt_if_ << "\n";
4298     stream << "  TBS state: " << (in_call_ ? " In call" : "No calls") << "\n";
4299     stream << "  Active group: " << +active_group_id_ << "\n";
4300     stream << "  Reconnection mode: "
4301            << (reconnection_mode_ == BTM_BLE_BKG_CONNECT_ALLOW_LIST ? "Allow List"
4302                                                                     : "Targeted Announcements")
4303            << "\n";
4304     stream << "  Configuration: " << bluetooth::common::ToString(configuration_context_type_)
4305            << " (" << loghex(static_cast<uint16_t>(configuration_context_type_)) << ")\n";
4306     stream << "  Local source metadata context type mask: "
4307            << local_metadata_context_types_.source.to_string() << "\n";
4308     stream << "  Local sink metadata context type mask: "
4309            << local_metadata_context_types_.sink.to_string() << "\n";
4310     stream << "  Sink listening mode: " << (sink_monitor_mode_ ? "true" : "false") << "\n";
4311     if (sink_monitor_notified_status_) {
4312       stream << "  Local sink notified state: "
4313              << static_cast<int>(sink_monitor_notified_status_.value()) << "\n";
4314     }
4315     stream << "  Source monitor mode: " << (source_monitor_mode_ ? "true" : "false") << "\n";
4316     if (source_monitor_notified_status_) {
4317       dprintf(fd, "  Local source notified state: %d\n",
4318               static_cast<int>(source_monitor_notified_status_.value()));
4319     }
4320 
4321     auto codec_loc = CodecManager::GetInstance()->GetCodecLocation();
4322     if (codec_loc == bluetooth::le_audio::types::CodecLocation::HOST) {
4323       stream << "  Codec location: HOST\n";
4324     } else if (codec_loc == bluetooth::le_audio::types::CodecLocation::CONTROLLER) {
4325       stream << "  Codec location: CONTROLLER\n";
4326     } else if (codec_loc == bluetooth::le_audio::types::CodecLocation::ADSP) {
4327       stream << "  Codec location: ADSP"
4328              << (CodecManager::GetInstance()->IsUsingCodecExtensibility() ? " (codec extensibility)"
4329                                                                           : "")
4330              << "\n";
4331     } else {
4332       dprintf(fd, "  Codec location: UNKNOWN\n");
4333     }
4334 
4335     stream << "  Stream creation speed: ";
4336     for (auto t : stream_speed_history_) {
4337       t.Dump(stream);
4338       stream << ",";
4339     }
4340     stream << "\n";
4341     printCurrentStreamConfiguration(stream);
4342     stream << "\n";
4343     aseGroups_.Dump(stream, active_group_id_);
4344     stream << "\n ";
4345     stream << "  Not grouped devices:\n";
4346     leAudioDevices_.Dump(stream, bluetooth::groups::kGroupUnknown);
4347 
4348     dprintf(fd, "%s", stream.str().c_str());
4349 
4350     if (leAudioHealthStatus_) {
4351       leAudioHealthStatus_->DebugDump(fd);
4352     }
4353   }
4354 
Cleanup()4355   void Cleanup() {
4356     StopVbcCloseTimeout();
4357     StopSuspendTimeout();
4358 
4359     if (active_group_id_ != bluetooth::groups::kGroupUnknown) {
4360       /* Bluetooth turned off while streaming */
4361       StopAudio();
4362       SetUnicastMonitorMode(bluetooth::le_audio::types::kLeAudioDirectionSink, false);
4363       ClientAudioInterfaceRelease();
4364     } else {
4365       /* There may be not stopped Sink HAL client due to set Listening mode */
4366       if (sink_monitor_mode_) {
4367         SetUnicastMonitorMode(bluetooth::le_audio::types::kLeAudioDirectionSink, false);
4368       }
4369     }
4370     groupStateMachine_->Cleanup();
4371     aseGroups_.Cleanup();
4372     lastNotifiedGroupStreamStatusMap_.clear();
4373     leAudioDevices_.Cleanup(gatt_if_);
4374     if (gatt_if_) {
4375       BTA_GATTC_AppDeregister(gatt_if_);
4376     }
4377 
4378     if (leAudioHealthStatus_) {
4379       leAudioHealthStatus_->Cleanup();
4380     }
4381   }
4382 
UpdateConfigAndCheckIfReconfigurationIsNeeded(LeAudioDeviceGroup * group,LeAudioContextType context_type)4383   AudioReconfigurationResult UpdateConfigAndCheckIfReconfigurationIsNeeded(
4384           LeAudioDeviceGroup* group, LeAudioContextType context_type) {
4385     log::debug("Checking whether to reconfigure from {} to {}",
4386                ToString(configuration_context_type_), ToString(context_type));
4387 
4388     auto audio_set_conf = group->GetConfiguration(context_type);
4389     if (!audio_set_conf) {
4390       return AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE;
4391     }
4392 
4393     if (group->IsGroupConfiguredTo(*audio_set_conf) && !DsaReconfigureNeeded(group, context_type)) {
4394       // Assign the new configuration context as it represennts the current
4395       // use case even when it eventually ends up being the exact same
4396       // codec and qos configuration.
4397       if (configuration_context_type_ != context_type) {
4398         configuration_context_type_ = context_type;
4399         group->SetConfigurationContextType(context_type);
4400       }
4401       return AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED;
4402     }
4403 
4404     log::info("Session reconfiguration needed group: {} for context type: {}", group->group_id_,
4405               ToHexString(context_type));
4406 
4407     configuration_context_type_ = context_type;
4408 
4409     // Note: The local sink config is based on remote device's source config
4410     //       and vice versa.
4411     current_decoder_config_ = group->GetAudioSessionCodecConfigForDirection(
4412             context_type, bluetooth::le_audio::types::kLeAudioDirectionSource);
4413     current_encoder_config_ = group->GetAudioSessionCodecConfigForDirection(
4414             context_type, bluetooth::le_audio::types::kLeAudioDirectionSink);
4415     return AudioReconfigurationResult::RECONFIGURATION_NEEDED;
4416   }
4417 
4418   /* Returns true if stream is started */
OnAudioResume(LeAudioDeviceGroup * group,int local_direction)4419   bool OnAudioResume(LeAudioDeviceGroup* group, int local_direction) {
4420     auto remote_direction = (local_direction == bluetooth::le_audio::types::kLeAudioDirectionSink
4421                                      ? bluetooth::le_audio::types::kLeAudioDirectionSource
4422                                      : bluetooth::le_audio::types::kLeAudioDirectionSink);
4423 
4424     auto remote_contexts = DirectionalRealignMetadataAudioContexts(group, remote_direction);
4425     ApplyRemoteMetadataAudioContextPolicy(group, remote_contexts, remote_direction);
4426 
4427     if (!remote_contexts.sink.any() && !remote_contexts.source.any()) {
4428       log::warn("Requested context type not available on the remote side");
4429 
4430       if (source_monitor_mode_) {
4431         notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_REQUESTED_NO_CONTEXT_VALIDATE);
4432 
4433         return false;
4434       }
4435 
4436       if (leAudioHealthStatus_) {
4437         leAudioHealthStatus_->AddStatisticForGroup(
4438                 group, LeAudioHealthGroupStatType::STREAM_CONTEXT_NOT_AVAILABLE);
4439       }
4440       return false;
4441     }
4442 
4443     return GroupStream(group, configuration_context_type_, remote_contexts);
4444   }
4445 
OnAudioSuspend()4446   void OnAudioSuspend() {
4447     if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
4448       log::warn(", there is no longer active group");
4449       return;
4450     }
4451 
4452     if (stack_config_get_interface()->get_pts_le_audio_disable_ases_before_stopping()) {
4453       log::info("Stream disable_timer_ started");
4454       if (alarm_is_scheduled(disable_timer_)) {
4455         alarm_cancel(disable_timer_);
4456       }
4457 
4458       alarm_set_on_mloop(
4459               disable_timer_, kAudioDisableTimeoutMs,
4460               [](void* data) {
4461                 if (instance) {
4462                   auto const group_id = PTR_TO_INT(data);
4463                   log::debug("No resume request received. Suspend the group ID: {}", group_id);
4464                   instance->GroupSuspend(group_id);
4465                 }
4466               },
4467               INT_TO_PTR(active_group_id_));
4468     }
4469 
4470     StartSuspendTimeout();
4471   }
4472 
OnLocalAudioSourceSuspend()4473   void OnLocalAudioSourceSuspend() {
4474     log::info("active group_id: {}, IN: audio_receiver_state_: {}, audio_sender_state_: {}",
4475               active_group_id_, ToString(audio_receiver_state_), ToString(audio_sender_state_));
4476     LeAudioLogHistory::Get()->AddLogHistory(kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4477                                             kLogAfSuspend + "LocalSource",
4478                                             "r_state: " + ToString(audio_receiver_state_) +
4479                                                     ", s_state: " + ToString(audio_sender_state_));
4480 
4481     /* Note: This callback is from audio hal driver.
4482      * Bluetooth peer is a Sink for Audio Framework.
4483      * e.g. Peer is a speaker
4484      */
4485     switch (audio_sender_state_) {
4486       case AudioState::READY_TO_START:
4487       case AudioState::STARTED:
4488         audio_sender_state_ = AudioState::READY_TO_RELEASE;
4489         break;
4490       case AudioState::RELEASING:
4491         return;
4492       case AudioState::IDLE:
4493         if (audio_receiver_state_ == AudioState::READY_TO_RELEASE) {
4494           OnAudioSuspend();
4495         }
4496         return;
4497       case AudioState::READY_TO_RELEASE:
4498         break;
4499     }
4500 
4501     /* Last suspends group - triggers group stop */
4502     if ((audio_receiver_state_ == AudioState::IDLE) ||
4503         (audio_receiver_state_ == AudioState::READY_TO_RELEASE)) {
4504       OnAudioSuspend();
4505       bluetooth::le_audio::MetricsCollector::Get()->OnStreamEnded(active_group_id_);
4506     }
4507 
4508     log::info("OUT: audio_receiver_state_: {},  audio_sender_state_: {}",
4509               ToString(audio_receiver_state_), ToString(audio_sender_state_));
4510 
4511     LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
4512                                             kLogAfSuspendConfirm + "LocalSource",
4513                                             "r_state: " + ToString(audio_receiver_state_) +
4514                                                     "s_state: " + ToString(audio_sender_state_));
4515   }
4516 
OnLocalAudioSourceResume()4517   void OnLocalAudioSourceResume() {
4518     log::info("active group_id: {}, IN: audio_receiver_state_: {}, audio_sender_state_: {}",
4519               active_group_id_, ToString(audio_receiver_state_), ToString(audio_sender_state_));
4520     LeAudioLogHistory::Get()->AddLogHistory(kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4521                                             kLogAfResume + "LocalSource",
4522                                             "r_state: " + ToString(audio_receiver_state_) +
4523                                                     ", s_state: " + ToString(audio_sender_state_));
4524 
4525     /* Note: This callback is from audio hal driver.
4526      * Bluetooth peer is a Sink for Audio Framework.
4527      * e.g. Peer is a speaker
4528      */
4529     auto group = aseGroups_.FindById(active_group_id_);
4530     if (!group) {
4531       log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4532       return;
4533     }
4534 
4535     /* Check if the device resume is allowed */
4536     if (!group->HasCodecConfigurationForDirection(
4537                 configuration_context_type_, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4538       log::error("invalid resume request for context type: {}",
4539                  ToHexString(configuration_context_type_));
4540       CancelLocalAudioSourceStreamingRequest();
4541       return;
4542     }
4543 
4544     /* Group should not be resumed if:
4545      * - configured context type is not allowed
4546      * - updated metadata contains only not allowed context types
4547      * - is not in call mode (quick metadata updates between audio modes)
4548      */
4549     if (!IsInVoipOrRegularCall() &&
4550         (!group->GetAllowedContextMask(bluetooth::le_audio::types::kLeAudioDirectionSink)
4551                   .test_all(local_metadata_context_types_.source) ||
4552          !group->GetAllowedContextMask(bluetooth::le_audio::types::kLeAudioDirectionSink)
4553                   .test(configuration_context_type_))) {
4554       log::warn(
4555               "Block source resume request context types: {}, allowed context mask: {}, "
4556               "configured: {}",
4557               ToString(local_metadata_context_types_.source),
4558               ToString(group->GetAllowedContextMask(
4559                       bluetooth::le_audio::types::kLeAudioDirectionSink)),
4560               ToString(configuration_context_type_));
4561       CancelLocalAudioSourceStreamingRequest();
4562       return;
4563     }
4564 
4565     log::debug(
4566             "active_group_id: {}\n audio_receiver_state: {}\n audio_sender_state: "
4567             "{}\n configuration_context_type_: {}\n",
4568             active_group_id_, audio_receiver_state_, audio_sender_state_,
4569             ToHexString(configuration_context_type_));
4570 
4571     switch (audio_sender_state_) {
4572       case AudioState::STARTED:
4573         /* Looks like previous Confirm did not get to the Audio Framework*/
4574         ConfirmLocalAudioSourceStreamingRequest();
4575         break;
4576       case AudioState::IDLE:
4577         switch (audio_receiver_state_) {
4578           case AudioState::IDLE:
4579             /* Stream is not started. Try to do it.*/
4580             if (OnAudioResume(group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4581               audio_sender_state_ = AudioState::READY_TO_START;
4582               if (IsReconfigurationTimeoutRunning(active_group_id_)) {
4583                 StopReconfigurationTimeout(active_group_id_,
4584                                            bluetooth::le_audio::types::kLeAudioDirectionSource);
4585               }
4586             } else {
4587               CancelLocalAudioSourceStreamingRequest();
4588             }
4589             break;
4590           case AudioState::READY_TO_START:
4591             audio_sender_state_ = AudioState::READY_TO_START;
4592             if (!IsDirectionAvailableForCurrentConfiguration(
4593                         group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4594               log::warn(
4595                       "sink is not configured. \n audio_receiver_state: {} "
4596                       "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4597                       "Reconfiguring to {}",
4598                       ToString(audio_receiver_state_), ToString(audio_sender_state_),
4599                       group->IsPendingConfiguration(), ToString(configuration_context_type_));
4600               group->PrintDebugState();
4601               SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4602             }
4603             break;
4604           case AudioState::STARTED:
4605             audio_sender_state_ = AudioState::READY_TO_START;
4606             /* If signalling part is completed trigger start sending audio
4607              * here, otherwise it'll be called on group streaming state callback
4608              */
4609             if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4610               if (IsDirectionAvailableForCurrentConfiguration(
4611                           group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4612                 StartSendingAudio(active_group_id_);
4613               } else {
4614                 log::warn(
4615                         "sink is not configured. \n audio_receiver_state: {} "
4616                         "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4617                         "Reconfiguring to {}",
4618                         ToString(audio_receiver_state_), ToString(audio_sender_state_),
4619                         group->IsPendingConfiguration(), ToString(configuration_context_type_));
4620                 group->PrintDebugState();
4621                 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4622               }
4623             } else {
4624               log::error(
4625                       "called in wrong state. \n audio_receiver_state: {} "
4626                       "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4627                       "Reconfiguring to {}",
4628                       ToString(audio_receiver_state_), ToString(audio_sender_state_),
4629                       group->IsPendingConfiguration(), ToString(configuration_context_type_));
4630               group->PrintDebugState();
4631               CancelStreamingRequest();
4632             }
4633             break;
4634           case AudioState::RELEASING:
4635             /* Group is reconfiguring, reassing state and wait for
4636              * the stream to be configured
4637              */
4638             audio_sender_state_ = audio_receiver_state_;
4639             break;
4640           case AudioState::READY_TO_RELEASE:
4641             /* If the other direction is streaming we can start sending audio */
4642             if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4643               if (IsDirectionAvailableForCurrentConfiguration(
4644                           group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4645                 StopSuspendTimeout();
4646                 StartSendingAudio(active_group_id_);
4647               } else {
4648                 log::warn(
4649                         "sink is not configured. \n audio_receiver_state: {} "
4650                         "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4651                         "Reconfiguring to {}",
4652                         ToString(audio_receiver_state_), ToString(audio_sender_state_),
4653                         group->IsPendingConfiguration(), ToString(configuration_context_type_));
4654                 group->PrintDebugState();
4655                 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4656               }
4657             } else {
4658               log::error(
4659                       "called in wrong state. \n audio_receiver_state: {} "
4660                       "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4661                       "Reconfiguring to {}",
4662                       ToString(audio_receiver_state_), ToString(audio_sender_state_),
4663                       group->IsPendingConfiguration(), ToString(configuration_context_type_));
4664               group->PrintDebugState();
4665               CancelStreamingRequest();
4666             }
4667             break;
4668         }
4669         break;
4670       case AudioState::READY_TO_START:
4671         log::error(
4672                 "called in wrong state, ignoring double start request. \n "
4673                 "audio_receiver_state: {} \naudio_sender_state: {} \n "
4674                 "isPendingConfiguration: {} \n Reconfiguring to {}",
4675                 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4676                 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4677         group->PrintDebugState();
4678         break;
4679       case AudioState::READY_TO_RELEASE:
4680         switch (audio_receiver_state_) {
4681           case AudioState::STARTED:
4682           case AudioState::READY_TO_START:
4683           case AudioState::IDLE:
4684           case AudioState::READY_TO_RELEASE:
4685             /* Stream is up just restore it */
4686             StopSuspendTimeout();
4687             ConfirmLocalAudioSourceStreamingRequest();
4688             bluetooth::le_audio::MetricsCollector::Get()->OnStreamStarted(
4689                     active_group_id_, configuration_context_type_);
4690             break;
4691           case AudioState::RELEASING:
4692             /* Keep waiting. After release is done, Audio Hal will be notified
4693              */
4694             break;
4695         }
4696         break;
4697       case AudioState::RELEASING:
4698         /* Keep waiting. After release is done, Audio Hal will be notified */
4699         break;
4700     }
4701   }
4702 
OnLocalAudioSinkSuspend()4703   void OnLocalAudioSinkSuspend() {
4704     log::info("active group_id: {}, IN: audio_receiver_state_: {}, audio_sender_state_: {}",
4705               active_group_id_, ToString(audio_receiver_state_), ToString(audio_sender_state_));
4706     LeAudioLogHistory::Get()->AddLogHistory(kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4707                                             kLogAfSuspend + "LocalSink",
4708                                             "r_state: " + ToString(audio_receiver_state_) +
4709                                                     ", s_state: " + ToString(audio_sender_state_));
4710 
4711     /* If the local sink direction is used, we want to monitor
4712      * if back channel is actually needed.
4713      */
4714     StartVbcCloseTimeout();
4715 
4716     /* Note: This callback is from audio hal driver.
4717      * Bluetooth peer is a Source for Audio Framework.
4718      * e.g. Peer is microphone.
4719      */
4720     switch (audio_receiver_state_) {
4721       case AudioState::READY_TO_START:
4722       case AudioState::STARTED:
4723         audio_receiver_state_ = AudioState::READY_TO_RELEASE;
4724         break;
4725       case AudioState::RELEASING:
4726         return;
4727       case AudioState::IDLE:
4728         if (audio_sender_state_ == AudioState::READY_TO_RELEASE) {
4729           OnAudioSuspend();
4730         }
4731         return;
4732       case AudioState::READY_TO_RELEASE:
4733         break;
4734     }
4735 
4736     /* Last suspends group - triggers group stop */
4737     if ((audio_sender_state_ == AudioState::IDLE) ||
4738         (audio_sender_state_ == AudioState::READY_TO_RELEASE)) {
4739       OnAudioSuspend();
4740     }
4741 
4742     log::info("OUT: audio_receiver_state_: {},  audio_sender_state_: {}",
4743               ToString(audio_receiver_state_), ToString(audio_sender_state_));
4744 
4745     LeAudioLogHistory::Get()->AddLogHistory(kLogBtCallAf, active_group_id_, RawAddress::kEmpty,
4746                                             kLogAfSuspendConfirm + "LocalSink",
4747                                             "r_state: " + ToString(audio_receiver_state_) +
4748                                                     "s_state: " + ToString(audio_sender_state_));
4749   }
4750 
IsDirectionAvailableForCurrentConfiguration(const LeAudioDeviceGroup * group,uint8_t remote_direction) const4751   inline bool IsDirectionAvailableForCurrentConfiguration(const LeAudioDeviceGroup* group,
4752                                                           uint8_t remote_direction) const {
4753     auto current_config =
4754             group->IsUsingPreferredAudioSetConfiguration(configuration_context_type_)
4755                     ? group->GetCachedPreferredConfiguration(configuration_context_type_)
4756                     : group->GetCachedConfiguration(configuration_context_type_);
4757     log::debug("configuration_context_type_ = {}, group_id: {}, remote_direction: {}",
4758                ToString(configuration_context_type_), group->group_id_,
4759                remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink ? "Sink"
4760                                                                                      : "Source");
4761     if (current_config) {
4762       log::debug("name = {}, size {}", current_config->name,
4763                  current_config->confs.get(remote_direction).size());
4764       return current_config->confs.get(remote_direction).size() != 0;
4765     }
4766     log::debug("no cached configuration");
4767     return false;
4768   }
4769 
notifyAudioLocalSink(UnicastMonitorModeStatus status)4770   void notifyAudioLocalSink(UnicastMonitorModeStatus status) {
4771     if (sink_monitor_notified_status_ != status) {
4772       log::info("Stream monitoring status changed to: {}", static_cast<int>(status));
4773       sink_monitor_notified_status_ = status;
4774       callbacks_->OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSink,
4775                                              status);
4776     }
4777   }
4778 
notifyAudioLocalSource(UnicastMonitorModeStatus status)4779   void notifyAudioLocalSource(UnicastMonitorModeStatus status) {
4780     if (source_monitor_notified_status_ != status) {
4781       log::info("Source stream monitoring status changed to: {}", static_cast<int>(status));
4782       source_monitor_notified_status_ = status;
4783       callbacks_->OnUnicastMonitorModeStatus(bluetooth::le_audio::types::kLeAudioDirectionSource,
4784                                              status);
4785     }
4786   }
4787 
OnLocalAudioSinkResume()4788   void OnLocalAudioSinkResume() {
4789     log::info("active group_id: {} IN: audio_receiver_state_: {}, audio_sender_state_: {}",
4790               active_group_id_, ToString(audio_receiver_state_), ToString(audio_sender_state_));
4791     LeAudioLogHistory::Get()->AddLogHistory(kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
4792                                             kLogAfResume + "LocalSink",
4793                                             "r_state: " + ToString(audio_receiver_state_) +
4794                                                     ", s_state: " + ToString(audio_sender_state_));
4795 
4796     if (!com::android::bluetooth::flags::leaudio_use_audio_recording_listener()) {
4797       if (sink_monitor_mode_ && active_group_id_ == bluetooth::groups::kGroupUnknown) {
4798         if (sink_monitor_notified_status_ != UnicastMonitorModeStatus::STREAMING_REQUESTED) {
4799           notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_REQUESTED);
4800         }
4801         CancelLocalAudioSinkStreamingRequest();
4802         return;
4803       }
4804     }
4805 
4806     /* Stop the VBC close watchdog if needed */
4807     StopVbcCloseTimeout();
4808 
4809     /* Note: This callback is from audio hal driver.
4810      * Bluetooth peer is a Source for Audio Framework.
4811      * e.g. Peer is microphone.
4812      */
4813     auto group = aseGroups_.FindById(active_group_id_);
4814     if (!group) {
4815       log::error("Invalid group: {}", static_cast<int>(active_group_id_));
4816       return;
4817     }
4818 
4819     if (audio_receiver_state_ == AudioState::IDLE) {
4820       /* We need new configuration_context_type_ to be selected before we go any
4821        * further.
4822        */
4823       ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSource);
4824       log::info("new_configuration_context = {}", ToString(configuration_context_type_));
4825     }
4826 
4827     /* Check if the device resume is allowed */
4828     if (!group->HasCodecConfigurationForDirection(
4829                 configuration_context_type_, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4830       log::error("invalid resume request for context type: {}",
4831                  ToHexString(configuration_context_type_));
4832       CancelLocalAudioSinkStreamingRequest();
4833       return;
4834     }
4835 
4836     /* Group should not be resumed if:
4837      * - configured context type is not allowed
4838      * - updated metadata contains only not allowed context types
4839      * - is not in call mode (quick metadata updates between audio modes)
4840      */
4841     if (!IsInVoipOrRegularCall() &&
4842         (!group->GetAllowedContextMask(bluetooth::le_audio::types::kLeAudioDirectionSource)
4843                   .test_all(local_metadata_context_types_.sink) ||
4844          !group->GetAllowedContextMask(bluetooth::le_audio::types::kLeAudioDirectionSource)
4845                   .test(configuration_context_type_))) {
4846       log::warn(
4847               "Block sink resume request context types: {} vs allowed context mask: {}, "
4848               "configured: {}",
4849               ToString(local_metadata_context_types_.sink),
4850               ToString(group->GetAllowedContextMask(
4851                       bluetooth::le_audio::types::kLeAudioDirectionSource)),
4852               ToString(configuration_context_type_));
4853       CancelLocalAudioSourceStreamingRequest();
4854       return;
4855     }
4856 
4857     log::debug(
4858             "active_group_id: {}\n audio_receiver_state: {}\n audio_sender_state: "
4859             "{}\n configuration_context_type_: {}\n group {}\n",
4860             active_group_id_, audio_receiver_state_, audio_sender_state_,
4861             ToHexString(configuration_context_type_), group ? " exist " : " does not exist ");
4862 
4863     switch (audio_receiver_state_) {
4864       case AudioState::STARTED:
4865         ConfirmLocalAudioSinkStreamingRequest();
4866         break;
4867       case AudioState::IDLE:
4868         switch (audio_sender_state_) {
4869           case AudioState::IDLE:
4870             if (OnAudioResume(group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
4871               audio_receiver_state_ = AudioState::READY_TO_START;
4872               if (IsReconfigurationTimeoutRunning(active_group_id_)) {
4873                 StopReconfigurationTimeout(active_group_id_,
4874                                            bluetooth::le_audio::types::kLeAudioDirectionSink);
4875               }
4876             } else {
4877               CancelLocalAudioSinkStreamingRequest();
4878             }
4879             break;
4880           case AudioState::READY_TO_START:
4881             audio_receiver_state_ = AudioState::READY_TO_START;
4882             if (!IsDirectionAvailableForCurrentConfiguration(
4883                         group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4884               log::warn(
4885                       "source is not configured. \n audio_receiver_state: {} "
4886                       "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4887                       "Reconfiguring to {}",
4888                       ToString(audio_receiver_state_), ToString(audio_sender_state_),
4889                       group->IsPendingConfiguration(), ToString(configuration_context_type_));
4890               group->PrintDebugState();
4891               SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4892             }
4893             break;
4894           case AudioState::STARTED:
4895             audio_receiver_state_ = AudioState::READY_TO_START;
4896             /* If signalling part is completed trigger start receiving audio
4897              * here, otherwise it'll be called on group streaming state callback
4898              */
4899             if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4900               if (IsDirectionAvailableForCurrentConfiguration(
4901                           group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4902                 StartReceivingAudio(active_group_id_);
4903               } else {
4904                 log::warn(
4905                         "source is not configured. \n audio_receiver_state: {} "
4906                         "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4907                         "Reconfiguring to {}",
4908                         ToString(audio_receiver_state_), ToString(audio_sender_state_),
4909                         group->IsPendingConfiguration(), ToString(configuration_context_type_));
4910                 group->PrintDebugState();
4911                 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4912               }
4913             } else {
4914               log::error(
4915                       "called in wrong state. \n audio_receiver_state: {} "
4916                       "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4917                       "Reconfiguring to {}",
4918                       ToString(audio_receiver_state_), ToString(audio_sender_state_),
4919                       group->IsPendingConfiguration(), ToString(configuration_context_type_));
4920               group->PrintDebugState();
4921               CancelStreamingRequest();
4922             }
4923             break;
4924           case AudioState::RELEASING:
4925             /* Group is reconfiguring, reassing state and wait for
4926              * the stream to be configured
4927              */
4928             audio_receiver_state_ = audio_sender_state_;
4929             break;
4930           case AudioState::READY_TO_RELEASE:
4931             /* If the other direction is streaming we can start receiving audio
4932              */
4933             if (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
4934               if (IsDirectionAvailableForCurrentConfiguration(
4935                           group, bluetooth::le_audio::types::kLeAudioDirectionSource)) {
4936                 StopSuspendTimeout();
4937                 StartReceivingAudio(active_group_id_);
4938               } else {
4939                 log::warn(
4940                         "source is not configured. \n audio_receiver_state: {} "
4941                         "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4942                         "Reconfiguring to {}",
4943                         ToString(audio_receiver_state_), ToString(audio_sender_state_),
4944                         group->IsPendingConfiguration(), ToString(configuration_context_type_));
4945                 group->PrintDebugState();
4946                 SetConfigurationAndStopStreamWhenNeeded(group, configuration_context_type_);
4947               }
4948             } else {
4949               log::error(
4950                       "called in wrong state. \n audio_receiver_state: {} "
4951                       "\naudio_sender_state: {} \n isPendingConfiguration: {} \n "
4952                       "Reconfiguring to {}",
4953                       ToString(audio_receiver_state_), ToString(audio_sender_state_),
4954                       group->IsPendingConfiguration(), ToString(configuration_context_type_));
4955               group->PrintDebugState();
4956               CancelStreamingRequest();
4957             }
4958             break;
4959         }
4960         break;
4961       case AudioState::READY_TO_START:
4962         log::error(
4963                 "Double resume request, just ignore it.. \n audio_receiver_state: "
4964                 "{} \naudio_sender_state: {} \n isPendingConfiguration: {} \n Reconfiguring to {}",
4965                 ToString(audio_receiver_state_), ToString(audio_sender_state_),
4966                 group->IsPendingConfiguration(), ToString(configuration_context_type_));
4967         group->PrintDebugState();
4968         break;
4969       case AudioState::READY_TO_RELEASE:
4970         switch (audio_sender_state_) {
4971           case AudioState::STARTED:
4972           case AudioState::IDLE:
4973           case AudioState::READY_TO_START:
4974           case AudioState::READY_TO_RELEASE:
4975             /* Stream is up just restore it */
4976             StopSuspendTimeout();
4977             ConfirmLocalAudioSinkStreamingRequest();
4978             break;
4979           case AudioState::RELEASING:
4980             /* Wait until releasing is completed */
4981             break;
4982         }
4983 
4984         break;
4985       case AudioState::RELEASING:
4986         /* Wait until releasing is completed */
4987         break;
4988     }
4989   }
4990 
4991   /* Chooses a single context type to use as a key for selecting a single
4992    * audio set configuration. Contexts used for the metadata can be different
4993    * than this, but it's reasonable to select a configuration context from
4994    * the metadata context types.
4995    */
ChooseConfigurationContextType(AudioContexts available_remote_contexts)4996   LeAudioContextType ChooseConfigurationContextType(AudioContexts available_remote_contexts) {
4997     log::debug("Got contexts={} in config_context={}",
4998                bluetooth::common::ToString(available_remote_contexts),
4999                bluetooth::common::ToString(configuration_context_type_));
5000 
5001     if (IsInCall()) {
5002       log::debug("In Call preference used.");
5003       return LeAudioContextType::CONVERSATIONAL;
5004     }
5005 
5006     /* Mini policy - always prioritize sink+source configurations so that we are
5007      * sure that for a mixed content we enable all the needed directions.
5008      */
5009     if (available_remote_contexts.any()) {
5010       LeAudioContextType context_priority_list[] = {
5011               /* Highest priority first */
5012               LeAudioContextType::CONVERSATIONAL,
5013               LeAudioContextType::RINGTONE,
5014               LeAudioContextType::LIVE,
5015               LeAudioContextType::VOICEASSISTANTS,
5016               LeAudioContextType::GAME,
5017               LeAudioContextType::MEDIA,
5018               LeAudioContextType::EMERGENCYALARM,
5019               LeAudioContextType::ALERTS,
5020               LeAudioContextType::INSTRUCTIONAL,
5021               LeAudioContextType::NOTIFICATIONS,
5022               LeAudioContextType::SOUNDEFFECTS,
5023       };
5024       for (auto ct : context_priority_list) {
5025         if (available_remote_contexts.test(ct)) {
5026           log::debug("Selecting configuration context type: {}", ToString(ct));
5027           return ct;
5028         }
5029       }
5030     }
5031 
5032     /* Use BAP mandated UNSPECIFIED only if we don't have any other valid
5033      * configuration
5034      */
5035     auto fallback_config = LeAudioContextType::UNSPECIFIED;
5036     if (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) {
5037       fallback_config = configuration_context_type_;
5038     }
5039 
5040     log::debug("Selecting configuration context type: {}", ToString(fallback_config));
5041     return fallback_config;
5042   }
5043 
SetConfigurationAndStopStreamWhenNeeded(LeAudioDeviceGroup * group,LeAudioContextType new_context_type)5044   bool SetConfigurationAndStopStreamWhenNeeded(LeAudioDeviceGroup* group,
5045                                                LeAudioContextType new_context_type) {
5046     auto previous_context_type = configuration_context_type_;
5047 
5048     auto reconfig_result = UpdateConfigAndCheckIfReconfigurationIsNeeded(group, new_context_type);
5049     /* Even though the reconfiguration may not be needed, this has
5050      * to be set here as it might be the initial configuration.
5051      */
5052 
5053     configuration_context_type_ = new_context_type;
5054 
5055     log::info("group_id {}, previous_context {} context type {} ({}), {}", group->group_id_,
5056               ToString(previous_context_type), ToString(new_context_type),
5057               ToHexString(new_context_type), ToString(reconfig_result));
5058     if (reconfig_result == AudioReconfigurationResult::RECONFIGURATION_NOT_NEEDED) {
5059       return false;
5060     }
5061 
5062     if (reconfig_result == AudioReconfigurationResult::RECONFIGURATION_NOT_POSSIBLE) {
5063       return false;
5064     }
5065 
5066     if (group->GetState() != AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
5067       log::debug("Group is not streaming");
5068       return false;
5069     }
5070 
5071     StopSuspendTimeout();
5072     /* If group suspend is scheduled, cancel as we are stopping it anyway */
5073 
5074     /* Need to reconfigure stream. At this point pre_configuration_context_type shall be set */
5075 
5076     initReconfiguration(group, previous_context_type);
5077     SendAudioGroupCurrentCodecConfigChanged(group);
5078     return true;
5079   }
5080 
stopStreamIfCurrentContextTypeIsNotAllowed(uint8_t direction,LeAudioDeviceGroup * group,AudioContexts local_contexts)5081   bool stopStreamIfCurrentContextTypeIsNotAllowed(uint8_t direction, LeAudioDeviceGroup* group,
5082                                                   AudioContexts local_contexts) {
5083     AudioContexts allowed_contexts = group->GetAllowedContextMask(direction);
5084 
5085     /* Stream should be suspended if:
5086      * - updated metadata is only not allowed
5087      * - there is no metadata (cleared) but configuration is for not allowed context
5088      */
5089     if (group->IsStreaming() && !allowed_contexts.test_any(local_contexts) &&
5090         !(allowed_contexts.test(configuration_context_type_) && local_contexts.none())) {
5091       /* SuspendForReconfiguration and ReconfigurationComplete is a workaround method to let Audio
5092        * Framework know that session is suspended. Strem resume would be handled from
5093        * suspended session context with stopped group.
5094        */
5095       SuspendedForReconfiguration();
5096       ReconfigurationComplete(direction);
5097       GroupStop(active_group_id_);
5098 
5099       return true;
5100     }
5101 
5102     return false;
5103   }
5104 
OnLocalAudioSourceMetadataUpdate(const std::vector<struct playback_track_metadata_v7> & source_metadata,DsaMode dsa_mode)5105   void OnLocalAudioSourceMetadataUpdate(
5106           const std::vector<struct playback_track_metadata_v7>& source_metadata, DsaMode dsa_mode) {
5107     if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
5108       log::warn(", cannot start streaming if no active group set");
5109       return;
5110     }
5111 
5112     auto group = aseGroups_.FindById(active_group_id_);
5113     if (!group) {
5114       log::error("Invalid group: {}", static_cast<int>(active_group_id_));
5115       return;
5116     }
5117 
5118     log::info(
5119             "group_id {} state={}, target_state={}, audio_receiver_state_: {}, "
5120             "audio_sender_state_: {}, dsa_mode: {}",
5121             group->group_id_, ToString(group->GetState()), ToString(group->GetTargetState()),
5122             ToString(audio_receiver_state_), ToString(audio_sender_state_),
5123             static_cast<int>(dsa_mode));
5124 
5125     if (IsReconfigurationTimeoutRunning(group->group_id_)) {
5126       log::info("Skip it as group is reconfiguring");
5127       return;
5128     }
5129 
5130     /* Stop the VBC close timeout timer, since we will reconfigure anyway if the
5131      * VBC was suspended.
5132      */
5133     StopVbcCloseTimeout();
5134 
5135     group->dsa_.mode = dsa_mode;
5136 
5137     /* Set the remote sink metadata context from the playback tracks metadata */
5138     UpdateSourceLocalMetadataContextTypes(GetAudioContextsFromSourceMetadata(source_metadata));
5139 
5140     /* Check if stream should be suspended due to reamaining only not allowed contexts in metadata
5141      * or configured context.
5142      *
5143      * If device is inCall mode, AF may quickly change metadata from ringing mode to active.
5144      * To avoid short stream suspend, let's keep stream alive.
5145      */
5146     if (com::android::bluetooth::flags::leaudio_stop_updated_to_not_available_context_stream() &&
5147         !IsInVoipOrRegularCall() &&
5148         stopStreamIfCurrentContextTypeIsNotAllowed(
5149                 bluetooth::le_audio::types::kLeAudioDirectionSink, group,
5150                 local_metadata_context_types_.source)) {
5151       log::info(
5152               "Updated source metadata contexts are not allowed context types: {} | configured: {} "
5153               "vs allowed context mask: {}",
5154               ToString(local_metadata_context_types_.source), ToString(configuration_context_type_),
5155               ToString(group->GetAllowedContextMask(
5156                       bluetooth::le_audio::types::kLeAudioDirectionSink)));
5157 
5158       return;
5159     }
5160 
5161     UpdateSourceLocalMetadataContextTypes(
5162             ChooseMetadataContextType(local_metadata_context_types_.source));
5163 
5164     ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSink);
5165   }
5166 
5167   /* Applies some predefined policy on the audio context metadata, including
5168    * special handling of UNSPECIFIED context, which also involves checking
5169    * context support and availability.
5170    */
ApplyRemoteMetadataAudioContextPolicy(LeAudioDeviceGroup * group,BidirectionalPair<AudioContexts> & contexts_pair,int remote_dir)5171   void ApplyRemoteMetadataAudioContextPolicy(LeAudioDeviceGroup* group,
5172                                              BidirectionalPair<AudioContexts>& contexts_pair,
5173                                              int remote_dir) {
5174     // We expect at least some context when this direction gets enabled
5175     if (contexts_pair.get(remote_dir).none()) {
5176       log::warn("invalid/unknown {} context metadata, using 'UNSPECIFIED' instead",
5177                 (remote_dir == bluetooth::le_audio::types::kLeAudioDirectionSink) ? "sink"
5178                                                                                   : "source");
5179       contexts_pair.get(remote_dir) = AudioContexts(LeAudioContextType::UNSPECIFIED);
5180     }
5181 
5182     std::tuple<int, int, AudioState*> remote_directions[] = {
5183             {bluetooth::le_audio::types::kLeAudioDirectionSink,
5184              bluetooth::le_audio::types::kLeAudioDirectionSource, &audio_sender_state_},
5185             {bluetooth::le_audio::types::kLeAudioDirectionSource,
5186              bluetooth::le_audio::types::kLeAudioDirectionSink, &audio_receiver_state_},
5187     };
5188 
5189     /* Align with the context availability */
5190     for (auto entry : remote_directions) {
5191       int dir, other_dir;
5192       AudioState* local_hal_state;
5193       std::tie(dir, other_dir, local_hal_state) = entry;
5194 
5195       /* When a certain context became unavailable while it was already in
5196        * an active stream, it means that it is unavailable to other clients
5197        * but we can keep using it.
5198        */
5199       auto group_available_contexts = group->GetAvailableContexts(dir);
5200       if ((*local_hal_state == AudioState::STARTED) ||
5201           (*local_hal_state == AudioState::READY_TO_START)) {
5202         group_available_contexts |= group->GetMetadataContexts().get(dir);
5203       }
5204 
5205       log::debug("Checking contexts: {}, against the available contexts: {}",
5206                  ToString(contexts_pair.get(dir)), ToString(group_available_contexts));
5207       auto unavail_contexts = contexts_pair.get(dir) & ~group_available_contexts;
5208       if (unavail_contexts.none()) {
5209         continue;
5210       }
5211 
5212       // Use only available contexts
5213       contexts_pair.get(dir) &= group_available_contexts;
5214 
5215       // Check we we should add UNSPECIFIED as well in case not available context is also not
5216       // supported
5217       auto unavail_but_supported = (unavail_contexts & group->GetSupportedContexts(dir));
5218       if (unavail_but_supported.none() &&
5219           group_available_contexts.test(LeAudioContextType::UNSPECIFIED)) {
5220         contexts_pair.get(dir).set(LeAudioContextType::UNSPECIFIED);
5221 
5222         log::debug("Replaced the unsupported contexts: {} with UNSPECIFIED -> {}",
5223                    ToString(unavail_contexts), ToString(contexts_pair.get(dir)));
5224       } else {
5225         log::debug("Some contexts are supported but currently unavailable: {}!",
5226                    ToString(unavail_but_supported));
5227         /* Some of the streamed contexts are support but not available and they
5228          * were erased from the metadata.
5229          * TODO: Either filter out these contexts from the stream or do not
5230          * stream at all if the unavail_but_supported contexts are the only
5231          * streamed contexts.
5232          */
5233       }
5234     }
5235 
5236     /* Don't mix UNSPECIFIED with any other context
5237      * Note: This has to be in a separate loop - do not merge it with the above.
5238      */
5239     for (auto entry : remote_directions) {
5240       int dir, other_dir;
5241       AudioState* local_hal_state;
5242       std::tie(dir, other_dir, local_hal_state) = entry;
5243 
5244       if (contexts_pair.get(dir).test(LeAudioContextType::UNSPECIFIED)) {
5245         /* If this directions is streaming just UNSPECIFIED and if other direction is streaming some
5246          * meaningfull context type,  try to use the meaningful context type
5247          */
5248         if (contexts_pair.get(dir) == AudioContexts(LeAudioContextType::UNSPECIFIED)) {
5249           auto is_other_direction_streaming = (*local_hal_state == AudioState::STARTED) ||
5250                                               (*local_hal_state == AudioState::READY_TO_START);
5251           if (is_other_direction_streaming) {
5252             auto supported_contexts = group->GetAllSupportedSingleDirectionOnlyContextTypes(dir);
5253             auto common_part = supported_contexts & contexts_pair.get(other_dir);
5254 
5255             log::info(
5256                     "Other direction is streaming. Possible aligning other direction "
5257                     "metadata to match the remote {} direction context: {}. Remote {} supported "
5258                     "contexts: {} ",
5259                     other_dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink"
5260                                                                                    : " Source",
5261                     ToString(contexts_pair.get(other_dir)),
5262                     dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink" : " Source",
5263                     ToString(supported_contexts));
5264 
5265             if (common_part.value() != 0) {
5266               contexts_pair.get(dir) = common_part;
5267             }
5268           }
5269         } else {
5270           log::debug("Removing UNSPECIFIED from the remote {} context: {}",
5271                      dir == bluetooth::le_audio::types::kLeAudioDirectionSink ? " Sink" : " Source",
5272                      ToString(contexts_pair.get(other_dir)));
5273           contexts_pair.get(dir).unset(LeAudioContextType::UNSPECIFIED);
5274         }
5275       }
5276     }
5277 
5278     contexts_pair.sink = ChooseMetadataContextType(contexts_pair.sink);
5279     contexts_pair.source = ChooseMetadataContextType(contexts_pair.source);
5280 
5281     log::debug("Aligned remote metadata audio context: sink={}, source={}",
5282                ToString(contexts_pair.sink), ToString(contexts_pair.source));
5283   }
5284 
OnLocalAudioSinkMetadataUpdate(const std::vector<record_track_metadata_v7> & sink_metadata)5285   void OnLocalAudioSinkMetadataUpdate(const std::vector<record_track_metadata_v7>& sink_metadata) {
5286     if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
5287       log::warn(", cannot start streaming if no active group set");
5288       return;
5289     }
5290 
5291     auto group = aseGroups_.FindById(active_group_id_);
5292     if (!group) {
5293       log::error("Invalid group: {}", static_cast<int>(active_group_id_));
5294       return;
5295     }
5296 
5297     log::info(
5298             "group_id {} state={}, target_state={}, audio_receiver_state_: {}, "
5299             "audio_sender_state_: {}",
5300             group->group_id_, ToString(group->GetState()), ToString(group->GetTargetState()),
5301             ToString(audio_receiver_state_), ToString(audio_sender_state_));
5302 
5303     if (IsReconfigurationTimeoutRunning(group->group_id_)) {
5304       log::info("Skip it as group is reconfiguring");
5305       return;
5306     }
5307 
5308     /* Set remote source metadata context from the recording tracks metadata */
5309     local_metadata_context_types_.sink = GetAudioContextsFromSinkMetadata(sink_metadata);
5310 
5311     /* Check if stream should be suspended due to only reamaining not allowed contexts in metadata
5312      * or configured context.
5313      *
5314      * If device is inCall mode, AF may quickly change metadata from ringing mode to active.
5315      * To avoid short stream suspend, let's keep stream alive.
5316      */
5317     if (com::android::bluetooth::flags::leaudio_stop_updated_to_not_available_context_stream() &&
5318         !IsInVoipOrRegularCall() &&
5319         stopStreamIfCurrentContextTypeIsNotAllowed(
5320                 bluetooth::le_audio::types::kLeAudioDirectionSource, group,
5321                 local_metadata_context_types_.sink)) {
5322       log::info(
5323               "Updated sink metadata contexts are not allowed context types: {} | configured: {} "
5324               "vs allowed context mask: {}",
5325               ToString(local_metadata_context_types_.sink), ToString(configuration_context_type_),
5326               ToString(group->GetAllowedContextMask(
5327                       bluetooth::le_audio::types::kLeAudioDirectionSource)));
5328       return;
5329     }
5330 
5331     UpdateSinkLocalMetadataContextTypes(
5332             ChooseMetadataContextType(local_metadata_context_types_.sink));
5333 
5334     /* Reconfigure or update only if the stream is already started
5335      * otherwise wait for the local sink to resume.
5336      */
5337     if (audio_receiver_state_ == AudioState::STARTED) {
5338       ReconfigureOrUpdateRemote(group, bluetooth::le_audio::types::kLeAudioDirectionSource);
5339     }
5340   }
5341 
DirectionalRealignMetadataAudioContexts(LeAudioDeviceGroup * group,int remote_direction)5342   BidirectionalPair<AudioContexts> DirectionalRealignMetadataAudioContexts(
5343           LeAudioDeviceGroup* group, int remote_direction) {
5344     uint8_t remote_other_direction;
5345     std::string remote_direction_str;
5346     std::string remote_other_direction_str;
5347     AudioState other_direction_hal;
5348 
5349     if (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink) {
5350       remote_other_direction = bluetooth::le_audio::types::kLeAudioDirectionSource;
5351       remote_direction_str = "Sink";
5352       remote_other_direction_str = "Source";
5353       other_direction_hal = audio_receiver_state_;
5354     } else {
5355       remote_other_direction = bluetooth::le_audio::types::kLeAudioDirectionSink;
5356       remote_direction_str = "Source";
5357       remote_other_direction_str = "Sink";
5358       other_direction_hal = audio_sender_state_;
5359     }
5360 
5361     auto is_streaming_other_direction = (other_direction_hal == AudioState::STARTED) ||
5362                                         (other_direction_hal == AudioState::READY_TO_START);
5363 
5364     auto local_direction = bluetooth::le_audio::types::kLeAudioDirectionBoth & ~remote_direction;
5365     auto local_other_direction =
5366             bluetooth::le_audio::types::kLeAudioDirectionBoth & ~remote_other_direction;
5367 
5368     auto is_releasing_for_reconfiguration =
5369             (((audio_receiver_state_ == AudioState::RELEASING) ||
5370               (audio_sender_state_ == AudioState::RELEASING)) &&
5371              group->IsPendingConfiguration() &&
5372              IsDirectionAvailableForCurrentConfiguration(group, remote_other_direction)) ||
5373             IsReconfigurationTimeoutRunning(active_group_id_, local_direction);
5374 
5375     auto is_releasing_for_reconfiguration_other_direction =
5376             is_releasing_for_reconfiguration &
5377             IsReconfigurationTimeoutRunning(active_group_id_, local_other_direction);
5378 
5379     // Inject conversational when ringtone is played - this is required for all
5380     // the VoIP applications which are not using the telecom API.
5381     constexpr AudioContexts possible_voip_contexts =
5382             LeAudioContextType::RINGTONE | LeAudioContextType::CONVERSATIONAL;
5383     if (local_metadata_context_types_.source.test_any(possible_voip_contexts) &&
5384         ((remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink) ||
5385          (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSource &&
5386           is_streaming_other_direction))) {
5387       /* Simulate, we are already in the call. Sending RINGTONE when there is
5388        * no incoming call to accept or reject on TBS could confuse the remote
5389        * device and interrupt the stream establish procedure.
5390        */
5391       if (!IsInCall() && !IsInVoipCall()) {
5392         SetInVoipCall(true);
5393       }
5394     } else if (IsInVoipCall()) {
5395       /* When determining whether the VoIP has ended or not make sure
5396        * we check the just updated direction metadata for CONVERSATIONAL
5397        */
5398       auto const local_direction_contexts = local_metadata_context_types_.get(local_direction);
5399       if (!local_direction_contexts.test_any(possible_voip_contexts)) {
5400         SetInVoipCall(false);
5401       }
5402     }
5403 
5404     BidirectionalPair<AudioContexts> remote_metadata = {
5405             .sink = local_metadata_context_types_.source,
5406             .source = local_metadata_context_types_.sink};
5407 
5408     auto all_bidirectional_contexts = group->GetAllSupportedBidirectionalContextTypes();
5409     log::debug("all_bidirectional_contexts {}", ToString(all_bidirectional_contexts));
5410 
5411     /*
5412      * Detect the gaming scenario and mirror the context to the other direction.
5413      * Thanks to this, we will be able to configure even Microphone only devices, for the GAME
5414      * audio context detected on the local audio source, which never gets resumed for such devices.
5415      */
5416     if (remote_metadata.sink.test(LeAudioContextType::GAME)) {
5417       auto ctxs = group->GetSupportedContexts(bluetooth::le_audio::types::kLeAudioDirectionSource) &
5418                   AudioContexts(LeAudioContextType::GAME) &
5419                   bluetooth::le_audio::types::kLeAudioContextAllBidir;
5420       if (ctxs.any()) {
5421         log::debug(
5422                 "Gaming scenario detected. Use this audio context for the other direction if "
5423                 "supported");
5424         remote_metadata.source.clear();
5425         remote_metadata.source.set_all(ctxs);
5426       }
5427     }
5428 
5429     /* Make sure we have CONVERSATIONAL when in a call and it is not mixed
5430      * with any other bidirectional context
5431      */
5432     if (IsInCall() || IsInVoipCall()) {
5433       log::debug("In Call preference used: {}, voip call: {}", IsInCall(), IsInVoipCall());
5434       remote_metadata.sink.unset_all(all_bidirectional_contexts);
5435       remote_metadata.source.unset_all(all_bidirectional_contexts);
5436       remote_metadata.sink.set(LeAudioContextType::CONVERSATIONAL);
5437       remote_metadata.source.set(LeAudioContextType::CONVERSATIONAL);
5438     }
5439 
5440     if (IsInVoipCall()) {
5441       log::debug("Unsetting RINGTONE from remote sink");
5442       remote_metadata.sink.unset(LeAudioContextType::RINGTONE);
5443     }
5444 
5445     auto is_ongoing_call_on_other_direction =
5446             is_streaming_other_direction && (IsInVoipCall() || IsInCall());
5447 
5448     log::debug("local_metadata_context_types_.source= {}",
5449                ToString(local_metadata_context_types_.source));
5450     log::debug("local_metadata_context_types_.sink= {}",
5451                ToString(local_metadata_context_types_.sink));
5452     log::debug("remote_metadata.source= {}", ToString(remote_metadata.source));
5453     log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink));
5454     log::debug("remote_direction= {}", remote_direction_str);
5455     log::debug("is_streaming_other_direction= {}", is_streaming_other_direction ? "True" : "False");
5456     log::debug("is_releasing_for_reconfiguration= {}",
5457                is_releasing_for_reconfiguration ? "True" : "False");
5458     log::debug("is_releasing_for_reconfiguration_other_direction= {}",
5459                is_releasing_for_reconfiguration_other_direction ? "True" : "False");
5460     log::debug("is_ongoing_call_on_other_direction={}",
5461                is_ongoing_call_on_other_direction ? "True" : "False");
5462 
5463     /* If the other direction is a bidir scenario we might want to take it into the account, but
5464      * not always. Look below for details.
5465      */
5466     auto is_other_direction_bidir =
5467             remote_metadata.get(remote_other_direction).test_any(all_bidirectional_contexts);
5468 
5469     /* If the not-resumed direction is local source, we might need to take it's metadata,
5470      * (this way we detect GAME scenario), but local sink metadata is unreliable.
5471      */
5472     bool take_unresumed_local_source_metadata_for_mic_only_devices =
5473             (group->audio_locations_.sink == std::nullopt) &&
5474             (local_other_direction == bluetooth::le_audio::types::kLeAudioDirectionSource);
5475     if (is_other_direction_bidir) {
5476       if (!(is_streaming_other_direction || is_releasing_for_reconfiguration_other_direction) &&
5477           !take_unresumed_local_source_metadata_for_mic_only_devices) {
5478         log::debug(
5479                 "The other direction is not streaming bidirectional or is not a reliable source of "
5480                 "metadata, ignore that context.");
5481         remote_metadata.get(remote_other_direction).clear();
5482       }
5483     }
5484 
5485     auto single_direction_only_context_types =
5486             group->GetAllSupportedSingleDirectionOnlyContextTypes(remote_direction);
5487     auto single_other_direction_only_context_types =
5488             group->GetAllSupportedSingleDirectionOnlyContextTypes(remote_other_direction);
5489     log::debug(
5490             "single direction only contexts : {} for direction {}, single direction contexts {} "
5491             "for {}",
5492             ToString(single_direction_only_context_types), remote_direction_str,
5493             ToString(single_other_direction_only_context_types), remote_other_direction_str);
5494 
5495     /* Mixed contexts in the voiceback channel scenarios can confuse the remote
5496      * on how to configure each channel. We should align the other direction
5497      * metadata for the remote device.
5498      */
5499     if (remote_metadata.get(remote_direction).test_any(all_bidirectional_contexts)) {
5500       log::debug("Aligning the other direction remote metadata to add this direction context");
5501 
5502       if (is_ongoing_call_on_other_direction) {
5503         /* Other direction is streaming and is in call */
5504         remote_metadata.get(remote_direction).unset_all(all_bidirectional_contexts);
5505         remote_metadata.get(remote_direction).set(LeAudioContextType::CONVERSATIONAL);
5506       } else {
5507         if (!(is_streaming_other_direction || is_releasing_for_reconfiguration_other_direction) &&
5508             !take_unresumed_local_source_metadata_for_mic_only_devices) {
5509           // Do not take the obsolete metadata
5510           remote_metadata.get(remote_other_direction).clear();
5511         } else {
5512           // The other direction was opened when already in a bidirectional scenario that was not a
5513           // VoIP or a regular Call. We need to figure out which direction metadata is the leading
5514           // one.
5515           // Note: We usually remove any bidirectional or the previous direction specific context
5516           //       from the previous direction metadata and replace it with the just-resumed
5517           //       direction (but still bidirectional) context. However when recording is started
5518           //       in a GAME scenario, we don't want to reconfigure to or mix the context with LIVE.
5519           auto remote_game_uplink_available =
5520                   group->GetAvailableContexts(le_audio::types::kLeAudioDirectionSource)
5521                           .test(LeAudioContextType::GAME);
5522           auto local_game_uplink_active =
5523                   (audio_sender_state_ == AudioState::STARTED) &&
5524                   remote_metadata.sink.test(LeAudioContextType::GAME) &&
5525                   remote_metadata.source.test_any(LeAudioContextType::LIVE |
5526                                                   LeAudioContextType::CONVERSATIONAL);
5527           log::debug(
5528                   "Remote {} metadata change ({}) while having remote {} context ({}) in a "
5529                   "bidirectional scenario of {}, local_game_uplink_active: {}, "
5530                   "remote_game_uplink_available: {}",
5531                   remote_direction_str, ToString(remote_metadata.get(remote_direction)),
5532                   remote_other_direction_str, ToString(remote_metadata.get(remote_other_direction)),
5533                   ToString(configuration_context_type_), local_game_uplink_active,
5534                   remote_game_uplink_available);
5535           if (local_game_uplink_active && remote_game_uplink_available) {
5536             remote_metadata.source.clear();
5537             remote_metadata.source.set(LeAudioContextType::GAME);
5538           } else {
5539             remote_metadata.get(remote_other_direction).unset_all(all_bidirectional_contexts);
5540             remote_metadata.get(remote_other_direction)
5541                     .unset_all(single_direction_only_context_types);
5542           }
5543         }
5544 
5545         remote_metadata.get(remote_other_direction)
5546                 .set_all(remote_metadata.get(remote_direction) &
5547                          ~single_other_direction_only_context_types);
5548       }
5549     }
5550     log::debug("remote_metadata.source= {}", ToString(remote_metadata.source));
5551     log::debug("remote_metadata.sink= {}", ToString(remote_metadata.sink));
5552 
5553     if (is_releasing_for_reconfiguration || is_streaming_other_direction) {
5554       log::debug("Other direction is streaming or there is reconfiguration. Taking its contexts {}",
5555                  ToString(remote_metadata.get(remote_other_direction)));
5556       /* If current direction has no valid context or the other direction is
5557        * bidirectional scenario, take the other direction context as well
5558        */
5559       if ((remote_metadata.get(remote_direction).none() &&
5560            remote_metadata.get(remote_other_direction).any()) ||
5561           remote_metadata.get(remote_other_direction).test_any(all_bidirectional_contexts)) {
5562         log::debug("Aligning this direction remote metadata to add the other direction context");
5563         /* Turn off bidirectional contexts on this direction to avoid mixing
5564          * with the other direction bidirectional context
5565          */
5566         remote_metadata.get(remote_direction).unset_all(all_bidirectional_contexts);
5567         remote_metadata.get(remote_direction).set_all(remote_metadata.get(remote_other_direction));
5568       }
5569     }
5570 
5571     /* Make sure that after alignment no sink only context leaks into the other
5572      * direction. */
5573     remote_metadata.source.unset_all(group->GetAllSupportedSingleDirectionOnlyContextTypes(
5574             bluetooth::le_audio::types::kLeAudioDirectionSink));
5575 
5576     log::debug("final remote_metadata.source= {}", ToString(remote_metadata.source));
5577     log::debug("final remote_metadata.sink= {}", ToString(remote_metadata.sink));
5578     return remote_metadata;
5579   }
5580 
ReconfigureOrUpdateRemoteForPTS(LeAudioDeviceGroup * group,int)5581   bool ReconfigureOrUpdateRemoteForPTS(LeAudioDeviceGroup* group, int /*remote_direction*/) {
5582     log::info("{}", group->group_id_);
5583     // Use common audio stream contexts exposed by the PTS
5584     auto override_contexts = AudioContexts(0xFFFF);
5585     for (auto device = group->GetFirstDevice(); device != nullptr;
5586          device = group->GetNextDevice(device)) {
5587       override_contexts &= device->GetAvailableContexts();
5588     }
5589     if (override_contexts.value() == 0xFFFF) {
5590       override_contexts = AudioContexts(LeAudioContextType::UNSPECIFIED);
5591     }
5592     log::warn("Overriding local_metadata_context_types_: {} with: {}",
5593               local_metadata_context_types_.source.to_string(), override_contexts.to_string());
5594 
5595     /* Choose the right configuration context */
5596     auto new_configuration_context = ChooseConfigurationContextType(override_contexts);
5597 
5598     log::info("new_configuration_context= {}.", ToString(new_configuration_context));
5599     BidirectionalPair<AudioContexts> remote_contexts = {.sink = override_contexts,
5600                                                         .source = override_contexts};
5601     return GroupStream(group, new_configuration_context, remote_contexts);
5602   }
5603 
5604   /* Return true if stream is started */
ReconfigureOrUpdateRemote(LeAudioDeviceGroup * group,int remote_direction)5605   bool ReconfigureOrUpdateRemote(LeAudioDeviceGroup* group, int remote_direction) {
5606     if (stack_config_get_interface()->get_pts_force_le_audio_multiple_contexts_metadata()) {
5607       return ReconfigureOrUpdateRemoteForPTS(group, remote_direction);
5608     }
5609 
5610     /* When the local sink and source update their metadata, we need to come up
5611      * with a coherent set of contexts for either one or both directions,
5612      * especially when bidirectional scenarios can be triggered be either sink
5613      * or source metadata update event.
5614      */
5615     auto remote_metadata = DirectionalRealignMetadataAudioContexts(group, remote_direction);
5616     if (!remote_metadata.sink.any() && !remote_metadata.source.any()) {
5617       log::warn("No valid metadata to update or reconfigure to.");
5618       return false;
5619     }
5620 
5621     /* Choose the right configuration context */
5622     auto config_context_candids = get_bidirectional(remote_metadata);
5623     auto new_config_context = ChooseConfigurationContextType(config_context_candids);
5624     log::debug("config_context_candids= {}, new_config_context= {}",
5625                ToString(config_context_candids), ToString(new_config_context));
5626 
5627     /* For the following contexts we don't actually need HQ audio:
5628      * LeAudioContextType::NOTIFICATIONS
5629      * LeAudioContextType::SOUNDEFFECTS
5630      * LeAudioContextType::INSTRUCTIONAL
5631      * LeAudioContextType::ALERTS
5632      * LeAudioContextType::EMERGENCYALARM
5633      * LeAudioContextType::UNSPECIFIED
5634      * So do not reconfigure if the remote sink is already available at any
5635      * quality and these are the only contributors to the current audio stream.
5636      */
5637     auto no_reconfigure_contexts =
5638             LeAudioContextType::NOTIFICATIONS | LeAudioContextType::SOUNDEFFECTS |
5639             LeAudioContextType::INSTRUCTIONAL | LeAudioContextType::ALERTS |
5640             LeAudioContextType::EMERGENCYALARM | LeAudioContextType::UNSPECIFIED;
5641     if (group->IsStreaming() && !group->IsReleasingOrIdle() && config_context_candids.any() &&
5642         (config_context_candids & ~no_reconfigure_contexts).none() &&
5643         (configuration_context_type_ != LeAudioContextType::UNINITIALIZED) &&
5644         (configuration_context_type_ != LeAudioContextType::UNSPECIFIED) &&
5645         IsDirectionAvailableForCurrentConfiguration(
5646                 group, bluetooth::le_audio::types::kLeAudioDirectionSink)) {
5647       log::info(
5648               "There is no need to reconfigure for the sonification events, "
5649               "staying with the existing configuration context of {}",
5650               ToString(configuration_context_type_));
5651       new_config_context = configuration_context_type_;
5652     }
5653 
5654     /* Do not configure the Voiceback channel if it is already configured.
5655      * WARNING: This eliminates additional reconfigurations but can
5656      * lead to unsatisfying audio quality when that direction was
5657      * already configured with a lower quality.
5658      */
5659     if (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSource) {
5660       const auto has_audio_source_configured =
5661               IsDirectionAvailableForCurrentConfiguration(
5662                       group, bluetooth::le_audio::types::kLeAudioDirectionSource) &&
5663               (group->GetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5664       if (has_audio_source_configured) {
5665         log::info(
5666                 "Audio source is already available in the current configuration "
5667                 "context in {}. Not switching to {} right now.",
5668                 ToString(configuration_context_type_), ToString(new_config_context));
5669         new_config_context = configuration_context_type_;
5670       }
5671     }
5672 
5673     /* Note that the remote device metadata was so far unfiltered when it comes
5674      * to group context availability, or multiple contexts support flag, so that
5675      * we could choose the correct configuration for the use case. Now we can
5676      * align it to meet the metadata usage.
5677      */
5678     ApplyRemoteMetadataAudioContextPolicy(group, remote_metadata, remote_direction);
5679     return ReconfigureOrUpdateMetadata(group, new_config_context, remote_metadata);
5680   }
5681 
DsaReconfigureNeeded(LeAudioDeviceGroup * group,LeAudioContextType context)5682   bool DsaReconfigureNeeded(LeAudioDeviceGroup* group, LeAudioContextType context) {
5683     // Reconfigure if DSA mode changed for media streaming
5684     if (context != bluetooth::le_audio::types::LeAudioContextType::MEDIA) {
5685       return false;
5686     }
5687 
5688     if (group->dsa_.mode != DsaMode::ISO_SW && group->dsa_.mode != DsaMode::ISO_HW) {
5689       return false;
5690     }
5691 
5692     if (group->dsa_.active) {
5693       return false;
5694     }
5695 
5696     log::info("DSA mode {} requested but not active", group->dsa_.mode);
5697     return true;
5698   }
5699 
5700   /* Return true if stream is started */
ReconfigureOrUpdateMetadata(LeAudioDeviceGroup * group,LeAudioContextType new_configuration_context,BidirectionalPair<AudioContexts> remote_contexts)5701   bool ReconfigureOrUpdateMetadata(LeAudioDeviceGroup* group,
5702                                    LeAudioContextType new_configuration_context,
5703                                    BidirectionalPair<AudioContexts> remote_contexts) {
5704     if (new_configuration_context != configuration_context_type_ ||
5705         DsaReconfigureNeeded(group, new_configuration_context)) {
5706       log::info("Checking whether to change configuration context from {} to {}",
5707                 ToString(configuration_context_type_), ToString(new_configuration_context));
5708 
5709       LeAudioLogHistory::Get()->AddLogHistory(
5710               kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
5711               kLogAfMetadataUpdate + "Reconfigure",
5712               ToString(configuration_context_type_) + "->" + ToString(new_configuration_context));
5713       auto is_stopping = SetConfigurationAndStopStreamWhenNeeded(group, new_configuration_context);
5714       if (is_stopping) {
5715         return false;
5716       }
5717     }
5718 
5719     if (group->GetTargetState() == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING) {
5720       log::info("The {} configuration did not change. Updating the metadata to sink={}, source={}",
5721                 ToString(configuration_context_type_), ToString(remote_contexts.sink),
5722                 ToString(remote_contexts.source));
5723 
5724       LeAudioLogHistory::Get()->AddLogHistory(
5725               kLogAfCallBt, active_group_id_, RawAddress::kEmpty,
5726               kLogAfMetadataUpdate + "Updating...",
5727               "Sink: " + ToString(remote_contexts.sink) +
5728                       "Source: " + ToString(remote_contexts.source));
5729 
5730       return GroupStream(group, configuration_context_type_, remote_contexts);
5731     }
5732     return false;
5733   }
5734 
OnGattReadRspStatic(tCONN_ID conn_id,tGATT_STATUS status,uint16_t hdl,uint16_t len,uint8_t * value,void * data)5735   static void OnGattReadRspStatic(tCONN_ID conn_id, tGATT_STATUS status, uint16_t hdl, uint16_t len,
5736                                   uint8_t* value, void* data) {
5737     if (!instance) {
5738       return;
5739     }
5740 
5741     LeAudioDevice* leAudioDevice = instance->leAudioDevices_.FindByConnId(conn_id);
5742 
5743     if (status == GATT_SUCCESS) {
5744       instance->LeAudioCharValueHandle(conn_id, hdl, len, value);
5745     } else if (status == GATT_DATABASE_OUT_OF_SYNC) {
5746       instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
5747       return;
5748     } else {
5749       log::error("Failed to read attribute, hdl: 0x{:04x}, status: 0x{:02x}", hdl,
5750                  static_cast<int>(status));
5751       return;
5752     }
5753 
5754     /* We use data to keep notify connected flag. */
5755     if (data && !!PTR_TO_INT(data)) {
5756       leAudioDevice->notify_connected_after_read_ = false;
5757 
5758       /* Update handles, PACs and ASEs when all is read.*/
5759       btif_storage_leaudio_update_handles_bin(leAudioDevice->address_);
5760       btif_storage_leaudio_update_pacs_bin(leAudioDevice->address_);
5761       btif_storage_leaudio_update_ase_bin(leAudioDevice->address_);
5762 
5763       if (leAudioDevice->audio_locations_.sink) {
5764         btif_storage_set_leaudio_sink_audio_location(
5765                 leAudioDevice->address_, leAudioDevice->audio_locations_.sink->value.to_ulong());
5766       }
5767       if (leAudioDevice->audio_locations_.source) {
5768         btif_storage_set_leaudio_source_audio_location(
5769                 leAudioDevice->address_, leAudioDevice->audio_locations_.source->value.to_ulong());
5770       }
5771 
5772       instance->connectionReady(leAudioDevice);
5773     }
5774   }
5775 
OnGattReadMultiRspStatic(tCONN_ID conn_id,tGATT_STATUS status,tBTA_GATTC_MULTI & handles,uint16_t total_len,uint8_t * value,void * data)5776   static void OnGattReadMultiRspStatic(tCONN_ID conn_id, tGATT_STATUS status,
5777                                        tBTA_GATTC_MULTI& handles, uint16_t total_len,
5778                                        uint8_t* value, void* data) {
5779     if (!instance) {
5780       return;
5781     }
5782 
5783     if (status == GATT_DATABASE_OUT_OF_SYNC) {
5784       LeAudioDevice* leAudioDevice = instance->leAudioDevices_.FindByConnId(conn_id);
5785       instance->ClearDeviceInformationAndStartSearch(leAudioDevice);
5786       return;
5787     }
5788     if (status != GATT_SUCCESS) {
5789       log::error("Failed to read multiple attributes, conn_id: 0x{:04x}, status: 0x{:02x}", conn_id,
5790                  +status);
5791       return;
5792     }
5793 
5794     size_t position = 0;
5795     int index = 0;
5796     while (position != total_len) {
5797       uint8_t* ptr = value + position;
5798       uint16_t len;
5799       STREAM_TO_UINT16(len, ptr);
5800       uint16_t hdl = handles.handles[index];
5801 
5802       if (position + len >= total_len) {
5803         log::warn("Multi read was too long, value truncated conn_id: 0x{:04x} handle: 0x{:04x}",
5804                   conn_id, hdl);
5805         break;
5806       }
5807 
5808       OnGattReadRspStatic(conn_id, status, hdl, len, ptr,
5809                           ((index == (handles.num_attr - 1)) ? data : nullptr));
5810 
5811       position += len + 2; /* skip the length of data */
5812       index++;
5813     }
5814 
5815     if (handles.num_attr != index) {
5816       log::warn("Attempted to read {} handles, but received just {} values", +handles.num_attr,
5817                 index);
5818     }
5819   }
5820 
LeAudioHealthSendRecommendation(const RawAddress & address,int group_id,LeAudioHealthBasedAction action)5821   void LeAudioHealthSendRecommendation(const RawAddress& address, int group_id,
5822                                        LeAudioHealthBasedAction action) {
5823     log::debug("{}, {}, {}", address, group_id, ToString(action));
5824 
5825     if (address != RawAddress::kEmpty && leAudioDevices_.FindByAddress(address)) {
5826       callbacks_->OnHealthBasedRecommendationAction(address, action);
5827     }
5828 
5829     if (group_id != bluetooth::groups::kGroupUnknown && aseGroups_.FindById(group_id)) {
5830       callbacks_->OnHealthBasedGroupRecommendationAction(group_id, action);
5831     }
5832   }
5833 
IsoCigEventsCb(uint16_t event_type,void * data)5834   void IsoCigEventsCb(uint16_t event_type, void* data) {
5835     switch (event_type) {
5836       case bluetooth::hci::iso_manager::kIsoEventCigOnCreateCmpl: {
5837         auto* evt = static_cast<cig_create_cmpl_evt*>(data);
5838         LeAudioDeviceGroup* group = aseGroups_.FindById(evt->cig_id);
5839         log::assert_that(group, "Group id: {} is null", evt->cig_id);
5840         groupStateMachine_->ProcessHciNotifOnCigCreate(group, evt->status, evt->cig_id,
5841                                                        evt->conn_handles);
5842       } break;
5843       case bluetooth::hci::iso_manager::kIsoEventCigOnRemoveCmpl: {
5844         auto* evt = static_cast<cig_remove_cmpl_evt*>(data);
5845         LeAudioDeviceGroup* group = aseGroups_.FindById(evt->cig_id);
5846         log::assert_that(group, "Group id: {} is null", evt->cig_id);
5847         groupStateMachine_->ProcessHciNotifOnCigRemove(evt->status, group);
5848         remove_group_if_possible(group);
5849       } break;
5850       default:
5851         log::error("Invalid event {}", event_type);
5852     }
5853   }
5854 
IsoCisEventsCb(uint16_t event_type,void * data)5855   void IsoCisEventsCb(uint16_t event_type, void* data) {
5856     switch (event_type) {
5857       case bluetooth::hci::iso_manager::kIsoEventCisDataAvailable: {
5858         auto* event = static_cast<bluetooth::hci::iso_manager::cis_data_evt*>(data);
5859 
5860         if (DsaDataConsume(event)) {
5861           return;
5862         }
5863 
5864         if (audio_receiver_state_ != AudioState::STARTED) {
5865           log::error("receiver state not ready, current state={}", ToString(audio_receiver_state_));
5866           break;
5867         }
5868 
5869         HandleIncomingCisData(event->p_msg->data + event->p_msg->offset,
5870                               event->p_msg->len - event->p_msg->offset, event->cis_conn_hdl,
5871                               event->ts);
5872       } break;
5873       case bluetooth::hci::iso_manager::kIsoEventCisEstablishCmpl: {
5874         auto* event = static_cast<bluetooth::hci::iso_manager::cis_establish_cmpl_evt*>(data);
5875 
5876         LeAudioDevice* leAudioDevice =
5877                 leAudioDevices_.FindByCisConnHdl(event->cig_id, event->cis_conn_hdl);
5878         if (!leAudioDevice) {
5879           log::error("no bonded Le Audio Device with CIS: {}", event->cis_conn_hdl);
5880           break;
5881         }
5882         LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5883 
5884         if (event->max_pdu_mtos > 0) {
5885           group->SetTransportLatency(bluetooth::le_audio::types::kLeAudioDirectionSink,
5886                                      event->trans_lat_mtos);
5887         }
5888         if (event->max_pdu_stom > 0) {
5889           group->SetTransportLatency(bluetooth::le_audio::types::kLeAudioDirectionSource,
5890                                      event->trans_lat_stom);
5891         }
5892 
5893         if (leAudioHealthStatus_ && (event->status != HCI_SUCCESS)) {
5894           leAudioHealthStatus_->AddStatisticForGroup(
5895                   group, LeAudioHealthGroupStatType::STREAM_CREATE_CIS_FAILED);
5896         }
5897 
5898         groupStateMachine_->ProcessHciNotifCisEstablished(group, leAudioDevice, event);
5899       } break;
5900       case bluetooth::hci::iso_manager::kIsoEventCisDisconnected: {
5901         auto* event = static_cast<bluetooth::hci::iso_manager::cis_disconnected_evt*>(data);
5902 
5903         LeAudioDevice* leAudioDevice =
5904                 leAudioDevices_.FindByCisConnHdl(event->cig_id, event->cis_conn_hdl);
5905         if (!leAudioDevice) {
5906           log::error("no bonded Le Audio Device with CIS: {}", event->cis_conn_hdl);
5907           break;
5908         }
5909         LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5910 
5911         groupStateMachine_->ProcessHciNotifCisDisconnected(group, leAudioDevice, event);
5912       } break;
5913       default:
5914         log::info(", Not handled ISO event");
5915         break;
5916     }
5917   }
5918 
IsoSetupIsoDataPathCb(uint8_t status,uint16_t conn_handle,uint8_t cig_id)5919   void IsoSetupIsoDataPathCb(uint8_t status, uint16_t conn_handle, uint8_t cig_id) {
5920     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5921     /* In case device has been disconnected before data path was setup */
5922     if (!leAudioDevice) {
5923       log::warn("Device for CIG {} and using cis_handle 0x{:04x} is disconnected.", cig_id,
5924                 conn_handle);
5925       return;
5926     }
5927     LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5928 
5929     instance->groupStateMachine_->ProcessHciNotifSetupIsoDataPath(group, leAudioDevice, status,
5930                                                                   conn_handle);
5931   }
5932 
IsoRemoveIsoDataPathCb(uint8_t status,uint16_t conn_handle,uint8_t cig_id)5933   void IsoRemoveIsoDataPathCb(uint8_t status, uint16_t conn_handle, uint8_t cig_id) {
5934     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5935 
5936     /* If CIS has been disconnected just before ACL being disconnected by the
5937      * remote device, leAudioDevice might be already cleared i.e. has no
5938      * information about conn_handle, when the data path remove compete arrives.
5939      */
5940     if (!leAudioDevice) {
5941       log::warn("Device for CIG {} and using cis_handle 0x{:04x} is disconnected.", cig_id,
5942                 conn_handle);
5943       return;
5944     }
5945 
5946     LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5947 
5948     instance->groupStateMachine_->ProcessHciNotifRemoveIsoDataPath(group, leAudioDevice, status,
5949                                                                    conn_handle);
5950   }
5951 
IsoLinkQualityReadCb(uint8_t conn_handle,uint8_t cig_id,uint32_t txUnackedPackets,uint32_t txFlushedPackets,uint32_t txLastSubeventPackets,uint32_t retransmittedPackets,uint32_t crcErrorPackets,uint32_t rxUnreceivedPackets,uint32_t duplicatePackets)5952   void IsoLinkQualityReadCb(uint8_t conn_handle, uint8_t cig_id, uint32_t txUnackedPackets,
5953                             uint32_t txFlushedPackets, uint32_t txLastSubeventPackets,
5954                             uint32_t retransmittedPackets, uint32_t crcErrorPackets,
5955                             uint32_t rxUnreceivedPackets, uint32_t duplicatePackets) {
5956     LeAudioDevice* leAudioDevice = leAudioDevices_.FindByCisConnHdl(cig_id, conn_handle);
5957     if (!leAudioDevice) {
5958       log::warn("device under connection handle: 0x{:x}, has been disconnecected in meantime",
5959                 conn_handle);
5960       return;
5961     }
5962     LeAudioDeviceGroup* group = aseGroups_.FindById(leAudioDevice->group_id_);
5963 
5964     instance->groupStateMachine_->ProcessHciNotifIsoLinkQualityRead(
5965             group, leAudioDevice, conn_handle, txUnackedPackets, txFlushedPackets,
5966             txLastSubeventPackets, retransmittedPackets, crcErrorPackets, rxUnreceivedPackets,
5967             duplicatePackets);
5968   }
5969 
HandlePendingDeviceRemove(LeAudioDeviceGroup * group)5970   void HandlePendingDeviceRemove(LeAudioDeviceGroup* group) {
5971     for (auto device = group->GetFirstDevice(); device != nullptr;
5972          device = group->GetNextDevice(device)) {
5973       if (device->GetConnectionState() == DeviceConnectState::REMOVING) {
5974         if (device->closing_stream_for_disconnection_) {
5975           device->closing_stream_for_disconnection_ = false;
5976           log::info("Disconnecting group id: {}, address: {}", group->group_id_, device->address_);
5977           bool force_acl_disconnect = device->autoconnect_flag_ && group->IsEnabled();
5978           DisconnectDevice(device, force_acl_disconnect);
5979         }
5980         group_remove_node(group, device->address_, true);
5981       }
5982     }
5983   }
5984 
HandlePendingDeviceDisconnection(LeAudioDeviceGroup * group)5985   void HandlePendingDeviceDisconnection(LeAudioDeviceGroup* group) {
5986     log::debug("");
5987 
5988     auto leAudioDevice = group->GetFirstDevice();
5989     while (leAudioDevice) {
5990       if (leAudioDevice->closing_stream_for_disconnection_) {
5991         leAudioDevice->closing_stream_for_disconnection_ = false;
5992         log::debug("Disconnecting group id: {}, address: {}", group->group_id_,
5993                    leAudioDevice->address_);
5994         bool force_acl_disconnect = leAudioDevice->autoconnect_flag_ && group->IsEnabled();
5995         DisconnectDevice(leAudioDevice, force_acl_disconnect);
5996       }
5997       leAudioDevice = group->GetNextDevice(leAudioDevice);
5998     }
5999   }
6000 
UpdateAudioConfigToHal(const::bluetooth::le_audio::stream_config & config,uint8_t remote_direction)6001   void UpdateAudioConfigToHal(const ::bluetooth::le_audio::stream_config& config,
6002                               uint8_t remote_direction) {
6003     if ((remote_direction & bluetooth::le_audio::types::kLeAudioDirectionSink) &&
6004         le_audio_source_hal_client_) {
6005       le_audio_source_hal_client_->UpdateAudioConfigToHal(config);
6006     }
6007     if ((remote_direction & bluetooth::le_audio::types::kLeAudioDirectionSource) &&
6008         le_audio_sink_hal_client_) {
6009       le_audio_sink_hal_client_->UpdateAudioConfigToHal(config);
6010     }
6011   }
6012 
NotifyUpperLayerGroupTurnedIdleDuringCall(int group_id)6013   void NotifyUpperLayerGroupTurnedIdleDuringCall(int group_id) {
6014     if (!osi_property_get_bool(kNotifyUpperLayerAboutGroupBeingInIdleDuringCall, false)) {
6015       return;
6016     }
6017 
6018     /* If group is inactive, phone is in call and Group is not having CIS
6019      * connected, notify upper layer about it, so it can decide to create SCO if
6020      * it is in the handover case
6021      */
6022     if ((IsInCall() || IsInVoipCall()) && active_group_id_ == bluetooth::groups::kGroupUnknown) {
6023       callbacks_->OnGroupStatus(group_id, GroupStatus::TURNED_IDLE_DURING_CALL);
6024     }
6025   }
6026 
speed_start_setup(int group_id,LeAudioContextType context_type,int num_of_connected,bool is_reconfig=false)6027   void speed_start_setup(int group_id, LeAudioContextType context_type, int num_of_connected,
6028                          bool is_reconfig = false) {
6029     log::verbose("is_started {} is_reconfig {} num_of_connected {}",
6030                  speed_tracker_.IsStarted(group_id), is_reconfig, num_of_connected);
6031     if (!speed_tracker_.IsStarted(group_id)) {
6032       speed_tracker_.Init(group_id, context_type, num_of_connected);
6033     }
6034     if (is_reconfig) {
6035       speed_tracker_.ReconfigStarted();
6036     } else {
6037       speed_tracker_.StartStream();
6038     }
6039   }
6040 
speed_stop_reconfig(int group_id)6041   void speed_stop_reconfig(int group_id) {
6042     log::verbose("");
6043     if (!speed_tracker_.IsStarted(group_id)) {
6044       return;
6045     }
6046 
6047     speed_tracker_.ReconfigurationComplete();
6048   }
6049 
speed_stream_created(int group_id)6050   void speed_stream_created(int group_id) {
6051     log::verbose("");
6052     if (!speed_tracker_.IsStarted(group_id)) {
6053       return;
6054     }
6055 
6056     speed_tracker_.StreamCreated();
6057   }
6058 
speed_stop_setup(int group_id)6059   void speed_stop_setup(int group_id) {
6060     log::verbose("");
6061     if (!speed_tracker_.IsStarted(group_id)) {
6062       return;
6063     }
6064 
6065     if (stream_speed_history_.size() == 10) {
6066       stream_speed_history_.pop_back();
6067     }
6068 
6069     speed_tracker_.StopStreamSetup();
6070     stream_speed_history_.emplace_front(speed_tracker_);
6071     speed_tracker_.Reset(group_id);
6072   }
6073 
notifyGroupStreamStatus(int group_id,GroupStreamStatus groupStreamStatus)6074   void notifyGroupStreamStatus(int group_id, GroupStreamStatus groupStreamStatus) {
6075     GroupStreamStatus newGroupStreamStatus = GroupStreamStatus::IDLE;
6076     if (groupStreamStatus == GroupStreamStatus::STREAMING) {
6077       newGroupStreamStatus = GroupStreamStatus::STREAMING;
6078     }
6079 
6080     auto it = lastNotifiedGroupStreamStatusMap_.find(group_id);
6081 
6082     if (it != lastNotifiedGroupStreamStatusMap_.end()) {
6083       if (it->second != newGroupStreamStatus) {
6084         callbacks_->OnGroupStreamStatus(group_id, newGroupStreamStatus);
6085         it->second = newGroupStreamStatus;
6086       }
6087     } else {
6088       callbacks_->OnGroupStreamStatus(group_id, newGroupStreamStatus);
6089       lastNotifiedGroupStreamStatusMap_.emplace(group_id, newGroupStreamStatus);
6090     }
6091   }
6092 
handleAsymmetricPhyForUnicast(LeAudioDeviceGroup * group)6093   void handleAsymmetricPhyForUnicast(LeAudioDeviceGroup* group) {
6094     if (!group->asymmetric_phy_for_unidirectional_cis_supported) {
6095       return;
6096     }
6097 
6098     auto it = lastNotifiedGroupStreamStatusMap_.find(group->group_id_);
6099 
6100     if (it != lastNotifiedGroupStreamStatusMap_.end() &&
6101         it->second == GroupStreamStatus::STREAMING &&
6102         group->GetSduInterval(bluetooth::le_audio::types::kLeAudioDirectionSource) == 0) {
6103       SetAsymmetricBlePhy(group, true);
6104       return;
6105     }
6106 
6107     SetAsymmetricBlePhy(group, false);
6108   }
6109 
reconfigurationComplete(void)6110   void reconfigurationComplete(void) {
6111     // Check which directions were suspended
6112     uint8_t previously_active_directions = 0;
6113     if (audio_sender_state_ >= AudioState::READY_TO_START) {
6114       previously_active_directions |= bluetooth::le_audio::types::kLeAudioDirectionSink;
6115     }
6116     if (audio_receiver_state_ >= AudioState::READY_TO_START) {
6117       previously_active_directions |= bluetooth::le_audio::types::kLeAudioDirectionSource;
6118     }
6119 
6120     /* We are done with reconfiguration.
6121      * Clean state and if Audio HAL is waiting, cancel the request
6122      * so Audio HAL can Resume again.
6123      */
6124     CancelStreamingRequest();
6125     ReconfigurationComplete(previously_active_directions);
6126     speed_stop_reconfig(active_group_id_);
6127   }
6128 
OnStateMachineStatusReportCb(int group_id,GroupStreamStatus status)6129   void OnStateMachineStatusReportCb(int group_id, GroupStreamStatus status) {
6130     /* When switching stream between two group, it is important to keep track if given status is for
6131      * active group or not in order to proper Audio HAL notifications.
6132      * It means, we should update Audio HAL and clear common resources when group is an active group
6133      * or active group is already cleared.
6134      */
6135     bool is_active_group_operation =
6136             (group_id == active_group_id_ || active_group_id_ == bluetooth::groups::kGroupUnknown);
6137 
6138     log::info(
6139             "status: {},  group_id: {}, audio_sender_state {}, audio_receiver_state {}, "
6140             "is_active_group_operation {}",
6141             bluetooth::common::ToString(status), group_id,
6142             bluetooth::common::ToString(audio_sender_state_),
6143             bluetooth::common::ToString(audio_receiver_state_), is_active_group_operation);
6144     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
6145 
6146     notifyGroupStreamStatus(group_id, status);
6147 
6148     switch (status) {
6149       case GroupStreamStatus::STREAMING: {
6150         if (!is_active_group_operation) {
6151           log::error("Streaming group {} is no longer active. Stop the group.", group_id);
6152           GroupStop(group_id);
6153           return;
6154         }
6155 
6156         speed_stream_created(group_id);
6157         bluetooth::le_audio::MetricsCollector::Get()->OnStreamStarted(active_group_id_,
6158                                                                       configuration_context_type_);
6159 
6160         if (leAudioHealthStatus_) {
6161           leAudioHealthStatus_->AddStatisticForGroup(
6162                   group, LeAudioHealthGroupStatType::STREAM_CREATE_SUCCESS);
6163         }
6164 
6165         if (!group) {
6166           log::error("Group {} does not exist anymore. This shall not happen", group_id);
6167           return;
6168         }
6169 
6170         handleAsymmetricPhyForUnicast(group);
6171 
6172         if ((audio_sender_state_ == AudioState::IDLE) &&
6173             (audio_receiver_state_ == AudioState::IDLE)) {
6174           /* Audio Framework is not interested in the stream anymore.
6175            * Just stop streaming
6176            */
6177           log::warn("Stopping stream for group {} as AF not interested.", group_id);
6178           speed_stop_setup(group_id);
6179           groupStateMachine_->StopStream(group);
6180           return;
6181         }
6182 
6183         /* It might happen that the configuration has already changed, while
6184          * the group was in the ongoing reconfiguration. We should stop the
6185          * stream and reconfigure once again.
6186          */
6187         if (group->GetConfigurationContextType() != configuration_context_type_) {
6188           log::debug(
6189                   "The configuration {} is no longer valid. Stopping the stream to "
6190                   "reconfigure to {}",
6191                   ToString(group->GetConfigurationContextType()),
6192                   ToString(configuration_context_type_));
6193           speed_stop_setup(group_id);
6194           initReconfiguration(group, group->GetConfigurationContextType());
6195           return;
6196         }
6197 
6198         if (audio_sender_state_ == AudioState::READY_TO_START) {
6199           StartSendingAudio(group_id);
6200         } else if (audio_sender_state_ == AudioState::STARTED) {
6201           /* If we are already sending, the initial configuration was already sent and
6202            * we might need to just update the current channel mixing information.
6203            */
6204           CodecManager::GetInstance()->UpdateActiveAudioConfig(
6205                   group->stream_conf.stream_params,
6206                   std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
6207                             std::placeholders::_1, std::placeholders::_2),
6208                   ::bluetooth::le_audio::types::kLeAudioDirectionSink);
6209         }
6210 
6211         if (audio_receiver_state_ == AudioState::READY_TO_START) {
6212           StartReceivingAudio(group_id);
6213         } else if (audio_receiver_state_ == AudioState::STARTED) {
6214           /* If we are already receiving, the initial configuration was already sent and
6215            * we might need to just update the current channel mixing information.
6216            */
6217           CodecManager::GetInstance()->UpdateActiveAudioConfig(
6218                   group->stream_conf.stream_params,
6219                   std::bind(&LeAudioClientImpl::UpdateAudioConfigToHal, weak_factory_.GetWeakPtr(),
6220                             std::placeholders::_1, std::placeholders::_2),
6221                   bluetooth::le_audio::types::kLeAudioDirectionSource);
6222         }
6223 
6224         speed_stop_setup(group_id);
6225         break;
6226       }
6227       case GroupStreamStatus::SUSPENDED:
6228         speed_tracker_.Reset(group_id);
6229 
6230         if (is_active_group_operation) {
6231           /** Stop Audio but don't release all the Audio resources */
6232           SuspendAudio();
6233         }
6234         break;
6235       case GroupStreamStatus::CONFIGURED_BY_USER:
6236         if (is_active_group_operation) {
6237           reconfigurationComplete();
6238         }
6239         break;
6240       case GroupStreamStatus::CONFIGURED_AUTONOMOUS:
6241         /* This state is notified only when
6242          * groups stays into CONFIGURED state after
6243          * STREAMING. Peer device uses cache. For the moment
6244          * it is handled same as IDLE
6245          */
6246       case GroupStreamStatus::IDLE: {
6247         if (is_active_group_operation) {
6248           if (sw_enc_left) {
6249             sw_enc_left.reset();
6250           }
6251           if (sw_enc_right) {
6252             sw_enc_right.reset();
6253           }
6254           if (sw_dec_left) {
6255             sw_dec_left.reset();
6256           }
6257           if (sw_dec_right) {
6258             sw_dec_right.reset();
6259           }
6260           CleanCachedMicrophoneData();
6261         }
6262 
6263         if (group) {
6264           handleAsymmetricPhyForUnicast(group);
6265           UpdateLocationsAndContextsAvailability(group);
6266           if (!group->IsPendingConfiguration()) {
6267             if (is_active_group_operation) {
6268               if (sink_monitor_mode_) {
6269                 notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
6270               }
6271 
6272               if (source_monitor_mode_) {
6273                 notifyAudioLocalSource(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
6274               }
6275             }
6276           } else {
6277             if (!is_active_group_operation) {
6278               log::info("Clear pending configuration flag for group {}", group->group_id_);
6279               group->ClearPendingConfiguration();
6280             } else {
6281               log::debug(
6282                       "Pending configuration for group_id: {} pre_configuration_context_type_ : {} "
6283                       "-> "
6284                       "configuration_context_type_ {}",
6285                       group->group_id_, ToString(pre_configuration_context_type_),
6286                       ToString(configuration_context_type_));
6287               auto remote_direction =
6288                       kLeAudioContextAllRemoteSource.test(configuration_context_type_)
6289                               ? bluetooth::le_audio::types::kLeAudioDirectionSource
6290                               : bluetooth::le_audio::types::kLeAudioDirectionSink;
6291 
6292               /* Reconfiguration to non requiring source scenario */
6293               if (sink_monitor_mode_ &&
6294                   (remote_direction == bluetooth::le_audio::types::kLeAudioDirectionSink)) {
6295                 notifyAudioLocalSink(UnicastMonitorModeStatus::STREAMING_SUSPENDED);
6296               }
6297 
6298               auto remote_contexts =
6299                       DirectionalRealignMetadataAudioContexts(group, remote_direction);
6300               ApplyRemoteMetadataAudioContextPolicy(group, remote_contexts, remote_direction);
6301               log::verbose(
6302                       "Pending configuration 2 pre_configuration_context_type_ : {} -> "
6303                       "configuration_context_type_ {}",
6304                       ToString(pre_configuration_context_type_),
6305                       ToString(configuration_context_type_));
6306               if ((configuration_context_type_ != pre_configuration_context_type_) &&
6307                   GroupStream(group, configuration_context_type_, remote_contexts)) {
6308                 /* If configuration succeed wait for new status. */
6309                 return;
6310               }
6311               log::info("Clear pending configuration flag for group {}", group->group_id_);
6312               group->ClearPendingConfiguration();
6313               reconfigurationComplete();
6314             }
6315           }
6316         }
6317 
6318         speed_tracker_.Reset(group_id);
6319         if (is_active_group_operation) {
6320           CancelStreamingRequest();
6321         }
6322 
6323         if (group) {
6324           NotifyUpperLayerGroupTurnedIdleDuringCall(group->group_id_);
6325           HandlePendingDeviceRemove(group);
6326           HandlePendingDeviceDisconnection(group);
6327         }
6328         break;
6329       }
6330       case GroupStreamStatus::RELEASING_AUTONOMOUS:
6331         /* Remote device releases all the ASEs autonomusly. This should not happen and not sure what
6332          * is the remote device intention. If remote wants stop the stream then MCS shall be used to
6333          * stop the stream in a proper way. For a phone call, GTBS shall be used. For now we assume
6334          * this device has does not want to be used for streaming and mark it as Inactive.
6335          */
6336         log::warn("Group {} is doing autonomous release, make it inactive", group_id);
6337         if (group) {
6338           group->PrintDebugState();
6339           groupSetAndNotifyInactive();
6340         }
6341         audio_sender_state_ = AudioState::IDLE;
6342         audio_receiver_state_ = AudioState::IDLE;
6343         break;
6344       case GroupStreamStatus::RELEASING:
6345       case GroupStreamStatus::SUSPENDING:
6346         if (active_group_id_ != bluetooth::groups::kGroupUnknown &&
6347             (active_group_id_ == group->group_id_) && !group->IsPendingConfiguration() &&
6348             (audio_sender_state_ == AudioState::STARTED ||
6349              audio_receiver_state_ == AudioState::STARTED) &&
6350             group->GetTargetState() != AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {
6351           /* If releasing state is happening but it was not initiated either by
6352            * reconfiguration or Audio Framework actions either by the Active group change,
6353            * it means that it is some internal state machine error. This is very unlikely and
6354            * for now just Inactivate the group.
6355            */
6356           log::error("Internal state machine error for group {}", group_id);
6357           group->PrintDebugState();
6358           groupSetAndNotifyInactive();
6359           audio_sender_state_ = AudioState::IDLE;
6360           audio_receiver_state_ = AudioState::IDLE;
6361           return;
6362         }
6363 
6364         /* Releasing state shall be always set here, because we do support only single group
6365          * streaming at the time.  */
6366         if (audio_sender_state_ != AudioState::IDLE) {
6367           audio_sender_state_ = AudioState::RELEASING;
6368         }
6369 
6370         if (audio_receiver_state_ != AudioState::IDLE) {
6371           audio_receiver_state_ = AudioState::RELEASING;
6372         }
6373 
6374         if (is_active_group_operation) {
6375           if (group && group->IsPendingConfiguration()) {
6376             log::info("Releasing for reconfiguration, don't send anything on CISes");
6377             SuspendedForReconfiguration();
6378           }
6379         }
6380 
6381         break;
6382       default:
6383         break;
6384     }
6385   }
6386 
OnUpdatedCisConfiguration(int group_id,uint8_t direction)6387   void OnUpdatedCisConfiguration(int group_id, uint8_t direction) {
6388     LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
6389     if (!group) {
6390       log::error("Invalid group_id: {}", group_id);
6391       return;
6392     }
6393     group->UpdateCisConfiguration(direction);
6394   }
6395 
6396 private:
6397   tGATT_IF gatt_if_;
6398   bluetooth::le_audio::LeAudioClientCallbacks* callbacks_;
6399   LeAudioDevices leAudioDevices_;
6400   LeAudioDeviceGroups aseGroups_;
6401   LeAudioGroupStateMachine* groupStateMachine_;
6402   int active_group_id_;
6403   LeAudioContextType pre_configuration_context_type_;
6404   LeAudioContextType configuration_context_type_;
6405   static constexpr char kAllowMultipleContextsInMetadata[] =
6406           "persist.bluetooth.leaudio.allow.multiple.contexts";
6407   BidirectionalPair<AudioContexts> in_call_metadata_context_types_;
6408   BidirectionalPair<AudioContexts> local_metadata_context_types_;
6409   StreamSpeedTracker speed_tracker_;
6410   std::deque<StreamSpeedTracker> stream_speed_history_;
6411 
6412   /* Microphone (s) */
6413   AudioState audio_receiver_state_;
6414   /* Speaker(s) */
6415   AudioState audio_sender_state_;
6416   /* Keep in call state. */
6417   bool in_call_;
6418   bool in_voip_call_;
6419   /* Listen for streaming status on Sink stream */
6420   bool sink_monitor_mode_;
6421   /* Sink stream status which has been notified to Service */
6422   std::optional<UnicastMonitorModeStatus> sink_monitor_notified_status_;
6423   /* Listen for streaming status on Source stream */
6424   bool source_monitor_mode_;
6425   /* Source stream status which has been notified to Service */
6426   std::optional<UnicastMonitorModeStatus> source_monitor_notified_status_;
6427 
6428   /* Reconnection mode */
6429   tBTM_BLE_CONN_TYPE reconnection_mode_;
6430   static constexpr uint64_t kGroupConnectedWatchDelayMs = 3000;
6431   static constexpr uint64_t kRecoveryReconnectDelayMs = 2000;
6432   static constexpr uint64_t kAutoConnectAfterOwnDisconnectDelayMs = 1000;
6433   static constexpr uint64_t kCsisGroupMemberDelayMs = 5000;
6434 
6435   /* LeAudioHealthStatus */
6436   LeAudioHealthStatus* leAudioHealthStatus_ = nullptr;
6437 
6438   static constexpr char kNotifyUpperLayerAboutGroupBeingInIdleDuringCall[] =
6439           "persist.bluetooth.leaudio.notify.idle.during.call";
6440 
6441   static constexpr uint16_t kBapMinimumAttMtu = 64;
6442 
6443   /* Current stream configuration - used to set up the software codecs */
6444   LeAudioCodecConfiguration current_encoder_config_;
6445   LeAudioCodecConfiguration current_decoder_config_;
6446 
6447   /* Static Audio Framework session configuration.
6448    *  Resampling will be done inside the bt stack
6449    */
6450   LeAudioCodecConfiguration audio_framework_source_config = {
6451           .num_channels = 2,
6452           .sample_rate = bluetooth::audio::le_audio::kSampleRate48000,
6453           .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
6454           .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
6455   };
6456 
6457   LeAudioCodecConfiguration audio_framework_sink_config = {
6458           .num_channels = 2,
6459           .sample_rate = bluetooth::audio::le_audio::kSampleRate16000,
6460           .bits_per_sample = bluetooth::audio::le_audio::kBitsPerSample16,
6461           .data_interval_us = LeAudioCodecConfiguration::kInterval10000Us,
6462   };
6463 
6464   std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_enc_left;
6465   std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_enc_right;
6466 
6467   std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_dec_left;
6468   std::unique_ptr<bluetooth::le_audio::CodecInterface> sw_dec_right;
6469 
6470   std::vector<uint8_t> encoded_data;
6471   std::unique_ptr<LeAudioSourceAudioHalClient> le_audio_source_hal_client_;
6472   std::unique_ptr<LeAudioSinkAudioHalClient> le_audio_sink_hal_client_;
6473   static constexpr uint64_t kAudioSuspentKeepIsoAliveTimeoutMs = 500;
6474   static constexpr uint64_t kAudioDisableTimeoutMs = 3000;
6475   static constexpr char kAudioSuspentKeepIsoAliveTimeoutMsProp[] =
6476           "persist.bluetooth.leaudio.audio.suspend.timeoutms";
6477   static constexpr uint64_t kAudioReconfigurationTimeoutMs = 1500;
6478   alarm_t* close_vbc_timeout_;
6479   alarm_t* suspend_timeout_;
6480 
6481   /* Reconfiguration guard to make sure reconfigration is not broken by unexpected Metadata change.
6482    * When Reconfiguration is scheduled then
6483    * 1. BT stack remembers local directions which should be resumed after reconfiguration
6484    * 2. Blocks another reconfiguration until:
6485    *      a) all the reconfigured directions has been resumed
6486    *      b) reconfiguration timeout fires
6487    */
6488   alarm_t* reconfiguration_timeout_;
6489   int reconfiguration_group_ = bluetooth::groups::kGroupUnknown;
6490   uint8_t reconfiguration_local_directions_ = 0;
6491 
6492   alarm_t* disable_timer_;
6493   static constexpr uint64_t kDeviceAttachDelayMs = 500;
6494 
6495   uint32_t cached_channel_timestamp_ = 0;
6496   bluetooth::le_audio::CodecInterface* cached_channel_ = nullptr;
6497 
6498   base::WeakPtrFactory<LeAudioClientImpl> weak_factory_{this};
6499 
6500   std::map<int, GroupStreamStatus> lastNotifiedGroupStreamStatusMap_;
6501 
ClientAudioInterfaceRelease()6502   void ClientAudioInterfaceRelease() {
6503     auto group = aseGroups_.FindById(active_group_id_);
6504     if (!group) {
6505       log::error("Invalid group: {}", static_cast<int>(active_group_id_));
6506     } else {
6507       handleAsymmetricPhyForUnicast(group);
6508       log::info("ClientAudioInterfaceRelease - cleanup");
6509     }
6510 
6511     auto result = CodecManager::GetInstance()->UpdateActiveUnicastAudioHalClient(
6512             le_audio_source_hal_client_.get(), le_audio_sink_hal_client_.get(), false);
6513     log::assert_that(result, "Could not update session to codec manager");
6514 
6515     if (le_audio_source_hal_client_) {
6516       le_audio_source_hal_client_->Stop();
6517       le_audio_source_hal_client_.reset();
6518     }
6519 
6520     if (le_audio_sink_hal_client_) {
6521       /* Keep session set up to monitor streaming request. This is required if
6522        * there is another LE Audio device streaming (e.g. Broadcast) and via
6523        * the session callbacks special action from this Module would be
6524        * required e.g. to Unicast handover.
6525        */
6526       if (com::android::bluetooth::flags::leaudio_use_audio_recording_listener() ||
6527           !sink_monitor_mode_) {
6528         local_metadata_context_types_.sink.clear();
6529         le_audio_sink_hal_client_->Stop();
6530         le_audio_sink_hal_client_.reset();
6531       }
6532     }
6533 
6534     local_metadata_context_types_.source.clear();
6535     configuration_context_type_ = LeAudioContextType::UNINITIALIZED;
6536 
6537     bluetooth::le_audio::MetricsCollector::Get()->OnStreamEnded(active_group_id_);
6538   }
6539 
DsaDataConsume(bluetooth::hci::iso_manager::cis_data_evt * event)6540   bool DsaDataConsume(bluetooth::hci::iso_manager::cis_data_evt* event) {
6541     if (active_group_id_ == bluetooth::groups::kGroupUnknown) {
6542       return false;
6543     }
6544     LeAudioDeviceGroup* group = aseGroups_.FindById(active_group_id_);
6545     if (!group || !group->dsa_.active) {
6546       return false;
6547     }
6548 
6549     if (group->dsa_.mode != DsaMode::ISO_SW) {
6550       log::warn("ISO packets received over HCI in DSA mode: {}", group->dsa_.mode);
6551       return false;
6552     }
6553 
6554     if (iso_data_callback == nullptr) {
6555       log::warn("Dsa data consumer not registered");
6556       return false;
6557     }
6558 
6559     uint16_t cis_conn_hdl = event->cis_conn_hdl;
6560     uint8_t* data = event->p_msg->data + event->p_msg->offset;
6561     uint16_t size = event->p_msg->len - event->p_msg->offset;
6562     uint32_t timestamp = event->ts;
6563 
6564     // Find LE Audio device
6565     LeAudioDevice* leAudioDevice = group->GetFirstDevice();
6566     while (leAudioDevice != nullptr) {
6567       if (leAudioDevice->GetDsaCisHandle() == cis_conn_hdl &&
6568           leAudioDevice->GetDsaDataPathState() == DataPathState::CONFIGURED) {
6569         break;
6570       }
6571       leAudioDevice = group->GetNextDevice(leAudioDevice);
6572     }
6573     if (leAudioDevice == nullptr) {
6574       log::warn("No LE Audio device found for CIS handle: {}", cis_conn_hdl);
6575       return false;
6576     }
6577 
6578     bool consumed = iso_data_callback(leAudioDevice->address_, cis_conn_hdl, data, size, timestamp);
6579     if (consumed) {
6580       return true;
6581     } else {
6582       log::verbose("ISO data consumer not ready to accept data");
6583       return false;
6584     }
6585   }
6586 
SetAsymmetricBlePhy(LeAudioDeviceGroup * group,bool asymmetric)6587   void SetAsymmetricBlePhy(LeAudioDeviceGroup* group, bool asymmetric) {
6588     LeAudioDevice* leAudioDevice = group->GetFirstDevice();
6589     if (leAudioDevice == nullptr) {
6590       log::error("Shouldn't be called without a device.");
6591       return;
6592     }
6593 
6594     for (auto tmpDevice = leAudioDevice; tmpDevice != nullptr;
6595          tmpDevice = group->GetNextDevice(tmpDevice)) {
6596       log::info("tmpDevice->acl_asymmetric_: {}, asymmetric: {}, address: {}, acl_connected: {}",
6597                 tmpDevice->acl_asymmetric_ == asymmetric, asymmetric, tmpDevice->address_,
6598                 get_btm_client_interface().peer.BTM_IsAclConnectionUp(tmpDevice->address_,
6599                                                                       BT_TRANSPORT_LE));
6600       if (tmpDevice->acl_asymmetric_ == asymmetric ||
6601           !get_btm_client_interface().peer.BTM_IsAclConnectionUp(tmpDevice->address_,
6602                                                                  BT_TRANSPORT_LE)) {
6603         continue;
6604       }
6605 
6606       log::info("SetAsymmetricBlePhy: {} for {}", asymmetric, tmpDevice->address_);
6607       get_btm_client_interface().ble.BTM_BleSetPhy(tmpDevice->address_, PHY_LE_2M,
6608                                                    asymmetric ? PHY_LE_1M : PHY_LE_2M, 0);
6609       tmpDevice->acl_asymmetric_ = asymmetric;
6610     }
6611   }
6612 };
6613 
le_audio_health_status_callback(const RawAddress & addr,int group_id,LeAudioHealthBasedAction action)6614 static void le_audio_health_status_callback(const RawAddress& addr, int group_id,
6615                                             LeAudioHealthBasedAction action) {
6616   if (instance) {
6617     instance->LeAudioHealthSendRecommendation(addr, group_id, action);
6618   }
6619 }
6620 
6621 /* This is a generic callback method for gatt client which handles every client
6622  * application events.
6623  */
le_audio_gattc_callback(tBTA_GATTC_EVT event,tBTA_GATTC * p_data)6624 void le_audio_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
6625   if (!p_data || !instance) {
6626     return;
6627   }
6628 
6629   log::info("event = {}", static_cast<int>(event));
6630 
6631   switch (event) {
6632     case BTA_GATTC_DEREG_EVT:
6633       break;
6634 
6635     case BTA_GATTC_NOTIF_EVT:
6636       instance->LeAudioCharValueHandle(p_data->notify.conn_id, p_data->notify.handle,
6637                                        p_data->notify.len,
6638                                        static_cast<uint8_t*>(p_data->notify.value), true);
6639 
6640       if (!p_data->notify.is_notify) {
6641         BTA_GATTC_SendIndConfirm(p_data->notify.conn_id, p_data->notify.handle);
6642       }
6643 
6644       break;
6645 
6646     case BTA_GATTC_OPEN_EVT:
6647       instance->OnGattConnected(p_data->open.status, p_data->open.conn_id, p_data->open.client_if,
6648                                 p_data->open.remote_bda, p_data->open.transport, p_data->open.mtu);
6649       break;
6650 
6651     case BTA_GATTC_ENC_CMPL_CB_EVT: {
6652       tBTM_STATUS encryption_status;
6653       if (BTM_IsEncrypted(p_data->enc_cmpl.remote_bda, BT_TRANSPORT_LE)) {
6654         encryption_status = tBTM_STATUS::BTM_SUCCESS;
6655       } else {
6656         encryption_status = tBTM_STATUS::BTM_FAILED_ON_SECURITY;
6657       }
6658       instance->OnEncryptionComplete(p_data->enc_cmpl.remote_bda, encryption_status);
6659     } break;
6660 
6661     case BTA_GATTC_CLOSE_EVT:
6662       instance->OnGattDisconnected(p_data->close.conn_id, p_data->close.client_if,
6663                                    p_data->close.remote_bda, p_data->close.reason);
6664       break;
6665 
6666     case BTA_GATTC_SEARCH_CMPL_EVT:
6667       instance->OnServiceSearchComplete(p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
6668       break;
6669 
6670     case BTA_GATTC_SRVC_DISC_DONE_EVT:
6671       instance->OnGattServiceDiscoveryDone(p_data->service_discovery_done.remote_bda);
6672       break;
6673 
6674     case BTA_GATTC_SRVC_CHG_EVT:
6675       instance->OnServiceChangeEvent(p_data->service_changed.remote_bda);
6676       break;
6677     case BTA_GATTC_CFG_MTU_EVT:
6678       instance->OnMtuChanged(p_data->cfg_mtu.conn_id, p_data->cfg_mtu.mtu);
6679       break;
6680     case BTA_GATTC_PHY_UPDATE_EVT:
6681       instance->OnPhyUpdate(p_data->phy_update.conn_id, p_data->phy_update.tx_phy,
6682                             p_data->phy_update.rx_phy, p_data->phy_update.status);
6683       break;
6684     default:
6685       break;
6686   }
6687 }
6688 
6689 class LeAudioStateMachineHciCallbacksImpl : public CigCallbacks {
6690 public:
OnCigEvent(uint8_t event,void * data)6691   void OnCigEvent(uint8_t event, void* data) override {
6692     if (instance) {
6693       instance->IsoCigEventsCb(event, data);
6694     }
6695   }
6696 
OnCisEvent(uint8_t event,void * data)6697   void OnCisEvent(uint8_t event, void* data) override {
6698     if (instance) {
6699       instance->IsoCisEventsCb(event, data);
6700     }
6701   }
6702 
OnSetupIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t cig_id)6703   void OnSetupIsoDataPath(uint8_t status, uint16_t conn_handle, uint8_t cig_id) override {
6704     if (instance) {
6705       instance->IsoSetupIsoDataPathCb(status, conn_handle, cig_id);
6706     }
6707   }
6708 
OnRemoveIsoDataPath(uint8_t status,uint16_t conn_handle,uint8_t cig_id)6709   void OnRemoveIsoDataPath(uint8_t status, uint16_t conn_handle, uint8_t cig_id) override {
6710     if (instance) {
6711       instance->IsoRemoveIsoDataPathCb(status, conn_handle, cig_id);
6712     }
6713   }
6714 
OnIsoLinkQualityRead(uint8_t conn_handle,uint8_t cig_id,uint32_t txUnackedPackets,uint32_t txFlushedPackets,uint32_t txLastSubeventPackets,uint32_t retransmittedPackets,uint32_t crcErrorPackets,uint32_t rxUnreceivedPackets,uint32_t duplicatePackets)6715   void OnIsoLinkQualityRead(uint8_t conn_handle, uint8_t cig_id, uint32_t txUnackedPackets,
6716                             uint32_t txFlushedPackets, uint32_t txLastSubeventPackets,
6717                             uint32_t retransmittedPackets, uint32_t crcErrorPackets,
6718                             uint32_t rxUnreceivedPackets, uint32_t duplicatePackets) {
6719     if (instance) {
6720       instance->IsoLinkQualityReadCb(conn_handle, cig_id, txUnackedPackets, txFlushedPackets,
6721                                      txLastSubeventPackets, retransmittedPackets, crcErrorPackets,
6722                                      rxUnreceivedPackets, duplicatePackets);
6723     }
6724   }
6725 };
6726 
6727 LeAudioStateMachineHciCallbacksImpl stateMachineHciCallbacksImpl;
6728 
6729 class CallbacksImpl : public LeAudioGroupStateMachine::Callbacks {
6730 public:
StatusReportCb(int group_id,GroupStreamStatus status)6731   void StatusReportCb(int group_id, GroupStreamStatus status) override {
6732     if (instance) {
6733       instance->OnStateMachineStatusReportCb(group_id, status);
6734     }
6735   }
6736 
OnStateTransitionTimeout(int group_id)6737   void OnStateTransitionTimeout(int group_id) override {
6738     if (instance) {
6739       instance->OnLeAudioDeviceSetStateTimeout(group_id);
6740     }
6741   }
6742 
OnUpdatedCisConfiguration(int group_id,uint8_t direction)6743   void OnUpdatedCisConfiguration(int group_id, uint8_t direction) {
6744     if (instance) {
6745       instance->OnUpdatedCisConfiguration(group_id, direction);
6746     }
6747   }
6748 };
6749 
6750 CallbacksImpl stateMachineCallbacksImpl;
6751 
6752 class SourceCallbacksImpl : public LeAudioSourceAudioHalClient::Callbacks {
6753 public:
OnAudioDataReady(const std::vector<uint8_t> & data)6754   void OnAudioDataReady(const std::vector<uint8_t>& data) override {
6755     if (instance) {
6756       instance->OnAudioDataReady(data);
6757     }
6758   }
OnAudioSuspend(void)6759   void OnAudioSuspend(void) override {
6760     if (instance) {
6761       instance->OnLocalAudioSourceSuspend();
6762     }
6763   }
6764 
OnAudioResume(void)6765   void OnAudioResume(void) override {
6766     if (instance) {
6767       instance->OnLocalAudioSourceResume();
6768     }
6769   }
6770 
OnAudioMetadataUpdate(std::vector<struct playback_track_metadata_v7> source_metadata,DsaMode dsa_mode)6771   void OnAudioMetadataUpdate(std::vector<struct playback_track_metadata_v7> source_metadata,
6772                              DsaMode dsa_mode) override {
6773     if (instance) {
6774       instance->OnLocalAudioSourceMetadataUpdate(source_metadata, dsa_mode);
6775     }
6776   }
6777 };
6778 
6779 class SinkCallbacksImpl : public LeAudioSinkAudioHalClient::Callbacks {
6780 public:
OnAudioSuspend(void)6781   void OnAudioSuspend(void) override {
6782     if (instance) {
6783       instance->OnLocalAudioSinkSuspend();
6784     }
6785   }
OnAudioResume(void)6786   void OnAudioResume(void) override {
6787     if (instance) {
6788       instance->OnLocalAudioSinkResume();
6789     }
6790   }
6791 
OnAudioMetadataUpdate(std::vector<record_track_metadata_v7> sink_metadata)6792   void OnAudioMetadataUpdate(std::vector<record_track_metadata_v7> sink_metadata) override {
6793     if (instance) {
6794       instance->OnLocalAudioSinkMetadataUpdate(sink_metadata);
6795     }
6796   }
6797 };
6798 
6799 SourceCallbacksImpl audioSinkReceiverImpl;
6800 SinkCallbacksImpl audioSourceReceiverImpl;
6801 
6802 class DeviceGroupsCallbacksImpl : public DeviceGroupsCallbacks {
6803 public:
OnGroupAdded(const RawAddress & address,const bluetooth::Uuid & uuid,int group_id)6804   void OnGroupAdded(const RawAddress& address, const bluetooth::Uuid& uuid, int group_id) override {
6805     if (instance) {
6806       instance->OnGroupAddedCb(address, uuid, group_id);
6807     }
6808   }
OnGroupMemberAdded(const RawAddress & address,int group_id)6809   void OnGroupMemberAdded(const RawAddress& address, int group_id) override {
6810     if (instance) {
6811       instance->OnGroupMemberAddedCb(address, group_id);
6812     }
6813   }
OnGroupMemberRemoved(const RawAddress & address,int group_id)6814   void OnGroupMemberRemoved(const RawAddress& address, int group_id) override {
6815     if (instance) {
6816       instance->OnGroupMemberRemovedCb(address, group_id);
6817     }
6818   }
OnGroupRemoved(const bluetooth::Uuid &,int)6819   void OnGroupRemoved(const bluetooth::Uuid& /*uuid*/,
6820                       int /*group_id*/) { /* to implement if needed */ }
OnGroupAddFromStorage(const RawAddress &,const bluetooth::Uuid &,int)6821   void OnGroupAddFromStorage(const RawAddress& /*address*/, const bluetooth::Uuid& /*uuid*/,
6822                              int /*group_id*/) {
6823     /* to implement if needed */
6824   }
6825 };
6826 
6827 class DeviceGroupsCallbacksImpl;
6828 DeviceGroupsCallbacksImpl deviceGroupsCallbacksImpl;
6829 
6830 }  // namespace
6831 
AddFromStorage(const RawAddress & addr,bool autoconnect,std::optional<int> sink_audio_location,std::optional<int> source_audio_location,int sink_supported_context_types,int source_supported_context_types,const std::vector<uint8_t> & handles,const std::vector<uint8_t> & sink_pacs,const std::vector<uint8_t> & source_pacs,const std::vector<uint8_t> & ases,const std::vector<uint8_t> & gmap)6832 void LeAudioClient::AddFromStorage(
6833         const RawAddress& addr, bool autoconnect, std::optional<int> sink_audio_location,
6834         std::optional<int> source_audio_location, int sink_supported_context_types,
6835         int source_supported_context_types, const std::vector<uint8_t>& handles,
6836         const std::vector<uint8_t>& sink_pacs, const std::vector<uint8_t>& source_pacs,
6837         const std::vector<uint8_t>& ases, const std::vector<uint8_t>& gmap) {
6838   if (!instance) {
6839     log::error("Not initialized yet");
6840     return;
6841   }
6842 
6843   instance->AddFromStorage(addr, autoconnect, sink_audio_location, source_audio_location,
6844                            sink_supported_context_types, source_supported_context_types, handles,
6845                            sink_pacs, source_pacs, ases, gmap);
6846 }
6847 
GetHandlesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6848 bool LeAudioClient::GetHandlesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6849   if (!instance) {
6850     log::error("Not initialized yet");
6851     return false;
6852   }
6853 
6854   return instance->GetHandlesForStorage(addr, out);
6855 }
6856 
GetSinkPacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6857 bool LeAudioClient::GetSinkPacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6858   if (!instance) {
6859     log::error("Not initialized yet");
6860     return false;
6861   }
6862 
6863   return instance->GetSinkPacsForStorage(addr, out);
6864 }
6865 
GetSourcePacsForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6866 bool LeAudioClient::GetSourcePacsForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6867   if (!instance) {
6868     log::error("Not initialized yet");
6869     return false;
6870   }
6871 
6872   return instance->GetSourcePacsForStorage(addr, out);
6873 }
6874 
GetAsesForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6875 bool LeAudioClient::GetAsesForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6876   if (!instance) {
6877     log::error("Not initialized yet");
6878     return false;
6879   }
6880 
6881   return instance->GetAsesForStorage(addr, out);
6882 }
6883 
GetGmapForStorage(const RawAddress & addr,std::vector<uint8_t> & out)6884 bool LeAudioClient::GetGmapForStorage(const RawAddress& addr, std::vector<uint8_t>& out) {
6885   if (!instance) {
6886     log::error("Not initialized yet");
6887     return false;
6888   }
6889 
6890   return instance->GetGmapForStorage(addr, out);
6891 }
6892 
IsLeAudioClientRunning(void)6893 bool LeAudioClient::IsLeAudioClientRunning(void) { return instance != nullptr; }
6894 
IsLeAudioClientInStreaming(void)6895 bool LeAudioClient::IsLeAudioClientInStreaming(void) {
6896   if (!instance) {
6897     return false;
6898   }
6899   return instance->IsInStreaming();
6900 }
6901 
Get()6902 LeAudioClient* LeAudioClient::Get() {
6903   log::assert_that(instance != nullptr, "assert failed: instance != nullptr");
6904   return instance;
6905 }
6906 
6907 /* Initializer of main le audio implementation class and its instance */
Initialize(bluetooth::le_audio::LeAudioClientCallbacks * callbacks_,base::Closure initCb,base::Callback<bool ()> hal_2_1_verifier,const std::vector<bluetooth::le_audio::btle_audio_codec_config_t> & offloading_preference)6908 void LeAudioClient::Initialize(
6909         bluetooth::le_audio::LeAudioClientCallbacks* callbacks_, base::Closure initCb,
6910         base::Callback<bool()> hal_2_1_verifier,
6911         const std::vector<bluetooth::le_audio::btle_audio_codec_config_t>& offloading_preference) {
6912   std::scoped_lock<std::mutex> lock(instance_mutex);
6913   if (instance) {
6914     log::error("Already initialized");
6915     return;
6916   }
6917 
6918   if (!bluetooth::shim::GetController()->SupportsBleConnectedIsochronousStreamCentral() &&
6919       !bluetooth::shim::GetController()->SupportsBleConnectedIsochronousStreamPeripheral()) {
6920     log::error("Controller reports no ISO support. LeAudioClient Init aborted.");
6921     return;
6922   }
6923 
6924   log::assert_that(std::move(hal_2_1_verifier).Run(),
6925                    "LE Audio Client requires Bluetooth Audio HAL V2.1 at least. Either "
6926                    "disable LE Audio Profile, or update your HAL");
6927 
6928   IsoManager::GetInstance()->Start();
6929 
6930   audioSinkReceiver = &audioSinkReceiverImpl;
6931   audioSourceReceiver = &audioSourceReceiverImpl;
6932   stateMachineHciCallbacks = &stateMachineHciCallbacksImpl;
6933   stateMachineCallbacks = &stateMachineCallbacksImpl;
6934   device_group_callbacks = &deviceGroupsCallbacksImpl;
6935   instance = new LeAudioClientImpl(callbacks_, stateMachineCallbacks, initCb);
6936 
6937   IsoManager::GetInstance()->RegisterCigCallbacks(stateMachineHciCallbacks);
6938   CodecManager::GetInstance()->Start(offloading_preference);
6939   ContentControlIdKeeper::GetInstance()->Start();
6940 
6941   callbacks_->OnInitialized();
6942 
6943   auto cm = CodecManager::GetInstance();
6944   callbacks_->OnAudioLocalCodecCapabilities(cm->GetLocalAudioInputCodecCapa(),
6945                                             cm->GetLocalAudioOutputCodecCapa());
6946 
6947   if (GmapServer::IsGmapServerEnabled()) {
6948     std::bitset<8> UGG_feature = GmapServer::GetUGGFeature();
6949 
6950     auto input_capabilities = cm->GetLocalAudioOutputCodecCapa();
6951     for (auto& capa : input_capabilities) {
6952       if (capa.sample_rate == bluetooth::le_audio::LE_AUDIO_SAMPLE_RATE_INDEX_48000HZ) {
6953         UGG_feature |= static_cast<uint8_t>(
6954                 bluetooth::gmap::UGGFeatureBitMask::NinetySixKbpsSourceFeatureSupport);
6955         break;
6956       }
6957     }
6958 
6959     auto output_capabilities = cm->GetLocalAudioOutputCodecCapa();
6960     for (auto& capa : output_capabilities) {
6961       if (capa.channel_count > bluetooth::le_audio::LE_AUDIO_CHANNEL_COUNT_INDEX_1) {
6962         UGG_feature |=
6963                 static_cast<uint8_t>(bluetooth::gmap::UGGFeatureBitMask::MultiplexFeatureSupport);
6964         break;
6965       }
6966     }
6967     GmapServer::Initialize(UGG_feature);
6968   }
6969 }
6970 
DebugDump(int fd)6971 void LeAudioClient::DebugDump(int fd) {
6972   std::scoped_lock<std::mutex> lock(instance_mutex);
6973   DeviceGroups::DebugDump(fd);
6974   GmapServer::DebugDump(fd);
6975 
6976   dprintf(fd, "LeAudio Manager: \n");
6977   if (instance) {
6978     instance->Dump(fd);
6979   } else {
6980     dprintf(fd, "  Not initialized \n");
6981   }
6982 
6983   LeAudioSinkAudioHalClient::DebugDump(fd);
6984   LeAudioSourceAudioHalClient::DebugDump(fd);
6985   IsoManager::GetInstance()->Dump(fd);
6986   LeAudioLogHistory::DebugDump(fd);
6987   dprintf(fd, "\n");
6988 }
6989 
Cleanup(void)6990 void LeAudioClient::Cleanup(void) {
6991   std::scoped_lock<std::mutex> lock(instance_mutex);
6992   if (!instance) {
6993     log::error("Not initialized");
6994     return;
6995   }
6996 
6997   LeAudioClientImpl* ptr = instance;
6998   instance = nullptr;
6999   ptr->Cleanup();
7000   delete ptr;
7001   ptr = nullptr;
7002 
7003   CodecManager::GetInstance()->Stop();
7004   ContentControlIdKeeper::GetInstance()->Stop();
7005   LeAudioGroupStateMachine::Cleanup();
7006 
7007   if (!LeAudioBroadcaster::IsLeAudioBroadcasterRunning()) {
7008     IsoManager::GetInstance()->Stop();
7009   }
7010 
7011   bluetooth::le_audio::MetricsCollector::Get()->Flush();
7012 }
7013 
RegisterIsoDataConsumer(LeAudioIsoDataCallback callback)7014 bool LeAudioClient::RegisterIsoDataConsumer(LeAudioIsoDataCallback callback) {
7015   log::info("ISO data consumer changed");
7016   iso_data_callback = callback;
7017   return true;
7018 }
7019