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

Commit 8ae60938 authored by Łukasz Rymanowski's avatar Łukasz Rymanowski Committed by Gerrit Code Review
Browse files

Merge changes I12a64a0b,I575510a1,Id5361805 into main

* changes:
  LeAudioServiceTest: Improve test setup and teardown
  LeAudio: Introduce capabilities struct
  LeAudio: Use LTV map in CodecConfigSetting and ase struct
parents cbd68d32 d3a21fdd
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -358,6 +358,11 @@ public class LeAudioService extends ProfileService {
    }

    private void init() {
        if (!isAvailable()) {
            Log.e(TAG, " Service disabled before init");
            return;
        }

        if (!mTmapStarted) {
            mTmapStarted = registerTmap();
        }
+12 −2
Original line number Diff line number Diff line
@@ -171,6 +171,11 @@ public class LeAudioServiceTest {
        LeAudioObjectsFactory.setInstanceForTesting(mObjectsFactory);
        doReturn(mTmapGattServer).when(mObjectsFactory).getTmapGattServer(any());

        /* If previous test failed, make sure to clear adapter. */
        if (AdapterService.getAdapterService() != null) {
            TestUtils.clearAdapterService(AdapterService.getAdapterService());
        }

        TestUtils.setAdapterService(mAdapterService);
        doReturn(MAX_LE_AUDIO_CONNECTIONS).when(mAdapterService).getMaxConnectedAudioDevices();
        doReturn(new ParcelUuid[]{BluetoothUuid.LE_AUDIO}).when(mAdapterService)
@@ -242,11 +247,16 @@ public class LeAudioServiceTest {
            return;
        }

        if (mLeAudioIntentReceiver != null) {
            mTargetContext.unregisterReceiver(mLeAudioIntentReceiver);
        }

        mBondedDevices.clear();
        mGroupIntentQueue.clear();
        stopService();
        if (mDeviceQueueMap != null) {
            mDeviceQueueMap.clear();
        }
        TestUtils.clearAdapterService(mAdapterService);
        LeAudioNativeInterface.setInstance(null);
    }
+39 −22
Original line number Diff line number Diff line
@@ -492,22 +492,31 @@ bool hal_ucast_capability_to_stack_format(
          octets_per_frame_map.end() ||
      audio_location_map.find(supported_channel) == audio_location_map.end()) {
    LOG(ERROR) << __func__ << ": Failed to convert HAL format to stack format"
               << "\nsample rate = " << sample_rate_hz
               << "\nframe duration = " << frame_duration_us
               << "\nsample rate hz = " << sample_rate_hz
               << "\nframe duration us = " << frame_duration_us
               << "\noctets per frame= " << octets_per_frame
               << "\naudio location = " << toString(supported_channel);
               << "\nsupported channel = " << toString(supported_channel)
               << "\nchannel count per device = " << channel_count
               << "\ndevice count = " << hal_capability.deviceCount;

    return false;
  }

  stack_capability = {
      .id = ::le_audio::set_configurations::LeAudioCodecIdLc3,
      .config = LeAudioCoreCodecConfig(
          {.sampling_frequency = sampling_freq_map[sample_rate_hz],
           .frame_duration = frame_duration_map[frame_duration_us],
           .audio_channel_allocation = audio_location_map[supported_channel],
           .octets_per_codec_frame = octets_per_frame_map[octets_per_frame],
           .channel_count = static_cast<uint8_t>(channel_count)})};
  stack_capability.id = ::le_audio::set_configurations::LeAudioCodecIdLc3;
  stack_capability.channel_count_per_iso_stream = channel_count;

  stack_capability.params.Add(
      ::le_audio::codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
      sampling_freq_map[sample_rate_hz]);
  stack_capability.params.Add(
      ::le_audio::codec_spec_conf::kLeAudioLtvTypeFrameDuration,
      frame_duration_map[frame_duration_us]);
  stack_capability.params.Add(
      ::le_audio::codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
      audio_location_map[supported_channel]);
  stack_capability.params.Add(
      ::le_audio::codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame,
      octets_per_frame_map[octets_per_frame]);
  return true;
}

@@ -546,22 +555,30 @@ bool hal_bcast_capability_to_stack_format(
      audio_location_map.find(supported_channel) == audio_location_map.end()) {
    LOG(WARNING) << __func__
                 << " : Failed to convert HAL format to stack format"
                 << "\nsample rate = " << sample_rate_hz
                 << "\nframe duration = " << frame_duration_us
                 << "\nsample rate hz = " << sample_rate_hz
                 << "\nframe duration us = " << frame_duration_us
                 << "\noctets per frame= " << octets_per_frame
                 << "\naudio location = " << toString(supported_channel);
                 << "\nsupported channel = " << toString(supported_channel)
                 << "\nchannel count per stream = " << channel_count;

    return false;
  }

  stack_capability = {
      .id = ::le_audio::set_configurations::LeAudioCodecIdLc3,
      .config = LeAudioCoreCodecConfig(
          {.sampling_frequency = sampling_freq_map[sample_rate_hz],
           .frame_duration = frame_duration_map[frame_duration_us],
           .audio_channel_allocation = audio_location_map[supported_channel],
           .octets_per_codec_frame = octets_per_frame_map[octets_per_frame],
           .channel_count = static_cast<uint8_t>(channel_count)})};
  stack_capability.id = ::le_audio::set_configurations::LeAudioCodecIdLc3;
  stack_capability.channel_count_per_iso_stream = channel_count;

  stack_capability.params.Add(
      ::le_audio::codec_spec_conf::kLeAudioLtvTypeSamplingFreq,
      sampling_freq_map[sample_rate_hz]);
  stack_capability.params.Add(
      ::le_audio::codec_spec_conf::kLeAudioLtvTypeFrameDuration,
      frame_duration_map[frame_duration_us]);
  stack_capability.params.Add(
      ::le_audio::codec_spec_conf::kLeAudioLtvTypeAudioChannelAllocation,
      audio_location_map[supported_channel]);
  stack_capability.params.Add(
      ::le_audio::codec_spec_conf::kLeAudioLtvTypeOctetsPerCodecFrame,
      octets_per_frame_map[octets_per_frame]);
  return true;
}

+10 −7
Original line number Diff line number Diff line
@@ -188,10 +188,12 @@ struct codec_manager_impl {
        continue;
      }
      auto& adsp_config = adsp_audio_set_conf.confs[0];

      const types::LeAudioCoreCodecConfig core_config =
          std::get<types::LeAudioCoreCodecConfig>(adsp_config.codec.config);
          adsp_config.codec.params.GetAsCoreCodecConfig();
      le_audio::broadcast_offload_config broadcast_config;
      broadcast_config.stream_map.resize(core_config.channel_count);
      broadcast_config.stream_map.resize(
          core_config.GetChannelCountPerIsoStream());
      broadcast_config.bits_per_sample =
          LeAudioCodecConfiguration::kBitsPerSample16;
      broadcast_config.sampling_rate = core_config.GetSamplingFrequencyHz();
@@ -385,22 +387,23 @@ struct codec_manager_impl {
  }

  bool IsLc3ConfigMatched(
      const set_configurations::CodecConfigSetting& adsp_config,
      const set_configurations::CodecConfigSetting& target_config) {
      const set_configurations::CodecConfigSetting& target_config,
      const set_configurations::CodecConfigSetting& adsp_config) {
    if (adsp_config.id.coding_format != types::kLeAudioCodingFormatLC3 ||
        target_config.id.coding_format != types::kLeAudioCodingFormatLC3) {
      return false;
    }

    const types::LeAudioCoreCodecConfig adsp_lc3_config =
        std::get<types::LeAudioCoreCodecConfig>(adsp_config.config);
        adsp_config.params.GetAsCoreCodecConfig();
    const types::LeAudioCoreCodecConfig target_lc3_config =
        std::get<types::LeAudioCoreCodecConfig>(target_config.config);
        target_config.params.GetAsCoreCodecConfig();

    if (adsp_lc3_config.sampling_frequency !=
            target_lc3_config.sampling_frequency ||
        adsp_lc3_config.frame_duration != target_lc3_config.frame_duration ||
        adsp_lc3_config.channel_count != target_lc3_config.channel_count ||
        adsp_config.GetChannelCountPerIsoStream() !=
            target_config.GetChannelCountPerIsoStream() ||
        adsp_lc3_config.octets_per_codec_frame !=
            target_lc3_config.octets_per_codec_frame) {
      return false;
+45 −46
Original line number Diff line number Diff line
@@ -449,7 +449,7 @@ uint32_t LeAudioDeviceGroup::GetSduInterval(uint8_t direction) const {
    struct ase* ase = leAudioDevice->GetFirstActiveAseByDirection(direction);
    if (!ase) continue;

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

  return 0;
@@ -899,11 +899,12 @@ types::LeAudioConfigurationStrategy LeAudioDeviceGroup::GetGroupStrategy(
  }

  auto device = GetFirstDevice();
  auto channel_cnt =
      device->GetLc3SupportedChannelCount(types::kLeAudioDirectionSink);
  LOG_DEBUG("Channel count for group %d is %d (device %s)", group_id_,
            channel_cnt, ADDRESS_TO_LOGGABLE_CSTR(device->address_));
  if (channel_cnt == 1) {
  auto channel_count_bitmap =
      device->GetSupportedAudioChannelCounts(types::kLeAudioDirectionSink);
  LOG_DEBUG("Supported channel counts for group %d (device %s) is %d",
            group_id_, ADDRESS_TO_LOGGABLE_CSTR(device->address_),
            channel_count_bitmap);
  if (channel_count_bitmap == 1) {
    return types::LeAudioConfigurationStrategy::STEREO_TWO_CISES_PER_DEVICE;
  }

@@ -1180,11 +1181,18 @@ void LeAudioDeviceGroup::CigConfiguration::UnassignCis(
}

bool CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,
                              types::AudioLocations audio_locations,
                              uint8_t requested_channel_count,
                              uint8_t channel_count_mask) {
  DLOG(INFO) << __func__ << " strategy: " << (int)strategy
             << " locations: " << +audio_locations.to_ulong();
                              const set_configurations::SetConfiguration& conf,
                              const LeAudioDevice& device) {
  /* Check direction and if audio location allows to create more cises to a
   * single device.
   */
  types::AudioLocations audio_locations =
      (conf.direction == types::kLeAudioDirectionSink)
          ? device.snk_audio_locations_
          : device.src_audio_locations_;

  LOG_DEBUG("strategy: %d, locations: %lu", (int)strategy,
            audio_locations.to_ulong());

  switch (strategy) {
    case types::LeAudioConfigurationStrategy::MONO_ONE_CIS_PER_DEVICE:
@@ -1197,22 +1205,26 @@ bool CheckIfStrategySupported(types::LeAudioConfigurationStrategy strategy,
        return true;
      else
        return false;
    case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE:
    case types::LeAudioConfigurationStrategy::STEREO_ONE_CIS_PER_DEVICE: {
      if (!(audio_locations.to_ulong() &
            codec_spec_conf::kLeAudioLocationAnyLeft) ||
          !(audio_locations.to_ulong() &
            codec_spec_conf::kLeAudioLocationAnyRight))
        return false;

      DLOG(INFO) << __func__ << " requested chan cnt "
                 << +requested_channel_count
                 << " chan mask: " << loghex(channel_count_mask);
      auto channel_count_mask =
          device.GetSupportedAudioChannelCounts(conf.direction);
      auto requested_channel_count = conf.codec.params.GetAsCoreCodecConfig()
                                         .GetChannelCountPerIsoStream();
      LOG_DEBUG("Requested channel count: %d, supp. channel counts: %s",
                requested_channel_count, loghex(channel_count_mask).c_str());

      /* Return true if requested channel count is set in the channel count
       * mask. In the channel_count_mask, bit0 is set when 1 channel is
      /* Return true if requested channel count is set in the supported channel
       * counts. In the channel_count_mask, bit 0 is set when 1 channel is
       * supported.
       */
      return ((1 << (requested_channel_count - 1)) & channel_count_mask);
    }
    default:
      return false;
  }
@@ -1283,32 +1295,17 @@ bool LeAudioDeviceGroup::IsAudioSetConfigurationSupported(

      if (device->ases_.empty()) continue;

      if (!device->GetCodecConfigurationSupportedPac(ent.direction, ent.codec))
      if (!device->GetCodecConfigurationSupportedPac(ent.direction,
                                                     ent.codec)) {
        LOG_DEBUG("Insufficient PAC");
        continue;
      }

      int needed_ase = std::min(static_cast<int>(max_required_ase_per_dev),
                                static_cast<int>(ent.ase_cnt - active_ase_num));

      /* If we required more ASEs per device which means we would like to
       * create more CISes to one device, we should also check the allocation
       * if it allows us to do this.
       */

      types::AudioLocations audio_locations = 0;
      /* Check direction and if audio location allows to create more cise */
      if (ent.direction == types::kLeAudioDirectionSink)
        audio_locations = device->snk_audio_locations_;
      else
        audio_locations = device->src_audio_locations_;

      /* TODO Make it no Lc3 specific */
      if (!CheckIfStrategySupported(
              strategy, audio_locations,
              std::get<LeAudioCoreCodecConfig>(ent.codec.config)
                  .GetChannelCount(),
              device->GetLc3SupportedChannelCount(ent.direction))) {
        LOG_DEBUG(" insufficient device audio allocation: %lu",
                  audio_locations.to_ulong());
      if (!CheckIfStrategySupported(strategy, ent, *device)) {
        LOG_DEBUG("Strategy not supported");
        continue;
      }

@@ -1519,37 +1516,37 @@ LeAudioDeviceGroup::GetCachedCodecConfigurationByDirection(
    if (conf.direction != direction) continue;

    if (group_config.sample_rate != 0 &&
        conf.codec.GetConfigSamplingFrequency() != group_config.sample_rate) {
        conf.codec.GetSamplingFrequencyHz() != group_config.sample_rate) {
      LOG(WARNING) << __func__
                   << ", stream configuration could not be "
                      "determined (sampling frequency differs) for direction: "
                   << loghex(direction);
      return std::nullopt;
    }
    group_config.sample_rate = conf.codec.GetConfigSamplingFrequency();
    group_config.sample_rate = conf.codec.GetSamplingFrequencyHz();

    if (group_config.data_interval_us != 0 &&
        conf.codec.GetConfigDataIntervalUs() != group_config.data_interval_us) {
        conf.codec.GetDataIntervalUs() != group_config.data_interval_us) {
      LOG(WARNING) << __func__
                   << ", stream configuration could not be "
                      "determined (data interval differs) for direction: "
                   << loghex(direction);
      return std::nullopt;
    }
    group_config.data_interval_us = conf.codec.GetConfigDataIntervalUs();
    group_config.data_interval_us = conf.codec.GetDataIntervalUs();

    if (group_config.bits_per_sample != 0 &&
        conf.codec.GetConfigBitsPerSample() != group_config.bits_per_sample) {
        conf.codec.GetBitsPerSample() != group_config.bits_per_sample) {
      LOG(WARNING) << __func__
                   << ", stream configuration could not be "
                      "determined (bits per sample differs) for direction: "
                   << loghex(direction);
      return std::nullopt;
    }
    group_config.bits_per_sample = conf.codec.GetConfigBitsPerSample();
    group_config.bits_per_sample = conf.codec.GetBitsPerSample();

    group_config.num_channels +=
        conf.codec.GetConfigChannelCount() * conf.device_cnt;
        conf.codec.GetChannelCountPerIsoStream() * conf.device_cnt;
  }

  if (group_config.IsInvalid()) return std::nullopt;
@@ -1634,7 +1631,9 @@ void LeAudioDeviceGroup::RemoveCisFromStreamIfNeeded(
              if (ases_pair.get(dir) && cis_conn_hdl == pair.first) {
                params.num_of_devices--;
                params.num_of_channels -=
                    ases_pair.get(dir)->codec_config.channel_count;
                    ases_pair.get(dir)
                        ->codec_config.GetAsCoreCodecConfig()
                        .GetChannelCountPerIsoStream();
                params.audio_channel_allocation &= ~pair.second;
              }
              return (ases_pair.get(dir) && cis_conn_hdl == pair.first);
Loading