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

Commit 39b3aefb authored by Łukasz Rymanowski's avatar Łukasz Rymanowski
Browse files

leaudio: Improve configuration and reconfiguration

With this patch after reconfiguration(e.g. when metadata changed),
group stays in the CONFIGURED state and does not go to STREAMING as
before. Instread Audio Hal gets suspended.
Group will go to streaming when Audio Hal tries to resume stream.

Also, with this patch, if ASEs are alread configured, state machine will
do QoS Config right away without trying to do Codec Config.

Bug: 222674521
Bug: 150670922
Test: atest --bluetooth_le_audio_test bluetoot_le_audio_client_test

Change-Id: Ibe771914f57732015d8dd57688cac84fee0cd296
parent f21ef791
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -227,6 +227,19 @@ void BluetoothAudioPortAidl::ControlResultHandler(
            << ", status=" << toString(status);

  switch (previous_state) {
    case BluetoothStreamState::STARTED:
      /* Only Suspend signal can be send in STARTED state*/
      if (status == BluetoothAudioStatus::RECONFIGURATION ||
          status == BluetoothAudioStatus::SUCCESS) {
        state_ = BluetoothStreamState::STANDBY;
      } else {
        // Set to standby since the stack may be busy switching between outputs
        LOG(WARNING) << "control_result_cb: status=" << toString(status)
                     << " failure for session_type=" << toString(session_type_)
                     << ", cookie=" << StringPrintf("%#hx", cookie_)
                     << ", previous_state=" << previous_state;
      }
      break;
    case BluetoothStreamState::STARTING:
      if (status == BluetoothAudioStatus::SUCCESS) {
        state_ = BluetoothStreamState::STARTED;
+13 −0
Original line number Diff line number Diff line
@@ -251,6 +251,19 @@ void BluetoothAudioPortHidl::ControlResultHandler(
            << ", status=" << toString(status);

  switch (previous_state) {
    case BluetoothStreamState::STARTED:
      /* Only Suspend signal can be send in STARTED state*/
      if (status == BluetoothAudioStatus::SUCCESS) {
        state_ = BluetoothStreamState::STANDBY;
      } else {
        // Set to standby since the stack may be busy switching between outputs
        LOG(WARNING) << "control_result_cb: status=" << toString(status)
                     << " failure for session_type="
                     << toString(session_type_hidl_)
                     << ", cookie=" << StringPrintf("%#hx", cookie_)
                     << ", previous_state=" << previous_state;
      }
      break;
    case BluetoothStreamState::STARTING:
      if (status == BluetoothAudioStatusHidl::SUCCESS) {
        state_ = BluetoothStreamState::STARTED;
+4 −12
Original line number Diff line number Diff line
@@ -229,12 +229,8 @@ void LeAudioClientInterface::Sink::UpdateAudioConfigToHal(
void LeAudioClientInterface::Sink::SuspendedForReconfiguration() {
  if (HalVersionManager::GetHalTransport() ==
      BluetoothAudioHalTransport::HIDL) {
    return;
  }

  if (aidl::le_audio::LeAudioSinkTransport::interface->GetTransportInstance()
          ->GetSessionType() !=
      aidl::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
    hidl::le_audio::LeAudioSinkTransport::interface->StreamSuspended(
        hidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED);
    return;
  }

@@ -343,12 +339,8 @@ void LeAudioClientInterface::Source::StartSession() {
void LeAudioClientInterface::Source::SuspendedForReconfiguration() {
  if (HalVersionManager::GetHalTransport() ==
      BluetoothAudioHalTransport::HIDL) {
    return;
  }

  if (aidl::le_audio::LeAudioSourceTransport::interface->GetTransportInstance()
          ->GetSessionType() !=
      aidl::SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
    hidl::le_audio::LeAudioSourceTransport::interface->StreamSuspended(
        hidl::BluetoothAudioCtrlAck::SUCCESS_FINISHED);
    return;
  }

+48 −47
Original line number Diff line number Diff line
@@ -1784,7 +1784,7 @@ class LeAudioClientImpl : public LeAudioClient {

    if (num_of_devices < group->NumOfConnected()) {
      /* Second device got just paired. We need to reconfigure CIG */
      stream_conf->reconfiguration_ongoing = true;
      group->SetPendingConfiguration();
      groupStateMachine_->StopStream(group);
      return;
    }
@@ -2739,7 +2739,7 @@ class LeAudioClientImpl : public LeAudioClient {
            /* If group is reconfiguring, reassing state and wait for
             * the stream to be established
             */
            if (group->stream_conf.reconfiguration_ongoing) {
            if (group->IsPendingConfiguration()) {
              audio_sender_state_ = audio_receiver_state_;
              return;
            }
@@ -2873,7 +2873,7 @@ class LeAudioClientImpl : public LeAudioClient {
            /* If group is reconfiguring, reassing state and wait for
             * the stream to be established
             */
            if (group->stream_conf.reconfiguration_ongoing) {
            if (group->IsPendingConfiguration()) {
              audio_receiver_state_ = audio_sender_state_;
              return;
            }
@@ -3004,8 +3004,8 @@ class LeAudioClientImpl : public LeAudioClient {
    if (alarm_is_scheduled(suspend_timeout_)) alarm_cancel(suspend_timeout_);

    /* Need to reconfigure stream */
    group->stream_conf.reconfiguration_ongoing = true;
    GroupStop(group->group_id_);
    group->SetPendingConfiguration();
    groupStateMachine_->StopStream(group);
    return true;
  }

@@ -3216,44 +3216,17 @@ class LeAudioClientImpl : public LeAudioClient {
        rxUnreceivedPackets, duplicatePackets);
  }

  bool IsSuspendedForReconfiguration(int group_id) {
    if (group_id != active_group_id_) return false;

    DLOG(INFO) << __func__ << " audio_sender_state_: " << audio_sender_state_
               << " audio_receiver_state_: " << audio_receiver_state_;

    auto group = aseGroups_.FindById(group_id);
    if (!group) return false;

    auto stream_conf = &group->stream_conf;
    DLOG(INFO) << __func__ << " stream_conf->reconfiguration_ongoing "
               << stream_conf->reconfiguration_ongoing;

    return stream_conf->reconfiguration_ongoing;
  void CompleteUserConfiguration(LeAudioDeviceGroup* group) {
    if (audio_sender_state_ == AudioState::RELEASING) {
      audio_sender_state_ = AudioState::IDLE;
    }

  bool RestartStreamingAfterReconfiguration(int group_id) {
    auto group = aseGroups_.FindById(group_id);
    LOG_ASSERT(group) << __func__ << " group does not exist: " << group_id;

    if (groupStateMachine_->StartStream(
            group, static_cast<LeAudioContextType>(current_context_type_))) {
      if (audio_sender_state_ == AudioState::RELEASING)
        audio_sender_state_ = AudioState::READY_TO_START;

      if (audio_receiver_state_ == AudioState::RELEASING)
        audio_receiver_state_ = AudioState::READY_TO_START;
    } else {
    if (audio_receiver_state_ == AudioState::RELEASING) {
      audio_receiver_state_ = AudioState::IDLE;
      audio_sender_state_ = AudioState::IDLE;
    }

    group->stream_conf.reconfiguration_ongoing = false;
    return true;
  }

  void HandlePendingAvailableContexts(int group_id) {
    LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
  void HandlePendingAvailableContexts(LeAudioDeviceGroup* group) {
    if (!group) return;

    /* Update group configuration with pending available context */
@@ -3275,9 +3248,10 @@ class LeAudioClientImpl : public LeAudioClient {
  }

  void StatusReportCb(int group_id, GroupStreamStatus status) {
    DLOG(INFO) << __func__ << "status: " << static_cast<int>(status)
    LOG(INFO) << __func__ << "status: " << static_cast<int>(status)
              << " audio_sender_state_: " << audio_sender_state_
              << " audio_receiver_state_: " << audio_receiver_state_;
    LeAudioDeviceGroup* group = aseGroups_.FindById(group_id);
    switch (status) {
      case GroupStreamStatus::STREAMING:
        LOG_ASSERT(group_id == active_group_id_)
@@ -3292,20 +3266,47 @@ class LeAudioClientImpl : public LeAudioClient {
            bluetooth::common::time_get_os_boottime_us();
        break;
      case GroupStreamStatus::SUSPENDED:
        stream_setup_end_timestamp_ = 0;
        stream_setup_start_timestamp_ = 0;
        /** Stop Audio but don't release all the Audio resources */
        SuspendAudio();
        break;
      case GroupStreamStatus::IDLE: {
      case GroupStreamStatus::CONFIGURED_BY_USER:
        CompleteUserConfiguration(group);
        break;
      case GroupStreamStatus::CONFIGURED_AUTONOMOUS:
        /* This state is notified only when
         * groups stays into CONFIGURED state after
         * STREAMING. Peer device uses cache.
         * */
        stream_setup_end_timestamp_ = 0;
        stream_setup_start_timestamp_ = 0;
        if (IsSuspendedForReconfiguration(group_id)) {

        /* Check if stream was stopped for reconfiguration */
        if (group->IsPendingConfiguration()) {
          SuspendedForReconfiguration();
          RestartStreamingAfterReconfiguration(group_id);
        } else {
          if (!groupStateMachine_->ConfigureStream(group,
                                                   current_context_type_)) {
            // DO SOMETHING
          }
          return;
        }
        CancelStreamingRequest();
        HandlePendingAvailableContexts(group);
        break;
      case GroupStreamStatus::IDLE: {
        stream_setup_end_timestamp_ = 0;
        stream_setup_start_timestamp_ = 0;
        if (group && group->IsPendingConfiguration()) {
          SuspendedForReconfiguration();
          if (!groupStateMachine_->ConfigureStream(group,
                                                   current_context_type_)) {
            // DO SOMETHING
          }

        HandlePendingAvailableContexts(group_id);
          return;
        }
        CancelStreamingRequest();
        HandlePendingAvailableContexts(group);
        break;
      }
      case GroupStreamStatus::RELEASING:
+34 −2
Original line number Diff line number Diff line
@@ -107,6 +107,14 @@ void LeAudioDeviceGroup::Deactivate(void) {
  }
}

void LeAudioDeviceGroup::Activate(void) {
  for (auto leAudioDevice : leAudioDevices_) {
    if (leAudioDevice.expired()) continue;

    leAudioDevice.lock()->ActivateConfiguredAses();
  }
}

LeAudioDevice* LeAudioDeviceGroup::GetFirstDevice(void) {
  auto d = leAudioDevices_.front();
  if (d.expired()) return nullptr;
@@ -1120,6 +1128,14 @@ types::LeAudioContextType LeAudioDeviceGroup::GetCurrentContextType(void) {
  return active_context_type_;
}

bool LeAudioDeviceGroup::IsPendingConfiguration(void) {
  return stream_conf.pending_configuration;
}

void LeAudioDeviceGroup::SetPendingConfiguration(void) {
  stream_conf.pending_configuration = true;
}

const set_configurations::AudioSetConfiguration*
LeAudioDeviceGroup::FindFirstSupportedConfiguration(
    LeAudioContextType context_type) {
@@ -1197,8 +1213,8 @@ void LeAudioDeviceGroup::Dump(int fd) {
         << "      active stream configuration name: "
         << (active_conf ? active_conf->name : " not set") << "\n"
         << "    Last used stream configuration: \n"
         << "      reconfiguration_ongoing: "
         << stream_conf.reconfiguration_ongoing << "\n"
         << "      pending_configuration: " << stream_conf.pending_configuration
         << "\n"
         << "      codec id : " << +(stream_conf.id.coding_format) << "\n"
         << "      name: "
         << (stream_conf.conf != nullptr ? stream_conf.conf->name : " null ")
@@ -1660,6 +1676,22 @@ AudioContexts LeAudioDevice::SetAvailableContexts(AudioContexts snk_contexts,
  return updated_contexts;
}

void LeAudioDevice::ActivateConfiguredAses(void) {
  if (conn_id_ == GATT_INVALID_CONN_ID) {
    LOG_DEBUG(" Device %s is not connected ", address_.ToString().c_str());
    return;
  }

  LOG_DEBUG(" Configuring device %s", address_.ToString().c_str());
  for (auto& ase : ases_) {
    if (!ase.active &&
        ase.state == AseState::BTA_LE_AUDIO_ASE_STATE_CODEC_CONFIGURED) {
      LOG_DEBUG(" Ase id %d, cis id %d activated.", ase.id, ase.cis_id);
      ase.active = true;
    }
  }
}

void LeAudioDevice::DeactivateAllAses(void) {
  /* Just clear states and keep previous configuration for use
   * in case device will get reconnected
Loading