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

Commit 7434b72e authored by Oleg Lyovin's avatar Oleg Lyovin
Browse files

AudioFlinger: fallback to non-primary HW devs if getInputBufferSize failed



At the moment only primary audio module is requested for its
input buffer size, but it may not even support input streams,
while there may be other modules with input support.

This patch adds fallback that requests non-primary modules
if the primary module failed in the following precedence:

-- USB
-- Bluetooth
-- A2DP
-- Other modules
-- Remote submix

Test: manual
Change-Id: I54bae431745edecdf23ec09e59292dca6b434965
Signed-off-by: default avatarOleg Lyovin <ovlevin@salutedevices.com>
parent 422f94a8
Loading
Loading
Loading
Loading
+58 −11
Original line number Diff line number Diff line
@@ -1922,10 +1922,11 @@ size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t form
    if (mPrimaryHardwareDev == nullptr) {
        return 0;
    }
    if (mInputBufferSizeOrderedDevs.empty()) {
        return 0;
    }
    mHardwareStatus = AUDIO_HW_GET_INPUT_BUFFER_SIZE;

    sp<DeviceHalInterface> dev = mPrimaryHardwareDev.load()->hwDevice();

    std::vector<audio_channel_mask_t> channelMasks = {channelMask};
    if (channelMask != AUDIO_CHANNEL_IN_MONO) {
        channelMasks.push_back(AUDIO_CHANNEL_IN_MONO);
@@ -1955,6 +1956,22 @@ size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t form

    mHardwareStatus = AUDIO_HW_IDLE;

    auto getInputBufferSize = [](const sp<DeviceHalInterface>& dev, audio_config_t config,
                                 size_t* bytes) -> status_t {
        if (!dev) {
            return BAD_VALUE;
        }
        status_t result = dev->getInputBufferSize(&config, bytes);
        if (result == BAD_VALUE) {
            // Retry with the config suggested by the HAL.
            result = dev->getInputBufferSize(&config, bytes);
        }
        if (result != OK || *bytes == 0) {
            return BAD_VALUE;
        }
        return result;
    };

    // Change parameters of the configuration each iteration until we find a
    // configuration that the device will support, or HAL suggests what it supports.
    audio_config_t config = AUDIO_CONFIG_INITIALIZER;
@@ -1966,16 +1983,15 @@ size_t AudioFlinger::getInputBufferSize(uint32_t sampleRate, audio_format_t form
                config.sample_rate = testSampleRate;

                size_t bytes = 0;
                audio_config_t loopConfig = config;
                status_t result = dev->getInputBufferSize(&config, &bytes);
                if (result == BAD_VALUE) {
                    // Retry with the config suggested by the HAL.
                    result = dev->getInputBufferSize(&config, &bytes);
                ret = BAD_VALUE;
                for (const AudioHwDevice* dev : mInputBufferSizeOrderedDevs) {
                    ret = getInputBufferSize(dev->hwDevice(), config, &bytes);
                    if (ret == OK) {
                        break;
                    }
                if (result != OK || bytes == 0) {
                    config = loopConfig;
                    continue;
                }
                if (ret == BAD_VALUE) continue;

                if (config.sample_rate != sampleRate || config.channel_mask != channelMask ||
                    config.format != format) {
                    uint32_t dstChannelCount = audio_channel_count_from_in_mask(channelMask);
@@ -2603,12 +2619,43 @@ AudioHwDevice* AudioFlinger::loadHwModule_ll(const char *name)
    }

    mAudioHwDevs.add(handle, audioDevice);
    if (strcmp(name, AUDIO_HARDWARE_MODULE_ID_STUB) != 0) {
        mInputBufferSizeOrderedDevs.insert(audioDevice);
    }

    ALOGI("loadHwModule() Loaded %s audio interface, handle %d", name, handle);

    return audioDevice;
}

// Sort AudioHwDevice to be traversed in the getInputBufferSize call in the following order:
// Primary, Usb, Bluetooth, A2DP, other modules, remote submix.
/* static */
bool AudioFlinger::inputBufferSizeDevsCmp(const AudioHwDevice* lhs, const AudioHwDevice* rhs) {
    static const std::map<std::string_view, int> kPriorities = {
        { AUDIO_HARDWARE_MODULE_ID_PRIMARY, 0 }, { AUDIO_HARDWARE_MODULE_ID_USB, 1 },
        { AUDIO_HARDWARE_MODULE_ID_BLUETOOTH, 2 }, { AUDIO_HARDWARE_MODULE_ID_A2DP, 3 },
        { AUDIO_HARDWARE_MODULE_ID_REMOTE_SUBMIX, std::numeric_limits<int>::max() }
    };

    const std::string_view lhsName = lhs->moduleName();
    const std::string_view rhsName = rhs->moduleName();

    auto lhsPriority = std::numeric_limits<int>::max() - 1;
    if (const auto lhsIt = kPriorities.find(lhsName); lhsIt != kPriorities.end()) {
        lhsPriority = lhsIt->second;
    }
    auto rhsPriority = std::numeric_limits<int>::max() - 1;
    if (const auto rhsIt = kPriorities.find(rhsName); rhsIt != kPriorities.end()) {
        rhsPriority = rhsIt->second;
    }

    if (lhsPriority != rhsPriority) {
        return lhsPriority < rhsPriority;
    }
    return lhsName < rhsName;
}

// ----------------------------------------------------------------------------

uint32_t AudioFlinger::getPrimaryOutputSamplingRate() const
+4 −0
Original line number Diff line number Diff line
@@ -629,6 +629,10 @@ private:
    DefaultKeyedVector<audio_module_handle_t, AudioHwDevice*> mAudioHwDevs
            GUARDED_BY(hardwareMutex()) {nullptr /* defValue */};

    static bool inputBufferSizeDevsCmp(const AudioHwDevice* lhs, const AudioHwDevice* rhs);
    std::set<AudioHwDevice*, decltype(&inputBufferSizeDevsCmp)>
            mInputBufferSizeOrderedDevs GUARDED_BY(hardwareMutex()) {inputBufferSizeDevsCmp};

     const sp<DevicesFactoryHalInterface> mDevicesFactoryHal =
             DevicesFactoryHalInterface::create();
     /* const */ sp<DevicesFactoryHalCallback> mDevicesFactoryHalCallback;  // set onFirstRef().