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

Commit 8016023e authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I0f14c203,Ia590974e into main

* changes:
  Add VTS for setAudioPortConfig with invalid gain
  Implement volume control on default audio HAL
parents aa1ce4b3 7f1ab0c3
Loading
Loading
Loading
Loading
+50 −1
Original line number Diff line number Diff line
@@ -47,6 +47,7 @@ using aidl::android::media::audio::common::AudioDevice;
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::AudioMMapPolicy;
@@ -1200,7 +1201,9 @@ ndk::ScopedAStatus Module::setAudioPortConfigImpl(
    }

    if (in_requested.gain.has_value()) {
        // Let's pretend that gain can always be applied.
        if (!setAudioPortConfigGain(*portIt, in_requested.gain.value())) {
            return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
        }
        out_suggested->gain = in_requested.gain.value();
    }

@@ -1242,6 +1245,52 @@ ndk::ScopedAStatus Module::setAudioPortConfigImpl(
    return ndk::ScopedAStatus::ok();
}

bool Module::setAudioPortConfigGain(const AudioPort& port, const AudioGainConfig& gainRequested) {
    auto& ports = getConfig().ports;
    if (gainRequested.index < 0 || gainRequested.index >= (int)port.gains.size()) {
        LOG(ERROR) << __func__ << ": gains for port " << port.id << " is undefined";
        return false;
    }
    int stepValue = port.gains[gainRequested.index].stepValue;
    if (stepValue == 0) {
        LOG(ERROR) << __func__ << ": port gain step value is 0";
        return false;
    }
    int minValue = port.gains[gainRequested.index].minValue;
    int maxValue = port.gains[gainRequested.index].maxValue;
    if (gainRequested.values[0] > maxValue || gainRequested.values[0] < minValue) {
        LOG(ERROR) << __func__ << ": gain value " << gainRequested.values[0]
                   << " out of range of min and max gain config";
        return false;
    }
    int gainIndex = (gainRequested.values[0] - minValue) / stepValue;
    int totalSteps = (maxValue - minValue) / stepValue;
    if (totalSteps == 0) {
        LOG(ERROR) << __func__ << ": difference between port gain min value " << minValue
                   << " and max value " << maxValue << " is less than step value " << stepValue;
        return false;
    }
    // Root-power quantities are used in curve:
    // 10^((minMb / 100 + (maxMb / 100 - minMb / 100) * gainIndex / totalSteps) / (10 * 2))
    // where 100 is the conversion from mB to dB, 10 comes from the log 10 conversion from power
    // ratios, and 2 means are the square of amplitude.
    float gain =
            pow(10, (minValue + (maxValue - minValue) * (gainIndex / (float)totalSteps)) / 2000);
    if (gain < 0) {
        LOG(ERROR) << __func__ << ": gain " << gain << " is less than 0";
        return false;
    }
    for (const auto& route : getConfig().routes) {
        if (route.sinkPortId != port.id) {
            continue;
        }
        for (const auto sourcePortId : route.sourcePortIds) {
            mStreams.setGain(sourcePortId, gain);
        }
    }
    return true;
}

ndk::ScopedAStatus Module::resetAudioPatch(int32_t in_patchId) {
    auto& patches = getConfig().patches;
    auto patchIt = findById<AudioPatch>(patches, in_patchId);
+5 −0
Original line number Diff line number Diff line
@@ -855,6 +855,11 @@ ndk::ScopedAStatus StreamCommonImpl::setConnectedDevices(
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus StreamCommonImpl::setGain(float gain) {
    LOG(DEBUG) << __func__ << ": gain " << gain;
    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}

ndk::ScopedAStatus StreamCommonImpl::bluetoothParametersUpdated() {
    LOG(DEBUG) << __func__;
    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+8 −0
Original line number Diff line number Diff line
@@ -260,4 +260,12 @@ ndk::ScopedAStatus StreamSwitcher::bluetoothParametersUpdated() {
    return mStream->bluetoothParametersUpdated();
}

ndk::ScopedAStatus StreamSwitcher::setGain(float gain) {
    if (mStream == nullptr) {
        LOG(ERROR) << __func__ << ": stream was closed";
        return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
    }
    return mStream->setGain(gain);
}

}  // namespace aidl::android::hardware::audio::core
+6 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ StreamAlsa::~StreamAlsa() {
                                mReadWriteRetries);
        maxLatency = proxy_get_latency(mAlsaDeviceProxies[0].get());
    } else {
        alsa::applyGain(buffer, mGain, bytesToTransfer, mConfig.value().format, mConfig->channels);
        for (auto& proxy : mAlsaDeviceProxies) {
            proxy_write_with_retries(proxy.get(), buffer, bytesToTransfer, mReadWriteRetries);
            maxLatency = std::max(maxLatency, proxy_get_latency(proxy.get()));
@@ -166,4 +167,9 @@ void StreamAlsa::shutdown() {
    mAlsaDeviceProxies.clear();
}

ndk::ScopedAStatus StreamAlsa::setGain(float gain) {
    mGain = gain;
    return ndk::ScopedAStatus::ok();
}

}  // namespace aidl::android::hardware::audio::core
+66 −0
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@
#include <aidl/android/media/audio/common/AudioFormatType.h>
#include <aidl/android/media/audio/common/PcmType.h>
#include <android-base/logging.h>
#include <audio_utils/primitives.h>
#include <cutils/compiler.h>

#include "Utils.h"
#include "core-impl/utils.h"
@@ -343,4 +345,68 @@ pcm_format aidl2c_AudioFormatDescription_pcm_format(const AudioFormatDescription
    return findValueOrDefault(getAudioFormatDescriptorToPcmFormatMap(), aidl, PCM_FORMAT_INVALID);
}

void applyGain(void* buffer, float gain, size_t bytesToTransfer, enum pcm_format pcmFormat,
               int channelCount) {
    if (channelCount != 1 && channelCount != 2) {
        LOG(WARNING) << __func__ << ": unsupported channel count " << channelCount;
        return;
    }
    if (!getPcmFormatToAudioFormatDescMap().contains(pcmFormat)) {
        LOG(WARNING) << __func__ << ": unsupported pcm format " << pcmFormat;
        return;
    }
    const float unityGainFloat = 1.0f;
    if (std::abs(gain - unityGainFloat) < 1e-6) {
        return;
    }
    int numFrames;
    switch (pcmFormat) {
        case PCM_FORMAT_S16_LE: {
            const uint16_t unityGainQ4_12 = u4_12_from_float(unityGainFloat);
            const uint16_t vl = u4_12_from_float(gain);
            const uint32_t vrl = (vl << 16) | vl;
            if (channelCount == 2) {
                numFrames = bytesToTransfer / sizeof(uint32_t);
                uint32_t* intBuffer = (uint32_t*)buffer;
                if (CC_UNLIKELY(vl > unityGainQ4_12)) {
                    // volume is boosted, so we might need to clamp even though
                    // we process only one track.
                    do {
                        int32_t l = mulRL(1, *intBuffer, vrl) >> 12;
                        int32_t r = mulRL(0, *intBuffer, vrl) >> 12;
                        l = clamp16(l);
                        r = clamp16(r);
                        *intBuffer++ = (r << 16) | (l & 0xFFFF);
                    } while (--numFrames);
                } else {
                    do {
                        int32_t l = mulRL(1, *intBuffer, vrl) >> 12;
                        int32_t r = mulRL(0, *intBuffer, vrl) >> 12;
                        *intBuffer++ = (r << 16) | (l & 0xFFFF);
                    } while (--numFrames);
                }
            } else {
                numFrames = bytesToTransfer / sizeof(uint16_t);
                int16_t* intBuffer = (int16_t*)buffer;
                if (CC_UNLIKELY(vl > unityGainQ4_12)) {
                    // volume is boosted, so we might need to clamp even though
                    // we process only one track.
                    do {
                        int32_t mono = mulRL(1, *intBuffer, vrl) >> 12;
                        *intBuffer++ = clamp16(mono);
                    } while (--numFrames);
                } else {
                    do {
                        int32_t mono = mulRL(1, *intBuffer, vrl) >> 12;
                        *intBuffer++ = static_cast<int16_t>(mono & 0xFFFF);
                    } while (--numFrames);
                }
            }
        } break;
        default:
            // TODO(336370745): Implement gain for other supported formats
            break;
    }
}

}  // namespace aidl::android::hardware::audio::core::alsa
Loading