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