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

Commit f5c39150 authored by Alice Kuo's avatar Alice Kuo
Browse files

Seperate audio allocation and connection status configuraiton update

With the patch, we change flow and remove downmix property. As the stream started, the bluetooth stack will update the target allocation to the bluetooth audio HAL. If part of cises are not connected, the stack will update the audio configuration again with the streamMap that contains the current allocation.

Bug: 231084798
Test: check the audio configuration update sequence as downmix_fallback_
enable/disable
Test: atest bluetooth_le_audio_test

Change-Id: Ic5d4bb8b3f265499657f2d162b3616e1b377adbb
parent 0eca2b96
Loading
Loading
Loading
Loading
+15 −2
Original line number Original line Diff line number Diff line
@@ -2520,6 +2520,12 @@ class LeAudioClientImpl : public LeAudioClient {
    leAudioClientAudioSource->UpdateRemoteDelay(remote_delay_ms);
    leAudioClientAudioSource->UpdateRemoteDelay(remote_delay_ms);
    leAudioClientAudioSource->ConfirmStreamingRequest();
    leAudioClientAudioSource->ConfirmStreamingRequest();
    audio_sender_state_ = AudioState::STARTED;
    audio_sender_state_ = AudioState::STARTED;
    /* We update the target audio allocation before streamStarted that the
     * offloder would know how to configure offloader encoder. We should check
     * if we need to update the current
     * allocation here as the target allocation and the current allocation is
     * different */
    updateOffloaderIfNeeded(group);


    return true;
    return true;
  }
  }
@@ -2578,6 +2584,12 @@ class LeAudioClientImpl : public LeAudioClient {
    leAudioClientAudioSink->UpdateRemoteDelay(remote_delay_ms);
    leAudioClientAudioSink->UpdateRemoteDelay(remote_delay_ms);
    leAudioClientAudioSink->ConfirmStreamingRequest();
    leAudioClientAudioSink->ConfirmStreamingRequest();
    audio_receiver_state_ = AudioState::STARTED;
    audio_receiver_state_ = AudioState::STARTED;
    /* We update the target audio allocation before streamStarted that the
     * offloder would know how to configure offloader decoder. We should check
     * if we need to update the current
     * allocation here as the target allocation and the current allocation is
     * different */
    updateOffloaderIfNeeded(group);
  }
  }


  void SuspendAudio(void) {
  void SuspendAudio(void) {
@@ -3504,7 +3516,7 @@ class LeAudioClientImpl : public LeAudioClient {


    const auto* stream_conf = &group->stream_conf;
    const auto* stream_conf = &group->stream_conf;


    if (stream_conf->sink_offloader_changed) {
    if (stream_conf->sink_offloader_changed || stream_conf->sink_is_initial) {
      LOG_INFO("Update sink offloader streams");
      LOG_INFO("Update sink offloader streams");
      uint16_t remote_delay_ms =
      uint16_t remote_delay_ms =
          group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSink);
          group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSink);
@@ -3515,7 +3527,8 @@ class LeAudioClientImpl : public LeAudioClient {
      group->StreamOffloaderUpdated(le_audio::types::kLeAudioDirectionSink);
      group->StreamOffloaderUpdated(le_audio::types::kLeAudioDirectionSink);
    }
    }


    if (stream_conf->source_offloader_changed) {
    if (stream_conf->source_offloader_changed ||
        stream_conf->source_is_initial) {
      LOG_INFO("Update source offloader streams");
      LOG_INFO("Update source offloader streams");
      uint16_t remote_delay_ms =
      uint16_t remote_delay_ms =
          group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSource);
          group->GetRemoteDelay(le_audio::types::kLeAudioDirectionSource);
+14 −2
Original line number Original line Diff line number Diff line
@@ -89,7 +89,13 @@ struct codec_manager_impl {
          update_receiver) {
          update_receiver) {
    if (stream_conf.sink_streams.empty()) return;
    if (stream_conf.sink_streams.empty()) return;


    sink_config.stream_map = std::move(stream_conf.sink_offloader_streams);
    if (stream_conf.sink_is_initial) {
      sink_config.stream_map =
          stream_conf.sink_offloader_streams_target_allocation;
    } else {
      sink_config.stream_map =
          stream_conf.sink_offloader_streams_current_allocation;
    }
    // TODO: set the default value 16 for now, would change it if we support
    // TODO: set the default value 16 for now, would change it if we support
    // mode bits_per_sample
    // mode bits_per_sample
    sink_config.bits_per_sample = 16;
    sink_config.bits_per_sample = 16;
@@ -107,7 +113,13 @@ struct codec_manager_impl {
          update_receiver) {
          update_receiver) {
    if (stream_conf.source_streams.empty()) return;
    if (stream_conf.source_streams.empty()) return;


    source_config.stream_map = std::move(stream_conf.source_offloader_streams);
    if (stream_conf.source_is_initial) {
      source_config.stream_map =
          stream_conf.source_offloader_streams_target_allocation;
    } else {
      source_config.stream_map =
          stream_conf.source_offloader_streams_current_allocation;
    }
    // TODO: set the default value 16 for now, would change it if we support
    // TODO: set the default value 16 for now, would change it if we support
    // mode bits_per_sample
    // mode bits_per_sample
    source_config.bits_per_sample = 16;
    source_config.bits_per_sample = 16;
+50 −29
Original line number Original line Diff line number Diff line
@@ -109,7 +109,8 @@ int LeAudioDeviceGroup::NumOfConnected(types::LeAudioContextType context_type) {
void LeAudioDeviceGroup::ClearSinksFromConfiguration(void) {
void LeAudioDeviceGroup::ClearSinksFromConfiguration(void) {
  LOG_INFO("Group %p, group_id %d", this, group_id_);
  LOG_INFO("Group %p, group_id %d", this, group_id_);
  stream_conf.sink_streams.clear();
  stream_conf.sink_streams.clear();
  stream_conf.sink_offloader_streams.clear();
  stream_conf.sink_offloader_streams_target_allocation.clear();
  stream_conf.sink_offloader_streams_current_allocation.clear();
  stream_conf.sink_audio_channel_allocation = 0;
  stream_conf.sink_audio_channel_allocation = 0;
  stream_conf.sink_num_of_channels = 0;
  stream_conf.sink_num_of_channels = 0;
  stream_conf.sink_num_of_devices = 0;
  stream_conf.sink_num_of_devices = 0;
@@ -122,7 +123,8 @@ void LeAudioDeviceGroup::ClearSinksFromConfiguration(void) {
void LeAudioDeviceGroup::ClearSourcesFromConfiguration(void) {
void LeAudioDeviceGroup::ClearSourcesFromConfiguration(void) {
  LOG_INFO("Group %p, group_id %d", this, group_id_);
  LOG_INFO("Group %p, group_id %d", this, group_id_);
  stream_conf.source_streams.clear();
  stream_conf.source_streams.clear();
  stream_conf.source_offloader_streams.clear();
  stream_conf.source_offloader_streams_target_allocation.clear();
  stream_conf.source_offloader_streams_current_allocation.clear();
  stream_conf.source_audio_channel_allocation = 0;
  stream_conf.source_audio_channel_allocation = 0;
  stream_conf.source_num_of_channels = 0;
  stream_conf.source_num_of_channels = 0;
  stream_conf.source_num_of_devices = 0;
  stream_conf.source_num_of_devices = 0;
@@ -1636,9 +1638,9 @@ bool LeAudioDeviceGroup::IsMetadataChanged(


void LeAudioDeviceGroup::StreamOffloaderUpdated(uint8_t direction) {
void LeAudioDeviceGroup::StreamOffloaderUpdated(uint8_t direction) {
  if (direction == le_audio::types::kLeAudioDirectionSource) {
  if (direction == le_audio::types::kLeAudioDirectionSource) {
    stream_conf.source_offloader_changed = false;
    stream_conf.source_is_initial = false;
  } else {
  } else {
    stream_conf.sink_offloader_changed = false;
    stream_conf.sink_is_initial = false;
  }
  }
}
}


@@ -1650,23 +1652,35 @@ void LeAudioDeviceGroup::CreateStreamVectorForOffloader(uint8_t direction) {


  CisType cis_type;
  CisType cis_type;
  std::vector<std::pair<uint16_t, uint32_t>>* streams;
  std::vector<std::pair<uint16_t, uint32_t>>* streams;
  std::vector<std::pair<uint16_t, uint32_t>>* offloader_streams;
  std::vector<std::pair<uint16_t, uint32_t>>*
      offloader_streams_target_allocation;
  std::vector<std::pair<uint16_t, uint32_t>>*
      offloader_streams_current_allocation;
  std::string tag;
  std::string tag;
  uint32_t available_allocations = 0;
  uint32_t available_allocations = 0;
  bool* changed_flag;
  bool* changed_flag;
  bool* is_initial;
  if (direction == le_audio::types::kLeAudioDirectionSource) {
  if (direction == le_audio::types::kLeAudioDirectionSource) {
    changed_flag = &stream_conf.source_offloader_changed;
    changed_flag = &stream_conf.source_offloader_changed;
    is_initial = &stream_conf.source_is_initial;
    cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE;
    cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SOURCE;
    streams = &stream_conf.source_streams;
    streams = &stream_conf.source_streams;
    offloader_streams = &stream_conf.source_offloader_streams;
    offloader_streams_target_allocation =
        &stream_conf.source_offloader_streams_target_allocation;
    offloader_streams_current_allocation =
        &stream_conf.source_offloader_streams_current_allocation;
    tag = "Source";
    tag = "Source";
    available_allocations = AdjustAllocationForOffloader(
    available_allocations = AdjustAllocationForOffloader(
        stream_conf.source_audio_channel_allocation);
        stream_conf.source_audio_channel_allocation);
  } else {
  } else {
    changed_flag = &stream_conf.sink_offloader_changed;
    changed_flag = &stream_conf.sink_offloader_changed;
    is_initial = &stream_conf.sink_is_initial;
    cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SINK;
    cis_type = CisType::CIS_TYPE_UNIDIRECTIONAL_SINK;
    streams = &stream_conf.sink_streams;
    streams = &stream_conf.sink_streams;
    offloader_streams = &stream_conf.sink_offloader_streams;
    offloader_streams_target_allocation =
        &stream_conf.sink_offloader_streams_target_allocation;
    offloader_streams_current_allocation =
        &stream_conf.sink_offloader_streams_current_allocation;
    tag = "Sink";
    tag = "Sink";
    available_allocations =
    available_allocations =
        AdjustAllocationForOffloader(stream_conf.sink_audio_channel_allocation);
        AdjustAllocationForOffloader(stream_conf.sink_audio_channel_allocation);
@@ -1677,26 +1691,24 @@ void LeAudioDeviceGroup::CreateStreamVectorForOffloader(uint8_t direction) {
    return;
    return;
  }
  }


  if (offloader_streams->size() > 0) {
  if (offloader_streams_target_allocation->size() == 0) {
    /* We are here because of the CIS modification during streaming.
    *is_initial = true;
     * this makes sense only when downmixing is enabled so we can notify
     * offloader about connected / disconnected CISes. If downmixing is disabled
     * then there is not need to notify offloader as it has all the informations
     * already */
    if (!downmix_fallback_) {
      LOG_INFO("Downmixing disabled - nothing to do");
      return;
    }
  }
  }


  offloader_streams->clear();
  offloader_streams_current_allocation->clear();
  *changed_flag = true;
  *changed_flag = true;

  bool not_all_cises_connected = false;
  bool not_all_cises_connected = false;
  if (available_allocations != codec_spec_conf::kLeAudioLocationStereo) {
  if (available_allocations != codec_spec_conf::kLeAudioLocationStereo) {
    not_all_cises_connected = true;
    not_all_cises_connected = true;
  }
  }


  /* If the all cises are connected as stream started, reset changed_flag that
   * the bt stack wouldn't send another audio configuration for the connection
   * status */
  if (*is_initial && !not_all_cises_connected) {
    *changed_flag = false;
  }

  /* Note: For the offloader case we simplify allocation to only Left and Right.
  /* Note: For the offloader case we simplify allocation to only Left and Right.
   * If we need 2 CISes and only one is connected, the connected one will have
   * If we need 2 CISes and only one is connected, the connected one will have
   * allocation set to stereo (left | right) and other one will have allocation
   * allocation set to stereo (left | right) and other one will have allocation
@@ -1710,28 +1722,37 @@ void LeAudioDeviceGroup::CreateStreamVectorForOffloader(uint8_t direction) {
    if ((cis_entry.type == CisType::CIS_TYPE_BIDIRECTIONAL ||
    if ((cis_entry.type == CisType::CIS_TYPE_BIDIRECTIONAL ||
         cis_entry.type == cis_type) &&
         cis_entry.type == cis_type) &&
        cis_entry.conn_handle != 0) {
        cis_entry.conn_handle != 0) {
      uint32_t allocation = 0;
      uint32_t target_allocation = 0;
      uint32_t current_allocation = 0;
      for (const auto& s : *streams) {
      for (const auto& s : *streams) {
        if (s.first == cis_entry.conn_handle) {
        if (s.first == cis_entry.conn_handle) {
          allocation = AdjustAllocationForOffloader(s.second);
          target_allocation = AdjustAllocationForOffloader(s.second);
          if (not_all_cises_connected && downmix_fallback_) {
          current_allocation = target_allocation;
          if (not_all_cises_connected) {
            /* Tell offloader to mix on this CIS.*/
            /* Tell offloader to mix on this CIS.*/
            allocation = codec_spec_conf::kLeAudioLocationStereo;
            current_allocation = codec_spec_conf::kLeAudioLocationStereo;
          }
          }
          break;
          break;
        }
        }
      }
      }


      if (allocation == 0 && !downmix_fallback_) {
      if (target_allocation == 0) {
        /* Take missing allocation for that one .*/
        /* Take missing allocation for that one .*/
        allocation =
        target_allocation =
            codec_spec_conf::kLeAudioLocationStereo & ~available_allocations;
            codec_spec_conf::kLeAudioLocationStereo & ~available_allocations;
      }
      }


      LOG_INFO("%s: Cis handle 0x%04x, allocation  0x%08x", tag.c_str(),
      LOG_INFO(
               cis_entry.conn_handle, allocation);
          "%s: Cis handle 0x%04x, target allocation  0x%08x, current "
      offloader_streams->emplace_back(
          "allocation 0x%08x",
          std::make_pair(cis_entry.conn_handle, allocation));
          tag.c_str(), cis_entry.conn_handle, target_allocation,
          current_allocation);
      if (*is_initial) {
        offloader_streams_target_allocation->emplace_back(
            std::make_pair(cis_entry.conn_handle, target_allocation));
      }
      offloader_streams_current_allocation->emplace_back(
          std::make_pair(cis_entry.conn_handle, current_allocation));
    }
    }
  }
  }
}
}
+1 −6
Original line number Original line Diff line number Diff line
@@ -214,9 +214,7 @@ class LeAudioDeviceGroup {
        pending_update_available_contexts_(std::nullopt),
        pending_update_available_contexts_(std::nullopt),
        target_state_(types::AseState::BTA_LE_AUDIO_ASE_STATE_IDLE),
        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),
        context_type_(types::LeAudioContextType::UNINITIALIZED) {
        context_type_(types::LeAudioContextType::UNINITIALIZED) {}
    downmix_fallback_ = osi_property_get_bool(kDownmixFallback, false);
  }
  ~LeAudioDeviceGroup(void);
  ~LeAudioDeviceGroup(void);


  void AddNode(const std::shared_ptr<LeAudioDevice>& leAudioDevice);
  void AddNode(const std::shared_ptr<LeAudioDevice>& leAudioDevice);
@@ -349,9 +347,6 @@ class LeAudioDeviceGroup {
           const set_configurations::AudioSetConfiguration*>
           const set_configurations::AudioSetConfiguration*>
      active_context_to_configuration_map;
      active_context_to_configuration_map;


  static constexpr char kDownmixFallback[] =
      "persist.bluetooth.leaudio.offloader.downmix_fallback";
  bool downmix_fallback_;
  types::AseState target_state_;
  types::AseState target_state_;
  types::AseState current_state_;
  types::AseState current_state_;
  types::LeAudioContextType context_type_;
  types::LeAudioContextType context_type_;
+14 −2
Original line number Original line Diff line number Diff line
@@ -703,8 +703,14 @@ struct stream_configuration {
  int sink_num_of_devices;
  int sink_num_of_devices;
  /* cis_handle, audio location*/
  /* cis_handle, audio location*/
  std::vector<std::pair<uint16_t, uint32_t>> sink_streams;
  std::vector<std::pair<uint16_t, uint32_t>> sink_streams;
  std::vector<std::pair<uint16_t, uint32_t>> sink_offloader_streams;
  /* cis_handle, target allocation */
  std::vector<std::pair<uint16_t, uint32_t>>
      sink_offloader_streams_target_allocation;
  /* cis_handle, current allocation */
  std::vector<std::pair<uint16_t, uint32_t>>
      sink_offloader_streams_current_allocation;
  bool sink_offloader_changed;
  bool sink_offloader_changed;
  bool sink_is_initial;


  /* Source configuration */
  /* Source configuration */
  /* For now we have always same frequency for all the channels */
  /* For now we have always same frequency for all the channels */
@@ -718,8 +724,14 @@ struct stream_configuration {
  int source_num_of_devices;
  int source_num_of_devices;
  /* cis_handle, audio location*/
  /* cis_handle, audio location*/
  std::vector<std::pair<uint16_t, uint32_t>> source_streams;
  std::vector<std::pair<uint16_t, uint32_t>> source_streams;
  std::vector<std::pair<uint16_t, uint32_t>> source_offloader_streams;
  /* cis_handle, target allocation */
  std::vector<std::pair<uint16_t, uint32_t>>
      source_offloader_streams_target_allocation;
  /* cis_handle, current allocation */
  std::vector<std::pair<uint16_t, uint32_t>>
      source_offloader_streams_current_allocation;
  bool source_offloader_changed;
  bool source_offloader_changed;
  bool source_is_initial;
};
};


void AppendMetadataLtvEntryForCcidList(std::vector<uint8_t>& metadata,
void AppendMetadataLtvEntryForCcidList(std::vector<uint8_t>& metadata,
Loading