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

Commit 5503ac01 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge "leaudio: Fix group IsInTransition" into main

parents ad3c29e4 cc80a791
Loading
Loading
Loading
Loading
+1 −3
Original line number Diff line number Diff line
@@ -832,9 +832,7 @@ bool LeAudioDeviceGroup::ReloadAudioDirections(void) {
  return true;
}

bool LeAudioDeviceGroup::IsInTransition(void) const {
  return target_state_ != current_state_;
}
bool LeAudioDeviceGroup::IsInTransition(void) const { return in_transition_; }

bool LeAudioDeviceGroup::IsStreaming(void) const {
  return current_state_ == AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
+18 −5
Original line number Diff line number Diff line
@@ -110,7 +110,8 @@ class LeAudioDeviceGroup {
        pending_group_available_contexts_change_(
            types::LeAudioContextType::UNINITIALIZED),
        target_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE),
        current_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {
        current_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE),
        in_transition_(false) {
#ifdef __ANDROID__
    // 22 maps to BluetoothProfile#LE_AUDIO
    is_output_preference_le_audio = android::sysprop::BluetoothProperties::
@@ -227,13 +228,19 @@ class LeAudioDeviceGroup {

  inline types::AseState GetState(void) const { return current_state_; }
  void SetState(types::AseState state) {
    LOG(INFO) << __func__ << " current state: " << current_state_
              << " new state: " << state;
    LOG_INFO(" current state: %s, new state %s, in_transition_ %d",
             bluetooth::common::ToString(current_state_).c_str(),
             bluetooth::common::ToString(state).c_str(), in_transition_);
    LeAudioLogHistory::Get()->AddLogHistory(
        kLogStateMachineTag, group_id_, RawAddress::kEmpty, kLogStateChangedOp,
        bluetooth::common::ToString(current_state_) + "->" +
            bluetooth::common::ToString(state));
    current_state_ = state;

    if (target_state_ == current_state_) {
      in_transition_ = false;
      LOG_INFO("In transition flag cleared");
    }
  }

  inline types::AseState GetTargetState(void) const { return target_state_; }
@@ -244,14 +251,19 @@ class LeAudioDeviceGroup {
    return notify_streaming_when_cises_are_ready_;
  }
  void SetTargetState(types::AseState state) {
    LOG(INFO) << __func__ << " target state: " << target_state_
              << " new target state: " << state;
    LOG_INFO("target state: %s, new target state: %s, in_transition_ %d",
             bluetooth::common::ToString(target_state_).c_str(),
             bluetooth::common::ToString(state).c_str(), in_transition_);
    LeAudioLogHistory::Get()->AddLogHistory(
        kLogStateMachineTag, group_id_, RawAddress::kEmpty,
        kLogTargetStateChangedOp,
        bluetooth::common::ToString(target_state_) + "->" +
            bluetooth::common::ToString(state));

    target_state_ = state;

    in_transition_ = target_state_ != current_state_;
    LOG_INFO("In transition flag  = %d", in_transition_);
  }

  /* Returns context types for which support was recently added or removed */
@@ -396,6 +408,7 @@ class LeAudioDeviceGroup {

  types::AseState target_state_;
  types::AseState current_state_;
  bool in_transition_;
  std::vector<std::weak_ptr<LeAudioDevice>> leAudioDevices_;
};

+7 −3
Original line number Diff line number Diff line
@@ -1871,6 +1871,10 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
          /* This is autonomus change of the remote device */
          LOG_DEBUG("Autonomus change for device %s, ase id %d. Just store it.",
                    ADDRESS_TO_LOGGABLE_CSTR(leAudioDevice->address_), ase->id);

          /* Since at least one ASE is in configured state, we should admit
           * group is configured state */
          group->SetState(AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED);
          return;
        }

@@ -2044,7 +2048,7 @@ class LeAudioGroupStateMachineImpl : public LeAudioGroupStateMachine {
          return;
        }

        LOG_ERROR(", Autonomouse change, from: %s to %s",
        LOG_INFO("Autonomous change, from: %s to %s",
                 ToString(group->GetState()).c_str(),
                 ToString(group->GetTargetState()).c_str());

+86 −0
Original line number Diff line number Diff line
@@ -808,6 +808,26 @@ class StateMachineTestBase : public Test {
    }
  }

  void InjectInitialIdleAndConfiguredNotification(LeAudioDeviceGroup* group) {
    for (auto* device = group->GetFirstDevice(); device != nullptr;
         device = group->GetNextDevice(device)) {
      int i = 0;
      for (auto& ase : device->ases_) {
        if (i % 2 == 1) {
          InjectAseStateNotification(&ase, device, group, ascs::kAseStateIdle,
                                     nullptr);
        } else {
          client_parser::ascs::ase_codec_configured_state_params
              codec_configured_state_params;
          InjectAseStateNotification(&ase, device, group,
                                     ascs::kAseStateCodecConfigured,
                                     &codec_configured_state_params);
        }
        i++;
      }
    }
  }

  void MultipleTestDevicePrepare(int leaudio_group_id,
                                 LeAudioContextType context_type,
                                 uint16_t device_cnt,
@@ -3843,6 +3863,72 @@ TEST_F(StateMachineTest, testAseAutonomousRelease2Devices) {
  }
}

TEST_F(StateMachineTest, testHandlingAutonomousCodecConfigStateOnConnection) {
  /* Scenario
   * 1. After connection remote device has different ASE configurations
   * 2. Try to start stream and make sure it is configured well.
   */

  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);
  PrepareReceiverStartReadyHandler(group);
  PrepareReceiverStopReady(group);

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

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

  InjectInitialIdleAndConfiguredNotification(group);
  // Call it second time to make sure we get into state that current_state_ is
  // different then target_state_ even group is not in transition.
  InjectInitialIdleAndConfiguredNotification(group);

  ASSERT_TRUE(group->GetTargetState() != group->GetState());
  ASSERT_FALSE(group->IsInTransition());

  // 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_);
}

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