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

Commit 92c98544 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Automerger Merge Worker
Browse files

Merge "leaudio: Fix invalid ReleaseCmd sent on Codec Configured" into main am: 2f3656c4

parents da085815 2f3656c4
Loading
Loading
Loading
Loading
+18 −27
Original line number Diff line number Diff line
@@ -1923,7 +1923,6 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
        /* TODO: Config Codec */
        break;
      case AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING:
        LeAudioDevice* leAudioDeviceNext;
        SetAseState(leAudioDevice, ase,
                    AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
        ase->active = false;
@@ -1946,14 +1945,7 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
          return;
        }

        leAudioDeviceNext = group->GetNextActiveDevice(leAudioDevice);

        /* Configure ASEs for next device in group */
        if (leAudioDeviceNext) {
          PrepareAndSendRelease(leAudioDeviceNext);
        } else {
        /* Last node is in releasing state*/

        group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
        /* Remote device has cache and keep staying in configured state after
         * release. Therefore, we assume this is a target state requested by
@@ -1974,7 +1966,6 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {

        state_machine_callbacks_->StatusReportCb(
            group->group_id_, GroupStreamStatus::CONFIGURED_AUTONOMOUS);
        }
        break;
      default:
        LOG(ERROR) << __func__ << ", invalid state transition, from: "
+93 −0
Original line number Diff line number Diff line
@@ -183,6 +183,9 @@ class StateMachineTestBase : public Test {
  uint8_t overwrite_cis_status_idx_;
  std::vector<uint8_t> cis_status_;

  /* Keep ASE in releasing state */
  bool stay_in_releasing_state_;

  virtual void SetUp() override {
    bluetooth::common::InitFlags::Load(test_flags);
    reset_mock_function_count_map();
@@ -194,6 +197,7 @@ class StateMachineTestBase : public Test {
    overwrite_cis_status_idx_ = 0;
    overwrite_cis_status_ = false;
    do_not_send_cis_establish_event_ = false;
    stay_in_releasing_state_ = false;
    cis_status_.clear();

    LeAudioGroupStateMachine::Initialize(&mock_callbacks_);
@@ -1255,6 +1259,10 @@ class StateMachineTestBase : public Test {
            InjectAseStateNotification(ase, device, group,
                                       ascs::kAseStateReleasing, nullptr);

            if (stay_in_releasing_state_) {
              continue;
            }

            /* Check if codec configuration is cached */
            if (cached_codec_configuration_map_.count(ase_id) > 0) {
              InjectAseStateNotification(
@@ -3501,6 +3509,91 @@ TEST_F(StateMachineTest, testAseAutonomousRelease2Devices) {
  }
}

TEST_F(StateMachineTest, testHandlingCachedCodecConfig2Devices) {
  const auto context_type = kContextTypeConversational;
  const int leaudio_group_id = 4;
  const int num_of_devices = 2;

  // Prepare fake connected device group
  auto* group = PrepareSingleTestDeviceGroup(leaudio_group_id, context_type,
                                             num_of_devices);

  auto* firstDevice = group->GetFirstDevice();
  auto* secondDevice = group->GetNextDevice(firstDevice);

  /* Since we prepared device with Conversional context in mind, Sink and Source
   * ASEs should have been configured.
   */
  PrepareConfigureCodecHandler(group, 0, true);
  PrepareConfigureQosHandler(group);
  PrepareEnableHandler(group);
  PrepareDisableHandler(group);
  PrepareReceiverStartReady(group);
  PrepareReceiverStopReady(group);
  PrepareReleaseHandler(group);

  stay_in_releasing_state_ = true;

  /* Number of control point calls
   * 1. Codec Config
   * 2. QoS Config
   * 3. Enable
   * 4. Receiver Start Ready
   * 5. Release*/
  EXPECT_CALL(gatt_queue, WriteCharacteristic(firstDevice->conn_id_,
                                              firstDevice->ctp_hdls_.val_hdl, _,
                                              GATT_WRITE_NO_RSP, _, _))
      .Times(5);

  EXPECT_CALL(gatt_queue, WriteCharacteristic(secondDevice->conn_id_,
                                              secondDevice->ctp_hdls_.val_hdl,
                                              _, GATT_WRITE_NO_RSP, _, _))
      .Times(5);

  InjectInitialIdleNotification(group);

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

  // Start the configuration and stream Media content
  ASSERT_TRUE(LeAudioGroupStateMachine::Get()->StartStream(
      group, context_type,
      {.sink = types::AudioContexts(context_type),
       .source = types::AudioContexts(context_type)}));

  testing::Mock::VerifyAndClearExpectations(&mock_callbacks_);

  /* Single disconnect as it is bidirectional Cis*/
  EXPECT_CALL(*mock_iso_manager_, DisconnectCis(_, _)).Times(2);

  LOG_ERROR("STOP");
  // Stop the stream
  LeAudioGroupStateMachine::Get()->StopStream(group);

  for (auto& ase : firstDevice->ases_) {
    LOG_ERROR("%s , %d, %s", ADDRESS_TO_LOGGABLE_CSTR(firstDevice->address_),
              ase.id, bluetooth::common::ToString(ase.state).c_str());
    ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING);
    // Simulate autonomus configured state.
    InjectAseStateNotification(&ase, firstDevice, group,
                               ascs::kAseStateCodecConfigured,
                               &cached_codec_configuration_map_[ase.id]);
  }

  for (auto& ase : secondDevice->ases_) {
    LOG_ERROR("%s , %d, %s", ADDRESS_TO_LOGGABLE_CSTR(firstDevice->address_),
              ase.id, bluetooth::common::ToString(ase.state).c_str());
    ASSERT_EQ(ase.state, types::AseState::BTA_LE_AUDIO_ASE_STATE_RELEASING);
    // Simulate autonomus configured state.
    InjectAseStateNotification(&ase, secondDevice, group,
                               ascs::kAseStateCodecConfigured,
                               &cached_codec_configuration_map_[ase.id]);
  }
}

TEST_F(StateMachineTest, testStateTransitionTimeoutOnIdleState) {
  const auto context_type = kContextTypeRingtone;
  const int leaudio_group_id = 4;