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

Commit fb0e030b authored by Jakub Tyszkowski's avatar Jakub Tyszkowski
Browse files

LeAudio: Clean-up the QoS structures in ASE

Bug: 308427707
Flag: EXEMPT; only grouped the fields into structures - mechanical refactor - correctness confirmed with unit tests
Test: atest --host bluetooth_le_audio_test bluetooth_le_audio_client_test  bluetooth_test_broadcaster bluetooth_test_broadcaster_state_machine bluetooth_le_audio_codec_manager_test --disable-upload-result --minimal-build --no-metrics
Change-Id: I3bbda232fca9da8ea1ba14187568b0e89898ae65
parent 3ade1f68
Loading
Loading
Loading
Loading
+28 −22
Original line number Diff line number Diff line
@@ -449,8 +449,7 @@ uint32_t LeAudioDeviceGroup::GetSduInterval(uint8_t direction) const {
       leAudioDevice = GetNextActiveDevice(leAudioDevice)) {
    struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
    if (!ase) continue;

    return ase->codec_config.GetAsCoreCodecConfig().GetFrameDurationUs();
    return ase->qos_config.sdu_interval;
  }

  return 0;
@@ -494,7 +493,8 @@ uint8_t LeAudioDeviceGroup::GetFraming(void) const {
    if (!ase) continue;

    do {
      if (ase->framing == types::kFramingUnframedPduUnsupported)
      if (ase->qos_preferences.supported_framing ==
          types::kFramingUnframedPduUnsupported)
        return bluetooth::hci::kIsoCigFramingFramed;
    } while ((ase = leAudioDevice->GetNextActiveAse(ase)));
  } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));
@@ -517,10 +517,11 @@ static uint16_t find_max_transport_latency(const LeAudioDeviceGroup* group,

      if (max_transport_latency == 0) {
        // first assignment
        max_transport_latency = ase->max_transport_latency;
      } else if (ase->max_transport_latency < max_transport_latency) {
        if (ase->max_transport_latency != 0) {
          max_transport_latency = ase->max_transport_latency;
        max_transport_latency = ase->qos_config.max_transport_latency;
      } else if (ase->qos_config.max_transport_latency <
                 max_transport_latency) {
        if (ase->qos_config.max_transport_latency != 0) {
          max_transport_latency = ase->qos_config.max_transport_latency;
        } else {
          LOG_WARN("Trying to set latency back to 0, ASE ID %d", ase->id);
        }
@@ -595,10 +596,10 @@ uint8_t LeAudioDeviceGroup::GetRtn(uint8_t direction, uint8_t cis_id) const {
    auto ases_pair = leAudioDevice->GetAsesByCisId(cis_id);

    if (ases_pair.sink && direction == types::kLeAudioDirectionSink) {
      return ases_pair.sink->retrans_nb;
      return ases_pair.sink->qos_config.retrans_nb;
    } else if (ases_pair.source &&
               direction == types::kLeAudioDirectionSource) {
      return ases_pair.source->retrans_nb;
      return ases_pair.source->qos_config.retrans_nb;
    }
  } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));

@@ -615,10 +616,10 @@ uint16_t LeAudioDeviceGroup::GetMaxSduSize(uint8_t direction,
    auto ases_pair = leAudioDevice->GetAsesByCisId(cis_id);

    if (ases_pair.sink && direction == types::kLeAudioDirectionSink) {
      return ases_pair.sink->max_sdu_size;
      return ases_pair.sink->qos_config.max_sdu_size;
    } else if (ases_pair.source &&
               direction == types::kLeAudioDirectionSource) {
      return ases_pair.source->max_sdu_size;
      return ases_pair.source->qos_config.max_sdu_size;
    }
  } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));

@@ -649,15 +650,16 @@ uint8_t LeAudioDeviceGroup::GetPhyBitmask(uint8_t direction) const {
        phy_bitfield &= leAudioDevice->GetPhyBitmask();

        // A value of 0x00 denotes no preference
        if (ase->preferred_phy && (phy_bitfield & ase->preferred_phy)) {
          phy_bitfield &= ase->preferred_phy;
        if (ase->qos_preferences.preferred_phy &&
            (phy_bitfield & ase->qos_preferences.preferred_phy)) {
          phy_bitfield &= ase->qos_preferences.preferred_phy;
          LOG_DEBUG("Using ASE preferred phy 0x%02x",
                    static_cast<int>(phy_bitfield));
        } else {
          LOG_WARN(
              "ASE preferred 0x%02x has nothing common with phy_bitfield "
              "0x%02x ",
              static_cast<int>(ase->preferred_phy),
              static_cast<int>(ase->qos_preferences.preferred_phy),
              static_cast<int>(phy_bitfield));
        }
      }
@@ -696,16 +698,20 @@ bool LeAudioDeviceGroup::GetPresentationDelay(uint32_t* delay,

    do {
      /* No common range check */
      if (ase->pres_delay_min > delay_max || ase->pres_delay_max < delay_min)
      if (ase->qos_preferences.pres_delay_min > delay_max ||
          ase->qos_preferences.pres_delay_max < delay_min)
        return false;

      if (ase->pres_delay_min > delay_min) delay_min = ase->pres_delay_min;
      if (ase->pres_delay_max < delay_max) delay_max = ase->pres_delay_max;
      if (ase->preferred_pres_delay_min > preferred_delay_min)
        preferred_delay_min = ase->preferred_pres_delay_min;
      if (ase->preferred_pres_delay_max < preferred_delay_max &&
          ase->preferred_pres_delay_max != types::kPresDelayNoPreference)
        preferred_delay_max = ase->preferred_pres_delay_max;
      if (ase->qos_preferences.pres_delay_min > delay_min)
        delay_min = ase->qos_preferences.pres_delay_min;
      if (ase->qos_preferences.pres_delay_max < delay_max)
        delay_max = ase->qos_preferences.pres_delay_max;
      if (ase->qos_preferences.preferred_pres_delay_min > preferred_delay_min)
        preferred_delay_min = ase->qos_preferences.preferred_pres_delay_min;
      if (ase->qos_preferences.preferred_pres_delay_max < preferred_delay_max &&
          ase->qos_preferences.preferred_pres_delay_max !=
              types::kPresDelayNoPreference)
        preferred_delay_max = ase->qos_preferences.preferred_pres_delay_max;
    } while ((ase = leAudioDevice->GetNextActiveAseWithSameDirection(ase)));
  } while ((leAudioDevice = GetNextActiveDevice(leAudioDevice)));

+56 −27
Original line number Diff line number Diff line
@@ -289,14 +289,15 @@ bool LeAudioDevice::ConfigureAses(
            GetMaxCodecFramesPerSduFromPac(pac));
      }

      /* Recalculate Max SDU size */
      auto core_config = ent.codec.params.GetAsCoreCodecConfig();
      ase->max_sdu_size = core_config.GetChannelCountPerIsoStream() *
                          core_config.octets_per_codec_frame.value_or(0) *
                          core_config.codec_frames_blocks_per_sdu.value_or(1);
      /* Recalculate Max SDU size from the Core codec config */
      ase->qos_config.max_sdu_size =
          ase->codec_config.GetAsCoreCodecConfig().CalculateMaxSduSize();
      /* Get the SDU interval from the Core codec config */
      ase->qos_config.sdu_interval =
          ase->codec_config.GetAsCoreCodecConfig().GetFrameDurationUs();

      ase->retrans_nb = ent.qos.retransmission_number;
      ase->max_transport_latency = ent.qos.max_transport_latency;
      ase->qos_config.retrans_nb = ent.qos.retransmission_number;
      ase->qos_config.max_transport_latency = ent.qos.max_transport_latency;

      SetMetadataToAse(ase, metadata_context_types, ccid_lists);
    }
@@ -305,8 +306,8 @@ bool LeAudioDevice::ConfigureAses(
        "device=%s, activated ASE id=%d, direction=%s, max_sdu_size=%d, "
        "cis_id=%d, target_latency=%d",
        ADDRESS_TO_LOGGABLE_CSTR(address_), ase->id,
        (ent.direction == 1 ? "snk" : "src"), ase->max_sdu_size, ase->cis_id,
        ent.qos.target_latency);
        (ent.direction == 1 ? "snk" : "src"), ase->qos_config.max_sdu_size,
        ase->cis_id, ent.qos.target_latency);

    /* Try to use the already active ASE */
    ase = GetNextActiveAseWithSameDirection(ase);
@@ -764,7 +765,7 @@ LeAudioDevice::GetCodecConfigurationSupportedPac(
/**
 * Returns supported PHY's bitfield
 */
uint8_t LeAudioDevice::GetPhyBitmask(void) {
uint8_t LeAudioDevice::GetPhyBitmask(void) const {
  uint8_t phy_bitfield = kIsoCigPhy1M;

  if (BTM_IsPhy2mSupported(address_, BT_TRANSPORT_LE))
@@ -784,18 +785,21 @@ void LeAudioDevice::PrintDebugState(void) {
  if (ases_.size() > 0) {
    debug_str << "\n  == ASEs == ";
    for (auto& ase : ases_) {
      debug_str << "\n  id: " << +ase.id << ", active: " << ase.active
                << ", dir: "
                << (ase.direction == types::kLeAudioDirectionSink ? "sink"
                                                                  : "source")
      debug_str
          << "\n  id: " << +ase.id << ", active: " << ase.active << ", dir: "
          << (ase.direction == types::kLeAudioDirectionSink ? "sink" : "source")
          << ", cis_id: " << +ase.cis_id
          << ", cis_handle: " << +ase.cis_conn_hdl
          << ", state: " << bluetooth::common::ToString(ase.cis_state)
          << ", data_path_state: "
          << bluetooth::common::ToString(ase.data_path_state)
                << "\n ase max_latency: " << +ase.max_transport_latency
                << ", rtn: " << +ase.retrans_nb
                << ", max_sdu: " << +ase.max_sdu_size
          << "\n ase max_latency: " << +ase.qos_config.max_transport_latency
          << ", rtn: " << +ase.qos_config.retrans_nb
          << ", max_sdu: " << +ase.qos_config.max_sdu_size
          << ", sdu_interval: " << +ase.qos_config.sdu_interval
          << ", presentation_delay: " << +ase.qos_config.presentation_delay
          << ", framing: " << +ase.qos_config.framing
          << ", phy: " << +ase.qos_config.phy
          << ", target latency: " << +ase.target_latency;
    }
  }
@@ -803,6 +807,29 @@ void LeAudioDevice::PrintDebugState(void) {
  LOG_INFO("%s", debug_str.str().c_str());
}

uint8_t LeAudioDevice::GetPreferredPhyBitmask(uint8_t preferred_phy) const {
  // Start with full local phy support
  uint8_t phy_bitmask = bluetooth::hci::kIsoCigPhy1M;
  if (controller_get_interface()->SupportsBle2mPhy())
    phy_bitmask |= bluetooth::hci::kIsoCigPhy2M;
  if (controller_get_interface()->SupportsBleCodedPhy())
    phy_bitmask |= bluetooth::hci::kIsoCigPhyC;

  // Check against the remote device support
  phy_bitmask &= GetPhyBitmask();

  // Take the preferences if possible
  if (preferred_phy && (phy_bitmask & preferred_phy)) {
    phy_bitmask &= preferred_phy;
    LOG_DEBUG("Using ASE preferred phy 0x%02x", static_cast<int>(phy_bitmask));
  } else {
    LOG_WARN(
        "ASE preferred 0x%02x has nothing common with phy_bitfield  0x%02x ",
        static_cast<int>(preferred_phy), static_cast<int>(phy_bitmask));
  }
  return phy_bitmask;
}

void LeAudioDevice::DumpPacsDebugState(std::stringstream& stream,
                                       types::PublishedAudioCapabilities pacs) {
  if (pacs.size() > 0) {
@@ -882,10 +909,12 @@ void LeAudioDevice::Dump(int fd) {
                                                               : "source")
             << std::left << std::setw(8) << static_cast<int>(ase.cis_id)
             << std::left << std::setw(12) << ase.cis_conn_hdl << std::left
             << std::setw(5) << ase.max_sdu_size << std::left << std::setw(8)
             << ase.max_transport_latency << std::left << std::setw(5)
             << static_cast<int>(ase.retrans_nb) << std::left << std::setw(10)
             << bluetooth::common::ToString(ase.cis_state) << std::setw(12)
             << std::setw(5) << ase.qos_config.max_sdu_size << std::left
             << std::setw(8) << ase.qos_config.max_transport_latency
             << std::left << std::setw(5)
             << static_cast<int>(ase.qos_config.retrans_nb) << std::left
             << std::setw(10) << bluetooth::common::ToString(ase.cis_state)
             << std::setw(12)
             << bluetooth::common::ToString(ase.data_path_state);
    }
  }
+2 −1
Original line number Diff line number Diff line
@@ -186,7 +186,8 @@ class LeAudioDevice {
      uint8_t direction,
      const set_configurations::CodecConfigSetting& codec_capability_setting);
  uint8_t GetSupportedAudioChannelCounts(uint8_t direction) const;
  uint8_t GetPhyBitmask(void);
  uint8_t GetPhyBitmask(void) const;
  uint8_t GetPreferredPhyBitmask(uint8_t preferred_phy) const;
  bool ConfigureAses(
      const le_audio::set_configurations::SetConfiguration& ent,
      types::LeAudioContextType context_type,
+4 −4
Original line number Diff line number Diff line
@@ -1054,10 +1054,10 @@ class UnicastTestNoInit : public Test {
              ase.cis_state = types::CisState::CONNECTED;
              ase.data_path_state = types::DataPathState::CONFIGURED;
              ase.state = types::AseState::BTA_LE_AUDIO_ASE_STATE_STREAMING;
              ase.pres_delay_min = 2500;
              ase.pres_delay_max = 2500;
              ase.preferred_pres_delay_min = 2500;
              ase.preferred_pres_delay_max = 2500;
              ase.qos_preferences.pres_delay_min = 2500;
              ase.qos_preferences.pres_delay_max = 2500;
              ase.qos_preferences.preferred_pres_delay_min = 2500;
              ase.qos_preferences.preferred_pres_delay_max = 2500;
              auto core_config = ase.codec_config.GetAsCoreCodecConfig();

              uint16_t cis_conn_hdl = ase.cis_conn_hdl;
+29 −18
Original line number Diff line number Diff line
@@ -591,6 +591,11 @@ struct LeAudioCoreCodecConfig {
  uint8_t GetChannelCountPerIsoStream(void) const {
    return allocated_channel_count;
  }

  uint16_t CalculateMaxSduSize() const {
    return GetChannelCountPerIsoStream() * octets_per_codec_frame.value_or(0) *
           codec_frames_blocks_per_sdu.value_or(1);
  }
};

struct LeAudioCoreCodecCapabilities {
@@ -927,6 +932,26 @@ struct hdl_pair {
  uint16_t ccc_hdl = 0;
};

struct AseQosConfiguration {
  uint32_t presentation_delay = 0;
  uint32_t sdu_interval = 0;
  uint16_t max_transport_latency = 0;
  uint16_t max_sdu_size = 0;
  uint8_t retrans_nb = 0;
  uint8_t framing = 0;
  uint8_t phy = 0;
};

struct AseQosPreferences {
  uint8_t supported_framing = 0;
  uint8_t preferred_phy = 0;
  uint8_t preferred_retrans_nb = 0;
  uint32_t pres_delay_min = 0;
  uint32_t pres_delay_max = 0;
  uint32_t preferred_pres_delay_min = 0;
  uint32_t preferred_pres_delay_max = 0;
};

struct ase {
  static constexpr uint8_t kAseIdInvalid = 0x00;

@@ -942,16 +967,8 @@ struct ase {
        cis_state(CisState::IDLE),
        data_path_state(DataPathState::IDLE),
        configured_for_context_type(LeAudioContextType::UNINITIALIZED),
        preferred_phy(0),
        is_codec_in_controller(false),
        data_path_id(bluetooth::hci::iso_manager::kIsoDataPathDisabled),
        max_sdu_size(0),
        retrans_nb(0),
        max_transport_latency(0),
        pres_delay_min(0),
        pres_delay_max(0),
        preferred_pres_delay_min(0),
        preferred_pres_delay_max(0),
        autonomous_operation_timer_(nullptr),
        autonomous_target_state_(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE),
        state(AseState::BTA_LE_AUDIO_ASE_STATE_IDLE) {}
@@ -973,9 +990,6 @@ struct ase {
  LeAudioCodecId codec_id;
  LeAudioLtvMap codec_config;

  uint8_t framing;
  uint8_t preferred_phy;

  /* Set to true, if the codec is implemented in BT controller, false if it's
   * implemented in host, or in separate DSP
   */
@@ -984,13 +998,10 @@ struct ase {
  uint8_t data_path_id;

  /* Qos configuration */
  uint16_t max_sdu_size;
  uint8_t retrans_nb;
  uint16_t max_transport_latency;
  uint32_t pres_delay_min;
  uint32_t pres_delay_max;
  uint32_t preferred_pres_delay_min;
  uint32_t preferred_pres_delay_max;
  AseQosConfiguration qos_config;

  /* QoS requirements in Codec Configured state */
  AseQosPreferences qos_preferences;

  std::vector<uint8_t> metadata;

Loading