Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4a9a1eb authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Gerrit Code Review
Browse files

Merge "le_audio: Clear temporary cises assignement while disconnecting CISes"

parents 570fc219 39713cc7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -837,6 +837,7 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
        }

        LOG_INFO("Lost all members from the group %d", group->group_id_);
        group->cises_.clear();
        RemoveCigForGroup(group);

        group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE);
+130 −0
Original line number Diff line number Diff line
@@ -3814,5 +3814,135 @@ TEST_F(StateMachineTest, lateCisDisconnectedEvent_Idle) {
  testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
  ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
}

TEST_F(StateMachineTest, StreamReconfigureAfterCisLostTwoDevices) {
  auto context_type = kContextTypeConversational;
  const auto leaudio_group_id = 4;
  const auto num_devices = 2;

  // Prepare multiple fake connected devices in a group
  auto* group = PrepareSingleTestDeviceGroup(
      leaudio_group_id, context_type, num_devices,
      kContextTypeConversational | kContextTypeMedia);
  ASSERT_EQ(group->Size(), num_devices);

  PrepareConfigureCodecHandler(group);
  PrepareConfigureQosHandler(group);
  PrepareEnableHandler(group);
  PrepareReceiverStartReady(group);

  /* Prepare DisconnectCis mock to not symulate CisDisconnection */
  ON_CALL(*mock_iso_manager_, DisconnectCis).WillByDefault(Return());

  EXPECT_CALL(*mock_iso_manager_, CreateCig(_, _)).Times(2);
  EXPECT_CALL(*mock_iso_manager_, EstablishCis(_)).Times(2);
  EXPECT_CALL(*mock_iso_manager_, SetupIsoDataPath(_, _)).Times(6);
  EXPECT_CALL(*mock_iso_manager_, RemoveIsoDataPath(_, _)).Times(0);
  EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(0);
  EXPECT_CALL(*mock_iso_manager_, RemoveCig(_, _)).Times(1);

  InjectInitialIdleNotification(group);

  auto* leAudioDevice = group->GetFirstDevice();
  auto expected_devices_written = 0;
  while (leAudioDevice) {
    EXPECT_CALL(gatt_queue,
                WriteCharacteristic(leAudioDevice->conn_id_,
                                    leAudioDevice->ctp_hdls_.val_hdl, _,
                                    GATT_WRITE_NO_RSP, _, _))
        .Times(3);
    expected_devices_written++;
    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }
  ASSERT_EQ(expected_devices_written, num_devices);

  // Validate GroupStreamStatus
  EXPECT_CALL(
      mock_callbacks_,
      StatusReportCb(leaudio_group_id,
                     bluetooth::le_audio::GroupStreamStatus::STREAMING));

  // Start the configuration and stream Media content
  context_type = kContextTypeMedia;
  ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
      group, static_cast<LeAudioContextType>(context_type),
      types::AudioContexts(context_type)));

  // Check if group has transitioned to a proper state
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
  ASSERT_EQ(1, mock_function_count_map["alarm_cancel"]);
  testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
  testing::Mock::VerifyAndClearExpectations(&gatt_queue);
  testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);

  // Device disconnects due to timeout of CIS
  leAudioDevice = group->GetFirstDevice();
  while (leAudioDevice) {
    InjectCisDisconnected(group, leAudioDevice, HCI_ERR_CONN_CAUSE_LOCAL_HOST);
    // Disconnect device
    LeAudioGroupStateMachine::Get()->ProcessHciNotifAclDisconnected(
        group, leAudioDevice);

    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }

  LOG(INFO) << "GK A1";
  group->ReloadAudioLocations();
  group->ReloadAudioDirections();
  group->UpdateAudioContextTypeAvailability();

  // Start conversational scenario
  leAudioDevice = group->GetFirstDevice();
  int device_cnt = num_devices;
  while (leAudioDevice) {
    LOG(INFO) << "GK A11";
    leAudioDevice->conn_id_ = device_cnt--;
    leAudioDevice->SetConnectionState(DeviceConnectState::CONNECTED);
    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }

  LOG(INFO) << "GK A2";
  InjectInitialIdleNotification(group);

  group->ReloadAudioLocations();
  group->ReloadAudioDirections();
  group->UpdateAudioContextTypeAvailability(kContextTypeConversational |
                                            kContextTypeMedia);

  leAudioDevice = group->GetFirstDevice();
  expected_devices_written = 0;
  while (leAudioDevice) {
    EXPECT_CALL(gatt_queue,
                WriteCharacteristic(leAudioDevice->conn_id_,
                                    leAudioDevice->ctp_hdls_.val_hdl, _,
                                    GATT_WRITE_NO_RSP, _, _))
        .Times(4);
    expected_devices_written++;
    leAudioDevice = group->GetNextDevice(leAudioDevice);
  }
  ASSERT_EQ(expected_devices_written, num_devices);

  // Validate GroupStreamStatus
  EXPECT_CALL(
      mock_callbacks_,
      StatusReportCb(leaudio_group_id,
                     bluetooth::le_audio::GroupStreamStatus::STREAMING));

  // Start the configuration and stream Conversational content
  context_type = kContextTypeConversational;
  ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
      group, static_cast<LeAudioContextType>(context_type),
      types::AudioContexts(context_type)));

  // Check if group has transitioned to a proper state
  ASSERT_EQ(group->GetState(),
            types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING);
  ASSERT_EQ(2, mock_function_count_map["alarm_cancel"]);
  testing::Mock::VerifyAndClearExpectations(&mock_iso_manager_);
  testing::Mock::VerifyAndClearExpectations(&gatt_queue);
  testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);
}

}  // namespace internal
}  // namespace le_audio