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 "state_machine.h"
19 
20 #include <bluetooth/log.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include <log/log.h>
24 
25 #include <functional>
26 
27 #include "bta/le_audio/content_control_id_keeper.h"
28 #include "bta_gatt_api_mock.h"
29 #include "bta_gatt_queue_mock.h"
30 #include "btm_api_mock.h"
31 #include "client_parser.h"
32 #include "fake_osi.h"
33 #include "hci/controller_interface_mock.h"
34 #include "internal_include/stack_config.h"
35 #include "le_audio/le_audio_types.h"
36 #include "le_audio_set_configuration_provider.h"
37 #include "mock_codec_manager.h"
38 #include "mock_csis_client.h"
39 #include "stack/include/bt_types.h"
40 #include "test/common/mock_functions.h"
41 #include "test/mock/mock_main_shim_entry.h"
42 #include "test/mock/mock_stack_btm_iso.h"
43 #include "types/bt_transport.h"
44 
45 // TODO(b/369381361) Enfore -Wmissing-prototypes
46 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
47 
48 using ::bluetooth::le_audio::DeviceConnectState;
49 using ::bluetooth::le_audio::codec_spec_caps::kLeAudioCodecChannelCountSingleChannel;
50 using ::bluetooth::le_audio::codec_spec_caps::kLeAudioCodecChannelCountTwoChannel;
51 using ::bluetooth::le_audio::types::LeAudioContextType;
52 using ::testing::_;
53 using ::testing::AnyNumber;
54 using ::testing::AtLeast;
55 using ::testing::DoAll;
56 using ::testing::Invoke;
57 using ::testing::NiceMock;
58 using ::testing::Return;
59 using ::testing::SaveArg;
60 using ::testing::Test;
61 
62 extern struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_;
63 
64 void osi_property_set_bool(const char* key, bool value);
65 
66 constexpr uint8_t media_ccid = 0xC0;
67 constexpr auto media_context = LeAudioContextType::MEDIA;
68 
69 constexpr uint8_t call_ccid = 0xD0;
70 constexpr auto call_context = LeAudioContextType::CONVERSATIONAL;
71 
72 const std::string kSmpOptions("mock smp options");
get_pts_avrcp_test(void)73 bool get_pts_avrcp_test(void) { return false; }
get_pts_secure_only_mode(void)74 bool get_pts_secure_only_mode(void) { return false; }
get_pts_conn_updates_disabled(void)75 bool get_pts_conn_updates_disabled(void) { return false; }
get_pts_crosskey_sdp_disable(void)76 bool get_pts_crosskey_sdp_disable(void) { return false; }
get_pts_smp_options(void)77 const std::string* get_pts_smp_options(void) { return &kSmpOptions; }
get_pts_smp_failure_case(void)78 int get_pts_smp_failure_case(void) { return 123; }
get_pts_force_eatt_for_notifications(void)79 bool get_pts_force_eatt_for_notifications(void) { return false; }
get_pts_connect_eatt_unconditionally(void)80 bool get_pts_connect_eatt_unconditionally(void) { return false; }
get_pts_connect_eatt_before_encryption(void)81 bool get_pts_connect_eatt_before_encryption(void) { return false; }
get_pts_unencrypt_broadcast(void)82 bool get_pts_unencrypt_broadcast(void) { return false; }
get_pts_eatt_peripheral_collision_support(void)83 bool get_pts_eatt_peripheral_collision_support(void) { return false; }
get_pts_force_le_audio_multiple_contexts_metadata(void)84 bool get_pts_force_le_audio_multiple_contexts_metadata(void) { return false; }
get_pts_le_audio_disable_ases_before_stopping(void)85 bool get_pts_le_audio_disable_ases_before_stopping(void) { return false; }
get_all(void)86 config_t* get_all(void) { return nullptr; }
87 
88 stack_config_t mock_stack_config{
89         .get_pts_avrcp_test = get_pts_avrcp_test,
90         .get_pts_secure_only_mode = get_pts_secure_only_mode,
91         .get_pts_conn_updates_disabled = get_pts_conn_updates_disabled,
92         .get_pts_crosskey_sdp_disable = get_pts_crosskey_sdp_disable,
93         .get_pts_smp_options = get_pts_smp_options,
94         .get_pts_smp_failure_case = get_pts_smp_failure_case,
95         .get_pts_force_eatt_for_notifications = get_pts_force_eatt_for_notifications,
96         .get_pts_connect_eatt_unconditionally = get_pts_connect_eatt_unconditionally,
97         .get_pts_connect_eatt_before_encryption = get_pts_connect_eatt_before_encryption,
98         .get_pts_unencrypt_broadcast = get_pts_unencrypt_broadcast,
99         .get_pts_eatt_peripheral_collision_support = get_pts_eatt_peripheral_collision_support,
100         .get_pts_force_le_audio_multiple_contexts_metadata =
101                 get_pts_force_le_audio_multiple_contexts_metadata,
102         .get_pts_le_audio_disable_ases_before_stopping =
103                 get_pts_le_audio_disable_ases_before_stopping,
104         .get_all = get_all,
105 };
stack_config_get_interface(void)106 const stack_config_t* stack_config_get_interface(void) { return &mock_stack_config; }
107 
108 namespace bluetooth::le_audio {
109 namespace internal {
110 
111 // Just some arbitrary initial handles - it has no real meaning
112 #define ATTR_HANDLE_ASCS_POOL_START (0x0000 | 32)
113 #define ATTR_HANDLE_PACS_POOL_START (0xFF00 | 64)
114 
115 constexpr LeAudioContextType kContextTypeUnspecified = static_cast<LeAudioContextType>(0x0001);
116 constexpr LeAudioContextType kContextTypeConversational = static_cast<LeAudioContextType>(0x0002);
117 constexpr LeAudioContextType kContextTypeMedia = static_cast<LeAudioContextType>(0x0004);
118 constexpr LeAudioContextType kContextTypeLive = static_cast<LeAudioContextType>(0x0040);
119 constexpr LeAudioContextType kContextTypeSoundEffects = static_cast<LeAudioContextType>(0x0080);
120 constexpr LeAudioContextType kContextTypeRingtone = static_cast<LeAudioContextType>(0x0200);
121 
122 namespace codec_specific {
123 
124 constexpr uint8_t kLc3CodingFormat = 0x06;
125 
126 // Reference Codec Capabilities values to test against
127 constexpr uint8_t kCapTypeSupportedSamplingFrequencies = 0x01;
128 constexpr uint8_t kCapTypeSupportedFrameDurations = 0x02;
129 constexpr uint8_t kCapTypeAudioChannelCount = 0x03;
130 constexpr uint8_t kCapTypeSupportedOctetsPerCodecFrame = 0x04;
131 constexpr uint8_t kCapTypeSupportedLc3CodecFramesPerSdu = 0x05;
132 
133 // constexpr uint8_t kCapSamplingFrequency8000Hz = 0x0001;
134 // constexpr uint8_t kCapSamplingFrequency11025Hz = 0x0002;
135 constexpr uint8_t kCapSamplingFrequency16000Hz = 0x0004;
136 // constexpr uint8_t kCapSamplingFrequency22050Hz = 0x0008;
137 // constexpr uint8_t kCapSamplingFrequency24000Hz = 0x0010;
138 constexpr uint8_t kCapSamplingFrequency32000Hz = 0x0020;
139 // constexpr uint8_t kCapSamplingFrequency44100Hz = 0x0040;
140 constexpr uint8_t kCapSamplingFrequency48000Hz = 0x0080;
141 // constexpr uint8_t kCapSamplingFrequency88200Hz = 0x0100;
142 // constexpr uint8_t kCapSamplingFrequency96000Hz = 0x0200;
143 // constexpr uint8_t kCapSamplingFrequency176400Hz = 0x0400;
144 // constexpr uint8_t kCapSamplingFrequency192000Hz = 0x0800;
145 // constexpr uint8_t kCapSamplingFrequency384000Hz = 0x1000;
146 
147 constexpr uint8_t kCapFrameDuration7p5ms = 0x01;
148 constexpr uint8_t kCapFrameDuration10ms = 0x02;
149 // constexpr uint8_t kCapFrameDuration7p5msPreferred = 0x10;
150 constexpr uint8_t kCapFrameDuration10msPreferred = 0x20;
151 }  // namespace codec_specific
152 
153 namespace ascs {
154 constexpr uint8_t kAseStateIdle = 0x00;
155 constexpr uint8_t kAseStateCodecConfigured = 0x01;
156 constexpr uint8_t kAseStateQoSConfigured = 0x02;
157 constexpr uint8_t kAseStateEnabling = 0x03;
158 constexpr uint8_t kAseStateStreaming = 0x04;
159 constexpr uint8_t kAseStateDisabling = 0x05;
160 constexpr uint8_t kAseStateReleasing = 0x06;
161 
162 // constexpr uint8_t kAseParamDirectionServerIsAudioSink = 0x01;
163 // constexpr uint8_t kAseParamDirectionServerIsAudioSource = 0x02;
164 
165 constexpr uint8_t kAseParamFramingUnframedSupported = 0x00;
166 // constexpr uint8_t kAseParamFramingUnframedNotSupported = 0x01;
167 
168 // constexpr uint8_t kAseParamPreferredPhy1M = 0x01;
169 // constexpr uint8_t kAseParamPreferredPhy2M = 0x02;
170 // constexpr uint8_t kAseParamPreferredPhyCoded = 0x04;
171 
172 constexpr uint8_t kAseCtpOpcodeMaxVal = client_parser::ascs::kCtpOpcodeRelease;
173 
174 }  // namespace ascs
175 
GetTestAddress(uint8_t index)176 static RawAddress GetTestAddress(uint8_t index) { return {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}}; }
177 
178 class MockLeAudioGroupStateMachineCallbacks : public LeAudioGroupStateMachine::Callbacks {
179 public:
180   MockLeAudioGroupStateMachineCallbacks() = default;
181   MockLeAudioGroupStateMachineCallbacks(const MockLeAudioGroupStateMachineCallbacks&) = delete;
182   MockLeAudioGroupStateMachineCallbacks& operator=(const MockLeAudioGroupStateMachineCallbacks&) =
183           delete;
184 
185   ~MockLeAudioGroupStateMachineCallbacks() override = default;
186   MOCK_METHOD((void), StatusReportCb, (int group_id, bluetooth::le_audio::GroupStreamStatus status),
187               (override));
188   MOCK_METHOD((void), OnStateTransitionTimeout, (int group_id), (override));
189   MOCK_METHOD((void), OnUpdatedCisConfiguration, (int group_id, uint8_t direction), (override));
190 };
191 
192 class MockAseRemoteStateMachine {
193 public:
194   MockAseRemoteStateMachine() = default;
195   MockAseRemoteStateMachine& operator=(const MockAseRemoteStateMachine&) = delete;
196   ~MockAseRemoteStateMachine() = default;
197   MOCK_METHOD((void), AseCtpConfigureCodecHandler,
198               (LeAudioDevice * device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
199                void* cb_data));
200   MOCK_METHOD((void), AseCtpConfigureQosHandler,
201               (LeAudioDevice * device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
202                void* cb_data));
203   MOCK_METHOD((void), AseCtpEnableHandler,
204               (LeAudioDevice * device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
205                void* cb_data));
206   MOCK_METHOD((void), AseCtpReceiverStartReadyHandler,
207               (LeAudioDevice * device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
208                void* cb_data));
209   MOCK_METHOD((void), AseCtpDisableHandler,
210               (LeAudioDevice * device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
211                void* cb_data));
212   MOCK_METHOD((void), AseCtpReceiverStopReadyHandler,
213               (LeAudioDevice * device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
214                void* cb_data));
215   MOCK_METHOD((void), AseCtpUpdateMetadataHandler,
216               (LeAudioDevice * device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
217                void* cb_data));
218   MOCK_METHOD((void), AseCtpReleaseHandler,
219               (LeAudioDevice * device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
220                void* cb_data));
221 };
222 
223 class StateMachineTestBase : public Test {
224 protected:
225   uint8_t ase_id_last_assigned = types::ase::kAseIdInvalid;
226   uint8_t additional_snk_ases = 0;
227   uint8_t additional_src_ases = 0;
228   uint8_t channel_count_ = kLeAudioCodecChannelCountSingleChannel;
229   uint8_t codec_frame_blocks_per_sdu_ = 1;
230   uint16_t sample_freq_ = codec_specific::kCapSamplingFrequency16000Hz |
231                           codec_specific::kCapSamplingFrequency32000Hz;
232   uint8_t channel_allocations_sink_ =
233           ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
234           ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
235   uint8_t channel_allocations_source_ =
236           ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
237           ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
238 
239   /* Use to simulated error status on Cis creation */
240   bool overwrite_cis_status_;
241   bool use_cis_retry_cnt_;
242   int retry_cis_established_cnt_;
243   bool do_not_send_cis_establish_event_;
244   bool do_not_send_cis_disconnected_event_;
245   uint8_t overwrite_cis_status_idx_;
246   std::vector<uint8_t> cis_status_;
247 
248   /* Keep ASE in releasing state */
249   bool stay_in_releasing_state_;
250 
251   /* Use for single test to simulate late ASE notifications */
252   bool stop_inject_configured_ase_after_first_ase_configured_;
253 
254   uint16_t pacs_attr_handle_next = ATTR_HANDLE_PACS_POOL_START;
255 
SetUp()256   virtual void SetUp() override {
257     __android_log_set_minimum_priority(ANDROID_LOG_DEBUG);
258     reset_mock_function_count_map();
259     bluetooth::manager::SetMockBtmInterface(&btm_interface);
260     gatt::SetMockBtaGattInterface(&gatt_interface);
261     gatt::SetMockBtaGattQueue(&gatt_queue);
262     bluetooth::hci::testing::mock_controller_ = &controller_;
263 
264     overwrite_cis_status_idx_ = 0;
265     use_cis_retry_cnt_ = false;
266     retry_cis_established_cnt_ = 0;
267     overwrite_cis_status_ = false;
268     do_not_send_cis_establish_event_ = false;
269     do_not_send_cis_disconnected_event_ = false;
270     stay_in_releasing_state_ = false;
271     stop_inject_configured_ase_after_first_ase_configured_ = false;
272     cis_status_.clear();
273 
274     LeAudioGroupStateMachine::Initialize(&mock_callbacks_);
275 
276     ContentControlIdKeeper::GetInstance()->Start();
277 
278     ON_CALL(mock_callbacks_, StatusReportCb(_, _))
279             .WillByDefault(Invoke([](int group_id, bluetooth::le_audio::GroupStreamStatus status) {
280               log::debug("[Testing] StatusReportCb: group id: {}, status: {}", group_id, status);
281             }));
282 
283     MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
284     ON_CALL(mock_csis_client_module_, Get()).WillByDefault(Return(&mock_csis_client_module_));
285     ON_CALL(mock_csis_client_module_, IsCsisClientRunning()).WillByDefault(Return(true));
286     ON_CALL(mock_csis_client_module_, GetDeviceList(_))
287             .WillByDefault(Invoke([this](int /*group_id*/) { return addresses_; }));
288     ON_CALL(mock_csis_client_module_, GetDesiredSize(_))
289             .WillByDefault(Invoke([this](int /*group_id*/) { return (int)(addresses_.size()); }));
290 
291     // Support 2M Phy
292     ON_CALL(btm_interface, IsPhy2mSupported(_, _)).WillByDefault(Return(true));
293     ON_CALL(btm_interface, GetHCIConnHandle(_, _))
294             .WillByDefault(Invoke([](RawAddress const& remote_bda, tBT_TRANSPORT /*transport*/) {
295               return remote_bda.IsEmpty()
296                              ? HCI_INVALID_HANDLE
297                              : ((uint16_t)(remote_bda.address[0] ^ remote_bda.address[1] ^
298                                            remote_bda.address[2]))
299                                                << 8 |
300                                        (remote_bda.address[3] ^ remote_bda.address[4] ^
301                                         remote_bda.address[5]);
302             }));
303 
304     ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, GATT_WRITE_NO_RSP, _, _))
305             .WillByDefault(Invoke(
306                     [this](uint16_t conn_id, uint16_t handle, std::vector<uint8_t> value,
307                            tGATT_WRITE_TYPE /*write_type*/, GATT_WRITE_OP_CB cb, void* cb_data) {
308                       for (auto& dev : le_audio_devices_) {
309                         if (dev->conn_id_ == conn_id) {
310                           // Control point write handler
311                           if (dev->ctp_hdls_.val_hdl == handle) {
312                             HandleCtpOperation(dev.get(), value, cb, cb_data);
313                           }
314                           break;
315                         }
316                       }
317                     }));
318 
319     ConfigureIsoManagerMock();
320   }
321 
HandleCtpOperation(LeAudioDevice * device,std::vector<uint8_t> value,GATT_WRITE_OP_CB cb,void * cb_data)322   void HandleCtpOperation(LeAudioDevice* device, std::vector<uint8_t> value, GATT_WRITE_OP_CB cb,
323                           void* cb_data) {
324     auto opcode = value[0];
325 
326     // Verify against valid opcode range
327     ASSERT_LT(opcode, ascs::kAseCtpOpcodeMaxVal + 1);
328     ASSERT_NE(opcode, 0);
329 
330     switch (opcode) {
331       case client_parser::ascs::kCtpOpcodeCodecConfiguration:
332         ase_ctp_handler.AseCtpConfigureCodecHandler(device, std::move(value), cb, cb_data);
333         break;
334       case client_parser::ascs::kCtpOpcodeQosConfiguration:
335         ase_ctp_handler.AseCtpConfigureQosHandler(device, std::move(value), cb, cb_data);
336         break;
337       case client_parser::ascs::kCtpOpcodeEnable:
338         ase_ctp_handler.AseCtpEnableHandler(device, std::move(value), cb, cb_data);
339         break;
340       case client_parser::ascs::kCtpOpcodeReceiverStartReady:
341         ase_ctp_handler.AseCtpReceiverStartReadyHandler(device, std::move(value), cb, cb_data);
342         break;
343       case client_parser::ascs::kCtpOpcodeDisable:
344         ase_ctp_handler.AseCtpDisableHandler(device, std::move(value), cb, cb_data);
345         break;
346       case client_parser::ascs::kCtpOpcodeReceiverStopReady:
347         ase_ctp_handler.AseCtpReceiverStopReadyHandler(device, std::move(value), cb, cb_data);
348         break;
349       case client_parser::ascs::kCtpOpcodeUpdateMetadata:
350         ase_ctp_handler.AseCtpUpdateMetadataHandler(device, std::move(value), cb, cb_data);
351         break;
352       case client_parser::ascs::kCtpOpcodeRelease:
353         ase_ctp_handler.AseCtpReleaseHandler(device, std::move(value), cb, cb_data);
354         break;
355       default:
356         break;
357     };
358   }
359 
360 /* Helper function to make a deterministic (and unique on the entire device)
361  * connection handle for a given cis.
362  */
363 #define UNIQUE_CIS_CONN_HANDLE(cig_id, cis_index) (cig_id << 8 | cis_index)
364 
ConfigureIsoManagerMock()365   void ConfigureIsoManagerMock() {
366     iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
367     ASSERT_NE(iso_manager_, nullptr);
368     iso_manager_->Start();
369 
370     mock_iso_manager_ = MockIsoManager::GetInstance();
371     ASSERT_NE(mock_iso_manager_, nullptr);
372 
373     ON_CALL(*mock_iso_manager_, CreateCig)
374             .WillByDefault(
375                     [this](uint8_t cig_id, bluetooth::hci::iso_manager::cig_create_params p) {
376                       log::debug("CreateCig");
377                       last_cig_params_ = p;
378 
379                       auto& group = le_audio_device_groups_[cig_id];
380                       if (group) {
381                         std::vector<uint16_t> conn_handles;
382                         // Fake connection ID for each cis in a request
383                         for (auto i = 0u; i < p.cis_cfgs.size(); ++i) {
384                           conn_handles.push_back(UNIQUE_CIS_CONN_HANDLE(cig_id, i));
385                         }
386                         auto status = HCI_SUCCESS;
387                         if (group_create_command_disallowed_) {
388                           group_create_command_disallowed_ = false;
389                           status = HCI_ERR_COMMAND_DISALLOWED;
390                         }
391 
392                         LeAudioGroupStateMachine::Get()->ProcessHciNotifOnCigCreate(
393                                 group.get(), status, cig_id, conn_handles);
394                       }
395                     });
396 
397     ON_CALL(*mock_iso_manager_, RemoveCig).WillByDefault([this](uint8_t cig_id, bool /*force*/) {
398       log::debug("CreateRemove");
399 
400       auto& group = le_audio_device_groups_[cig_id];
401       if (group) {
402         // Fake connection ID for each cis in a request
403         LeAudioGroupStateMachine::Get()->ProcessHciNotifOnCigRemove(0, group.get());
404       }
405     });
406 
407     ON_CALL(*mock_iso_manager_, SetupIsoDataPath)
408             .WillByDefault([this](uint16_t conn_handle,
409                                   bluetooth::hci::iso_manager::iso_data_path_params /*p*/) {
410               log::debug("SetupIsoDataPath");
411 
412               ASSERT_NE(conn_handle, kInvalidCisConnHandle);
413 
414               auto dev_it = std::find_if(le_audio_devices_.begin(), le_audio_devices_.end(),
415                                          [&conn_handle](auto& dev) {
416                                            auto ases = dev->GetAsesByCisConnHdl(conn_handle);
417                                            return ases.sink || ases.source;
418                                          });
419               if (dev_it == le_audio_devices_.end()) {
420                 log::error("Device not found");
421                 return;
422               }
423 
424               for (auto& kv_pair : le_audio_device_groups_) {
425                 auto& group = kv_pair.second;
426                 if (group->IsDeviceInTheGroup(dev_it->get())) {
427                   LeAudioGroupStateMachine::Get()->ProcessHciNotifSetupIsoDataPath(
428                           group.get(), dev_it->get(), 0, conn_handle);
429                   return;
430                 }
431               }
432             });
433 
434     ON_CALL(*mock_iso_manager_, RemoveIsoDataPath)
435             .WillByDefault([this](uint16_t conn_handle, uint8_t /*iso_direction*/) {
436               log::debug("RemoveIsoDataPath");
437 
438               ASSERT_NE(conn_handle, kInvalidCisConnHandle);
439 
440               auto dev_it = std::find_if(le_audio_devices_.begin(), le_audio_devices_.end(),
441                                          [&conn_handle](auto& dev) {
442                                            auto ases = dev->GetAsesByCisConnHdl(conn_handle);
443                                            return ases.sink || ases.source;
444                                          });
445               if (dev_it == le_audio_devices_.end()) {
446                 log::error("Device not found");
447                 return;
448               }
449 
450               for (auto& kv_pair : le_audio_device_groups_) {
451                 auto& group = kv_pair.second;
452                 if (group->IsDeviceInTheGroup(dev_it->get())) {
453                   LeAudioGroupStateMachine::Get()->ProcessHciNotifRemoveIsoDataPath(
454                           group.get(), dev_it->get(), 0, conn_handle);
455                   return;
456                 }
457               }
458             });
459 
460     ON_CALL(*mock_iso_manager_, EstablishCis)
461             .WillByDefault([this](bluetooth::hci::iso_manager::cis_establish_params conn_params) {
462               log::debug("EstablishCis");
463 
464               for (auto& pair : conn_params.conn_pairs) {
465                 ASSERT_NE(pair.cis_conn_handle, kInvalidCisConnHandle);
466 
467                 if (do_not_send_cis_establish_event_) {
468                   log::debug("Don't send cis establish event");
469                   continue;
470                 }
471 
472                 auto dev_it = std::find_if(
473                         le_audio_devices_.begin(), le_audio_devices_.end(), [&pair](auto& dev) {
474                           auto ases = dev->GetAsesByCisConnHdl(pair.cis_conn_handle);
475                           return ases.sink || ases.source;
476                         });
477                 if (dev_it == le_audio_devices_.end()) {
478                   log::error("Device not found");
479                   return;
480                 }
481 
482                 for (auto& kv_pair : le_audio_device_groups_) {
483                   auto& group = kv_pair.second;
484                   if (group->IsDeviceInTheGroup(dev_it->get())) {
485                     bluetooth::hci::iso_manager::cis_establish_cmpl_evt evt;
486 
487                     // Fill proper values if needed
488                     if (use_cis_retry_cnt_) {
489                       if (retry_cis_established_cnt_ > 0) {
490                         evt.status = HCI_ERR_CONN_FAILED_ESTABLISHMENT;
491                         retry_cis_established_cnt_--;
492                       } else {
493                         evt.status = 0;
494                       }
495                     } else if (overwrite_cis_status_) {
496                       evt.status = cis_status_[overwrite_cis_status_idx_++];
497                       /* Reset the index */
498                       if (cis_status_.size() == overwrite_cis_status_idx_) {
499                         overwrite_cis_status_idx_ = 0;
500                       }
501                     } else {
502                       evt.status = 0;
503                     }
504 
505                     evt.cig_id = group->group_id_;
506                     evt.cis_conn_hdl = pair.cis_conn_handle;
507                     evt.cig_sync_delay = 0;
508                     evt.cis_sync_delay = 0;
509                     evt.trans_lat_mtos = 0;
510                     evt.trans_lat_stom = 0;
511                     evt.phy_mtos = 0;
512                     evt.phy_stom = 0;
513                     evt.nse = 0;
514                     evt.bn_mtos = 0;
515                     evt.bn_stom = 0;
516                     evt.ft_mtos = 0;
517                     evt.ft_stom = 0;
518                     evt.max_pdu_mtos = 0;
519                     evt.max_pdu_stom = 0;
520                     evt.iso_itv = 0;
521 
522                     LeAudioGroupStateMachine::Get()->ProcessHciNotifCisEstablished(
523                             group.get(), dev_it->get(), &evt);
524                     break;
525                   }
526                 }
527               }
528             });
529 
530     ON_CALL(*mock_iso_manager_, DisconnectCis)
531             .WillByDefault([this](uint16_t cis_handle, uint8_t reason) {
532               log::debug("DisconnectCis");
533 
534               ASSERT_NE(cis_handle, kInvalidCisConnHandle);
535 
536               if (do_not_send_cis_disconnected_event_) {
537                 log::debug("Don't send cis disconnected event");
538                 return;
539               }
540 
541               auto dev_it = std::find_if(le_audio_devices_.begin(), le_audio_devices_.end(),
542                                          [&cis_handle](auto& dev) {
543                                            auto ases = dev->GetAsesByCisConnHdl(cis_handle);
544                                            return ases.sink || ases.source;
545                                          });
546               if (dev_it == le_audio_devices_.end()) {
547                 log::error("Device not found");
548                 return;
549               }
550 
551               // When we disconnect the remote with HCI_ERR_PEER_USER, we
552               // should be getting HCI_ERR_CONN_CAUSE_LOCAL_HOST from HCI.
553               if (reason == HCI_ERR_PEER_USER) {
554                 reason = HCI_ERR_CONN_CAUSE_LOCAL_HOST;
555               }
556 
557               for (auto& kv_pair : le_audio_device_groups_) {
558                 auto& group = kv_pair.second;
559                 if (group->IsDeviceInTheGroup(dev_it->get())) {
560                   bluetooth::hci::iso_manager::cis_disconnected_evt evt{
561                           .reason = reason,
562                           .cig_id = static_cast<uint8_t>(group->group_id_),
563                           .cis_conn_hdl = cis_handle,
564                   };
565                   LeAudioGroupStateMachine::Get()->ProcessHciNotifCisDisconnected(
566                           group.get(), dev_it->get(), &evt);
567                   return;
568                 }
569               }
570             });
571   }
572 
ConfigCodecManagerMock(types::CodecLocation location)573   void ConfigCodecManagerMock(types::CodecLocation location) {
574     codec_manager_ = bluetooth::le_audio::CodecManager::GetInstance();
575     ASSERT_NE(codec_manager_, nullptr);
576     std::vector<bluetooth::le_audio::btle_audio_codec_config_t> mock_offloading_preference(0);
577     codec_manager_->Start(mock_offloading_preference);
578     mock_codec_manager_ = MockCodecManager::GetInstance();
579     ASSERT_NE(mock_codec_manager_, nullptr);
580     ON_CALL(*mock_codec_manager_, GetCodecLocation()).WillByDefault(Return(location));
581     // Regardless of the codec location, return all the possible configurations
582     ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(true));
583     ON_CALL(*mock_codec_manager_, CheckCodecConfigIsBiDirSwb)
584             .WillByDefault(
585                     Invoke([](const set_configurations::AudioSetConfiguration& config) -> bool {
586                       return AudioSetConfigurationProvider::Get()->CheckConfigurationIsBiDirSwb(
587                               config);
588                     }));
589     ON_CALL(*mock_codec_manager_, GetCodecConfig)
590             .WillByDefault(Invoke(
591                     [](const bluetooth::le_audio::CodecManager::UnicastConfigurationRequirements&
592                                requirements,
593                        bluetooth::le_audio::CodecManager::UnicastConfigurationProvider provider) {
594                       auto configs = *bluetooth::le_audio::AudioSetConfigurationProvider::Get()
595                                               ->GetConfigurations(requirements.audio_context_type);
596                       // Note: This dual bidir SWB exclusion logic has to match the
597                       // CodecManager::GetCodecConfig() implementation.
598                       if (!CodecManager::GetInstance()->IsDualBiDirSwbSupported()) {
599                         configs.erase(
600                                 std::remove_if(configs.begin(), configs.end(),
601                                                [](auto const& el) {
602                                                  if (el->confs.source.empty()) {
603                                                    return false;
604                                                  }
605                                                  return AudioSetConfigurationProvider::Get()
606                                                          ->CheckConfigurationIsDualBiDirSwb(*el);
607                                                }),
608                                 configs.end());
609                       }
610 
611                       return provider(requirements, &configs);
612                     }));
613   }
614 
TearDown()615   void TearDown() override {
616     com::android::bluetooth::flags::provider_->reset_flags();
617 
618     /* Clear the alarm on tear down in case test case ends when the
619      * alarm is scheduled
620      */
621     alarm_cancel(nullptr);
622 
623     iso_manager_->Stop();
624     mock_iso_manager_ = nullptr;
625     codec_manager_->Stop();
626     mock_codec_manager_ = nullptr;
627 
628     gatt::SetMockBtaGattQueue(nullptr);
629     gatt::SetMockBtaGattInterface(nullptr);
630     bluetooth::manager::SetMockBtmInterface(nullptr);
631 
632     le_audio_devices_.clear();
633     le_audio_device_groups_.clear();
634     addresses_.clear();
635     cached_codec_configuration_map_.clear();
636     cached_qos_configuration_map_.clear();
637     cached_ase_to_cis_id_map_.clear();
638     cached_remote_qos_configuration_for_ase_.clear();
639     LeAudioGroupStateMachine::Cleanup();
640     ::bluetooth::le_audio::AudioSetConfigurationProvider::Cleanup();
641     bluetooth::hci::testing::mock_controller_ = nullptr;
642   }
643 
PrepareConnectedDevice(uint8_t id,DeviceConnectState initial_connect_state,uint8_t num_ase_snk,uint8_t num_ase_src)644   std::shared_ptr<LeAudioDevice> PrepareConnectedDevice(uint8_t id,
645                                                         DeviceConnectState initial_connect_state,
646                                                         uint8_t num_ase_snk, uint8_t num_ase_src) {
647     auto leAudioDevice = std::make_shared<LeAudioDevice>(GetTestAddress(id), initial_connect_state);
648     leAudioDevice->conn_id_ = id;
649     leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
650 
651     uint16_t attr_handle = ATTR_HANDLE_ASCS_POOL_START;
652     leAudioDevice->snk_audio_locations_hdls_.val_hdl = attr_handle++;
653     leAudioDevice->snk_audio_locations_hdls_.ccc_hdl = attr_handle++;
654     leAudioDevice->src_audio_locations_hdls_.val_hdl = attr_handle++;
655     leAudioDevice->src_audio_locations_hdls_.ccc_hdl = attr_handle++;
656     leAudioDevice->audio_avail_hdls_.val_hdl = attr_handle++;
657     leAudioDevice->audio_avail_hdls_.ccc_hdl = attr_handle++;
658     leAudioDevice->audio_supp_cont_hdls_.val_hdl = attr_handle++;
659     leAudioDevice->audio_supp_cont_hdls_.ccc_hdl = attr_handle++;
660     leAudioDevice->ctp_hdls_.val_hdl = attr_handle++;
661     leAudioDevice->ctp_hdls_.ccc_hdl = attr_handle++;
662 
663     // Add some Sink ASEs
664     while (num_ase_snk) {
665       types::ase ase(0, 0, 0x01);
666       ase.hdls.val_hdl = attr_handle++;
667       ase.hdls.ccc_hdl = attr_handle++;
668 
669       leAudioDevice->ases_.push_back(std::move(ase));
670       num_ase_snk--;
671     }
672 
673     // Add some Source ASEs
674     while (num_ase_src) {
675       types::ase ase(0, 0, 0x02);
676       ase.hdls.val_hdl = attr_handle++;
677       ase.hdls.ccc_hdl = attr_handle++;
678 
679       leAudioDevice->ases_.push_back(std::move(ase));
680       num_ase_src--;
681     }
682 
683     le_audio_devices_.push_back(leAudioDevice);
684     addresses_.push_back(leAudioDevice->address_);
685 
686     return leAudioDevice;
687   }
688 
GroupFindById(int group_id)689   LeAudioDeviceGroup* GroupFindById(int group_id) {
690     return le_audio_device_groups_.count(group_id) ? le_audio_device_groups_[group_id].get()
691                                                    : nullptr;
692   }
693 
GroupTheDevice(int group_id,const std::shared_ptr<LeAudioDevice> & leAudioDevice)694   LeAudioDeviceGroup* GroupTheDevice(int group_id,
695                                      const std::shared_ptr<LeAudioDevice>& leAudioDevice) {
696     if (le_audio_device_groups_.count(group_id) == 0) {
697       le_audio_device_groups_[group_id] = std::make_unique<LeAudioDeviceGroup>(group_id);
698     }
699 
700     auto& group = le_audio_device_groups_[group_id];
701 
702     group->AddNode(leAudioDevice);
703     if (group->IsEmpty()) {
704       return nullptr;
705     }
706 
707     return &(*group);
708   }
709 
InjectAclConnected(LeAudioDeviceGroup * group,LeAudioDevice * leAudioDevice,uint16_t conn_id)710   void InjectAclConnected(LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
711                           uint16_t conn_id) {
712     // Do what the client.cc does when handling the disconnection event
713     leAudioDevice->conn_id_ = conn_id;
714     leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
715 
716     /* Update all stuff on the group when device got connected */
717     group->ReloadAudioLocations();
718     group->ReloadAudioDirections();
719     group->UpdateAudioContextAvailability();
720     group->InvalidateCachedConfigurations();
721     group->InvalidateGroupStrategy();
722   }
723 
InjectAclDisconnected(LeAudioDeviceGroup * group,LeAudioDevice * leAudioDevice)724   void InjectAclDisconnected(LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice) {
725     // Do what the client.cc does when handling the disconnection event
726     leAudioDevice->conn_id_ = GATT_INVALID_CONN_ID;
727     leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
728     LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(group, leAudioDevice);
729   }
730 
InjectReleasingAndIdleState(LeAudioDeviceGroup * group,LeAudioDevice * device,bool release=true,bool idle=true)731   void InjectReleasingAndIdleState(LeAudioDeviceGroup* group, LeAudioDevice* device,
732                                    bool release = true, bool idle = true) {
733     for (auto& ase : device->ases_) {
734       if (ase.id == bluetooth::le_audio::types::ase::kAseIdInvalid) {
735         continue;
736       }
737       // Simulate autonomus RELEASE and moving to IDLE state
738       if (release) {
739         InjectAseStateNotification(&ase, device, group, ascs::kAseStateReleasing, nullptr);
740       }
741       if (idle) {
742         InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle, nullptr);
743       }
744     }
745   }
746 
InjectReleaseAndIdleStateForAGroup(LeAudioDeviceGroup * group,bool release=true,bool idle=true)747   void InjectReleaseAndIdleStateForAGroup(LeAudioDeviceGroup* group, bool release = true,
748                                           bool idle = true) {
749     auto leAudioDevice = group->GetFirstActiveDevice();
750     while (leAudioDevice) {
751       log::info("Group : {},  dev: {}", group->group_id_, leAudioDevice->address_);
752       InjectReleasingAndIdleState(group, leAudioDevice, release, idle);
753       leAudioDevice = group->GetNextActiveDevice(leAudioDevice);
754     }
755   }
756 
InjectCachedConfigurationForActiveAses(LeAudioDeviceGroup * group,LeAudioDevice * device)757   void InjectCachedConfigurationForActiveAses(LeAudioDeviceGroup* group, LeAudioDevice* device) {
758     for (auto& ase : device->ases_) {
759       if (!ase.active) {
760         continue;
761       }
762       log::info("ID : {},  status {}", ase.id, bluetooth::common::ToString(ase.state));
763 
764       InjectAseStateNotification(&ase, device, group, ascs::kAseStateCodecConfigured,
765                                  &cached_codec_configuration_map_[ase.id]);
766     }
767   }
768 
InjectCachedConfigurationForGroup(LeAudioDeviceGroup * group)769   void InjectCachedConfigurationForGroup(LeAudioDeviceGroup* group) {
770     auto leAudioDevice = group->GetFirstActiveDevice();
771     while (leAudioDevice) {
772       log::info("Group : {},  dev: {}", group->group_id_, leAudioDevice->address_);
773       InjectCachedConfigurationForActiveAses(group, leAudioDevice);
774       leAudioDevice = group->GetNextActiveDevice(leAudioDevice);
775     }
776   }
777 
InjectStreamingStateFroActiveAses(LeAudioDeviceGroup * group,LeAudioDevice * device)778   void InjectStreamingStateFroActiveAses(LeAudioDeviceGroup* group, LeAudioDevice* device) {
779     for (auto& ase : device->ases_) {
780       if (!ase.active) {
781         continue;
782       }
783       log::info("ID : {},  status {}", ase.id, bluetooth::common::ToString(ase.state));
784       client_parser::ascs::ase_transient_state_params params;
785 
786       InjectAseStateNotification(&ase, device, group, ascs::kAseStateStreaming, &params);
787     }
788   }
789 
InjectEnablingStateFroActiveAses(LeAudioDeviceGroup * group,LeAudioDevice * device)790   void InjectEnablingStateFroActiveAses(LeAudioDeviceGroup* group, LeAudioDevice* device) {
791     for (auto& ase : device->ases_) {
792       if (!ase.active) {
793         continue;
794       }
795       log::info("ID : {},  status {}", ase.id, bluetooth::common::ToString(ase.state));
796       client_parser::ascs::ase_transient_state_params enable_params;
797 
798       InjectAseStateNotification(&ase, device, group, ascs::kAseStateEnabling, &enable_params);
799     }
800   }
801 
InjectQoSConfigurationForActiveAses(LeAudioDeviceGroup * group,LeAudioDevice * device)802   void InjectQoSConfigurationForActiveAses(LeAudioDeviceGroup* group, LeAudioDevice* device) {
803     for (auto& ase : device->ases_) {
804       if (!ase.active) {
805         continue;
806       }
807       log::info("ID : {},  status {}", ase.id, bluetooth::common::ToString(ase.state));
808 
809       if (ase.direction == ::bluetooth::le_audio::types::kLeAudioDirectionSource) {
810         client_parser::ascs::ase_transient_state_params disabling_params = {.metadata = {}};
811         InjectAseStateNotification(&ase, device, group, ascs::kAseStateDisabling,
812                                    &disabling_params);
813       }
814 
815       InjectAseStateNotification(&ase, device, group, ascs::kAseStateQoSConfigured,
816                                  &cached_qos_configuration_map_[ase.id]);
817     }
818   }
819 
InjectQoSConfigurationForGroupActiveAses(LeAudioDeviceGroup * group)820   void InjectQoSConfigurationForGroupActiveAses(LeAudioDeviceGroup* group) {
821     auto leAudioDevice = group->GetFirstActiveDevice();
822     while (leAudioDevice) {
823       log::info("Group : {},  dev: {}", group->group_id_, leAudioDevice->address_);
824       InjectQoSConfigurationForActiveAses(group, leAudioDevice);
825       leAudioDevice = group->GetNextActiveDevice(leAudioDevice);
826     }
827   }
828 
InjectAseStateNotification(types::ase * ase,LeAudioDevice * device,LeAudioDeviceGroup * group,uint8_t new_state,void * new_state_params)829   void InjectAseStateNotification(types::ase* ase, LeAudioDevice* device, LeAudioDeviceGroup* group,
830                                   uint8_t new_state, void* new_state_params) {
831     // Prepare additional params
832     switch (new_state) {
833       case ascs::kAseStateCodecConfigured: {
834         client_parser::ascs::ase_codec_configured_state_params* conf =
835                 static_cast<client_parser::ascs::ase_codec_configured_state_params*>(
836                         new_state_params);
837         std::vector<uint8_t> notif_value(25 + conf->codec_spec_conf.size());
838         auto* p = notif_value.data();
839 
840         UINT8_TO_STREAM(p, ase->id == types::ase::kAseIdInvalid ? ++ase_id_last_assigned : ase->id);
841         UINT8_TO_STREAM(p, new_state);
842 
843         UINT8_TO_STREAM(p, conf->framing);
844         UINT8_TO_STREAM(p, conf->preferred_phy);
845         UINT8_TO_STREAM(p, conf->preferred_retrans_nb);
846         UINT16_TO_STREAM(p, conf->max_transport_latency);
847         UINT24_TO_STREAM(p, conf->pres_delay_min);
848         UINT24_TO_STREAM(p, conf->pres_delay_max);
849         UINT24_TO_STREAM(p, conf->preferred_pres_delay_min);
850         UINT24_TO_STREAM(p, conf->preferred_pres_delay_max);
851 
852         // CodecID:
853         UINT8_TO_STREAM(p, conf->codec_id.coding_format);
854         UINT16_TO_STREAM(p, conf->codec_id.vendor_company_id);
855         UINT16_TO_STREAM(p, conf->codec_id.vendor_codec_id);
856 
857         // Codec Spec. Conf. Length and Data
858         UINT8_TO_STREAM(p, conf->codec_spec_conf.size());
859         memcpy(p, conf->codec_spec_conf.data(), conf->codec_spec_conf.size());
860 
861         LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
862                 notif_value.data(), notif_value.size(), ase, device, group);
863       } break;
864 
865       case ascs::kAseStateQoSConfigured: {
866         client_parser::ascs::ase_qos_configured_state_params* conf =
867                 static_cast<client_parser::ascs::ase_qos_configured_state_params*>(
868                         new_state_params);
869         std::vector<uint8_t> notif_value(17);
870         auto* p = notif_value.data();
871 
872         // Prepare header
873         UINT8_TO_STREAM(p, ase->id == types::ase::kAseIdInvalid ? ++ase_id_last_assigned : ase->id);
874         UINT8_TO_STREAM(p, new_state);
875 
876         UINT8_TO_STREAM(p, conf->cig_id);
877         UINT8_TO_STREAM(p, conf->cis_id);
878         UINT24_TO_STREAM(p, conf->sdu_interval);
879         UINT8_TO_STREAM(p, conf->framing);
880         UINT8_TO_STREAM(p, conf->phy);
881         UINT16_TO_STREAM(p, conf->max_sdu);
882         UINT8_TO_STREAM(p, conf->retrans_nb);
883         UINT16_TO_STREAM(p, conf->max_transport_latency);
884         UINT24_TO_STREAM(p, conf->pres_delay);
885 
886         cached_remote_qos_configuration_for_ase_[ase] = notif_value;
887 
888         LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
889                 notif_value.data(), notif_value.size(), ase, device, group);
890       } break;
891 
892       case ascs::kAseStateEnabling:
893         // fall-through
894       case ascs::kAseStateStreaming:
895         // fall-through
896       case ascs::kAseStateDisabling: {
897         client_parser::ascs::ase_transient_state_params* params =
898                 static_cast<client_parser::ascs::ase_transient_state_params*>(new_state_params);
899         std::vector<uint8_t> notif_value(5 + params->metadata.size());
900         auto* p = notif_value.data();
901 
902         // Prepare header
903         UINT8_TO_STREAM(p, ase->id == types::ase::kAseIdInvalid ? ++ase_id_last_assigned : ase->id);
904 
905         UINT8_TO_STREAM(p, new_state);
906 
907         UINT8_TO_STREAM(p, group->group_id_);
908         UINT8_TO_STREAM(p, ase->cis_id);
909         UINT8_TO_STREAM(p, params->metadata.size());
910         memcpy(p, params->metadata.data(), params->metadata.size());
911 
912         LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
913                 notif_value.data(), notif_value.size(), ase, device, group);
914       } break;
915 
916       case ascs::kAseStateReleasing:
917         // fall-through
918       case ascs::kAseStateIdle: {
919         std::vector<uint8_t> notif_value(2);
920         auto* p = notif_value.data();
921 
922         // Prepare header
923         UINT8_TO_STREAM(p, ase->id == types::ase::kAseIdInvalid ? ++ase_id_last_assigned : ase->id);
924         UINT8_TO_STREAM(p, new_state);
925 
926         LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
927                 notif_value.data(), notif_value.size(), ase, device, group);
928       } break;
929 
930       default:
931         break;
932     };
933   }
934 
InsertPacRecord(std::vector<types::acs_ac_record> & recs,uint16_t sampling_frequencies_bitfield,uint8_t supported_frame_durations_bitfield,uint8_t audio_channel_count_bitfield,uint16_t supported_octets_per_codec_frame_min,uint16_t supported_octets_per_codec_frame_max,uint8_t codec_frame_blocks_per_sdu_=1,uint8_t coding_format=codec_specific::kLc3CodingFormat,uint16_t vendor_company_id=0x0000,uint16_t vendor_codec_id=0x0000,std::vector<uint8_t> metadata={})935   static void InsertPacRecord(
936           std::vector<types::acs_ac_record>& recs, uint16_t sampling_frequencies_bitfield,
937           uint8_t supported_frame_durations_bitfield, uint8_t audio_channel_count_bitfield,
938           uint16_t supported_octets_per_codec_frame_min,
939           uint16_t supported_octets_per_codec_frame_max, uint8_t codec_frame_blocks_per_sdu_ = 1,
940           uint8_t coding_format = codec_specific::kLc3CodingFormat,
941           uint16_t vendor_company_id = 0x0000, uint16_t vendor_codec_id = 0x0000,
942           std::vector<uint8_t> metadata = {}) {
943     auto ltv_map = types::LeAudioLtvMap({
944             {codec_specific::kCapTypeSupportedSamplingFrequencies,
945              {(uint8_t)(sampling_frequencies_bitfield),
946               (uint8_t)(sampling_frequencies_bitfield >> 8)}},
947             {codec_specific::kCapTypeSupportedFrameDurations, {supported_frame_durations_bitfield}},
948             {codec_specific::kCapTypeAudioChannelCount, {audio_channel_count_bitfield}},
949             {codec_specific::kCapTypeSupportedOctetsPerCodecFrame,
950              {
951                      // Min
952                      (uint8_t)(supported_octets_per_codec_frame_min),
953                      (uint8_t)(supported_octets_per_codec_frame_min >> 8),
954                      // Max
955                      (uint8_t)(supported_octets_per_codec_frame_max),
956                      (uint8_t)(supported_octets_per_codec_frame_max >> 8),
957              }},
958     });
959     ltv_map.Add(codec_specific::kCapTypeSupportedLc3CodecFramesPerSdu,
960                 (uint8_t)codec_frame_blocks_per_sdu_);
961     recs.push_back({
962             .codec_id =
963                     {
964                             .coding_format = coding_format,
965                             .vendor_company_id = vendor_company_id,
966                             .vendor_codec_id = vendor_codec_id,
967                     },
968             .codec_spec_caps = ltv_map,
969             .codec_spec_caps_raw = ltv_map.RawPacket(),
970             .metadata = std::move(metadata),
971     });
972   }
973 
InjectInitialIdleNotification(LeAudioDeviceGroup * group)974   void InjectInitialIdleNotification(LeAudioDeviceGroup* group) {
975     for (auto* device = group->GetFirstDevice(); device != nullptr;
976          device = group->GetNextDevice(device)) {
977       for (auto& ase : device->ases_) {
978         InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle, nullptr);
979       }
980     }
981   }
982 
InjectInitialConfiguredNotification(LeAudioDeviceGroup * group)983   void InjectInitialConfiguredNotification(LeAudioDeviceGroup* group) {
984     for (auto* device = group->GetFirstDevice(); device != nullptr;
985          device = group->GetNextDevice(device)) {
986       for (auto& ase : device->ases_) {
987         client_parser::ascs::ase_codec_configured_state_params codec_configured_state_params;
988         InjectAseStateNotification(&ase, device, group, ascs::kAseStateCodecConfigured,
989                                    &codec_configured_state_params);
990       }
991     }
992   }
993 
InjectInitialIdleAndConfiguredNotification(LeAudioDeviceGroup * group)994   void InjectInitialIdleAndConfiguredNotification(LeAudioDeviceGroup* group) {
995     for (auto* device = group->GetFirstDevice(); device != nullptr;
996          device = group->GetNextDevice(device)) {
997       int i = 0;
998       for (auto& ase : device->ases_) {
999         if (i % 2 == 1) {
1000           InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle, nullptr);
1001         } else {
1002           client_parser::ascs::ase_codec_configured_state_params codec_configured_state_params;
1003           InjectAseStateNotification(&ase, device, group, ascs::kAseStateCodecConfigured,
1004                                      &codec_configured_state_params);
1005         }
1006         i++;
1007       }
1008     }
1009   }
1010 
InjectInitialInvalidNotification(LeAudioDeviceGroup * group)1011   void InjectInitialInvalidNotification(LeAudioDeviceGroup* group) {
1012     for (auto* device = group->GetFirstDevice(); device != nullptr;
1013          device = group->GetNextDevice(device)) {
1014       int i = 0;
1015       for (auto& ase : device->ases_) {
1016         if (i % 2 == 1) {
1017           client_parser::ascs::ase_qos_configured_state_params qos_configured_state_params;
1018           InjectAseStateNotification(&ase, device, group, ascs::kAseStateQoSConfigured,
1019                                      &qos_configured_state_params);
1020         } else {
1021           client_parser::ascs::ase_transient_state_params enable_params;
1022           InjectAseStateNotification(&ase, device, group, ascs::kAseStateEnabling, &enable_params);
1023         }
1024         i++;
1025       }
1026     }
1027   }
1028 
DeviceContextsUpdate(LeAudioDevice * leAudioDevice,uint8_t direction,types::AudioContexts contexts_available,types::AudioContexts contexts_supported)1029   void DeviceContextsUpdate(LeAudioDevice* leAudioDevice, uint8_t direction,
1030                             types::AudioContexts contexts_available,
1031                             types::AudioContexts contexts_supported) {
1032     types::AudioContexts snk_contexts_available;
1033     types::AudioContexts src_contexts_available;
1034     types::AudioContexts snk_contexts_supported;
1035     types::AudioContexts src_contexts_supported;
1036     /* Ensure Unspecified context is supported as per spec */
1037     contexts_supported.set(kContextTypeUnspecified);
1038 
1039     if ((direction & types::kLeAudioDirectionSink) > 0) {
1040       snk_contexts_available = contexts_available;
1041       snk_contexts_supported = contexts_supported;
1042     } else {
1043       snk_contexts_available = leAudioDevice->GetAvailableContexts(types::kLeAudioDirectionSink);
1044       snk_contexts_supported = leAudioDevice->GetSupportedContexts(types::kLeAudioDirectionSink);
1045     }
1046 
1047     if ((direction & types::kLeAudioDirectionSource) > 0) {
1048       src_contexts_available = contexts_available;
1049       src_contexts_supported = contexts_supported;
1050     } else {
1051       src_contexts_available = leAudioDevice->GetAvailableContexts(types::kLeAudioDirectionSource);
1052       src_contexts_supported = leAudioDevice->GetSupportedContexts(types::kLeAudioDirectionSource);
1053     }
1054 
1055     leAudioDevice->SetSupportedContexts(
1056             {.sink = snk_contexts_supported, .source = src_contexts_supported});
1057     leAudioDevice->SetAvailableContexts(
1058             {.sink = snk_contexts_available, .source = src_contexts_available});
1059 
1060     auto group = GroupFindById(leAudioDevice->group_id_);
1061     if (group) {
1062       bool group_conf_changed = group->ReloadAudioLocations();
1063       group_conf_changed |= group->ReloadAudioDirections();
1064       group_conf_changed |= group->UpdateAudioContextAvailability();
1065       if (group_conf_changed) {
1066         /* All the configurations should be recalculated for the new conditions */
1067         group->InvalidateCachedConfigurations();
1068         group->InvalidateGroupStrategy();
1069       }
1070     }
1071   }
1072 
DevicePacsInit(LeAudioDevice * leAudioDevice,uint8_t direction,uint8_t audio_locations,types::AudioContexts contexts_available,types::AudioContexts contexts_supported)1073   void DevicePacsInit(LeAudioDevice* leAudioDevice, uint8_t direction, uint8_t audio_locations,
1074                       types::AudioContexts contexts_available,
1075                       types::AudioContexts contexts_supported) {
1076     if ((direction & types::kLeAudioDirectionSink) > 0) {
1077       // Set target ASE configurations
1078       std::vector<types::acs_ac_record> pac_recs;
1079 
1080       InsertPacRecord(pac_recs, sample_freq_,
1081                       codec_specific::kCapFrameDuration10ms |
1082                               codec_specific::kCapFrameDuration7p5ms |
1083                               codec_specific::kCapFrameDuration10msPreferred,
1084                       channel_count_, 30, 120, codec_frame_blocks_per_sdu_);
1085 
1086       types::hdl_pair handle_pair;
1087       handle_pair.val_hdl = pacs_attr_handle_next++;
1088       handle_pair.ccc_hdl = pacs_attr_handle_next++;
1089 
1090       leAudioDevice->snk_pacs_.emplace_back(std::make_tuple(std::move(handle_pair), pac_recs));
1091 
1092       leAudioDevice->snk_audio_locations_ = audio_locations;
1093     }
1094 
1095     if ((direction & types::kLeAudioDirectionSource) > 0) {
1096       // Set target ASE configurations
1097       std::vector<types::acs_ac_record> pac_recs;
1098 
1099       InsertPacRecord(pac_recs,
1100                       codec_specific::kCapSamplingFrequency16000Hz |
1101                               codec_specific::kCapSamplingFrequency32000Hz,
1102                       codec_specific::kCapFrameDuration10ms |
1103                               codec_specific::kCapFrameDuration7p5ms |
1104                               codec_specific::kCapFrameDuration10msPreferred,
1105                       0b00000001, 30, 120, codec_frame_blocks_per_sdu_);
1106 
1107       types::hdl_pair handle_pair;
1108       handle_pair.val_hdl = pacs_attr_handle_next++;
1109       handle_pair.ccc_hdl = pacs_attr_handle_next++;
1110 
1111       leAudioDevice->src_pacs_.emplace_back(std::make_tuple(std::move(handle_pair), pac_recs));
1112 
1113       leAudioDevice->src_audio_locations_ = audio_locations;
1114     }
1115 
1116     DeviceContextsUpdate(leAudioDevice, direction, contexts_available, contexts_supported);
1117   }
1118 
MultipleTestDevicePrepare(int leaudio_group_id,LeAudioContextType context_type,const uint16_t total_devices,types::AudioContexts update_contexts,bool insert_default_pac_records=true,bool second_device_0_ases=false)1119   void MultipleTestDevicePrepare(int leaudio_group_id, LeAudioContextType context_type,
1120                                  const uint16_t total_devices, types::AudioContexts update_contexts,
1121                                  bool insert_default_pac_records = true,
1122                                  bool second_device_0_ases = false) {
1123     // Prepare fake connected device group
1124     DeviceConnectState initial_connect_state = DeviceConnectState::CONNECTING_BY_USER;
1125 
1126     uint8_t num_ase_snk;
1127     uint8_t num_ase_src;
1128     switch (context_type) {
1129       case kContextTypeRingtone:
1130         num_ase_snk = 1 + additional_snk_ases;
1131         num_ase_src = 0 + additional_src_ases;
1132         break;
1133 
1134       case kContextTypeMedia:
1135         num_ase_snk = 2 + additional_snk_ases;
1136         num_ase_src = 0 + additional_src_ases;
1137         break;
1138 
1139       case kContextTypeConversational:
1140         num_ase_snk = 1 + additional_snk_ases;
1141         num_ase_src = 1 + additional_src_ases;
1142         break;
1143 
1144       case kContextTypeLive:
1145         num_ase_snk = 1 + additional_snk_ases;
1146         num_ase_src = 1 + additional_src_ases;
1147         break;
1148 
1149       default:
1150         ASSERT_TRUE(false);
1151     }
1152 
1153     for (uint8_t device_cnt = 0; device_cnt < total_devices; device_cnt++) {
1154       std::shared_ptr<LeAudioDevice> leAudioDevice;
1155       bluetooth::le_audio::LeAudioDeviceGroup* group;
1156 
1157       if (device_cnt == 1 && second_device_0_ases == true) {
1158         leAudioDevice = PrepareConnectedDevice(device_cnt, initial_connect_state, 0, 0);
1159       } else {
1160         leAudioDevice =
1161                 PrepareConnectedDevice(device_cnt, initial_connect_state, num_ase_snk, num_ase_src);
1162       }
1163 
1164       group = GroupTheDevice(leaudio_group_id, std::move(leAudioDevice));
1165       ASSERT_NE(group, nullptr);
1166       ASSERT_EQ(group->Size(), device_cnt + 1);
1167 
1168       if (insert_default_pac_records) {
1169         // Prepare Sink Published Audio Capability records
1170         if ((kContextTypeRingtone | kContextTypeMedia | kContextTypeConversational |
1171              kContextTypeLive)
1172                     .test(context_type)) {
1173           auto snk_context_type = update_contexts;
1174           snk_context_type.set(context_type);
1175 
1176           DevicePacsInit(leAudioDevice.get(), types::kLeAudioDirectionSink,
1177                          channel_allocations_sink_, snk_context_type, snk_context_type);
1178         }
1179 
1180         // Prepare Source Published Audio Capability records
1181         if ((context_type == kContextTypeConversational) || (context_type == kContextTypeLive)) {
1182           auto src_context_type = update_contexts;
1183           src_context_type.set(context_type);
1184 
1185           DevicePacsInit(leAudioDevice.get(), types::kLeAudioDirectionSource,
1186                          channel_allocations_source_, src_context_type, src_context_type);
1187         }
1188       }
1189     }
1190 
1191     auto group = GroupFindById(leaudio_group_id);
1192     ASSERT_NE(group, nullptr);
1193 
1194     group->UpdateAudioSetConfigurationCache(context_type);
1195     ASSERT_EQ(group->Size(), total_devices);
1196   }
1197 
PrepareSingleTestDeviceGroup(int leaudio_group_id,LeAudioContextType context_type,uint16_t device_cnt=1,types::AudioContexts update_contexts=types::AudioContexts (),bool second_device_0_ases=false)1198   LeAudioDeviceGroup* PrepareSingleTestDeviceGroup(
1199           int leaudio_group_id, LeAudioContextType context_type, uint16_t device_cnt = 1,
1200           types::AudioContexts update_contexts = types::AudioContexts(),
1201           bool second_device_0_ases = false) {
1202     MultipleTestDevicePrepare(leaudio_group_id, context_type, device_cnt, update_contexts, true,
1203                               second_device_0_ases);
1204     return le_audio_device_groups_.count(leaudio_group_id)
1205                    ? le_audio_device_groups_[leaudio_group_id].get()
1206                    : nullptr;
1207   }
1208 
PrepareConfigureCodecHandler(LeAudioDeviceGroup * group,int verify_ase_count=0,bool caching=false,bool inject_configured=true)1209   void PrepareConfigureCodecHandler(LeAudioDeviceGroup* group, int verify_ase_count = 0,
1210                                     bool caching = false, bool inject_configured = true) {
1211     ON_CALL(ase_ctp_handler, AseCtpConfigureCodecHandler)
1212             .WillByDefault(Invoke([group, verify_ase_count, caching, inject_configured, this](
1213                                           LeAudioDevice* device, std::vector<uint8_t> value,
1214                                           GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) {
1215               auto num_ase = value[1];
1216 
1217               // Verify ase count if needed
1218               if (verify_ase_count) {
1219                 ASSERT_EQ(verify_ase_count, num_ase);
1220               }
1221 
1222               // Inject Configured ASE state notification for each requested ASE
1223               auto* ase_p = &value[2];
1224               for (auto i = 0u; i < num_ase; ++i) {
1225                 client_parser::ascs::ase_codec_configured_state_params
1226                         codec_configured_state_params;
1227 
1228                 /* Check if this is a valid ASE ID  */
1229                 auto ase_id = *ase_p++;
1230                 auto it = std::find_if(device->ases_.begin(), device->ases_.end(),
1231                                        [ase_id](auto& ase) { return ase.id == ase_id; });
1232                 ASSERT_NE(it, device->ases_.end());
1233                 const auto ase = &(*it);
1234 
1235                 // Skip target latency param
1236                 ase_p++;
1237 
1238                 codec_configured_state_params.preferred_phy = *ase_p++;
1239                 codec_configured_state_params.codec_id.coding_format = ase_p[0];
1240                 codec_configured_state_params.codec_id.vendor_company_id =
1241                         (uint16_t)(ase_p[1] << 8 | ase_p[2]),
1242                 codec_configured_state_params.codec_id.vendor_codec_id =
1243                         (uint16_t)(ase_p[3] << 8 | ase_p[4]),
1244                 ase_p += 5;
1245 
1246                 auto codec_spec_param_len = *ase_p++;
1247                 auto num_handled_bytes = ase_p - value.data();
1248                 codec_configured_state_params.codec_spec_conf = std::vector<uint8_t>(
1249                         value.begin() + num_handled_bytes,
1250                         value.begin() + num_handled_bytes + codec_spec_param_len);
1251                 ase_p += codec_spec_param_len;
1252 
1253                 // Some initial QoS settings
1254                 codec_configured_state_params.framing = ascs::kAseParamFramingUnframedSupported;
1255                 codec_configured_state_params.preferred_retrans_nb = 0x04;
1256                 codec_configured_state_params.max_transport_latency = 0x0020;
1257                 codec_configured_state_params.pres_delay_min = 0xABABAB;
1258                 codec_configured_state_params.pres_delay_max = 0xCDCDCD;
1259                 codec_configured_state_params.preferred_pres_delay_min =
1260                         types::kPresDelayNoPreference;
1261                 codec_configured_state_params.preferred_pres_delay_max =
1262                         types::kPresDelayNoPreference;
1263 
1264                 if (caching) {
1265                   cached_codec_configuration_map_[ase_id] = codec_configured_state_params;
1266                 }
1267 
1268                 if (inject_configured) {
1269                   InjectAseStateNotification(ase, device, group, ascs::kAseStateCodecConfigured,
1270                                              &codec_configured_state_params);
1271                 }
1272 
1273                 if (stop_inject_configured_ase_after_first_ase_configured_) {
1274                   return;
1275                 }
1276               }
1277             }));
1278   }
1279 
PrepareConfigureQosHandler(LeAudioDeviceGroup * group,int verify_ase_count=0,bool caching=false,bool inject_qos_configured=true)1280   void PrepareConfigureQosHandler(LeAudioDeviceGroup* group, int verify_ase_count = 0,
1281                                   bool caching = false, bool inject_qos_configured = true) {
1282     ON_CALL(ase_ctp_handler, AseCtpConfigureQosHandler)
1283             .WillByDefault(Invoke([group, verify_ase_count, caching, inject_qos_configured, this](
1284                                           LeAudioDevice* device, std::vector<uint8_t> value,
1285                                           GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) {
1286               auto num_ase = value[1];
1287 
1288               // Verify ase count if needed
1289               if (verify_ase_count) {
1290                 ASSERT_EQ(verify_ase_count, num_ase);
1291               }
1292 
1293               // Inject Configured QoS state notification for each requested ASE
1294               auto* ase_p = &value[2];
1295               for (auto i = 0u; i < num_ase; ++i) {
1296                 client_parser::ascs::ase_qos_configured_state_params qos_configured_state_params;
1297 
1298                 /* Check if this is a valid ASE ID  */
1299                 auto ase_id = *ase_p++;
1300                 auto it = std::find_if(device->ases_.begin(), device->ases_.end(),
1301                                        [ase_id](auto& ase) { return ase.id == ase_id; });
1302                 ASSERT_NE(it, device->ases_.end());
1303                 const auto ase = &(*it);
1304 
1305                 qos_configured_state_params.cig_id = *ase_p++;
1306                 qos_configured_state_params.cis_id = *ase_p++;
1307 
1308                 qos_configured_state_params.sdu_interval =
1309                         (uint32_t)((ase_p[0] << 16) | (ase_p[1] << 8) | ase_p[2]);
1310                 ase_p += 3;
1311 
1312                 qos_configured_state_params.framing = *ase_p++;
1313                 qos_configured_state_params.phy = *ase_p++;
1314                 qos_configured_state_params.max_sdu = (uint16_t)((ase_p[0] << 8) | ase_p[1]);
1315                 ase_p += 2;
1316 
1317                 qos_configured_state_params.retrans_nb = *ase_p++;
1318                 qos_configured_state_params.max_transport_latency =
1319                         (uint16_t)((ase_p[0] << 8) | ase_p[1]);
1320                 ase_p += 2;
1321 
1322                 qos_configured_state_params.pres_delay =
1323                         (uint16_t)((ase_p[0] << 16) | (ase_p[1] << 8) | ase_p[2]);
1324                 ase_p += 3;
1325 
1326                 if (caching) {
1327                   log::info("Device: {}", device->address_);
1328                   if (cached_ase_to_cis_id_map_.count(device->address_) > 0) {
1329                     auto ase_list = cached_ase_to_cis_id_map_.at(device->address_);
1330                     if (ase_list.count(ase_id) > 0) {
1331                       auto cis_id = ase_list.at(ase_id);
1332                       ASSERT_EQ(cis_id, qos_configured_state_params.cis_id);
1333                     } else {
1334                       ase_list[ase_id] = qos_configured_state_params.cis_id;
1335                     }
1336                   } else {
1337                     std::map<int, int> ase_map;
1338                     ase_map[ase_id] = qos_configured_state_params.cis_id;
1339 
1340                     cached_ase_to_cis_id_map_[device->address_] = ase_map;
1341                   }
1342                   cached_qos_configuration_map_[ase_id] = qos_configured_state_params;
1343                 }
1344 
1345                 if (inject_qos_configured) {
1346                   InjectAseStateNotification(ase, device, group, ascs::kAseStateQoSConfigured,
1347                                              &qos_configured_state_params);
1348                 }
1349               }
1350             }));
1351   }
1352 
PrepareCtpNotificationError(LeAudioDeviceGroup * group,uint8_t opcode,uint8_t response_code,uint8_t reason)1353   void PrepareCtpNotificationError(LeAudioDeviceGroup* group, uint8_t opcode, uint8_t response_code,
1354                                    uint8_t reason) {
1355     auto foo = [group, opcode, response_code, reason](LeAudioDevice* device,
1356                                                       std::vector<uint8_t> value,
1357                                                       GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) {
1358       auto num_ase = value[1];
1359       std::vector<uint8_t> notif_value(2 +
1360                                        num_ase * sizeof(struct client_parser::ascs::ctp_ase_entry));
1361       auto* p = notif_value.data();
1362 
1363       UINT8_TO_STREAM(p, opcode);
1364       UINT8_TO_STREAM(p, num_ase);
1365 
1366       auto* ase_p = &value[2];
1367       for (auto i = 0u; i < num_ase; ++i) {
1368         /* Check if this is a valid ASE ID  */
1369         auto ase_id = *ase_p++;
1370         auto it = std::find_if(device->ases_.begin(), device->ases_.end(),
1371                                [ase_id](auto& ase) { return ase.id == ase_id; });
1372         ASSERT_NE(it, device->ases_.end());
1373 
1374         auto meta_len = *ase_p++;
1375         auto num_handled_bytes = ase_p - value.data();
1376         ase_p += meta_len;
1377 
1378         client_parser::ascs::ase_transient_state_params enable_params = {
1379                 .metadata = std::vector<uint8_t>(value.begin() + num_handled_bytes,
1380                                                  value.begin() + num_handled_bytes + meta_len)};
1381 
1382         // Inject error response
1383         UINT8_TO_STREAM(p, ase_id);
1384         UINT8_TO_STREAM(p, response_code);
1385         UINT8_TO_STREAM(p, reason);
1386       }
1387 
1388       LeAudioGroupStateMachine::Get()->ProcessGattCtpNotification(group, notif_value.data(),
1389                                                                   notif_value.size());
1390     };
1391 
1392     switch (opcode) {
1393       case client_parser::ascs::kCtpOpcodeCodecConfiguration:
1394         ON_CALL(ase_ctp_handler, AseCtpConfigureCodecHandler).WillByDefault(Invoke(foo));
1395         break;
1396       case client_parser::ascs::kCtpOpcodeQosConfiguration:
1397         ON_CALL(ase_ctp_handler, AseCtpConfigureQosHandler).WillByDefault(Invoke(foo));
1398         break;
1399       case client_parser::ascs::kCtpOpcodeEnable:
1400         ON_CALL(ase_ctp_handler, AseCtpEnableHandler).WillByDefault(Invoke(foo));
1401         break;
1402       case client_parser::ascs::kCtpOpcodeReceiverStartReady:
1403         ON_CALL(ase_ctp_handler, AseCtpReceiverStartReadyHandler).WillByDefault(Invoke(foo));
1404         break;
1405       case client_parser::ascs::kCtpOpcodeDisable:
1406         ON_CALL(ase_ctp_handler, AseCtpDisableHandler).WillByDefault(Invoke(foo));
1407         break;
1408       case client_parser::ascs::kCtpOpcodeReceiverStopReady:
1409         ON_CALL(ase_ctp_handler, AseCtpReceiverStopReadyHandler).WillByDefault(Invoke(foo));
1410         break;
1411       case client_parser::ascs::kCtpOpcodeUpdateMetadata:
1412         ON_CALL(ase_ctp_handler, AseCtpUpdateMetadataHandler).WillByDefault(Invoke(foo));
1413         break;
1414       case client_parser::ascs::kCtpOpcodeRelease:
1415         ON_CALL(ase_ctp_handler, AseCtpReleaseHandler).WillByDefault(Invoke(foo));
1416         break;
1417       default:
1418         break;
1419     };
1420   }
1421 
PrepareEnableHandler(LeAudioDeviceGroup * group,int verify_ase_count=0,bool inject_enabling=true,bool incject_streaming=true)1422   void PrepareEnableHandler(LeAudioDeviceGroup* group, int verify_ase_count = 0,
1423                             bool inject_enabling = true, bool incject_streaming = true) {
1424     ON_CALL(ase_ctp_handler, AseCtpEnableHandler)
1425             .WillByDefault(Invoke([group, verify_ase_count, inject_enabling, incject_streaming,
1426                                    this](LeAudioDevice* device, std::vector<uint8_t> value,
1427                                          GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) {
1428               auto num_ase = value[1];
1429 
1430               // Verify ase count if needed
1431               if (verify_ase_count) {
1432                 ASSERT_EQ(verify_ase_count, num_ase);
1433               }
1434 
1435               // Inject Streaming ASE state notification for each requested ASE
1436               auto* ase_p = &value[2];
1437               for (auto i = 0u; i < num_ase; ++i) {
1438                 /* Check if this is a valid ASE ID  */
1439                 auto ase_id = *ase_p++;
1440                 auto it = std::find_if(device->ases_.begin(), device->ases_.end(),
1441                                        [ase_id](auto& ase) { return ase.id == ase_id; });
1442                 ASSERT_NE(it, device->ases_.end());
1443                 const auto ase = &(*it);
1444 
1445                 auto meta_len = *ase_p++;
1446                 auto num_handled_bytes = ase_p - value.data();
1447                 ase_p += meta_len;
1448 
1449                 client_parser::ascs::ase_transient_state_params enable_params = {
1450                         .metadata =
1451                                 std::vector<uint8_t>(value.begin() + num_handled_bytes,
1452                                                      value.begin() + num_handled_bytes + meta_len)};
1453 
1454                 // Server does the 'ReceiverStartReady' on its own - goes to
1455                 // Streaming, when in Sink role
1456                 if (ase->direction & bluetooth::le_audio::types::kLeAudioDirectionSink) {
1457                   if (inject_enabling) {
1458                     InjectAseStateNotification(ase, device, group, ascs::kAseStateEnabling,
1459                                                &enable_params);
1460                   }
1461                   if (incject_streaming) {
1462                     InjectAseStateNotification(ase, device, group, ascs::kAseStateStreaming,
1463                                                &enable_params);
1464                   }
1465                 } else {
1466                   if (inject_enabling) {
1467                     InjectAseStateNotification(ase, device, group, ascs::kAseStateEnabling,
1468                                                &enable_params);
1469                   }
1470                 }
1471               }
1472             }));
1473   }
1474 
PrepareDisableHandler(LeAudioDeviceGroup * group,int verify_ase_count=0)1475   void PrepareDisableHandler(LeAudioDeviceGroup* group, int verify_ase_count = 0) {
1476     ON_CALL(ase_ctp_handler, AseCtpDisableHandler)
1477             .WillByDefault(Invoke([group, verify_ase_count, this](
1478                                           LeAudioDevice* device, std::vector<uint8_t> value,
1479                                           GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) {
1480               auto num_ase = value[1];
1481 
1482               // Verify ase count if needed
1483               if (verify_ase_count) {
1484                 ASSERT_EQ(verify_ase_count, num_ase);
1485               }
1486               ASSERT_EQ(value.size(), 2ul + num_ase);
1487 
1488               // Inject Disabling & QoS Conf. ASE state notification for each ASE
1489               auto* ase_p = &value[2];
1490               for (auto i = 0u; i < num_ase; ++i) {
1491                 /* Check if this is a valid ASE ID  */
1492                 auto ase_id = *ase_p++;
1493                 auto it = std::find_if(device->ases_.begin(), device->ases_.end(),
1494                                        [ase_id](auto& ase) { return ase.id == ase_id; });
1495                 ASSERT_NE(it, device->ases_.end());
1496                 const auto ase = &(*it);
1497 
1498                 // The Disabling state is present for Source ASE
1499                 if (ase->direction & bluetooth::le_audio::types::kLeAudioDirectionSource) {
1500                   client_parser::ascs::ase_transient_state_params disabling_params = {
1501                           .metadata = {}};
1502                   InjectAseStateNotification(ase, device, group, ascs::kAseStateDisabling,
1503                                              &disabling_params);
1504                 }
1505 
1506                 // Server does the 'ReceiverStopReady' on its own - goes to
1507                 // Streaming, when in Sink role
1508                 if (ase->direction & bluetooth::le_audio::types::kLeAudioDirectionSink) {
1509                   // FIXME: For now our fake peer does not remember qos params
1510                   client_parser::ascs::ase_qos_configured_state_params qos_configured_state_params;
1511                   InjectAseStateNotification(ase, device, group, ascs::kAseStateQoSConfigured,
1512                                              &qos_configured_state_params);
1513                 }
1514               }
1515             }));
1516   }
1517 
PrepareReceiverStartReadyHandler(LeAudioDeviceGroup * group,int verify_ase_count=0)1518   void PrepareReceiverStartReadyHandler(LeAudioDeviceGroup* group, int verify_ase_count = 0) {
1519     ON_CALL(ase_ctp_handler, AseCtpReceiverStartReadyHandler)
1520             .WillByDefault(Invoke([group, verify_ase_count, this](
1521                                           LeAudioDevice* device, std::vector<uint8_t> value,
1522                                           GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) {
1523               auto num_ase = value[1];
1524 
1525               // Verify ase count if needed
1526               if (verify_ase_count) {
1527                 ASSERT_EQ(verify_ase_count, num_ase);
1528               }
1529 
1530               // Inject Streaming ASE state notification for each Source ASE
1531               auto* ase_p = &value[2];
1532               for (auto i = 0u; i < num_ase; ++i) {
1533                 /* Check if this is a valid ASE ID  */
1534                 auto ase_id = *ase_p++;
1535                 auto it = std::find_if(device->ases_.begin(), device->ases_.end(),
1536                                        [ase_id](auto& ase) { return ase.id == ase_id; });
1537                 ASSERT_NE(it, device->ases_.end());
1538 
1539                 // Once we did the 'ReceiverStartReady' the server goes to
1540                 // Streaming, when in Source role
1541                 const auto& ase = &(*it);
1542                 client_parser::ascs::ase_transient_state_params streaming_params = {
1543                         .metadata = ase->metadata};
1544                 InjectAseStateNotification(ase, device, group, ascs::kAseStateStreaming,
1545                                            &streaming_params);
1546               }
1547             }));
1548   }
1549 
PrepareReceiverStopReady(LeAudioDeviceGroup * group,int verify_ase_count=0)1550   void PrepareReceiverStopReady(LeAudioDeviceGroup* group, int verify_ase_count = 0) {
1551     ON_CALL(ase_ctp_handler, AseCtpReceiverStopReadyHandler)
1552             .WillByDefault(Invoke([group, verify_ase_count, this](
1553                                           LeAudioDevice* device, std::vector<uint8_t> value,
1554                                           GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) {
1555               auto num_ase = value[1];
1556 
1557               // Verify ase count if needed
1558               if (verify_ase_count) {
1559                 ASSERT_EQ(verify_ase_count, num_ase);
1560               }
1561 
1562               // Inject QoS configured ASE state notification for each Source
1563               // ASE
1564               auto* ase_p = &value[2];
1565               for (auto i = 0u; i < num_ase; ++i) {
1566                 /* Check if this is a valid ASE ID  */
1567                 auto ase_id = *ase_p++;
1568                 auto it = std::find_if(device->ases_.begin(), device->ases_.end(),
1569                                        [ase_id](auto& ase) { return ase.id == ase_id; });
1570                 ASSERT_NE(it, device->ases_.end());
1571 
1572                 const auto& ase = &(*it);
1573 
1574                 // FIXME: For now our fake peer does not remember qos params
1575                 client_parser::ascs::ase_qos_configured_state_params qos_configured_state_params;
1576                 InjectAseStateNotification(ase, device, group, ascs::kAseStateQoSConfigured,
1577                                            &qos_configured_state_params);
1578               }
1579             }));
1580   }
1581 
PrepareReleaseHandler(LeAudioDeviceGroup * group,int verify_ase_count=0,bool inject_disconnect_device=false,LeAudioDevice * dev=nullptr)1582   void PrepareReleaseHandler(LeAudioDeviceGroup* group, int verify_ase_count = 0,
1583                              bool inject_disconnect_device = false, LeAudioDevice* dev = nullptr) {
1584     ON_CALL(ase_ctp_handler, AseCtpReleaseHandler)
1585             .WillByDefault(Invoke([group, verify_ase_count, inject_disconnect_device, dev, this](
1586                                           LeAudioDevice* device, std::vector<uint8_t> value,
1587                                           GATT_WRITE_OP_CB /*cb*/, void* /*cb_data*/) {
1588               if (dev != nullptr && device != dev) {
1589                 log::info("Do nothing for {}", dev->address_);
1590                 return;
1591               }
1592 
1593               auto num_ase = value[1];
1594 
1595               // Verify ase count if needed
1596               if (verify_ase_count) {
1597                 ASSERT_EQ(verify_ase_count, num_ase);
1598               }
1599               ASSERT_EQ(value.size(), 2ul + num_ase);
1600 
1601               if (inject_disconnect_device) {
1602                 InjectAclDisconnected(group, device);
1603                 return;
1604               }
1605 
1606               // Inject Releasing & Idle ASE state notification for each ASE
1607               auto* ase_p = &value[2];
1608               for (auto i = 0u; i < num_ase; ++i) {
1609                 /* Check if this is a valid ASE ID  */
1610                 auto ase_id = *ase_p++;
1611                 auto it = std::find_if(device->ases_.begin(), device->ases_.end(),
1612                                        [ase_id](auto& ase) { return ase.id == ase_id; });
1613                 ASSERT_NE(it, device->ases_.end());
1614                 const auto ase = &(*it);
1615 
1616                 InjectAseStateNotification(ase, device, group, ascs::kAseStateReleasing, nullptr);
1617 
1618                 if (stay_in_releasing_state_) {
1619                   continue;
1620                 }
1621 
1622                 /* Check if codec configuration is cached */
1623                 if (cached_codec_configuration_map_.count(ase_id) > 0) {
1624                   InjectAseStateNotification(ase, device, group, ascs::kAseStateCodecConfigured,
1625                                              &cached_codec_configuration_map_[ase_id]);
1626                 } else {
1627                   // Release - no caching
1628                   InjectAseStateNotification(ase, device, group, ascs::kAseStateIdle, nullptr);
1629                 }
1630               }
1631             }));
1632   }
1633 
1634   MockCsisClient mock_csis_client_module_;
1635   NiceMock<bluetooth::manager::MockBtmInterface> btm_interface;
1636   gatt::MockBtaGattInterface gatt_interface;
1637   gatt::MockBtaGattQueue gatt_queue;
1638 
1639   bluetooth::hci::IsoManager* iso_manager_;
1640   bluetooth::hci::iso_manager::cig_create_params last_cig_params_;
1641   MockIsoManager* mock_iso_manager_;
1642   bluetooth::le_audio::CodecManager* codec_manager_;
1643   MockCodecManager* mock_codec_manager_;
1644 
1645   MockAseRemoteStateMachine ase_ctp_handler;
1646   std::map<int, client_parser::ascs::ase_codec_configured_state_params>
1647           cached_codec_configuration_map_;
1648   std::map<int, client_parser::ascs::ase_qos_configured_state_params> cached_qos_configuration_map_;
1649 
1650   std::map<RawAddress, std::map<int, int>> cached_ase_to_cis_id_map_;
1651   std::map<types::ase*, std::vector<uint8_t>> cached_remote_qos_configuration_for_ase_;
1652 
1653   MockLeAudioGroupStateMachineCallbacks mock_callbacks_;
1654   std::vector<std::shared_ptr<LeAudioDevice>> le_audio_devices_;
1655   std::vector<RawAddress> addresses_;
1656   std::map<uint8_t, std::unique_ptr<LeAudioDeviceGroup>> le_audio_device_groups_;
1657   bool group_create_command_disallowed_ = false;
1658   bluetooth::hci::testing::MockControllerInterface controller_;
1659 };
1660 
1661 class StateMachineTest : public StateMachineTestBase {
SetUp()1662   void SetUp() override {
1663     ConfigCodecManagerMock(types::CodecLocation::HOST);
1664     ::bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(
1665             ::bluetooth::le_audio::types::CodecLocation::HOST);
1666     StateMachineTestBase::SetUp();
1667   }
1668 };
1669 
1670 class StateMachineTestNoSwb : public StateMachineTestBase {
SetUp()1671   void SetUp() override {
1672     ConfigCodecManagerMock(types::CodecLocation::HOST);
1673     ::bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(
1674             ::bluetooth::le_audio::types::CodecLocation::HOST);
1675     ON_CALL(*mock_codec_manager_, IsDualBiDirSwbSupported).WillByDefault(Return(false));
1676     StateMachineTestBase::SetUp();
1677   }
1678 };
1679 
1680 class StateMachineTestAdsp : public StateMachineTestBase {
SetUp()1681   void SetUp() override {
1682     ConfigCodecManagerMock(types::CodecLocation::ADSP);
1683     ::bluetooth::le_audio::AudioSetConfigurationProvider::Initialize(
1684             ::bluetooth::le_audio::types::CodecLocation::ADSP);
1685     StateMachineTestBase::SetUp();
1686   }
1687 };
1688 
TEST_F(StateMachineTest,testInit)1689 TEST_F(StateMachineTest, testInit) { ASSERT_NE(LeAudioGroupStateMachine::Get(), nullptr); }
1690 
TEST_F(StateMachineTest,testCleanup)1691 TEST_F(StateMachineTest, testCleanup) {
1692   ASSERT_NE(LeAudioGroupStateMachine::Get(), nullptr);
1693   LeAudioGroupStateMachine::Cleanup();
1694   EXPECT_DEATH(LeAudioGroupStateMachine::Get(), "");
1695 }
1696 
TEST_F(StateMachineTest,testConfigureCodecSingle)1697 TEST_F(StateMachineTest, testConfigureCodecSingle) {
1698   /* Device is banded headphones with 1x snk + 0x src ase
1699    * (1xunidirectional CIS) with channel count 2 (for stereo
1700    */
1701   const auto context_type = kContextTypeRingtone;
1702   const int leaudio_group_id = 2;
1703   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
1704 
1705   // Prepare fake connected device group
1706   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1707 
1708   /* Since we prepared device with Ringtone context in mind, only one ASE
1709    * should have been configured.
1710    */
1711   auto* leAudioDevice = group->GetFirstDevice();
1712   PrepareConfigureCodecHandler(group, 1);
1713 
1714   /* Start the configuration and stream Media content.
1715    * Expect 1 time for the Codec Config call only. */
1716   EXPECT_CALL(gatt_queue,
1717               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
1718                                   GATT_WRITE_NO_RSP, _, _))
1719           .Times(1);
1720 
1721   /* Do nothing on the CigCreate, so the state machine stays in the configure
1722    * state */
1723   ON_CALL(*mock_iso_manager_, CreateCig).WillByDefault(Return());
1724   EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(1);
1725 
1726   InjectInitialIdleNotification(group);
1727 
1728   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1729           group, context_type,
1730           {.sink = types::AudioContexts(context_type),
1731            .source = types::AudioContexts(context_type)}));
1732 
1733   // Check if group has transitioned to a proper state
1734   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
1735 
1736   /* Cancel is called when group goes to streaming. */
1737   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
1738 }
1739 
TEST_F(StateMachineTest,testConfigureCodecSingleFb2)1740 TEST_F(StateMachineTest, testConfigureCodecSingleFb2) {
1741   codec_frame_blocks_per_sdu_ = 2;
1742   bool is_fb2_passed_as_sink_requirement = false;
1743   bool is_fb2_passed_as_source_requirement = false;
1744 
1745   ON_CALL(*mock_codec_manager_, GetCodecConfig)
1746           .WillByDefault(Invoke([&](const bluetooth::le_audio::CodecManager::
1747                                             UnicastConfigurationRequirements& requirements,
1748                                     bluetooth::le_audio::CodecManager::UnicastConfigurationProvider
1749                                             provider) {
1750             auto configs =
1751                     *bluetooth::le_audio::AudioSetConfigurationProvider::Get()->GetConfigurations(
1752                             requirements.audio_context_type);
1753             // Note: This dual bidir SWB exclusion logic has to match the
1754             // CodecManager::GetCodecConfig() implementation.
1755             if (!CodecManager::GetInstance()->IsDualBiDirSwbSupported()) {
1756               configs.erase(std::remove_if(configs.begin(), configs.end(),
1757                                            [](auto const& el) {
1758                                              if (el->confs.source.empty()) {
1759                                                return false;
1760                                              }
1761                                              return AudioSetConfigurationProvider::Get()
1762                                                      ->CheckConfigurationIsDualBiDirSwb(*el);
1763                                            }),
1764                             configs.end());
1765             }
1766 
1767             auto cfg = provider(requirements, &configs);
1768             if (cfg == nullptr) {
1769               return std::unique_ptr<
1770                       bluetooth::le_audio::set_configurations::AudioSetConfiguration>(nullptr);
1771             }
1772 
1773             if (requirements.sink_pacs.has_value()) {
1774               for (auto const& rec : requirements.sink_pacs.value()) {
1775                 auto caps = rec.codec_spec_caps.GetAsCoreCodecCapabilities();
1776                 if (caps.HasSupportedMaxCodecFramesPerSdu()) {
1777                   if (caps.supported_max_codec_frames_per_sdu.value() ==
1778                       codec_frame_blocks_per_sdu_) {
1779                     // Scale by Codec Frames Per SDU = 2
1780                     for (auto& entry : cfg->confs.sink) {
1781                       entry.codec.params.Add(codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
1782                                              (uint8_t)codec_frame_blocks_per_sdu_);
1783                       entry.qos.maxSdu *= codec_frame_blocks_per_sdu_;
1784                       entry.qos.sduIntervalUs *= codec_frame_blocks_per_sdu_;
1785                       entry.qos.max_transport_latency *= codec_frame_blocks_per_sdu_;
1786                     }
1787                     is_fb2_passed_as_sink_requirement = true;
1788                   }
1789                 }
1790               }
1791             }
1792             if (requirements.source_pacs.has_value()) {
1793               for (auto const& rec : requirements.source_pacs.value()) {
1794                 auto caps = rec.codec_spec_caps.GetAsCoreCodecCapabilities();
1795                 if (caps.HasSupportedMaxCodecFramesPerSdu()) {
1796                   if (caps.supported_max_codec_frames_per_sdu.value() ==
1797                       codec_frame_blocks_per_sdu_) {
1798                     // Scale by Codec Frames Per SDU = 2
1799                     for (auto& entry : cfg->confs.source) {
1800                       entry.codec.params.Add(codec_spec_conf::kLeAudioLtvTypeCodecFrameBlocksPerSdu,
1801                                              (uint8_t)codec_frame_blocks_per_sdu_);
1802                       entry.qos.maxSdu *= codec_frame_blocks_per_sdu_;
1803                       entry.qos.sduIntervalUs *= codec_frame_blocks_per_sdu_;
1804                       entry.qos.max_transport_latency *= codec_frame_blocks_per_sdu_;
1805                     }
1806                     is_fb2_passed_as_source_requirement = true;
1807                   }
1808                 }
1809               }
1810             }
1811 
1812             return cfg;
1813           }));
1814 
1815   /* Device is banded headphones with 1x snk + 0x src ase
1816    * (1xunidirectional CIS) with channel count 2 (for stereo
1817    */
1818   const auto context_type = kContextTypeRingtone;
1819   const int leaudio_group_id = 2;
1820   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
1821 
1822   /* Prepare the fake connected device group */
1823   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1824 
1825   /* Since we prepared device with Ringtone context in mind, only one ASE
1826    * should have been configured.
1827    */
1828   auto* leAudioDevice = group->GetFirstDevice();
1829   PrepareConfigureCodecHandler(group, 1);
1830   PrepareConfigureQosHandler(group, 1);
1831 
1832   /* Start the configuration and stream Media content.
1833    * Expect 3 times: for Codec Configure & QoS Configure & Enable */
1834   EXPECT_CALL(gatt_queue,
1835               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
1836                                   GATT_WRITE_NO_RSP, _, _))
1837           .Times(3);
1838 
1839   InjectInitialIdleNotification(group);
1840 
1841   EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(1);
1842   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1843           group, context_type,
1844           {.sink = types::AudioContexts(context_type),
1845            .source = types::AudioContexts(context_type)}));
1846 
1847   /* Check if group has transitioned to a proper state */
1848   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1849 
1850   /* Cancel is called when group goes to streaming. */
1851   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
1852 
1853   ASSERT_TRUE(is_fb2_passed_as_sink_requirement);
1854 
1855   /* Make sure that data interval is based on the codec frame blocks count */
1856   auto data_interval = group->GetActiveConfiguration()->confs.sink.at(0).codec.GetDataIntervalUs();
1857   ASSERT_EQ(data_interval, group->GetActiveConfiguration()
1858                                            ->confs.sink.at(0)
1859                                            .codec.params.GetAsCoreCodecConfig()
1860                                            .GetFrameDurationUs() *
1861                                    codec_frame_blocks_per_sdu_);
1862 
1863   /* Verify CIG parameters */
1864   auto channel_count =
1865           group->GetActiveConfiguration()->confs.sink.at(0).codec.GetChannelCountPerIsoStream();
1866   auto frame_octets = group->GetActiveConfiguration()->confs.sink.at(0).codec.GetOctetsPerFrame();
1867   ASSERT_NE(last_cig_params_.cis_cfgs.size(), 0lu);
1868   ASSERT_EQ(last_cig_params_.sdu_itv_mtos, data_interval);
1869   ASSERT_EQ(last_cig_params_.cis_cfgs.at(0).max_sdu_size_mtos,
1870             codec_frame_blocks_per_sdu_ * channel_count * frame_octets);
1871 }
1872 
TEST_F(StateMachineTest,testConfigureCodecMulti)1873 TEST_F(StateMachineTest, testConfigureCodecMulti) {
1874   const auto context_type = kContextTypeMedia;
1875   const auto leaudio_group_id = 2;
1876   const auto num_devices = 2;
1877 
1878   // Prepare multiple fake connected devices in a group
1879   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
1880   ASSERT_EQ(group->Size(), num_devices);
1881 
1882   PrepareConfigureCodecHandler(group);
1883 
1884   auto expected_devices_written = 0;
1885   auto* leAudioDevice = group->GetFirstDevice();
1886   while (leAudioDevice) {
1887     EXPECT_CALL(gatt_queue,
1888                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
1889                                     GATT_WRITE_NO_RSP, _, _))
1890             .Times(AtLeast(1));
1891     expected_devices_written++;
1892     leAudioDevice = group->GetNextDevice(leAudioDevice);
1893   }
1894   ASSERT_EQ(expected_devices_written, num_devices);
1895 
1896   InjectInitialIdleNotification(group);
1897 
1898   /* Do nothing on the CigCreate, so the state machine stays in the configure
1899    * state */
1900   ON_CALL(*mock_iso_manager_, CreateCig).WillByDefault(Return());
1901   EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(1);
1902 
1903   // Start the configuration and stream the content
1904   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1905           group, context_type,
1906           {.sink = types::AudioContexts(context_type),
1907            .source = types::AudioContexts(context_type)}));
1908 
1909   // Check if group has transitioned to a proper state
1910   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
1911 
1912   /* Cancel is called when group goes to streaming. */
1913   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
1914 }
1915 
TEST_F(StateMachineTest,testConfigureQosSingle)1916 TEST_F(StateMachineTest, testConfigureQosSingle) {
1917   /* Device is banded headphones with 2x snk + 1x src ase
1918    * (1x bidirectional + 1xunidirectional CIS)
1919    */
1920   additional_snk_ases = 1;
1921   additional_src_ases = 1;
1922   const auto context_type = kContextTypeRingtone;
1923   const int leaudio_group_id = 3;
1924 
1925   // Prepare fake connected device group
1926   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1927 
1928   /* Since we prepared device with Ringtone context in mind, only one ASE
1929    * should have been configured.
1930    */
1931   auto* leAudioDevice = group->GetFirstDevice();
1932   PrepareConfigureCodecHandler(group, 2);
1933   PrepareConfigureQosHandler(group, 2);
1934 
1935   // Start the configuration and stream Media content
1936   EXPECT_CALL(gatt_queue,
1937               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
1938                                   GATT_WRITE_NO_RSP, _, _))
1939           .Times(3);
1940 
1941   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1942   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
1943   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
1944   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1945   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1946   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1947 
1948   InjectInitialIdleNotification(group);
1949 
1950   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1951           group, context_type,
1952           {.sink = types::AudioContexts(context_type),
1953            .source = types::AudioContexts(context_type)}));
1954 
1955   // Check if group has transitioned to a proper state
1956   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1957 
1958   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
1959 }
1960 
TEST_F(StateMachineTest,testConfigureQosSingleRecoverCig)1961 TEST_F(StateMachineTest, testConfigureQosSingleRecoverCig) {
1962   /* Device is banded headphones with 2x snk + 1x src ase
1963    * (1x bidirectional + 1xunidirectional CIS)
1964    */
1965   additional_snk_ases = 1;
1966   additional_src_ases = 1;
1967   const auto context_type = kContextTypeRingtone;
1968   const int leaudio_group_id = 3;
1969 
1970   /* Assume that on previous BT OFF CIG was not removed */
1971   group_create_command_disallowed_ = true;
1972 
1973   // Prepare fake connected device group
1974   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1975 
1976   /* Since we prepared device with Ringtone context in mind, only one ASE
1977    * should have been configured.
1978    */
1979   auto* leAudioDevice = group->GetFirstDevice();
1980   PrepareConfigureCodecHandler(group, 2);
1981   PrepareConfigureQosHandler(group, 2);
1982 
1983   // Start the configuration and stream Media content
1984   EXPECT_CALL(gatt_queue,
1985               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
1986                                   GATT_WRITE_NO_RSP, _, _))
1987           .Times(3);
1988 
1989   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(2);
1990   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
1991   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
1992   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
1993   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1994   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1995 
1996   InjectInitialIdleNotification(group);
1997 
1998   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1999           group, context_type,
2000           {.sink = types::AudioContexts(context_type),
2001            .source = types::AudioContexts(context_type)}));
2002 
2003   // Check if group has transitioned to a proper state
2004   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
2005   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
2006 }
2007 
TEST_F(StateMachineTest,testConfigureQosMultiple)2008 TEST_F(StateMachineTest, testConfigureQosMultiple) {
2009   const auto context_type = kContextTypeMedia;
2010   const auto leaudio_group_id = 3;
2011   const auto num_devices = 2;
2012 
2013   // Prepare multiple fake connected devices in a group
2014   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2015   ASSERT_EQ(group->Size(), num_devices);
2016 
2017   PrepareConfigureCodecHandler(group);
2018   PrepareConfigureQosHandler(group);
2019 
2020   auto* leAudioDevice = group->GetFirstDevice();
2021   auto expected_devices_written = 0;
2022   while (leAudioDevice) {
2023     EXPECT_CALL(gatt_queue,
2024                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2025                                     GATT_WRITE_NO_RSP, _, _))
2026             .Times(AtLeast(2));
2027     expected_devices_written++;
2028     leAudioDevice = group->GetNextDevice(leAudioDevice);
2029   }
2030   ASSERT_EQ(expected_devices_written, num_devices);
2031 
2032   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2033   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2034   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2035   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2036   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2037   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2038 
2039   InjectInitialIdleNotification(group);
2040 
2041   // Start the configuration and stream Media content
2042   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2043           group, context_type,
2044           {.sink = types::AudioContexts(context_type),
2045            .source = types::AudioContexts(context_type)}));
2046 
2047   // Check if group has transitioned to a proper state
2048   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
2049   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
2050 }
2051 
TEST_F(StateMachineTest,testConfigureQosFailed)2052 TEST_F(StateMachineTest, testConfigureQosFailed) {
2053   const auto context_type = kContextTypeMedia;
2054   const auto leaudio_group_id = 3;
2055   const auto num_devices = 2;
2056 
2057   // Check if CIG is properly cleared when QoS failed
2058 
2059   // Prepare multiple fake connected devices in a group
2060   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2061   ASSERT_EQ(group->Size(), num_devices);
2062 
2063   PrepareConfigureCodecHandler(group);
2064   PrepareCtpNotificationError(
2065           group, client_parser::ascs::kCtpOpcodeQosConfiguration,
2066           client_parser::ascs::kCtpResponseCodeInvalidConfigurationParameterValue,
2067           client_parser::ascs::kCtpResponsePhy);
2068   PrepareReleaseHandler(group);
2069 
2070   auto* leAudioDevice = group->GetFirstDevice();
2071   auto expected_devices_written = 0;
2072   while (leAudioDevice) {
2073     EXPECT_CALL(gatt_queue,
2074                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2075                                     GATT_WRITE_NO_RSP, _, _))
2076             .Times(AtLeast(2));
2077     expected_devices_written++;
2078     leAudioDevice = group->GetNextDevice(leAudioDevice);
2079   }
2080   ASSERT_EQ(expected_devices_written, num_devices);
2081 
2082   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2083   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2084   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2085   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2086   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2087   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2088 
2089   InjectInitialIdleNotification(group);
2090 
2091   // Start the configuration and stream Media content
2092   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2093           group, context_type,
2094           {.sink = types::AudioContexts(context_type),
2095            .source = types::AudioContexts(context_type)}));
2096 
2097   // Check if group has transitioned to a proper state
2098   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2099   ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
2100 
2101   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
2102 }
2103 
TEST_F(StateMachineTest,testDeviceDisconnectedWhileCigCreated)2104 TEST_F(StateMachineTest, testDeviceDisconnectedWhileCigCreated) {
2105   const auto context_type = kContextTypeMedia;
2106   const auto leaudio_group_id = 3;
2107   const auto num_devices = 1;
2108 
2109   // verify proper cleaning when group is disconnected while CIG is creating.
2110 
2111   // Prepare fake connected device in a group
2112   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2113   ASSERT_EQ(group->Size(), num_devices);
2114 
2115   PrepareConfigureCodecHandler(group);
2116 
2117   ON_CALL(*mock_iso_manager_, CreateCig).WillByDefault(Return());
2118 
2119   auto* leAudioDevice = group->GetFirstDevice();
2120   EXPECT_CALL(gatt_queue,
2121               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2122                                   GATT_WRITE_NO_RSP, _, _))
2123           .Times(1);
2124 
2125   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2126   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2127   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2128   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2129   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2130 
2131   InjectInitialIdleNotification(group);
2132 
2133   // Start the configuration and stream Media content
2134   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2135           group, context_type,
2136           {.sink = types::AudioContexts(context_type),
2137            .source = types::AudioContexts(context_type)}));
2138 
2139   // Check if group has transitioned to a proper state
2140   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
2141 
2142   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
2143 
2144   InjectAclDisconnected(group, leAudioDevice);
2145   std::vector<uint16_t> conn_handles = {0x0001, 0x0002};
2146   int cig_id = 1;
2147 
2148   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2149   LeAudioGroupStateMachine::Get()->ProcessHciNotifOnCigCreate(group, HCI_SUCCESS, cig_id,
2150                                                               conn_handles);
2151 
2152   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2153   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
2154 }
2155 
TEST_F(StateMachineTest,testStreamCreationError)2156 TEST_F(StateMachineTest, testStreamCreationError) {
2157   /* Device is banded headphones with 1x snk + 0x src ase
2158    * (1xunidirectional CIS) with channel count 2 (for stereo
2159    */
2160   const auto context_type = kContextTypeRingtone;
2161   const int leaudio_group_id = 4;
2162   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
2163 
2164   // Prepare fake connected device group
2165   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2166 
2167   /* Ringtone with channel count 1 for single device and 1 ASE sink will
2168    * end up with 1 Sink ASE being configured.
2169    */
2170   PrepareConfigureCodecHandler(group, 1);
2171   PrepareConfigureQosHandler(group, 1);
2172   PrepareCtpNotificationError(group, client_parser::ascs::kCtpOpcodeEnable,
2173                               client_parser::ascs::kCtpResponseCodeUnspecifiedError,
2174                               client_parser::ascs::kCtpResponseNoReason);
2175   PrepareReleaseHandler(group);
2176 
2177   auto* leAudioDevice = group->GetFirstDevice();
2178 
2179   /*
2180    * 1 - Configure ASE
2181    * 2 - QoS ASE
2182    * 3 - Enable ASE
2183    * 4 - Release ASE
2184    */
2185   EXPECT_CALL(gatt_queue,
2186               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2187                                   GATT_WRITE_NO_RSP, _, _))
2188           .Times(4);
2189 
2190   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2191   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2192   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2193   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2194   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2195   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2196 
2197   InjectInitialIdleNotification(group);
2198 
2199   // Validate GroupStreamStatus
2200   EXPECT_CALL(mock_callbacks_,
2201               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
2202   EXPECT_CALL(mock_callbacks_,
2203               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
2204 
2205   // Start the configuration and stream Media content
2206   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2207           group, context_type,
2208           {.sink = types::AudioContexts(context_type),
2209            .source = types::AudioContexts(context_type)}));
2210 
2211   // Check if group has transitioned to a proper state
2212   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2213   ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
2214 }
2215 
TEST_F(StateMachineTest,testStreamSingle)2216 TEST_F(StateMachineTest, testStreamSingle) {
2217   /* Device is banded headphones with 1x snk + 0x src ase
2218    * (1xunidirectional CIS) with channel count 2 (for stereo
2219    */
2220   const auto context_type = kContextTypeRingtone;
2221   const int leaudio_group_id = 4;
2222   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
2223 
2224   // Prepare fake connected device group
2225   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2226 
2227   /* Ringtone with channel count 1 for single device and 1 ASE sink will
2228    * end up with 1 Sink ASE being configured.
2229    */
2230   PrepareConfigureCodecHandler(group, 1);
2231   PrepareConfigureQosHandler(group, 1);
2232   PrepareEnableHandler(group, 1);
2233 
2234   auto* leAudioDevice = group->GetFirstDevice();
2235   EXPECT_CALL(gatt_queue,
2236               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2237                                   GATT_WRITE_NO_RSP, _, _))
2238           .Times(3);
2239 
2240   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2241   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
2242   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
2243   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2244   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2245   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2246 
2247   InjectInitialIdleNotification(group);
2248 
2249   // Validate GroupStreamStatus
2250   EXPECT_CALL(mock_callbacks_,
2251               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
2252 
2253   // Start the configuration and stream Media content
2254   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2255           group, context_type,
2256           {.sink = types::AudioContexts(context_type),
2257            .source = types::AudioContexts(context_type)}));
2258 
2259   // Check if group has transitioned to a proper state
2260   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2261   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2262 }
2263 
TEST_F(StateMachineTest,testStreamSingleRetryCisFailure)2264 TEST_F(StateMachineTest, testStreamSingleRetryCisFailure) {
2265   /* Device is banded headphones with 1x snk + 0x src ase
2266    * (1xunidirectional CIS) with channel count 2 (for stereo
2267    */
2268   const auto context_type = kContextTypeRingtone;
2269   const int leaudio_group_id = 4;
2270   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
2271 
2272   // Prepare fake connected device group
2273   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2274 
2275   /* Ringtone with channel count 1 for single device and 1 ASE sink will
2276    * end up with 1 Sink ASE being configured.
2277    */
2278   PrepareConfigureCodecHandler(group, 1);
2279   PrepareConfigureQosHandler(group, 1);
2280   PrepareEnableHandler(group, 1);
2281   PrepareReleaseHandler(group);
2282 
2283   use_cis_retry_cnt_ = true;
2284   retry_cis_established_cnt_ = 4;
2285 
2286   auto* leAudioDevice = group->GetFirstDevice();
2287   EXPECT_CALL(gatt_queue,
2288               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2289                                   GATT_WRITE_NO_RSP, _, _))
2290           .Times(4);
2291 
2292   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2293   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(3);
2294   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2295   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2296   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2297   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2298 
2299   InjectInitialIdleNotification(group);
2300 
2301   // Validate GroupStreamStatus
2302   EXPECT_CALL(mock_callbacks_,
2303               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
2304   EXPECT_CALL(mock_callbacks_,
2305               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
2306 
2307   // Start the configuration and stream Media content
2308   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2309           group, context_type,
2310           {.sink = types::AudioContexts(context_type),
2311            .source = types::AudioContexts(context_type)}));
2312 
2313   // Check if group has transitioned to a proper state
2314   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2315   ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
2316 }
2317 
TEST_F(StateMachineTest,testStreamSingleRetryCisSuccess)2318 TEST_F(StateMachineTest, testStreamSingleRetryCisSuccess) {
2319   /* Device is banded headphones with 1x snk + 0x src ase
2320    * (1xunidirectional CIS) with channel count 2 (for stereo
2321    */
2322   const auto context_type = kContextTypeRingtone;
2323   const int leaudio_group_id = 4;
2324   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
2325 
2326   // Prepare fake connected device group
2327   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2328 
2329   /* Ringtone with channel count 1 for single device and 1 ASE sink will
2330    * end up with 1 Sink ASE being configured.
2331    */
2332   PrepareConfigureCodecHandler(group, 1);
2333   PrepareConfigureQosHandler(group, 1);
2334   PrepareEnableHandler(group, 1);
2335 
2336   use_cis_retry_cnt_ = true;
2337   retry_cis_established_cnt_ = 2;
2338 
2339   auto* leAudioDevice = group->GetFirstDevice();
2340   EXPECT_CALL(gatt_queue,
2341               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2342                                   GATT_WRITE_NO_RSP, _, _))
2343           .Times(3);
2344 
2345   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2346   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(3);
2347   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
2348   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2349   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2350   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2351 
2352   InjectInitialIdleNotification(group);
2353 
2354   // Validate GroupStreamStatus
2355   EXPECT_CALL(mock_callbacks_,
2356               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
2357 
2358   // Start the configuration and stream Media content
2359   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2360           group, context_type,
2361           {.sink = types::AudioContexts(context_type),
2362            .source = types::AudioContexts(context_type)}));
2363 
2364   // Check if group has transitioned to a proper state
2365   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2366   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2367 }
2368 
TEST_F(StateMachineTest,testStreamSkipEnablingSink)2369 TEST_F(StateMachineTest, testStreamSkipEnablingSink) {
2370   /* Device is banded headphones with 2x snk + none src ase
2371    * (2x unidirectional CIS)
2372    */
2373 
2374   /* Not, that when remote device skip Enabling it is considered as an error and
2375    * group will not be able to go to Streaming state.
2376    * It is because, Android is not creating CISes before all ASEs gets into
2377    * Enabling state, therefore it is impossible to remote device to skip
2378    * Enabling state.
2379    */
2380   const auto context_type = kContextTypeMedia;
2381   const int leaudio_group_id = 4;
2382 
2383   // Prepare fake connected device group
2384   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2385 
2386   /* For Media context type with channel count 1 and two ASEs,
2387    * there should have be 2 Ases configured configured.
2388    */
2389   PrepareConfigureCodecHandler(group, 2);
2390   PrepareConfigureQosHandler(group, 2);
2391   PrepareEnableHandler(group, 2, false);
2392 
2393   /*
2394    * 1. Configure
2395    * 2. QoS Config
2396    * 3. Enable
2397    * 4. Release
2398    */
2399   auto* leAudioDevice = group->GetFirstDevice();
2400   EXPECT_CALL(gatt_queue,
2401               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2402                                   GATT_WRITE_NO_RSP, _, _))
2403           .Times(4);
2404 
2405   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2406   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2407   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2408   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2409   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2410   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2411 
2412   InjectInitialIdleNotification(group);
2413 
2414   // Validate GroupStreamStatus
2415   EXPECT_CALL(mock_callbacks_,
2416               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
2417           .Times(0);
2418 
2419   EXPECT_CALL(mock_callbacks_,
2420               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING))
2421           .Times(1);
2422 
2423   // Start the configuration and stream Media content
2424   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2425           group, context_type,
2426           {.sink = types::AudioContexts(context_type),
2427            .source = types::AudioContexts(context_type)}));
2428 
2429   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2430 }
2431 
TEST_F(StateMachineTest,testStreamSkipEnablingSinkSource)2432 TEST_F(StateMachineTest, testStreamSkipEnablingSinkSource) {
2433   /* Device is banded headphones with 2x snk + 1x src ase
2434    * (1x bidirectional CIS)
2435    */
2436   const auto context_type = kContextTypeConversational;
2437   const int leaudio_group_id = 4;
2438 
2439   additional_snk_ases = 1;
2440 
2441   // Prepare fake connected device group
2442   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2443 
2444   /* Since we prepared device with Conversional context in mind,
2445    * 2 Sink ASEs and 1 Source ASE should have been configured.
2446    */
2447   PrepareConfigureCodecHandler(group, 3);
2448   PrepareConfigureQosHandler(group, 3);
2449   PrepareEnableHandler(group, 3, false);
2450   PrepareReceiverStartReadyHandler(group, 1);
2451 
2452   /*
2453    * 1. Codec Config
2454    * 2. Qos Config
2455    * 3. Enable
2456    * 4. Release
2457    */
2458   auto* leAudioDevice = group->GetFirstDevice();
2459   EXPECT_CALL(gatt_queue,
2460               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2461                                   GATT_WRITE_NO_RSP, _, _))
2462           .Times(4);
2463 
2464   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2465   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2466   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2467   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2468   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2469   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2470 
2471   InjectInitialIdleNotification(group);
2472 
2473   // Validate GroupStreamStatus
2474   EXPECT_CALL(mock_callbacks_,
2475               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
2476           .Times(0);
2477   EXPECT_CALL(mock_callbacks_,
2478               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING))
2479           .Times(1);
2480 
2481   // Start the configuration and stream Media content
2482   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2483           group, context_type,
2484           {.sink = types::AudioContexts(context_type),
2485            .source = types::AudioContexts(context_type)}));
2486 
2487   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2488 }
2489 
TEST_F(StateMachineTest,testStreamMultipleMedia_OneMemberHasNoAses)2490 TEST_F(StateMachineTest, testStreamMultipleMedia_OneMemberHasNoAses) {
2491   const auto context_type = kContextTypeMedia;
2492   const auto leaudio_group_id = 4;
2493   const auto num_devices = 2;
2494 
2495   // Prepare multiple fake connected devices in a group. This time one device
2496   // has 0 Ases
2497   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
2498                                              types::AudioContexts(), true);
2499   ASSERT_EQ(group->Size(), num_devices);
2500 
2501   PrepareConfigureCodecHandler(group);
2502   PrepareConfigureQosHandler(group);
2503   PrepareEnableHandler(group);
2504   PrepareReceiverStartReadyHandler(group);
2505 
2506   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2507   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
2508   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
2509   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2510   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2511   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2512 
2513   InjectInitialIdleNotification(group);
2514 
2515   /* Check there are two devices*/
2516   auto* leAudioDevice = group->GetFirstDevice();
2517   auto* secondDevice = group->GetNextDevice(leAudioDevice);
2518   /*
2519    * Second set member has no ASEs, no operations on control point are expected
2520    * 0
2521    */
2522   EXPECT_CALL(gatt_queue,
2523               WriteCharacteristic(secondDevice->conn_id_, secondDevice->ctp_hdls_.val_hdl, _,
2524                                   GATT_WRITE_NO_RSP, _, _))
2525           .Times(0);
2526 
2527   /*
2528    * First device will be configured for Streaming. Expecting 3 operations:
2529    * 1. Codec Config
2530    * 2. QoS Config
2531    * 3. Enable
2532    */
2533   EXPECT_CALL(gatt_queue,
2534               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2535                                   GATT_WRITE_NO_RSP, _, _))
2536           .Times(3);
2537 
2538   // Validate GroupStreamStatus
2539   EXPECT_CALL(mock_callbacks_,
2540               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
2541 
2542   // Start the configuration and stream Media content
2543   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2544           group, context_type,
2545           {.sink = types::AudioContexts(context_type),
2546            .source = types::AudioContexts(context_type)}));
2547 
2548   // Check if group has transitioned to a proper state
2549   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2550   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2551 }
2552 
TEST_F(StateMachineTest,testStreamMultipleMedia_OneMemberHasNoAsesAndNotConnected)2553 TEST_F(StateMachineTest, testStreamMultipleMedia_OneMemberHasNoAsesAndNotConnected) {
2554   const auto context_type = kContextTypeMedia;
2555   const auto leaudio_group_id = 4;
2556   const auto num_devices = 2;
2557 
2558   // Prepare multiple fake connected devices in a group. This time one device
2559   // has 0 Ases
2560   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
2561                                              types::AudioContexts(), true);
2562   ASSERT_EQ(group->Size(), num_devices);
2563 
2564   PrepareConfigureCodecHandler(group);
2565   PrepareConfigureQosHandler(group);
2566   PrepareEnableHandler(group);
2567   PrepareReceiverStartReadyHandler(group);
2568 
2569   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2570   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
2571   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
2572   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2573   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2574   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2575 
2576   InjectInitialIdleNotification(group);
2577 
2578   /* Check there are two devices*/
2579   auto* leAudioDevice = group->GetFirstDevice();
2580   auto* secondDevice = group->GetNextDevice(leAudioDevice);
2581   /*
2582    * Second set member has no ASEs, no operations on control point are expected
2583    * 0
2584    */
2585   EXPECT_CALL(gatt_queue,
2586               WriteCharacteristic(secondDevice->conn_id_, secondDevice->ctp_hdls_.val_hdl, _,
2587                                   GATT_WRITE_NO_RSP, _, _))
2588           .Times(0);
2589 
2590   /* Device with 0 Ases is disconnected */
2591   InjectAclDisconnected(group, secondDevice);
2592 
2593   /*
2594    * First device will be configured for Streaming. Expecting 3 operations:
2595    * 1. Codec Config
2596    * 2. QoS Config
2597    * 3. Enable
2598    */
2599   EXPECT_CALL(gatt_queue,
2600               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2601                                   GATT_WRITE_NO_RSP, _, _))
2602           .Times(3);
2603 
2604   // Validate GroupStreamStatus
2605   EXPECT_CALL(mock_callbacks_,
2606               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
2607 
2608   // Start the configuration and stream Media content
2609   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2610           group, context_type,
2611           {.sink = types::AudioContexts(context_type),
2612            .source = types::AudioContexts(context_type)}));
2613 
2614   // Check if group has transitioned to a proper state
2615   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2616   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2617 }
2618 
TEST_F(StateMachineTest,testStreamSingleConversational_TwsWithTwoBidirectional)2619 TEST_F(StateMachineTest, testStreamSingleConversational_TwsWithTwoBidirectional) {
2620   const auto context_type = kContextTypeConversational;
2621   const auto leaudio_group_id = 4;
2622   const auto num_devices = 1;
2623 
2624   /* Conversational to single device which has 4 ASE Sink and 2 ASE Source and channel count 1.
2625    * This should result with CIG configured with 2 bidirectional channels .
2626    */
2627 
2628   additional_snk_ases = 3;
2629   additional_src_ases = 1;
2630 
2631   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2632   ASSERT_EQ(group->Size(), num_devices);
2633 
2634   PrepareConfigureCodecHandler(group);
2635   PrepareConfigureQosHandler(group);
2636   PrepareEnableHandler(group);
2637   PrepareReceiverStartReadyHandler(group);
2638 
2639   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2640   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
2641   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
2642   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2643   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2644   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2645 
2646   InjectInitialIdleNotification(group);
2647 
2648   auto* leAudioDevice = group->GetFirstDevice();
2649   auto expected_devices_written = 0;
2650   while (leAudioDevice) {
2651     EXPECT_CALL(gatt_queue,
2652                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2653                                     GATT_WRITE_NO_RSP, _, _))
2654             .Times(4);
2655     expected_devices_written++;
2656     leAudioDevice = group->GetNextDevice(leAudioDevice);
2657   }
2658   ASSERT_EQ(expected_devices_written, num_devices);
2659 
2660   // Validate GroupStreamStatus
2661   EXPECT_CALL(mock_callbacks_,
2662               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
2663 
2664   // Start the configuration and stream Media content
2665   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2666           group, context_type,
2667           {.sink = types::AudioContexts(context_type),
2668            .source = types::AudioContexts(context_type)}));
2669 
2670   // Check if group has transitioned to a proper state
2671   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2672   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2673 }
2674 
TEST_F(StateMachineTest,testStreamMultipleConversational)2675 TEST_F(StateMachineTest, testStreamMultipleConversational) {
2676   const auto context_type = kContextTypeConversational;
2677   const auto leaudio_group_id = 4;
2678   const auto num_devices = 2;
2679 
2680   // Prepare multiple fake connected devices in a group
2681   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2682   ASSERT_EQ(group->Size(), num_devices);
2683 
2684   PrepareConfigureCodecHandler(group);
2685   PrepareConfigureQosHandler(group);
2686   PrepareEnableHandler(group);
2687   PrepareReceiverStartReadyHandler(group);
2688 
2689   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2690   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
2691   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
2692   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2693   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2694   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2695 
2696   InjectInitialIdleNotification(group);
2697 
2698   auto* leAudioDevice = group->GetFirstDevice();
2699   auto expected_devices_written = 0;
2700   while (leAudioDevice) {
2701     EXPECT_CALL(gatt_queue,
2702                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2703                                     GATT_WRITE_NO_RSP, _, _))
2704             .Times(4);
2705     expected_devices_written++;
2706     leAudioDevice = group->GetNextDevice(leAudioDevice);
2707   }
2708   ASSERT_EQ(expected_devices_written, num_devices);
2709 
2710   // Validate GroupStreamStatus
2711   EXPECT_CALL(mock_callbacks_,
2712               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
2713 
2714   // Start the configuration and stream Media content
2715   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2716           group, context_type,
2717           {.sink = types::AudioContexts(context_type),
2718            .source = types::AudioContexts(context_type)}));
2719 
2720   // Check if group has transitioned to a proper state
2721   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2722   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
2723 }
2724 
2725 MATCHER_P(dataPathDirIsEq, expected, "") { return arg.data_path_dir == expected; }
2726 
TEST_F(StateMachineTest,testFailedStreamMultipleConversational)2727 TEST_F(StateMachineTest, testFailedStreamMultipleConversational) {
2728   /* Testing here CIS Failed to be established */
2729   const auto context_type = kContextTypeConversational;
2730   const auto leaudio_group_id = 4;
2731   const auto num_devices = 2;
2732   overwrite_cis_status_ = true;
2733 
2734   cis_status_.resize(2);
2735   cis_status_[0] = 0x00;
2736   cis_status_[1] = 0x0e;  // Failed to be established
2737 
2738   // Prepare multiple fake connected devices in a group
2739   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2740   ASSERT_EQ(group->Size(), num_devices);
2741 
2742   PrepareConfigureCodecHandler(group);
2743   PrepareConfigureQosHandler(group);
2744   PrepareEnableHandler(group);
2745   PrepareReceiverStartReadyHandler(group);
2746   PrepareReleaseHandler(group);
2747 
2748   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2749   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
2750 
2751   /* Bidirectional CIS data path is configured in tw ocalls and removed for both
2752    * directions with a single call.
2753    */
2754   EXPECT_CALL(*mock_iso_manager_,
2755               SetupIsoDataPath(
2756                       _, dataPathDirIsEq(bluetooth::hci::iso_manager::kIsoDataPathDirectionIn)))
2757           .Times(1);
2758   EXPECT_CALL(*mock_iso_manager_,
2759               SetupIsoDataPath(
2760                       _, dataPathDirIsEq(bluetooth::hci::iso_manager::kIsoDataPathDirectionOut)))
2761           .Times(1);
2762   EXPECT_CALL(*mock_iso_manager_,
2763               RemoveIsoDataPath(
2764                       _, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput |
2765                                  bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput))
2766           .Times(1);
2767 
2768   /* This check is the major one in this test, as we want to make sure,
2769    * it will not be called twice but only once (when both bidirectional ASEs are
2770    * not in the STREAMING or ENABLING state)
2771    */
2772   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
2773 
2774   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2775 
2776   InjectInitialIdleNotification(group);
2777 
2778   auto* leAudioDevice = group->GetFirstDevice();
2779 
2780   /* First device Control Point actions
2781    * Codec Config
2782    * QoS Config
2783    * Enable
2784    * Receiver ready
2785    * Release
2786    */
2787   EXPECT_CALL(gatt_queue,
2788               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2789                                   GATT_WRITE_NO_RSP, _, _))
2790           .Times(5);
2791   leAudioDevice = group->GetNextDevice(leAudioDevice);
2792 
2793   /* Second device Control Point actions
2794    * Codec Config
2795    * QoS Config
2796    * Enable (failed on CIS established - therefore no Receiver Ready)
2797    * Release
2798    */
2799   EXPECT_CALL(gatt_queue,
2800               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2801                                   GATT_WRITE_NO_RSP, _, _))
2802           .Times(4);
2803 
2804   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
2805   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
2806 
2807   // Start the configuration and stream Media content
2808   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2809           group, context_type,
2810           {.sink = types::AudioContexts(context_type),
2811            .source = types::AudioContexts(context_type)}));
2812 
2813   // Check if group has transitioned to a proper state
2814   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2815 
2816   /* Called twice. One when change target state from Streaming to IDLE,
2817    * and second time, when state machine entered IDLE.
2818    */
2819   ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
2820 }
2821 
TEST_F(StateMachineTest,testAttachToStreamWhileFirstDeviceIsStartingStream)2822 TEST_F(StateMachineTest, testAttachToStreamWhileFirstDeviceIsStartingStream) {
2823   /* Testing here CIS Failed to be established */
2824   const auto context_type = kContextTypeConversational;
2825   const auto leaudio_group_id = 4;
2826   const auto num_devices = 2;
2827 
2828   // Prepare multiple fake connected devices in a group
2829   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2830   ASSERT_EQ(group->Size(), num_devices);
2831 
2832   PrepareConfigureCodecHandler(group);
2833   PrepareConfigureQosHandler(group);
2834   PrepareEnableHandler(group, 0, true /* inject enabling */, false /* inject streaming*/);
2835   PrepareReleaseHandler(group);
2836 
2837   InjectInitialIdleNotification(group);
2838   auto firstDevice = group->GetFirstDevice();
2839   auto lastDevice = group->GetNextDevice(firstDevice);
2840 
2841   /* Disconnect first device */
2842   InjectAclDisconnected(group, firstDevice);
2843 
2844   // Start the configuration and stream Media content
2845   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2846           group, context_type,
2847           {.sink = types::AudioContexts(context_type),
2848            .source = types::AudioContexts(context_type)}));
2849 
2850   // Now, group is not yet in the streaming state. Let's simulated the other
2851   // device got connected
2852   firstDevice->conn_id_ = 1;
2853   firstDevice->SetConnectionState(DeviceConnectState::CONNECTED);
2854 
2855   for (auto& ase : lastDevice->ases_) {
2856     std::vector<uint8_t> params{};
2857     if (ase.active) {
2858       InjectAseStateNotification(&ase, lastDevice, group, ascs::kAseStateStreaming, &params);
2859     }
2860   }
2861 
2862   // Check if group has transitioned to a proper state
2863   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2864 }
2865 
TEST_F(StateMachineTest,testFailedStreamCreation)2866 TEST_F(StateMachineTest, testFailedStreamCreation) {
2867   /* Testing here different error than CIS Failed to be established */
2868   const auto context_type = kContextTypeConversational;
2869   const auto leaudio_group_id = 4;
2870   const auto num_devices = 2;
2871 
2872   // Prepare multiple fake connected devices in a group
2873   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2874   ASSERT_EQ(group->Size(), num_devices);
2875 
2876   PrepareConfigureCodecHandler(group);
2877   PrepareConfigureQosHandler(group);
2878   PrepareEnableHandler(group, 0, true /* inject enabling */, false /* inject streaming*/);
2879   PrepareReleaseHandler(group);
2880 
2881   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2882   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
2883   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2884   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2885   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
2886   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2887 
2888   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
2889   ON_CALL(*mock_iso_manager_, EstablishCis).WillByDefault(Return());
2890 
2891   InjectInitialIdleNotification(group);
2892 
2893   auto* leAudioDevice = group->GetFirstDevice();
2894 
2895   /* First device Control Point actions
2896    * Codec Config
2897    * QoS Config
2898    * Enable
2899    * Release
2900    */
2901   EXPECT_CALL(gatt_queue,
2902               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2903                                   GATT_WRITE_NO_RSP, _, _))
2904           .Times(4);
2905   leAudioDevice = group->GetNextDevice(leAudioDevice);
2906 
2907   /* Second device Control Point actions
2908    * Codec Config
2909    * QoS Config
2910    * Enable (failed on CIS established - therefore no Receiver Ready)
2911    * Release
2912    */
2913   EXPECT_CALL(gatt_queue,
2914               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2915                                   GATT_WRITE_NO_RSP, _, _))
2916           .Times(4);
2917 
2918   // Start the configuration and stream Media content
2919   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2920           group, context_type,
2921           {.sink = types::AudioContexts(context_type),
2922            .source = types::AudioContexts(context_type)}));
2923 
2924   bluetooth::hci::iso_manager::cis_establish_cmpl_evt evt;
2925   evt.status = HCI_ERR_LMP_RESPONSE_TIMEOUT;
2926 
2927   LeAudioGroupStateMachine::Get()->ProcessHciNotifCisEstablished(group, leAudioDevice, &evt);
2928 
2929   // Check if group has transitioned to a proper state
2930   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2931 
2932   /* Called twice. One when change target state from Streaming to IDLE,
2933    * and second time, when state machine entered IDLE.
2934    */
2935   ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
2936 }
2937 
TEST_F(StateMachineTest,remoteRejectsEnable)2938 TEST_F(StateMachineTest, remoteRejectsEnable) {
2939   /* Testing here CIS Failed to be established */
2940   const auto context_type = kContextTypeConversational;
2941   const auto leaudio_group_id = 4;
2942   const auto num_devices = 2;
2943 
2944   // Prepare multiple fake connected devices in a group
2945   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2946   ASSERT_EQ(group->Size(), num_devices);
2947 
2948   PrepareConfigureCodecHandler(group);
2949   PrepareConfigureQosHandler(group);
2950   PrepareCtpNotificationError(group, client_parser::ascs::kCtpOpcodeEnable,
2951                               client_parser::ascs::kCtpResponseCodeUnspecifiedError,
2952                               client_parser::ascs::kCtpResponseNoReason);
2953   PrepareReleaseHandler(group);
2954 
2955   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2956   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2957   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2958   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2959   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2960   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2961 
2962   InjectInitialIdleNotification(group);
2963 
2964   auto* leAudioDevice = group->GetFirstDevice();
2965 
2966   /* First device Control Point actions
2967    * Codec Config
2968    * QoS Config
2969    * Enable
2970    * Release
2971    */
2972   EXPECT_CALL(gatt_queue,
2973               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2974                                   GATT_WRITE_NO_RSP, _, _))
2975           .Times(4);
2976   leAudioDevice = group->GetNextDevice(leAudioDevice);
2977 
2978   /* Second device Control Point actions
2979    * Codec Config
2980    * QoS Config
2981    * Release
2982    */
2983   EXPECT_CALL(gatt_queue,
2984               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
2985                                   GATT_WRITE_NO_RSP, _, _))
2986           .Times(3);
2987 
2988   // Start the configuration and stream Media content
2989   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2990           group, context_type,
2991           {.sink = types::AudioContexts(context_type),
2992            .source = types::AudioContexts(context_type)}));
2993 
2994   // Check if group has transitioned to a proper state
2995   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2996   ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
2997 }
2998 
TEST_F(StateMachineTest,testStreamMultiple)2999 TEST_F(StateMachineTest, testStreamMultiple) {
3000   const auto context_type = kContextTypeMedia;
3001   const auto leaudio_group_id = 4;
3002   const auto num_devices = 2;
3003 
3004   // Prepare multiple fake connected devices in a group
3005   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3006   ASSERT_EQ(group->Size(), num_devices);
3007 
3008   PrepareConfigureCodecHandler(group);
3009   PrepareConfigureQosHandler(group);
3010   PrepareEnableHandler(group);
3011 
3012   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3013   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
3014   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3015   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
3016   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
3017   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
3018 
3019   InjectInitialIdleNotification(group);
3020 
3021   auto* leAudioDevice = group->GetFirstDevice();
3022   auto expected_devices_written = 0;
3023   while (leAudioDevice) {
3024     EXPECT_CALL(gatt_queue,
3025                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3026                                     GATT_WRITE_NO_RSP, _, _))
3027             .Times(AtLeast(3));
3028     expected_devices_written++;
3029     leAudioDevice = group->GetNextDevice(leAudioDevice);
3030   }
3031   ASSERT_EQ(expected_devices_written, num_devices);
3032 
3033   // Validate GroupStreamStatus
3034   EXPECT_CALL(mock_callbacks_,
3035               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
3036 
3037   // Start the configuration and stream Media content
3038   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
3039           group, context_type,
3040           {.sink = types::AudioContexts(context_type),
3041            .source = types::AudioContexts(context_type)}));
3042 
3043   // Check if group has transitioned to a proper state
3044   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3045   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3046 }
3047 
TEST_F(StateMachineTest,testUpdateMetadataMultiple)3048 TEST_F(StateMachineTest, testUpdateMetadataMultiple) {
3049   const auto context_type = kContextTypeMedia;
3050   const auto leaudio_group_id = 4;
3051   const auto num_devices = 2;
3052 
3053   auto supported_contexts = types::AudioContexts(kContextTypeMedia | kContextTypeSoundEffects);
3054 
3055   // Prepare multiple fake connected devices in a group
3056   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
3057                                              supported_contexts);
3058   ASSERT_EQ(group->Size(), num_devices);
3059 
3060   PrepareConfigureCodecHandler(group);
3061   PrepareConfigureQosHandler(group);
3062   PrepareEnableHandler(group);
3063 
3064   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3065   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
3066   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3067   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
3068   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
3069   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
3070 
3071   InjectInitialIdleNotification(group);
3072 
3073   auto* leAudioDevice = group->GetFirstDevice();
3074   auto expected_devices_written = 0;
3075   while (leAudioDevice) {
3076     EXPECT_CALL(gatt_queue,
3077                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3078                                     GATT_WRITE_NO_RSP, _, _))
3079             .Times(AtLeast(3));
3080     expected_devices_written++;
3081     leAudioDevice = group->GetNextDevice(leAudioDevice);
3082   }
3083   ASSERT_EQ(expected_devices_written, num_devices);
3084 
3085   // Validate GroupStreamStatus
3086   EXPECT_CALL(mock_callbacks_,
3087               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
3088 
3089   // Start the configuration and stream Media content
3090   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
3091           group, context_type,
3092           {.sink = types::AudioContexts(context_type),
3093            .source = types::AudioContexts(context_type)}));
3094 
3095   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
3096 
3097   // Check if group has transitioned to a proper state
3098   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3099 
3100   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3101   reset_mock_function_count_map();
3102 
3103   // Make sure all devices get the metadata update
3104   leAudioDevice = group->GetFirstDevice();
3105   expected_devices_written = 0;
3106   while (leAudioDevice) {
3107     EXPECT_CALL(gatt_queue,
3108                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3109                                     GATT_WRITE_NO_RSP, _, _))
3110             .Times(1);
3111     expected_devices_written++;
3112     leAudioDevice = group->GetNextDevice(leAudioDevice);
3113   }
3114   ASSERT_EQ(expected_devices_written, num_devices);
3115 
3116   const auto metadata_context_type = kContextTypeMedia | kContextTypeSoundEffects;
3117   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
3118           group, context_type, {.sink = metadata_context_type, .source = metadata_context_type}));
3119 
3120   /* This is just update metadata - watchdog is not used */
3121   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
3122 }
3123 
TEST_F(StateMachineTest,testUpdateMetadataMultiple_NoUpdatesOnKeyTouch)3124 TEST_F(StateMachineTest, testUpdateMetadataMultiple_NoUpdatesOnKeyTouch) {
3125   const auto context_type = kContextTypeMedia;
3126   const auto leaudio_group_id = 4;
3127   const auto num_devices = 2;
3128 
3129   /* Only Media is supported and available, */
3130   auto supported_contexts = types::AudioContexts(kContextTypeMedia);
3131 
3132   // Prepare multiple fake connected devices in a group
3133   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
3134                                              supported_contexts);
3135   ASSERT_EQ(group->Size(), num_devices);
3136 
3137   PrepareConfigureCodecHandler(group);
3138   PrepareConfigureQosHandler(group);
3139   PrepareEnableHandler(group);
3140 
3141   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3142   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
3143   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3144   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
3145   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
3146   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
3147 
3148   InjectInitialIdleNotification(group);
3149 
3150   auto* leAudioDevice = group->GetFirstDevice();
3151   auto expected_devices_written = 0;
3152   while (leAudioDevice) {
3153     EXPECT_CALL(gatt_queue,
3154                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3155                                     GATT_WRITE_NO_RSP, _, _))
3156             .Times(AtLeast(3));
3157     expected_devices_written++;
3158     leAudioDevice = group->GetNextDevice(leAudioDevice);
3159   }
3160   ASSERT_EQ(expected_devices_written, num_devices);
3161 
3162   // Validate GroupStreamStatus
3163   EXPECT_CALL(mock_callbacks_,
3164               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
3165 
3166   // Start the configuration and stream Media content
3167   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
3168           group, context_type,
3169           {.sink = types::AudioContexts(context_type),
3170            .source = types::AudioContexts(context_type)}));
3171 
3172   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
3173 
3174   // Check if group has transitioned to a proper state
3175   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3176 
3177   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3178   reset_mock_function_count_map();
3179 
3180   // Make sure all devices get the metadata update
3181   leAudioDevice = group->GetFirstDevice();
3182   expected_devices_written = 0;
3183   while (leAudioDevice) {
3184     EXPECT_CALL(gatt_queue,
3185                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3186                                     GATT_WRITE_NO_RSP, _, _))
3187             .Times(0);
3188     expected_devices_written++;
3189     leAudioDevice = group->GetNextDevice(leAudioDevice);
3190   }
3191   ASSERT_EQ(expected_devices_written, num_devices);
3192 
3193   const auto metadata_context_type = kContextTypeMedia | kContextTypeSoundEffects;
3194   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
3195           group, context_type, {.sink = metadata_context_type, .source = metadata_context_type}));
3196 
3197   /* This is just update metadata - watchdog is not used */
3198   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
3199 }
3200 
TEST_F(StateMachineTest,testDisableSingle)3201 TEST_F(StateMachineTest, testDisableSingle) {
3202   /* Device is banded headphones with 2x snk + 0x src ase
3203    * (2xunidirectional CIS)
3204    */
3205   additional_snk_ases = 1;
3206   const auto context_type = kContextTypeRingtone;
3207   const int leaudio_group_id = 4;
3208 
3209   // Prepare fake connected device group
3210   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
3211 
3212   /* Ringtone context plus additional ASE with channel count 1
3213    * gives us 2 ASE which should have been configured.
3214    */
3215   PrepareConfigureCodecHandler(group, 2);
3216   PrepareConfigureQosHandler(group, 2);
3217   PrepareEnableHandler(group, 2);
3218   PrepareDisableHandler(group, 2);
3219 
3220   auto* leAudioDevice = group->GetFirstDevice();
3221   EXPECT_CALL(gatt_queue,
3222               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3223                                   GATT_WRITE_NO_RSP, _, _))
3224           .Times(4);
3225 
3226   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3227   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3228   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3229   EXPECT_CALL(*mock_iso_manager_,
3230               RemoveIsoDataPath(_, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput))
3231           .Times(2);
3232   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
3233   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
3234 
3235   InjectInitialIdleNotification(group);
3236 
3237   EXPECT_CALL(mock_callbacks_,
3238               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
3239 
3240   // Start the configuration and stream Media content
3241   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3242                                                {.sink = types::AudioContexts(context_type),
3243                                                 .source = types::AudioContexts(context_type)});
3244 
3245   // Check if group has transitioned to a proper state
3246   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3247 
3248   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3249   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3250   reset_mock_function_count_map();
3251 
3252   // Validate GroupStreamStatus
3253   EXPECT_CALL(mock_callbacks_,
3254               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::SUSPENDING));
3255   EXPECT_CALL(mock_callbacks_,
3256               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::SUSPENDED));
3257 
3258   // Suspend the stream
3259   LeAudioGroupStateMachine::Get()->SuspendStream(group);
3260 
3261   // Check if group has transition to a proper state
3262   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
3263 
3264   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3265   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3266 }
3267 
TEST_F(StateMachineTest,testDisableMultiple)3268 TEST_F(StateMachineTest, testDisableMultiple) {
3269   const auto context_type = kContextTypeMedia;
3270   const auto leaudio_group_id = 4;
3271   const auto num_devices = 2;
3272 
3273   // Prepare multiple fake connected devices in a group
3274   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3275   ASSERT_EQ(group->Size(), num_devices);
3276 
3277   PrepareConfigureCodecHandler(group);
3278   PrepareConfigureQosHandler(group);
3279   PrepareEnableHandler(group);
3280   PrepareDisableHandler(group);
3281 
3282   auto* leAudioDevice = group->GetFirstDevice();
3283   auto expected_devices_written = 0;
3284   while (leAudioDevice) {
3285     EXPECT_CALL(gatt_queue,
3286                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3287                                     GATT_WRITE_NO_RSP, _, _))
3288             .Times(AtLeast(4));
3289     expected_devices_written++;
3290     leAudioDevice = group->GetNextDevice(leAudioDevice);
3291   }
3292   ASSERT_EQ(expected_devices_written, num_devices);
3293 
3294   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3295   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3296   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3297   EXPECT_CALL(*mock_iso_manager_,
3298               RemoveIsoDataPath(_, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput))
3299           .Times(2);
3300   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
3301   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
3302 
3303   InjectInitialIdleNotification(group);
3304 
3305   // Start the configuration and stream Media content
3306   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3307                                                {.sink = types::AudioContexts(context_type),
3308                                                 .source = types::AudioContexts(context_type)});
3309 
3310   // Check if group has transitioned to a proper state
3311   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3312   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3313   reset_mock_function_count_map();
3314 
3315   // Validate GroupStreamStatus
3316   EXPECT_CALL(mock_callbacks_,
3317               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::SUSPENDING));
3318   EXPECT_CALL(mock_callbacks_,
3319               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::SUSPENDED));
3320 
3321   // Suspend the stream
3322   LeAudioGroupStateMachine::Get()->SuspendStream(group);
3323 
3324   // Check if group has transitioned to a proper state
3325   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
3326   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3327   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3328 }
3329 
TEST_F(StateMachineTest,testDisableBidirectional)3330 TEST_F(StateMachineTest, testDisableBidirectional) {
3331   /* Device is banded headphones with 2x snk + 1x src ase
3332    * (1x bidirectional + 1xunidirectional CIS)
3333    */
3334   additional_snk_ases = 1;
3335   const auto context_type = kContextTypeConversational;
3336   const int leaudio_group_id = 4;
3337 
3338   // Prepare fake connected device group
3339   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
3340 
3341   /* Since we prepared device with Conversional context in mind, Sink and Source
3342    * ASEs should have been configured.
3343    */
3344   PrepareConfigureCodecHandler(group, 3);
3345   PrepareConfigureQosHandler(group, 3);
3346   PrepareEnableHandler(group, 3);
3347   PrepareDisableHandler(group, 3);
3348   PrepareReceiverStartReadyHandler(group, 1);
3349   PrepareReceiverStopReady(group, 1);
3350 
3351   auto* leAudioDevice = group->GetFirstDevice();
3352   EXPECT_CALL(gatt_queue,
3353               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3354                                   GATT_WRITE_NO_RSP, _, _))
3355           .Times(AtLeast(4));
3356 
3357   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3358   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3359   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
3360   bool removed_bidirectional = false;
3361   bool removed_unidirectional = false;
3362 
3363   /* Check data path removal */
3364   ON_CALL(*mock_iso_manager_, RemoveIsoDataPath)
3365           .WillByDefault(Invoke([&removed_bidirectional, &removed_unidirectional, this](
3366                                         uint16_t conn_handle, uint8_t data_path_dir) {
3367             /* Set flags for verification */
3368             if (data_path_dir == (bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput |
3369                                   bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput)) {
3370               removed_bidirectional = true;
3371             } else if (data_path_dir ==
3372                        bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput) {
3373               removed_unidirectional = true;
3374             }
3375 
3376             /* Copied from default handler of RemoveIsoDataPath*/
3377             auto dev_it = std::find_if(le_audio_devices_.begin(), le_audio_devices_.end(),
3378                                        [&conn_handle](auto& dev) {
3379                                          auto ases = dev->GetAsesByCisConnHdl(conn_handle);
3380                                          return ases.sink || ases.source;
3381                                        });
3382             if (dev_it == le_audio_devices_.end()) {
3383               return;
3384             }
3385 
3386             for (auto& kv_pair : le_audio_device_groups_) {
3387               auto& group = kv_pair.second;
3388               if (group->IsDeviceInTheGroup(dev_it->get())) {
3389                 LeAudioGroupStateMachine::Get()->ProcessHciNotifRemoveIsoDataPath(
3390                         group.get(), dev_it->get(), 0, conn_handle);
3391                 return;
3392               }
3393             }
3394             /* End of copy */
3395           }));
3396 
3397   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
3398   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
3399 
3400   // Start the configuration and stream Media content
3401   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3402                                                {.sink = types::AudioContexts(context_type),
3403                                                 .source = types::AudioContexts(context_type)});
3404 
3405   // Check if group has transitioned to a proper state
3406   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3407 
3408   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3409   reset_mock_function_count_map();
3410 
3411   // Validate GroupStreamStatus
3412   EXPECT_CALL(mock_callbacks_,
3413               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::SUSPENDING));
3414   EXPECT_CALL(mock_callbacks_,
3415               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::SUSPENDED));
3416 
3417   // Suspend the stream
3418   LeAudioGroupStateMachine::Get()->SuspendStream(group);
3419 
3420   // Check if group has transitioned to a proper state
3421   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
3422   ASSERT_EQ(removed_bidirectional, true);
3423   ASSERT_EQ(removed_unidirectional, true);
3424 
3425   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3426   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3427 }
3428 
TEST_F(StateMachineTest,testReleaseSingle)3429 TEST_F(StateMachineTest, testReleaseSingle) {
3430   /* Device is banded headphones with 1x snk + 0x src ase
3431    * (1xunidirectional CIS) with channel count 2 (for stereo)
3432    */
3433   const auto context_type = kContextTypeRingtone;
3434   const int leaudio_group_id = 4;
3435   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
3436 
3437   // Prepare fake connected device group
3438   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
3439 
3440   /* Since we prepared device with Ringtone context in mind, only one ASE
3441    * should have been configured.
3442    */
3443   PrepareConfigureCodecHandler(group, 1);
3444   PrepareConfigureQosHandler(group, 1);
3445   PrepareEnableHandler(group, 1);
3446   PrepareDisableHandler(group, 1);
3447   PrepareReleaseHandler(group, 1);
3448 
3449   auto* leAudioDevice = group->GetFirstDevice();
3450   EXPECT_CALL(gatt_queue,
3451               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3452                                   GATT_WRITE_NO_RSP, _, _))
3453           .Times(4);
3454 
3455   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3456   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3457   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
3458   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
3459   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
3460   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
3461 
3462   EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(0);
3463   EXPECT_CALL(*mock_codec_manager_, ClearCisConfiguration(_)).Times(0);
3464 
3465   InjectInitialIdleNotification(group);
3466 
3467   // Start the configuration and stream Media content
3468   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3469                                                {.sink = types::AudioContexts(context_type),
3470                                                 .source = types::AudioContexts(context_type)});
3471 
3472   // Check if group has transitioned to a proper state
3473   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3474   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3475 
3476   testing::Mock::VerifyAndClearExpectations(mock_codec_manager_);
3477 
3478   reset_mock_function_count_map();
3479   // Validate GroupStreamStatus
3480   EXPECT_CALL(mock_callbacks_,
3481               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
3482   EXPECT_CALL(mock_callbacks_,
3483               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
3484 
3485   // Stop the stream
3486   EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(0);
3487 
3488   /* ClearCisConfiguration is called for each direction unconditionaly when stream goes to idle.
3489    * In addition, it is called when handling CIS disconnection and here we want Sink to be called.
3490    */
3491   EXPECT_CALL(*mock_codec_manager_,
3492               ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSink))
3493           .Times(2);
3494   EXPECT_CALL(*mock_codec_manager_,
3495               ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSource))
3496           .Times(1);
3497 
3498   LeAudioGroupStateMachine::Get()->StopStream(group);
3499 
3500   // Check if group has transitioned to a proper state
3501   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
3502   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3503   testing::Mock::VerifyAndClearExpectations(mock_codec_manager_);
3504 }
3505 
TEST_F(StateMachineTest,testReleaseCachingSingle)3506 TEST_F(StateMachineTest, testReleaseCachingSingle) {
3507   /* Device is banded headphones with 1x snk + 0x src ase
3508    * (1xunidirectional CIS)
3509    */
3510   const auto context_type = kContextTypeRingtone;
3511   const int leaudio_group_id = 4;
3512   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
3513 
3514   // Prepare fake connected device group
3515   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
3516 
3517   /* Since we prepared device with Ringtone context in mind, only one ASE
3518    * should have been configured.
3519    */
3520   PrepareConfigureCodecHandler(group, 1, true);
3521   PrepareConfigureQosHandler(group, 1);
3522   PrepareEnableHandler(group, 1);
3523   PrepareDisableHandler(group, 1);
3524   PrepareReleaseHandler(group, 1);
3525 
3526   auto* leAudioDevice = group->GetFirstDevice();
3527   EXPECT_CALL(gatt_queue,
3528               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3529                                   GATT_WRITE_NO_RSP, _, _))
3530           .Times(4);
3531 
3532   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3533   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3534   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
3535   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
3536   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
3537   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
3538 
3539   InjectInitialIdleNotification(group);
3540 
3541   // Validate GroupStreamStatus
3542   EXPECT_CALL(mock_callbacks_,
3543               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
3544 
3545   EXPECT_CALL(mock_callbacks_,
3546               StatusReportCb(leaudio_group_id,
3547                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
3548   EXPECT_CALL(mock_callbacks_,
3549               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
3550 
3551   // Start the configuration and stream Media content
3552   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3553                                                {.sink = types::AudioContexts(context_type),
3554                                                 .source = types::AudioContexts(context_type)});
3555 
3556   // Check if group has transitioned to a proper state
3557   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3558 
3559   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3560   reset_mock_function_count_map();
3561 
3562   // Stop the stream
3563   LeAudioGroupStateMachine::Get()->StopStream(group);
3564 
3565   // Check if group has transitioned to a proper state
3566   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
3567 
3568   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3569 }
3570 
TEST_F(StateMachineTest,testStreamCaching_NoReconfigurationNeeded_SingleDevice)3571 TEST_F(StateMachineTest, testStreamCaching_NoReconfigurationNeeded_SingleDevice) {
3572   const auto context_type = kContextTypeRingtone;
3573   const int leaudio_group_id = 4;
3574   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
3575 
3576   additional_snk_ases = 2;
3577   // Prepare fake connected device group
3578   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
3579 
3580   /* Since we prepared device with Ringtone context in mind and with no Source
3581    * ASEs, therefor only one ASE should have been configured.
3582    */
3583   PrepareConfigureCodecHandler(group, 1, true);
3584   PrepareConfigureQosHandler(group, 1, true);
3585   PrepareEnableHandler(group, 1);
3586   PrepareDisableHandler(group, 1);
3587   PrepareReleaseHandler(group, 1);
3588 
3589   /* Ctp messages we expect:
3590    * 1. Codec Config
3591    * 2. QoS Config
3592    * 3. Enable
3593    * 4. Release
3594    * 5. QoS Config (because device stays in Configured state)
3595    * 6. Enable
3596    */
3597   auto* leAudioDevice = group->GetFirstDevice();
3598   EXPECT_CALL(gatt_queue,
3599               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3600                                   GATT_WRITE_NO_RSP, _, _))
3601           .Times(6);
3602 
3603   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(2);
3604   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(2);
3605   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3606   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
3607   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
3608   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
3609 
3610   InjectInitialIdleNotification(group);
3611 
3612   // Validate GroupStreamStatus
3613   EXPECT_CALL(mock_callbacks_,
3614               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
3615 
3616   EXPECT_CALL(mock_callbacks_,
3617               StatusReportCb(leaudio_group_id,
3618                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
3619 
3620   EXPECT_CALL(mock_callbacks_,
3621               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
3622           .Times(2);
3623 
3624   // Start the configuration and stream Ringtone content
3625   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3626                                                {.sink = types::AudioContexts(context_type),
3627                                                 .source = types::AudioContexts(context_type)});
3628 
3629   // Check if group has transitioned to a proper state
3630   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3631 
3632   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3633   reset_mock_function_count_map();
3634 
3635   // Stop the stream
3636   LeAudioGroupStateMachine::Get()->StopStream(group);
3637 
3638   // Check if group has transitioned to a proper state
3639   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
3640 
3641   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3642   reset_mock_function_count_map();
3643 
3644   // Start the configuration and stream Media content
3645   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3646                                                {.sink = types::AudioContexts(context_type),
3647                                                 .source = types::AudioContexts(context_type)});
3648 
3649   // Check if group has transitioned to a proper state
3650   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3651 
3652   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3653   reset_mock_function_count_map();
3654 }
3655 
TEST_F(StateMachineTest,test_StreamCaching_ReconfigureForContextChange_SingleDevice)3656 TEST_F(StateMachineTest, test_StreamCaching_ReconfigureForContextChange_SingleDevice) {
3657   auto context_type = kContextTypeConversational;
3658   const int leaudio_group_id = 4;
3659   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
3660 
3661   additional_snk_ases = 2;
3662   /* Prepare fake connected device group with update of Media and Conversational
3663    * contexts
3664    */
3665   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, 1,
3666                                              kContextTypeConversational | kContextTypeMedia);
3667 
3668   /* Don't validate ASE here, as after reconfiguration different ASE number
3669    * will be used.
3670    * For the first configuration (CONVERSTATIONAL) there will be 2 ASEs (Sink
3671    * and Source) After reconfiguration (MEDIA) there will be single ASE.
3672    */
3673   PrepareConfigureCodecHandler(group, 0, true);
3674   PrepareConfigureQosHandler(group, 0, true);
3675   PrepareEnableHandler(group);
3676   PrepareReceiverStartReadyHandler(group);
3677   PrepareReleaseHandler(group);
3678 
3679   /* Ctp messages we expect:
3680    * 1. Codec Config
3681    * 2. QoS Config
3682    * 3. Enable
3683    * 4. Release
3684    * 5. Codec Config
3685    * 6. QoS Config
3686    * 7. Enable
3687    */
3688   auto* leAudioDevice = group->GetFirstDevice();
3689   EXPECT_CALL(gatt_queue,
3690               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3691                                   GATT_WRITE_NO_RSP, _, _))
3692           .Times(8);
3693 
3694   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(2);
3695   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(2);
3696 
3697   /* 2 times for first configuration (1 Sink, 1 Source), 1 time for second
3698    * configuration (1 Sink)*/
3699   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
3700 
3701   uint8_t value = bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput |
3702                   bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput;
3703   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, value)).Times(1);
3704   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
3705   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
3706 
3707   InjectInitialIdleNotification(group);
3708 
3709   // Validate GroupStreamStatus
3710   EXPECT_CALL(mock_callbacks_,
3711               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
3712 
3713   EXPECT_CALL(mock_callbacks_,
3714               StatusReportCb(leaudio_group_id,
3715                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
3716 
3717   EXPECT_CALL(mock_callbacks_,
3718               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
3719           .Times(2);
3720 
3721   // Start the configuration and stream Conversational content
3722   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3723                                                {.sink = types::AudioContexts(context_type),
3724                                                 .source = types::AudioContexts(context_type)});
3725 
3726   // Check if group has transitioned to a proper state
3727   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3728 
3729   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3730   reset_mock_function_count_map();
3731 
3732   // Stop the stream
3733   LeAudioGroupStateMachine::Get()->StopStream(group);
3734 
3735   // Check if group has transitioned to a proper state
3736   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
3737 
3738   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3739   reset_mock_function_count_map();
3740 
3741   // Start the configuration and stream Media content
3742   context_type = kContextTypeMedia;
3743   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3744                                                {.sink = types::AudioContexts(context_type),
3745                                                 .source = types::AudioContexts(context_type)});
3746 
3747   // Check if group has transitioned to a proper state
3748   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3749   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3750 }
3751 
TEST_F(StateMachineTest,testReleaseMultiple)3752 TEST_F(StateMachineTest, testReleaseMultiple) {
3753   const auto context_type = kContextTypeMedia;
3754   const auto leaudio_group_id = 6;
3755   const auto num_devices = 2;
3756 
3757   // Prepare multiple fake connected devices in a group
3758   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3759   ASSERT_EQ(group->Size(), num_devices);
3760 
3761   PrepareConfigureCodecHandler(group);
3762   PrepareConfigureQosHandler(group);
3763   PrepareEnableHandler(group);
3764   PrepareDisableHandler(group);
3765   PrepareReleaseHandler(group);
3766 
3767   auto* leAudioDevice = group->GetFirstDevice();
3768   auto expected_devices_written = 0;
3769   while (leAudioDevice) {
3770     EXPECT_CALL(gatt_queue,
3771                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3772                                     GATT_WRITE_NO_RSP, _, _))
3773             .Times(AtLeast(4));
3774     expected_devices_written++;
3775     leAudioDevice = group->GetNextDevice(leAudioDevice);
3776   }
3777   ASSERT_EQ(expected_devices_written, num_devices);
3778 
3779   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3780   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3781   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3782   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
3783   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
3784   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
3785 
3786   InjectInitialIdleNotification(group);
3787 
3788   EXPECT_CALL(mock_callbacks_,
3789               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
3790           .Times(1);
3791 
3792   // Start the configuration and stream Media content
3793   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3794                                                {.sink = types::AudioContexts(context_type),
3795                                                 .source = types::AudioContexts(context_type)});
3796 
3797   // Check if group has transitioned to a proper state
3798   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3799 
3800   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3801   reset_mock_function_count_map();
3802 
3803   // Validate GroupStreamStatus
3804   EXPECT_CALL(mock_callbacks_,
3805               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
3806   EXPECT_CALL(mock_callbacks_,
3807               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
3808   EXPECT_CALL(mock_callbacks_,
3809               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
3810           .Times(0);
3811 
3812   // Stop the stream
3813   LeAudioGroupStateMachine::Get()->StopStream(group);
3814 
3815   // Check if group has transitioned to a proper state
3816   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
3817   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3818 }
3819 
InjectCisDisconnected(LeAudioDeviceGroup * group,LeAudioDevice * leAudioDevice,uint8_t reason,bool first_cis_disconnect_only=false)3820 static void InjectCisDisconnected(LeAudioDeviceGroup* group, LeAudioDevice* leAudioDevice,
3821                                   uint8_t reason, bool first_cis_disconnect_only = false) {
3822   bluetooth::hci::iso_manager::cis_disconnected_evt event;
3823 
3824   for (auto const ase : leAudioDevice->ases_) {
3825     if (ase.cis_state != types::CisState::ASSIGNED && ase.cis_state != types::CisState::IDLE) {
3826       event.reason = reason;
3827       event.cig_id = group->group_id_;
3828       event.cis_conn_hdl = ase.cis_conn_hdl;
3829       LeAudioGroupStateMachine::Get()->ProcessHciNotifCisDisconnected(group, leAudioDevice, &event);
3830       if (first_cis_disconnect_only) {
3831         break;
3832       }
3833     }
3834   }
3835 }
3836 
TEST_F(StateMachineTest,testStartAndStopStreamConversational_VerifyCodecManagerCallsOnCisRemoval)3837 TEST_F(StateMachineTest, testStartAndStopStreamConversational_VerifyCodecManagerCallsOnCisRemoval) {
3838   const auto context_type = kContextTypeConversational;
3839   const auto leaudio_group_id = 6;
3840   const auto num_devices = 2;
3841 
3842   // Prepare multiple fake connected devices in a group
3843   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3844   ASSERT_EQ(group->Size(), num_devices);
3845 
3846   PrepareConfigureCodecHandler(group);
3847   PrepareConfigureQosHandler(group);
3848   PrepareEnableHandler(group);
3849   PrepareReceiverStartReadyHandler(group);
3850   PrepareDisableHandler(group);
3851   PrepareReleaseHandler(group);
3852 
3853   auto* leAudioDevice = group->GetFirstDevice();
3854 
3855   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3856   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3857   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
3858   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
3859   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
3860   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
3861 
3862   InjectInitialIdleNotification(group);
3863 
3864   EXPECT_CALL(mock_callbacks_,
3865               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
3866           .Times(1);
3867 
3868   // Start the configuration and stream Media content
3869   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3870                                                {.sink = types::AudioContexts(context_type),
3871                                                 .source = types::AudioContexts(context_type)});
3872 
3873   // Check if group has transitioned to a proper state
3874   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3875 
3876   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3877   reset_mock_function_count_map();
3878 
3879   // Validate GroupStreamStatus
3880   EXPECT_CALL(mock_callbacks_,
3881               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
3882   EXPECT_CALL(mock_callbacks_,
3883               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
3884 
3885   // This is called when 1 CIS got disconnected.
3886   EXPECT_CALL(mock_callbacks_,
3887               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
3888           .Times(1);
3889 
3890   EXPECT_CALL(*mock_codec_manager_,
3891               UpdateCisConfiguration(_, _, bluetooth::le_audio::types::kLeAudioDirectionSink))
3892           .Times(1);
3893   EXPECT_CALL(*mock_codec_manager_,
3894               UpdateCisConfiguration(_, _, bluetooth::le_audio::types::kLeAudioDirectionSource))
3895           .Times(1);
3896   EXPECT_CALL(*mock_codec_manager_, ClearCisConfiguration(_)).Times(0);
3897 
3898   InjectCisDisconnected(group, leAudioDevice, HCI_ERR_PEER_USER);
3899   testing::Mock::VerifyAndClearExpectations(mock_codec_manager_);
3900 
3901   // Stop the stream
3902   EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(0);
3903   EXPECT_CALL(*mock_codec_manager_,
3904               ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSink))
3905           .Times(2);
3906   EXPECT_CALL(*mock_codec_manager_,
3907               ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSource))
3908           .Times(2);
3909 
3910   LeAudioGroupStateMachine::Get()->StopStream(group);
3911 
3912   // Check if group has transitioned to a proper state
3913   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
3914   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3915   testing::Mock::VerifyAndClearExpectations(mock_codec_manager_);
3916 }
3917 
TEST_F(StateMachineTest,testReleaseMultiple_CisDisconnectedBeforeGettingToIdleState)3918 TEST_F(StateMachineTest, testReleaseMultiple_CisDisconnectedBeforeGettingToIdleState) {
3919   const auto context_type = kContextTypeMedia;
3920   const auto leaudio_group_id = 6;
3921   const auto num_devices = 2;
3922 
3923   /* Test Scenario:
3924    * 1. Start stream
3925    * 2. Stop the stream
3926    * 3. While stopping, make sure that CISes are disconnected before current state is IDLE - verify
3927    * watchdog keeps running
3928    * 4. Move to IDLE, make sure watchdog is cleared
3929    */
3930 
3931   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3932   ASSERT_EQ(group->Size(), num_devices);
3933 
3934   PrepareConfigureCodecHandler(group);
3935   PrepareConfigureQosHandler(group);
3936   PrepareEnableHandler(group);
3937   PrepareDisableHandler(group);
3938   PrepareReleaseHandler(group);
3939 
3940   stay_in_releasing_state_ = true;
3941 
3942   auto* leAudioDevice = group->GetFirstDevice();
3943   auto expected_devices_written = 0;
3944   while (leAudioDevice) {
3945     EXPECT_CALL(gatt_queue,
3946                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
3947                                     GATT_WRITE_NO_RSP, _, _))
3948             .Times(AtLeast(4));
3949     expected_devices_written++;
3950     leAudioDevice = group->GetNextDevice(leAudioDevice);
3951   }
3952   ASSERT_EQ(expected_devices_written, num_devices);
3953 
3954   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3955   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3956   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3957   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
3958   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
3959   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
3960 
3961   InjectInitialIdleNotification(group);
3962 
3963   EXPECT_CALL(mock_callbacks_,
3964               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
3965           .Times(1);
3966 
3967   // Start the configuration and stream Media content
3968   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
3969                                                {.sink = types::AudioContexts(context_type),
3970                                                 .source = types::AudioContexts(context_type)});
3971 
3972   // Check if group has transitioned to a proper state
3973   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3974 
3975   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3976   reset_mock_function_count_map();
3977   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3978 
3979   // Validate GroupStreamStatus
3980   EXPECT_CALL(mock_callbacks_,
3981               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
3982   EXPECT_CALL(mock_callbacks_,
3983               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
3984   EXPECT_CALL(mock_callbacks_,
3985               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
3986           .Times(0);
3987 
3988   // Stop the stream
3989   LeAudioGroupStateMachine::Get()->StopStream(group);
3990 
3991   // Watchdog shall not be cancled here.
3992   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
3993 
3994   InjectReleaseAndIdleStateForAGroup(group, false, true);
3995 
3996   // Check if group has transitioned to a proper state
3997   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
3998   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
3999   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4000   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
4001 }
4002 
TEST_F(StateMachineTest,testReleaseMultiple_CisDisconnectedBeforeGettingToConfiguredState)4003 TEST_F(StateMachineTest, testReleaseMultiple_CisDisconnectedBeforeGettingToConfiguredState) {
4004   const auto context_type = kContextTypeMedia;
4005   const auto leaudio_group_id = 6;
4006   const auto num_devices = 2;
4007 
4008   /* Test Scenario:
4009    * 1. Start stream
4010    * 2. Stop the stream
4011    * 3. While stopping, make sure that CISes are disconnected before current state is CONFIGURED -
4012    * verify watchdog keeps running
4013    * 4. Move to CONFIGURED, make sure watchdog is cleared
4014    */
4015 
4016   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
4017   ASSERT_EQ(group->Size(), num_devices);
4018 
4019   PrepareConfigureCodecHandler(group, 0, true);
4020   PrepareConfigureQosHandler(group, 0, true);
4021   PrepareEnableHandler(group);
4022   PrepareDisableHandler(group);
4023   PrepareReleaseHandler(group);
4024 
4025   stay_in_releasing_state_ = true;
4026 
4027   auto* leAudioDevice = group->GetFirstDevice();
4028   auto expected_devices_written = 0;
4029   while (leAudioDevice) {
4030     EXPECT_CALL(gatt_queue,
4031                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4032                                     GATT_WRITE_NO_RSP, _, _))
4033             .Times(AtLeast(4));
4034     expected_devices_written++;
4035     leAudioDevice = group->GetNextDevice(leAudioDevice);
4036   }
4037   ASSERT_EQ(expected_devices_written, num_devices);
4038 
4039   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
4040   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
4041   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
4042   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
4043   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
4044   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
4045 
4046   InjectInitialIdleNotification(group);
4047 
4048   EXPECT_CALL(mock_callbacks_,
4049               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4050           .Times(1);
4051 
4052   // Start the configuration and stream Media content
4053   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
4054                                                {.sink = types::AudioContexts(context_type),
4055                                                 .source = types::AudioContexts(context_type)});
4056 
4057   // Check if group has transitioned to a proper state
4058   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
4059 
4060   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4061 
4062   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4063   reset_mock_function_count_map();
4064 
4065   // Validate GroupStreamStatus
4066   EXPECT_CALL(mock_callbacks_,
4067               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
4068   EXPECT_CALL(mock_callbacks_,
4069               StatusReportCb(leaudio_group_id,
4070                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
4071   EXPECT_CALL(mock_callbacks_,
4072               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4073           .Times(0);
4074 
4075   // Stop the stream
4076   LeAudioGroupStateMachine::Get()->StopStream(group);
4077 
4078   // Watchdog shall not be cancled here.
4079   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
4080 
4081   InjectCachedConfigurationForGroup(group);
4082 
4083   // Check if group has transitioned to a proper state
4084   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
4085   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4086   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4087   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
4088 }
4089 
TEST_F(StateMachineTest,testAutonomousReleaseMultiple)4090 TEST_F(StateMachineTest, testAutonomousReleaseMultiple) {
4091   const auto context_type = kContextTypeMedia;
4092   const auto leaudio_group_id = 6;
4093   const auto num_devices = 2;
4094 
4095   // Prepare multiple fake connected devices in a group
4096   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
4097   ASSERT_EQ(group->Size(), num_devices);
4098 
4099   PrepareConfigureCodecHandler(group);
4100   PrepareConfigureQosHandler(group);
4101   PrepareEnableHandler(group);
4102 
4103   auto* leAudioDevice = group->GetFirstDevice();
4104   LeAudioDevice* firstDevice = leAudioDevice;
4105   LeAudioDevice* secondDevice;
4106 
4107   /*
4108    * 1. Codec Config
4109    * 2. QoS Config
4110    * 3. Enable
4111    */
4112   auto expected_devices_written = 0;
4113   while (leAudioDevice) {
4114     EXPECT_CALL(gatt_queue,
4115                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4116                                     GATT_WRITE_NO_RSP, _, _))
4117             .Times(3);
4118     expected_devices_written++;
4119     secondDevice = leAudioDevice;
4120     leAudioDevice = group->GetNextDevice(leAudioDevice);
4121   }
4122   ASSERT_EQ(expected_devices_written, num_devices);
4123 
4124   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
4125   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
4126   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
4127   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
4128   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
4129 
4130   InjectInitialIdleNotification(group);
4131 
4132   EXPECT_CALL(mock_callbacks_,
4133               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4134           .Times(1);
4135 
4136   // Start the configuration and stream Media content
4137   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
4138                                                {.sink = types::AudioContexts(context_type),
4139                                                 .source = types::AudioContexts(context_type)});
4140 
4141   // Check if group has transitioned to a proper state
4142   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
4143 
4144   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
4145   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4146   reset_mock_function_count_map();
4147 
4148   // Validate GroupStreamStatus
4149   EXPECT_CALL(mock_callbacks_,
4150               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING))
4151           .Times(1);
4152   EXPECT_CALL(mock_callbacks_,
4153               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE))
4154           .Times(1);
4155   EXPECT_CALL(mock_callbacks_,
4156               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4157           .Times(0);
4158 
4159   // Do not take any actions on DisconnectCis. Later it will be injected.
4160   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
4161 
4162   log::info("Inject Release of all ASEs");
4163 
4164   // Inject Release state from remove
4165   InjectReleaseAndIdleStateForAGroup(group, true, false);
4166 
4167   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING);
4168 
4169   log::info("Inject CIS Disconnected Event");
4170 
4171   // Inject CIS Disconnection from remote
4172   InjectCisDisconnected(group, firstDevice, HCI_ERR_PEER_USER);
4173   InjectCisDisconnected(group, secondDevice, HCI_ERR_PEER_USER);
4174 
4175   // Inject Idle ASE
4176   InjectReleaseAndIdleStateForAGroup(group, false, true);
4177 
4178   // Check if group has transitioned to a proper state
4179   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4180   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
4181   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4182 }
4183 
TEST_F(StateMachineTest,testReleaseMultiple_DeviceDisconnectedDuringRelease)4184 TEST_F(StateMachineTest, testReleaseMultiple_DeviceDisconnectedDuringRelease) {
4185   const auto context_type = kContextTypeMedia;
4186   const auto leaudio_group_id = 6;
4187   const auto num_devices = 2;
4188 
4189   // Prepare multiple fake connected devices in a group
4190   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
4191   ASSERT_EQ(group->Size(), num_devices);
4192 
4193   PrepareConfigureCodecHandler(group);
4194   PrepareConfigureQosHandler(group);
4195   PrepareEnableHandler(group);
4196   PrepareDisableHandler(group);
4197 
4198   /* Here we inject device disconnection during release */
4199   PrepareReleaseHandler(group, 0, true);
4200 
4201   auto* leAudioDevice = group->GetFirstDevice();
4202   auto expected_devices_written = 0;
4203   while (leAudioDevice) {
4204     EXPECT_CALL(gatt_queue,
4205                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4206                                     GATT_WRITE_NO_RSP, _, _))
4207             .Times(AtLeast(4));
4208     expected_devices_written++;
4209     leAudioDevice = group->GetNextDevice(leAudioDevice);
4210   }
4211   ASSERT_EQ(expected_devices_written, num_devices);
4212 
4213   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
4214   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
4215   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
4216   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
4217   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
4218 
4219   InjectInitialIdleNotification(group);
4220 
4221   EXPECT_CALL(mock_callbacks_,
4222               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4223           .Times(1);
4224 
4225   // Start the configuration and stream Media content
4226   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
4227                                                {.sink = types::AudioContexts(context_type),
4228                                                 .source = types::AudioContexts(context_type)});
4229 
4230   // Check if group has transitioned to a proper state
4231   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
4232 
4233   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4234   reset_mock_function_count_map();
4235 
4236   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
4237 
4238   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
4239   // Validate GroupStreamStatus
4240   EXPECT_CALL(mock_callbacks_,
4241               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
4242   EXPECT_CALL(mock_callbacks_,
4243               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
4244   EXPECT_CALL(mock_callbacks_,
4245               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4246           .Times(0);
4247 
4248   // Stop the stream
4249   LeAudioGroupStateMachine::Get()->StopStream(group);
4250 
4251   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
4252 
4253   // Check if group has transitioned to a proper state
4254   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4255   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4256 }
4257 
TEST_F(StateMachineTest,testReleaseBidirectional)4258 TEST_F(StateMachineTest, testReleaseBidirectional) {
4259   /* Device is banded headphones with 2x snk + 1x src ase
4260    * (1x bidirectional + 1xunidirectional CIS)
4261    */
4262   additional_snk_ases = 1;
4263   const auto context_type = kContextTypeConversational;
4264   const auto leaudio_group_id = 6;
4265 
4266   // Prepare fake connected device group
4267   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4268 
4269   /* Since we prepared device with Conversional context in mind, Sink and Source
4270    * ASEs should have been configured.
4271    */
4272   PrepareConfigureCodecHandler(group, 3);
4273   PrepareConfigureQosHandler(group, 3);
4274   PrepareEnableHandler(group, 3);
4275   PrepareDisableHandler(group, 3);
4276   PrepareReceiverStartReadyHandler(group, 1);
4277   PrepareReleaseHandler(group, 3);
4278 
4279   auto* leAudioDevice = group->GetFirstDevice();
4280   EXPECT_CALL(gatt_queue,
4281               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4282                                   GATT_WRITE_NO_RSP, _, _))
4283           .Times(AtLeast(4));
4284 
4285   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
4286   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
4287   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
4288   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
4289   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
4290   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
4291 
4292   // 1 for Sink and 1 for Source
4293   EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(0);
4294   EXPECT_CALL(*mock_codec_manager_, ClearCisConfiguration(_)).Times(0);
4295 
4296   InjectInitialIdleNotification(group);
4297 
4298   // Start the configuration and stream Media content
4299   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
4300                                                {.sink = types::AudioContexts(context_type),
4301                                                 .source = types::AudioContexts(context_type)});
4302 
4303   // Check if group has transitioned to a proper state
4304   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
4305 
4306   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4307   reset_mock_function_count_map();
4308   testing::Mock::VerifyAndClearExpectations(mock_codec_manager_);
4309 
4310   group->PrintDebugState();
4311 
4312   // Stop the stream
4313   // This will be called once after first CIS is disconnected
4314   EXPECT_CALL(*mock_codec_manager_, UpdateCisConfiguration(_, _, _)).Times(1);
4315 
4316   /* ClearCisConfiguration is called for each direction unconditionaly when stream goes to idle.
4317    * In addition, it is called when handling CIS disconnection and here we want Sink and Source to
4318    * be called.
4319    */
4320   EXPECT_CALL(*mock_codec_manager_,
4321               ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSink))
4322           .Times(2);
4323   EXPECT_CALL(*mock_codec_manager_,
4324               ClearCisConfiguration(bluetooth::le_audio::types::kLeAudioDirectionSource))
4325           .Times(2);
4326 
4327   LeAudioGroupStateMachine::Get()->StopStream(group);
4328 
4329   // Check if group has transitioned to a proper state
4330   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4331   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4332   reset_mock_function_count_map();
4333   testing::Mock::VerifyAndClearExpectations(mock_codec_manager_);
4334 }
4335 
TEST_F(StateMachineTest,testDisableAndReleaseBidirectional)4336 TEST_F(StateMachineTest, testDisableAndReleaseBidirectional) {
4337   /* Device is banded headphones with 2x snk + 1x src ase
4338    * (1x bidirectional + 1xunidirectional CIS)
4339    */
4340   additional_snk_ases = 1;
4341   const auto context_type = kContextTypeConversational;
4342   const int leaudio_group_id = 4;
4343 
4344   // Prepare fake connected device group
4345   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4346 
4347   /* Since we prepared device with Conversional context in mind, Sink and Source
4348    * ASEs should have been configured.
4349    */
4350   PrepareConfigureCodecHandler(group, 3);
4351   PrepareConfigureQosHandler(group, 3);
4352   PrepareEnableHandler(group, 3);
4353   PrepareDisableHandler(group, 3);
4354   PrepareReceiverStartReadyHandler(group, 1);
4355   PrepareReceiverStopReady(group, 1);
4356   PrepareReleaseHandler(group, 3);
4357 
4358   auto* leAudioDevice = group->GetFirstDevice();
4359   EXPECT_CALL(gatt_queue,
4360               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4361                                   GATT_WRITE_NO_RSP, _, _))
4362           .Times(AtLeast(4));
4363 
4364   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
4365   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
4366   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
4367   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
4368   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
4369   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
4370 
4371   // Start the configuration and stream Media content
4372   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
4373                                                {.sink = types::AudioContexts(context_type),
4374                                                 .source = types::AudioContexts(context_type)});
4375 
4376   // Suspend the stream
4377   LeAudioGroupStateMachine::Get()->SuspendStream(group);
4378 
4379   // Stop the stream
4380   LeAudioGroupStateMachine::Get()->StopStream(group);
4381 
4382   // Check if group has transitioned to a proper state
4383   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4384 }
4385 
TEST_F(StateMachineTest,testAseIdAssignmentIdle)4386 TEST_F(StateMachineTest, testAseIdAssignmentIdle) {
4387   const auto context_type = kContextTypeConversational;
4388   const auto leaudio_group_id = 6;
4389   const auto num_devices = 1;
4390 
4391   // Prepare multiple fake connected devices in a group
4392   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
4393   ASSERT_EQ(group->Size(), num_devices);
4394 
4395   // Should not trigger any action on our side
4396   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
4397   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(0);
4398   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
4399   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
4400   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
4401   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
4402   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
4403 
4404   for (auto* device = group->GetFirstDevice(); device != nullptr;
4405        device = group->GetNextDevice(device)) {
4406     for (auto& ase : device->ases_) {
4407       ASSERT_EQ(ase.id, bluetooth::le_audio::types::ase::kAseIdInvalid);
4408       InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle, nullptr);
4409       ASSERT_EQ(ase.id, ase_id_last_assigned);
4410     }
4411   }
4412 }
4413 
TEST_F(StateMachineTest,testAseIdAssignmentCodecConfigured)4414 TEST_F(StateMachineTest, testAseIdAssignmentCodecConfigured) {
4415   const auto context_type = kContextTypeConversational;
4416   const auto leaudio_group_id = 6;
4417   const auto num_devices = 1;
4418 
4419   // Prepare multiple fake connected devices in a group
4420   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
4421   ASSERT_EQ(group->Size(), num_devices);
4422 
4423   // Should not trigger any action on our side
4424   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
4425   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(0);
4426   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
4427   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
4428   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
4429   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
4430   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
4431 
4432   for (auto* device = group->GetFirstDevice(); device != nullptr;
4433        device = group->GetNextDevice(device)) {
4434     for (auto& ase : device->ases_) {
4435       client_parser::ascs::ase_codec_configured_state_params codec_configured_state_params;
4436 
4437       ASSERT_EQ(ase.id, bluetooth::le_audio::types::ase::kAseIdInvalid);
4438       InjectAseStateNotification(&ase, device, group, ascs::kAseStateCodecConfigured,
4439                                  &codec_configured_state_params);
4440       ASSERT_EQ(ase.id, ase_id_last_assigned);
4441     }
4442   }
4443 }
4444 
TEST_F(StateMachineTest,testAseAutonomousRelease)4445 TEST_F(StateMachineTest, testAseAutonomousRelease) {
4446   /* Device is banded headphones with 2x snk + 1x src ase
4447    * (1x bidirectional + 1xunidirectional CIS)
4448    */
4449   additional_snk_ases = 1;
4450   const auto context_type = kContextTypeConversational;
4451   const int leaudio_group_id = 4;
4452 
4453   // Prepare fake connected device group
4454   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4455 
4456   /* Since we prepared device with Conversional context in mind, Sink and Source
4457    * ASEs should have been configured.
4458    */
4459   PrepareConfigureCodecHandler(group, 3);
4460   PrepareConfigureQosHandler(group, 3);
4461   PrepareEnableHandler(group, 3);
4462   PrepareDisableHandler(group, 3);
4463   PrepareReceiverStartReadyHandler(group, 1);
4464   PrepareReceiverStopReady(group, 1);
4465   PrepareReleaseHandler(group, 3);
4466 
4467   InjectInitialIdleNotification(group);
4468 
4469   // Validate initial GroupStreamStatus
4470   EXPECT_CALL(mock_callbacks_,
4471               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4472           .Times(1);
4473 
4474   // Start the configuration and stream Media content
4475   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4476           group, context_type,
4477           {.sink = types::AudioContexts(context_type),
4478            .source = types::AudioContexts(context_type)}));
4479 
4480   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4481 
4482   // Validate new GroupStreamStatus
4483   EXPECT_CALL(mock_callbacks_,
4484               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4485           .Times(1);
4486   EXPECT_CALL(mock_callbacks_,
4487               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE))
4488           .Times(AtLeast(1));
4489 
4490   /* Single disconnect as it is bidirectional Cis*/
4491   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
4492 
4493   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
4494   reset_mock_function_count_map();
4495 
4496   for (auto* device = group->GetFirstDevice(); device != nullptr;
4497        device = group->GetNextDevice(device)) {
4498     for (auto& ase : device->ases_) {
4499       client_parser::ascs::ase_codec_configured_state_params codec_configured_state_params;
4500 
4501       ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
4502 
4503       // Each one does the autonomous release
4504       InjectAseStateNotification(&ase, device, group, ascs::kAseStateReleasing,
4505                                  &codec_configured_state_params);
4506       InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle,
4507                                  &codec_configured_state_params);
4508     }
4509   }
4510 
4511   // Verify we've handled the release and updated all states
4512   for (auto* device = group->GetFirstDevice(); device != nullptr;
4513        device = group->GetNextDevice(device)) {
4514     for (auto& ase : device->ases_) {
4515       ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4516     }
4517   }
4518 
4519   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
4520 }
4521 
TEST_F(StateMachineTest,testAseAutonomousRelease2Devices)4522 TEST_F(StateMachineTest, testAseAutonomousRelease2Devices) {
4523   const auto context_type = kContextTypeConversational;
4524   const int leaudio_group_id = 4;
4525   const int num_of_devices = 2;
4526 
4527   // Prepare fake connected device group
4528   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_of_devices);
4529 
4530   /* Since we prepared device with Conversional context in mind, Sink and Source
4531    * ASEs should have been configured.
4532    */
4533   PrepareConfigureCodecHandler(group);
4534   PrepareConfigureQosHandler(group);
4535   PrepareEnableHandler(group);
4536   PrepareDisableHandler(group);
4537   PrepareReceiverStartReadyHandler(group);
4538   PrepareReceiverStopReady(group);
4539   PrepareReleaseHandler(group);
4540 
4541   InjectInitialIdleNotification(group);
4542 
4543   // Validate initial GroupStreamStatus
4544   EXPECT_CALL(mock_callbacks_,
4545               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4546           .Times(1);
4547 
4548   // Start the configuration and stream Media content
4549   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4550           group, context_type,
4551           {.sink = types::AudioContexts(context_type),
4552            .source = types::AudioContexts(context_type)}));
4553 
4554   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4555 
4556   /* Check streaming will continue. Streaming status should be send up so the user
4557    * can update e.g. CIS count
4558    */
4559   EXPECT_CALL(mock_callbacks_,
4560               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
4561           .Times(1);
4562 
4563   EXPECT_CALL(mock_callbacks_,
4564               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE))
4565           .Times(0);
4566 
4567   /* Single disconnect as it is bidirectional Cis*/
4568   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
4569 
4570   auto device = group->GetFirstDevice();
4571   for (auto& ase : device->ases_) {
4572     client_parser::ascs::ase_codec_configured_state_params codec_configured_state_params;
4573 
4574     ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
4575 
4576     // Simulate autonomus release for one device.
4577     InjectAseStateNotification(&ase, device, group, ascs::kAseStateReleasing,
4578                                &codec_configured_state_params);
4579     InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle,
4580                                &codec_configured_state_params);
4581     testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4582   }
4583 }
4584 
TEST_F(StateMachineTest,testHandlingAutonomousCodecConfigStateOnConnection)4585 TEST_F(StateMachineTest, testHandlingAutonomousCodecConfigStateOnConnection) {
4586   /* Scenario
4587    * 1. After connection remote device has different ASE configurations
4588    * 2. Try to start stream and make sure it is configured well.
4589    */
4590 
4591   const auto context_type = kContextTypeConversational;
4592   const int leaudio_group_id = 4;
4593   const int num_of_devices = 2;
4594 
4595   // Prepare fake connected device group
4596   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_of_devices);
4597 
4598   auto* firstDevice = group->GetFirstDevice();
4599   auto* secondDevice = group->GetNextDevice(firstDevice);
4600 
4601   /* Since we prepared device with Conversional context in mind, Sink and Source
4602    * ASEs should have been configured.
4603    */
4604   PrepareConfigureCodecHandler(group, 0, true);
4605   PrepareConfigureQosHandler(group);
4606   PrepareEnableHandler(group);
4607   PrepareDisableHandler(group);
4608   PrepareReceiverStartReadyHandler(group);
4609   PrepareReceiverStopReady(group);
4610 
4611   /* Number of control point calls
4612    * 1. Codec Config
4613    * 2. QoS Config
4614    * 3. Enable
4615    * 4. Receiver Start Ready
4616    */
4617   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
4618                                               _, GATT_WRITE_NO_RSP, _, _))
4619           .Times(4);
4620 
4621   EXPECT_CALL(gatt_queue,
4622               WriteCharacteristic(secondDevice->conn_id_, secondDevice->ctp_hdls_.val_hdl, _,
4623                                   GATT_WRITE_NO_RSP, _, _))
4624           .Times(4);
4625 
4626   InjectInitialIdleAndConfiguredNotification(group);
4627   // Call it second time to make sure we get into state that current_state_ is
4628   // different then target_state_ even group is not in transition.
4629   InjectInitialIdleAndConfiguredNotification(group);
4630 
4631   ASSERT_TRUE(group->GetTargetState() != group->GetState());
4632   ASSERT_FALSE(group->IsInTransition());
4633 
4634   // Validate initial GroupStreamStatus
4635   EXPECT_CALL(mock_callbacks_,
4636               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
4637 
4638   // Start the configuration and stream Media content
4639   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4640           group, context_type,
4641           {.sink = types::AudioContexts(context_type),
4642            .source = types::AudioContexts(context_type)}));
4643 
4644   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4645 }
4646 
TEST_F(StateMachineTest,testHandlingInvalidRemoteAseStateHandling)4647 TEST_F(StateMachineTest, testHandlingInvalidRemoteAseStateHandling) {
4648   /* Scenario
4649    * 1. After connection remote device has different ASE configurations
4650    * 2. Try to start stream and make sure it is configured well.
4651    */
4652 
4653   const auto context_type = kContextTypeConversational;
4654   const int leaudio_group_id = 4;
4655   const int num_of_devices = 2;
4656 
4657   // Prepare fake connected device group
4658   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_of_devices);
4659 
4660   auto* firstDevice = group->GetFirstDevice();
4661   auto* secondDevice = group->GetNextDevice(firstDevice);
4662 
4663   /* Since we prepared device with Conversional context in mind, Sink and Source
4664    * ASEs should have been configured.
4665    */
4666   PrepareConfigureCodecHandler(group, 0, true);
4667   PrepareConfigureQosHandler(group);
4668   PrepareEnableHandler(group);
4669   PrepareDisableHandler(group);
4670   PrepareReceiverStartReadyHandler(group);
4671   PrepareReceiverStopReady(group);
4672 
4673   /* Number of control point calls
4674    * 1. Codec Config
4675    * 2. QoS Config
4676    * 3. Enable
4677    * 4. Receiver Start Ready
4678    */
4679   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
4680                                               _, GATT_WRITE_NO_RSP, _, _))
4681           .Times(4);
4682 
4683   EXPECT_CALL(gatt_queue,
4684               WriteCharacteristic(secondDevice->conn_id_, secondDevice->ctp_hdls_.val_hdl, _,
4685                                   GATT_WRITE_NO_RSP, _, _))
4686           .Times(4);
4687 
4688   /* Inject invalid states*/
4689   InjectInitialInvalidNotification(group);
4690 
4691   ASSERT_FALSE(group->IsInTransition());
4692 
4693   // Validate initial GroupStreamStatus
4694   EXPECT_CALL(mock_callbacks_,
4695               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
4696 
4697   // Start the configuration and stream Media content
4698   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4699           group, context_type,
4700           {.sink = types::AudioContexts(context_type),
4701            .source = types::AudioContexts(context_type)}));
4702 
4703   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4704 }
4705 
TEST_F(StateMachineTest,testHandlingCachedCodecConfig2Devices)4706 TEST_F(StateMachineTest, testHandlingCachedCodecConfig2Devices) {
4707   const auto context_type = kContextTypeConversational;
4708   const int leaudio_group_id = 4;
4709   const int num_of_devices = 2;
4710 
4711   // Prepare fake connected device group
4712   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_of_devices);
4713 
4714   auto* firstDevice = group->GetFirstDevice();
4715   auto* secondDevice = group->GetNextDevice(firstDevice);
4716 
4717   /* Since we prepared device with Conversional context in mind, Sink and Source
4718    * ASEs should have been configured.
4719    */
4720   PrepareConfigureCodecHandler(group, 0, true);
4721   PrepareConfigureQosHandler(group);
4722   PrepareEnableHandler(group);
4723   PrepareDisableHandler(group);
4724   PrepareReceiverStartReadyHandler(group);
4725   PrepareReceiverStopReady(group);
4726   PrepareReleaseHandler(group);
4727 
4728   stay_in_releasing_state_ = true;
4729 
4730   /* Number of control point calls
4731    * 1. Codec Config
4732    * 2. QoS Config
4733    * 3. Enable
4734    * 4. Receiver Start Ready
4735    * 5. Release*/
4736   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
4737                                               _, GATT_WRITE_NO_RSP, _, _))
4738           .Times(5);
4739 
4740   EXPECT_CALL(gatt_queue,
4741               WriteCharacteristic(secondDevice->conn_id_, secondDevice->ctp_hdls_.val_hdl, _,
4742                                   GATT_WRITE_NO_RSP, _, _))
4743           .Times(5);
4744 
4745   InjectInitialIdleNotification(group);
4746 
4747   // Validate initial GroupStreamStatus
4748   EXPECT_CALL(mock_callbacks_,
4749               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
4750 
4751   // Start the configuration and stream Media content
4752   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4753           group, context_type,
4754           {.sink = types::AudioContexts(context_type),
4755            .source = types::AudioContexts(context_type)}));
4756 
4757   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4758 
4759   /* Two disconnect as it is two bidirectional Cises */
4760   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
4761 
4762   // Validate initial GroupStreamStatus
4763   EXPECT_CALL(mock_callbacks_,
4764               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING))
4765           .Times(1);
4766   EXPECT_CALL(mock_callbacks_,
4767               StatusReportCb(leaudio_group_id,
4768                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS))
4769           .Times(0);
4770 
4771   // Stop the stream
4772   LeAudioGroupStateMachine::Get()->StopStream(group);
4773 
4774   for (auto& ase : firstDevice->ases_) {
4775     log::debug("{} , {}, {}", firstDevice->address_, ase.id,
4776                bluetooth::common::ToString(ase.state));
4777     ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING);
4778     // Simulate autonomus configured state.
4779     InjectAseStateNotification(&ase, firstDevice, group, ascs::kAseStateCodecConfigured,
4780                                &cached_codec_configuration_map_[ase.id]);
4781   }
4782 
4783   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4784 
4785   /* When ALL devices got inactive, we should got the proper group status */
4786   EXPECT_CALL(mock_callbacks_,
4787               StatusReportCb(leaudio_group_id,
4788                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS))
4789           .Times(1);
4790   for (auto& ase : secondDevice->ases_) {
4791     log::debug("{} , {}, {}", firstDevice->address_, ase.id,
4792                bluetooth::common::ToString(ase.state));
4793     ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING);
4794     // Simulate autonomus configured state.
4795     InjectAseStateNotification(&ase, secondDevice, group, ascs::kAseStateCodecConfigured,
4796                                &cached_codec_configuration_map_[ase.id]);
4797   }
4798 
4799   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
4800 }
4801 
TEST_F(StateMachineTest,testStateTransitionTimeoutOnIdleState)4802 TEST_F(StateMachineTest, testStateTransitionTimeoutOnIdleState) {
4803   const auto context_type = kContextTypeRingtone;
4804   const int leaudio_group_id = 4;
4805   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
4806 
4807   // Prepare fake connected device group
4808   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4809 
4810   auto* leAudioDevice = group->GetFirstDevice();
4811   EXPECT_CALL(gatt_queue,
4812               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4813                                   GATT_WRITE_NO_RSP, _, _))
4814           .Times(1);
4815 
4816   // Start the configuration and stream Media content
4817   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4818           group, context_type,
4819           {.sink = types::AudioContexts(context_type),
4820            .source = types::AudioContexts(context_type)}));
4821 
4822   // Disconnect device
4823   // in client.cc before this function is called, state of device is changed.
4824   leAudioDevice->SetConnectionState(DeviceConnectState::DISCONNECTED);
4825   LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(group, leAudioDevice);
4826 
4827   // Make sure timeout is cleared
4828   ASSERT_TRUE(fake_osi_alarm_set_on_mloop_.cb == nullptr);
4829 }
4830 
TEST_F(StateMachineTest,testStateIdleNotifyAclDisconnectedRemoveCig)4831 TEST_F(StateMachineTest, testStateIdleNotifyAclDisconnectedRemoveCig) {
4832   const auto context_type = kContextTypeRingtone;
4833   const int leaudio_group_id = 4;
4834 
4835   // Prepare fake connected device group
4836   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4837   group->cig.SetState(types::CigState::CREATED);
4838 
4839   // Assert current state
4840   ASSERT_TRUE(group->GetState() == types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4841   ASSERT_FALSE(group->IsInTransition());
4842   ASSERT_TRUE(group->cig.GetState() == types::CigState::CREATED);
4843 
4844   // Expect RemoveCig to be called
4845   EXPECT_CALL(*mock_iso_manager_, RemoveCig(group->group_id_, _)).Times(1);
4846 
4847   // Disconnect device
4848   auto* leAudioDevice = group->GetFirstDevice();
4849   LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(group, leAudioDevice);
4850 
4851   // Assert Cig state transition to NONE after REMOVING
4852   ASSERT_TRUE(group->cig.GetState() == types::CigState::NONE);
4853 }
4854 
TEST_F(StateMachineTest,testStateTransitionTimeout)4855 TEST_F(StateMachineTest, testStateTransitionTimeout) {
4856   const auto context_type = kContextTypeRingtone;
4857   const int leaudio_group_id = 4;
4858   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
4859 
4860   // Prepare fake connected device group
4861   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4862 
4863   /* Since we prepared device with Ringtone context in mind, only one ASE
4864    * should have been configured.
4865    */
4866   PrepareConfigureCodecHandler(group, 1);
4867   PrepareConfigureQosHandler(group, 1);
4868 
4869   auto* leAudioDevice = group->GetFirstDevice();
4870   EXPECT_CALL(gatt_queue,
4871               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4872                                   GATT_WRITE_NO_RSP, _, _))
4873           .Times(3);
4874 
4875   // Start the configuration and stream Media content
4876   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4877           group, context_type,
4878           {.sink = types::AudioContexts(context_type),
4879            .source = types::AudioContexts(context_type)}));
4880 
4881   // Check if timeout is fired
4882   EXPECT_CALL(mock_callbacks_, OnStateTransitionTimeout(leaudio_group_id));
4883 
4884   // simulate timeout seconds passed, alarm executing
4885   fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
4886   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
4887 }
4888 
TEST_F(StateMachineTest,testStateTransitionTimeoutAndDisconnectWhenConfigured)4889 TEST_F(StateMachineTest, testStateTransitionTimeoutAndDisconnectWhenConfigured) {
4890   const auto context_type = kContextTypeMedia;
4891   const int leaudio_group_id = 4;
4892   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
4893 
4894   // Prepare fake connected device group
4895   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4896 
4897   auto* leAudioDevice = group->GetFirstDevice();
4898   EXPECT_CALL(gatt_queue,
4899               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4900                                   GATT_WRITE_NO_RSP, _, _))
4901           .Times(1);
4902 
4903   InjectInitialConfiguredNotification(group);
4904 
4905   group->PrintDebugState();
4906 
4907   // Start the configuration and stream Media content
4908   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4909           group, context_type,
4910           {.sink = types::AudioContexts(context_type),
4911            .source = types::AudioContexts(context_type)}));
4912 
4913   group->PrintDebugState();
4914 
4915   // Check if timeout is fired
4916   EXPECT_CALL(mock_callbacks_, OnStateTransitionTimeout(leaudio_group_id));
4917 
4918   // simulate timeout seconds passed, alarm executing
4919   fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
4920   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
4921 
4922   log::info("OnStateTransitionTimeout");
4923 
4924   /* Simulate On State timeout */
4925   group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4926   group->ClearAllCises();
4927   group->PrintDebugState();
4928 
4929   InjectAclDisconnected(group, leAudioDevice);
4930 
4931   /* Verify that all ASEs are inactive and reconfiguration flag is cleared.*/
4932   for (const auto& ase : leAudioDevice->ases_) {
4933     ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4934     ASSERT_EQ(ase.cis_state, types::CisState::IDLE);
4935     ASSERT_EQ(ase.data_path_state, types::DataPathState::IDLE);
4936     ASSERT_EQ(ase.reconfigure, 0);
4937   }
4938 }
4939 
TEST_F(StateMachineTest,testStateTransitionTimeoutAndDisconnectWhenQoSConfigured)4940 TEST_F(StateMachineTest, testStateTransitionTimeoutAndDisconnectWhenQoSConfigured) {
4941   const auto context_type = kContextTypeMedia;
4942   const int leaudio_group_id = 4;
4943   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
4944 
4945   // Prepare fake connected device group
4946   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4947   PrepareConfigureCodecHandler(group, 1);
4948 
4949   auto* leAudioDevice = group->GetFirstDevice();
4950   EXPECT_CALL(gatt_queue,
4951               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
4952                                   GATT_WRITE_NO_RSP, _, _))
4953           .Times(2);
4954 
4955   InjectInitialConfiguredNotification(group);
4956 
4957   group->PrintDebugState();
4958 
4959   // Start the configuration and stream Media content
4960   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
4961           group, context_type,
4962           {.sink = types::AudioContexts(context_type),
4963            .source = types::AudioContexts(context_type)}));
4964 
4965   group->PrintDebugState();
4966 
4967   // Check if timeout is fired
4968   EXPECT_CALL(mock_callbacks_, OnStateTransitionTimeout(leaudio_group_id));
4969 
4970   // simulate timeout seconds passed, alarm executing
4971   fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
4972   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
4973 
4974   log::info("OnStateTransitionTimeout");
4975 
4976   /* Simulate On State timeout */
4977   group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4978   group->ClearAllCises();
4979   group->PrintDebugState();
4980 
4981   InjectAclDisconnected(group, leAudioDevice);
4982 
4983   /* Verify that all ASEs are inactive and reconfiguration flag is cleared.*/
4984   for (const auto& ase : leAudioDevice->ases_) {
4985     ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
4986     ASSERT_EQ(ase.cis_state, types::CisState::IDLE);
4987     ASSERT_EQ(ase.data_path_state, types::DataPathState::IDLE);
4988     ASSERT_EQ(ase.reconfigure, 0);
4989   }
4990 }
4991 
TEST_F(StateMachineTest,testStateTransitionTimeoutAndDisconnectWhenEnabling)4992 TEST_F(StateMachineTest, testStateTransitionTimeoutAndDisconnectWhenEnabling) {
4993   const auto context_type = kContextTypeMedia;
4994   const int leaudio_group_id = 4;
4995   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
4996 
4997   // Prepare fake connected device group
4998   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
4999   PrepareConfigureCodecHandler(group, 1);
5000   PrepareConfigureQosHandler(group, 1);
5001 
5002   auto* leAudioDevice = group->GetFirstDevice();
5003   EXPECT_CALL(gatt_queue,
5004               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
5005                                   GATT_WRITE_NO_RSP, _, _))
5006           .Times(3);
5007 
5008   InjectInitialConfiguredNotification(group);
5009 
5010   group->PrintDebugState();
5011 
5012   // Start the configuration and stream Media content
5013   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
5014           group, context_type,
5015           {.sink = types::AudioContexts(context_type),
5016            .source = types::AudioContexts(context_type)}));
5017 
5018   group->PrintDebugState();
5019 
5020   // Check if timeout is fired
5021   EXPECT_CALL(mock_callbacks_, OnStateTransitionTimeout(leaudio_group_id));
5022 
5023   // simulate timeout seconds passed, alarm executing
5024   fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
5025   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
5026 
5027   log::info("OnStateTransitionTimeout");
5028 
5029   /* Simulate On State timeout */
5030   group->SetTargetState(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5031   group->ClearAllCises();
5032   group->PrintDebugState();
5033 
5034   InjectAclDisconnected(group, leAudioDevice);
5035 
5036   /* Verify that all ASEs are inactive and reconfiguration flag is cleared.*/
5037   for (const auto& ase : leAudioDevice->ases_) {
5038     ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5039     ASSERT_EQ(ase.cis_state, types::CisState::IDLE);
5040     ASSERT_EQ(ase.data_path_state, types::DataPathState::IDLE);
5041     ASSERT_EQ(ase.reconfigure, 0);
5042   }
5043 }
5044 
TEST_F(StateMachineTest,testInjectReleasingStateWhenEnabling)5045 TEST_F(StateMachineTest, testInjectReleasingStateWhenEnabling) {
5046   const auto context_type = kContextTypeConversational;
5047   const int leaudio_group_id = 4;
5048   channel_count_ = kLeAudioCodecChannelCountSingleChannel;
5049 
5050   // Prepare fake connected device group
5051   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
5052   PrepareConfigureCodecHandler(group, 2);
5053   PrepareConfigureQosHandler(group, 2);
5054   PrepareEnableHandler(group, 0, true, false);
5055 
5056   InjectInitialConfiguredNotification(group);
5057 
5058   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
5059   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5060   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
5061   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
5062   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
5063   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
5064 
5065   // Stub Establish Cis and Remove CIG
5066   ON_CALL(*mock_iso_manager_, EstablishCis).WillByDefault(Return());
5067   ON_CALL(*mock_iso_manager_, RemoveCig).WillByDefault(Return());
5068 
5069   group->PrintDebugState();
5070 
5071   // Start the configuration and stream Media content
5072   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
5073           group, context_type,
5074           {.sink = types::AudioContexts(context_type),
5075            .source = types::AudioContexts(context_type)}));
5076 
5077   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5078 
5079   group->PrintDebugState();
5080 
5081   log::info("Inject Release of all ASEs");
5082 
5083   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
5084 
5085   // Stub DisconnectCis to trigger the issue.
5086   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
5087 
5088   InjectReleaseAndIdleStateForAGroup(group, true, false);
5089 
5090   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5091 }
5092 
5093 MATCHER_P(dataPathIsEq, expected, "") { return arg.data_path_id == expected; }
5094 
TEST_F(StateMachineTest,testConfigureDataPathForHost)5095 TEST_F(StateMachineTest, testConfigureDataPathForHost) {
5096   const auto context_type = kContextTypeRingtone;
5097   const int leaudio_group_id = 4;
5098   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
5099 
5100   /* Can be called for every context when fetching the configuration
5101    */
5102   EXPECT_CALL(*mock_codec_manager_, GetCodecConfig(_, _)).Times(AtLeast(1));
5103 
5104   // Prepare fake connected device group
5105   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
5106 
5107   /* Since we prepared device with Ringtone context in mind, only one ASE
5108    * should have been configured.
5109    */
5110   PrepareConfigureCodecHandler(group, 1);
5111   PrepareConfigureQosHandler(group, 1);
5112   PrepareEnableHandler(group, 1);
5113 
5114   EXPECT_CALL(*mock_iso_manager_,
5115               SetupIsoDataPath(_, dataPathIsEq(bluetooth::hci::iso_manager::kIsoDataPathHci)))
5116           .Times(1);
5117 
5118   InjectInitialIdleNotification(group);
5119 
5120   // Start the configuration and stream Media content
5121   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
5122           group, context_type,
5123           {.sink = types::AudioContexts(context_type),
5124            .source = types::AudioContexts(context_type)}));
5125 }
5126 
TEST_F(StateMachineTest,testRemoveDataPathWhenSingleBudDisconnectsOnGattTimeout)5127 TEST_F(StateMachineTest, testRemoveDataPathWhenSingleBudDisconnectsOnGattTimeout) {
5128   const auto context_type = kContextTypeConversational;
5129   const int leaudio_group_id = 4;
5130   const auto num_devices = 2;
5131   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
5132 
5133   /* Scenario
5134    * 1. Two buds are streaming
5135    * 2. There is a GATT timeout on one of the device which cause disconnection but profile will get
5136    * fist GATT Close and later CIS Disconnection Timeout
5137    *
5138    * 3. Verify that Data Path is removed for the disconnected CIS
5139    */
5140 
5141   ContentControlIdKeeper::GetInstance()->SetCcid(kContextTypeConversational, call_ccid);
5142 
5143   // Prepare multiple fake connected devices in a group
5144   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
5145   ASSERT_EQ(group->Size(), num_devices);
5146 
5147   /* Since we prepared device with Ringtone context in mind, only one ASE
5148    * should have been configured.
5149    */
5150   PrepareConfigureCodecHandler(group);
5151   PrepareConfigureQosHandler(group);
5152   PrepareEnableHandler(group);
5153   PrepareReceiverStartReadyHandler(group);
5154 
5155   EXPECT_CALL(*mock_iso_manager_,
5156               SetupIsoDataPath(_, dataPathIsEq(bluetooth::hci::iso_manager::kIsoDataPathHci)))
5157           .Times(4);
5158 
5159   InjectInitialIdleNotification(group);
5160 
5161   // Start the configuration and stream Media content
5162   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
5163           group, context_type,
5164           {.sink = types::AudioContexts(context_type),
5165            .source = types::AudioContexts(context_type)}));
5166 
5167   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5168 
5169   EXPECT_CALL(*mock_iso_manager_,
5170               RemoveIsoDataPath(
5171                       _, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput |
5172                                  bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput))
5173           .Times(1);
5174 
5175   auto device = group->GetFirstDevice();
5176   InjectAclDisconnected(group, device);
5177   InjectCisDisconnected(group, device, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
5178 
5179   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5180 }
5181 
TEST_F(StateMachineTestAdsp,testConfigureDataPathForAdsp)5182 TEST_F(StateMachineTestAdsp, testConfigureDataPathForAdsp) {
5183   const auto context_type = kContextTypeRingtone;
5184   const int leaudio_group_id = 4;
5185   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
5186 
5187   /* Can be called for every context when fetching the configuration
5188    */
5189   EXPECT_CALL(*mock_codec_manager_, GetCodecConfig(_, _)).Times(AtLeast(1));
5190 
5191   // Prepare fake connected device group
5192   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
5193 
5194   /* Since we prepared device with Ringtone context in mind, only one ASE
5195    * should have been configured.
5196    */
5197   PrepareConfigureCodecHandler(group, 1);
5198   PrepareConfigureQosHandler(group, 1);
5199   PrepareEnableHandler(group, 1);
5200 
5201   EXPECT_CALL(*mock_iso_manager_,
5202               SetupIsoDataPath(
5203                       _, dataPathIsEq(bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault)))
5204           .Times(1);
5205 
5206   InjectInitialIdleNotification(group);
5207 
5208   // Start the configuration and stream Media content
5209   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
5210           group, context_type,
5211           {.sink = types::AudioContexts(context_type),
5212            .source = types::AudioContexts(context_type)}));
5213 }
5214 
TEST_F(StateMachineTestAdsp,testStreamConfigurationAdspDownMix)5215 TEST_F(StateMachineTestAdsp, testStreamConfigurationAdspDownMix) {
5216   const auto context_type = kContextTypeConversational;
5217   const int leaudio_group_id = 4;
5218   const int num_devices = 2;
5219 
5220   // Prepare fake connected device group
5221   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
5222                                              types::AudioContexts(kContextTypeConversational));
5223 
5224   EXPECT_CALL(mock_callbacks_,
5225               OnUpdatedCisConfiguration(group->group_id_,
5226                                         bluetooth::le_audio::types::kLeAudioDirectionSink))
5227           .Times(1);
5228   EXPECT_CALL(mock_callbacks_,
5229               OnUpdatedCisConfiguration(group->group_id_,
5230                                         bluetooth::le_audio::types::kLeAudioDirectionSource))
5231           .Times(1);
5232 
5233   /* Can be called for every context when fetching the configuration
5234    */
5235   EXPECT_CALL(*mock_codec_manager_, GetCodecConfig(_, _)).Times(AtLeast(1));
5236 
5237   PrepareConfigureCodecHandler(group);
5238   PrepareConfigureQosHandler(group);
5239   PrepareEnableHandler(group);
5240   PrepareReceiverStartReadyHandler(group);
5241 
5242   InjectInitialIdleNotification(group);
5243 
5244   auto* leAudioDevice = group->GetFirstDevice();
5245   InjectAclDisconnected(group, leAudioDevice);
5246 
5247   // Start the configuration and stream Media content
5248   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
5249           group, context_type,
5250           {.sink = types::AudioContexts(context_type),
5251            .source = types::AudioContexts(context_type)}));
5252 
5253   // Check if group has transitioned to a proper state
5254   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5255 
5256   // Note: The actual channel mixing is verified by the CodecManager unit tests.
5257 }
5258 
TEST_F(StateMachineTest,testAttachDeviceToTheStream)5259 TEST_F(StateMachineTest, testAttachDeviceToTheStream) {
5260   const auto context_type = kContextTypeMedia;
5261   const auto leaudio_group_id = 6;
5262   const auto num_devices = 2;
5263 
5264   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
5265 
5266   // Prepare multiple fake connected devices in a group
5267   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
5268   ASSERT_EQ(group->Size(), num_devices);
5269 
5270   PrepareConfigureCodecHandler(group);
5271   PrepareConfigureQosHandler(group);
5272   PrepareEnableHandler(group);
5273   PrepareDisableHandler(group);
5274   PrepareReleaseHandler(group);
5275 
5276   auto* leAudioDevice = group->GetFirstDevice();
5277   LeAudioDevice* lastDevice;
5278   LeAudioDevice* fistDevice = leAudioDevice;
5279 
5280   auto expected_devices_written = 0;
5281   while (leAudioDevice) {
5282     /* Three Writes:
5283      * 1: Codec Config
5284      * 2: Codec QoS
5285      * 3: Enabling
5286      */
5287     lastDevice = leAudioDevice;
5288     EXPECT_CALL(gatt_queue,
5289                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
5290                                     GATT_WRITE_NO_RSP, _, _))
5291             .Times(AtLeast(3));
5292     expected_devices_written++;
5293     leAudioDevice = group->GetNextDevice(leAudioDevice);
5294   }
5295   ASSERT_EQ(expected_devices_written, num_devices);
5296 
5297   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
5298   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5299   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
5300 
5301   InjectInitialIdleNotification(group);
5302 
5303   // Start the configuration and stream Media content
5304   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
5305                                                {.sink = types::AudioContexts(context_type),
5306                                                 .source = types::AudioContexts(context_type)});
5307 
5308   // Check if group has transitioned to a proper state
5309   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5310   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5311 
5312   // Inject CIS and ACL disconnection of first device
5313   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
5314   InjectAclDisconnected(group, lastDevice);
5315 
5316   // Check if group keeps streaming
5317   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5318 
5319   lastDevice->conn_id_ = 3;
5320   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
5321 
5322   // Make sure ASE with disconnected CIS are not left in STREAMING
5323   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
5324                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5325             nullptr);
5326   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
5327                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5328             nullptr);
5329 
5330   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
5331                                               _, GATT_WRITE_NO_RSP, _, _))
5332           .Times(AtLeast(3));
5333 
5334   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5335   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
5336   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
5337                                                   {.sink = {media_ccid}, .source = {}});
5338 
5339   // Check if group keeps streaming
5340   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5341 
5342   // Verify that the joining device receives the right CCID list
5343   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
5344   bool parsedOk = false;
5345   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
5346                                                               parsedOk);
5347   ASSERT_TRUE(parsedOk);
5348 
5349   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
5350   ASSERT_TRUE(ccids.has_value());
5351   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
5352 
5353   /* Verify that ASE of first device are still good*/
5354   auto ase = fistDevice->GetFirstActiveAse();
5355   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
5356   ASSERT_NE(ase->qos_config.retrans_nb, 0);
5357 }
5358 
TEST_F(StateMachineTest,testAttachDeviceToTheStreamV2)5359 TEST_F(StateMachineTest, testAttachDeviceToTheStreamV2) {
5360   const auto context_type = kContextTypeMedia;
5361   const auto leaudio_group_id = 6;
5362   const auto num_devices = 2;
5363 
5364   /* Scenario
5365    * 1. Both devices streaming
5366    * 2. One device disconnects
5367    * 3. Audio configuration resume and configuration cache is rebuilt
5368    * 4. Device attached
5369    */
5370   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
5371 
5372   // Prepare multiple fake connected devices in a group
5373   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
5374   ASSERT_EQ(group->Size(), num_devices);
5375 
5376   PrepareConfigureCodecHandler(group);
5377   PrepareConfigureQosHandler(group);
5378   PrepareEnableHandler(group);
5379   PrepareDisableHandler(group);
5380   PrepareReleaseHandler(group);
5381 
5382   auto* leAudioDevice = group->GetFirstDevice();
5383   LeAudioDevice* lastDevice;
5384   LeAudioDevice* fistDevice = leAudioDevice;
5385 
5386   auto expected_devices_written = 0;
5387   while (leAudioDevice) {
5388     /* Three Writes:
5389      * 1: Codec Config
5390      * 2: Codec QoS
5391      * 3: Enabling
5392      */
5393     lastDevice = leAudioDevice;
5394     EXPECT_CALL(gatt_queue,
5395                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
5396                                     GATT_WRITE_NO_RSP, _, _))
5397             .Times(AtLeast(3));
5398     expected_devices_written++;
5399     leAudioDevice = group->GetNextDevice(leAudioDevice);
5400   }
5401   ASSERT_EQ(expected_devices_written, num_devices);
5402 
5403   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
5404   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5405   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
5406 
5407   InjectInitialIdleNotification(group);
5408 
5409   // Start the configuration and stream Media content
5410   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
5411                                                {.sink = types::AudioContexts(context_type),
5412                                                 .source = types::AudioContexts(context_type)});
5413 
5414   // Check if group has transitioned to a proper state
5415   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5416   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5417 
5418   // Inject CIS and ACL disconnection of first device
5419   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
5420   InjectAclDisconnected(group, lastDevice);
5421 
5422   /* Force update configuration which is what happens when stream stops
5423    * and starts while streaming to single dev. This will rebuild cache,
5424    * which is what we need in this test.
5425    */
5426   group->UpdateAudioSetConfigurationCache(context_type);
5427 
5428   // Check if group keeps streaming
5429   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5430 
5431   lastDevice->conn_id_ = 3;
5432   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
5433 
5434   // Make sure ASE with disconnected CIS are not left in STREAMING
5435   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
5436                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5437             nullptr);
5438   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
5439                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5440             nullptr);
5441 
5442   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
5443                                               _, GATT_WRITE_NO_RSP, _, _))
5444           .Times(AtLeast(3));
5445 
5446   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5447   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
5448   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
5449                                                   {.sink = {media_ccid}, .source = {}});
5450 
5451   // Check if group keeps streaming
5452   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5453 
5454   // Verify that the joining device receives the right CCID list
5455   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
5456   bool parsedOk = false;
5457   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
5458                                                               parsedOk);
5459   ASSERT_TRUE(parsedOk);
5460 
5461   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
5462   ASSERT_TRUE(ccids.has_value());
5463   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
5464 
5465   /* Verify that ASE of first device are still good*/
5466   auto ase = fistDevice->GetFirstActiveAse();
5467   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
5468   ASSERT_NE(ase->qos_config.retrans_nb, 0);
5469 }
5470 
TEST_F(StateMachineTest,testAttachDeviceToTheStreamDeviceNoAvailableContext)5471 TEST_F(StateMachineTest, testAttachDeviceToTheStreamDeviceNoAvailableContext) {
5472   const auto context_type = kContextTypeMedia;
5473   const auto leaudio_group_id = 6;
5474   const auto num_devices = 2;
5475 
5476   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
5477 
5478   // Prepare multiple fake connected devices in a group
5479   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
5480   ASSERT_EQ(group->Size(), num_devices);
5481 
5482   PrepareConfigureCodecHandler(group);
5483   PrepareConfigureQosHandler(group);
5484   PrepareEnableHandler(group);
5485   PrepareDisableHandler(group);
5486   PrepareReleaseHandler(group);
5487 
5488   auto* leAudioDevice = group->GetFirstDevice();
5489   LeAudioDevice* lastDevice;
5490 
5491   auto expected_devices_written = 0;
5492   while (leAudioDevice) {
5493     /* Three Writes:
5494      * 1: Codec Config
5495      * 2: Codec QoS
5496      * 3: Enabling
5497      */
5498     lastDevice = leAudioDevice;
5499     EXPECT_CALL(gatt_queue,
5500                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
5501                                     GATT_WRITE_NO_RSP, _, _))
5502             .Times(AtLeast(3));
5503     expected_devices_written++;
5504     leAudioDevice = group->GetNextDevice(leAudioDevice);
5505   }
5506   ASSERT_EQ(expected_devices_written, num_devices);
5507 
5508   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
5509   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5510   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
5511 
5512   InjectInitialIdleNotification(group);
5513 
5514   // Start the configuration and stream Media content
5515   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
5516                                                {.sink = types::AudioContexts(context_type),
5517                                                 .source = types::AudioContexts(context_type)});
5518 
5519   // Check if group has transitioned to a proper state
5520   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5521   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5522 
5523   // Inject CIS and ACL disconnection of first device
5524   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
5525   InjectAclDisconnected(group, lastDevice);
5526 
5527   // Check if group keeps streaming
5528   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5529 
5530   // Connect the disconnected device BUT remove MEDIA from available Contex
5531   // Types
5532   lastDevice->conn_id_ = 3;
5533   auto test_context_type = kContextTypeUnspecified | kContextTypeConversational;
5534   lastDevice->SetAvailableContexts({.sink = test_context_type, .source = test_context_type});
5535   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
5536 
5537   // Make sure ASE with disconnected CIS are not left in STREAMING
5538   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
5539                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5540             nullptr);
5541   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
5542                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5543             nullptr);
5544 
5545   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
5546                                               _, GATT_WRITE_NO_RSP, _, _))
5547           .Times(AtLeast(0));
5548 
5549   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
5550   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
5551   ASSERT_EQ(LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
5552                                                             {.sink = {media_ccid}, .source = {}}),
5553             false);
5554 
5555   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5556 }
5557 
TEST_F(StateMachineTest,testQoSConfigureWhileStreaming)5558 TEST_F(StateMachineTest, testQoSConfigureWhileStreaming) {
5559   /* Device is banded headphones with 1x snk  0x src ase
5560    * (1xunidirectional CIS) with channel count 2 (for stereo
5561    */
5562   const auto context_type = kContextTypeRingtone;
5563   const int leaudio_group_id = 4;
5564   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
5565 
5566   // Prepare fake connected device group
5567   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
5568 
5569   /* Ringtone with channel count 1 for single device and 1 ASE sink will
5570    * end up with 1 Sink ASE being configured.
5571    */
5572   PrepareConfigureCodecHandler(group, 1);
5573   PrepareConfigureQosHandler(group, 1);
5574   PrepareEnableHandler(group, 1);
5575   PrepareReleaseHandler(group, 1);
5576 
5577   /*
5578    * Device got to streaming state and sends QoSConfigured state.
5579    * Num of GATT operations
5580    * 1. Config
5581    * 2. QoS Config
5582    * 3. Enable
5583    * 4. Release
5584    */
5585   auto* leAudioDevice = group->GetFirstDevice();
5586   EXPECT_CALL(gatt_queue,
5587               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
5588                                   GATT_WRITE_NO_RSP, _, _))
5589           .Times(4);
5590 
5591   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
5592   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5593   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
5594   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
5595   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
5596   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
5597 
5598   InjectInitialIdleNotification(group);
5599 
5600   // Validate GroupStreamStatus
5601   EXPECT_CALL(mock_callbacks_,
5602               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
5603 
5604   // Start the configuration and stream Media content
5605   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
5606           group, context_type,
5607           {.sink = types::AudioContexts(context_type),
5608            .source = types::AudioContexts(context_type)}));
5609 
5610   // Check if group has transitioned to a proper state
5611   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5612   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
5613 
5614   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
5615 
5616   log::info(" Moving to QoS state");
5617 
5618   // Validate GroupStreamStatus
5619   EXPECT_CALL(mock_callbacks_,
5620               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
5621   EXPECT_CALL(mock_callbacks_,
5622               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
5623 
5624   InjectQoSConfigurationForGroupActiveAses(group);
5625   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
5626   testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
5627   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
5628 }
5629 
TEST_F(StateMachineTest,testReleaseStreamWithLateAttachToStream_CodecConfigState)5630 TEST_F(StateMachineTest, testReleaseStreamWithLateAttachToStream_CodecConfigState) {
5631   const auto context_type = kContextTypeMedia;
5632   const auto leaudio_group_id = 6;
5633   const auto num_devices = 2;
5634 
5635   /* Scenario
5636    * 1. Start streaming
5637    * 2. Stop stream on one device
5638    * 3. Reconnect
5639    * 4. Trigger attach the stream
5640    * 6. StopStream while getting to Codec Configured State on attaching device
5641    * 7. Check that Attaching device will also go to IDLE
5642    */
5643 
5644   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
5645 
5646   // Prepare multiple fake connected devices in a group
5647   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
5648   ASSERT_EQ(group->Size(), num_devices);
5649 
5650   PrepareConfigureCodecHandler(group, 0, true);
5651   PrepareConfigureQosHandler(group);
5652   PrepareEnableHandler(group);
5653   PrepareDisableHandler(group);
5654 
5655   auto* leAudioDevice = group->GetFirstDevice();
5656   LeAudioDevice* firstDevice = leAudioDevice;
5657   LeAudioDevice* lastDevice;
5658 
5659   auto expected_devices_written = 0;
5660   while (leAudioDevice) {
5661     /* Three Writes:
5662      * 1: Codec Config
5663      * 2: Codec QoS
5664      * 3: Enabling
5665      */
5666     lastDevice = leAudioDevice;
5667     EXPECT_CALL(gatt_queue,
5668                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
5669                                     GATT_WRITE_NO_RSP, _, _))
5670             .Times(3);
5671     expected_devices_written++;
5672     leAudioDevice = group->GetNextDevice(leAudioDevice);
5673   }
5674   ASSERT_EQ(expected_devices_written, num_devices);
5675 
5676   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
5677   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5678   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
5679 
5680   InjectInitialIdleNotification(group);
5681 
5682   // Start the configuration and stream Media content
5683   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
5684                                                {.sink = types::AudioContexts(context_type),
5685                                                 .source = types::AudioContexts(context_type)});
5686 
5687   // Check if group has transitioned to a proper state
5688   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5689   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5690   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
5691 
5692   log::info("Stream is started for group {}, disconnect {}", group->group_id_,
5693             lastDevice->address_);
5694 
5695   // Inject CIS and ACL disconnection of first device
5696   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
5697   InjectAclDisconnected(group, lastDevice);
5698 
5699   // Check if group keeps streaming
5700   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5701 
5702   /* Set device is getting ready for the connection */
5703   lastDevice->conn_id_ = 3;
5704   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
5705 
5706   // Make sure ASE with disconnected CIS are not left in STREAMING
5707   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
5708                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5709             nullptr);
5710   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
5711                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5712             nullptr);
5713 
5714   log::info("Set device {} to CONNECTED state", lastDevice->address_);
5715   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
5716 
5717   /*
5718    * 1. Codec Configure for attaching device
5719    * 2. Release for both devices
5720    */
5721   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
5722                                               _, GATT_WRITE_NO_RSP, _, _))
5723           .Times(2);
5724 
5725   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
5726                                               _, GATT_WRITE_NO_RSP, _, _))
5727           .Times(1);
5728 
5729   log::info("Block Codec Configured Notification");
5730   PrepareConfigureCodecHandler(group, 0, true, false);
5731 
5732   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
5733   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
5734 
5735   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
5736                                                   {.sink = {media_ccid}, .source = {}});
5737 
5738   log::info("Stop the stream");
5739 
5740   EXPECT_CALL(mock_callbacks_,
5741               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
5742   // Stop the stream
5743   LeAudioGroupStateMachine::Get()->StopStream(group);
5744 
5745   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5746   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
5747   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
5748 
5749   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
5750                                               _, GATT_WRITE_NO_RSP, _, _))
5751           .Times(0);
5752 
5753   log::info(
5754           "Inject Codec Configured Notification and make sure there is no QoS "
5755           "Config sent");
5756 
5757   InjectCachedConfigurationForActiveAses(group, lastDevice);
5758   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
5759 
5760   // Check if group is still in Streaming state - it will change when Release
5761   // notification will arrive.
5762   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5763   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5764 
5765   log::info("Inject Release for a group");
5766 
5767   EXPECT_CALL(mock_callbacks_,
5768               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
5769 
5770   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
5771   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
5772   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
5773 
5774   InjectReleaseAndIdleStateForAGroup(group);
5775   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
5776   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5777 
5778   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5779   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5780 }
5781 
TEST_F(StateMachineTest,testReleaseStreamWithLateAttachToStream_QoSConfigState)5782 TEST_F(StateMachineTest, testReleaseStreamWithLateAttachToStream_QoSConfigState) {
5783   const auto context_type = kContextTypeMedia;
5784   const auto leaudio_group_id = 6;
5785   const auto num_devices = 2;
5786 
5787   /* Scenario
5788    * 1. Start streaming
5789    * 2. Stop stream on one device
5790    * 3. Reconnect
5791    * 4. Trigger attach the stream
5792    * 6. StopStream while getting to QoS Configured state on attaching device
5793    * 7. Check that Attaching device will also go to IDLE
5794    */
5795 
5796   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
5797 
5798   // Prepare multiple fake connected devices in a group
5799   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
5800   ASSERT_EQ(group->Size(), num_devices);
5801 
5802   PrepareConfigureCodecHandler(group, 0, true);
5803   PrepareConfigureQosHandler(group);
5804   PrepareEnableHandler(group);
5805   PrepareDisableHandler(group);
5806 
5807   auto* leAudioDevice = group->GetFirstDevice();
5808   LeAudioDevice* firstDevice = leAudioDevice;
5809   LeAudioDevice* lastDevice;
5810 
5811   auto expected_devices_written = 0;
5812   while (leAudioDevice) {
5813     /* Three Writes:
5814      * 1: Codec Config
5815      * 2: Codec QoS
5816      * 3: Enabling
5817      */
5818     lastDevice = leAudioDevice;
5819     EXPECT_CALL(gatt_queue,
5820                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
5821                                     GATT_WRITE_NO_RSP, _, _))
5822             .Times(3);
5823     expected_devices_written++;
5824     leAudioDevice = group->GetNextDevice(leAudioDevice);
5825   }
5826   ASSERT_EQ(expected_devices_written, num_devices);
5827 
5828   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
5829   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5830   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
5831 
5832   InjectInitialIdleNotification(group);
5833 
5834   // Start the configuration and stream Media content
5835   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
5836                                                {.sink = types::AudioContexts(context_type),
5837                                                 .source = types::AudioContexts(context_type)});
5838 
5839   // Check if group has transitioned to a proper state
5840   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5841   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5842 
5843   log::info("Stream is started for group {}, disconnect {}", group->group_id_,
5844             lastDevice->address_);
5845 
5846   // Inject CIS and ACL disconnection of first device
5847   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
5848   InjectAclDisconnected(group, lastDevice);
5849 
5850   // Check if group keeps streaming
5851   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5852 
5853   /* Set device is getting ready for the connection */
5854   lastDevice->conn_id_ = 3;
5855   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
5856 
5857   // Make sure ASE with disconnected CIS are not left in STREAMING
5858   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
5859                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5860             nullptr);
5861   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
5862                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
5863             nullptr);
5864 
5865   log::info("Set device {} to CONNECTED state", lastDevice->address_);
5866   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
5867 
5868   /*
5869    * 1. Codec Configured for attaching device
5870    * 2. QoS Configured State for attaching device
5871    * 3. Release for both
5872    */
5873   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
5874                                               _, GATT_WRITE_NO_RSP, _, _))
5875           .Times(3);
5876   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
5877                                               _, GATT_WRITE_NO_RSP, _, _))
5878           .Times(1);
5879 
5880   log::info("Block QoS Configured Notification");
5881   PrepareConfigureQosHandler(group, 0, true, false);
5882 
5883   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
5884   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
5885 
5886   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
5887                                                   {.sink = {media_ccid}, .source = {}});
5888 
5889   log::info("Stop the stream");
5890 
5891   EXPECT_CALL(mock_callbacks_,
5892               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
5893 
5894   // Stop the stream
5895   LeAudioGroupStateMachine::Get()->StopStream(group);
5896 
5897   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
5898   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5899   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
5900 
5901   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
5902                                               _, GATT_WRITE_NO_RSP, _, _))
5903           .Times(0);
5904 
5905   log::info(
5906           "Inject QoS Config Notification and make sure that Enable Command is not "
5907           "sent");
5908 
5909   InjectQoSConfigurationForActiveAses(group, lastDevice);
5910   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
5911 
5912   // Check if group is still in Streaming state - it will change when Release
5913   // notification will arrive.
5914   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5915   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5916 
5917   log::info("Inject Release for a group");
5918 
5919   EXPECT_CALL(mock_callbacks_,
5920               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
5921 
5922   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
5923   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
5924   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
5925 
5926   InjectReleaseAndIdleStateForAGroup(group);
5927   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
5928   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5929 
5930   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5931   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
5932 }
5933 
TEST_F(StateMachineTest,testReleaseStreamWithLateAttachToStream_EnablingState)5934 TEST_F(StateMachineTest, testReleaseStreamWithLateAttachToStream_EnablingState) {
5935   const auto context_type = kContextTypeMedia;
5936   const auto leaudio_group_id = 6;
5937   const auto num_devices = 2;
5938 
5939   /* Scenario
5940    * 1. Start streaming
5941    * 2. Stop stream on one device
5942    * 3. Reconnect
5943    * 4. Trigger attach the stream
5944    * 6. StopStream while getting to Enable state on attaching device
5945    * 7. Check that Attaching device will also go to IDLE
5946    */
5947 
5948   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
5949 
5950   // Prepare multiple fake connected devices in a group
5951   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
5952   ASSERT_EQ(group->Size(), num_devices);
5953 
5954   PrepareConfigureCodecHandler(group, 0, true);
5955   PrepareConfigureQosHandler(group);
5956   PrepareEnableHandler(group);
5957   PrepareDisableHandler(group);
5958 
5959   auto* leAudioDevice = group->GetFirstDevice();
5960   LeAudioDevice* firstDevice = leAudioDevice;
5961   LeAudioDevice* lastDevice;
5962 
5963   auto expected_devices_written = 0;
5964   while (leAudioDevice) {
5965     /* Three Writes:
5966      * 1: Codec Config
5967      * 2: Codec QoS
5968      * 3: Enabling
5969      */
5970     lastDevice = leAudioDevice;
5971     EXPECT_CALL(gatt_queue,
5972                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
5973                                     GATT_WRITE_NO_RSP, _, _))
5974             .Times(3);
5975     expected_devices_written++;
5976     leAudioDevice = group->GetNextDevice(leAudioDevice);
5977   }
5978   ASSERT_EQ(expected_devices_written, num_devices);
5979 
5980   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
5981   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
5982   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
5983 
5984   InjectInitialIdleNotification(group);
5985 
5986   // Start the configuration and stream Media content
5987   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
5988                                                {.sink = types::AudioContexts(context_type),
5989                                                 .source = types::AudioContexts(context_type)});
5990 
5991   // Check if group has transitioned to a proper state
5992   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
5993   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
5994 
5995   log::info("Stream is started for group {}, disconnect {}", group->group_id_,
5996             lastDevice->address_);
5997 
5998   // Inject CIS and ACL disconnection of first device
5999   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
6000   InjectAclDisconnected(group, lastDevice);
6001 
6002   // Check if group keeps streaming
6003   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6004 
6005   /* Set device is getting ready for the connection */
6006   lastDevice->conn_id_ = 3;
6007   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
6008 
6009   // Make sure ASE with disconnected CIS are not left in STREAMING
6010   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
6011                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6012             nullptr);
6013   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
6014                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6015             nullptr);
6016 
6017   log::info("Set device {} to CONNECTED state", lastDevice->address_);
6018   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6019 
6020   /*
6021    * 1. Codec Configured for attaching device
6022    * 2. QoS Configured State for attaching device
6023    * 3. Enable for attaching device
6024    * 3. Release for both
6025    */
6026   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6027                                               _, GATT_WRITE_NO_RSP, _, _))
6028           .Times(4);
6029   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
6030                                               _, GATT_WRITE_NO_RSP, _, _))
6031           .Times(1);
6032 
6033   log::info("Block Enable Notification");
6034   PrepareEnableHandler(group, 0, false, false);
6035 
6036   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
6037   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
6038 
6039   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
6040                                                   {.sink = {media_ccid}, .source = {}});
6041 
6042   log::info("Stop the stream");
6043 
6044   EXPECT_CALL(mock_callbacks_,
6045               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
6046 
6047   // Stop the stream
6048   LeAudioGroupStateMachine::Get()->StopStream(group);
6049 
6050   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
6051   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6052   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
6053 
6054   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6055                                               _, GATT_WRITE_NO_RSP, _, _))
6056           .Times(0);
6057 
6058   log::info("Inject Enabling Notification, don't create CIS");
6059 
6060   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
6061   ON_CALL(*mock_iso_manager_, EstablishCis).WillByDefault(Return());
6062 
6063   InjectEnablingStateFroActiveAses(group, lastDevice);
6064   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
6065 
6066   // Check if group is still in Streaming state - it will change when Release
6067   // notification will arrive.
6068   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6069   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
6070 
6071   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6072 
6073   log::info("Inject Release for a group");
6074 
6075   EXPECT_CALL(mock_callbacks_,
6076               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
6077 
6078   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
6079   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
6080   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
6081 
6082   InjectReleaseAndIdleStateForAGroup(group);
6083   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
6084   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6085 
6086   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
6087   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
6088 }
6089 
TEST_F(StateMachineTest,testReleaseStreamWithLateAttachToStream_BeforeStreamingState)6090 TEST_F(StateMachineTest, testReleaseStreamWithLateAttachToStream_BeforeStreamingState) {
6091   const auto context_type = kContextTypeMedia;
6092   const auto leaudio_group_id = 6;
6093   const auto num_devices = 2;
6094 
6095   /* Scenario
6096    * 1. Start streaming
6097    * 2. Stop stream on one device
6098    * 3. Reconnect
6099    * 4. Trigger attach the stream
6100    * 6. StopStream while getting to Streaming state on attaching device
6101    * 7. Check that Attaching device will also go to IDLE
6102    */
6103 
6104   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
6105 
6106   // Prepare multiple fake connected devices in a group
6107   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
6108   ASSERT_EQ(group->Size(), num_devices);
6109 
6110   PrepareConfigureCodecHandler(group, 0, true);
6111   PrepareConfigureQosHandler(group);
6112   PrepareEnableHandler(group);
6113   PrepareDisableHandler(group);
6114 
6115   auto* leAudioDevice = group->GetFirstDevice();
6116   LeAudioDevice* firstDevice = leAudioDevice;
6117   LeAudioDevice* lastDevice;
6118 
6119   auto expected_devices_written = 0;
6120   while (leAudioDevice) {
6121     /* Three Writes:
6122      * 1: Codec Config
6123      * 2: Codec QoS
6124      * 3: Enabling
6125      */
6126     lastDevice = leAudioDevice;
6127     EXPECT_CALL(gatt_queue,
6128                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
6129                                     GATT_WRITE_NO_RSP, _, _))
6130             .Times(3);
6131     expected_devices_written++;
6132     leAudioDevice = group->GetNextDevice(leAudioDevice);
6133   }
6134   ASSERT_EQ(expected_devices_written, num_devices);
6135 
6136   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6137   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6138   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
6139 
6140   InjectInitialIdleNotification(group);
6141 
6142   // Start the configuration and stream Media content
6143   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6144                                                {.sink = types::AudioContexts(context_type),
6145                                                 .source = types::AudioContexts(context_type)});
6146 
6147   // Check if group has transitioned to a proper state
6148   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6149   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6150 
6151   log::info("Stream is started for group {}, disconnect {}", group->group_id_,
6152             lastDevice->address_);
6153 
6154   // Inject CIS and ACL disconnection of first device
6155   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
6156   InjectAclDisconnected(group, lastDevice);
6157 
6158   // Check if group keeps streaming
6159   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6160 
6161   /* Set device is getting ready for the connection */
6162   lastDevice->conn_id_ = 3;
6163   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
6164 
6165   // Make sure ASE with disconnected CIS are not left in STREAMING
6166   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
6167                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6168             nullptr);
6169   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
6170                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6171             nullptr);
6172 
6173   log::info("Set device {} to CONNECTED state", lastDevice->address_);
6174   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6175 
6176   /*
6177    * 1. Codec Configured for attaching device
6178    * 2. QoS Configured State for attaching device
6179    * 3. Enable for attaching device
6180    * 3. Release for both
6181    */
6182   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6183                                               _, GATT_WRITE_NO_RSP, _, _))
6184           .Times(4);
6185   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
6186                                               _, GATT_WRITE_NO_RSP, _, _))
6187           .Times(1);
6188 
6189   log::info("Block Streaming Notification");
6190 
6191   PrepareEnableHandler(group, 0, true, false);
6192 
6193   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6194   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
6195 
6196   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
6197                                                   {.sink = {media_ccid}, .source = {}});
6198 
6199   log::info("Stop the stream");
6200 
6201   EXPECT_CALL(mock_callbacks_,
6202               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
6203 
6204   // Stop the stream
6205   LeAudioGroupStateMachine::Get()->StopStream(group);
6206 
6207   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
6208   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6209   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
6210 
6211   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6212                                               _, GATT_WRITE_NO_RSP, _, _))
6213           .Times(0);
6214 
6215   log::info("Inject Streaming Notification");
6216 
6217   InjectStreamingStateFroActiveAses(group, lastDevice);
6218   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
6219   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6220 
6221   // Check if group is still in Streaming state - it will change when Release
6222   // notification will arrive.
6223   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6224   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
6225 
6226   log::info("Inject Release for a group");
6227 
6228   EXPECT_CALL(mock_callbacks_,
6229               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
6230 
6231   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
6232   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
6233   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
6234 
6235   InjectReleaseAndIdleStateForAGroup(group);
6236   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
6237   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6238 
6239   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
6240   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
6241 }
6242 
TEST_F(StateMachineTest,testAutonomousConfiguredAndAttachToStream)6243 TEST_F(StateMachineTest, testAutonomousConfiguredAndAttachToStream) {
6244   const auto context_type = kContextTypeMedia;
6245   const auto leaudio_group_id = 6;
6246   const auto num_devices = 2;
6247 
6248   /* Scenario
6249    * 1. Start streaming
6250    * 2. Stop stream on one device
6251    * 3. Reconnect
6252    * 4. Autonomous Configured state
6253    * 5. Make sure QoS Configure is not send out
6254    * 6. Trigger attach the stream
6255    * 7. Make sure stream is up
6256    */
6257 
6258   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
6259 
6260   // Prepare multiple fake connected devices in a group
6261   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
6262   ASSERT_EQ(group->Size(), num_devices);
6263 
6264   PrepareConfigureCodecHandler(group, 0, true);
6265   PrepareConfigureQosHandler(group);
6266   PrepareEnableHandler(group);
6267   PrepareDisableHandler(group);
6268   PrepareReleaseHandler(group);
6269 
6270   auto* leAudioDevice = group->GetFirstDevice();
6271   LeAudioDevice* lastDevice;
6272   LeAudioDevice* fistDevice = leAudioDevice;
6273 
6274   auto expected_devices_written = 0;
6275   while (leAudioDevice) {
6276     /* Three Writes:
6277      * 1: Codec Config
6278      * 2: Codec QoS
6279      * 3: Enabling
6280      */
6281     lastDevice = leAudioDevice;
6282     EXPECT_CALL(gatt_queue,
6283                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
6284                                     GATT_WRITE_NO_RSP, _, _))
6285             .Times(AtLeast(3));
6286     expected_devices_written++;
6287     leAudioDevice = group->GetNextDevice(leAudioDevice);
6288   }
6289   ASSERT_EQ(expected_devices_written, num_devices);
6290 
6291   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6292   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6293   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
6294 
6295   InjectInitialIdleNotification(group);
6296 
6297   // Start the configuration and stream Media content
6298   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6299                                                {.sink = types::AudioContexts(context_type),
6300                                                 .source = types::AudioContexts(context_type)});
6301 
6302   // Check if group has transitioned to a proper state
6303   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6304   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6305 
6306   // Inject CIS and ACL disconnection of first device
6307   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
6308   InjectAclDisconnected(group, lastDevice);
6309 
6310   // Check if group keeps streaming
6311   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6312 
6313   /* Set device is getting ready for the connection */
6314   lastDevice->conn_id_ = 3;
6315   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED_AUTOCONNECT_GETTING_READY);
6316 
6317   // Make sure ASE with disconnected CIS are not left in STREAMING
6318   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
6319                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6320             nullptr);
6321   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
6322                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6323             nullptr);
6324 
6325   // Symulate remote autonomous CONFIGURE state
6326   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6327                                               _, GATT_WRITE_NO_RSP, _, _))
6328           .Times(0);
6329 
6330   int num_of_notifications = 0;
6331   for (auto& ase : lastDevice->ases_) {
6332     if (ase.id == bluetooth::le_audio::types::ase::kAseIdInvalid) {
6333       continue;
6334     }
6335     log::error("ID : {},  status {}", ase.id, bluetooth::common::ToString(ase.state));
6336     num_of_notifications++;
6337     InjectAseStateNotification(&ase, lastDevice, group, ascs::kAseStateCodecConfigured,
6338                                &cached_codec_configuration_map_[ase.id]);
6339     break;
6340   }
6341   ASSERT_EQ(num_of_notifications, 1);
6342 
6343   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
6344   // Now device is connected. Attach it to the stream
6345 
6346   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6347 
6348   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6349                                               _, GATT_WRITE_NO_RSP, _, _))
6350           .Times(AtLeast(3));
6351 
6352   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6353   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
6354   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
6355                                                   {.sink = {media_ccid}, .source = {}});
6356 
6357   // Check if group keeps streaming
6358   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6359 
6360   // Verify that the joining device receives the right CCID list
6361   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
6362   bool parsedOk = false;
6363   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
6364                                                               parsedOk);
6365   ASSERT_TRUE(parsedOk);
6366 
6367   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
6368   ASSERT_TRUE(ccids.has_value());
6369   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
6370 
6371   /* Verify that ASE of first device are still good*/
6372   auto ase = fistDevice->GetFirstActiveAse();
6373   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
6374   ASSERT_NE(ase->qos_config.retrans_nb, 0);
6375 }
6376 
TEST_F(StateMachineTest,testAttachDeviceToTheStream_autonomusQoSConfiguredState)6377 TEST_F(StateMachineTest, testAttachDeviceToTheStream_autonomusQoSConfiguredState) {
6378   const auto context_type = kContextTypeMedia;
6379   const auto leaudio_group_id = 6;
6380   const auto num_devices = 2;
6381 
6382   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
6383 
6384   // Prepare multiple fake connected devices in a group
6385   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
6386   ASSERT_EQ(group->Size(), num_devices);
6387 
6388   PrepareConfigureCodecHandler(group);
6389   PrepareConfigureQosHandler(group);
6390   PrepareEnableHandler(group);
6391   PrepareDisableHandler(group);
6392   PrepareReleaseHandler(group);
6393 
6394   auto* leAudioDevice = group->GetFirstDevice();
6395   LeAudioDevice* lastDevice;
6396   LeAudioDevice* fistDevice = leAudioDevice;
6397 
6398   auto expected_devices_written = 0;
6399   while (leAudioDevice) {
6400     /* Three Writes:
6401      * 1: Codec Config
6402      * 2: Codec QoS
6403      * 3: Enabling
6404      */
6405     lastDevice = leAudioDevice;
6406     EXPECT_CALL(gatt_queue,
6407                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
6408                                     GATT_WRITE_NO_RSP, _, _))
6409             .Times(AtLeast(3));
6410     expected_devices_written++;
6411     leAudioDevice = group->GetNextDevice(leAudioDevice);
6412   }
6413   ASSERT_EQ(expected_devices_written, num_devices);
6414 
6415   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6416   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6417   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
6418 
6419   InjectInitialIdleNotification(group);
6420 
6421   // Start the configuration and stream Media content
6422   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6423                                                {.sink = types::AudioContexts(context_type),
6424                                                 .source = types::AudioContexts(context_type)},
6425                                                {.sink = std::vector<uint8_t>(1, media_ccid),
6426                                                 .source = std::vector<uint8_t>(1, media_ccid)});
6427 
6428   // Check if group has transitioned to a proper state
6429   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6430   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6431 
6432   // Inject CIS and ACL disconnection of first device
6433   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
6434 
6435   // Check if group keeps streaming
6436   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6437 
6438   // Make sure ASE with disconnected CIS are not left in STREAMING
6439   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
6440                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6441             nullptr);
6442   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
6443                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6444             nullptr);
6445 
6446   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6447                                               _, GATT_WRITE_NO_RSP, _, _))
6448           .Times(1);
6449 
6450   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6451   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
6452 
6453   for (auto& ase : lastDevice->ases_) {
6454     if (cached_remote_qos_configuration_for_ase_.count(&ase) > 0) {
6455       InjectAseStateNotification(&ase, lastDevice, group, ascs::kAseStateQoSConfigured,
6456                                  &(cached_remote_qos_configuration_for_ase_[&ase]));
6457     }
6458   }
6459 
6460   // Check if group keeps streaming
6461   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6462 
6463   // Verify that the joining device receives the right CCID list
6464   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
6465   bool parsedOk = false;
6466   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
6467                                                               parsedOk);
6468   ASSERT_TRUE(parsedOk);
6469 
6470   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
6471   ASSERT_TRUE(ccids.has_value());
6472   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
6473 
6474   /* Verify that ASE of first device are still good*/
6475   auto ase = fistDevice->GetFirstActiveAse();
6476   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
6477   ASSERT_NE(ase->qos_config.retrans_nb, 0);
6478 }
6479 
TEST_F(StateMachineTest,testAttachDeviceToTheStream_remoteDoesNotResponseOnCodecConfig)6480 TEST_F(StateMachineTest, testAttachDeviceToTheStream_remoteDoesNotResponseOnCodecConfig) {
6481   const auto context_type = kContextTypeMedia;
6482   const auto leaudio_group_id = 6;
6483   const auto num_devices = 2;
6484 
6485   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
6486 
6487   // Prepare multiple fake connected devices in a group
6488   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
6489   ASSERT_EQ(group->Size(), num_devices);
6490 
6491   PrepareConfigureCodecHandler(group);
6492   PrepareConfigureQosHandler(group);
6493   PrepareEnableHandler(group);
6494   PrepareDisableHandler(group);
6495   PrepareReleaseHandler(group);
6496 
6497   auto* leAudioDevice = group->GetFirstDevice();
6498   LeAudioDevice* lastDevice;
6499   LeAudioDevice* fistDevice = leAudioDevice;
6500 
6501   auto expected_devices_written = 0;
6502   while (leAudioDevice) {
6503     /* Three Writes:
6504      * 1: Codec Config
6505      * 2: Codec QoS
6506      * 3: Enabling
6507      */
6508     lastDevice = leAudioDevice;
6509     EXPECT_CALL(gatt_queue,
6510                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
6511                                     GATT_WRITE_NO_RSP, _, _))
6512             .Times(AtLeast(3));
6513     expected_devices_written++;
6514     leAudioDevice = group->GetNextDevice(leAudioDevice);
6515   }
6516   ASSERT_EQ(expected_devices_written, num_devices);
6517 
6518   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6519   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6520   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
6521 
6522   InjectInitialIdleNotification(group);
6523 
6524   // Start the configuration and stream Media content
6525   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6526                                                {.sink = types::AudioContexts(context_type),
6527                                                 .source = types::AudioContexts(context_type)},
6528                                                {.sink = std::vector<uint8_t>(1, media_ccid),
6529                                                 .source = std::vector<uint8_t>(1, media_ccid)});
6530 
6531   // Check if group has transitioned to a proper state
6532   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6533   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6534 
6535   log::info(" Inject ACL disconnection of last device {} ", lastDevice->address_);
6536   uint16_t conn_id = lastDevice->conn_id_;
6537 
6538   InjectAclDisconnected(group, lastDevice);
6539 
6540   log::info("Check if group keeps streaming");
6541 
6542   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6543 
6544   log::info("Make sure ASE with disconnected CIS are not left in STREAMING");
6545 
6546   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
6547                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6548             nullptr);
6549   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
6550                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
6551             nullptr);
6552 
6553   log::info(
6554           "Now, group is not yet in the streaming state. Let's simulated the other device got "
6555           "connected");
6556 
6557   lastDevice->conn_id_ = conn_id;
6558   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6559 
6560   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6561                                               _, GATT_WRITE_NO_RSP, _, _))
6562           .Times(1);
6563 
6564   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
6565   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
6566 
6567   log::info(" Block configured state");
6568   PrepareConfigureCodecHandler(group, 0, false, false);
6569 
6570   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
6571                                                   {.sink = {media_ccid}, .source = {}});
6572 
6573   // Check if group keeps streaming
6574   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6575 
6576   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6577   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
6578 
6579   log::info("Inject ACL disconnect and reconnect again");
6580   InjectAclDisconnected(group, lastDevice);
6581   lastDevice->conn_id_ = conn_id;
6582   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6583 
6584   log::info("allow codec configured state");
6585   PrepareConfigureCodecHandler(group);
6586 
6587   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
6588                                               _, GATT_WRITE_NO_RSP, _, _))
6589           .Times(3);
6590 
6591   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6592   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
6593 
6594   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
6595                                                   {.sink = {media_ccid}, .source = {}});
6596 
6597   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6598   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
6599 
6600   // Verify that the joining device receives the right CCID list
6601   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
6602   bool parsedOk = false;
6603   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
6604                                                               parsedOk);
6605   ASSERT_TRUE(parsedOk);
6606 
6607   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
6608   ASSERT_TRUE(ccids.has_value());
6609   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
6610 
6611   /* Verify that ASE of first device are still good*/
6612   auto ase = fistDevice->GetFirstActiveAse();
6613   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
6614   ASSERT_NE(ase->qos_config.retrans_nb, 0);
6615 }
6616 
TEST_F(StateMachineTest,testAttachDeviceToTheStreamDoNotAttach)6617 TEST_F(StateMachineTest, testAttachDeviceToTheStreamDoNotAttach) {
6618   const auto context_type = kContextTypeMedia;
6619   const auto leaudio_group_id = 6;
6620   const auto num_devices = 2;
6621 
6622   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
6623 
6624   // Prepare multiple fake connected devices in a group
6625   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
6626   ASSERT_EQ(group->Size(), num_devices);
6627 
6628   PrepareConfigureCodecHandler(group);
6629   PrepareConfigureQosHandler(group);
6630   PrepareEnableHandler(group);
6631 
6632   auto* leAudioDevice = group->GetFirstDevice();
6633   LeAudioDevice* lastDevice;
6634 
6635   while (leAudioDevice) {
6636     lastDevice = leAudioDevice;
6637     leAudioDevice = group->GetNextDevice(leAudioDevice);
6638   }
6639 
6640   InjectInitialIdleNotification(group);
6641 
6642   // Inject CIS and ACL disconnection of first device
6643   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
6644   InjectAclDisconnected(group, lastDevice);
6645 
6646   // Start the configuration and stream Media content
6647   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6648   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6649   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
6650   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6651                                                {.sink = types::AudioContexts(context_type),
6652                                                 .source = types::AudioContexts(context_type)});
6653 
6654   // Check if group has transitioned to a proper state
6655   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6656   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6657 
6658   // Check if group keeps streaming
6659   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6660 
6661   lastDevice->conn_id_ = 3;
6662   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6663 
6664   EXPECT_CALL(mock_callbacks_,
6665               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
6666   LeAudioGroupStateMachine::Get()->StopStream(group);
6667   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
6668 
6669   ASSERT_FALSE(LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
6670                                                                {.sink = {}, .source = {}}));
6671 }
6672 
TEST_F(StateMachineTest,testReconfigureAfterLateDeviceAttached)6673 TEST_F(StateMachineTest, testReconfigureAfterLateDeviceAttached) {
6674   const auto context_type = kContextTypeMedia;
6675   const auto leaudio_group_id = 6;
6676   const auto num_devices = 2;
6677 
6678   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
6679 
6680   // Prepare multiple fake connected devices in a group
6681   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
6682   ASSERT_EQ(group->Size(), num_devices);
6683 
6684   PrepareConfigureCodecHandler(group, 0, true);
6685   PrepareConfigureQosHandler(group);
6686   PrepareEnableHandler(group);
6687   PrepareDisableHandler(group);
6688   PrepareReleaseHandler(group);
6689 
6690   auto* leAudioDevice = group->GetFirstDevice();
6691   LeAudioDevice* lastDevice;
6692   LeAudioDevice* fistDevice = leAudioDevice;
6693 
6694   while (leAudioDevice) {
6695     lastDevice = leAudioDevice;
6696     leAudioDevice = group->GetNextDevice(leAudioDevice);
6697   }
6698 
6699   InjectInitialIdleNotification(group);
6700 
6701   // Inject CIS and ACL disconnection of first device
6702   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
6703   InjectAclDisconnected(group, lastDevice);
6704 
6705   /* First device connected. Configure it to stream media */
6706 
6707   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6708   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6709   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
6710 
6711   types::BidirectionalPair<std::vector<uint8_t>> ccids_list = {.sink = {media_ccid},
6712                                                                .source = {media_ccid}};
6713 
6714   // Start the configuration and stream Media content
6715   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6716                                                {.sink = types::AudioContexts(context_type),
6717                                                 .source = types::AudioContexts(context_type)},
6718                                                ccids_list);
6719 
6720   // Check if group has transitioned to a proper state
6721   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6722   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6723 
6724   /* Stop  the stream and let first device to stay in configured state (caching
6725    * is on)*/
6726   LeAudioGroupStateMachine::Get()->StopStream(group);
6727   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
6728 
6729   /* Verify state in the configured state */
6730   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
6731 
6732   /* Now when stream is stopped, connect second device. */
6733   lastDevice->conn_id_ = 3;
6734   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6735 
6736   group->UpdateAudioContextAvailability();
6737   group->UpdateAudioSetConfigurationCache(context_type);
6738 
6739   /* Start stream, make sure 2 devices are started. */
6740 
6741   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6742   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6743   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
6744 
6745   // Start the configuration and stream Media content
6746   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6747                                                {.sink = types::AudioContexts(context_type),
6748                                                 .source = types::AudioContexts(context_type)},
6749                                                ccids_list);
6750 
6751   // Check if group keeps streaming
6752   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6753 
6754   // Verify that both devicse receives the right CCID list and both are
6755   // streaming
6756   auto ase = lastDevice->GetFirstActiveAse();
6757 
6758   // FIXME: No ASE was activated - that's bad
6759   ASSERT_NE(nullptr, ase);
6760   auto lastMeta = ase->metadata;
6761   bool parsedOk = false;
6762   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
6763                                                               parsedOk);
6764   ASSERT_TRUE(parsedOk);
6765 
6766   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
6767   ASSERT_TRUE(ccids.has_value());
6768   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
6769 
6770   /* Verify that ASE of first device are still good*/
6771   ase = fistDevice->GetFirstActiveAse();
6772   ASSERT_NE(nullptr, ase);
6773   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
6774   ASSERT_NE(ase->qos_config.retrans_nb, 0);
6775 }
6776 
TEST_F(StateMachineTest,testReconfigureAfterLateDeviceAttachedConversationalSwb)6777 TEST_F(StateMachineTest, testReconfigureAfterLateDeviceAttachedConversationalSwb) {
6778   const auto context_type = kContextTypeConversational;
6779   const auto leaudio_group_id = 6;
6780   const auto num_devices = 2;
6781 
6782   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
6783 
6784   // Prepare multiple fake connected devices in a group
6785   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
6786   ASSERT_EQ(group->Size(), num_devices);
6787 
6788   PrepareConfigureCodecHandler(group, 0, true);
6789   PrepareConfigureQosHandler(group);
6790   PrepareEnableHandler(group);
6791   PrepareReceiverStartReadyHandler(group);
6792   PrepareDisableHandler(group);
6793   PrepareReleaseHandler(group);
6794 
6795   auto* leAudioDevice = group->GetFirstDevice();
6796   LeAudioDevice* lastDevice;
6797   LeAudioDevice* fistDevice = leAudioDevice;
6798 
6799   while (leAudioDevice) {
6800     lastDevice = leAudioDevice;
6801     leAudioDevice = group->GetNextDevice(leAudioDevice);
6802   }
6803 
6804   InjectInitialIdleNotification(group);
6805 
6806   // Inject CIS and ACL disconnection of first device
6807   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
6808   InjectAclDisconnected(group, lastDevice);
6809 
6810   /* First device connected. Configure it to stream media */
6811   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6812   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6813   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
6814 
6815   types::BidirectionalPair<std::vector<uint8_t>> ccids_list = {.sink = {media_ccid},
6816                                                                .source = {media_ccid}};
6817 
6818   // Start the configuration and stream Media content
6819   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6820                                                {.sink = types::AudioContexts(context_type),
6821                                                 .source = types::AudioContexts(context_type)},
6822                                                ccids_list);
6823 
6824   auto current_config = group->GetCachedConfiguration(context_type);
6825   ASSERT_NE(nullptr, current_config.get());
6826   // With a single device there will be no dual bidir SWB but a single bidir SWB
6827   ASSERT_TRUE(AudioSetConfigurationProvider::Get()->CheckConfigurationIsBiDirSwb(
6828           *current_config.get()));
6829   ASSERT_FALSE(AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb(
6830           *current_config.get()));
6831 
6832   // Check if group has transitioned to a proper state
6833   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6834   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6835 
6836   /* Stop  the stream and let first device to stay in configured state (caching
6837    * is on)*/
6838   LeAudioGroupStateMachine::Get()->StopStream(group);
6839   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
6840 
6841   /* Verify state in the configured state */
6842   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
6843 
6844   /* Now when stream is stopped, connect second device. */
6845   lastDevice->conn_id_ = 3;
6846   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6847 
6848   group->UpdateAudioContextAvailability();
6849   group->UpdateAudioSetConfigurationCache(context_type);
6850 
6851   /* Start stream, make sure 2 devices are started. */
6852   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6853   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6854   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
6855 
6856   // Start the configuration and stream Media content
6857   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6858                                                {.sink = types::AudioContexts(context_type),
6859                                                 .source = types::AudioContexts(context_type)},
6860                                                ccids_list);
6861 
6862   // Check if group keeps streaming
6863   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6864 
6865   // Verify that both devicse receives the right CCID list and both are
6866   // streaming
6867   auto ase = lastDevice->GetFirstActiveAse();
6868 
6869   // No ASE was activated - that's bad
6870   ASSERT_NE(nullptr, ase);
6871   auto lastMeta = ase->metadata;
6872   bool parsedOk = false;
6873   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
6874                                                               parsedOk);
6875   ASSERT_TRUE(parsedOk);
6876 
6877   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
6878   ASSERT_TRUE(ccids.has_value());
6879   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
6880 
6881   /* Verify that ASE of first device are still good*/
6882   ase = fistDevice->GetFirstActiveAse();
6883   ASSERT_NE(nullptr, ase);
6884   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
6885   ASSERT_NE(ase->qos_config.retrans_nb, 0);
6886 
6887   // With both devices we should get the dual bidir SWB configuration
6888   current_config = group->GetCachedConfiguration(context_type);
6889   ASSERT_NE(nullptr, current_config.get());
6890   ASSERT_TRUE(AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb(
6891           *current_config.get()));
6892 }
6893 
TEST_F(StateMachineTestNoSwb,testReconfigureAfterLateDeviceAttachedConversationalNoSwb)6894 TEST_F(StateMachineTestNoSwb, testReconfigureAfterLateDeviceAttachedConversationalNoSwb) {
6895   const auto context_type = kContextTypeConversational;
6896   const auto leaudio_group_id = 6;
6897   const auto num_devices = 2;
6898 
6899   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
6900 
6901   // Prepare multiple fake connected devices in a group
6902   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
6903   ASSERT_EQ(group->Size(), num_devices);
6904 
6905   PrepareConfigureCodecHandler(group, 0, true);
6906   PrepareConfigureQosHandler(group);
6907   PrepareEnableHandler(group);
6908   PrepareReceiverStartReadyHandler(group);
6909   PrepareDisableHandler(group);
6910   PrepareReleaseHandler(group);
6911 
6912   auto* leAudioDevice = group->GetFirstDevice();
6913   LeAudioDevice* lastDevice;
6914   LeAudioDevice* fistDevice = leAudioDevice;
6915 
6916   while (leAudioDevice) {
6917     lastDevice = leAudioDevice;
6918     leAudioDevice = group->GetNextDevice(leAudioDevice);
6919   }
6920 
6921   InjectInitialIdleNotification(group);
6922 
6923   // Inject CIS and ACL disconnection of first device
6924   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
6925   InjectAclDisconnected(group, lastDevice);
6926 
6927   /* First device connected. Configure it to stream media */
6928   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6929   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6930   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
6931 
6932   types::BidirectionalPair<std::vector<uint8_t>> ccids_list = {.sink = {media_ccid},
6933                                                                .source = {media_ccid}};
6934 
6935   // Start the configuration and stream Media content
6936   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6937                                                {.sink = types::AudioContexts(context_type),
6938                                                 .source = types::AudioContexts(context_type)},
6939                                                ccids_list);
6940 
6941   auto current_config = group->GetCachedConfiguration(context_type);
6942   ASSERT_NE(nullptr, current_config.get());
6943   // With a single device there shall be no bidir SWB, as we expect the 2nd
6944   // device to join the stream seamlessly while dual bidir SWB is disabled.
6945   ASSERT_FALSE(AudioSetConfigurationProvider::Get()->CheckConfigurationIsBiDirSwb(
6946           *current_config.get()));
6947   ASSERT_FALSE(AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb(
6948           *current_config.get()));
6949 
6950   // Check if group has transitioned to a proper state
6951   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6952   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
6953 
6954   /* Stop  the stream and let first device to stay in configured state (caching
6955    * is on)*/
6956   LeAudioGroupStateMachine::Get()->StopStream(group);
6957   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
6958 
6959   /* Verify state in the configured state */
6960   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
6961 
6962   /* Now when stream is stopped, connect second device. */
6963   lastDevice->conn_id_ = 3;
6964   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
6965 
6966   group->UpdateAudioContextAvailability();
6967   group->UpdateAudioSetConfigurationCache(context_type);
6968 
6969   /* Start stream, make sure 2 devices are started. */
6970   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
6971   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
6972   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
6973 
6974   // Start the configuration and stream Media content
6975   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
6976                                                {.sink = types::AudioContexts(context_type),
6977                                                 .source = types::AudioContexts(context_type)},
6978                                                ccids_list);
6979 
6980   // Check if group keeps streaming
6981   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
6982 
6983   // Verify that both devicse receives the right CCID list and both are
6984   // streaming
6985   auto ase = lastDevice->GetFirstActiveAse();
6986 
6987   // No ASE was activated - that's bad
6988   ASSERT_NE(nullptr, ase);
6989   auto lastMeta = ase->metadata;
6990   bool parsedOk = false;
6991   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
6992                                                               parsedOk);
6993   ASSERT_TRUE(parsedOk);
6994 
6995   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
6996   ASSERT_TRUE(ccids.has_value());
6997   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
6998 
6999   /* Verify that ASE of first device are still good*/
7000   ase = fistDevice->GetFirstActiveAse();
7001   ASSERT_NE(nullptr, ase);
7002   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
7003   ASSERT_NE(ase->qos_config.retrans_nb, 0);
7004 
7005   // With both devices we still should not get the dual bidir SWB configuration
7006   // as it is currently disabled.
7007   current_config = group->GetCachedConfiguration(context_type);
7008   ASSERT_NE(nullptr, current_config.get());
7009   ASSERT_FALSE(AudioSetConfigurationProvider::Get()->CheckConfigurationIsDualBiDirSwb(
7010           *current_config.get()));
7011 }
7012 
TEST_F(StateMachineTest,testStreamToGettingReadyDevice)7013 TEST_F(StateMachineTest, testStreamToGettingReadyDevice) {
7014   const auto context_type = kContextTypeLive;
7015   const auto leaudio_group_id = 666;
7016   const auto num_devices = 2;
7017 
7018   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
7019 
7020   // Prepare multiple fake connected devices in a group
7021   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7022 
7023   // Simulate the 2nd device still getting ready
7024   auto* firstDevice = group->GetFirstDevice();
7025   auto* secondDevice = group->GetNextDevice(firstDevice);
7026   secondDevice->SetConnectionState(DeviceConnectState::CONNECTED_BY_USER_GETTING_READY);
7027 
7028   group->UpdateAudioContextAvailability();
7029   group->UpdateAudioSetConfigurationCache(context_type);
7030 
7031   ASSERT_EQ(group->Size(), num_devices);
7032   ASSERT_EQ(1, group->NumOfConnected());
7033 
7034   PrepareConfigureCodecHandler(group);
7035   PrepareConfigureQosHandler(group);
7036   PrepareEnableHandler(group);
7037   PrepareReceiverStartReadyHandler(group);
7038   PrepareDisableHandler(group);
7039   PrepareReleaseHandler(group);
7040 
7041   /* Three Writes:
7042    * 1: Codec Config
7043    * 2: Codec QoS
7044    * 3: Enabling
7045    */
7046   // Expect actions only on the already prepared device
7047   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
7048                                               _, GATT_WRITE_NO_RSP, _, _))
7049           .Times(AtLeast(3));
7050 
7051   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
7052   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
7053   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
7054 
7055   InjectInitialIdleNotification(group);
7056 
7057   // Start the configuration and the stream
7058   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7059                                                {.sink = types::AudioContexts(context_type),
7060                                                 .source = types::AudioContexts(context_type)});
7061 
7062   // Check if group has transitioned to a proper state with one device still
7063   // being in the `CONNECTED_BY_USER_GETTING_READY` state
7064   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
7065   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
7066 }
7067 
TEST_F(StateMachineTest,testAttachDeviceToTheConversationalStream)7068 TEST_F(StateMachineTest, testAttachDeviceToTheConversationalStream) {
7069   const auto context_type = kContextTypeConversational;
7070   const auto leaudio_group_id = 6;
7071   const auto num_devices = 2;
7072 
7073   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
7074 
7075   // Prepare multiple fake connected devices in a group
7076   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7077   ASSERT_EQ(group->Size(), num_devices);
7078 
7079   PrepareConfigureCodecHandler(group);
7080   PrepareConfigureQosHandler(group);
7081   PrepareEnableHandler(group);
7082   PrepareReceiverStartReadyHandler(group);
7083   PrepareDisableHandler(group);
7084   PrepareReleaseHandler(group);
7085 
7086   auto* leAudioDevice = group->GetFirstDevice();
7087   LeAudioDevice* lastDevice;
7088   LeAudioDevice* firstDevice = leAudioDevice;
7089 
7090   auto expected_devices_written = 0;
7091   while (leAudioDevice) {
7092     /* Three Writes:
7093      * 1: Codec Config
7094      * 2: Codec QoS
7095      * 3: Enabling
7096      */
7097     lastDevice = leAudioDevice;
7098     EXPECT_CALL(gatt_queue,
7099                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7100                                     GATT_WRITE_NO_RSP, _, _))
7101             .Times(AtLeast(3));
7102     expected_devices_written++;
7103     leAudioDevice = group->GetNextDevice(leAudioDevice);
7104   }
7105   ASSERT_EQ(expected_devices_written, num_devices);
7106   ASSERT_NE(nullptr, firstDevice);
7107   ASSERT_NE(nullptr, lastDevice);
7108 
7109   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
7110   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
7111 
7112   EXPECT_CALL(*mock_iso_manager_,
7113               SetupIsoDataPath(
7114                       _, dataPathDirIsEq(bluetooth::hci::iso_manager::kIsoDataPathDirectionIn)))
7115           .Times(2);
7116 
7117   // Make sure the Out data path is set before we declare that we are ready
7118   {
7119     ::testing::InSequence seq;
7120     EXPECT_CALL(*mock_iso_manager_,
7121                 SetupIsoDataPath(
7122                         UNIQUE_CIS_CONN_HANDLE(leaudio_group_id, 0),
7123                         dataPathDirIsEq(bluetooth::hci::iso_manager::kIsoDataPathDirectionOut)))
7124             .Times(1);
7125     EXPECT_CALL(ase_ctp_handler, AseCtpReceiverStartReadyHandler(firstDevice, _, _, _)).Times(1);
7126   }
7127   {
7128     ::testing::InSequence seq;
7129     EXPECT_CALL(*mock_iso_manager_,
7130                 SetupIsoDataPath(
7131                         UNIQUE_CIS_CONN_HANDLE(leaudio_group_id, 1),
7132                         dataPathDirIsEq(bluetooth::hci::iso_manager::kIsoDataPathDirectionOut)))
7133             .Times(1);
7134     EXPECT_CALL(ase_ctp_handler, AseCtpReceiverStartReadyHandler(lastDevice, _, _, _)).Times(1);
7135   }
7136 
7137   InjectInitialIdleNotification(group);
7138 
7139   // Start the configuration and stream Conversational content
7140   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7141                                                {.sink = types::AudioContexts(context_type),
7142                                                 .source = types::AudioContexts(context_type)});
7143 
7144   // Check if group has transitioned to a proper state
7145   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
7146   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
7147 
7148   // Verify data path removal on the second bidirectional CIS
7149   EXPECT_CALL(
7150           *mock_iso_manager_,
7151           RemoveIsoDataPath(UNIQUE_CIS_CONN_HANDLE(leaudio_group_id, 1),
7152                             bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput |
7153                                     bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput))
7154           .Times(1);
7155 
7156   // Inject CIS and ACL disconnection of first device
7157   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
7158   InjectAclDisconnected(group, lastDevice);
7159   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
7160 
7161   // Check if group keeps streaming
7162   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
7163 
7164   lastDevice->conn_id_ = 3;
7165   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
7166 
7167   // Make sure ASE with disconnected CIS are not left in STREAMING
7168   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
7169                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
7170             nullptr);
7171   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
7172                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
7173             nullptr);
7174 
7175   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
7176                                               _, GATT_WRITE_NO_RSP, _, _))
7177           .Times(AtLeast(3));
7178 
7179   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
7180   EXPECT_CALL(*mock_iso_manager_,
7181               SetupIsoDataPath(
7182                       _, dataPathDirIsEq(bluetooth::hci::iso_manager::kIsoDataPathDirectionIn)))
7183           .Times(1);
7184   // Make sure the Out data path is set before we declare that we are ready
7185   {
7186     ::testing::InSequence seq;
7187     EXPECT_CALL(*mock_iso_manager_,
7188                 SetupIsoDataPath(
7189                         UNIQUE_CIS_CONN_HANDLE(leaudio_group_id, 1),
7190                         dataPathDirIsEq(bluetooth::hci::iso_manager::kIsoDataPathDirectionOut)))
7191             .Times(1);
7192     EXPECT_CALL(ase_ctp_handler, AseCtpReceiverStartReadyHandler(lastDevice, _, _, _)).Times(1);
7193   }
7194 
7195   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
7196                                                   {.sink = {call_ccid}, .source = {call_ccid}});
7197 
7198   // Check if group keeps streaming
7199   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
7200 
7201   // Verify that the joining device receives the right CCID list
7202   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
7203   bool parsedOk = false;
7204   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
7205                                                               parsedOk);
7206   ASSERT_TRUE(parsedOk);
7207 
7208   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
7209   ASSERT_TRUE(ccids.has_value());
7210   ASSERT_NE(std::find(ccids->begin(), ccids->end(), call_ccid), ccids->end());
7211 
7212   /* Verify that ASE of first device are still good*/
7213   auto ase = firstDevice->GetFirstActiveAse();
7214   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
7215   ASSERT_NE(ase->qos_config.retrans_nb, 0);
7216 
7217   // Make sure ASEs with reconnected CIS are in STREAMING state
7218   ASSERT_TRUE(lastDevice->HaveAllActiveAsesSameState(
7219           types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING));
7220 }
7221 
TEST_F(StateMachineTest,ReconfigureGroupWhenSecondDeviceConnectsAndFirstIsInQoSConfiguredState)7222 TEST_F(StateMachineTest, ReconfigureGroupWhenSecondDeviceConnectsAndFirstIsInQoSConfiguredState) {
7223   const auto context_type = kContextTypeMedia;
7224   const auto leaudio_group_id = 6;
7225   const auto num_devices = 2;
7226 
7227   /**
7228    * Scenario
7229    * 1. One set member is connected and configured to QoS
7230    * 2. Second set member connects and group is configured after that
7231    * 3. Expect Start stream and expect to get Codec Config and later QoS Config on both devices.
7232    *
7233    */
7234   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7235 
7236   // Prepare multiple fake connected devices in a group
7237   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7238   ASSERT_EQ(group->Size(), num_devices);
7239 
7240   PrepareConfigureCodecHandler(group, 0, true);
7241   PrepareConfigureQosHandler(group);
7242 
7243   InjectInitialIdleNotification(group);
7244 
7245   auto* leAudioDevice = group->GetFirstDevice();
7246   LeAudioDevice* firstDevice = leAudioDevice;
7247   LeAudioDevice* secondDevice = group->GetNextDevice(leAudioDevice);
7248   uint16_t stored_conn_id = secondDevice->conn_id_;
7249 
7250   log::info("Inject disconnect second device");
7251   InjectAclDisconnected(group, secondDevice);
7252 
7253   /* Three Writes:
7254    * 1. Codec configure
7255    * 2. Codec QoS
7256    * 3. Enable
7257    */
7258   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
7259                                               _, GATT_WRITE_NO_RSP, _, _))
7260           .Times(3);
7261 
7262   EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(1);
7263 
7264   // Start the configuration and stream Media content
7265   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7266                                                {.sink = types::AudioContexts(context_type),
7267                                                 .source = types::AudioContexts(context_type)},
7268                                                {.sink = {}, .source = {}});
7269 
7270   /* Check if group has transitioned to a proper state */
7271   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
7272 
7273   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
7274   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
7275 
7276   log::info("Inject connecting second device");
7277   InjectAclConnected(group, secondDevice, stored_conn_id);
7278 
7279   PrepareEnableHandler(group);
7280 
7281   EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(0);
7282   EXPECT_CALL(*mock_iso_manager_, RemoveCig).Times(0);
7283 
7284   EXPECT_CALL(mock_callbacks_,
7285               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7286 
7287   /* Three Writes:
7288    * 1. Codec configure
7289    * 2. Codec QoS
7290    * 3. Enable
7291    */
7292   EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
7293                                               _, GATT_WRITE_NO_RSP, _, _))
7294           .Times(3);
7295   EXPECT_CALL(gatt_queue,
7296               WriteCharacteristic(secondDevice->conn_id_, secondDevice->ctp_hdls_.val_hdl, _,
7297                                   GATT_WRITE_NO_RSP, _, _))
7298           .Times(3);
7299 
7300   // Start the configuration and stream Media content
7301   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7302                                                {.sink = types::AudioContexts(context_type),
7303                                                 .source = types::AudioContexts(context_type)},
7304                                                {.sink = {}, .source = {}});
7305 
7306   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7307   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
7308   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
7309 }
7310 
TEST_F(StateMachineTest,StartStreamAfterConfigureToQoS)7311 TEST_F(StateMachineTest, StartStreamAfterConfigureToQoS) {
7312   const auto context_type = kContextTypeMedia;
7313   const auto leaudio_group_id = 6;
7314   const auto num_devices = 2;
7315 
7316   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7317 
7318   // Prepare multiple fake connected devices in a group
7319   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7320   ASSERT_EQ(group->Size(), num_devices);
7321 
7322   PrepareConfigureCodecHandler(group, 0, true);
7323   PrepareConfigureQosHandler(group);
7324   PrepareEnableHandler(group);
7325   PrepareDisableHandler(group);
7326   PrepareReleaseHandler(group);
7327 
7328   InjectInitialIdleNotification(group);
7329 
7330   auto* leAudioDevice = group->GetFirstDevice();
7331   auto expected_devices_written = 0;
7332   while (leAudioDevice) {
7333     /* Three Writes:
7334      * 1. Codec configure
7335      * 2: Codec QoS
7336      * 3: Enabling
7337      */
7338     EXPECT_CALL(gatt_queue,
7339                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7340                                     GATT_WRITE_NO_RSP, _, _))
7341             .Times(3);
7342     expected_devices_written++;
7343     leAudioDevice = group->GetNextDevice(leAudioDevice);
7344   }
7345   ASSERT_EQ(expected_devices_written, num_devices);
7346 
7347   // Validate GroupStreamStatus
7348   EXPECT_CALL(mock_callbacks_,
7349               StatusReportCb(leaudio_group_id,
7350                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER));
7351 
7352   // Start the configuration and stream Media content
7353   LeAudioGroupStateMachine::Get()->ConfigureStream(group, context_type,
7354                                                    {.sink = types::AudioContexts(context_type),
7355                                                     .source = types::AudioContexts(context_type)},
7356                                                    {.sink = {}, .source = {}}, true);
7357 
7358   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7359   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7360 
7361   // Validate GroupStreamStatus
7362   EXPECT_CALL(mock_callbacks_,
7363               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7364 
7365   // Start the configuration and stream Media content
7366   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7367                                                {.sink = types::AudioContexts(context_type),
7368                                                 .source = types::AudioContexts(context_type)});
7369 
7370   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7371 }
7372 
TEST_F(StateMachineTest,StartStreamAfterConfigureToQoS_ConfigurationCaching)7373 TEST_F(StateMachineTest, StartStreamAfterConfigureToQoS_ConfigurationCaching) {
7374   const auto context_type = kContextTypeMedia;
7375   const auto leaudio_group_id = 6;
7376   const auto num_devices = 2;
7377 
7378   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7379 
7380   // Prepare multiple fake connected devices in a group
7381   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7382   ASSERT_EQ(group->Size(), num_devices);
7383 
7384   PrepareConfigureCodecHandler(group, 0, true);
7385   PrepareConfigureQosHandler(group);
7386   PrepareEnableHandler(group);
7387   PrepareDisableHandler(group);
7388   PrepareReleaseHandler(group);
7389 
7390   InjectInitialConfiguredNotification(group);
7391 
7392   auto* leAudioDevice = group->GetFirstDevice();
7393   auto expected_devices_written = 0;
7394   while (leAudioDevice) {
7395     /* Three Writes:
7396      * 1. Codec configure
7397      * 2: Codec QoS
7398      * 3: Enabling
7399      */
7400     EXPECT_CALL(gatt_queue,
7401                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7402                                     GATT_WRITE_NO_RSP, _, _))
7403             .Times(3);
7404     expected_devices_written++;
7405     leAudioDevice = group->GetNextDevice(leAudioDevice);
7406   }
7407   ASSERT_EQ(expected_devices_written, num_devices);
7408 
7409   // Validate GroupStreamStatus
7410   EXPECT_CALL(mock_callbacks_,
7411               StatusReportCb(leaudio_group_id,
7412                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER));
7413 
7414   // Start the configuration and stream Media content
7415   LeAudioGroupStateMachine::Get()->ConfigureStream(group, context_type,
7416                                                    {.sink = types::AudioContexts(context_type),
7417                                                     .source = types::AudioContexts(context_type)},
7418                                                    {.sink = {}, .source = {}}, true);
7419 
7420   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7421   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7422 
7423   // Validate GroupStreamStatus
7424   EXPECT_CALL(mock_callbacks_,
7425               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7426 
7427   // Start the configuration and stream Media content
7428   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7429                                                {.sink = types::AudioContexts(context_type),
7430                                                 .source = types::AudioContexts(context_type)});
7431 
7432   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7433 }
7434 
TEST_F(StateMachineTest,StopStreamAfterConfigureToQoS)7435 TEST_F(StateMachineTest, StopStreamAfterConfigureToQoS) {
7436   const auto context_type = kContextTypeMedia;
7437   const auto leaudio_group_id = 6;
7438   const auto num_devices = 2;
7439 
7440   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7441 
7442   // Prepare multiple fake connected devices in a group
7443   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7444   ASSERT_EQ(group->Size(), num_devices);
7445 
7446   PrepareConfigureCodecHandler(group, 0, true);
7447   PrepareConfigureQosHandler(group);
7448   PrepareEnableHandler(group);
7449   PrepareDisableHandler(group);
7450   PrepareReleaseHandler(group);
7451 
7452   InjectInitialIdleNotification(group);
7453 
7454   auto* leAudioDevice = group->GetFirstDevice();
7455   auto expected_devices_written = 0;
7456   while (leAudioDevice) {
7457     /* Three Writes:
7458      * 1. Codec configure
7459      * 2: Codec QoS
7460      * 3: Release
7461      */
7462     EXPECT_CALL(gatt_queue,
7463                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7464                                     GATT_WRITE_NO_RSP, _, _))
7465             .Times(3);
7466     expected_devices_written++;
7467     leAudioDevice = group->GetNextDevice(leAudioDevice);
7468   }
7469   ASSERT_EQ(expected_devices_written, num_devices);
7470 
7471   // Validate GroupStreamStatus
7472   EXPECT_CALL(mock_callbacks_,
7473               StatusReportCb(leaudio_group_id,
7474                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER));
7475 
7476   // Start the configuration and stream Media content
7477   group->SetPendingConfiguration();
7478   LeAudioGroupStateMachine::Get()->ConfigureStream(group, context_type,
7479                                                    {.sink = types::AudioContexts(context_type),
7480                                                     .source = types::AudioContexts(context_type)},
7481                                                    {.sink = {}, .source = {}}, true);
7482 
7483   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7484   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7485 
7486   group->ClearPendingConfiguration();
7487   // Validate GroupStreamStatus (since caching is on CONFIGURE_AUTONOMOUS will be the last state)
7488   EXPECT_CALL(mock_callbacks_,
7489               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
7490   EXPECT_CALL(mock_callbacks_,
7491               StatusReportCb(leaudio_group_id,
7492                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
7493 
7494   // Start the configuration and stream Media content
7495   LeAudioGroupStateMachine::Get()->StopStream(group);
7496 
7497   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7498 }
7499 
TEST_F(StateMachineTest,StartStreamAfterConfigure)7500 TEST_F(StateMachineTest, StartStreamAfterConfigure) {
7501   const auto context_type = kContextTypeMedia;
7502   const auto leaudio_group_id = 6;
7503   const auto num_devices = 2;
7504 
7505   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7506 
7507   // Prepare multiple fake connected devices in a group
7508   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7509   ASSERT_EQ(group->Size(), num_devices);
7510 
7511   PrepareConfigureCodecHandler(group, 0, true);
7512   PrepareConfigureQosHandler(group);
7513   PrepareEnableHandler(group);
7514   PrepareDisableHandler(group);
7515   PrepareReleaseHandler(group);
7516 
7517   InjectInitialIdleNotification(group);
7518 
7519   auto* leAudioDevice = group->GetFirstDevice();
7520   auto expected_devices_written = 0;
7521   while (leAudioDevice) {
7522     /* Three Writes:
7523      * 1. Codec configure
7524      * 2: Codec QoS
7525      * 3: Enabling
7526      */
7527     EXPECT_CALL(gatt_queue,
7528                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7529                                     GATT_WRITE_NO_RSP, _, _))
7530             .Times(3);
7531     expected_devices_written++;
7532     leAudioDevice = group->GetNextDevice(leAudioDevice);
7533   }
7534   ASSERT_EQ(expected_devices_written, num_devices);
7535 
7536   // Validate GroupStreamStatus
7537   EXPECT_CALL(mock_callbacks_,
7538               StatusReportCb(leaudio_group_id,
7539                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER));
7540 
7541   // Start the configuration and stream Media content
7542   group->SetPendingConfiguration();
7543   LeAudioGroupStateMachine::Get()->ConfigureStream(group, context_type,
7544                                                    {.sink = types::AudioContexts(context_type),
7545                                                     .source = types::AudioContexts(context_type)});
7546 
7547   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7548 
7549   group->ClearPendingConfiguration();
7550   // Validate GroupStreamStatus
7551   EXPECT_CALL(mock_callbacks_,
7552               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7553 
7554   // Start the configuration and stream Media content
7555   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7556                                                {.sink = types::AudioContexts(context_type),
7557                                                 .source = types::AudioContexts(context_type)});
7558 
7559   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7560 }
7561 
TEST_F(StateMachineTest,StartStreamCachedConfig)7562 TEST_F(StateMachineTest, StartStreamCachedConfig) {
7563   const auto context_type = kContextTypeMedia;
7564   const auto leaudio_group_id = 6;
7565   const auto num_devices = 2;
7566 
7567   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7568 
7569   // Prepare multiple fake connected devices in a group
7570   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7571   ASSERT_EQ(group->Size(), num_devices);
7572 
7573   PrepareConfigureCodecHandler(group, 0, true);
7574   PrepareConfigureQosHandler(group);
7575   PrepareEnableHandler(group);
7576   PrepareDisableHandler(group);
7577   PrepareReleaseHandler(group);
7578 
7579   InjectInitialIdleNotification(group);
7580 
7581   auto* leAudioDevice = group->GetFirstDevice();
7582   auto expected_devices_written = 0;
7583   while (leAudioDevice) {
7584     /* Three Writes:
7585      * 1: Codec config
7586      * 2: Codec QoS (+1 after restart)
7587      * 3: Enabling (+1 after restart)
7588      * 4: Release (1)
7589      */
7590     EXPECT_CALL(gatt_queue,
7591                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7592                                     GATT_WRITE_NO_RSP, _, _))
7593             .Times(6);
7594     expected_devices_written++;
7595     leAudioDevice = group->GetNextDevice(leAudioDevice);
7596   }
7597   ASSERT_EQ(expected_devices_written, num_devices);
7598 
7599   // Validate GroupStreamStatus
7600   EXPECT_CALL(mock_callbacks_,
7601               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7602 
7603   // Start the configuration and stream Media content
7604   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7605                                                {.sink = types::AudioContexts(context_type),
7606                                                 .source = types::AudioContexts(context_type)});
7607 
7608   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7609 
7610   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7611   reset_mock_function_count_map();
7612 
7613   // Validate GroupStreamStatus
7614   EXPECT_CALL(mock_callbacks_,
7615               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
7616 
7617   EXPECT_CALL(mock_callbacks_,
7618               StatusReportCb(leaudio_group_id,
7619                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
7620   // Start the configuration and stream Media content
7621   LeAudioGroupStateMachine::Get()->StopStream(group);
7622 
7623   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7624 
7625   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7626   reset_mock_function_count_map();
7627 
7628   // Restart stream
7629   EXPECT_CALL(mock_callbacks_,
7630               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7631 
7632   // Start the configuration and stream Media content
7633   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7634                                                {.sink = types::AudioContexts(context_type),
7635                                                 .source = types::AudioContexts(context_type)});
7636 
7637   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7638   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7639 }
7640 
TEST_F(StateMachineTest,StartStreamCachedConfigReconfigInvalidBehavior)7641 TEST_F(StateMachineTest, StartStreamCachedConfigReconfigInvalidBehavior) {
7642   const auto context_type = kContextTypeConversational;
7643   const auto leaudio_group_id = 6;
7644   const auto num_devices = 1;
7645   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
7646 
7647   /* Scenario
7648    * 1. Start stream and stop stream so ASEs stays in Configured State
7649    * 2. Reconfigure ASEs localy, so the QoS parameters are zeroed
7650    * 3. Inject one ASE 2 to be in Releasing state
7651    * 4. Start stream and Incject ASE 1 to go into Codec Configured state
7652    * 5. IN such case CIG shall not be created and fallback to Release and
7653    * Configure stream should happen. Before fix CigCreate with invalid
7654    * parameters were called */
7655   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
7656 
7657   // Prepare multiple fake connected devices in a group
7658   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
7659   ASSERT_EQ(group->Size(), num_devices);
7660 
7661   PrepareConfigureCodecHandler(group, 0, true);
7662   PrepareConfigureQosHandler(group);
7663   PrepareEnableHandler(group);
7664   PrepareDisableHandler(group);
7665   PrepareReceiverStartReadyHandler(group);
7666   PrepareReleaseHandler(group);
7667 
7668   InjectInitialIdleNotification(group);
7669 
7670   // Validate GroupStreamStatus
7671   EXPECT_CALL(mock_callbacks_,
7672               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7673 
7674   EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(1);
7675 
7676   // Start the configuration and stream call content
7677   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
7678                                                {.sink = types::AudioContexts(context_type),
7679                                                 .source = types::AudioContexts(context_type)});
7680 
7681   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7682 
7683   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7684   reset_mock_function_count_map();
7685 
7686   // Validate GroupStreamStatus
7687   EXPECT_CALL(mock_callbacks_,
7688               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
7689 
7690   EXPECT_CALL(mock_callbacks_,
7691               StatusReportCb(leaudio_group_id,
7692                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
7693   // Start the configuration and stream Media content
7694   LeAudioGroupStateMachine::Get()->StopStream(group);
7695 
7696   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7697   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
7698 
7699   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7700   reset_mock_function_count_map();
7701 
7702   stop_inject_configured_ase_after_first_ase_configured_ = true;
7703 
7704   auto device = group->GetFirstDevice();
7705   int i = 0;
7706   for (auto& ase : device->ases_) {
7707     if (i++ == 0) {
7708       continue;
7709     }
7710 
7711     // Simulate autonomus release for one ASE
7712     InjectAseStateNotification(&ase, device, group, ascs::kAseStateReleasing, nullptr);
7713   }
7714 
7715   // Restart stream and expect it will not be created.
7716   EXPECT_CALL(mock_callbacks_,
7717               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING))
7718           .Times(0);
7719   EXPECT_CALL(mock_callbacks_,
7720               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING))
7721           .Times(0);
7722 
7723   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(0);
7724 
7725   // Block the fallback Release which will happen when CreateCig will fail
7726   stay_in_releasing_state_ = true;
7727 
7728   // Start the configuration and stream Live content
7729   bool result = LeAudioGroupStateMachine::Get()->StartStream(
7730           group, kContextTypeLive,
7731           {.sink = types::AudioContexts(kContextTypeLive),
7732            .source = types::AudioContexts(kContextTypeLive)});
7733 
7734   // Group internally in releasing state. StartStrean should faile.
7735 
7736   ASSERT_FALSE(result);
7737 
7738   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7739   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
7740 }
7741 
TEST_F(StateMachineTest,BoundedHeadphonesConversationalToMediaChannelCount_2)7742 TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_2) {
7743   const auto initial_context_type = kContextTypeConversational;
7744   const auto new_context_type = kContextTypeMedia;
7745   const auto leaudio_group_id = 6;
7746   const auto num_devices = 1;
7747   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
7748 
7749   sample_freq_ |= codec_specific::kCapSamplingFrequency48000Hz |
7750                   codec_specific::kCapSamplingFrequency32000Hz;
7751   additional_snk_ases = 3;
7752   additional_src_ases = 1;
7753 
7754   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7755   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
7756 
7757   // Prepare multiple fake connected devices in a group
7758   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, initial_context_type, num_devices,
7759                                              kContextTypeConversational | kContextTypeMedia);
7760   ASSERT_EQ(group->Size(), num_devices);
7761 
7762   PrepareConfigureCodecHandler(group, 0, true);
7763   PrepareConfigureQosHandler(group);
7764   PrepareEnableHandler(group);
7765   PrepareDisableHandler(group);
7766   PrepareReleaseHandler(group);
7767   PrepareReceiverStartReadyHandler(group);
7768 
7769   InjectInitialIdleNotification(group);
7770 
7771   auto* leAudioDevice = group->GetFirstDevice();
7772   auto expected_devices_written = 0;
7773   while (leAudioDevice) {
7774     /* 8 Writes:
7775      * 1: Codec config (+1 after reconfig)
7776      * 2: Codec QoS (+1 after reconfig)
7777      * 3: Enabling (+1 after reconfig)
7778      * 4: ReceiverStartReady (only for conversational)
7779      * 5: Release
7780      */
7781     EXPECT_CALL(gatt_queue,
7782                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7783                                     GATT_WRITE_NO_RSP, _, _))
7784             .Times(8);
7785     expected_devices_written++;
7786     leAudioDevice = group->GetNextDevice(leAudioDevice);
7787   }
7788   ASSERT_EQ(expected_devices_written, num_devices);
7789 
7790   // Validate GroupStreamStatus
7791   EXPECT_CALL(mock_callbacks_,
7792               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7793 
7794   // Start the configuration and stream Media content
7795   LeAudioGroupStateMachine::Get()->StartStream(
7796           group, initial_context_type,
7797           {.sink = types::AudioContexts(initial_context_type),
7798            .source = types::AudioContexts(initial_context_type)});
7799 
7800   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7801 
7802   auto current_config = group->GetCachedConfiguration(initial_context_type);
7803   ASSERT_NE(nullptr, current_config);
7804   ASSERT_EQ(1lu, current_config->confs.sink.size());
7805   ASSERT_EQ(1lu, current_config->confs.source.size());
7806 
7807   // Validate GroupStreamStatus
7808   EXPECT_CALL(mock_callbacks_,
7809               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
7810 
7811   EXPECT_CALL(mock_callbacks_,
7812               StatusReportCb(leaudio_group_id,
7813                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
7814   // Start the configuration and stream Media content
7815   LeAudioGroupStateMachine::Get()->StopStream(group);
7816 
7817   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7818 
7819   // Restart stream
7820   EXPECT_CALL(mock_callbacks_,
7821               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7822 
7823   // Start the configuration and stream Media content
7824   LeAudioGroupStateMachine::Get()->StartStream(group, new_context_type,
7825                                                {.sink = types::AudioContexts(new_context_type),
7826                                                 .source = types::AudioContexts(new_context_type)});
7827 
7828   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7829 
7830   current_config = group->GetCachedConfiguration(new_context_type);
7831   ASSERT_NE(nullptr, current_config);
7832   ASSERT_EQ(1lu, current_config->confs.sink.size());
7833   ASSERT_EQ(0lu, current_config->confs.source.size());
7834 }
7835 
TEST_F(StateMachineTest,BoundedHeadphonesConversationalToMediaChannelCount_1_MonoMic)7836 TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_1_MonoMic) {
7837   const auto initial_context_type = kContextTypeConversational;
7838   const auto new_context_type = kContextTypeMedia;
7839   const auto leaudio_group_id = 6;
7840   const auto num_devices = 1;
7841   // Single audio allocation for the mono source
7842   channel_allocations_source_ = ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft;
7843   channel_count_ = kLeAudioCodecChannelCountSingleChannel;
7844 
7845   sample_freq_ |= codec_specific::kCapSamplingFrequency48000Hz |
7846                   codec_specific::kCapSamplingFrequency32000Hz;
7847   additional_snk_ases = 3;
7848   additional_src_ases = 1;
7849 
7850   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7851   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
7852 
7853   // Prepare one fake connected devices in a group
7854   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, initial_context_type, num_devices,
7855                                              kContextTypeConversational | kContextTypeMedia);
7856   ASSERT_EQ(group->Size(), num_devices);
7857 
7858   // Cannot verify here as we will change the number of ases on reconfigure
7859   PrepareConfigureCodecHandler(group, 0, true);
7860   PrepareConfigureQosHandler(group);
7861   PrepareEnableHandler(group);
7862   PrepareDisableHandler(group);
7863   PrepareReleaseHandler(group);
7864   PrepareReceiverStartReadyHandler(group);
7865 
7866   InjectInitialIdleNotification(group);
7867 
7868   auto* leAudioDevice = group->GetFirstDevice();
7869   auto expected_devices_written = 0;
7870   while (leAudioDevice) {
7871     /* 8 Writes:
7872      * 1: Codec config (+1 after reconfig)
7873      * 2: Codec QoS (+1 after reconfig)
7874      * 3: Enabling (+1 after reconfig)
7875      * 4: ReceiverStartReady (only for conversational)
7876      * 5: Release
7877      */
7878     EXPECT_CALL(gatt_queue,
7879                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7880                                     GATT_WRITE_NO_RSP, _, _))
7881             .Times(8);
7882     expected_devices_written++;
7883     leAudioDevice = group->GetNextDevice(leAudioDevice);
7884   }
7885   ASSERT_EQ(expected_devices_written, num_devices);
7886 
7887   // Validate GroupStreamStatus
7888   EXPECT_CALL(mock_callbacks_,
7889               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7890 
7891   // Start the configuration and stream Media content
7892   LeAudioGroupStateMachine::Get()->StartStream(
7893           group, initial_context_type,
7894           {.sink = types::AudioContexts(initial_context_type),
7895            .source = types::AudioContexts(initial_context_type)});
7896 
7897   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7898 
7899   auto current_config = group->GetCachedConfiguration(initial_context_type);
7900   ASSERT_NE(nullptr, current_config);
7901   // sink has two locations
7902   ASSERT_EQ(2lu, current_config->confs.sink.size());
7903   // source has a single location
7904   ASSERT_EQ(1lu, current_config->confs.source.size());
7905 
7906   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7907   reset_mock_function_count_map();
7908 
7909   // Validate GroupStreamStatus
7910   EXPECT_CALL(mock_callbacks_,
7911               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
7912 
7913   EXPECT_CALL(mock_callbacks_,
7914               StatusReportCb(leaudio_group_id,
7915                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
7916   // Start the configuration and stream Media content
7917   LeAudioGroupStateMachine::Get()->StopStream(group);
7918 
7919   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7920   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7921   reset_mock_function_count_map();
7922 
7923   // Restart stream
7924   EXPECT_CALL(mock_callbacks_,
7925               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7926 
7927   // Start the configuration and stream Media content
7928   LeAudioGroupStateMachine::Get()->StartStream(group, new_context_type,
7929                                                {.sink = types::AudioContexts(new_context_type),
7930                                                 .source = types::AudioContexts(new_context_type)});
7931 
7932   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
7933   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
7934 
7935   current_config = group->GetCachedConfiguration(new_context_type);
7936   ASSERT_NE(nullptr, current_config);
7937   ASSERT_EQ(2lu, current_config->confs.sink.size());
7938   ASSERT_EQ(0lu, current_config->confs.source.size());
7939 }
7940 
TEST_F(StateMachineTest,DISABLED_BoundedHeadphonesConversationalToMediaChannelCount_1_StereoMic)7941 TEST_F(StateMachineTest, DISABLED_BoundedHeadphonesConversationalToMediaChannelCount_1_StereoMic) {
7942   const auto initial_context_type = kContextTypeConversational;
7943   const auto new_context_type = kContextTypeMedia;
7944   const auto leaudio_group_id = 6;
7945   const auto num_devices = 1;
7946   channel_allocations_source_ = ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
7947                                 ::bluetooth::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
7948   channel_count_ = kLeAudioCodecChannelCountSingleChannel;
7949 
7950   sample_freq_ |= codec_specific::kCapSamplingFrequency48000Hz |
7951                   codec_specific::kCapSamplingFrequency32000Hz;
7952   additional_snk_ases = 3;
7953   additional_src_ases = 1;
7954 
7955   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
7956   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
7957 
7958   // Prepare one fake connected devices in a group
7959   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, initial_context_type, num_devices,
7960                                              kContextTypeConversational | kContextTypeMedia);
7961   ASSERT_EQ(group->Size(), num_devices);
7962 
7963   // Cannot verify here as we will change the number of ases on reconfigure
7964   PrepareConfigureCodecHandler(group, 0, true);
7965   PrepareConfigureQosHandler(group);
7966   PrepareEnableHandler(group);
7967   PrepareDisableHandler(group);
7968   PrepareReleaseHandler(group);
7969   PrepareReceiverStartReadyHandler(group);
7970 
7971   InjectInitialIdleNotification(group);
7972 
7973   auto* leAudioDevice = group->GetFirstDevice();
7974   auto expected_devices_written = 0;
7975   while (leAudioDevice) {
7976     /* 8 Writes:
7977      * 1: Codec config (+1 after reconfig)
7978      * 2: Codec QoS (+1 after reconfig)
7979      * 3: Enabling (+1 after reconfig)
7980      * 4: ReceiverStartReady (only for conversational)
7981      * 5: Release
7982      */
7983     EXPECT_CALL(gatt_queue,
7984                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
7985                                     GATT_WRITE_NO_RSP, _, _))
7986             .Times(8);
7987     expected_devices_written++;
7988     leAudioDevice = group->GetNextDevice(leAudioDevice);
7989   }
7990   ASSERT_EQ(expected_devices_written, num_devices);
7991 
7992   // Validate GroupStreamStatus
7993   EXPECT_CALL(mock_callbacks_,
7994               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
7995 
7996   // Start the configuration and stream Media content
7997   LeAudioGroupStateMachine::Get()->StartStream(
7998           group, initial_context_type,
7999           {.sink = types::AudioContexts(initial_context_type),
8000            .source = types::AudioContexts(initial_context_type)});
8001 
8002   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8003 
8004   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8005   reset_mock_function_count_map();
8006 
8007   auto current_config = group->GetCachedConfiguration(initial_context_type);
8008   ASSERT_NE(nullptr, current_config);
8009   ASSERT_EQ(2lu, current_config->confs.sink.size());
8010   ASSERT_EQ(2lu, current_config->confs.source.size());
8011 
8012   // Validate GroupStreamStatus
8013   EXPECT_CALL(mock_callbacks_,
8014               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
8015 
8016   EXPECT_CALL(mock_callbacks_,
8017               StatusReportCb(leaudio_group_id,
8018                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
8019   // Start the configuration and stream Media content
8020   LeAudioGroupStateMachine::Get()->StopStream(group);
8021 
8022   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8023   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8024   reset_mock_function_count_map();
8025 
8026   // Restart stream
8027   EXPECT_CALL(mock_callbacks_,
8028               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
8029 
8030   // Start the configuration and stream Media content
8031   LeAudioGroupStateMachine::Get()->StartStream(group, new_context_type,
8032                                                {.sink = types::AudioContexts(new_context_type),
8033                                                 .source = types::AudioContexts(new_context_type)});
8034 
8035   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8036   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8037 
8038   current_config = group->GetCachedConfiguration(new_context_type);
8039   ASSERT_NE(nullptr, current_config);
8040   ASSERT_EQ(2lu, current_config->confs.sink.size());
8041   ASSERT_EQ(0lu, current_config->confs.source.size());
8042 }
8043 
TEST_F(StateMachineTest,lateCisDisconnectedEvent_DuringReconfiguration)8044 TEST_F(StateMachineTest, lateCisDisconnectedEvent_DuringReconfiguration) {
8045   const auto context_type = kContextTypeMedia;
8046   const auto leaudio_group_id = 6;
8047   const auto num_devices = 1;
8048 
8049   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
8050 
8051   // Prepare multiple fake connected devices in a group
8052   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
8053   ASSERT_EQ(group->Size(), num_devices);
8054 
8055   PrepareConfigureCodecHandler(group, 0, true);
8056   PrepareConfigureQosHandler(group);
8057   PrepareEnableHandler(group);
8058   PrepareDisableHandler(group);
8059   PrepareReleaseHandler(group);
8060 
8061   auto* leAudioDevice = group->GetFirstDevice();
8062   auto expected_devices_written = 0;
8063 
8064   /* Three Writes:
8065    * 1: Codec Config
8066    * 2: Codec QoS
8067    * 3: Enabling
8068    */
8069   EXPECT_CALL(gatt_queue,
8070               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8071                                   GATT_WRITE_NO_RSP, _, _))
8072           .Times(AtLeast(3));
8073   expected_devices_written++;
8074 
8075   ASSERT_EQ(expected_devices_written, num_devices);
8076 
8077   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8078   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8079   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
8080 
8081   InjectInitialIdleNotification(group);
8082 
8083   // Start the configuration and stream Media content
8084   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
8085                                                {.sink = types::AudioContexts(context_type),
8086                                                 .source = types::AudioContexts(context_type)});
8087 
8088   // Check if group has transitioned to a proper state
8089   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8090   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8091 
8092   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8093   reset_mock_function_count_map();
8094 
8095   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
8096   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
8097 
8098   /* Do reconfiguration */
8099   group->SetPendingConfiguration();
8100 
8101   // Validate GroupStreamStatus
8102   EXPECT_CALL(mock_callbacks_,
8103               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
8104 
8105   EXPECT_CALL(mock_callbacks_,
8106               StatusReportCb(leaudio_group_id,
8107                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS))
8108           .Times(0);
8109   LeAudioGroupStateMachine::Get()->StopStream(group);
8110 
8111   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8112 
8113   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
8114 
8115   EXPECT_CALL(mock_callbacks_,
8116               StatusReportCb(leaudio_group_id,
8117                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
8118 
8119   // Inject CIS and ACL disconnection of first device
8120   InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
8121   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8122   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8123 }
8124 
TEST_F(StateMachineTest,lateCisDisconnectedEvent_AutonomousConfigured)8125 TEST_F(StateMachineTest, lateCisDisconnectedEvent_AutonomousConfigured) {
8126   const auto context_type = kContextTypeMedia;
8127   const auto leaudio_group_id = 6;
8128   const auto num_devices = 1;
8129 
8130   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
8131 
8132   // Prepare multiple fake connected devices in a group
8133   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
8134   ASSERT_EQ(group->Size(), num_devices);
8135 
8136   PrepareConfigureCodecHandler(group, 0, true);
8137   PrepareConfigureQosHandler(group);
8138   PrepareEnableHandler(group);
8139   PrepareDisableHandler(group);
8140   PrepareReleaseHandler(group);
8141 
8142   auto* leAudioDevice = group->GetFirstDevice();
8143   auto expected_devices_written = 0;
8144 
8145   /* Three Writes:
8146    * 1: Codec Config
8147    * 2: Codec QoS
8148    * 3: Enabling
8149    */
8150   EXPECT_CALL(gatt_queue,
8151               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8152                                   GATT_WRITE_NO_RSP, _, _))
8153           .Times(AtLeast(3));
8154   expected_devices_written++;
8155 
8156   ASSERT_EQ(expected_devices_written, num_devices);
8157 
8158   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8159   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8160   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
8161 
8162   InjectInitialIdleNotification(group);
8163 
8164   // Start the configuration and stream Media content
8165   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
8166                                                {.sink = types::AudioContexts(context_type),
8167                                                 .source = types::AudioContexts(context_type)});
8168 
8169   // Check if group has transitioned to a proper state
8170   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8171   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8172 
8173   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8174   reset_mock_function_count_map();
8175 
8176   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
8177   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
8178 
8179   // Validate GroupStreamStatus
8180   EXPECT_CALL(mock_callbacks_,
8181               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
8182 
8183   EXPECT_CALL(mock_callbacks_,
8184               StatusReportCb(leaudio_group_id,
8185                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS))
8186           .Times(0);
8187 
8188   // Stop the stream
8189   LeAudioGroupStateMachine::Get()->StopStream(group);
8190 
8191   // Check if group has transitioned to a proper state
8192   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
8193 
8194   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8195 
8196   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
8197 
8198   EXPECT_CALL(mock_callbacks_,
8199               StatusReportCb(leaudio_group_id,
8200                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
8201 
8202   // Inject CIS and ACL disconnection of first device
8203   InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
8204   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8205   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8206 }
8207 
TEST_F(StateMachineTest,lateCisDisconnectedEvent_Idle)8208 TEST_F(StateMachineTest, lateCisDisconnectedEvent_Idle) {
8209   const auto context_type = kContextTypeMedia;
8210   const auto leaudio_group_id = 6;
8211   const auto num_devices = 1;
8212 
8213   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
8214 
8215   // Prepare multiple fake connected devices in a group
8216   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
8217   ASSERT_EQ(group->Size(), num_devices);
8218 
8219   PrepareConfigureCodecHandler(group);
8220   PrepareConfigureQosHandler(group);
8221   PrepareEnableHandler(group);
8222   PrepareDisableHandler(group);
8223   PrepareReleaseHandler(group);
8224 
8225   auto* leAudioDevice = group->GetFirstDevice();
8226   auto expected_devices_written = 0;
8227 
8228   /* Three Writes:
8229    * 1: Codec Config
8230    * 2: Codec QoS
8231    * 3: Enabling
8232    */
8233   EXPECT_CALL(gatt_queue,
8234               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8235                                   GATT_WRITE_NO_RSP, _, _))
8236           .Times(AtLeast(3));
8237   expected_devices_written++;
8238 
8239   ASSERT_EQ(expected_devices_written, num_devices);
8240 
8241   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8242   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8243   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
8244 
8245   InjectInitialIdleNotification(group);
8246 
8247   // Start the configuration and stream Media content
8248   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
8249                                                {.sink = types::AudioContexts(context_type),
8250                                                 .source = types::AudioContexts(context_type)});
8251 
8252   // Check if group has transitioned to a proper state
8253   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8254   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8255 
8256   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8257   reset_mock_function_count_map();
8258   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
8259   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
8260 
8261   // Validate GroupStreamStatus
8262   EXPECT_CALL(mock_callbacks_,
8263               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
8264 
8265   EXPECT_CALL(mock_callbacks_,
8266               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE))
8267           .Times(0);
8268 
8269   // Stop the stream
8270   LeAudioGroupStateMachine::Get()->StopStream(group);
8271 
8272   // Check if group has transitioned to a proper state
8273   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
8274   ASSERT_EQ(0, get_func_call_count("alarm_cancel"));
8275 
8276   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8277 
8278   EXPECT_CALL(mock_callbacks_,
8279               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
8280 
8281   // Inject CIS and ACL disconnection of first device
8282   InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
8283   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8284   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8285 }
8286 
TEST_F(StateMachineTest,StreamReconfigureAfterCisLostTwoDevices)8287 TEST_F(StateMachineTest, StreamReconfigureAfterCisLostTwoDevices) {
8288   auto context_type = kContextTypeConversational;
8289   const auto leaudio_group_id = 4;
8290   const auto num_devices = 2;
8291 
8292   // Prepare multiple fake connected devices in a group
8293   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
8294                                              kContextTypeConversational | kContextTypeMedia);
8295   ASSERT_EQ(group->Size(), num_devices);
8296 
8297   PrepareConfigureCodecHandler(group);
8298   PrepareConfigureQosHandler(group);
8299   PrepareEnableHandler(group);
8300   PrepareReceiverStartReadyHandler(group);
8301 
8302   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
8303   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
8304 
8305   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8306   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8307   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
8308   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
8309 
8310   InjectInitialIdleNotification(group);
8311 
8312   auto* leAudioDevice = group->GetFirstDevice();
8313   auto expected_devices_written = 0;
8314   while (leAudioDevice) {
8315     EXPECT_CALL(gatt_queue,
8316                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8317                                     GATT_WRITE_NO_RSP, _, _))
8318             .Times(3);
8319     expected_devices_written++;
8320     leAudioDevice = group->GetNextDevice(leAudioDevice);
8321   }
8322   ASSERT_EQ(expected_devices_written, num_devices);
8323 
8324   // Validate GroupStreamStatus
8325   EXPECT_CALL(mock_callbacks_,
8326               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
8327 
8328   // Start the configuration and stream Media content
8329   context_type = kContextTypeMedia;
8330   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
8331           group, context_type,
8332           {.sink = types::AudioContexts(context_type),
8333            .source = types::AudioContexts(context_type)}));
8334 
8335   // Check if group has transitioned to a proper state
8336   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8337   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8338   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8339   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
8340   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8341 
8342   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8343   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8344   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
8345   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
8346   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
8347 
8348   // Device disconnects due to timeout of CIS
8349   leAudioDevice = group->GetFirstDevice();
8350   while (leAudioDevice) {
8351     InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
8352     // Disconnect device
8353     LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(group, leAudioDevice);
8354 
8355     leAudioDevice = group->GetNextDevice(leAudioDevice);
8356   }
8357 
8358   group->ReloadAudioLocations();
8359   group->ReloadAudioDirections();
8360 
8361   // Start conversational scenario
8362   leAudioDevice = group->GetFirstDevice();
8363   int device_cnt = num_devices;
8364   while (leAudioDevice) {
8365     leAudioDevice->conn_id_ = device_cnt--;
8366     leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
8367     leAudioDevice = group->GetNextDevice(leAudioDevice);
8368   }
8369 
8370   InjectInitialIdleNotification(group);
8371 
8372   group->ReloadAudioLocations();
8373   group->ReloadAudioDirections();
8374 
8375   leAudioDevice = group->GetFirstDevice();
8376   expected_devices_written = 0;
8377   while (leAudioDevice) {
8378     EXPECT_CALL(gatt_queue,
8379                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8380                                     GATT_WRITE_NO_RSP, _, _))
8381             .Times(4);
8382     expected_devices_written++;
8383     leAudioDevice = group->GetNextDevice(leAudioDevice);
8384   }
8385   ASSERT_EQ(expected_devices_written, num_devices);
8386 
8387   // Validate GroupStreamStatus
8388   EXPECT_CALL(mock_callbacks_,
8389               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
8390 
8391   // Start the configuration and stream Conversational content
8392   context_type = kContextTypeConversational;
8393   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
8394           group, context_type,
8395           {.sink = types::AudioContexts(context_type),
8396            .source = types::AudioContexts(context_type)}));
8397 
8398   // Check if group has transitioned to a proper state
8399   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8400   ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
8401   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8402   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
8403   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8404 }
8405 
TEST_F(StateMachineTest,StreamClearAfterReleaseAndConnectionTimeout)8406 TEST_F(StateMachineTest, StreamClearAfterReleaseAndConnectionTimeout) {
8407   auto context_type = kContextTypeMedia;
8408   const auto leaudio_group_id = 4;
8409   const auto num_devices = 2;
8410 
8411   /* Scenario
8412   1. Streaming to 2 device
8413   2. Stream suspend
8414   3. One device got to IDLE
8415   4. Second device Connection Timeout
8416   */
8417 
8418   // Prepare multiple fake connected devices in a group
8419   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
8420                                              kContextTypeConversational | kContextTypeMedia);
8421   ASSERT_EQ(group->Size(), num_devices);
8422 
8423   PrepareConfigureCodecHandler(group);
8424   PrepareConfigureQosHandler(group);
8425   PrepareEnableHandler(group);
8426 
8427   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8428   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8429   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
8430   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
8431   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
8432   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
8433 
8434   InjectInitialIdleNotification(group);
8435 
8436   auto* leAudioDevice = group->GetFirstDevice();
8437   auto* firstDevice = leAudioDevice;
8438   auto* lastDevice = leAudioDevice;
8439 
8440   while (leAudioDevice) {
8441     lastDevice = leAudioDevice;
8442     leAudioDevice = group->GetNextDevice(leAudioDevice);
8443   }
8444 
8445   // Validate GroupStreamStatus
8446   EXPECT_CALL(mock_callbacks_,
8447               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
8448 
8449   // Start the configuration and stream Media content
8450   context_type = kContextTypeMedia;
8451   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
8452           group, context_type,
8453           {.sink = types::AudioContexts(context_type),
8454            .source = types::AudioContexts(context_type)}));
8455 
8456   // Check if group has transitioned to a proper state
8457   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8458   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8459   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8460 
8461   EXPECT_CALL(mock_callbacks_,
8462               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
8463   EXPECT_CALL(mock_callbacks_,
8464               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
8465 
8466   /* Prepare release handler only for first device. */
8467   PrepareReleaseHandler(group, 0, false, firstDevice);
8468   LeAudioGroupStateMachine::Get()->StopStream(group);
8469 
8470   /* Second device will disconnect because of timeout. Do not bother
8471    * with remove data path response from the controller. In test we are doing it
8472    * in a test thread which breaks things. */
8473   ON_CALL(*mock_iso_manager_, RemoveIsoDataPath).WillByDefault(Return());
8474   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
8475   InjectAclDisconnected(group, lastDevice);
8476 
8477   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8478   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8479 }
8480 
TEST_F(StateMachineTest,DisconnectGroupMemberWhileEnablingStream)8481 TEST_F(StateMachineTest, DisconnectGroupMemberWhileEnablingStream) {
8482   auto context_type = kContextTypeMedia;
8483   const auto leaudio_group_id = 4;
8484   const auto num_devices = 2;
8485 
8486   /* Scenario
8487   1. Initiate streaming to 1 device but stay in QOS_CONFIGURED due to started enabling ASEs
8488   2. Second device is attached and immediately disconnected
8489   4. Groups should not go to IDLE as the first device is about to stream
8490   5. Continue streaming with the first device
8491   */
8492 
8493   // Prepare multiple fake connected devices in a group
8494   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
8495                                              kContextTypeConversational | kContextTypeMedia);
8496   ASSERT_EQ(group->Size(), num_devices);
8497 
8498   PrepareConfigureCodecHandler(group);
8499   PrepareConfigureQosHandler(group);
8500 
8501   auto* leAudioDevice = group->GetFirstDevice();
8502   auto* firstDevice = leAudioDevice;
8503   auto* lastDevice = leAudioDevice;
8504 
8505   while (leAudioDevice) {
8506     lastDevice = leAudioDevice;
8507     leAudioDevice = group->GetNextDevice(leAudioDevice);
8508   }
8509 
8510   InjectInitialIdleNotification(group);
8511 
8512   // Start the configuration up to the ENABLING state
8513   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
8514           group, context_type,
8515           {.sink = types::AudioContexts(context_type),
8516            .source = types::AudioContexts(context_type)}));
8517   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
8518 
8519   ASSERT_EQ(group->NumOfConnected(), 2);
8520 
8521   // Inject second device disconnection
8522   InjectAclDisconnected(group, lastDevice);
8523 
8524   // Expect the group to not go to IDLE, as the first device is enabling
8525   ASSERT_NE(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
8526 
8527   // Resume the interrupted enabling process
8528   InjectEnablingStateFroActiveAses(group, firstDevice);
8529   InjectStreamingStateFroActiveAses(group, firstDevice);
8530 
8531   // Verify we go to STREAMING
8532   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8533 }
8534 
TEST_F(StateMachineTest,VerifyThereIsNoDoubleDataPathRemoval)8535 TEST_F(StateMachineTest, VerifyThereIsNoDoubleDataPathRemoval) {
8536   auto context_type = kContextTypeConversational;
8537   const auto leaudio_group_id = 4;
8538   const auto num_devices = 1;
8539 
8540   /* Symulate banded headphonse */
8541   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
8542 
8543   /* Scenario
8544   1. Phone call to 1 device
8545   2. Stop the stream
8546   3. Get both ASE sink and Source to releasing
8547   4. Verify only 1 RemoveDataPath is called
8548   */
8549 
8550   // Prepare multiple fake connected devices in a group
8551   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
8552                                              kContextTypeConversational | kContextTypeMedia);
8553   ASSERT_EQ(group->Size(), num_devices);
8554 
8555   PrepareConfigureCodecHandler(group);
8556   PrepareConfigureQosHandler(group);
8557   PrepareEnableHandler(group);
8558   PrepareReleaseHandler(group);
8559   PrepareReceiverStartReadyHandler(group);
8560 
8561   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8562   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8563   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
8564   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
8565 
8566   /*Test ends before full clean*/
8567   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
8568   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
8569 
8570   InjectInitialIdleNotification(group);
8571 
8572   // Validate GroupStreamStatus
8573   EXPECT_CALL(mock_callbacks_,
8574               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
8575 
8576   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
8577           group, context_type,
8578           {.sink = types::AudioContexts(context_type),
8579            .source = types::AudioContexts(context_type)}));
8580 
8581   // Check if group has transitioned to a proper state
8582   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8583   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
8584   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8585 
8586   EXPECT_CALL(mock_callbacks_,
8587               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
8588 
8589   /* Do not trigger any action on removeIsoData path.*/
8590   ON_CALL(*mock_iso_manager_, RemoveIsoDataPath).WillByDefault(Return());
8591 
8592   LeAudioGroupStateMachine::Get()->StopStream(group);
8593 
8594   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8595   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8596 }
8597 
TEST_F(StateMachineTest,StreamStartWithDifferentContextFromConfiguredState)8598 TEST_F(StateMachineTest, StreamStartWithDifferentContextFromConfiguredState) {
8599   auto context_type = kContextTypeConversational;
8600   const auto leaudio_group_id = 6;
8601   const auto num_devices = 2;
8602 
8603   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
8604 
8605   // Prepare multiple fake connected devices in a group
8606   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
8607                                              kContextTypeConversational | kContextTypeMedia);
8608   ASSERT_EQ(group->Size(), num_devices);
8609 
8610   PrepareConfigureCodecHandler(group, 0, true);
8611   PrepareConfigureQosHandler(group);
8612   PrepareEnableHandler(group);
8613   PrepareDisableHandler(group);
8614   PrepareReleaseHandler(group);
8615   PrepareReceiverStartReadyHandler(group);
8616 
8617   InjectInitialIdleNotification(group);
8618 
8619   auto* leAudioDevice = group->GetFirstDevice();
8620   auto expected_devices_written = 0;
8621   while (leAudioDevice) {
8622     /* Three Writes:
8623      * 1. Codec configure
8624      * 2: Codec QoS
8625      * 3: Enabling
8626      */
8627     EXPECT_CALL(gatt_queue,
8628                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8629                                     GATT_WRITE_NO_RSP, _, _))
8630             .Times(4);
8631     expected_devices_written++;
8632     leAudioDevice = group->GetNextDevice(leAudioDevice);
8633   }
8634   ASSERT_EQ(expected_devices_written, num_devices);
8635 
8636   // Validate GroupStreamStatus
8637   EXPECT_CALL(mock_callbacks_,
8638               StatusReportCb(leaudio_group_id,
8639                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER));
8640 
8641   // Start the configuration and stream Media content
8642   group->SetPendingConfiguration();
8643   LeAudioGroupStateMachine::Get()->ConfigureStream(group, context_type,
8644                                                    {.sink = types::AudioContexts(context_type),
8645                                                     .source = types::AudioContexts(context_type)});
8646 
8647   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8648 
8649   group->ClearPendingConfiguration();
8650   // Validate GroupStreamStatus
8651   EXPECT_CALL(mock_callbacks_,
8652               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
8653 
8654   context_type = kContextTypeMedia;
8655   // Start the configuration and stream Media content
8656   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
8657                                                {.sink = types::AudioContexts(context_type),
8658                                                 .source = types::AudioContexts(context_type)});
8659 
8660   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8661 }
8662 
TEST_F(StateMachineTest,StreamStartWithSameContextFromConfiguredStateButNewMetadata)8663 TEST_F(StateMachineTest, StreamStartWithSameContextFromConfiguredStateButNewMetadata) {
8664   auto context_type = kContextTypeConversational;
8665   const auto leaudio_group_id = 6;
8666   const auto num_devices = 2;
8667 
8668   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
8669 
8670   // Prepare multiple fake connected devices in a group
8671   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices,
8672                                              kContextTypeConversational | kContextTypeLive);
8673   ASSERT_EQ(group->Size(), num_devices);
8674 
8675   PrepareConfigureCodecHandler(group, 0, true);
8676   PrepareConfigureQosHandler(group);
8677   PrepareEnableHandler(group);
8678   PrepareDisableHandler(group);
8679   PrepareReleaseHandler(group);
8680   PrepareReceiverStartReadyHandler(group);
8681 
8682   InjectInitialIdleNotification(group);
8683 
8684   auto* leAudioDevice = group->GetFirstDevice();
8685   LeAudioDevice* firstActiveDevice = leAudioDevice;
8686   auto expected_devices_written = 0;
8687   while (leAudioDevice) {
8688     /* Three Writes:
8689      * 1. Codec configure
8690      * 2: Codec QoS
8691      * 3: Enabling
8692      */
8693     EXPECT_CALL(gatt_queue,
8694                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8695                                     GATT_WRITE_NO_RSP, _, _))
8696             .Times(4);
8697     expected_devices_written++;
8698     leAudioDevice = group->GetNextDevice(leAudioDevice);
8699   }
8700   ASSERT_EQ(expected_devices_written, num_devices);
8701 
8702   // Validate GroupStreamStatus
8703   EXPECT_CALL(mock_callbacks_,
8704               StatusReportCb(leaudio_group_id,
8705                              bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER));
8706 
8707   // Start the configuration and stream Media content
8708   group->SetPendingConfiguration();
8709   LeAudioGroupStateMachine::Get()->ConfigureStream(group, context_type,
8710                                                    {.sink = types::AudioContexts(context_type),
8711                                                     .source = types::AudioContexts(context_type)});
8712 
8713   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8714 
8715   group->ClearPendingConfiguration();
8716   // Validate GroupStreamStatus
8717   EXPECT_CALL(mock_callbacks_,
8718               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
8719 
8720   auto metadata_context_type = kContextTypeLive;
8721   types::BidirectionalPair<std::vector<uint8_t>> ccid_lists = {.sink = {media_ccid},
8722                                                                .source = {media_ccid}};
8723 
8724   // Start the configuration and stream Media content
8725   LeAudioGroupStateMachine::Get()->StartStream(
8726           group, context_type,
8727           {.sink = types::AudioContexts(metadata_context_type),
8728            .source = types::AudioContexts(metadata_context_type)},
8729           ccid_lists);
8730 
8731   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
8732 
8733   // Verify that the joining device receives the right CCID list
8734   auto lastMeta = firstActiveDevice->GetFirstActiveAse()->metadata;
8735   bool parsedOk = false;
8736   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
8737                                                               parsedOk);
8738   ASSERT_TRUE(parsedOk);
8739 
8740   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
8741   ASSERT_TRUE(ccids.has_value());
8742   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
8743 }
8744 
TEST_F(StateMachineTest,testAttachDeviceToTheStreamCisFailure)8745 TEST_F(StateMachineTest, testAttachDeviceToTheStreamCisFailure) {
8746   const auto context_type = kContextTypeMedia;
8747   const auto leaudio_group_id = 6;
8748   const auto num_devices = 2;
8749 
8750   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
8751 
8752   // Prepare multiple fake connected devices in a group
8753   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
8754   ASSERT_EQ(group->Size(), num_devices);
8755 
8756   PrepareConfigureCodecHandler(group);
8757   PrepareConfigureQosHandler(group);
8758   PrepareEnableHandler(group);
8759   PrepareDisableHandler(group);
8760   PrepareReleaseHandler(group);
8761 
8762   auto* leAudioDevice = group->GetFirstDevice();
8763   LeAudioDevice* lastDevice;
8764   LeAudioDevice* fistDevice = leAudioDevice;
8765 
8766   auto expected_devices_written = 0;
8767   while (leAudioDevice) {
8768     /* Three Writes:
8769      * 1: Codec Config
8770      * 2: Codec QoS
8771      * 3: Enabling
8772      */
8773     lastDevice = leAudioDevice;
8774     EXPECT_CALL(gatt_queue,
8775                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8776                                     GATT_WRITE_NO_RSP, _, _))
8777             .Times(AtLeast(3));
8778     expected_devices_written++;
8779     leAudioDevice = group->GetNextDevice(leAudioDevice);
8780   }
8781   ASSERT_EQ(expected_devices_written, num_devices);
8782 
8783   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8784   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8785   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
8786 
8787   InjectInitialIdleNotification(group);
8788 
8789   // Start the configuration and stream Media content
8790   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
8791                                                {.sink = types::AudioContexts(context_type),
8792                                                 .source = types::AudioContexts(context_type)});
8793 
8794   // Check if group has transitioned to a proper state
8795   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8796   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8797 
8798   // Inject CIS and ACL disconnection of first device
8799   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
8800   InjectAclDisconnected(group, lastDevice);
8801 
8802   // Check if group keeps streaming
8803   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8804 
8805   lastDevice->conn_id_ = 3;
8806   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
8807 
8808   // Make sure ASE with disconnected CIS are not left in STREAMING
8809   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
8810                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
8811             nullptr);
8812   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
8813                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
8814             nullptr);
8815 
8816   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
8817                                               _, GATT_WRITE_NO_RSP, _, _))
8818           .Times(AtLeast(3));
8819 
8820   do_not_send_cis_establish_event_ = true;
8821 
8822   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8823   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
8824   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
8825                                                   {.sink = {media_ccid}, .source = {}});
8826 
8827   // Check if group keeps streaming
8828   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8829 
8830   // Verify that the joining device receives the right CCID list
8831   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
8832   bool parsedOk = false;
8833   auto ltv = bluetooth::le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(), lastMeta.size(),
8834                                                               parsedOk);
8835   ASSERT_TRUE(parsedOk);
8836 
8837   auto ccids = ltv.Find(bluetooth::le_audio::types::kLeAudioMetadataTypeCcidList);
8838   ASSERT_TRUE(ccids.has_value());
8839   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
8840 
8841   /* Verify that ASE of first device are still good*/
8842   auto ase = fistDevice->GetFirstActiveAse();
8843   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
8844   ASSERT_NE(ase->qos_config.retrans_nb, 0);
8845 }
8846 
TEST_F(StateMachineTest,testAttachDeviceWhileSecondDeviceDisconnects)8847 TEST_F(StateMachineTest, testAttachDeviceWhileSecondDeviceDisconnects) {
8848   const auto context_type = kContextTypeMedia;
8849   const auto leaudio_group_id = 6;
8850   const auto num_devices = 2;
8851 
8852   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
8853 
8854   // Prepare multiple fake connected devices in a group
8855   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
8856   ASSERT_EQ(group->Size(), num_devices);
8857 
8858   PrepareConfigureCodecHandler(group);
8859   PrepareConfigureQosHandler(group);
8860   PrepareEnableHandler(group);
8861   PrepareDisableHandler(group);
8862   PrepareReleaseHandler(group);
8863 
8864   auto* leAudioDevice = group->GetFirstDevice();
8865   LeAudioDevice* lastDevice;
8866   LeAudioDevice* firstDevice = leAudioDevice;
8867 
8868   auto expected_devices_written = 0;
8869   while (leAudioDevice) {
8870     /* Three Writes:
8871      * 1: Codec Config
8872      * 2: Codec QoS
8873      * 3: Enable
8874      */
8875     lastDevice = leAudioDevice;
8876     EXPECT_CALL(gatt_queue,
8877                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
8878                                     GATT_WRITE_NO_RSP, _, _))
8879             .Times(AtLeast(3));
8880     expected_devices_written++;
8881     leAudioDevice = group->GetNextDevice(leAudioDevice);
8882   }
8883   ASSERT_EQ(expected_devices_written, num_devices);
8884 
8885   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
8886   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8887   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
8888 
8889   InjectInitialIdleNotification(group);
8890 
8891   // Start the configuration and stream Media content
8892   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
8893                                                {.sink = types::AudioContexts(context_type),
8894                                                 .source = types::AudioContexts(context_type)});
8895 
8896   // Check if group has transitioned to a proper state
8897   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8898   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8899 
8900   // Inject CIS and ACL disconnection of first device
8901   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
8902   InjectAclDisconnected(group, lastDevice);
8903 
8904   log::info(" Device B - Disconnected ");
8905 
8906   // Check if group keeps streaming
8907   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8908 
8909   // Set second device is connected now.
8910   lastDevice->conn_id_ = 3;
8911   lastDevice->SetConnectionState(DeviceConnectState::CONNECTED);
8912 
8913   // Make sure ASE with disconnected CIS are not left in STREAMING
8914   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSink,
8915                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
8916             nullptr);
8917   ASSERT_EQ(lastDevice->GetFirstAseWithState(::bluetooth::le_audio::types::kLeAudioDirectionSource,
8918                                              types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
8919             nullptr);
8920 
8921   // Expect just Codec Configure on ASCS Control Point
8922   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
8923                                               _, GATT_WRITE_NO_RSP, _, _))
8924           .Times(AtLeast(1));
8925 
8926   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
8927   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
8928 
8929   // Remove Configuration incjection but cache configuration for future
8930   // injection
8931   PrepareConfigureCodecHandler(group, 0, true, false);
8932 
8933   log::info("Device B - Attaching to the stream");
8934 
8935   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
8936                                                   {.sink = {media_ccid}, .source = {}});
8937 
8938   // Check if group keeps streaming
8939   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8940 
8941   /* Verify that ASE of first device are still good*/
8942   auto ase = firstDevice->GetFirstActiveAse();
8943   ASSERT_NE(ase->qos_config.max_transport_latency, 0);
8944   ASSERT_NE(ase->qos_config.retrans_nb, 0);
8945 
8946   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8947   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
8948 
8949   log::info("Device A is disconnecting while Device B is attaching to the stream");
8950 
8951   InjectCisDisconnected(group, firstDevice, HCI_ERR_CONNECTION_TOUT);
8952   InjectReleasingAndIdleState(group, firstDevice);
8953 
8954   // Check if group keeps streaming
8955   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
8956   ASSERT_EQ(group->GetTargetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8957 
8958   ASSERT_EQ(group->cig.GetState(), types::CigState::CREATED);
8959 
8960   log::info("Device B continues configuration and streaming");
8961 
8962   // Expect QoS config and Enable on ASCS Control Point
8963   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, lastDevice->ctp_hdls_.val_hdl,
8964                                               _, GATT_WRITE_NO_RSP, _, _))
8965           .Times(AtLeast(2));
8966 
8967   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
8968   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
8969 
8970   InjectCachedConfigurationForActiveAses(group, lastDevice);
8971 
8972   // Check if group keeps streaming
8973   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
8974 
8975   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
8976   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
8977 }
8978 
TEST_F(StateMachineTest,testAclDropWithoutApriorCisDisconnection)8979 TEST_F(StateMachineTest, testAclDropWithoutApriorCisDisconnection) {
8980   const auto context_type = kContextTypeMedia;
8981   const auto leaudio_group_id = 6;
8982   const auto num_devices = 2;
8983 
8984   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
8985 
8986   // Prepare multiple fake connected devices in a group
8987   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
8988   ASSERT_EQ(group->Size(), num_devices);
8989 
8990   PrepareConfigureCodecHandler(group);
8991   PrepareConfigureQosHandler(group);
8992   PrepareEnableHandler(group);
8993   PrepareDisableHandler(group);
8994   PrepareReleaseHandler(group);
8995 
8996   auto* leAudioDevice = group->GetFirstDevice();
8997   LeAudioDevice* firstDevice = leAudioDevice;
8998   LeAudioDevice* lastDevice = leAudioDevice;
8999 
9000   auto expected_devices_written = 0;
9001   while (leAudioDevice) {
9002     /* Three Writes:
9003      * 1: Codec Config
9004      * 2: Codec QoS
9005      * 3: Enabling
9006      */
9007     lastDevice = leAudioDevice;
9008     EXPECT_CALL(gatt_queue,
9009                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
9010                                     GATT_WRITE_NO_RSP, _, _))
9011             .Times(AtLeast(3));
9012     expected_devices_written++;
9013     leAudioDevice = group->GetNextDevice(leAudioDevice);
9014   }
9015   ASSERT_EQ(expected_devices_written, num_devices);
9016 
9017   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
9018   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
9019   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
9020 
9021   InjectInitialIdleNotification(group);
9022 
9023   // Start the configuration and stream Media content
9024   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
9025                                                {.sink = types::AudioContexts(context_type),
9026                                                 .source = types::AudioContexts(context_type)});
9027 
9028   // Check if group has transitioned to a proper state
9029   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9030   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9031 
9032   /* Separate CIS  for dual CIS device is treated as sink device */
9033   ASSERT_EQ(group->stream_conf.stream_params.sink.num_of_devices, 2);
9034   ASSERT_EQ(group->stream_conf.stream_params.sink.num_of_channels, 2);
9035 
9036   // Inject CIS and ACL disconnection of first device
9037   InjectAclDisconnected(group, firstDevice);
9038 
9039   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
9040   InjectAclDisconnected(group, lastDevice);
9041 
9042   ASSERT_EQ(group->stream_conf.stream_params.sink.num_of_devices, 0);
9043   ASSERT_EQ(group->stream_conf.stream_params.sink.num_of_channels, 0);
9044 }
9045 
TEST_F(StateMachineTest,testAutonomousDisableOneDeviceAndGoBackToStream_CisDisconnectedOnDisable)9046 TEST_F(StateMachineTest, testAutonomousDisableOneDeviceAndGoBackToStream_CisDisconnectedOnDisable) {
9047   const auto context_type = kContextTypeConversational;
9048   const auto leaudio_group_id = 6;
9049   const auto num_devices = 2;
9050 
9051   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
9052 
9053   // Prepare multiple fake connected devices in a group
9054   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
9055   ASSERT_EQ(group->Size(), num_devices);
9056 
9057   PrepareConfigureCodecHandler(group);
9058   PrepareConfigureQosHandler(group);
9059   PrepareEnableHandler(group);
9060   PrepareDisableHandler(group);
9061   PrepareReleaseHandler(group);
9062   PrepareReceiverStartReadyHandler(group);
9063 
9064   auto* leAudioDevice = group->GetFirstDevice();
9065 
9066   LeAudioDevice* firstDevice = leAudioDevice;
9067   LeAudioDevice* lastDevice;
9068 
9069   auto expected_devices_written = 0;
9070   while (leAudioDevice) {
9071     /* Three Writes:
9072      * 1: Codec Config
9073      * 2: Codec QoS
9074      * 3: Enabling
9075      */
9076     lastDevice = leAudioDevice;
9077     EXPECT_CALL(gatt_queue,
9078                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
9079                                     GATT_WRITE_NO_RSP, _, _))
9080             .Times(AtLeast(3));
9081     expected_devices_written++;
9082     leAudioDevice = group->GetNextDevice(leAudioDevice);
9083   }
9084   ASSERT_EQ(expected_devices_written, num_devices);
9085 
9086   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
9087   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
9088   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
9089 
9090   InjectInitialIdleNotification(group);
9091 
9092   // Start the configuration and stream Conversational content
9093   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
9094                                                {.sink = types::AudioContexts(context_type),
9095                                                 .source = types::AudioContexts(context_type)});
9096 
9097   /* First timer started for transition to streaming state */
9098   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
9099 
9100   // Check if group has transitioned to a proper state
9101   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9102 
9103   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9104 
9105   log::info(" Phone call stream created");
9106 
9107   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
9108 
9109   /* First timer finished when group achieves streaming state */
9110   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
9111 
9112   /* Remote initiates autonomous Disable operation */
9113   auto ase = lastDevice->GetFirstActiveAseByDirection(
9114           ::bluetooth::le_audio::types::kLeAudioDirectionSink);
9115 
9116   log::info(" Inject ASE state changed to QoS for  {} ", lastDevice->address_);
9117   InjectAseStateNotification(ase, lastDevice, group, ascs::kAseStateQoSConfigured,
9118                              &cached_qos_configuration_map_[ase->id]);
9119 
9120   /* No action on timer in this moment. */
9121   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
9122 
9123   log::info(" Disconnect CIS for   {} ", lastDevice->address_);
9124   // Inject CIS disconnection of first device, check that group keeps streaming
9125   InjectCisDisconnected(group, lastDevice, HCI_ERR_PEER_USER);
9126 
9127   /* First device keeps streaming */
9128   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9129   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9130   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
9131 
9132   log::info(" {} should have all ASEs in QoS State ", lastDevice->address_);
9133   /* Now lets try to attach the device back to the stream (Enabling and Receiver
9134    * Start ready to be called)*/
9135 
9136   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
9137                                               _, GATT_WRITE_NO_RSP, _, _))
9138           .Times(2);
9139 
9140   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
9141   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
9142 
9143   log::info(" Attach {} to the stream, need to establish CIS", lastDevice->address_);
9144   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
9145                                                   {.sink = {media_ccid}, .source = {}});
9146 
9147   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9148   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
9149 
9150   ase = lastDevice->GetFirstActiveAse();
9151   ASSERT_EQ(ase->state, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9152 }
9153 
TEST_F(StateMachineTest,testAutonomousDisableOneDeviceAndGoBackToStream_CisConnectedOnDisable)9154 TEST_F(StateMachineTest, testAutonomousDisableOneDeviceAndGoBackToStream_CisConnectedOnDisable) {
9155   const auto context_type = kContextTypeConversational;
9156   const auto leaudio_group_id = 6;
9157   const auto num_devices = 2;
9158 
9159   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
9160 
9161   // Prepare multiple fake connected devices in a group
9162   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
9163   ASSERT_EQ(group->Size(), num_devices);
9164 
9165   PrepareConfigureCodecHandler(group);
9166   PrepareConfigureQosHandler(group);
9167   PrepareEnableHandler(group);
9168   PrepareDisableHandler(group);
9169   PrepareReleaseHandler(group);
9170   PrepareReceiverStartReadyHandler(group);
9171 
9172   auto* leAudioDevice = group->GetFirstDevice();
9173 
9174   LeAudioDevice* firstDevice = leAudioDevice;
9175   LeAudioDevice* lastDevice;
9176 
9177   auto expected_devices_written = 0;
9178   while (leAudioDevice) {
9179     /* Three Writes:
9180      * 1: Codec Config
9181      * 2: Codec QoS
9182      * 3: Enabling
9183      */
9184     lastDevice = leAudioDevice;
9185     EXPECT_CALL(gatt_queue,
9186                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
9187                                     GATT_WRITE_NO_RSP, _, _))
9188             .Times(AtLeast(3));
9189     expected_devices_written++;
9190     leAudioDevice = group->GetNextDevice(leAudioDevice);
9191   }
9192   ASSERT_EQ(expected_devices_written, num_devices);
9193 
9194   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
9195   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
9196   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
9197 
9198   InjectInitialIdleNotification(group);
9199 
9200   // Start the configuration and stream Conversational content
9201   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
9202                                                {.sink = types::AudioContexts(context_type),
9203                                                 .source = types::AudioContexts(context_type)});
9204 
9205   /* First timer started for transition to streaming state */
9206   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
9207 
9208   // Check if group has transitioned to a proper state
9209   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9210 
9211   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9212 
9213   log::info(" Phone call stream created");
9214 
9215   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
9216 
9217   /* First timer finished when group achieves streaming state */
9218   ASSERT_EQ(1, get_func_call_count("alarm_cancel"));
9219 
9220   /* Remote initiates autonomous Disable operation */
9221   auto ase = lastDevice->GetFirstActiveAseByDirection(
9222           ::bluetooth::le_audio::types::kLeAudioDirectionSink);
9223 
9224   log::info(" Inject ASE state changed to QoS for  {} ", lastDevice->address_);
9225   InjectQoSConfigurationForActiveAses(group, lastDevice);
9226 
9227   /* No action on timer in this moment. */
9228   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
9229 
9230   /* First device keeps streaming */
9231   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9232   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9233   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
9234 
9235   log::info(" {} should have all ASEs in QoS State ", lastDevice->address_);
9236 
9237   ase = lastDevice->GetFirstActiveAse();
9238   ASSERT_TRUE(ase != nullptr);
9239 
9240   group->PrintDebugState();
9241 
9242   /* Now lets try to attach the device back to the stream (Enabling and Receiver
9243    * Start ready to be called)*/
9244 
9245   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_, firstDevice->ctp_hdls_.val_hdl,
9246                                               _, GATT_WRITE_NO_RSP, _, _))
9247           .Times(2);
9248 
9249   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
9250   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
9251 
9252   log::info(" Attach {} to the stream, need to establish CIS", lastDevice->address_);
9253   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice,
9254                                                   {.sink = {media_ccid}, .source = {}});
9255 
9256   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9257   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
9258 
9259   ase = lastDevice->GetFirstActiveAse();
9260   ASSERT_TRUE(ase != nullptr);
9261   ASSERT_EQ(ase->state, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9262 }
9263 
TEST_F(StateMachineTest,testAutonomousDisable_GoToIdle)9264 TEST_F(StateMachineTest, testAutonomousDisable_GoToIdle) {
9265   const auto context_type = kContextTypeConversational;
9266   const auto leaudio_group_id = 6;
9267   const auto num_devices = 2;
9268 
9269   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
9270 
9271   // Prepare multiple fake connected devices in a group
9272   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
9273   ASSERT_EQ(group->Size(), num_devices);
9274 
9275   PrepareConfigureCodecHandler(group);
9276   PrepareConfigureQosHandler(group);
9277   PrepareEnableHandler(group);
9278   PrepareDisableHandler(group);
9279   PrepareReleaseHandler(group);
9280   PrepareReceiverStartReadyHandler(group);
9281 
9282   auto* leAudioDevice = group->GetFirstDevice();
9283   LeAudioDevice* firstDevice = leAudioDevice;
9284   LeAudioDevice* lastDevice;
9285 
9286   auto expected_devices_written = 0;
9287   while (leAudioDevice) {
9288     /* Three Writes:
9289      * 1: Codec Config
9290      * 2: Codec QoS
9291      * 3: Enabling
9292      */
9293     lastDevice = leAudioDevice;
9294     EXPECT_CALL(gatt_queue,
9295                 WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
9296                                     GATT_WRITE_NO_RSP, _, _))
9297             .Times(AtLeast(3));
9298     expected_devices_written++;
9299     leAudioDevice = group->GetNextDevice(leAudioDevice);
9300   }
9301   ASSERT_EQ(expected_devices_written, num_devices);
9302 
9303   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
9304   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
9305   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
9306 
9307   InjectInitialIdleNotification(group);
9308 
9309   EXPECT_CALL(mock_callbacks_,
9310               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::STREAMING));
9311 
9312   // Start the configuration and stream Conversational content
9313   LeAudioGroupStateMachine::Get()->StartStream(group, context_type,
9314                                                {.sink = types::AudioContexts(context_type),
9315                                                 .source = types::AudioContexts(context_type)});
9316 
9317   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
9318 
9319   log::info(" group {} is streaming ", group->group_id_);
9320 
9321   /* First timer started for transition to streaming state */
9322   ASSERT_EQ(1, get_func_call_count("alarm_set_on_mloop"));
9323 
9324   // Check if group has transitioned to a proper state
9325   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9326 
9327   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9328 
9329   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
9330 
9331   log::info(" Incjecting QoS configured for  {} ", lastDevice->address_);
9332 
9333   /* Remote initiates autonomous Disable operation */
9334   InjectQoSConfigurationForActiveAses(group, lastDevice);
9335 
9336   // Check if group still streaming
9337   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9338 
9339   log::info("{} in QoS configured state, disconnect CIS ", lastDevice->address_);
9340 
9341   // Validate GroupStreamStatus or maybe update CIS should be called
9342 
9343   /* Inject CIS disconnection of first device, disconnect only first CIS because
9344    * while processing first disconnection test will try to bring up this ASEs
9345    * to STREAMING state and connect CISes again.
9346    */
9347   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT, true);
9348 
9349   // Check if group still streaming
9350   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9351 
9352   log::info("{} in QoS configured state ", lastDevice->address_);
9353   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9354 
9355   log::info(" device {} also goes to QoS state ", firstDevice->address_);
9356 
9357   EXPECT_CALL(mock_callbacks_,
9358               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
9359 
9360   EXPECT_CALL(mock_callbacks_,
9361               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
9362 
9363   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
9364   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
9365 
9366   InjectQoSConfigurationForActiveAses(group, firstDevice);
9367 
9368   testing::Mock::VerifyAndClearExpectations(mock_iso_manager_);
9369   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
9370 }
9371 
TEST_F(StateMachineTest,testStopStreamBeforeCodecConfigureIsArrived)9372 TEST_F(StateMachineTest, testStopStreamBeforeCodecConfigureIsArrived) {
9373   /* Device is banded headphones with 1x snk + 0x src ase
9374    * (1xunidirectional CIS with channel count 2 for stereo)
9375    */
9376   const auto context_type = kContextTypeRingtone;
9377   const int leaudio_group_id = 4;
9378   channel_count_ = kLeAudioCodecChannelCountSingleChannel | kLeAudioCodecChannelCountTwoChannel;
9379 
9380   // Prepare fake connected device group
9381   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
9382 
9383   auto* leAudioDevice = group->GetFirstDevice();
9384 
9385   /*
9386    * 1 - Configure ASE
9387    * 2 - Release ASE
9388    */
9389   EXPECT_CALL(gatt_queue,
9390               WriteCharacteristic(leAudioDevice->conn_id_, leAudioDevice->ctp_hdls_.val_hdl, _,
9391                                   GATT_WRITE_NO_RSP, _, _))
9392           .Times(2);
9393 
9394   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(0);
9395   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
9396   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
9397   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
9398   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
9399   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
9400 
9401   InjectInitialIdleNotification(group);
9402 
9403   // Validate GroupStreamStatus
9404   EXPECT_CALL(mock_callbacks_,
9405               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::RELEASING));
9406   EXPECT_CALL(mock_callbacks_,
9407               StatusReportCb(leaudio_group_id, bluetooth::le_audio::GroupStreamStatus::IDLE));
9408 
9409   // Start the configuration and stream Media content
9410   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
9411           group, context_type,
9412           {.sink = types::AudioContexts(context_type),
9413            .source = types::AudioContexts(context_type)}));
9414 
9415   // Stop the stream before Codec Configured arrived
9416   LeAudioGroupStateMachine::Get()->StopStream(group);
9417 
9418   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
9419 
9420   InjectCachedConfigurationForActiveAses(group, leAudioDevice);
9421   InjectReleaseAndIdleStateForAGroup(group);
9422 
9423   // Check if group has transitioned to a proper state
9424   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
9425   ASSERT_EQ(2, get_func_call_count("alarm_cancel"));
9426 }
9427 
TEST_F(StateMachineTest,testAutonomousReleaseFromEnablingState)9428 TEST_F(StateMachineTest, testAutonomousReleaseFromEnablingState) {
9429   const auto context_type = kContextTypeMedia;
9430   const auto audio_contexts = types::AudioContexts(context_type);
9431   const auto group_id = 4;
9432   const auto num_devices = 2;
9433 
9434   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
9435 
9436   // Prepare multiple fake connected devices in a group
9437   auto* group = PrepareSingleTestDeviceGroup(group_id, context_type, num_devices);
9438   ASSERT_EQ(group->Size(), num_devices);
9439 
9440   auto* earbudLeft = group->GetFirstDevice();
9441   EXPECT_CALL(gatt_queue, WriteCharacteristic(earbudLeft->conn_id_, earbudLeft->ctp_hdls_.val_hdl,
9442                                               _, GATT_WRITE_NO_RSP, _, _))
9443           .Times(AtLeast(3));
9444 
9445   auto* earbudRight = group->GetNextDevice(earbudLeft);
9446   EXPECT_CALL(gatt_queue, WriteCharacteristic(earbudRight->conn_id_, earbudRight->ctp_hdls_.val_hdl,
9447                                               _, GATT_WRITE_NO_RSP, _, _))
9448           .Times(AtLeast(3));
9449 
9450   // let us decide when the HCI Disconnection Complete event and HCI Connection
9451   // Established events will be reported
9452   do_not_send_cis_disconnected_event_ = true;
9453   do_not_send_cis_establish_event_ = true;
9454 
9455   PrepareConfigureCodecHandler(group, 0, true);
9456   PrepareConfigureQosHandler(group);
9457   PrepareEnableHandler(group, 0, true, /* inject_streaming */ false);
9458   PrepareDisableHandler(group);
9459   PrepareReleaseHandler(group);
9460 
9461   log::debug("[TESTING] StartStream action initiated by upper layer");
9462   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
9463           group, context_type,
9464           {.sink = types::AudioContexts(context_type),
9465            .source = types::AudioContexts(context_type)}));
9466 
9467   log::debug("[TESTING] left earbud indicates there are no available context at the time");
9468   DeviceContextsUpdate(earbudLeft, types::kLeAudioDirectionSink, types::AudioContexts(),
9469                        audio_contexts);
9470 
9471   auto* earbudLeftAse = earbudLeft->GetFirstActiveAseByDirection(types::kLeAudioDirectionSink);
9472   ASSERT_FALSE(earbudLeftAse == nullptr);
9473 
9474   // make sure the ASE is in correct state, required in this scenario
9475   ASSERT_TRUE(earbudLeftAse->state == types::AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING);
9476 
9477   log::debug("[TESTING] left earbud performs autonomous ASE state transition to Releasing state");
9478   InjectAseStateNotification(earbudLeftAse, earbudLeft, group, ascs::kAseStateReleasing, nullptr);
9479 
9480   log::debug(
9481           "[TESTING] left earbud performs autonomous ASE state transition to Codec Configured "
9482           "state (caching)");
9483   auto* codec_configured_params = &cached_codec_configuration_map_[earbudLeftAse->id];
9484   InjectAseStateNotification(earbudLeftAse, earbudLeft, group, ascs::kAseStateCodecConfigured,
9485                              codec_configured_params);
9486 
9487   auto* earbudRightAse = earbudRight->GetFirstActiveAseByDirection(types::kLeAudioDirectionSink);
9488   ASSERT_FALSE(earbudRightAse == nullptr);
9489 
9490   // make sure the ASE is in correct state, required in this scenario
9491   ASSERT_TRUE(earbudRightAse->state == types::AseState::BTA_LE_AUDIO_ASE_STATE_ENABLING);
9492 
9493   bluetooth::hci::iso_manager::cis_establish_cmpl_evt cis_establish_evt = {
9494           .status = 0,
9495           .cig_id = group_id,
9496           .cis_conn_hdl = earbudRightAse->cis_conn_hdl,
9497   };
9498   log::debug("[TESTING] controller reports right earbud CIS has been successfully established");
9499   LeAudioGroupStateMachine::Get()->ProcessHciNotifCisEstablished(group, earbudRight,
9500                                                                  &cis_establish_evt);
9501 
9502   std::vector<uint8_t> streaming_params{};
9503   log::debug("[TESTING] InjectAseStateNotification earbudRight kAseStateStreaming");
9504   InjectAseStateNotification(earbudRightAse, earbudRight, group, ascs::kAseStateStreaming,
9505                              &streaming_params);
9506 
9507   bluetooth::hci::iso_manager::cis_disconnected_evt cis_disconnected_evt = {
9508           .reason = HCI_ERR_PEER_USER,
9509           .cig_id = group_id,
9510           .cis_conn_hdl = earbudLeftAse->cis_conn_hdl,
9511   };
9512   log::debug("[TESTING] controller reports left earbud CIS has been disconnected");
9513   LeAudioGroupStateMachine::Get()->ProcessHciNotifCisDisconnected(group, earbudLeft,
9514                                                                   &cis_disconnected_evt);
9515 
9516   // check if group keeps streaming
9517   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9518 
9519   log::debug("[TESTING] the available contexts are back");
9520   DeviceContextsUpdate(earbudLeft, types::kLeAudioDirectionSink, audio_contexts, audio_contexts);
9521 
9522   // reset the handlers to default
9523   PrepareEnableHandler(group);
9524   do_not_send_cis_establish_event_ = false;
9525   do_not_send_cis_disconnected_event_ = false;
9526 
9527   log::debug("[TESTING] once the contexts are back, the upper layer calls AttachToStream");
9528   LeAudioGroupStateMachine::Get()->AttachToStream(group, earbudLeft,
9529                                                   {.sink = {media_ccid}, .source = {}});
9530 
9531   // check if group keeps streaming
9532   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9533 
9534   log::debug("[TESTING] check if both are streaming");
9535   earbudLeftAse = earbudLeft->GetFirstActiveAseByDirection(types::kLeAudioDirectionSink);
9536   ASSERT_FALSE(earbudLeftAse == nullptr);
9537   ASSERT_TRUE(earbudLeftAse->state == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9538   earbudRightAse = earbudRight->GetFirstActiveAseByDirection(types::kLeAudioDirectionSink);
9539   ASSERT_FALSE(earbudRightAse == nullptr);
9540   ASSERT_TRUE(earbudRightAse->state == types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
9541 }
9542 
9543 }  // namespace internal
9544 }  // namespace bluetooth::le_audio
9545