• 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 <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 
23 #include <functional>
24 
25 #include "bta/le_audio/content_control_id_keeper.h"
26 #include "bta_gatt_api_mock.h"
27 #include "bta_gatt_queue_mock.h"
28 #include "btm_api_mock.h"
29 #include "client_parser.h"
30 #include "fake_osi.h"
31 #include "gd/common/init_flags.h"
32 #include "le_audio_set_configuration_provider.h"
33 #include "mock_codec_manager.h"
34 #include "mock_controller.h"
35 #include "mock_csis_client.h"
36 #include "mock_iso_manager.h"
37 #include "types/bt_transport.h"
38 
39 using ::le_audio::DeviceConnectState;
40 using ::le_audio::codec_spec_caps::kLeAudioCodecLC3ChannelCountSingleChannel;
41 using ::le_audio::codec_spec_caps::kLeAudioCodecLC3ChannelCountTwoChannel;
42 using ::le_audio::types::LeAudioContextType;
43 using ::testing::_;
44 using ::testing::AnyNumber;
45 using ::testing::AtLeast;
46 using ::testing::DoAll;
47 using ::testing::Invoke;
48 using ::testing::NiceMock;
49 using ::testing::Return;
50 using ::testing::SaveArg;
51 using ::testing::Test;
52 
53 std::map<std::string, int> mock_function_count_map;
54 extern struct fake_osi_alarm_set_on_mloop fake_osi_alarm_set_on_mloop_;
55 
56 void osi_property_set_bool(const char* key, bool value);
57 static const char* test_flags[] = {
58     "INIT_logging_debug_enabled_for_all=true",
59     nullptr,
60 };
61 
62 constexpr uint8_t media_ccid = 0xC0;
63 constexpr auto media_context =
64     static_cast<std::underlying_type<LeAudioContextType>::type>(
65         LeAudioContextType::MEDIA);
66 
67 constexpr uint8_t call_ccid = 0xD0;
68 constexpr auto call_context =
69     static_cast<std::underlying_type<LeAudioContextType>::type>(
70         LeAudioContextType::CONVERSATIONAL);
71 
72 namespace le_audio {
73 namespace internal {
74 
75 // Just some arbitrary initial handles - it has no real meaning
76 #define ATTR_HANDLE_ASCS_POOL_START (0x0000 | 32)
77 #define ATTR_HANDLE_PACS_POOL_START (0xFF00 | 64)
78 
79 constexpr LeAudioContextType kContextTypeUnspecified =
80     static_cast<LeAudioContextType>(0x0001);
81 constexpr LeAudioContextType kContextTypeConversational =
82     static_cast<LeAudioContextType>(0x0002);
83 constexpr LeAudioContextType kContextTypeMedia =
84     static_cast<LeAudioContextType>(0x0004);
85 constexpr LeAudioContextType kContextTypeSoundEffects =
86     static_cast<LeAudioContextType>(0x0080);
87 constexpr LeAudioContextType kContextTypeRingtone =
88     static_cast<LeAudioContextType>(0x0200);
89 
90 namespace codec_specific {
91 
92 constexpr uint8_t kLc3CodingFormat = 0x06;
93 
94 // Reference Codec Capabilities values to test against
95 constexpr uint8_t kCapTypeSupportedSamplingFrequencies = 0x01;
96 constexpr uint8_t kCapTypeSupportedFrameDurations = 0x02;
97 constexpr uint8_t kCapTypeAudioChannelCount = 0x03;
98 constexpr uint8_t kCapTypeSupportedOctetsPerCodecFrame = 0x04;
99 // constexpr uint8_t kCapTypeSupportedLc3CodecFramesPerSdu = 0x05;
100 
101 // constexpr uint8_t kCapSamplingFrequency8000Hz = 0x0001;
102 // constexpr uint8_t kCapSamplingFrequency11025Hz = 0x0002;
103 constexpr uint8_t kCapSamplingFrequency16000Hz = 0x0004;
104 // constexpr uint8_t kCapSamplingFrequency22050Hz = 0x0008;
105 // constexpr uint8_t kCapSamplingFrequency24000Hz = 0x0010;
106 constexpr uint8_t kCapSamplingFrequency32000Hz = 0x0020;
107 // constexpr uint8_t kCapSamplingFrequency44100Hz = 0x0040;
108 constexpr uint8_t kCapSamplingFrequency48000Hz = 0x0080;
109 // constexpr uint8_t kCapSamplingFrequency88200Hz = 0x0100;
110 // constexpr uint8_t kCapSamplingFrequency96000Hz = 0x0200;
111 // constexpr uint8_t kCapSamplingFrequency176400Hz = 0x0400;
112 // constexpr uint8_t kCapSamplingFrequency192000Hz = 0x0800;
113 // constexpr uint8_t kCapSamplingFrequency384000Hz = 0x1000;
114 
115 constexpr uint8_t kCapFrameDuration7p5ms = 0x01;
116 constexpr uint8_t kCapFrameDuration10ms = 0x02;
117 // constexpr uint8_t kCapFrameDuration7p5msPreferred = 0x10;
118 constexpr uint8_t kCapFrameDuration10msPreferred = 0x20;
119 }  // namespace codec_specific
120 
121 namespace ascs {
122 constexpr uint8_t kAseStateIdle = 0x00;
123 constexpr uint8_t kAseStateCodecConfigured = 0x01;
124 constexpr uint8_t kAseStateQoSConfigured = 0x02;
125 constexpr uint8_t kAseStateEnabling = 0x03;
126 constexpr uint8_t kAseStateStreaming = 0x04;
127 constexpr uint8_t kAseStateDisabling = 0x05;
128 constexpr uint8_t kAseStateReleasing = 0x06;
129 
130 // constexpr uint8_t kAseParamDirectionServerIsAudioSink = 0x01;
131 // constexpr uint8_t kAseParamDirectionServerIsAudioSource = 0x02;
132 
133 constexpr uint8_t kAseParamFramingUnframedSupported = 0x00;
134 // constexpr uint8_t kAseParamFramingUnframedNotSupported = 0x01;
135 
136 // constexpr uint8_t kAseParamPreferredPhy1M = 0x01;
137 // constexpr uint8_t kAseParamPreferredPhy2M = 0x02;
138 // constexpr uint8_t kAseParamPreferredPhyCoded = 0x04;
139 
140 constexpr uint8_t kAseCtpOpcodeConfigureCodec = 0x01;
141 constexpr uint8_t kAseCtpOpcodeConfigureQos = 0x02;
142 constexpr uint8_t kAseCtpOpcodeEnable = 0x03;
143 constexpr uint8_t kAseCtpOpcodeReceiverStartReady = 0x04;
144 constexpr uint8_t kAseCtpOpcodeDisable = 0x05;
145 constexpr uint8_t kAseCtpOpcodeReceiverStopReady = 0x06;
146 // constexpr uint8_t kAseCtpOpcodeUpdateMetadata = 0x07;
147 constexpr uint8_t kAseCtpOpcodeRelease = 0x08;
148 constexpr uint8_t kAseCtpOpcodeMaxVal = kAseCtpOpcodeRelease;
149 
150 }  // namespace ascs
151 
GetTestAddress(uint8_t index)152 static RawAddress GetTestAddress(uint8_t index) {
153   return {{0xC0, 0xDE, 0xC0, 0xDE, 0x00, index}};
154 }
155 
156 class MockLeAudioGroupStateMachineCallbacks
157     : public LeAudioGroupStateMachine::Callbacks {
158  public:
159   MockLeAudioGroupStateMachineCallbacks() = default;
160   MockLeAudioGroupStateMachineCallbacks(
161       const MockLeAudioGroupStateMachineCallbacks&) = delete;
162   MockLeAudioGroupStateMachineCallbacks& operator=(
163       const MockLeAudioGroupStateMachineCallbacks&) = delete;
164 
165   ~MockLeAudioGroupStateMachineCallbacks() override = default;
166   MOCK_METHOD((void), StatusReportCb,
167               (int group_id, bluetooth::le_audio::GroupStreamStatus status),
168               (override));
169   MOCK_METHOD((void), OnStateTransitionTimeout, (int group_id), (override));
170 };
171 
172 class StateMachineTest : public Test {
173  protected:
174   uint8_t ase_id_last_assigned = types::ase::kAseIdInvalid;
175   uint8_t additional_snk_ases = 0;
176   uint8_t additional_src_ases = 0;
177   uint8_t channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel;
178   uint16_t sample_freq_ = codec_specific::kCapSamplingFrequency16000Hz;
179 
SetUp()180   void SetUp() override {
181     bluetooth::common::InitFlags::Load(test_flags);
182     mock_function_count_map.clear();
183     controller::SetMockControllerInterface(&mock_controller_);
184     bluetooth::manager::SetMockBtmInterface(&btm_interface);
185     gatt::SetMockBtaGattInterface(&gatt_interface);
186     gatt::SetMockBtaGattQueue(&gatt_queue);
187 
188     ::le_audio::AudioSetConfigurationProvider::Initialize();
189     LeAudioGroupStateMachine::Initialize(&mock_callbacks_);
190 
191     ContentControlIdKeeper::GetInstance()->Start();
192 
193     MockCsisClient::SetMockInstanceForTesting(&mock_csis_client_module_);
194     ON_CALL(mock_csis_client_module_, Get())
195         .WillByDefault(Return(&mock_csis_client_module_));
196     ON_CALL(mock_csis_client_module_, IsCsisClientRunning())
197         .WillByDefault(Return(true));
198     ON_CALL(mock_csis_client_module_, GetDeviceList(_))
199         .WillByDefault(Invoke([this](int group_id) { return addresses_; }));
200     ON_CALL(mock_csis_client_module_, GetDesiredSize(_))
201         .WillByDefault(
202             Invoke([this](int group_id) { return (int)(addresses_.size()); }));
203 
204     // Support 2M Phy
205     ON_CALL(mock_controller_, SupportsBle2mPhy()).WillByDefault(Return(true));
206     ON_CALL(btm_interface, IsPhy2mSupported(_, _)).WillByDefault(Return(true));
207     ON_CALL(btm_interface, GetHCIConnHandle(_, _))
208         .WillByDefault(
209             Invoke([](RawAddress const& remote_bda, tBT_TRANSPORT transport) {
210               return remote_bda.IsEmpty()
211                          ? HCI_INVALID_HANDLE
212                          : ((uint16_t)(remote_bda.address[0] ^
213                                        remote_bda.address[1] ^
214                                        remote_bda.address[2]))
215                                    << 8 |
216                                (remote_bda.address[3] ^ remote_bda.address[4] ^
217                                 remote_bda.address[5]);
218             }));
219 
220     ON_CALL(gatt_queue, WriteCharacteristic(_, _, _, GATT_WRITE_NO_RSP, _, _))
221         .WillByDefault(Invoke([this](uint16_t conn_id, uint16_t handle,
222                                      std::vector<uint8_t> value,
223                                      tGATT_WRITE_TYPE write_type,
224                                      GATT_WRITE_OP_CB cb, void* cb_data) {
225           for (auto& dev : le_audio_devices_) {
226             if (dev->conn_id_ == conn_id) {
227               // Control point write handler
228               if (dev->ctp_hdls_.val_hdl == handle) {
229                 HandleCtpOperation(dev.get(), value, cb, cb_data);
230               }
231               break;
232             }
233           }
234         }));
235 
236     ConfigureIsoManagerMock();
237     ConfigCodecManagerMock();
238   }
239 
HandleCtpOperation(LeAudioDevice * device,std::vector<uint8_t> value,GATT_WRITE_OP_CB cb,void * cb_data)240   void HandleCtpOperation(LeAudioDevice* device, std::vector<uint8_t> value,
241                           GATT_WRITE_OP_CB cb, void* cb_data) {
242     auto opcode = value[0];
243 
244     // Verify against valid opcode range
245     ASSERT_LT(opcode, ascs::kAseCtpOpcodeMaxVal + 1);
246     ASSERT_NE(opcode, 0);
247 
248     if (ase_ctp_handlers[opcode])
249       ase_ctp_handlers[opcode](device, std::move(value), cb, cb_data);
250   }
251 
252 /* Helper function to make a deterministic (and unique on the entire device)
253  * connection handle for a given cis.
254  */
255 #define UNIQUE_CIS_CONN_HANDLE(cig_id, cis_index) (cig_id << 8 | cis_index)
256 
ConfigureIsoManagerMock()257   void ConfigureIsoManagerMock() {
258     iso_manager_ = bluetooth::hci::IsoManager::GetInstance();
259     ASSERT_NE(iso_manager_, nullptr);
260     iso_manager_->Start();
261 
262     mock_iso_manager_ = MockIsoManager::GetInstance();
263     ASSERT_NE(mock_iso_manager_, nullptr);
264 
265     ON_CALL(*mock_iso_manager_, CreateCig)
266         .WillByDefault(
267             [this](uint8_t cig_id,
268                    bluetooth::hci::iso_manager::cig_create_params p) {
269               DLOG(INFO) << "CreateCig";
270 
271               auto& group = le_audio_device_groups_[cig_id];
272               if (group) {
273                 std::vector<uint16_t> conn_handles;
274                 // Fake connection ID for each cis in a request
275                 for (auto i = 0u; i < p.cis_cfgs.size(); ++i) {
276                   conn_handles.push_back(UNIQUE_CIS_CONN_HANDLE(cig_id, i));
277                 }
278                 auto status = HCI_SUCCESS;
279                 if (group_create_command_disallowed_) {
280                   group_create_command_disallowed_ = false;
281                   status = HCI_ERR_COMMAND_DISALLOWED;
282                 }
283 
284                 LeAudioGroupStateMachine::Get()->ProcessHciNotifOnCigCreate(
285                     group.get(), status, cig_id, conn_handles);
286               }
287             });
288 
289     ON_CALL(*mock_iso_manager_, RemoveCig)
290         .WillByDefault([this](uint8_t cig_id, bool force) {
291           DLOG(INFO) << "CreateRemove";
292 
293           auto& group = le_audio_device_groups_[cig_id];
294           if (group) {
295             // Fake connection ID for each cis in a request
296             LeAudioGroupStateMachine::Get()->ProcessHciNotifOnCigRemove(
297                 0, group.get());
298           }
299         });
300 
301     ON_CALL(*mock_iso_manager_, SetupIsoDataPath)
302         .WillByDefault([this](uint16_t conn_handle,
303                               bluetooth::hci::iso_manager::iso_data_path_params
304                                   p) {
305           DLOG(INFO) << "SetupIsoDataPath";
306 
307           auto dev_it =
308               std::find_if(le_audio_devices_.begin(), le_audio_devices_.end(),
309                            [&conn_handle](auto& dev) {
310                              auto ases = dev->GetAsesByCisConnHdl(conn_handle);
311                              return (ases.sink || ases.source);
312                            });
313           if (dev_it == le_audio_devices_.end()) {
314             DLOG(ERROR) << "Device not found";
315             return;
316           }
317 
318           for (auto& kv_pair : le_audio_device_groups_) {
319             auto& group = kv_pair.second;
320             if (group->IsDeviceInTheGroup(dev_it->get())) {
321               LeAudioGroupStateMachine::Get()->ProcessHciNotifSetupIsoDataPath(
322                   group.get(), dev_it->get(), 0, conn_handle);
323               return;
324             }
325           }
326         });
327 
328     ON_CALL(*mock_iso_manager_, RemoveIsoDataPath)
329         .WillByDefault([this](uint16_t conn_handle, uint8_t iso_direction) {
330           DLOG(INFO) << "RemoveIsoDataPath";
331 
332           auto dev_it =
333               std::find_if(le_audio_devices_.begin(), le_audio_devices_.end(),
334                            [&conn_handle](auto& dev) {
335                              auto ases = dev->GetAsesByCisConnHdl(conn_handle);
336                              return (ases.sink || ases.source);
337                            });
338           if (dev_it == le_audio_devices_.end()) {
339             DLOG(ERROR) << "Device not found";
340             return;
341           }
342 
343           for (auto& kv_pair : le_audio_device_groups_) {
344             auto& group = kv_pair.second;
345             if (group->IsDeviceInTheGroup(dev_it->get())) {
346               LeAudioGroupStateMachine::Get()->ProcessHciNotifRemoveIsoDataPath(
347                   group.get(), dev_it->get(), 0, conn_handle);
348               return;
349             }
350           }
351         });
352 
353     ON_CALL(*mock_iso_manager_, EstablishCis)
354         .WillByDefault([this](bluetooth::hci::iso_manager::cis_establish_params
355                                   conn_params) {
356           DLOG(INFO) << "EstablishCis";
357 
358           for (auto& pair : conn_params.conn_pairs) {
359             auto dev_it = std::find_if(
360                 le_audio_devices_.begin(), le_audio_devices_.end(),
361                 [&pair](auto& dev) {
362                   auto ases = dev->GetAsesByCisConnHdl(pair.cis_conn_handle);
363                   return (ases.sink || ases.source);
364                 });
365             if (dev_it == le_audio_devices_.end()) {
366               DLOG(ERROR) << "Device not found";
367               return;
368             }
369 
370             for (auto& kv_pair : le_audio_device_groups_) {
371               auto& group = kv_pair.second;
372               if (group->IsDeviceInTheGroup(dev_it->get())) {
373                 bluetooth::hci::iso_manager::cis_establish_cmpl_evt evt;
374 
375                 // Fill proper values if needed
376                 evt.status = 0x00;
377                 evt.cig_id = group->group_id_;
378                 evt.cis_conn_hdl = pair.cis_conn_handle;
379                 evt.cig_sync_delay = 0;
380                 evt.cis_sync_delay = 0;
381                 evt.trans_lat_mtos = 0;
382                 evt.trans_lat_stom = 0;
383                 evt.phy_mtos = 0;
384                 evt.phy_stom = 0;
385                 evt.nse = 0;
386                 evt.bn_mtos = 0;
387                 evt.bn_stom = 0;
388                 evt.ft_mtos = 0;
389                 evt.ft_stom = 0;
390                 evt.max_pdu_mtos = 0;
391                 evt.max_pdu_stom = 0;
392                 evt.iso_itv = 0;
393 
394                 LeAudioGroupStateMachine::Get()->ProcessHciNotifCisEstablished(
395                     group.get(), dev_it->get(), &evt);
396                 break;
397               }
398             }
399           }
400         });
401 
402     ON_CALL(*mock_iso_manager_, DisconnectCis)
403         .WillByDefault([this](uint16_t cis_handle, uint8_t reason) {
404           DLOG(INFO) << "DisconnectCis";
405 
406           auto dev_it =
407               std::find_if(le_audio_devices_.begin(), le_audio_devices_.end(),
408                            [&cis_handle](auto& dev) {
409                              auto ases = dev->GetAsesByCisConnHdl(cis_handle);
410                              return (ases.sink || ases.source);
411                            });
412           if (dev_it == le_audio_devices_.end()) {
413             DLOG(ERROR) << "Device not found";
414             return;
415           }
416 
417           // When we disconnect the remote with HCI_ERR_PEER_USER, we
418           // should be getting HCI_ERR_CONN_CAUSE_LOCAL_HOST from HCI.
419           if (reason == HCI_ERR_PEER_USER) {
420             reason = HCI_ERR_CONN_CAUSE_LOCAL_HOST;
421           }
422 
423           for (auto& kv_pair : le_audio_device_groups_) {
424             auto& group = kv_pair.second;
425             if (group->IsDeviceInTheGroup(dev_it->get())) {
426               bluetooth::hci::iso_manager::cis_disconnected_evt evt{
427                   .reason = reason,
428                   .cig_id = static_cast<uint8_t>(group->group_id_),
429                   .cis_conn_hdl = cis_handle,
430               };
431               LeAudioGroupStateMachine::Get()->ProcessHciNotifCisDisconnected(
432                   group.get(), dev_it->get(), &evt);
433               return;
434             }
435           }
436         });
437   }
438 
ConfigCodecManagerMock()439   void ConfigCodecManagerMock() {
440     codec_manager_ = le_audio::CodecManager::GetInstance();
441     ASSERT_NE(codec_manager_, nullptr);
442     std::vector<bluetooth::le_audio::btle_audio_codec_config_t>
443         mock_offloading_preference(0);
444     codec_manager_->Start(mock_offloading_preference);
445     mock_codec_manager_ = MockCodecManager::GetInstance();
446     ASSERT_NE(mock_codec_manager_, nullptr);
447     ON_CALL(*mock_codec_manager_, GetCodecLocation())
448         .WillByDefault(Return(types::CodecLocation::HOST));
449   }
450 
TearDown()451   void TearDown() override {
452     /* Clear the alarm on tear down in case test case ends when the
453      * alarm is scheduled
454      */
455     alarm_cancel(nullptr);
456 
457     iso_manager_->Stop();
458     mock_iso_manager_ = nullptr;
459     codec_manager_->Stop();
460     mock_codec_manager_ = nullptr;
461 
462     gatt::SetMockBtaGattQueue(nullptr);
463     gatt::SetMockBtaGattInterface(nullptr);
464     bluetooth::manager::SetMockBtmInterface(nullptr);
465     controller::SetMockControllerInterface(nullptr);
466 
467     for (auto i = 0u; i <= ascs::kAseCtpOpcodeMaxVal; ++i)
468       ase_ctp_handlers[i] = nullptr;
469 
470     le_audio_devices_.clear();
471     addresses_.clear();
472     cached_codec_configuration_map_.clear();
473     cached_ase_to_cis_id_map_.clear();
474     LeAudioGroupStateMachine::Cleanup();
475     ::le_audio::AudioSetConfigurationProvider::Cleanup();
476   }
477 
PrepareConnectedDevice(uint8_t id,DeviceConnectState initial_connect_state,uint8_t num_ase_snk,uint8_t num_ase_src)478   std::shared_ptr<LeAudioDevice> PrepareConnectedDevice(
479       uint8_t id, DeviceConnectState initial_connect_state, uint8_t num_ase_snk,
480       uint8_t num_ase_src) {
481     auto leAudioDevice = std::make_shared<LeAudioDevice>(GetTestAddress(id),
482                                                          initial_connect_state);
483     leAudioDevice->conn_id_ = id;
484     leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
485 
486     uint16_t attr_handle = ATTR_HANDLE_ASCS_POOL_START;
487     leAudioDevice->snk_audio_locations_hdls_.val_hdl = attr_handle++;
488     leAudioDevice->snk_audio_locations_hdls_.ccc_hdl = attr_handle++;
489     leAudioDevice->src_audio_locations_hdls_.val_hdl = attr_handle++;
490     leAudioDevice->src_audio_locations_hdls_.ccc_hdl = attr_handle++;
491     leAudioDevice->audio_avail_hdls_.val_hdl = attr_handle++;
492     leAudioDevice->audio_avail_hdls_.ccc_hdl = attr_handle++;
493     leAudioDevice->audio_supp_cont_hdls_.val_hdl = attr_handle++;
494     leAudioDevice->audio_supp_cont_hdls_.ccc_hdl = attr_handle++;
495     leAudioDevice->ctp_hdls_.val_hdl = attr_handle++;
496     leAudioDevice->ctp_hdls_.ccc_hdl = attr_handle++;
497 
498     // Add some Sink ASEs
499     while (num_ase_snk) {
500       types::ase ase(0, 0, 0x01);
501       ase.hdls.val_hdl = attr_handle++;
502       ase.hdls.ccc_hdl = attr_handle++;
503 
504       leAudioDevice->ases_.emplace_back(std::move(ase));
505       num_ase_snk--;
506     }
507 
508     // Add some Source ASEs
509     while (num_ase_src) {
510       types::ase ase(0, 0, 0x02);
511       ase.hdls.val_hdl = attr_handle++;
512       ase.hdls.ccc_hdl = attr_handle++;
513 
514       leAudioDevice->ases_.emplace_back(std::move(ase));
515       num_ase_src--;
516     }
517 
518     le_audio_devices_.push_back(leAudioDevice);
519     addresses_.push_back(leAudioDevice->address_);
520 
521     return std::move(leAudioDevice);
522   }
523 
GroupTheDevice(int group_id,const std::shared_ptr<LeAudioDevice> & leAudioDevice)524   LeAudioDeviceGroup* GroupTheDevice(
525       int group_id, const std::shared_ptr<LeAudioDevice>& leAudioDevice) {
526     if (le_audio_device_groups_.count(group_id) == 0) {
527       le_audio_device_groups_[group_id] =
528           std::make_unique<LeAudioDeviceGroup>(group_id);
529     }
530 
531     auto& group = le_audio_device_groups_[group_id];
532 
533     group->AddNode(leAudioDevice);
534     if (group->IsEmpty()) return nullptr;
535 
536     return &(*group);
537   }
538 
InjectAseStateNotification(types::ase * ase,LeAudioDevice * device,LeAudioDeviceGroup * group,uint8_t new_state,void * new_state_params)539   void InjectAseStateNotification(types::ase* ase, LeAudioDevice* device,
540                                   LeAudioDeviceGroup* group, uint8_t new_state,
541                                   void* new_state_params) {
542     // Prepare additional params
543     switch (new_state) {
544       case ascs::kAseStateCodecConfigured: {
545         client_parser::ascs::ase_codec_configured_state_params* conf =
546             static_cast<
547                 client_parser::ascs::ase_codec_configured_state_params*>(
548                 new_state_params);
549         std::vector<uint8_t> notif_value(25 + conf->codec_spec_conf.size());
550         auto* p = notif_value.data();
551 
552         UINT8_TO_STREAM(p, ase->id == types::ase::kAseIdInvalid
553                                ? ++ase_id_last_assigned
554                                : ase->id);
555         UINT8_TO_STREAM(p, new_state);
556 
557         UINT8_TO_STREAM(p, conf->framing);
558         UINT8_TO_STREAM(p, conf->preferred_phy);
559         UINT8_TO_STREAM(p, conf->preferred_retrans_nb);
560         UINT16_TO_STREAM(p, conf->max_transport_latency);
561         UINT24_TO_STREAM(p, conf->pres_delay_min);
562         UINT24_TO_STREAM(p, conf->pres_delay_max);
563         UINT24_TO_STREAM(p, conf->preferred_pres_delay_min);
564         UINT24_TO_STREAM(p, conf->preferred_pres_delay_max);
565 
566         // CodecID:
567         UINT8_TO_STREAM(p, conf->codec_id.coding_format);
568         UINT16_TO_STREAM(p, conf->codec_id.vendor_company_id);
569         UINT16_TO_STREAM(p, conf->codec_id.vendor_codec_id);
570 
571         // Codec Spec. Conf. Length and Data
572         UINT8_TO_STREAM(p, conf->codec_spec_conf.size());
573         memcpy(p, conf->codec_spec_conf.data(), conf->codec_spec_conf.size());
574 
575         LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
576             notif_value.data(), notif_value.size(), ase, device, group);
577       } break;
578 
579       case ascs::kAseStateQoSConfigured: {
580         client_parser::ascs::ase_qos_configured_state_params* conf =
581             static_cast<client_parser::ascs::ase_qos_configured_state_params*>(
582                 new_state_params);
583         std::vector<uint8_t> notif_value(17);
584         auto* p = notif_value.data();
585 
586         // Prepare header
587         UINT8_TO_STREAM(p, ase->id);
588         UINT8_TO_STREAM(p, new_state);
589 
590         UINT8_TO_STREAM(p, conf->cig_id);
591         UINT8_TO_STREAM(p, conf->cis_id);
592         UINT24_TO_STREAM(p, conf->sdu_interval);
593         UINT8_TO_STREAM(p, conf->framing);
594         UINT8_TO_STREAM(p, conf->phy);
595         UINT16_TO_STREAM(p, conf->max_sdu);
596         UINT8_TO_STREAM(p, conf->retrans_nb);
597         UINT16_TO_STREAM(p, conf->max_transport_latency);
598         UINT24_TO_STREAM(p, conf->pres_delay);
599 
600         LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
601             notif_value.data(), notif_value.size(), ase, device, group);
602       } break;
603 
604       case ascs::kAseStateEnabling:
605         // fall-through
606       case ascs::kAseStateStreaming:
607         // fall-through
608       case ascs::kAseStateDisabling: {
609         client_parser::ascs::ase_transient_state_params* params =
610             static_cast<client_parser::ascs::ase_transient_state_params*>(
611                 new_state_params);
612         std::vector<uint8_t> notif_value(5 + params->metadata.size());
613         auto* p = notif_value.data();
614 
615         // Prepare header
616         UINT8_TO_STREAM(p, ase->id);
617         UINT8_TO_STREAM(p, new_state);
618 
619         UINT8_TO_STREAM(p, group->group_id_);
620         UINT8_TO_STREAM(p, ase->cis_id);
621         UINT8_TO_STREAM(p, params->metadata.size());
622         memcpy(p, params->metadata.data(), params->metadata.size());
623 
624         LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
625             notif_value.data(), notif_value.size(), ase, device, group);
626       } break;
627 
628       case ascs::kAseStateReleasing:
629         // fall-through
630       case ascs::kAseStateIdle: {
631         std::vector<uint8_t> notif_value(2);
632         auto* p = notif_value.data();
633 
634         // Prepare header
635         UINT8_TO_STREAM(p, ase->id == types::ase::kAseIdInvalid
636                                ? ++ase_id_last_assigned
637                                : ase->id);
638         UINT8_TO_STREAM(p, new_state);
639 
640         LeAudioGroupStateMachine::Get()->ProcessGattNotifEvent(
641             notif_value.data(), notif_value.size(), ase, device, group);
642       } break;
643 
644       default:
645         break;
646     };
647   }
648 
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 coding_format=codec_specific::kLc3CodingFormat,uint16_t vendor_company_id=0x0000,uint16_t vendor_codec_id=0x0000,std::vector<uint8_t> metadata={})649   static void InsertPacRecord(
650       std::vector<types::acs_ac_record>& recs,
651       uint16_t sampling_frequencies_bitfield,
652       uint8_t supported_frame_durations_bitfield,
653       uint8_t audio_channel_count_bitfield,
654       uint16_t supported_octets_per_codec_frame_min,
655       uint16_t supported_octets_per_codec_frame_max,
656       uint8_t coding_format = codec_specific::kLc3CodingFormat,
657       uint16_t vendor_company_id = 0x0000, uint16_t vendor_codec_id = 0x0000,
658       std::vector<uint8_t> metadata = {}) {
659     recs.push_back({
660         .codec_id =
661             {
662                 .coding_format = coding_format,
663                 .vendor_company_id = vendor_company_id,
664                 .vendor_codec_id = vendor_codec_id,
665             },
666         .codec_spec_caps = types::LeAudioLtvMap({
667             {codec_specific::kCapTypeSupportedSamplingFrequencies,
668              {(uint8_t)(sampling_frequencies_bitfield),
669               (uint8_t)(sampling_frequencies_bitfield >> 8)}},
670             {codec_specific::kCapTypeSupportedFrameDurations,
671              {supported_frame_durations_bitfield}},
672             {codec_specific::kCapTypeAudioChannelCount,
673              {audio_channel_count_bitfield}},
674             {codec_specific::kCapTypeSupportedOctetsPerCodecFrame,
675              {
676                  // Min
677                  (uint8_t)(supported_octets_per_codec_frame_min),
678                  (uint8_t)(supported_octets_per_codec_frame_min >> 8),
679                  // Max
680                  (uint8_t)(supported_octets_per_codec_frame_max),
681                  (uint8_t)(supported_octets_per_codec_frame_max >> 8),
682              }},
683         }),
684         .metadata = std::move(metadata),
685     });
686   }
687 
InjectInitialIdleNotification(LeAudioDeviceGroup * group)688   void InjectInitialIdleNotification(LeAudioDeviceGroup* group) {
689     for (auto* device = group->GetFirstDevice(); device != nullptr;
690          device = group->GetNextDevice(device)) {
691       for (auto& ase : device->ases_) {
692         InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle,
693                                    nullptr);
694       }
695     }
696   }
697 
MultipleTestDevicePrepare(int leaudio_group_id,LeAudioContextType context_type,uint16_t device_cnt,types::AudioContexts update_contexts,bool insert_default_pac_records=true)698   void MultipleTestDevicePrepare(int leaudio_group_id,
699                                  LeAudioContextType context_type,
700                                  uint16_t device_cnt,
701                                  types::AudioContexts update_contexts,
702                                  bool insert_default_pac_records = true) {
703     // Prepare fake connected device group
704     DeviceConnectState initial_connect_state =
705         DeviceConnectState::CONNECTING_BY_USER;
706     int total_devices = device_cnt;
707     le_audio::LeAudioDeviceGroup* group = nullptr;
708 
709     uint8_t num_ase_snk;
710     uint8_t num_ase_src;
711     switch (context_type) {
712       case kContextTypeRingtone:
713         num_ase_snk = 1 + additional_snk_ases;
714         num_ase_src = 0 + additional_src_ases;
715         break;
716 
717       case kContextTypeMedia:
718         num_ase_snk = 2 + additional_snk_ases;
719         num_ase_src = 0 + additional_src_ases;
720         break;
721 
722       case kContextTypeConversational:
723         num_ase_snk = 1 + additional_snk_ases;
724         num_ase_src = 1 + additional_src_ases;
725         break;
726 
727       default:
728         ASSERT_TRUE(false);
729     }
730 
731     while (device_cnt) {
732       auto leAudioDevice = PrepareConnectedDevice(
733           device_cnt--, initial_connect_state, num_ase_snk, num_ase_src);
734 
735       if (insert_default_pac_records) {
736         uint16_t attr_handle = ATTR_HANDLE_PACS_POOL_START;
737 
738         /* As per spec, unspecified shall be supported */
739         auto snk_context_type = kContextTypeUnspecified | update_contexts;
740         auto src_context_type = kContextTypeUnspecified | update_contexts;
741 
742         // Prepare Sink Published Audio Capability records
743         if ((kContextTypeRingtone | kContextTypeMedia |
744              kContextTypeConversational)
745                 .test(context_type)) {
746           // Set target ASE configurations
747           std::vector<types::acs_ac_record> pac_recs;
748 
749           InsertPacRecord(pac_recs, sample_freq_,
750                           codec_specific::kCapFrameDuration10ms |
751                               codec_specific::kCapFrameDuration7p5ms |
752                               codec_specific::kCapFrameDuration10msPreferred,
753                           channel_count_, 30, 120);
754 
755           types::hdl_pair handle_pair;
756           handle_pair.val_hdl = attr_handle++;
757           handle_pair.ccc_hdl = attr_handle++;
758 
759           leAudioDevice->snk_pacs_.emplace_back(
760               std::make_tuple(std::move(handle_pair), pac_recs));
761 
762           snk_context_type.set(static_cast<LeAudioContextType>(context_type));
763           leAudioDevice->snk_audio_locations_ =
764               ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
765               ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
766         }
767 
768         // Prepare Source Published Audio Capability records
769         if (context_type == kContextTypeConversational) {
770           // Set target ASE configurations
771           std::vector<types::acs_ac_record> pac_recs;
772 
773           InsertPacRecord(pac_recs,
774                           codec_specific::kCapSamplingFrequency16000Hz,
775                           codec_specific::kCapFrameDuration10ms |
776                               codec_specific::kCapFrameDuration7p5ms |
777                               codec_specific::kCapFrameDuration10msPreferred,
778                           0b00000001, 30, 120);
779 
780           types::hdl_pair handle_pair;
781           handle_pair.val_hdl = attr_handle++;
782           handle_pair.ccc_hdl = attr_handle++;
783 
784           leAudioDevice->src_pacs_.emplace_back(
785               std::make_tuple(std::move(handle_pair), pac_recs));
786           src_context_type.set(
787               static_cast<LeAudioContextType>(kContextTypeConversational));
788 
789           leAudioDevice->src_audio_locations_ =
790               ::le_audio::codec_spec_conf::kLeAudioLocationFrontLeft |
791               ::le_audio::codec_spec_conf::kLeAudioLocationFrontRight;
792         }
793 
794         leAudioDevice->SetSupportedContexts(snk_context_type, src_context_type);
795         leAudioDevice->SetAvailableContexts(snk_context_type, src_context_type);
796       }
797 
798       group = GroupTheDevice(leaudio_group_id, std::move(leAudioDevice));
799       /* Set the location and direction to the group (done in client.cc)*/
800       group->ReloadAudioLocations();
801       group->ReloadAudioDirections();
802     }
803 
804     /* Stimulate update of available context map */
805     auto types_set = update_contexts.any() ? context_type | update_contexts
806                                            : types::AudioContexts(context_type);
807     group->UpdateAudioContextTypeAvailability(types_set);
808 
809     ASSERT_NE(group, nullptr);
810     ASSERT_EQ(group->Size(), total_devices);
811   }
812 
PrepareSingleTestDeviceGroup(int leaudio_group_id,LeAudioContextType context_type,uint16_t device_cnt=1,types::AudioContexts update_contexts=types::AudioContexts ())813   LeAudioDeviceGroup* PrepareSingleTestDeviceGroup(
814       int leaudio_group_id, LeAudioContextType context_type,
815       uint16_t device_cnt = 1,
816       types::AudioContexts update_contexts = types::AudioContexts()) {
817     MultipleTestDevicePrepare(leaudio_group_id, context_type, device_cnt,
818                               update_contexts);
819     return le_audio_device_groups_.count(leaudio_group_id)
820                ? le_audio_device_groups_[leaudio_group_id].get()
821                : nullptr;
822   }
823 
PrepareConfigureCodecHandler(LeAudioDeviceGroup * group,int verify_ase_count=0,bool caching=false)824   void PrepareConfigureCodecHandler(LeAudioDeviceGroup* group,
825                                     int verify_ase_count = 0,
826                                     bool caching = false) {
827     ase_ctp_handlers[ascs::kAseCtpOpcodeConfigureCodec] =
828         [group, verify_ase_count, caching, this](
829             LeAudioDevice* device, std::vector<uint8_t> value,
830             GATT_WRITE_OP_CB cb, void* cb_data) {
831           auto num_ase = value[1];
832 
833           // Verify ase count if needed
834           if (verify_ase_count) ASSERT_EQ(verify_ase_count, num_ase);
835 
836           // Inject Configured ASE state notification for each requested ASE
837           auto* ase_p = &value[2];
838           for (auto i = 0u; i < num_ase; ++i) {
839             client_parser::ascs::ase_codec_configured_state_params
840                 codec_configured_state_params;
841 
842             /* Check if this is a valid ASE ID  */
843             auto ase_id = *ase_p++;
844             auto it = std::find_if(
845                 device->ases_.begin(), device->ases_.end(),
846                 [ase_id](auto& ase) { return (ase.id == ase_id); });
847             ASSERT_NE(it, device->ases_.end());
848             const auto ase = &(*it);
849 
850             // Skip target latency param
851             ase_p++;
852 
853             codec_configured_state_params.preferred_phy = *ase_p++;
854             codec_configured_state_params.codec_id.coding_format = ase_p[0];
855             codec_configured_state_params.codec_id.vendor_company_id =
856                 (uint16_t)(ase_p[1] << 8 | ase_p[2]),
857             codec_configured_state_params.codec_id.vendor_codec_id =
858                 (uint16_t)(ase_p[3] << 8 | ase_p[4]),
859             ase_p += 5;
860 
861             auto codec_spec_param_len = *ase_p++;
862             auto num_handled_bytes = ase_p - value.data();
863             codec_configured_state_params.codec_spec_conf =
864                 std::vector<uint8_t>(
865                     value.begin() + num_handled_bytes,
866                     value.begin() + num_handled_bytes + codec_spec_param_len);
867             ase_p += codec_spec_param_len;
868 
869             // Some initial QoS settings
870             codec_configured_state_params.framing =
871                 ascs::kAseParamFramingUnframedSupported;
872             codec_configured_state_params.preferred_retrans_nb = 0x04;
873             codec_configured_state_params.max_transport_latency = 0x0010;
874             codec_configured_state_params.pres_delay_min = 0xABABAB;
875             codec_configured_state_params.pres_delay_max = 0xCDCDCD;
876             codec_configured_state_params.preferred_pres_delay_min =
877                 types::kPresDelayNoPreference;
878             codec_configured_state_params.preferred_pres_delay_max =
879                 types::kPresDelayNoPreference;
880 
881             if (caching) {
882               cached_codec_configuration_map_[ase_id] =
883                   codec_configured_state_params;
884             }
885             InjectAseStateNotification(ase, device, group,
886                                        ascs::kAseStateCodecConfigured,
887                                        &codec_configured_state_params);
888           }
889         };
890   }
891 
PrepareConfigureQosHandler(LeAudioDeviceGroup * group,int verify_ase_count=0,bool caching=false)892   void PrepareConfigureQosHandler(LeAudioDeviceGroup* group,
893                                   int verify_ase_count = 0,
894                                   bool caching = false) {
895     ase_ctp_handlers[ascs::kAseCtpOpcodeConfigureQos] =
896         [group, verify_ase_count, caching, this](
897             LeAudioDevice* device, std::vector<uint8_t> value,
898             GATT_WRITE_OP_CB cb, void* cb_data) {
899           auto num_ase = value[1];
900 
901           // Verify ase count if needed
902           if (verify_ase_count) ASSERT_EQ(verify_ase_count, num_ase);
903 
904           // Inject Configured QoS state notification for each requested ASE
905           auto* ase_p = &value[2];
906           for (auto i = 0u; i < num_ase; ++i) {
907             client_parser::ascs::ase_qos_configured_state_params
908                 qos_configured_state_params;
909 
910             /* Check if this is a valid ASE ID  */
911             auto ase_id = *ase_p++;
912             auto it = std::find_if(
913                 device->ases_.begin(), device->ases_.end(),
914                 [ase_id](auto& ase) { return (ase.id == ase_id); });
915             ASSERT_NE(it, device->ases_.end());
916             const auto ase = &(*it);
917 
918             qos_configured_state_params.cig_id = *ase_p++;
919             qos_configured_state_params.cis_id = *ase_p++;
920 
921             qos_configured_state_params.sdu_interval =
922                 (uint32_t)((ase_p[0] << 16) | (ase_p[1] << 8) | ase_p[2]);
923             ase_p += 3;
924 
925             qos_configured_state_params.framing = *ase_p++;
926             qos_configured_state_params.phy = *ase_p++;
927             qos_configured_state_params.max_sdu =
928                 (uint16_t)((ase_p[0] << 8) | ase_p[1]);
929             ase_p += 2;
930 
931             qos_configured_state_params.retrans_nb = *ase_p++;
932             qos_configured_state_params.max_transport_latency =
933                 (uint16_t)((ase_p[0] << 8) | ase_p[1]);
934             ase_p += 2;
935 
936             qos_configured_state_params.pres_delay =
937                 (uint16_t)((ase_p[0] << 16) | (ase_p[1] << 8) | ase_p[2]);
938             ase_p += 3;
939 
940             if (caching) {
941               LOG(INFO) << __func__ << " Device: " << device->address_;
942               if (cached_ase_to_cis_id_map_.count(device->address_) > 0) {
943                 auto ase_list = cached_ase_to_cis_id_map_.at(device->address_);
944                 if (ase_list.count(ase_id) > 0) {
945                   auto cis_id = ase_list.at(ase_id);
946                   ASSERT_EQ(cis_id, qos_configured_state_params.cis_id);
947                 } else {
948                   ase_list[ase_id] = qos_configured_state_params.cis_id;
949                 }
950               } else {
951                 std::map<int, int> ase_map;
952                 ase_map[ase_id] = qos_configured_state_params.cis_id;
953 
954                 cached_ase_to_cis_id_map_[device->address_] = ase_map;
955               }
956             }
957 
958             InjectAseStateNotification(ase, device, group,
959                                        ascs::kAseStateQoSConfigured,
960                                        &qos_configured_state_params);
961           }
962         };
963   }
964 
PrepareEnableHandler(LeAudioDeviceGroup * group,int verify_ase_count=0,bool inject_enabling=true)965   void PrepareEnableHandler(LeAudioDeviceGroup* group, int verify_ase_count = 0,
966                             bool inject_enabling = true) {
967     ase_ctp_handlers[ascs::kAseCtpOpcodeEnable] =
968         [group, verify_ase_count, inject_enabling, this](
969             LeAudioDevice* device, std::vector<uint8_t> value,
970             GATT_WRITE_OP_CB cb, void* cb_data) {
971           auto num_ase = value[1];
972 
973           // Verify ase count if needed
974           if (verify_ase_count) ASSERT_EQ(verify_ase_count, num_ase);
975 
976           // Inject Streaming ASE state notification for each requested ASE
977           auto* ase_p = &value[2];
978           for (auto i = 0u; i < num_ase; ++i) {
979             /* Check if this is a valid ASE ID  */
980             auto ase_id = *ase_p++;
981             auto it = std::find_if(
982                 device->ases_.begin(), device->ases_.end(),
983                 [ase_id](auto& ase) { return (ase.id == ase_id); });
984             ASSERT_NE(it, device->ases_.end());
985             const auto ase = &(*it);
986 
987             auto meta_len = *ase_p++;
988             auto num_handled_bytes = ase_p - value.data();
989             ase_p += meta_len;
990 
991             client_parser::ascs::ase_transient_state_params enable_params = {
992                 .metadata = std::vector<uint8_t>(
993                     value.begin() + num_handled_bytes,
994                     value.begin() + num_handled_bytes + meta_len)};
995 
996             // Server does the 'ReceiverStartReady' on its own - goes to
997             // Streaming, when in Sink role
998             if (ase->direction & le_audio::types::kLeAudioDirectionSink) {
999               if (inject_enabling)
1000                 InjectAseStateNotification(ase, device, group,
1001                                            ascs::kAseStateEnabling,
1002                                            &enable_params);
1003               InjectAseStateNotification(
1004                   ase, device, group, ascs::kAseStateStreaming, &enable_params);
1005             } else {
1006               InjectAseStateNotification(
1007                   ase, device, group, ascs::kAseStateEnabling, &enable_params);
1008             }
1009           }
1010         };
1011   }
1012 
PrepareDisableHandler(LeAudioDeviceGroup * group,int verify_ase_count=0)1013   void PrepareDisableHandler(LeAudioDeviceGroup* group,
1014                              int verify_ase_count = 0) {
1015     ase_ctp_handlers[ascs::kAseCtpOpcodeDisable] =
1016         [group, verify_ase_count, this](LeAudioDevice* device,
1017                                         std::vector<uint8_t> value,
1018                                         GATT_WRITE_OP_CB cb, void* cb_data) {
1019           auto num_ase = value[1];
1020 
1021           // Verify ase count if needed
1022           if (verify_ase_count) ASSERT_EQ(verify_ase_count, num_ase);
1023           ASSERT_EQ(value.size(), 2ul + num_ase);
1024 
1025           // Inject Disabling & QoS Conf. ASE state notification for each ASE
1026           auto* ase_p = &value[2];
1027           for (auto i = 0u; i < num_ase; ++i) {
1028             /* Check if this is a valid ASE ID  */
1029             auto ase_id = *ase_p++;
1030             auto it = std::find_if(
1031                 device->ases_.begin(), device->ases_.end(),
1032                 [ase_id](auto& ase) { return (ase.id == ase_id); });
1033             ASSERT_NE(it, device->ases_.end());
1034             const auto ase = &(*it);
1035 
1036             // The Disabling state is present for Source ASE
1037             if (ase->direction & le_audio::types::kLeAudioDirectionSource) {
1038               client_parser::ascs::ase_transient_state_params disabling_params =
1039                   {.metadata = {}};
1040               InjectAseStateNotification(ase, device, group,
1041                                          ascs::kAseStateDisabling,
1042                                          &disabling_params);
1043             }
1044 
1045             // Server does the 'ReceiverStopReady' on its own - goes to
1046             // Streaming, when in Sink role
1047             if (ase->direction & le_audio::types::kLeAudioDirectionSink) {
1048               // FIXME: For now our fake peer does not remember qos params
1049               client_parser::ascs::ase_qos_configured_state_params
1050                   qos_configured_state_params;
1051               InjectAseStateNotification(ase, device, group,
1052                                          ascs::kAseStateQoSConfigured,
1053                                          &qos_configured_state_params);
1054             }
1055           }
1056         };
1057   }
1058 
PrepareReceiverStartReady(LeAudioDeviceGroup * group,int verify_ase_count=0)1059   void PrepareReceiverStartReady(LeAudioDeviceGroup* group,
1060                                  int verify_ase_count = 0) {
1061     ase_ctp_handlers[ascs::kAseCtpOpcodeReceiverStartReady] =
1062         [group, verify_ase_count, this](LeAudioDevice* device,
1063                                         std::vector<uint8_t> value,
1064                                         GATT_WRITE_OP_CB cb, void* cb_data) {
1065           auto num_ase = value[1];
1066 
1067           // Verify ase count if needed
1068           if (verify_ase_count) ASSERT_EQ(verify_ase_count, num_ase);
1069 
1070           // Inject Streaming ASE state notification for each Source ASE
1071           auto* ase_p = &value[2];
1072           for (auto i = 0u; i < num_ase; ++i) {
1073             /* Check if this is a valid ASE ID  */
1074             auto ase_id = *ase_p++;
1075             auto it = std::find_if(
1076                 device->ases_.begin(), device->ases_.end(),
1077                 [ase_id](auto& ase) { return (ase.id == ase_id); });
1078             ASSERT_NE(it, device->ases_.end());
1079 
1080             // Once we did the 'ReceiverStartReady' the server goes to
1081             // Streaming, when in Source role
1082             auto meta_len = *ase_p++;
1083             auto num_handled_bytes = ase_p - value.data();
1084             ase_p += num_handled_bytes;
1085 
1086             const auto& ase = &(*it);
1087             client_parser::ascs::ase_transient_state_params enable_params = {
1088                 .metadata = std::vector<uint8_t>(
1089                     value.begin() + num_handled_bytes,
1090                     value.begin() + num_handled_bytes + meta_len)};
1091             InjectAseStateNotification(
1092                 ase, device, group, ascs::kAseStateStreaming, &enable_params);
1093           }
1094         };
1095   }
1096 
PrepareReceiverStopReady(LeAudioDeviceGroup * group,int verify_ase_count=0)1097   void PrepareReceiverStopReady(LeAudioDeviceGroup* group,
1098                                 int verify_ase_count = 0) {
1099     ase_ctp_handlers[ascs::kAseCtpOpcodeReceiverStopReady] =
1100         [group, verify_ase_count, this](LeAudioDevice* device,
1101                                         std::vector<uint8_t> value,
1102                                         GATT_WRITE_OP_CB cb, void* cb_data) {
1103           auto num_ase = value[1];
1104 
1105           // Verify ase count if needed
1106           if (verify_ase_count) ASSERT_EQ(verify_ase_count, num_ase);
1107 
1108           // Inject QoS configured ASE state notification for each Source ASE
1109           auto* ase_p = &value[2];
1110           for (auto i = 0u; i < num_ase; ++i) {
1111             /* Check if this is a valid ASE ID  */
1112             auto ase_id = *ase_p++;
1113             auto it = std::find_if(
1114                 device->ases_.begin(), device->ases_.end(),
1115                 [ase_id](auto& ase) { return (ase.id == ase_id); });
1116             ASSERT_NE(it, device->ases_.end());
1117 
1118             const auto& ase = &(*it);
1119 
1120             // FIXME: For now our fake peer does not remember qos params
1121             client_parser::ascs::ase_qos_configured_state_params
1122                 qos_configured_state_params;
1123             InjectAseStateNotification(ase, device, group,
1124                                        ascs::kAseStateQoSConfigured,
1125                                        &qos_configured_state_params);
1126           }
1127         };
1128   }
1129 
PrepareReleaseHandler(LeAudioDeviceGroup * group,int verify_ase_count=0)1130   void PrepareReleaseHandler(LeAudioDeviceGroup* group,
1131                              int verify_ase_count = 0) {
1132     ase_ctp_handlers[ascs::kAseCtpOpcodeRelease] =
1133         [group, verify_ase_count, this](LeAudioDevice* device,
1134                                         std::vector<uint8_t> value,
1135                                         GATT_WRITE_OP_CB cb, void* cb_data) {
1136           auto num_ase = value[1];
1137 
1138           // Verify ase count if needed
1139           if (verify_ase_count) ASSERT_EQ(verify_ase_count, num_ase);
1140           ASSERT_EQ(value.size(), 2ul + num_ase);
1141 
1142           // Inject Releasing & Idle ASE state notification for each ASE
1143           auto* ase_p = &value[2];
1144           for (auto i = 0u; i < num_ase; ++i) {
1145             /* Check if this is a valid ASE ID  */
1146             auto ase_id = *ase_p++;
1147             auto it = std::find_if(
1148                 device->ases_.begin(), device->ases_.end(),
1149                 [ase_id](auto& ase) { return (ase.id == ase_id); });
1150             ASSERT_NE(it, device->ases_.end());
1151             const auto ase = &(*it);
1152 
1153             InjectAseStateNotification(ase, device, group,
1154                                        ascs::kAseStateReleasing, nullptr);
1155 
1156             /* Check if codec configuration is cached */
1157             if (cached_codec_configuration_map_.count(ase_id) > 0) {
1158               InjectAseStateNotification(
1159                   ase, device, group, ascs::kAseStateCodecConfigured,
1160                   &cached_codec_configuration_map_[ase_id]);
1161             } else {
1162               // Release - no caching
1163               InjectAseStateNotification(ase, device, group,
1164                                          ascs::kAseStateIdle, nullptr);
1165             }
1166           }
1167         };
1168   }
1169 
1170   MockCsisClient mock_csis_client_module_;
1171   NiceMock<controller::MockControllerInterface> mock_controller_;
1172   NiceMock<bluetooth::manager::MockBtmInterface> btm_interface;
1173   gatt::MockBtaGattInterface gatt_interface;
1174   gatt::MockBtaGattQueue gatt_queue;
1175 
1176   bluetooth::hci::IsoManager* iso_manager_;
1177   MockIsoManager* mock_iso_manager_;
1178   le_audio::CodecManager* codec_manager_;
1179   MockCodecManager* mock_codec_manager_;
1180 
1181   std::function<void(LeAudioDevice* device, std::vector<uint8_t> value,
1182                      GATT_WRITE_OP_CB cb, void* cb_data)>
1183       ase_ctp_handlers[ascs::kAseCtpOpcodeMaxVal + 1] = {nullptr};
1184   std::map<int, client_parser::ascs::ase_codec_configured_state_params>
1185       cached_codec_configuration_map_;
1186 
1187   std::map<RawAddress, std::map<int, int>> cached_ase_to_cis_id_map_;
1188 
1189   MockLeAudioGroupStateMachineCallbacks mock_callbacks_;
1190   std::vector<std::shared_ptr<LeAudioDevice>> le_audio_devices_;
1191   std::vector<RawAddress> addresses_;
1192   std::map<uint8_t, std::unique_ptr<LeAudioDeviceGroup>>
1193       le_audio_device_groups_;
1194   bool group_create_command_disallowed_ = false;
1195 };
1196 
TEST_F(StateMachineTest,testInit)1197 TEST_F(StateMachineTest, testInit) {
1198   ASSERT_NE(LeAudioGroupStateMachine::Get(), nullptr);
1199 }
1200 
TEST_F(StateMachineTest,testCleanup)1201 TEST_F(StateMachineTest, testCleanup) {
1202   ASSERT_NE(LeAudioGroupStateMachine::Get(), nullptr);
1203   LeAudioGroupStateMachine::Cleanup();
1204   EXPECT_DEATH(LeAudioGroupStateMachine::Get(), "");
1205 }
1206 
TEST_F(StateMachineTest,testConfigureCodecSingle)1207 TEST_F(StateMachineTest, testConfigureCodecSingle) {
1208   /* Device is banded headphones with 1x snk + 0x src ase
1209    * (1xunidirectional CIS) with channel count 2 (for stereo
1210    */
1211   const auto context_type = kContextTypeRingtone;
1212   const int leaudio_group_id = 2;
1213   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
1214                    kLeAudioCodecLC3ChannelCountTwoChannel;
1215 
1216   // Prepare fake connected device group
1217   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1218 
1219   /* Since we prepared device with Ringtone context in mind, only one ASE
1220    * should have been configured.
1221    */
1222   auto* leAudioDevice = group->GetFirstDevice();
1223   PrepareConfigureCodecHandler(group, 1);
1224 
1225   /* Start the configuration and stream Media content.
1226    * Expect 1 time for the Codec Config call only. */
1227   EXPECT_CALL(gatt_queue,
1228               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
1229                                   GATT_WRITE_NO_RSP, _, _))
1230       .Times(1);
1231 
1232   /* Do nothing on the CigCreate, so the state machine stays in the configure
1233    * state */
1234   ON_CALL(*mock_iso_manager_, CreateCig).WillByDefault(Return());
1235   EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(1);
1236 
1237   InjectInitialIdleNotification(group);
1238 
1239   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1240       group, static_cast<LeAudioContextType>(context_type),
1241       types::AudioContexts(context_type)));
1242 
1243   // Check if group has transitioned to a proper state
1244   ASSERT_EQ(group->GetState(),
1245             types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
1246 
1247   /* Cancel is called when group goes to streaming. */
1248   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
1249 }
1250 
TEST_F(StateMachineTest,testConfigureCodecMulti)1251 TEST_F(StateMachineTest, testConfigureCodecMulti) {
1252   const auto context_type = kContextTypeMedia;
1253   const auto leaudio_group_id = 2;
1254   const auto num_devices = 2;
1255 
1256   // Prepare multiple fake connected devices in a group
1257   auto* group =
1258       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
1259   ASSERT_EQ(group->Size(), num_devices);
1260 
1261   PrepareConfigureCodecHandler(group);
1262 
1263   auto expected_devices_written = 0;
1264   auto* leAudioDevice = group->GetFirstDevice();
1265   while (leAudioDevice) {
1266     EXPECT_CALL(gatt_queue,
1267                 WriteCharacteristic(leAudioDevice->conn_id_,
1268                                     leAudioDevice->ctp_hdls_.val_hdl, _,
1269                                     GATT_WRITE_NO_RSP, _, _))
1270         .Times(AtLeast(1));
1271     expected_devices_written++;
1272     leAudioDevice = group->GetNextDevice(leAudioDevice);
1273   }
1274   ASSERT_EQ(expected_devices_written, num_devices);
1275 
1276   InjectInitialIdleNotification(group);
1277 
1278   /* Do nothing on the CigCreate, so the state machine stays in the configure
1279    * state */
1280   ON_CALL(*mock_iso_manager_, CreateCig).WillByDefault(Return());
1281   EXPECT_CALL(*mock_iso_manager_, CreateCig).Times(1);
1282 
1283   // Start the configuration and stream the content
1284   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1285       group, static_cast<LeAudioContextType>(context_type),
1286       types::AudioContexts(context_type)));
1287 
1288   // Check if group has transitioned to a proper state
1289   ASSERT_EQ(group->GetState(),
1290             types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
1291 
1292   /* Cancel is called when group goes to streaming. */
1293   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
1294 }
1295 
TEST_F(StateMachineTest,testConfigureQosSingle)1296 TEST_F(StateMachineTest, testConfigureQosSingle) {
1297   /* Device is banded headphones with 2x snk + 1x src ase
1298    * (1x bidirectional + 1xunidirectional CIS)
1299    */
1300   additional_snk_ases = 1;
1301   additional_src_ases = 1;
1302   const auto context_type = kContextTypeRingtone;
1303   const int leaudio_group_id = 3;
1304 
1305   // Prepare fake connected device group
1306   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1307 
1308   /* Since we prepared device with Ringtone context in mind, only one ASE
1309    * should have been configured.
1310    */
1311   auto* leAudioDevice = group->GetFirstDevice();
1312   PrepareConfigureCodecHandler(group, 2);
1313   PrepareConfigureQosHandler(group, 2);
1314 
1315   // Start the configuration and stream Media content
1316   EXPECT_CALL(gatt_queue,
1317               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
1318                                   GATT_WRITE_NO_RSP, _, _))
1319       .Times(3);
1320 
1321   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1322   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
1323   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
1324   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1325   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1326   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1327 
1328   InjectInitialIdleNotification(group);
1329 
1330   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1331       group, context_type, types::AudioContexts(context_type)));
1332 
1333   // Check if group has transitioned to a proper state
1334   ASSERT_EQ(group->GetState(),
1335             types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1336 
1337   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
1338 }
1339 
TEST_F(StateMachineTest,testConfigureQosSingleRecoverCig)1340 TEST_F(StateMachineTest, testConfigureQosSingleRecoverCig) {
1341   /* Device is banded headphones with 2x snk + 1x src ase
1342    * (1x bidirectional + 1xunidirectional CIS)
1343    */
1344   additional_snk_ases = 1;
1345   additional_src_ases = 1;
1346   const auto context_type = kContextTypeRingtone;
1347   const int leaudio_group_id = 3;
1348 
1349   /* Assume that on previous BT OFF CIG was not removed */
1350   group_create_command_disallowed_ = true;
1351 
1352   // Prepare fake connected device group
1353   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1354 
1355   /* Since we prepared device with Ringtone context in mind, only one ASE
1356    * should have been configured.
1357    */
1358   auto* leAudioDevice = group->GetFirstDevice();
1359   PrepareConfigureCodecHandler(group, 2);
1360   PrepareConfigureQosHandler(group, 2);
1361 
1362   // Start the configuration and stream Media content
1363   EXPECT_CALL(gatt_queue,
1364               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
1365                                   GATT_WRITE_NO_RSP, _, _))
1366       .Times(3);
1367 
1368   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(2);
1369   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
1370   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
1371   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
1372   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1373   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1374 
1375   InjectInitialIdleNotification(group);
1376 
1377   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1378       group, static_cast<LeAudioContextType>(context_type),
1379       types::AudioContexts(context_type)));
1380 
1381   // Check if group has transitioned to a proper state
1382   ASSERT_EQ(group->GetState(),
1383             types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1384   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
1385 }
1386 
TEST_F(StateMachineTest,testConfigureQosMultiple)1387 TEST_F(StateMachineTest, testConfigureQosMultiple) {
1388   const auto context_type = kContextTypeMedia;
1389   const auto leaudio_group_id = 3;
1390   const auto num_devices = 2;
1391 
1392   // Prepare multiple fake connected devices in a group
1393   auto* group =
1394       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
1395   ASSERT_EQ(group->Size(), num_devices);
1396 
1397   PrepareConfigureCodecHandler(group);
1398   PrepareConfigureQosHandler(group);
1399 
1400   auto* leAudioDevice = group->GetFirstDevice();
1401   auto expected_devices_written = 0;
1402   while (leAudioDevice) {
1403     EXPECT_CALL(gatt_queue,
1404                 WriteCharacteristic(leAudioDevice->conn_id_,
1405                                     leAudioDevice->ctp_hdls_.val_hdl, _,
1406                                     GATT_WRITE_NO_RSP, _, _))
1407         .Times(AtLeast(2));
1408     expected_devices_written++;
1409     leAudioDevice = group->GetNextDevice(leAudioDevice);
1410   }
1411   ASSERT_EQ(expected_devices_written, num_devices);
1412 
1413   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1414   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
1415   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
1416   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1417   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1418   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1419 
1420   InjectInitialIdleNotification(group);
1421 
1422   // Start the configuration and stream Media content
1423   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1424       group, static_cast<LeAudioContextType>(context_type),
1425       types::AudioContexts(context_type)));
1426 
1427   // Check if group has transitioned to a proper state
1428   ASSERT_EQ(group->GetState(),
1429             types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1430   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
1431 }
1432 
TEST_F(StateMachineTest,testStreamSingle)1433 TEST_F(StateMachineTest, testStreamSingle) {
1434   /* Device is banded headphones with 1x snk + 0x src ase
1435    * (1xunidirectional CIS) with channel count 2 (for stereo
1436    */
1437   const auto context_type = kContextTypeRingtone;
1438   const int leaudio_group_id = 4;
1439   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
1440                    kLeAudioCodecLC3ChannelCountTwoChannel;
1441 
1442   // Prepare fake connected device group
1443   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1444 
1445   /* Ringtone with channel count 1 for single device and 1 ASE sink will
1446    * end up with 1 Sink ASE being configured.
1447    */
1448   PrepareConfigureCodecHandler(group, 1);
1449   PrepareConfigureQosHandler(group, 1);
1450   PrepareEnableHandler(group, 1);
1451 
1452   auto* leAudioDevice = group->GetFirstDevice();
1453   EXPECT_CALL(gatt_queue,
1454               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
1455                                   GATT_WRITE_NO_RSP, _, _))
1456       .Times(3);
1457 
1458   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1459   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
1460   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
1461   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1462   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1463   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1464 
1465   InjectInitialIdleNotification(group);
1466 
1467   // Validate GroupStreamStatus
1468   EXPECT_CALL(
1469       mock_callbacks_,
1470       StatusReportCb(leaudio_group_id,
1471                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
1472 
1473   // Start the configuration and stream Media content
1474   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1475       group, static_cast<LeAudioContextType>(context_type),
1476       types::AudioContexts(context_type)));
1477 
1478   // Check if group has transitioned to a proper state
1479   ASSERT_EQ(group->GetState(),
1480             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1481   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1482 }
1483 
TEST_F(StateMachineTest,testStreamSkipEnablingSink)1484 TEST_F(StateMachineTest, testStreamSkipEnablingSink) {
1485   /* Device is banded headphones with 2x snk + none src ase
1486    * (2x unidirectional CIS)
1487    */
1488   const auto context_type = kContextTypeMedia;
1489   const int leaudio_group_id = 4;
1490 
1491   // Prepare fake connected device group
1492   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1493 
1494   /* For Media context type with channel count 1 and two ASEs,
1495    * there should have be 2 Ases configured configured.
1496    */
1497   PrepareConfigureCodecHandler(group, 2);
1498   PrepareConfigureQosHandler(group, 2);
1499   PrepareEnableHandler(group, 2, false);
1500 
1501   auto* leAudioDevice = group->GetFirstDevice();
1502   EXPECT_CALL(gatt_queue,
1503               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
1504                                   GATT_WRITE_NO_RSP, _, _))
1505       .Times(3);
1506 
1507   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1508   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
1509   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
1510   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1511   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1512   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1513 
1514   InjectInitialIdleNotification(group);
1515 
1516   // Validate GroupStreamStatus
1517   EXPECT_CALL(
1518       mock_callbacks_,
1519       StatusReportCb(leaudio_group_id,
1520                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
1521 
1522   // Start the configuration and stream Media content
1523   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1524       group, static_cast<LeAudioContextType>(context_type),
1525       types::AudioContexts(context_type)));
1526 
1527   // Check if group has transitioned to a proper state
1528   ASSERT_EQ(group->GetState(),
1529             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1530 
1531   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1532 }
1533 
TEST_F(StateMachineTest,testStreamSkipEnablingSinkSource)1534 TEST_F(StateMachineTest, testStreamSkipEnablingSinkSource) {
1535   /* Device is banded headphones with 2x snk + 1x src ase
1536    * (1x bidirectional CIS)
1537    */
1538   const auto context_type = kContextTypeConversational;
1539   const int leaudio_group_id = 4;
1540 
1541   additional_snk_ases = 1;
1542 
1543   // Prepare fake connected device group
1544   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1545 
1546   /* Since we prepared device with Conversional context in mind,
1547    * 2 Sink ASEs and 1 Source ASE should have been configured.
1548    */
1549   PrepareConfigureCodecHandler(group, 3);
1550   PrepareConfigureQosHandler(group, 3);
1551   PrepareEnableHandler(group, 3, false);
1552   PrepareReceiverStartReady(group, 1);
1553 
1554   auto* leAudioDevice = group->GetFirstDevice();
1555   EXPECT_CALL(gatt_queue,
1556               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
1557                                   GATT_WRITE_NO_RSP, _, _))
1558       .Times(4);
1559 
1560   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1561   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
1562   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
1563   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1564   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1565   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1566 
1567   InjectInitialIdleNotification(group);
1568 
1569   // Validate GroupStreamStatus
1570   EXPECT_CALL(
1571       mock_callbacks_,
1572       StatusReportCb(leaudio_group_id,
1573                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
1574 
1575   // Start the configuration and stream Media content
1576   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1577       group, static_cast<LeAudioContextType>(context_type),
1578       types::AudioContexts(context_type)));
1579 
1580   // Check if group has transitioned to a proper state
1581   ASSERT_EQ(group->GetState(),
1582             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1583   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1584 }
1585 
TEST_F(StateMachineTest,testStreamMultipleConversational)1586 TEST_F(StateMachineTest, testStreamMultipleConversational) {
1587   const auto context_type = kContextTypeConversational;
1588   const auto leaudio_group_id = 4;
1589   const auto num_devices = 2;
1590 
1591   // Prepare multiple fake connected devices in a group
1592   auto* group =
1593       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
1594   ASSERT_EQ(group->Size(), num_devices);
1595 
1596   PrepareConfigureCodecHandler(group);
1597   PrepareConfigureQosHandler(group);
1598   PrepareEnableHandler(group);
1599   PrepareReceiverStartReady(group);
1600 
1601   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1602   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
1603   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
1604   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1605   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1606   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1607 
1608   InjectInitialIdleNotification(group);
1609 
1610   auto* leAudioDevice = group->GetFirstDevice();
1611   auto expected_devices_written = 0;
1612   while (leAudioDevice) {
1613     EXPECT_CALL(gatt_queue,
1614                 WriteCharacteristic(leAudioDevice->conn_id_,
1615                                     leAudioDevice->ctp_hdls_.val_hdl, _,
1616                                     GATT_WRITE_NO_RSP, _, _))
1617         .Times(4);
1618     expected_devices_written++;
1619     leAudioDevice = group->GetNextDevice(leAudioDevice);
1620   }
1621   ASSERT_EQ(expected_devices_written, num_devices);
1622 
1623   // Validate GroupStreamStatus
1624   EXPECT_CALL(
1625       mock_callbacks_,
1626       StatusReportCb(leaudio_group_id,
1627                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
1628 
1629   // Start the configuration and stream Media content
1630   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1631       group, static_cast<LeAudioContextType>(context_type),
1632       types::AudioContexts(context_type)));
1633 
1634   // Check if group has transitioned to a proper state
1635   ASSERT_EQ(group->GetState(),
1636             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1637   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1638 }
1639 
TEST_F(StateMachineTest,testStreamMultiple)1640 TEST_F(StateMachineTest, testStreamMultiple) {
1641   const auto context_type = kContextTypeMedia;
1642   const auto leaudio_group_id = 4;
1643   const auto num_devices = 2;
1644 
1645   // Prepare multiple fake connected devices in a group
1646   auto* group =
1647       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
1648   ASSERT_EQ(group->Size(), num_devices);
1649 
1650   PrepareConfigureCodecHandler(group);
1651   PrepareConfigureQosHandler(group);
1652   PrepareEnableHandler(group);
1653 
1654   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1655   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
1656   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
1657   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1658   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1659   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1660 
1661   InjectInitialIdleNotification(group);
1662 
1663   auto* leAudioDevice = group->GetFirstDevice();
1664   auto expected_devices_written = 0;
1665   while (leAudioDevice) {
1666     EXPECT_CALL(gatt_queue,
1667                 WriteCharacteristic(leAudioDevice->conn_id_,
1668                                     leAudioDevice->ctp_hdls_.val_hdl, _,
1669                                     GATT_WRITE_NO_RSP, _, _))
1670         .Times(AtLeast(3));
1671     expected_devices_written++;
1672     leAudioDevice = group->GetNextDevice(leAudioDevice);
1673   }
1674   ASSERT_EQ(expected_devices_written, num_devices);
1675 
1676   // Validate GroupStreamStatus
1677   EXPECT_CALL(
1678       mock_callbacks_,
1679       StatusReportCb(leaudio_group_id,
1680                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
1681 
1682   // Start the configuration and stream Media content
1683   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1684       group, static_cast<LeAudioContextType>(context_type),
1685       types::AudioContexts(context_type)));
1686 
1687   // Check if group has transitioned to a proper state
1688   ASSERT_EQ(group->GetState(),
1689             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1690   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1691 }
1692 
TEST_F(StateMachineTest,testUpdateMetadataMultiple)1693 TEST_F(StateMachineTest, testUpdateMetadataMultiple) {
1694   const auto context_type = kContextTypeMedia;
1695   const auto leaudio_group_id = 4;
1696   const auto num_devices = 2;
1697 
1698   // Prepare multiple fake connected devices in a group
1699   auto* group =
1700       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
1701   ASSERT_EQ(group->Size(), num_devices);
1702 
1703   PrepareConfigureCodecHandler(group);
1704   PrepareConfigureQosHandler(group);
1705   PrepareEnableHandler(group);
1706 
1707   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1708   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(AtLeast(1));
1709   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
1710   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
1711   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
1712   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1713 
1714   InjectInitialIdleNotification(group);
1715 
1716   auto* leAudioDevice = group->GetFirstDevice();
1717   auto expected_devices_written = 0;
1718   while (leAudioDevice) {
1719     EXPECT_CALL(gatt_queue,
1720                 WriteCharacteristic(leAudioDevice->conn_id_,
1721                                     leAudioDevice->ctp_hdls_.val_hdl, _,
1722                                     GATT_WRITE_NO_RSP, _, _))
1723         .Times(AtLeast(3));
1724     expected_devices_written++;
1725     leAudioDevice = group->GetNextDevice(leAudioDevice);
1726   }
1727   ASSERT_EQ(expected_devices_written, num_devices);
1728 
1729   // Validate GroupStreamStatus
1730   EXPECT_CALL(
1731       mock_callbacks_,
1732       StatusReportCb(leaudio_group_id,
1733                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
1734 
1735   // Start the configuration and stream Media content
1736   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1737       group, static_cast<LeAudioContextType>(context_type),
1738       types::AudioContexts(context_type)));
1739 
1740   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
1741 
1742   // Check if group has transitioned to a proper state
1743   ASSERT_EQ(group->GetState(),
1744             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1745 
1746   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1747   mock_function_count_map["alarm_cancel"] = 0;
1748 
1749   // Make sure all devices get the metadata update
1750   leAudioDevice = group->GetFirstDevice();
1751   expected_devices_written = 0;
1752   while (leAudioDevice) {
1753     EXPECT_CALL(gatt_queue,
1754                 WriteCharacteristic(leAudioDevice->conn_id_,
1755                                     leAudioDevice->ctp_hdls_.val_hdl, _,
1756                                     GATT_WRITE_NO_RSP, _, _))
1757         .Times(1);
1758     expected_devices_written++;
1759     leAudioDevice = group->GetNextDevice(leAudioDevice);
1760   }
1761   ASSERT_EQ(expected_devices_written, num_devices);
1762 
1763   const auto metadata_context_type =
1764       kContextTypeMedia | kContextTypeSoundEffects;
1765   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
1766       group, static_cast<LeAudioContextType>(context_type),
1767       metadata_context_type));
1768 
1769   /* This is just update metadata - watchdog is not used */
1770   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
1771 }
1772 
TEST_F(StateMachineTest,testDisableSingle)1773 TEST_F(StateMachineTest, testDisableSingle) {
1774   /* Device is banded headphones with 2x snk + 0x src ase
1775    * (2xunidirectional CIS)
1776    */
1777   additional_snk_ases = 1;
1778   const auto context_type = kContextTypeRingtone;
1779   const int leaudio_group_id = 4;
1780 
1781   // Prepare fake connected device group
1782   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1783 
1784   /* Ringtone context plus additional ASE with channel count 1
1785    * gives us 2 ASE which should have been configured.
1786    */
1787   PrepareConfigureCodecHandler(group, 2);
1788   PrepareConfigureQosHandler(group, 2);
1789   PrepareEnableHandler(group, 2);
1790   PrepareDisableHandler(group, 2);
1791 
1792   auto* leAudioDevice = group->GetFirstDevice();
1793   EXPECT_CALL(gatt_queue,
1794               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
1795                                   GATT_WRITE_NO_RSP, _, _))
1796       .Times(4);
1797 
1798   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1799   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
1800   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
1801   EXPECT_CALL(
1802       *mock_iso_manager_,
1803       RemoveIsoDataPath(
1804           _, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput))
1805       .Times(2);
1806   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
1807   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1808 
1809   InjectInitialIdleNotification(group);
1810 
1811   EXPECT_CALL(
1812       mock_callbacks_,
1813       StatusReportCb(leaudio_group_id,
1814                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
1815 
1816   // Start the configuration and stream Media content
1817   LeAudioGroupStateMachine::Get()->StartStream(
1818       group, static_cast<LeAudioContextType>(context_type),
1819       types::AudioContexts(context_type));
1820 
1821   // Check if group has transitioned to a proper state
1822   ASSERT_EQ(group->GetState(),
1823             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1824 
1825   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
1826   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1827   mock_function_count_map["alarm_cancel"] = 0;
1828 
1829   // Validate GroupStreamStatus
1830   EXPECT_CALL(
1831       mock_callbacks_,
1832       StatusReportCb(leaudio_group_id,
1833                      bluetooth::le_audio::GroupStreamStatus::SUSPENDING));
1834   EXPECT_CALL(
1835       mock_callbacks_,
1836       StatusReportCb(leaudio_group_id,
1837                      bluetooth::le_audio::GroupStreamStatus::SUSPENDED));
1838 
1839   // Suspend the stream
1840   LeAudioGroupStateMachine::Get()->SuspendStream(group);
1841 
1842   // Check if group has transition to a proper state
1843   ASSERT_EQ(group->GetState(),
1844             types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1845 
1846   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
1847   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1848 }
1849 
TEST_F(StateMachineTest,testDisableMultiple)1850 TEST_F(StateMachineTest, testDisableMultiple) {
1851   const auto context_type = kContextTypeMedia;
1852   const auto leaudio_group_id = 4;
1853   const auto num_devices = 2;
1854 
1855   // Prepare multiple fake connected devices in a group
1856   auto* group =
1857       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
1858   ASSERT_EQ(group->Size(), num_devices);
1859 
1860   PrepareConfigureCodecHandler(group);
1861   PrepareConfigureQosHandler(group);
1862   PrepareEnableHandler(group);
1863   PrepareDisableHandler(group);
1864 
1865   auto* leAudioDevice = group->GetFirstDevice();
1866   auto expected_devices_written = 0;
1867   while (leAudioDevice) {
1868     EXPECT_CALL(gatt_queue,
1869                 WriteCharacteristic(leAudioDevice->conn_id_,
1870                                     leAudioDevice->ctp_hdls_.val_hdl, _,
1871                                     GATT_WRITE_NO_RSP, _, _))
1872         .Times(AtLeast(4));
1873     expected_devices_written++;
1874     leAudioDevice = group->GetNextDevice(leAudioDevice);
1875   }
1876   ASSERT_EQ(expected_devices_written, num_devices);
1877 
1878   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1879   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
1880   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
1881   EXPECT_CALL(
1882       *mock_iso_manager_,
1883       RemoveIsoDataPath(
1884           _, bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput))
1885       .Times(2);
1886   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
1887   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1888 
1889   InjectInitialIdleNotification(group);
1890 
1891   // Start the configuration and stream Media content
1892   LeAudioGroupStateMachine::Get()->StartStream(
1893       group, static_cast<LeAudioContextType>(context_type),
1894       types::AudioContexts(context_type));
1895 
1896   // Check if group has transitioned to a proper state
1897   ASSERT_EQ(group->GetState(),
1898             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
1899   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1900   mock_function_count_map["alarm_cancel"] = 0;
1901 
1902   // Validate GroupStreamStatus
1903   EXPECT_CALL(
1904       mock_callbacks_,
1905       StatusReportCb(leaudio_group_id,
1906                      bluetooth::le_audio::GroupStreamStatus::SUSPENDING));
1907   EXPECT_CALL(
1908       mock_callbacks_,
1909       StatusReportCb(leaudio_group_id,
1910                      bluetooth::le_audio::GroupStreamStatus::SUSPENDED));
1911 
1912   // Suspend the stream
1913   LeAudioGroupStateMachine::Get()->SuspendStream(group);
1914 
1915   // Check if group has transitioned to a proper state
1916   ASSERT_EQ(group->GetState(),
1917             types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
1918   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
1919   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
1920 }
1921 
TEST_F(StateMachineTest,testDisableBidirectional)1922 TEST_F(StateMachineTest, testDisableBidirectional) {
1923   /* Device is banded headphones with 2x snk + 1x src ase
1924    * (1x bidirectional + 1xunidirectional CIS)
1925    */
1926   additional_snk_ases = 1;
1927   const auto context_type = kContextTypeConversational;
1928   const int leaudio_group_id = 4;
1929 
1930   // Prepare fake connected device group
1931   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
1932 
1933   /* Since we prepared device with Conversional context in mind, Sink and Source
1934    * ASEs should have been configured.
1935    */
1936   PrepareConfigureCodecHandler(group, 3);
1937   PrepareConfigureQosHandler(group, 3);
1938   PrepareEnableHandler(group, 3);
1939   PrepareDisableHandler(group, 3);
1940   PrepareReceiverStartReady(group, 1);
1941   PrepareReceiverStopReady(group, 1);
1942 
1943   auto* leAudioDevice = group->GetFirstDevice();
1944   EXPECT_CALL(gatt_queue,
1945               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
1946                                   GATT_WRITE_NO_RSP, _, _))
1947       .Times(AtLeast(4));
1948 
1949   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
1950   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
1951   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
1952   bool removed_bidirectional = false;
1953   bool removed_unidirectional = false;
1954 
1955   /* Check data path removal */
1956   ON_CALL(*mock_iso_manager_, RemoveIsoDataPath)
1957       .WillByDefault(Invoke([&removed_bidirectional, &removed_unidirectional,
1958                              this](uint16_t conn_handle,
1959                                    uint8_t data_path_dir) {
1960         /* Set flags for verification */
1961         if (data_path_dir ==
1962             (bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput |
1963              bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput)) {
1964           removed_bidirectional = true;
1965         } else if (data_path_dir == bluetooth::hci::iso_manager::
1966                                         kRemoveIsoDataPathDirectionInput) {
1967           removed_unidirectional = true;
1968         }
1969 
1970         /* Copied from default handler of RemoveIsoDataPath*/
1971         auto dev_it =
1972             std::find_if(le_audio_devices_.begin(), le_audio_devices_.end(),
1973                          [&conn_handle](auto& dev) {
1974                            auto ases = dev->GetAsesByCisConnHdl(conn_handle);
1975                            return (ases.sink || ases.source);
1976                          });
1977         if (dev_it == le_audio_devices_.end()) {
1978           return;
1979         }
1980 
1981         for (auto& kv_pair : le_audio_device_groups_) {
1982           auto& group = kv_pair.second;
1983           if (group->IsDeviceInTheGroup(dev_it->get())) {
1984             LeAudioGroupStateMachine::Get()->ProcessHciNotifRemoveIsoDataPath(
1985                 group.get(), dev_it->get(), 0, conn_handle);
1986             return;
1987           }
1988         }
1989         /* End of copy */
1990       }));
1991 
1992   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
1993   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
1994 
1995   // Start the configuration and stream Media content
1996   LeAudioGroupStateMachine::Get()->StartStream(
1997       group, static_cast<LeAudioContextType>(context_type),
1998       types::AudioContexts(context_type));
1999 
2000   // Check if group has transitioned to a proper state
2001   ASSERT_EQ(group->GetState(),
2002             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2003 
2004   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2005   mock_function_count_map["alarm_cancel"] = 0;
2006 
2007   // Validate GroupStreamStatus
2008   EXPECT_CALL(
2009       mock_callbacks_,
2010       StatusReportCb(leaudio_group_id,
2011                      bluetooth::le_audio::GroupStreamStatus::SUSPENDING));
2012   EXPECT_CALL(
2013       mock_callbacks_,
2014       StatusReportCb(leaudio_group_id,
2015                      bluetooth::le_audio::GroupStreamStatus::SUSPENDED));
2016 
2017   // Suspend the stream
2018   LeAudioGroupStateMachine::Get()->SuspendStream(group);
2019 
2020   // Check if group has transitioned to a proper state
2021   ASSERT_EQ(group->GetState(),
2022             types::AseState::BTA_LE_AUDIO_ASE_STATE_QOS_CONFIGURED);
2023   ASSERT_EQ(removed_bidirectional, true);
2024   ASSERT_EQ(removed_unidirectional, true);
2025 
2026   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
2027   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2028 }
2029 
TEST_F(StateMachineTest,testReleaseSingle)2030 TEST_F(StateMachineTest, testReleaseSingle) {
2031   /* Device is banded headphones with 1x snk + 0x src ase
2032    * (1xunidirectional CIS) with channel count 2 (for stereo)
2033    */
2034   const auto context_type = kContextTypeRingtone;
2035   const int leaudio_group_id = 4;
2036   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
2037                    kLeAudioCodecLC3ChannelCountTwoChannel;
2038 
2039   // Prepare fake connected device group
2040   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2041 
2042   /* Since we prepared device with Ringtone context in mind, only one ASE
2043    * should have been configured.
2044    */
2045   PrepareConfigureCodecHandler(group, 1);
2046   PrepareConfigureQosHandler(group, 1);
2047   PrepareEnableHandler(group, 1);
2048   PrepareDisableHandler(group, 1);
2049   PrepareReleaseHandler(group, 1);
2050 
2051   auto* leAudioDevice = group->GetFirstDevice();
2052   EXPECT_CALL(gatt_queue,
2053               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
2054                                   GATT_WRITE_NO_RSP, _, _))
2055       .Times(4);
2056 
2057   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2058   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
2059   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
2060   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
2061   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
2062   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2063 
2064   InjectInitialIdleNotification(group);
2065 
2066   // Start the configuration and stream Media content
2067   LeAudioGroupStateMachine::Get()->StartStream(
2068       group, static_cast<LeAudioContextType>(context_type),
2069       types::AudioContexts(context_type));
2070 
2071   // Check if group has transitioned to a proper state
2072   ASSERT_EQ(group->GetState(),
2073             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2074   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2075   mock_function_count_map["alarm_cancel"] = 0;
2076   // Validate GroupStreamStatus
2077   EXPECT_CALL(
2078       mock_callbacks_,
2079       StatusReportCb(leaudio_group_id,
2080                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
2081   EXPECT_CALL(mock_callbacks_,
2082               StatusReportCb(leaudio_group_id,
2083                              bluetooth::le_audio::GroupStreamStatus::IDLE));
2084 
2085   // Stop the stream
2086   LeAudioGroupStateMachine::Get()->StopStream(group);
2087 
2088   // Check if group has transitioned to a proper state
2089   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2090   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2091 }
2092 
TEST_F(StateMachineTest,testReleaseCachingSingle)2093 TEST_F(StateMachineTest, testReleaseCachingSingle) {
2094   /* Device is banded headphones with 1x snk + 0x src ase
2095    * (1xunidirectional CIS)
2096    */
2097   const auto context_type = kContextTypeRingtone;
2098   const int leaudio_group_id = 4;
2099   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
2100                    kLeAudioCodecLC3ChannelCountTwoChannel;
2101 
2102   // Prepare fake connected device group
2103   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2104 
2105   /* Since we prepared device with Ringtone context in mind, only one ASE
2106    * should have been configured.
2107    */
2108   PrepareConfigureCodecHandler(group, 1, true);
2109   PrepareConfigureQosHandler(group, 1);
2110   PrepareEnableHandler(group, 1);
2111   PrepareDisableHandler(group, 1);
2112   PrepareReleaseHandler(group, 1);
2113 
2114   auto* leAudioDevice = group->GetFirstDevice();
2115   EXPECT_CALL(gatt_queue,
2116               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
2117                                   GATT_WRITE_NO_RSP, _, _))
2118       .Times(4);
2119 
2120   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2121   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
2122   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
2123   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
2124   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
2125   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2126 
2127   InjectInitialIdleNotification(group);
2128 
2129   // Validate GroupStreamStatus
2130   EXPECT_CALL(
2131       mock_callbacks_,
2132       StatusReportCb(leaudio_group_id,
2133                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
2134 
2135   EXPECT_CALL(
2136       mock_callbacks_,
2137       StatusReportCb(
2138           leaudio_group_id,
2139           bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
2140   EXPECT_CALL(
2141       mock_callbacks_,
2142       StatusReportCb(leaudio_group_id,
2143                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
2144 
2145   // Start the configuration and stream Media content
2146   LeAudioGroupStateMachine::Get()->StartStream(
2147       group, static_cast<LeAudioContextType>(context_type),
2148       types::AudioContexts(context_type));
2149 
2150   // Check if group has transitioned to a proper state
2151   ASSERT_EQ(group->GetState(),
2152             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2153 
2154   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2155   mock_function_count_map["alarm_cancel"] = 0;
2156 
2157   // Stop the stream
2158   LeAudioGroupStateMachine::Get()->StopStream(group);
2159 
2160   // Check if group has transitioned to a proper state
2161   ASSERT_EQ(group->GetState(),
2162             types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
2163 
2164   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2165 }
2166 
TEST_F(StateMachineTest,testStreamCaching_NoReconfigurationNeeded_SingleDevice)2167 TEST_F(StateMachineTest,
2168        testStreamCaching_NoReconfigurationNeeded_SingleDevice) {
2169   const auto context_type = kContextTypeRingtone;
2170   const int leaudio_group_id = 4;
2171   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
2172                    kLeAudioCodecLC3ChannelCountTwoChannel;
2173 
2174   additional_snk_ases = 2;
2175   // Prepare fake connected device group
2176   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2177 
2178   /* Since we prepared device with Ringtone context in mind and with no Source
2179    * ASEs, therefor only one ASE should have been configured.
2180    */
2181   PrepareConfigureCodecHandler(group, 1, true);
2182   PrepareConfigureQosHandler(group, 1, true);
2183   PrepareEnableHandler(group, 1);
2184   PrepareDisableHandler(group, 1);
2185   PrepareReleaseHandler(group, 1);
2186 
2187   /* Ctp messages we expect:
2188    * 1. Codec Config
2189    * 2. QoS Config
2190    * 3. Enable
2191    * 4. Release
2192    * 5. QoS Config (because device stays in Configured state)
2193    * 6. Enable
2194    */
2195   auto* leAudioDevice = group->GetFirstDevice();
2196   EXPECT_CALL(gatt_queue,
2197               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
2198                                   GATT_WRITE_NO_RSP, _, _))
2199       .Times(6);
2200 
2201   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(2);
2202   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(2);
2203   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
2204   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(1);
2205   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
2206   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2207 
2208   InjectInitialIdleNotification(group);
2209 
2210   // Validate GroupStreamStatus
2211   EXPECT_CALL(
2212       mock_callbacks_,
2213       StatusReportCb(leaudio_group_id,
2214                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
2215 
2216   EXPECT_CALL(
2217       mock_callbacks_,
2218       StatusReportCb(
2219           leaudio_group_id,
2220           bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
2221 
2222   EXPECT_CALL(mock_callbacks_,
2223               StatusReportCb(leaudio_group_id,
2224                              bluetooth::le_audio::GroupStreamStatus::STREAMING))
2225       .Times(2);
2226 
2227   // Start the configuration and stream Ringtone content
2228   LeAudioGroupStateMachine::Get()->StartStream(
2229       group, static_cast<LeAudioContextType>(context_type),
2230       types::AudioContexts(context_type));
2231 
2232   // Check if group has transitioned to a proper state
2233   ASSERT_EQ(group->GetState(),
2234             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2235 
2236   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2237   mock_function_count_map["alarm_cancel"] = 0;
2238 
2239   // Stop the stream
2240   LeAudioGroupStateMachine::Get()->StopStream(group);
2241 
2242   // Check if group has transitioned to a proper state
2243   ASSERT_EQ(group->GetState(),
2244             types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
2245 
2246   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2247   mock_function_count_map["alarm_cancel"] = 0;
2248 
2249   // Start the configuration and stream Media content
2250   LeAudioGroupStateMachine::Get()->StartStream(
2251       group, static_cast<LeAudioContextType>(context_type),
2252       types::AudioContexts(context_type));
2253 
2254   // Check if group has transitioned to a proper state
2255   ASSERT_EQ(group->GetState(),
2256             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2257 
2258   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2259   mock_function_count_map["alarm_cancel"] = 0;
2260 }
2261 
TEST_F(StateMachineTest,test_StreamCaching_ReconfigureForContextChange_SingleDevice)2262 TEST_F(StateMachineTest,
2263        test_StreamCaching_ReconfigureForContextChange_SingleDevice) {
2264   auto context_type = kContextTypeConversational;
2265   const int leaudio_group_id = 4;
2266   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
2267                    kLeAudioCodecLC3ChannelCountTwoChannel;
2268 
2269   additional_snk_ases = 2;
2270   /* Prepare fake connected device group with update of Media and Conversational
2271    * contexts
2272    */
2273   auto* group = PrepareSingleTestDeviceGroup(
2274       leaudio_group_id, context_type, 1,
2275       kContextTypeConversational | kContextTypeMedia);
2276 
2277   /* Don't validate ASE here, as after reconfiguration different ASE number
2278    * will be used.
2279    * For the first configuration (CONVERSTATIONAL) there will be 2 ASEs (Sink
2280    * and Source) After reconfiguration (MEDIA) there will be single ASE.
2281    */
2282   PrepareConfigureCodecHandler(group, 0, true);
2283   PrepareConfigureQosHandler(group, 0, true);
2284   PrepareEnableHandler(group);
2285   PrepareReceiverStartReady(group);
2286   PrepareReleaseHandler(group);
2287 
2288   /* Ctp messages we expect:
2289    * 1. Codec Config
2290    * 2. QoS Config
2291    * 3. Enable
2292    * 4. Release
2293    * 5. Codec Config
2294    * 6. QoS Config
2295    * 7. Enable
2296    */
2297   auto* leAudioDevice = group->GetFirstDevice();
2298   EXPECT_CALL(gatt_queue,
2299               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
2300                                   GATT_WRITE_NO_RSP, _, _))
2301       .Times(8);
2302 
2303   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(2);
2304   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(2);
2305 
2306   /* 2 times for first configuration (1 Sink, 1 Source), 1 time for second
2307    * configuration (1 Sink)*/
2308   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
2309 
2310   uint8_t value =
2311       bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionOutput |
2312       bluetooth::hci::iso_manager::kRemoveIsoDataPathDirectionInput;
2313   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, value)).Times(1);
2314   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
2315   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2316 
2317   InjectInitialIdleNotification(group);
2318 
2319   // Validate GroupStreamStatus
2320   EXPECT_CALL(
2321       mock_callbacks_,
2322       StatusReportCb(leaudio_group_id,
2323                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
2324 
2325   EXPECT_CALL(
2326       mock_callbacks_,
2327       StatusReportCb(
2328           leaudio_group_id,
2329           bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
2330 
2331   EXPECT_CALL(mock_callbacks_,
2332               StatusReportCb(leaudio_group_id,
2333                              bluetooth::le_audio::GroupStreamStatus::STREAMING))
2334       .Times(2);
2335 
2336   // Start the configuration and stream Conversational content
2337   LeAudioGroupStateMachine::Get()->StartStream(
2338       group, static_cast<LeAudioContextType>(context_type),
2339       types::AudioContexts(context_type));
2340 
2341   // Check if group has transitioned to a proper state
2342   ASSERT_EQ(group->GetState(),
2343             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2344 
2345   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2346   mock_function_count_map["alarm_cancel"] = 0;
2347 
2348   // Stop the stream
2349   LeAudioGroupStateMachine::Get()->StopStream(group);
2350 
2351   // Check if group has transitioned to a proper state
2352   ASSERT_EQ(group->GetState(),
2353             types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
2354 
2355   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2356   mock_function_count_map["alarm_cancel"] = 0;
2357 
2358   // Start the configuration and stream Media content
2359   context_type = kContextTypeMedia;
2360   LeAudioGroupStateMachine::Get()->StartStream(
2361       group, static_cast<LeAudioContextType>(context_type),
2362       types::AudioContexts(context_type));
2363 
2364   // Check if group has transitioned to a proper state
2365   ASSERT_EQ(group->GetState(),
2366             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2367   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2368 }
2369 
TEST_F(StateMachineTest,testReleaseMultiple)2370 TEST_F(StateMachineTest, testReleaseMultiple) {
2371   const auto context_type = kContextTypeMedia;
2372   const auto leaudio_group_id = 6;
2373   const auto num_devices = 2;
2374 
2375   // Prepare multiple fake connected devices in a group
2376   auto* group =
2377       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2378   ASSERT_EQ(group->Size(), num_devices);
2379 
2380   PrepareConfigureCodecHandler(group);
2381   PrepareConfigureQosHandler(group);
2382   PrepareEnableHandler(group);
2383   PrepareDisableHandler(group);
2384   PrepareReleaseHandler(group);
2385 
2386   auto* leAudioDevice = group->GetFirstDevice();
2387   auto expected_devices_written = 0;
2388   while (leAudioDevice) {
2389     EXPECT_CALL(gatt_queue,
2390                 WriteCharacteristic(leAudioDevice->conn_id_,
2391                                     leAudioDevice->ctp_hdls_.val_hdl, _,
2392                                     GATT_WRITE_NO_RSP, _, _))
2393         .Times(AtLeast(4));
2394     expected_devices_written++;
2395     leAudioDevice = group->GetNextDevice(leAudioDevice);
2396   }
2397   ASSERT_EQ(expected_devices_written, num_devices);
2398 
2399   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2400   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
2401   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
2402   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
2403   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
2404   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2405 
2406   InjectInitialIdleNotification(group);
2407 
2408   // Start the configuration and stream Media content
2409   LeAudioGroupStateMachine::Get()->StartStream(
2410       group, static_cast<LeAudioContextType>(context_type),
2411       types::AudioContexts(context_type));
2412 
2413   // Check if group has transitioned to a proper state
2414   ASSERT_EQ(group->GetState(),
2415             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2416 
2417   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2418   mock_function_count_map["alarm_cancel"] = 0;
2419 
2420   // Validate GroupStreamStatus
2421   EXPECT_CALL(
2422       mock_callbacks_,
2423       StatusReportCb(leaudio_group_id,
2424                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
2425   EXPECT_CALL(mock_callbacks_,
2426               StatusReportCb(leaudio_group_id,
2427                              bluetooth::le_audio::GroupStreamStatus::IDLE));
2428 
2429   // Stop the stream
2430   LeAudioGroupStateMachine::Get()->StopStream(group);
2431 
2432   // Check if group has transitioned to a proper state
2433   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2434   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2435 }
2436 
TEST_F(StateMachineTest,testReleaseBidirectional)2437 TEST_F(StateMachineTest, testReleaseBidirectional) {
2438   /* Device is banded headphones with 2x snk + 1x src ase
2439    * (1x bidirectional + 1xunidirectional CIS)
2440    */
2441   additional_snk_ases = 1;
2442   const auto context_type = kContextTypeConversational;
2443   const auto leaudio_group_id = 6;
2444 
2445   // Prepare fake connected device group
2446   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2447 
2448   /* Since we prepared device with Conversional context in mind, Sink and Source
2449    * ASEs should have been configured.
2450    */
2451   PrepareConfigureCodecHandler(group, 3);
2452   PrepareConfigureQosHandler(group, 3);
2453   PrepareEnableHandler(group, 3);
2454   PrepareDisableHandler(group, 3);
2455   PrepareReceiverStartReady(group, 1);
2456   PrepareReleaseHandler(group, 3);
2457 
2458   auto* leAudioDevice = group->GetFirstDevice();
2459   EXPECT_CALL(gatt_queue,
2460               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
2461                                   GATT_WRITE_NO_RSP, _, _))
2462       .Times(AtLeast(4));
2463 
2464   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2465   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
2466   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
2467   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
2468   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
2469   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2470 
2471   InjectInitialIdleNotification(group);
2472 
2473   // Start the configuration and stream Media content
2474   LeAudioGroupStateMachine::Get()->StartStream(
2475       group, static_cast<LeAudioContextType>(context_type),
2476       types::AudioContexts(context_type));
2477 
2478   // Check if group has transitioned to a proper state
2479   ASSERT_EQ(group->GetState(),
2480             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2481 
2482   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2483   mock_function_count_map["alarm_cancel"] = 0;
2484 
2485   // Stop the stream
2486   LeAudioGroupStateMachine::Get()->StopStream(group);
2487 
2488   // Check if group has transitioned to a proper state
2489   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2490   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2491   mock_function_count_map["alarm_cancel"] = 0;
2492 }
2493 
TEST_F(StateMachineTest,testDisableAndReleaseBidirectional)2494 TEST_F(StateMachineTest, testDisableAndReleaseBidirectional) {
2495   /* Device is banded headphones with 2x snk + 1x src ase
2496    * (1x bidirectional + 1xunidirectional CIS)
2497    */
2498   additional_snk_ases = 1;
2499   const auto context_type = kContextTypeConversational;
2500   const int leaudio_group_id = 4;
2501 
2502   // Prepare fake connected device group
2503   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2504 
2505   /* Since we prepared device with Conversional context in mind, Sink and Source
2506    * ASEs should have been configured.
2507    */
2508   PrepareConfigureCodecHandler(group, 3);
2509   PrepareConfigureQosHandler(group, 3);
2510   PrepareEnableHandler(group, 3);
2511   PrepareDisableHandler(group, 3);
2512   PrepareReceiverStartReady(group, 1);
2513   PrepareReceiverStopReady(group, 1);
2514   PrepareReleaseHandler(group, 3);
2515 
2516   auto* leAudioDevice = group->GetFirstDevice();
2517   EXPECT_CALL(gatt_queue,
2518               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
2519                                   GATT_WRITE_NO_RSP, _, _))
2520       .Times(AtLeast(4));
2521 
2522   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
2523   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
2524   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(3);
2525   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(2);
2526   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
2527   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
2528 
2529   // Start the configuration and stream Media content
2530   LeAudioGroupStateMachine::Get()->StartStream(
2531       group, static_cast<LeAudioContextType>(context_type),
2532       types::AudioContexts(context_type));
2533 
2534   // Suspend the stream
2535   LeAudioGroupStateMachine::Get()->SuspendStream(group);
2536 
2537   // Stop the stream
2538   LeAudioGroupStateMachine::Get()->StopStream(group);
2539 
2540   // Check if group has transitioned to a proper state
2541   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2542 }
2543 
TEST_F(StateMachineTest,testAseIdAssignmentIdle)2544 TEST_F(StateMachineTest, testAseIdAssignmentIdle) {
2545   const auto context_type = kContextTypeConversational;
2546   const auto leaudio_group_id = 6;
2547   const auto num_devices = 1;
2548 
2549   // Prepare multiple fake connected devices in a group
2550   auto* group =
2551       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2552   ASSERT_EQ(group->Size(), num_devices);
2553 
2554   // Should not trigger any action on our side
2555   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
2556   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(0);
2557   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2558   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2559   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2560   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2561   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2562 
2563   for (auto* device = group->GetFirstDevice(); device != nullptr;
2564        device = group->GetNextDevice(device)) {
2565     for (auto& ase : device->ases_) {
2566       ASSERT_EQ(ase.id, le_audio::types::ase::kAseIdInvalid);
2567       InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle,
2568                                  nullptr);
2569       ASSERT_EQ(ase.id, ase_id_last_assigned);
2570     }
2571   }
2572 }
2573 
TEST_F(StateMachineTest,testAseIdAssignmentCodecConfigured)2574 TEST_F(StateMachineTest, testAseIdAssignmentCodecConfigured) {
2575   const auto context_type = kContextTypeConversational;
2576   const auto leaudio_group_id = 6;
2577   const auto num_devices = 1;
2578 
2579   // Prepare multiple fake connected devices in a group
2580   auto* group =
2581       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
2582   ASSERT_EQ(group->Size(), num_devices);
2583 
2584   // Should not trigger any action on our side
2585   EXPECT_CALL(gatt_queue, WriteCharacteristic(_, _, _, _, _, _)).Times(0);
2586   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(0);
2587   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(0);
2588   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(0);
2589   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
2590   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
2591   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(0);
2592 
2593   for (auto* device = group->GetFirstDevice(); device != nullptr;
2594        device = group->GetNextDevice(device)) {
2595     for (auto& ase : device->ases_) {
2596       client_parser::ascs::ase_codec_configured_state_params
2597           codec_configured_state_params;
2598 
2599       ASSERT_EQ(ase.id, le_audio::types::ase::kAseIdInvalid);
2600       InjectAseStateNotification(&ase, device, group,
2601                                  ascs::kAseStateCodecConfigured,
2602                                  &codec_configured_state_params);
2603       ASSERT_EQ(ase.id, ase_id_last_assigned);
2604     }
2605   }
2606 }
2607 
TEST_F(StateMachineTest,testAseAutonomousRelease)2608 TEST_F(StateMachineTest, testAseAutonomousRelease) {
2609   /* Device is banded headphones with 2x snk + 1x src ase
2610    * (1x bidirectional + 1xunidirectional CIS)
2611    */
2612   additional_snk_ases = 1;
2613   const auto context_type = kContextTypeConversational;
2614   const int leaudio_group_id = 4;
2615 
2616   // Prepare fake connected device group
2617   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2618 
2619   /* Since we prepared device with Conversional context in mind, Sink and Source
2620    * ASEs should have been configured.
2621    */
2622   PrepareConfigureCodecHandler(group, 3);
2623   PrepareConfigureQosHandler(group, 3);
2624   PrepareEnableHandler(group, 3);
2625   PrepareDisableHandler(group, 3);
2626   PrepareReceiverStartReady(group, 1);
2627   PrepareReceiverStopReady(group, 1);
2628   PrepareReleaseHandler(group, 3);
2629 
2630   InjectInitialIdleNotification(group);
2631 
2632   // Validate initial GroupStreamStatus
2633   EXPECT_CALL(
2634       mock_callbacks_,
2635       StatusReportCb(leaudio_group_id,
2636                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
2637 
2638   // Start the configuration and stream Media content
2639   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2640       group, static_cast<LeAudioContextType>(context_type),
2641       types::AudioContexts(context_type)));
2642 
2643   // Validate new GroupStreamStatus
2644   EXPECT_CALL(mock_callbacks_,
2645               StatusReportCb(leaudio_group_id,
2646                              bluetooth::le_audio::GroupStreamStatus::IDLE))
2647       .Times(AtLeast(1));
2648 
2649   /* Single disconnect as it is bidirectional Cis*/
2650   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);
2651 
2652   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
2653   mock_function_count_map["alarm_cancel"] = 0;
2654 
2655   for (auto* device = group->GetFirstDevice(); device != nullptr;
2656        device = group->GetNextDevice(device)) {
2657     for (auto& ase : device->ases_) {
2658       client_parser::ascs::ase_codec_configured_state_params
2659           codec_configured_state_params;
2660 
2661       ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2662 
2663       // Each one does the autonomous release
2664       InjectAseStateNotification(&ase, device, group, ascs::kAseStateReleasing,
2665                                  &codec_configured_state_params);
2666       InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle,
2667                                  &codec_configured_state_params);
2668     }
2669   }
2670 
2671   // Verify we've handled the release and updated all states
2672   for (auto* device = group->GetFirstDevice(); device != nullptr;
2673        device = group->GetNextDevice(device)) {
2674     for (auto& ase : device->ases_) {
2675       ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
2676     }
2677   }
2678 
2679   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
2680 }
2681 
TEST_F(StateMachineTest,testAseAutonomousRelease2Devices)2682 TEST_F(StateMachineTest, testAseAutonomousRelease2Devices) {
2683   const auto context_type = kContextTypeConversational;
2684   const int leaudio_group_id = 4;
2685   const int num_of_devices = 2;
2686 
2687   // Prepare fake connected device group
2688   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type,
2689                                              num_of_devices);
2690 
2691   /* Since we prepared device with Conversional context in mind, Sink and Source
2692    * ASEs should have been configured.
2693    */
2694   PrepareConfigureCodecHandler(group);
2695   PrepareConfigureQosHandler(group);
2696   PrepareEnableHandler(group);
2697   PrepareDisableHandler(group);
2698   PrepareReceiverStartReady(group);
2699   PrepareReceiverStopReady(group);
2700   PrepareReleaseHandler(group);
2701 
2702   InjectInitialIdleNotification(group);
2703 
2704   // Validate initial GroupStreamStatus
2705   EXPECT_CALL(
2706       mock_callbacks_,
2707       StatusReportCb(leaudio_group_id,
2708                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
2709 
2710   // Start the configuration and stream Media content
2711   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2712       group, static_cast<LeAudioContextType>(context_type),
2713       types::AudioContexts(context_type)));
2714 
2715   // Check streaming will continue
2716   EXPECT_CALL(mock_callbacks_,
2717               StatusReportCb(leaudio_group_id,
2718                              bluetooth::le_audio::GroupStreamStatus::IDLE))
2719       .Times(0);
2720 
2721   /* Single disconnect as it is bidirectional Cis*/
2722   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(1);
2723 
2724   auto device = group->GetFirstDevice();
2725   for (auto& ase : device->ases_) {
2726     client_parser::ascs::ase_codec_configured_state_params
2727         codec_configured_state_params;
2728 
2729     ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2730 
2731     // Simulate autonomus release for one device.
2732     InjectAseStateNotification(&ase, device, group, ascs::kAseStateReleasing,
2733                                &codec_configured_state_params);
2734     InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle,
2735                                &codec_configured_state_params);
2736   }
2737 }
2738 
TEST_F(StateMachineTest,testStateTransitionTimeoutOnIdleState)2739 TEST_F(StateMachineTest, testStateTransitionTimeoutOnIdleState) {
2740   const auto context_type = kContextTypeRingtone;
2741   const int leaudio_group_id = 4;
2742   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
2743                    kLeAudioCodecLC3ChannelCountTwoChannel;
2744 
2745   // Prepare fake connected device group
2746   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2747 
2748   auto* leAudioDevice = group->GetFirstDevice();
2749   EXPECT_CALL(gatt_queue,
2750               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
2751                                   GATT_WRITE_NO_RSP, _, _))
2752       .Times(1);
2753 
2754   // Start the configuration and stream Media content
2755   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2756       group, static_cast<LeAudioContextType>(context_type),
2757       types::AudioContexts(context_type)));
2758 
2759   // Disconnect device
2760   LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(
2761       group, leAudioDevice);
2762 
2763   // Make sure timeout is cleared
2764   ASSERT_TRUE(fake_osi_alarm_set_on_mloop_.cb == nullptr);
2765 }
2766 
TEST_F(StateMachineTest,testStateTransitionTimeout)2767 TEST_F(StateMachineTest, testStateTransitionTimeout) {
2768   const auto context_type = kContextTypeRingtone;
2769   const int leaudio_group_id = 4;
2770   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
2771                    kLeAudioCodecLC3ChannelCountTwoChannel;
2772 
2773   // Prepare fake connected device group
2774   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2775 
2776   /* Since we prepared device with Ringtone context in mind, only one ASE
2777    * should have been configured.
2778    */
2779   PrepareConfigureCodecHandler(group, 1);
2780   PrepareConfigureQosHandler(group, 1);
2781 
2782   auto* leAudioDevice = group->GetFirstDevice();
2783   EXPECT_CALL(gatt_queue,
2784               WriteCharacteristic(1, leAudioDevice->ctp_hdls_.val_hdl, _,
2785                                   GATT_WRITE_NO_RSP, _, _))
2786       .Times(3);
2787 
2788   // Start the configuration and stream Media content
2789   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2790       group, static_cast<LeAudioContextType>(context_type),
2791       types::AudioContexts(context_type)));
2792 
2793   // Check if timeout is fired
2794   EXPECT_CALL(mock_callbacks_, OnStateTransitionTimeout(leaudio_group_id));
2795 
2796   // simulate timeout seconds passed, alarm executing
2797   fake_osi_alarm_set_on_mloop_.cb(fake_osi_alarm_set_on_mloop_.data);
2798   ASSERT_EQ(1, mock_function_count_map["alarm_set_on_mloop"]);
2799 }
2800 
2801 MATCHER_P(dataPathIsEq, expected, "") { return (arg.data_path_id == expected); }
2802 
TEST_F(StateMachineTest,testConfigureDataPathForHost)2803 TEST_F(StateMachineTest, testConfigureDataPathForHost) {
2804   const auto context_type = kContextTypeRingtone;
2805   const int leaudio_group_id = 4;
2806   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
2807                    kLeAudioCodecLC3ChannelCountTwoChannel;
2808 
2809   /* Should be called 3 times because
2810    * 1 - calling GetConfigurations just after connection
2811    * (UpdateAudioContextTypeAvailability)
2812    * 2 - when doing configuration of the context type
2813    * 3 - AddCisToStreamConfiguration -> CreateStreamVectorForOffloader
2814    * 4 - Data Path
2815    */
2816   EXPECT_CALL(*mock_codec_manager_, GetCodecLocation())
2817       .Times(4)
2818       .WillRepeatedly(Return(types::CodecLocation::HOST));
2819 
2820   // Prepare fake connected device group
2821   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2822 
2823   /* Since we prepared device with Ringtone context in mind, only one ASE
2824    * should have been configured.
2825    */
2826   PrepareConfigureCodecHandler(group, 1);
2827   PrepareConfigureQosHandler(group, 1);
2828   PrepareEnableHandler(group, 1);
2829 
2830   EXPECT_CALL(
2831       *mock_iso_manager_,
2832       SetupIsoDataPath(
2833           _, dataPathIsEq(bluetooth::hci::iso_manager::kIsoDataPathHci)))
2834       .Times(1);
2835 
2836   InjectInitialIdleNotification(group);
2837 
2838   // Start the configuration and stream Media content
2839   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2840       group, static_cast<LeAudioContextType>(context_type),
2841       types::AudioContexts(context_type)));
2842 }
TEST_F(StateMachineTest,testConfigureDataPathForAdsp)2843 TEST_F(StateMachineTest, testConfigureDataPathForAdsp) {
2844   const auto context_type = kContextTypeRingtone;
2845   const int leaudio_group_id = 4;
2846   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
2847                    kLeAudioCodecLC3ChannelCountTwoChannel;
2848 
2849   /* Should be called 3 times because
2850    * 1 - calling GetConfigurations just after connection
2851    * (UpdateAudioContextTypeAvailability)
2852    * 2 - when doing configuration of the context type
2853    * 3 - AddCisToStreamConfiguration -> CreateStreamVectorForOffloader
2854    * 4 - data path
2855    */
2856   EXPECT_CALL(*mock_codec_manager_, GetCodecLocation())
2857       .Times(4)
2858       .WillRepeatedly(Return(types::CodecLocation::ADSP));
2859 
2860   // Prepare fake connected device group
2861   auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type);
2862 
2863   /* Since we prepared device with Ringtone context in mind, only one ASE
2864    * should have been configured.
2865    */
2866   PrepareConfigureCodecHandler(group, 1);
2867   PrepareConfigureQosHandler(group, 1);
2868   PrepareEnableHandler(group, 1);
2869 
2870   EXPECT_CALL(
2871       *mock_iso_manager_,
2872       SetupIsoDataPath(
2873           _, dataPathIsEq(
2874                  bluetooth::hci::iso_manager::kIsoDataPathPlatformDefault)))
2875       .Times(1);
2876 
2877   InjectInitialIdleNotification(group);
2878 
2879   // Start the configuration and stream Media content
2880   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2881       group, static_cast<LeAudioContextType>(context_type),
2882       types::AudioContexts(context_type)));
2883 }
2884 
InjectAclDisconnected(LeAudioDeviceGroup * group,LeAudioDevice * leAudioDevice)2885 static void InjectAclDisconnected(LeAudioDeviceGroup* group,
2886                                   LeAudioDevice* leAudioDevice) {
2887   LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(
2888       group, leAudioDevice);
2889 }
2890 
TEST_F(StateMachineTest,testStreamConfigurationAdspDownMix)2891 TEST_F(StateMachineTest, testStreamConfigurationAdspDownMix) {
2892   const auto context_type = kContextTypeConversational;
2893   const int leaudio_group_id = 4;
2894   const int num_devices = 2;
2895 
2896   // Prepare fake connected device group
2897   auto* group = PrepareSingleTestDeviceGroup(
2898       leaudio_group_id, context_type, num_devices,
2899       types::AudioContexts(kContextTypeConversational));
2900 
2901   /* Should be called 5 times because
2902    * 1 - calling GetConfigurations just after connection
2903    * (UpdateAudioContextTypeAvailability),
2904    * 2 - when doing configuration of the context type
2905    * 3 - AddCisToStreamConfiguration -> CreateStreamVectorForOffloader (sink)
2906    * 4 - AddCisToStreamConfiguration -> CreateStreamVectorForOffloader (source)
2907    * 5,6 - Data Path
2908    */
2909   EXPECT_CALL(*mock_codec_manager_, GetCodecLocation())
2910       .Times(6)
2911       .WillRepeatedly(Return(types::CodecLocation::ADSP));
2912 
2913   PrepareConfigureCodecHandler(group);
2914   PrepareConfigureQosHandler(group);
2915   PrepareEnableHandler(group);
2916   PrepareReceiverStartReady(group);
2917 
2918   InjectInitialIdleNotification(group);
2919 
2920   auto* leAudioDevice = group->GetFirstDevice();
2921   InjectAclDisconnected(group, leAudioDevice);
2922 
2923   // Start the configuration and stream Media content
2924   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
2925       group, static_cast<LeAudioContextType>(context_type),
2926       types::AudioContexts(context_type)));
2927 
2928   ASSERT_EQ(
2929       static_cast<int>(
2930           group->stream_conf.sink_offloader_streams_target_allocation.size()),
2931       2);
2932   ASSERT_EQ(
2933       static_cast<int>(
2934           group->stream_conf.source_offloader_streams_target_allocation.size()),
2935       2);
2936 
2937   ASSERT_EQ(
2938       static_cast<int>(
2939           group->stream_conf.sink_offloader_streams_current_allocation.size()),
2940       2);
2941   ASSERT_EQ(
2942       static_cast<int>(group->stream_conf
2943                            .source_offloader_streams_current_allocation.size()),
2944       2);
2945 
2946   // Check if group has transitioned to a proper state
2947   ASSERT_EQ(group->GetState(),
2948             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
2949 
2950   uint32_t allocation = 0;
2951   for (const auto& s :
2952        group->stream_conf.sink_offloader_streams_target_allocation) {
2953     allocation |= s.second;
2954     ASSERT_FALSE(allocation == 0);
2955   }
2956   ASSERT_TRUE(allocation == codec_spec_conf::kLeAudioLocationStereo);
2957 
2958   allocation = 0;
2959   for (const auto& s :
2960        group->stream_conf.source_offloader_streams_target_allocation) {
2961     allocation |= s.second;
2962     ASSERT_FALSE(allocation == 0);
2963   }
2964   ASSERT_TRUE(allocation == codec_spec_conf::kLeAudioLocationStereo);
2965 
2966   for (const auto& s :
2967        group->stream_conf.sink_offloader_streams_current_allocation) {
2968     ASSERT_TRUE((s.second == 0) ||
2969                 (s.second == codec_spec_conf::kLeAudioLocationStereo));
2970   }
2971 
2972   for (const auto& s :
2973        group->stream_conf.source_offloader_streams_current_allocation) {
2974     ASSERT_TRUE((s.second == 0) ||
2975                 (s.second == codec_spec_conf::kLeAudioLocationStereo));
2976   }
2977 }
2978 
InjectCisDisconnected(LeAudioDeviceGroup * group,LeAudioDevice * leAudioDevice,uint8_t reason)2979 static void InjectCisDisconnected(LeAudioDeviceGroup* group,
2980                                   LeAudioDevice* leAudioDevice,
2981                                   uint8_t reason) {
2982   bluetooth::hci::iso_manager::cis_disconnected_evt event;
2983 
2984   for (auto const ase : leAudioDevice->ases_) {
2985     if (ase.data_path_state != types::AudioStreamDataPathState::CIS_ASSIGNED &&
2986         ase.data_path_state != types::AudioStreamDataPathState::IDLE) {
2987       event.reason = reason;
2988       event.cig_id = group->group_id_;
2989       event.cis_conn_hdl = ase.cis_conn_hdl;
2990       LeAudioGroupStateMachine::Get()->ProcessHciNotifCisDisconnected(
2991           group, leAudioDevice, &event);
2992     }
2993   }
2994 }
2995 
TEST_F(StateMachineTest,testAttachDeviceToTheStream)2996 TEST_F(StateMachineTest, testAttachDeviceToTheStream) {
2997   const auto context_type = kContextTypeMedia;
2998   const auto leaudio_group_id = 6;
2999   const auto num_devices = 2;
3000 
3001   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
3002 
3003   // Prepare multiple fake connected devices in a group
3004   auto* group =
3005       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3006   ASSERT_EQ(group->Size(), num_devices);
3007 
3008   PrepareConfigureCodecHandler(group);
3009   PrepareConfigureQosHandler(group);
3010   PrepareEnableHandler(group);
3011   PrepareDisableHandler(group);
3012   PrepareReleaseHandler(group);
3013 
3014   auto* leAudioDevice = group->GetFirstDevice();
3015   LeAudioDevice* lastDevice;
3016   LeAudioDevice* fistDevice = leAudioDevice;
3017 
3018   auto expected_devices_written = 0;
3019   while (leAudioDevice) {
3020     /* Three Writes:
3021      * 1: Codec Config
3022      * 2: Codec QoS
3023      * 3: Enabling
3024      */
3025     lastDevice = leAudioDevice;
3026     EXPECT_CALL(gatt_queue,
3027                 WriteCharacteristic(leAudioDevice->conn_id_,
3028                                     leAudioDevice->ctp_hdls_.val_hdl, _,
3029                                     GATT_WRITE_NO_RSP, _, _))
3030         .Times(AtLeast(3));
3031     expected_devices_written++;
3032     leAudioDevice = group->GetNextDevice(leAudioDevice);
3033   }
3034   ASSERT_EQ(expected_devices_written, num_devices);
3035 
3036   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3037   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3038   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3039 
3040   InjectInitialIdleNotification(group);
3041 
3042   // Start the configuration and stream Media content
3043   LeAudioGroupStateMachine::Get()->StartStream(
3044       group, static_cast<LeAudioContextType>(context_type),
3045       types::AudioContexts(context_type));
3046 
3047   // Check if group has transitioned to a proper state
3048   ASSERT_EQ(group->GetState(),
3049             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3050   testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
3051 
3052   // Inject CIS and ACL disconnection of first device
3053   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
3054   InjectAclDisconnected(group, lastDevice);
3055 
3056   // Check if group keeps streaming
3057   ASSERT_EQ(group->GetState(),
3058             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3059 
3060   lastDevice->conn_id_ = 3;
3061   group->UpdateAudioContextTypeAvailability();
3062 
3063   // Make sure ASE with disconnected CIS are not left in STREAMING
3064   ASSERT_EQ(lastDevice->GetFirstAseWithState(
3065                 ::le_audio::types::kLeAudioDirectionSink,
3066                 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
3067             nullptr);
3068   ASSERT_EQ(lastDevice->GetFirstAseWithState(
3069                 ::le_audio::types::kLeAudioDirectionSource,
3070                 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
3071             nullptr);
3072 
3073   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_,
3074                                               lastDevice->ctp_hdls_.val_hdl, _,
3075                                               GATT_WRITE_NO_RSP, _, _))
3076       .Times(AtLeast(3));
3077 
3078   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3079   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(1);
3080   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice);
3081 
3082   // Check if group keeps streaming
3083   ASSERT_EQ(group->GetState(),
3084             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3085 
3086   // Verify that the joining device receives the right CCID list
3087   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
3088   bool parsedOk = false;
3089   auto ltv = le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(),
3090                                                    lastMeta.size(), parsedOk);
3091   ASSERT_TRUE(parsedOk);
3092 
3093   auto ccids = ltv.Find(le_audio::types::kLeAudioMetadataTypeCcidList);
3094   ASSERT_TRUE(ccids.has_value());
3095   ASSERT_NE(std::find(ccids->begin(), ccids->end(), media_ccid), ccids->end());
3096 
3097   /* Verify that ASE of first device are still good*/
3098   auto ase = fistDevice->GetFirstActiveAse();
3099   ASSERT_NE(ase->max_transport_latency, 0);
3100   ASSERT_NE(ase->retrans_nb, 0);
3101 }
3102 
TEST_F(StateMachineTest,testAttachDeviceToTheConversationalStream)3103 TEST_F(StateMachineTest, testAttachDeviceToTheConversationalStream) {
3104   const auto context_type = kContextTypeConversational;
3105   const auto leaudio_group_id = 6;
3106   const auto num_devices = 2;
3107 
3108   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
3109 
3110   // Prepare multiple fake connected devices in a group
3111   auto* group =
3112       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3113   ASSERT_EQ(group->Size(), num_devices);
3114 
3115   PrepareConfigureCodecHandler(group);
3116   PrepareConfigureQosHandler(group);
3117   PrepareEnableHandler(group);
3118   PrepareReceiverStartReady(group);
3119   PrepareDisableHandler(group);
3120   PrepareReleaseHandler(group);
3121 
3122   auto* leAudioDevice = group->GetFirstDevice();
3123   LeAudioDevice* lastDevice;
3124   LeAudioDevice* fistDevice = leAudioDevice;
3125 
3126   auto expected_devices_written = 0;
3127   while (leAudioDevice) {
3128     /* Three Writes:
3129      * 1: Codec Config
3130      * 2: Codec QoS
3131      * 3: Enabling
3132      */
3133     lastDevice = leAudioDevice;
3134     EXPECT_CALL(gatt_queue,
3135                 WriteCharacteristic(leAudioDevice->conn_id_,
3136                                     leAudioDevice->ctp_hdls_.val_hdl, _,
3137                                     GATT_WRITE_NO_RSP, _, _))
3138         .Times(AtLeast(3));
3139     expected_devices_written++;
3140     leAudioDevice = group->GetNextDevice(leAudioDevice);
3141   }
3142   ASSERT_EQ(expected_devices_written, num_devices);
3143 
3144   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3145   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3146   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(4);
3147 
3148   InjectInitialIdleNotification(group);
3149 
3150   // Start the configuration and stream Conversational content
3151   LeAudioGroupStateMachine::Get()->StartStream(
3152       group, static_cast<LeAudioContextType>(context_type),
3153       types::AudioContexts(context_type));
3154 
3155   // Check if group has transitioned to a proper state
3156   ASSERT_EQ(group->GetState(),
3157             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3158   testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
3159 
3160   // Inject CIS and ACL disconnection of first device
3161   InjectCisDisconnected(group, lastDevice, HCI_ERR_CONNECTION_TOUT);
3162   InjectAclDisconnected(group, lastDevice);
3163 
3164   // Check if group keeps streaming
3165   ASSERT_EQ(group->GetState(),
3166             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3167 
3168   lastDevice->conn_id_ = 3;
3169   group->UpdateAudioContextTypeAvailability();
3170 
3171   // Make sure ASE with disconnected CIS are not left in STREAMING
3172   ASSERT_EQ(lastDevice->GetFirstAseWithState(
3173                 ::le_audio::types::kLeAudioDirectionSink,
3174                 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
3175             nullptr);
3176   ASSERT_EQ(lastDevice->GetFirstAseWithState(
3177                 ::le_audio::types::kLeAudioDirectionSource,
3178                 types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING),
3179             nullptr);
3180 
3181   EXPECT_CALL(gatt_queue, WriteCharacteristic(lastDevice->conn_id_,
3182                                               lastDevice->ctp_hdls_.val_hdl, _,
3183                                               GATT_WRITE_NO_RSP, _, _))
3184       .Times(AtLeast(3));
3185 
3186   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3187   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3188   LeAudioGroupStateMachine::Get()->AttachToStream(group, lastDevice);
3189 
3190   // Check if group keeps streaming
3191   ASSERT_EQ(group->GetState(),
3192             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3193 
3194   // Verify that the joining device receives the right CCID list
3195   auto lastMeta = lastDevice->GetFirstActiveAse()->metadata;
3196   bool parsedOk = false;
3197   auto ltv = le_audio::types::LeAudioLtvMap::Parse(lastMeta.data(),
3198                                                    lastMeta.size(), parsedOk);
3199   ASSERT_TRUE(parsedOk);
3200 
3201   auto ccids = ltv.Find(le_audio::types::kLeAudioMetadataTypeCcidList);
3202   ASSERT_TRUE(ccids.has_value());
3203   ASSERT_NE(std::find(ccids->begin(), ccids->end(), call_ccid), ccids->end());
3204 
3205   /* Verify that ASE of first device are still good*/
3206   auto ase = fistDevice->GetFirstActiveAse();
3207   ASSERT_NE(ase->max_transport_latency, 0);
3208   ASSERT_NE(ase->retrans_nb, 0);
3209 
3210   // Make sure ASEs with reconnected CIS are in STREAMING state
3211   ASSERT_TRUE(lastDevice->HaveAllActiveAsesSameState(
3212       types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING));
3213 }
3214 
TEST_F(StateMachineTest,StartStreamAfterConfigure)3215 TEST_F(StateMachineTest, StartStreamAfterConfigure) {
3216   const auto context_type = kContextTypeMedia;
3217   const auto leaudio_group_id = 6;
3218   const auto num_devices = 2;
3219 
3220   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
3221 
3222   // Prepare multiple fake connected devices in a group
3223   auto* group =
3224       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3225   ASSERT_EQ(group->Size(), num_devices);
3226 
3227   PrepareConfigureCodecHandler(group, 0, true);
3228   PrepareConfigureQosHandler(group);
3229   PrepareEnableHandler(group);
3230   PrepareDisableHandler(group);
3231   PrepareReleaseHandler(group);
3232 
3233   InjectInitialIdleNotification(group);
3234 
3235   auto* leAudioDevice = group->GetFirstDevice();
3236   auto expected_devices_written = 0;
3237   while (leAudioDevice) {
3238     /* Three Writes:
3239      * 1. Codec configure
3240      * 2: Codec QoS
3241      * 3: Enabling
3242      */
3243     EXPECT_CALL(gatt_queue,
3244                 WriteCharacteristic(leAudioDevice->conn_id_,
3245                                     leAudioDevice->ctp_hdls_.val_hdl, _,
3246                                     GATT_WRITE_NO_RSP, _, _))
3247         .Times(3);
3248     expected_devices_written++;
3249     leAudioDevice = group->GetNextDevice(leAudioDevice);
3250   }
3251   ASSERT_EQ(expected_devices_written, num_devices);
3252 
3253   // Validate GroupStreamStatus
3254   EXPECT_CALL(mock_callbacks_,
3255               StatusReportCb(
3256                   leaudio_group_id,
3257                   bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER));
3258 
3259   // Start the configuration and stream Media content
3260   group->SetPendingConfiguration();
3261   LeAudioGroupStateMachine::Get()->ConfigureStream(
3262       group, context_type, types::AudioContexts(context_type));
3263 
3264   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3265 
3266   group->ClearPendingConfiguration();
3267   // Validate GroupStreamStatus
3268   EXPECT_CALL(
3269       mock_callbacks_,
3270       StatusReportCb(leaudio_group_id,
3271                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3272 
3273   // Start the configuration and stream Media content
3274   LeAudioGroupStateMachine::Get()->StartStream(
3275       group, context_type, types::AudioContexts(context_type));
3276 
3277   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3278 }
3279 
TEST_F(StateMachineTest,StartStreamCachedConfig)3280 TEST_F(StateMachineTest, StartStreamCachedConfig) {
3281   const auto context_type = kContextTypeMedia;
3282   const auto leaudio_group_id = 6;
3283   const auto num_devices = 2;
3284 
3285   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
3286 
3287   // Prepare multiple fake connected devices in a group
3288   auto* group =
3289       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3290   ASSERT_EQ(group->Size(), num_devices);
3291 
3292   PrepareConfigureCodecHandler(group, 0, true);
3293   PrepareConfigureQosHandler(group);
3294   PrepareEnableHandler(group);
3295   PrepareDisableHandler(group);
3296   PrepareReleaseHandler(group);
3297 
3298   InjectInitialIdleNotification(group);
3299 
3300   auto* leAudioDevice = group->GetFirstDevice();
3301   auto expected_devices_written = 0;
3302   while (leAudioDevice) {
3303     /* Three Writes:
3304      * 1: Codec config
3305      * 2: Codec QoS (+1 after restart)
3306      * 3: Enabling (+1 after restart)
3307      * 4: Release (1)
3308      */
3309     EXPECT_CALL(gatt_queue,
3310                 WriteCharacteristic(leAudioDevice->conn_id_,
3311                                     leAudioDevice->ctp_hdls_.val_hdl, _,
3312                                     GATT_WRITE_NO_RSP, _, _))
3313         .Times(6);
3314     expected_devices_written++;
3315     leAudioDevice = group->GetNextDevice(leAudioDevice);
3316   }
3317   ASSERT_EQ(expected_devices_written, num_devices);
3318 
3319   // Validate GroupStreamStatus
3320   EXPECT_CALL(
3321       mock_callbacks_,
3322       StatusReportCb(leaudio_group_id,
3323                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3324 
3325   // Start the configuration and stream Media content
3326   LeAudioGroupStateMachine::Get()->StartStream(
3327       group, context_type, types::AudioContexts(context_type));
3328 
3329   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3330 
3331   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3332   mock_function_count_map["alarm_cancel"] = 0;
3333 
3334   // Validate GroupStreamStatus
3335   EXPECT_CALL(
3336       mock_callbacks_,
3337       StatusReportCb(leaudio_group_id,
3338                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
3339 
3340   EXPECT_CALL(
3341       mock_callbacks_,
3342       StatusReportCb(
3343           leaudio_group_id,
3344           bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
3345   // Start the configuration and stream Media content
3346   LeAudioGroupStateMachine::Get()->StopStream(group);
3347 
3348   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3349 
3350   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3351   mock_function_count_map["alarm_cancel"] = 0;
3352 
3353   // Restart stream
3354   EXPECT_CALL(
3355       mock_callbacks_,
3356       StatusReportCb(leaudio_group_id,
3357                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3358 
3359   // Start the configuration and stream Media content
3360   LeAudioGroupStateMachine::Get()->StartStream(
3361       group, context_type, types::AudioContexts(context_type));
3362 
3363   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3364   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3365 }
3366 
TEST_F(StateMachineTest,BoundedHeadphonesConversationalToMediaChannelCount_2)3367 TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_2) {
3368   const auto initial_context_type = kContextTypeConversational;
3369   const auto new_context_type = kContextTypeMedia;
3370   const auto leaudio_group_id = 6;
3371   const auto num_devices = 1;
3372   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel |
3373                    kLeAudioCodecLC3ChannelCountTwoChannel;
3374 
3375   sample_freq_ |= codec_specific::kCapSamplingFrequency48000Hz |
3376                   codec_specific::kCapSamplingFrequency32000Hz;
3377   additional_snk_ases = 3;
3378   additional_src_ases = 1;
3379 
3380   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
3381   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
3382 
3383   // Prepare multiple fake connected devices in a group
3384   auto* group = PrepareSingleTestDeviceGroup(
3385       leaudio_group_id, initial_context_type, num_devices,
3386       kContextTypeConversational | kContextTypeMedia);
3387   ASSERT_EQ(group->Size(), num_devices);
3388 
3389   PrepareConfigureCodecHandler(group, 0, true);
3390   PrepareConfigureQosHandler(group);
3391   PrepareEnableHandler(group);
3392   PrepareDisableHandler(group);
3393   PrepareReleaseHandler(group);
3394   PrepareReceiverStartReady(group);
3395 
3396   InjectInitialIdleNotification(group);
3397 
3398   auto* leAudioDevice = group->GetFirstDevice();
3399   auto expected_devices_written = 0;
3400   while (leAudioDevice) {
3401     /* 8 Writes:
3402      * 1: Codec config (+1 after reconfig)
3403      * 2: Codec QoS (+1 after reconfig)
3404      * 3: Enabling (+1 after reconfig)
3405      * 4: ReceiverStartReady (only for conversational)
3406      * 5: Release
3407      */
3408     EXPECT_CALL(gatt_queue,
3409                 WriteCharacteristic(leAudioDevice->conn_id_,
3410                                     leAudioDevice->ctp_hdls_.val_hdl, _,
3411                                     GATT_WRITE_NO_RSP, _, _))
3412         .Times(8);
3413     expected_devices_written++;
3414     leAudioDevice = group->GetNextDevice(leAudioDevice);
3415   }
3416   ASSERT_EQ(expected_devices_written, num_devices);
3417 
3418   // Validate GroupStreamStatus
3419   EXPECT_CALL(
3420       mock_callbacks_,
3421       StatusReportCb(leaudio_group_id,
3422                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3423 
3424   // Start the configuration and stream Media content
3425   LeAudioGroupStateMachine::Get()->StartStream(
3426       group, initial_context_type, types::AudioContexts(initial_context_type));
3427 
3428   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3429 
3430   // Validate GroupStreamStatus
3431   EXPECT_CALL(
3432       mock_callbacks_,
3433       StatusReportCb(leaudio_group_id,
3434                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
3435 
3436   EXPECT_CALL(
3437       mock_callbacks_,
3438       StatusReportCb(
3439           leaudio_group_id,
3440           bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
3441   // Start the configuration and stream Media content
3442   LeAudioGroupStateMachine::Get()->StopStream(group);
3443 
3444   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3445 
3446   // Restart stream
3447   EXPECT_CALL(
3448       mock_callbacks_,
3449       StatusReportCb(leaudio_group_id,
3450                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3451 
3452   // Start the configuration and stream Media content
3453   LeAudioGroupStateMachine::Get()->StartStream(
3454       group, new_context_type, types::AudioContexts(new_context_type));
3455 
3456   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3457 }
3458 
TEST_F(StateMachineTest,BoundedHeadphonesConversationalToMediaChannelCount_1)3459 TEST_F(StateMachineTest, BoundedHeadphonesConversationalToMediaChannelCount_1) {
3460   const auto initial_context_type = kContextTypeConversational;
3461   const auto new_context_type = kContextTypeMedia;
3462   const auto leaudio_group_id = 6;
3463   const auto num_devices = 1;
3464   channel_count_ = kLeAudioCodecLC3ChannelCountSingleChannel;
3465 
3466   sample_freq_ |= codec_specific::kCapSamplingFrequency48000Hz |
3467                   codec_specific::kCapSamplingFrequency32000Hz;
3468   additional_snk_ases = 3;
3469   additional_src_ases = 1;
3470 
3471   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
3472   ContentControlIdKeeper::GetInstance()->SetCcid(call_context, call_ccid);
3473 
3474   // Prepare one fake connected devices in a group
3475   auto* group = PrepareSingleTestDeviceGroup(
3476       leaudio_group_id, initial_context_type, num_devices,
3477       kContextTypeConversational | kContextTypeMedia);
3478   ASSERT_EQ(group->Size(), num_devices);
3479 
3480   // Cannot verify here as we will change the number of ases on reconfigure
3481   PrepareConfigureCodecHandler(group, 0, true);
3482   PrepareConfigureQosHandler(group);
3483   PrepareEnableHandler(group);
3484   PrepareDisableHandler(group);
3485   PrepareReleaseHandler(group);
3486   PrepareReceiverStartReady(group);
3487 
3488   InjectInitialIdleNotification(group);
3489 
3490   auto* leAudioDevice = group->GetFirstDevice();
3491   auto expected_devices_written = 0;
3492   while (leAudioDevice) {
3493     /* 8 Writes:
3494      * 1: Codec config (+1 after reconfig)
3495      * 2: Codec QoS (+1 after reconfig)
3496      * 3: Enabling (+1 after reconfig)
3497      * 4: ReceiverStartReady (only for conversational)
3498      * 5: Release
3499      */
3500     EXPECT_CALL(gatt_queue,
3501                 WriteCharacteristic(leAudioDevice->conn_id_,
3502                                     leAudioDevice->ctp_hdls_.val_hdl, _,
3503                                     GATT_WRITE_NO_RSP, _, _))
3504         .Times(8);
3505     expected_devices_written++;
3506     leAudioDevice = group->GetNextDevice(leAudioDevice);
3507   }
3508   ASSERT_EQ(expected_devices_written, num_devices);
3509 
3510   // Validate GroupStreamStatus
3511   EXPECT_CALL(
3512       mock_callbacks_,
3513       StatusReportCb(leaudio_group_id,
3514                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3515 
3516   // Start the configuration and stream Media content
3517   LeAudioGroupStateMachine::Get()->StartStream(
3518       group, initial_context_type, types::AudioContexts(initial_context_type));
3519 
3520   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3521 
3522   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3523   mock_function_count_map["alarm_cancel"] = 0;
3524 
3525   // Validate GroupStreamStatus
3526   EXPECT_CALL(
3527       mock_callbacks_,
3528       StatusReportCb(leaudio_group_id,
3529                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
3530 
3531   EXPECT_CALL(
3532       mock_callbacks_,
3533       StatusReportCb(
3534           leaudio_group_id,
3535           bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
3536   // Start the configuration and stream Media content
3537   LeAudioGroupStateMachine::Get()->StopStream(group);
3538 
3539   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3540   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3541   mock_function_count_map["alarm_cancel"] = 0;
3542 
3543   // Restart stream
3544   EXPECT_CALL(
3545       mock_callbacks_,
3546       StatusReportCb(leaudio_group_id,
3547                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3548 
3549   // Start the configuration and stream Media content
3550   LeAudioGroupStateMachine::Get()->StartStream(
3551       group, new_context_type, types::AudioContexts(new_context_type));
3552 
3553   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3554   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3555 }
3556 
TEST_F(StateMachineTest,lateCisDisconnectedEvent_ConfiguredByUser)3557 TEST_F(StateMachineTest, lateCisDisconnectedEvent_ConfiguredByUser) {
3558   const auto context_type = kContextTypeMedia;
3559   const auto leaudio_group_id = 6;
3560   const auto num_devices = 1;
3561 
3562   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
3563 
3564   // Prepare multiple fake connected devices in a group
3565   auto* group =
3566       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3567   ASSERT_EQ(group->Size(), num_devices);
3568 
3569   PrepareConfigureCodecHandler(group, 0, true);
3570   PrepareConfigureQosHandler(group);
3571   PrepareEnableHandler(group);
3572   PrepareDisableHandler(group);
3573   PrepareReleaseHandler(group);
3574 
3575   auto* leAudioDevice = group->GetFirstDevice();
3576   auto expected_devices_written = 0;
3577 
3578   /* Three Writes:
3579    * 1: Codec Config
3580    * 2: Codec QoS
3581    * 3: Enabling
3582    */
3583   EXPECT_CALL(gatt_queue, WriteCharacteristic(leAudioDevice->conn_id_,
3584                                               leAudioDevice->ctp_hdls_.val_hdl,
3585                                               _, GATT_WRITE_NO_RSP, _, _))
3586       .Times(AtLeast(3));
3587   expected_devices_written++;
3588 
3589   ASSERT_EQ(expected_devices_written, num_devices);
3590 
3591   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3592   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3593   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3594 
3595   InjectInitialIdleNotification(group);
3596 
3597   // Start the configuration and stream Media content
3598   LeAudioGroupStateMachine::Get()->StartStream(
3599       group, static_cast<LeAudioContextType>(context_type),
3600       types::AudioContexts(context_type));
3601 
3602   // Check if group has transitioned to a proper state
3603   ASSERT_EQ(group->GetState(),
3604             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3605   testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
3606 
3607   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3608   mock_function_count_map["alarm_cancel"] = 0;
3609 
3610   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
3611   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
3612 
3613   /* Do reconfiguration */
3614   group->SetPendingConfiguration();
3615 
3616   // Validate GroupStreamStatus
3617   EXPECT_CALL(
3618       mock_callbacks_,
3619       StatusReportCb(leaudio_group_id,
3620                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
3621 
3622   EXPECT_CALL(mock_callbacks_,
3623               StatusReportCb(
3624                   leaudio_group_id,
3625                   bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER))
3626       .Times(0);
3627   LeAudioGroupStateMachine::Get()->StopStream(group);
3628 
3629   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3630 
3631   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
3632 
3633   EXPECT_CALL(mock_callbacks_,
3634               StatusReportCb(
3635                   leaudio_group_id,
3636                   bluetooth::le_audio::GroupStreamStatus::CONFIGURED_BY_USER));
3637 
3638   // Inject CIS and ACL disconnection of first device
3639   InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
3640   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3641   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3642 }
3643 
TEST_F(StateMachineTest,lateCisDisconnectedEvent_AutonomousConfigured)3644 TEST_F(StateMachineTest, lateCisDisconnectedEvent_AutonomousConfigured) {
3645   const auto context_type = kContextTypeMedia;
3646   const auto leaudio_group_id = 6;
3647   const auto num_devices = 1;
3648 
3649   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
3650 
3651   // Prepare multiple fake connected devices in a group
3652   auto* group =
3653       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3654   ASSERT_EQ(group->Size(), num_devices);
3655 
3656   PrepareConfigureCodecHandler(group, 0, true);
3657   PrepareConfigureQosHandler(group);
3658   PrepareEnableHandler(group);
3659   PrepareDisableHandler(group);
3660   PrepareReleaseHandler(group);
3661 
3662   auto* leAudioDevice = group->GetFirstDevice();
3663   auto expected_devices_written = 0;
3664 
3665   /* Three Writes:
3666    * 1: Codec Config
3667    * 2: Codec QoS
3668    * 3: Enabling
3669    */
3670   EXPECT_CALL(gatt_queue, WriteCharacteristic(leAudioDevice->conn_id_,
3671                                               leAudioDevice->ctp_hdls_.val_hdl,
3672                                               _, GATT_WRITE_NO_RSP, _, _))
3673       .Times(AtLeast(3));
3674   expected_devices_written++;
3675 
3676   ASSERT_EQ(expected_devices_written, num_devices);
3677 
3678   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3679   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3680   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3681 
3682   InjectInitialIdleNotification(group);
3683 
3684   // Start the configuration and stream Media content
3685   LeAudioGroupStateMachine::Get()->StartStream(
3686       group, static_cast<LeAudioContextType>(context_type),
3687       types::AudioContexts(context_type));
3688 
3689   // Check if group has transitioned to a proper state
3690   ASSERT_EQ(group->GetState(),
3691             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3692   testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
3693 
3694   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3695   mock_function_count_map["alarm_cancel"] = 0;
3696 
3697   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
3698   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
3699 
3700   // Validate GroupStreamStatus
3701   EXPECT_CALL(
3702       mock_callbacks_,
3703       StatusReportCb(leaudio_group_id,
3704                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
3705 
3706   EXPECT_CALL(
3707       mock_callbacks_,
3708       StatusReportCb(
3709           leaudio_group_id,
3710           bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS))
3711       .Times(0);
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(),
3718             types::AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
3719 
3720   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3721 
3722   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
3723 
3724   EXPECT_CALL(
3725       mock_callbacks_,
3726       StatusReportCb(
3727           leaudio_group_id,
3728           bluetooth::le_audio::GroupStreamStatus::CONFIGURED_AUTONOMOUS));
3729 
3730   // Inject CIS and ACL disconnection of first device
3731   InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
3732   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3733   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3734 }
3735 
TEST_F(StateMachineTest,lateCisDisconnectedEvent_Idle)3736 TEST_F(StateMachineTest, lateCisDisconnectedEvent_Idle) {
3737   const auto context_type = kContextTypeMedia;
3738   const auto leaudio_group_id = 6;
3739   const auto num_devices = 1;
3740 
3741   ContentControlIdKeeper::GetInstance()->SetCcid(media_context, media_ccid);
3742 
3743   // Prepare multiple fake connected devices in a group
3744   auto* group =
3745       PrepareSingleTestDeviceGroup(leaudio_group_id, context_type, num_devices);
3746   ASSERT_EQ(group->Size(), num_devices);
3747 
3748   PrepareConfigureCodecHandler(group);
3749   PrepareConfigureQosHandler(group);
3750   PrepareEnableHandler(group);
3751   PrepareDisableHandler(group);
3752   PrepareReleaseHandler(group);
3753 
3754   auto* leAudioDevice = group->GetFirstDevice();
3755   auto expected_devices_written = 0;
3756 
3757   /* Three Writes:
3758    * 1: Codec Config
3759    * 2: Codec QoS
3760    * 3: Enabling
3761    */
3762   EXPECT_CALL(gatt_queue, WriteCharacteristic(leAudioDevice->conn_id_,
3763                                               leAudioDevice->ctp_hdls_.val_hdl,
3764                                               _, GATT_WRITE_NO_RSP, _, _))
3765       .Times(AtLeast(3));
3766   expected_devices_written++;
3767 
3768   ASSERT_EQ(expected_devices_written, num_devices);
3769 
3770   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(1);
3771   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(1);
3772   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(2);
3773 
3774   InjectInitialIdleNotification(group);
3775 
3776   // Start the configuration and stream Media content
3777   LeAudioGroupStateMachine::Get()->StartStream(
3778       group, static_cast<LeAudioContextType>(context_type),
3779       types::AudioContexts(context_type));
3780 
3781   // Check if group has transitioned to a proper state
3782   ASSERT_EQ(group->GetState(),
3783             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3784   testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
3785 
3786   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3787   mock_function_count_map["alarm_cancel"] = 0;
3788   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
3789   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
3790 
3791   // Validate GroupStreamStatus
3792   EXPECT_CALL(
3793       mock_callbacks_,
3794       StatusReportCb(leaudio_group_id,
3795                      bluetooth::le_audio::GroupStreamStatus::RELEASING));
3796 
3797   EXPECT_CALL(mock_callbacks_,
3798               StatusReportCb(leaudio_group_id,
3799                              bluetooth::le_audio::GroupStreamStatus::IDLE))
3800       .Times(0);
3801 
3802   // Stop the stream
3803   LeAudioGroupStateMachine::Get()->StopStream(group);
3804 
3805   // Check if group has transitioned to a proper state
3806   ASSERT_EQ(group->GetState(), types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
3807   ASSERT_EQ(0, mock_function_count_map["alarm_cancel"]);
3808 
3809   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3810 
3811   EXPECT_CALL(mock_callbacks_,
3812               StatusReportCb(leaudio_group_id,
3813                              bluetooth::le_audio::GroupStreamStatus::IDLE));
3814 
3815   // Inject CIS and ACL disconnection of first device
3816   InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
3817   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3818   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3819 }
3820 
TEST_F(StateMachineTest,StreamReconfigureAfterCisLostTwoDevices)3821 TEST_F(StateMachineTest, StreamReconfigureAfterCisLostTwoDevices) {
3822   auto context_type = kContextTypeConversational;
3823   const auto leaudio_group_id = 4;
3824   const auto num_devices = 2;
3825 
3826   // Prepare multiple fake connected devices in a group
3827   auto* group = PrepareSingleTestDeviceGroup(
3828       leaudio_group_id, context_type, num_devices,
3829       kContextTypeConversational | kContextTypeMedia);
3830   ASSERT_EQ(group->Size(), num_devices);
3831 
3832   PrepareConfigureCodecHandler(group);
3833   PrepareConfigureQosHandler(group);
3834   PrepareEnableHandler(group);
3835   PrepareReceiverStartReady(group);
3836 
3837   /* Prepare DisconnectCis mock to not symulate CisDisconnection */
3838   ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());
3839 
3840   EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(2);
3841   EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(2);
3842   EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(6);
3843   EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
3844   EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
3845   EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);
3846 
3847   InjectInitialIdleNotification(group);
3848 
3849   auto* leAudioDevice = group->GetFirstDevice();
3850   auto expected_devices_written = 0;
3851   while (leAudioDevice) {
3852     EXPECT_CALL(gatt_queue,
3853                 WriteCharacteristic(leAudioDevice->conn_id_,
3854                                     leAudioDevice->ctp_hdls_.val_hdl, _,
3855                                     GATT_WRITE_NO_RSP, _, _))
3856         .Times(3);
3857     expected_devices_written++;
3858     leAudioDevice = group->GetNextDevice(leAudioDevice);
3859   }
3860   ASSERT_EQ(expected_devices_written, num_devices);
3861 
3862   // Validate GroupStreamStatus
3863   EXPECT_CALL(
3864       mock_callbacks_,
3865       StatusReportCb(leaudio_group_id,
3866                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3867 
3868   // Start the configuration and stream Media content
3869   context_type = kContextTypeMedia;
3870   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
3871       group, static_cast<LeAudioContextType>(context_type),
3872       types::AudioContexts(context_type)));
3873 
3874   // Check if group has transitioned to a proper state
3875   ASSERT_EQ(group->GetState(),
3876             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3877   ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
3878   testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
3879   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
3880   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3881 
3882   // Device disconnects due to timeout of CIS
3883   leAudioDevice = group->GetFirstDevice();
3884   while (leAudioDevice) {
3885     InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
3886     // Disconnect device
3887     LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(
3888         group, leAudioDevice);
3889 
3890     leAudioDevice = group->GetNextDevice(leAudioDevice);
3891   }
3892 
3893   LOG(INFO) << "GK A1";
3894   group->ReloadAudioLocations();
3895   group->ReloadAudioDirections();
3896   group->UpdateAudioContextTypeAvailability();
3897 
3898   // Start conversational scenario
3899   leAudioDevice = group->GetFirstDevice();
3900   int device_cnt = num_devices;
3901   while (leAudioDevice) {
3902     LOG(INFO) << "GK A11";
3903     leAudioDevice->conn_id_ = device_cnt--;
3904     leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
3905     leAudioDevice = group->GetNextDevice(leAudioDevice);
3906   }
3907 
3908   LOG(INFO) << "GK A2";
3909   InjectInitialIdleNotification(group);
3910 
3911   group->ReloadAudioLocations();
3912   group->ReloadAudioDirections();
3913   group->UpdateAudioContextTypeAvailability(kContextTypeConversational |
3914                                             kContextTypeMedia);
3915 
3916   leAudioDevice = group->GetFirstDevice();
3917   expected_devices_written = 0;
3918   while (leAudioDevice) {
3919     EXPECT_CALL(gatt_queue,
3920                 WriteCharacteristic(leAudioDevice->conn_id_,
3921                                     leAudioDevice->ctp_hdls_.val_hdl, _,
3922                                     GATT_WRITE_NO_RSP, _, _))
3923         .Times(4);
3924     expected_devices_written++;
3925     leAudioDevice = group->GetNextDevice(leAudioDevice);
3926   }
3927   ASSERT_EQ(expected_devices_written, num_devices);
3928 
3929   // Validate GroupStreamStatus
3930   EXPECT_CALL(
3931       mock_callbacks_,
3932       StatusReportCb(leaudio_group_id,
3933                      bluetooth::le_audio::GroupStreamStatus::STREAMING));
3934 
3935   // Start the configuration and stream Conversational content
3936   context_type = kContextTypeConversational;
3937   ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
3938       group, static_cast<LeAudioContextType>(context_type),
3939       types::AudioContexts(context_type)));
3940 
3941   // Check if group has transitioned to a proper state
3942   ASSERT_EQ(group->GetState(),
3943             types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
3944   ASSERT_EQ(2, mock_function_count_map["alarm_cancel"]);
3945   testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
3946   testing::Mock::VerifyAndClearExpectations(&gatt_queue);
3947   testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
3948 }
3949 
3950 }  // namespace internal
3951 }  // namespace le_audio
3952