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

Commit 0f368dfd authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Recover on CIG not being removed on BT OFF

If BT OFF is done while ISO streming, stack might not have time to
remove CIG, as there are still CISes avalable.
Current stack design does not allow to wait for CIS to be disconnected
in such a case, therefor this patch, which tries to recover when
Creating CIG will endup with COMMAND DISALLOWED.

Note: This happens only when BT Controller is not Reseted on BT OFF due
to other activities.

Bug: 228351333
Bug: 246304525
Tag: #feature
Test: atest BluetoothInstrumentationTests
Test: manual: BT OFF while streaming Le Audio, then BT ON and start stream
Change-Id: I0a86e8851491cf147fe6f84ddd86be3466ef6c64
parent 110dda3d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -579,8 +579,8 @@ uint32_t AdjustAllocationForOffloader(uint32_t allocation) {

namespace types {
std::ostream& operator<<(std::ostream& os, const types::CigState& state) {
  static const char* char_value_[4] = {"NONE", "CREATING", "CREATED",
                                       "REMOVING"};
  static const char* char_value_[5] = {"NONE", "CREATING", "CREATED",
                                       "REMOVING", "RECOVERING"};

  os << char_value_[static_cast<uint8_t>(state)] << " ("
     << "0x" << std::setfill('0') << std::setw(2) << static_cast<int>(state)
+1 −1
Original line number Diff line number Diff line
@@ -311,7 +311,7 @@ constexpr uint16_t kMaxTransportLatencyMin = 0x0005;
constexpr uint16_t kMaxTransportLatencyMax = 0x0FA0;

/* Enums */
enum class CigState : uint8_t { NONE, CREATING, CREATED, REMOVING };
enum class CigState : uint8_t { NONE, CREATING, CREATED, REMOVING, RECOVERING };

/* ASE states according to BAP defined state machine states */
enum class AseState : uint8_t {
+3 −1
Original line number Diff line number Diff line
@@ -58,7 +58,9 @@ void IsoManager::ReconfigureCig(
  pimpl_->ReconfigureCig(cig_id, std::move(cig_params));
}

void IsoManager::RemoveCig(uint8_t cig_id) { pimpl_->RemoveCig(cig_id); }
void IsoManager::RemoveCig(uint8_t cig_id, bool force) {
  pimpl_->RemoveCig(cig_id, force);
}

void IsoManager::EstablishCis(
    struct iso_manager::cis_establish_params conn_params) {
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ struct MockIsoManager {
      (void), ReconfigureCig,
      (uint8_t cig_id,
       struct bluetooth::hci::iso_manager::cig_create_params cig_params));
  MOCK_METHOD((void), RemoveCig, (uint8_t cig_id));
  MOCK_METHOD((void), RemoveCig, (uint8_t cig_id, bool force));
  MOCK_METHOD(
      (void), EstablishCis,
      (struct bluetooth::hci::iso_manager::cis_establish_params conn_params));
+33 −0
Original line number Diff line number Diff line
@@ -362,6 +362,18 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
    }

    if (status != HCI_SUCCESS) {
      if (status == HCI_ERR_COMMAND_DISALLOWED) {
        /*
         * We are here, because stack has no chance to remove CIG when it was
         * shut during streaming. In the same time, controller probably was not
         * Reseted, which creates the issue. Lets remove CIG and try to create
         * it again.
         */
        group->SetCigState(CigState::RECOVERING);
        IsoManager::GetInstance()->RemoveCig(group->group_id_, true);
        return;
      }

      group->SetCigState(CigState::NONE);
      LOG_ERROR(", failed to create CIG, reason: 0x%02x, new cig state: %s",
                +status, ToString(group->cig_state_).c_str());
@@ -405,8 +417,29 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
    leAudioDevice->link_quality_timer = nullptr;
  }

  void ProcessHciNotifyOnCigRemoveRecovering(uint8_t status,
                                             LeAudioDeviceGroup* group) {
    group->SetCigState(CigState::NONE);

    if (status != HCI_SUCCESS) {
      LOG_ERROR(
          "Could not recover from the COMMAND DISALLOAD on CigCreate. Status "
          "on CIG remove is 0x%02x",
          status);
      StopStream(group);
      return;
    }
    LOG_INFO("Succeed on CIG Recover - back to creating CIG");
    CigCreate(group);
  }

  void ProcessHciNotifOnCigRemove(uint8_t status,
                                  LeAudioDeviceGroup* group) override {
    if (group->GetCigState() == CigState::RECOVERING) {
      ProcessHciNotifyOnCigRemoveRecovering(status, group);
      return;
    }

    if (status != HCI_SUCCESS) {
      group->SetCigState(CigState::CREATED);
      LOG_ERROR(
Loading