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

Commit ff84edb1 authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Gerrit Code Review
Browse files

Merge "libaudiohal@aidl: Implement gain change via 'setPortConfig'" into main

parents c0e479ea 1a2e0ff5
Loading
Loading
Loading
Loading
+25 −10
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ using aidl::android::media::audio::common::AudioDeviceDescription;
using aidl::android::media::audio::common::AudioDeviceType;
using aidl::android::media::audio::common::AudioFormatDescription;
using aidl::android::media::audio::common::AudioFormatType;
using aidl::android::media::audio::common::AudioGainConfig;
using aidl::android::media::audio::common::AudioInputFlags;
using aidl::android::media::audio::common::AudioIoFlags;
using aidl::android::media::audio::common::AudioOutputFlags;
@@ -325,8 +326,8 @@ status_t Hal2AidlMapper::findOrCreatePatch(
}

status_t Hal2AidlMapper::findOrCreateDevicePortConfig(
        const AudioDevice& device, const AudioConfig* config, AudioPortConfig* portConfig,
        bool* created) {
        const AudioDevice& device, const AudioConfig* config, const AudioGainConfig* gainConfig,
        AudioPortConfig* portConfig, bool* created) {
    if (auto portConfigIt = findPortConfig(device); portConfigIt == mPortConfigs.end()) {
        auto portsIt = findPort(device);
        if (portsIt == mPorts.end()) {
@@ -339,12 +340,18 @@ status_t Hal2AidlMapper::findOrCreateDevicePortConfig(
        if (config != nullptr) {
            setPortConfigFromConfig(&requestedPortConfig, *config);
        }
        if (gainConfig != nullptr) {
            requestedPortConfig.gain = *gainConfig;
        }
        return createOrUpdatePortConfigRetry(requestedPortConfig, portConfig, created);
    } else {
        AudioPortConfig requestedPortConfig = portConfigIt->second;
        if (config != nullptr) {
            setPortConfigFromConfig(&requestedPortConfig, *config);
        }
        if (gainConfig != nullptr) {
            requestedPortConfig.gain = *gainConfig;
        }

        if (requestedPortConfig != portConfigIt->second) {
            return createOrUpdatePortConfigRetry(requestedPortConfig, portConfig, created);
@@ -447,18 +454,26 @@ status_t Hal2AidlMapper::findOrCreatePortConfig(
                requestedPortConfig.ext.get<Tag::mix>().handle, source, destinationPortIds,
                portConfig, created);
    } else if (requestedPortConfig.ext.getTag() == Tag::device) {
        if (const auto& p = requestedPortConfig;
                p.sampleRate.has_value() && p.channelMask.has_value() &&
                p.format.has_value()) {
            AudioConfig config;
        const auto& p = requestedPortConfig;
        const bool hasAudioConfig =
                p.sampleRate.has_value() && p.channelMask.has_value() && p.format.has_value();
        const bool hasGainConfig = p.gain.has_value();
        if (hasAudioConfig || hasGainConfig) {
            AudioConfig config, *configPtr = nullptr;
            if (hasAudioConfig) {
                setConfigFromPortConfig(&config, requestedPortConfig);
                configPtr = &config;
            }
            const AudioGainConfig* gainConfigPtr = nullptr;
            if (hasGainConfig) gainConfigPtr = &(*(p.gain));
            return findOrCreateDevicePortConfig(
                    requestedPortConfig.ext.get<Tag::device>().device, &config,
                    requestedPortConfig.ext.get<Tag::device>().device, configPtr, gainConfigPtr,
                    portConfig, created);
        } else {
            ALOGD("%s: device port config does not have audio or gain config specified", __func__);
            return findOrCreateDevicePortConfig(
                    requestedPortConfig.ext.get<Tag::device>().device, nullptr /*config*/,
                    portConfig, created);
                    nullptr /*gainConfig*/, portConfig, created);
        }
    }
    ALOGW("%s: unsupported audio port config: %s",
@@ -769,7 +784,7 @@ status_t Hal2AidlMapper::prepareToOpenStream(
    // then find / create a patch between them, and open a stream on the mix port.
    AudioPortConfig devicePortConfig;
    bool created = false;
    RETURN_STATUS_IF_ERROR(findOrCreateDevicePortConfig(device, config,
    RETURN_STATUS_IF_ERROR(findOrCreateDevicePortConfig(device, config, nullptr /*gainConfig*/,
                    &devicePortConfig, &created));
    LOG_ALWAYS_FATAL_IF(devicePortConfig.id == 0);
    if (created) {
+1 −0
Original line number Diff line number Diff line
@@ -163,6 +163,7 @@ class Hal2AidlMapper {
    status_t findOrCreateDevicePortConfig(
            const ::aidl::android::media::audio::common::AudioDevice& device,
            const ::aidl::android::media::audio::common::AudioConfig* config,
            const ::aidl::android::media::audio::common::AudioGainConfig* gainConfig,
            ::aidl::android::media::audio::common::AudioPortConfig* portConfig,
            bool* created);
    // If the resulting 'portConfig->id' is 0, that means the config was not created,
+80 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <aidl/android/hardware/audio/core/BnModule.h>
#include <aidl/android/hardware/audio/core/BnStreamCommon.h>
#include <aidl/android/media/audio/BnHalAdapterVendorExtension.h>
#include <aidl/android/media/audio/common/AudioGainMode.h>
#include <aidl/android/media/audio/common/Int.h>
#include <utils/Log.h>

@@ -44,6 +45,8 @@ using ::aidl::android::media::audio::common::AudioDeviceDescription;
using ::aidl::android::media::audio::common::AudioDeviceType;
using ::aidl::android::media::audio::common::AudioFormatDescription;
using ::aidl::android::media::audio::common::AudioFormatType;
using ::aidl::android::media::audio::common::AudioGainConfig;
using ::aidl::android::media::audio::common::AudioGainMode;
using ::aidl::android::media::audio::common::AudioIoFlags;
using ::aidl::android::media::audio::common::AudioPort;
using ::aidl::android::media::audio::common::AudioPortConfig;
@@ -179,6 +182,11 @@ Configuration getTestConfiguration() {
    primaryInMix.profiles = standardPcmAudioProfiles;
    c.ports.push_back(primaryInMix);

    AudioPort speakerOutDevice = createPort(c.nextPortId++, "Speaker", 0, false,
                                            createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0));
    speakerOutDevice.profiles = standardPcmAudioProfiles;
    c.ports.push_back(speakerOutDevice);

    AudioPort btOutDevice =
            createPort(c.nextPortId++, "BT A2DP Out", 0, false,
                       createPortDeviceExt(AudioDeviceType::OUT_DEVICE, 0,
@@ -209,6 +217,13 @@ class ModuleMock : public ::aidl::android::hardware::audio::core::BnModule,
        getAudioPatches(&result);
        return result;
    }
    std::optional<AudioPortConfig> getPortConfig(int32_t id) {
        auto iter = findById<AudioPortConfig>(mConfig.portConfigs, id);
        if (iter != mConfig.portConfigs.end()) {
            return *iter;
        }
        return std::nullopt;
    }

  private:
    ndk::ScopedAStatus setModuleDebug(
@@ -646,6 +661,19 @@ std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os,
}
}  // namespace aidl::android::hardware::audio::core

namespace aidl::android::media::audio::common {
template <typename P>
std::enable_if_t<std::is_function_v<typename mf_traits<decltype(&P::toString)>::member_type>,
                 std::ostream&>
operator<<(std::ostream& os, const P& p) {
    return os << p.toString();
}
template <typename E>
std::enable_if_t<std::is_enum_v<E>, std::ostream&> operator<<(std::ostream& os, const E& e) {
    return os << toString(e);
}
}  // namespace aidl::android::media::audio::common

using namespace android;

namespace {
@@ -1214,3 +1242,55 @@ TEST_F(Hal2AidlMapperTest, ChangeTransientPatchDevice) {
    EXPECT_EQ(std::vector<int32_t>{backMicPortConfig.id}, patchIt->sourcePortConfigIds);
    EXPECT_EQ(std::vector<int32_t>{mixPortConfig.id}, patchIt->sinkPortConfigIds);
}

TEST_F(Hal2AidlMapperTest, SetAudioPortConfigGainChangeExistingPortConfig) {
    // First set config, then update gain.
    AudioPortConfig speakerPortConfig;
    speakerPortConfig.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
    speakerPortConfig.channelMask = AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
            AudioChannelLayout::LAYOUT_STEREO);
    speakerPortConfig.format =
            AudioFormatDescription{.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT};
    speakerPortConfig.sampleRate = ::aidl::android::media::audio::common::Int(48000);
    AudioPortConfig resultingPortConfig;
    ASSERT_EQ(OK,
              mMapper->setPortConfig(speakerPortConfig, std::set<int32_t>(), &resultingPortConfig));
    EXPECT_NE(0, resultingPortConfig.id);
    EXPECT_NE(0, resultingPortConfig.portId);

    AudioPortConfig gainUpdate;
    gainUpdate.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
    AudioGainConfig gainConfig{.index = -1,
                               .mode = 1 << static_cast<int>(AudioGainMode::JOINT),
                               .channelMask = AudioChannelLayout{},
                               .values = std::vector<int32_t>{-3200},
                               .rampDurationMs = 0};
    gainUpdate.gain = gainConfig;
    AudioPortConfig resultingGainUpdate;
    ASSERT_EQ(OK, mMapper->setPortConfig(gainUpdate, std::set<int32_t>(), &resultingGainUpdate));
    EXPECT_EQ(resultingPortConfig.id, resultingGainUpdate.id);
    auto updatedPortConfig = mModule->getPortConfig(resultingGainUpdate.id);
    ASSERT_TRUE(updatedPortConfig.has_value());
    ASSERT_TRUE(updatedPortConfig->gain.has_value());
    EXPECT_EQ(gainConfig, updatedPortConfig->gain);
}

TEST_F(Hal2AidlMapperTest, SetAudioPortConfigGainChangeFromScratch) {
    // Set gain as the first operation, the HAL should suggest the rest of the configuration.
    AudioPortConfig gainSet;
    gainSet.ext = createPortDeviceExt(AudioDeviceType::OUT_SPEAKER, 0);
    AudioGainConfig gainConfig{.index = -1,
                               .mode = 1 << static_cast<int>(AudioGainMode::JOINT),
                               .channelMask = AudioChannelLayout{},
                               .values = std::vector<int32_t>{-3200},
                               .rampDurationMs = 0};
    gainSet.gain = gainConfig;
    AudioPortConfig resultingPortConfig;
    ASSERT_EQ(OK, mMapper->setPortConfig(gainSet, std::set<int32_t>(), &resultingPortConfig));
    EXPECT_NE(0, resultingPortConfig.id);
    EXPECT_NE(0, resultingPortConfig.portId);
    auto portConfig = mModule->getPortConfig(resultingPortConfig.id);
    ASSERT_TRUE(portConfig.has_value());
    ASSERT_TRUE(portConfig->gain.has_value());
    EXPECT_EQ(gainConfig, portConfig->gain);
}