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

Commit cc86cd36 authored by Eric Laurent's avatar Eric Laurent Committed by Automerger Merge Worker
Browse files

audiolfinger: implement latency mode control in spatializer mixer am: 6f9534fb am: 4295d22b

parents 1a5abdd8 4295d22b
Loading
Loading
Loading
Loading
+14 −6
Original line number Diff line number Diff line
@@ -1587,21 +1587,29 @@ status_t AudioFlinger::setStreamVolume(audio_stream_type_t stream, float value,
}

status_t AudioFlinger::setRequestedLatencyMode(
        audio_io_handle_t output, audio_latency_mode_t mode __unused) {
        audio_io_handle_t output, audio_latency_mode_t mode) {
    if (output == AUDIO_IO_HANDLE_NONE) {
        return BAD_VALUE;
    }
    //TODO b/218273231: implement
    return INVALID_OPERATION;
    AutoMutex lock(mLock);
    PlaybackThread *thread = checkPlaybackThread_l(output);
    if (thread == nullptr) {
        return BAD_VALUE;
    }
    return thread->setRequestedLatencyMode(mode);
}

status_t AudioFlinger::getSupportedLatencyModes(audio_io_handle_t output,
            std::vector<audio_latency_mode_t>* modes __unused) {
            std::vector<audio_latency_mode_t>* modes) {
    if (output == AUDIO_IO_HANDLE_NONE) {
        return BAD_VALUE;
    }
    //TODO b/218273231: implement
    return INVALID_OPERATION;
    AutoMutex lock(mLock);
    PlaybackThread *thread = checkPlaybackThread_l(output);
    if (thread == nullptr) {
        return BAD_VALUE;
    }
    return thread->getSupportedLatencyModes(modes);
}

status_t AudioFlinger::setStreamMute(audio_stream_type_t stream, bool muted)
+109 −0
Original line number Diff line number Diff line
@@ -741,6 +741,12 @@ void AudioFlinger::ThreadBase::sendCheckOutputStageEffectsEvent_l()
    sendConfigEvent_l(configEvent);
}

void AudioFlinger::ThreadBase::sendHalLatencyModesChangedEvent_l()
{
    sp<ConfigEvent> configEvent = sp<HalLatencyModesChangedEvent>::make();
    sendConfigEvent_l(configEvent);
}

// post condition: mConfigEvents.isEmpty()
void AudioFlinger::ThreadBase::processConfigEvents_l()
{
@@ -808,6 +814,10 @@ void AudioFlinger::ThreadBase::processConfigEvents_l()
            setCheckOutputStageEffects();
        } break;

        case CFG_EVENT_HAL_LATENCY_MODES_CHANGED: {
            onHalLatencyModesChanged_l();
        } break;

        default:
            ALOG_ASSERT(false, "processConfigEvents_l() unknown event type %d", event->mType);
            break;
@@ -3922,6 +3932,8 @@ bool AudioFlinger::PlaybackThread::threadLoop()
            // stop(), pause(), etc.), but the threadLoop is entitled to call audio
            // data / buffer methods on tracks from activeTracks without the ThreadBase lock.
            activeTracks.insert(activeTracks.end(), mActiveTracks.begin(), mActiveTracks.end());

            setHalLatencyMode_l();
        } // mLock scope ends

        if (mBytesRemaining == 0) {
@@ -5016,6 +5028,7 @@ void AudioFlinger::PlaybackThread::threadLoop_standby()
        mCallbackThread->setDraining(mDrainSequence);
    }
    mHwPaused = false;
    setHalLatencyMode_l();
}

void AudioFlinger::PlaybackThread::onAddNewTrack_l()
@@ -7259,6 +7272,94 @@ AudioFlinger::SpatializerThread::SpatializerThread(const sp<AudioFlinger>& audio
{
}

void AudioFlinger::SpatializerThread::onFirstRef() {
    PlaybackThread::onFirstRef();

    Mutex::Autolock _l(mLock);
    status_t status = mOutput->stream->setLatencyModeCallback(this);
    if (status != INVALID_OPERATION) {
        updateHalSupportedLatencyModes_l();
    }
}

status_t AudioFlinger::SpatializerThread::createAudioPatch_l(const struct audio_patch *patch,
                                                          audio_patch_handle_t *handle)
{
    status_t status = MixerThread::createAudioPatch_l(patch, handle);
    updateHalSupportedLatencyModes_l();
    return status;
}

void AudioFlinger::SpatializerThread::updateHalSupportedLatencyModes_l() {
    std::vector<audio_latency_mode_t> latencyModes;
    if (mOutput->stream->getRecommendedLatencyModes(&latencyModes) != NO_ERROR) {
        latencyModes.clear();
    }
    if (latencyModes != mSupportedLatencyModes) {
        mSupportedLatencyModes.swap(latencyModes);
        sendHalLatencyModesChangedEvent_l();
    }
}

void AudioFlinger::SpatializerThread::onHalLatencyModesChanged_l() {
    mAudioFlinger->onSupportedLatencyModesChanged(mId, mSupportedLatencyModes);
}

void AudioFlinger::SpatializerThread::setHalLatencyMode_l() {
    // if mSupportedLatencyModes is empty, the HAL stream does not support
    // latency mode control and we can exit.
    if (mSupportedLatencyModes.empty()) {
        return;
    }
    audio_latency_mode_t latencyMode = AUDIO_LATENCY_MODE_FREE;
    if (mSupportedLatencyModes.size() == 1) {
        // If the HAL only support one latency mode currently, confirm the choice
        latencyMode = mSupportedLatencyModes[0];
    } else if (mSupportedLatencyModes.size() > 1) {
        // Request low latency if:
        // - The low latency mode is requested by the spatializer controller
        //   (mRequestedLatencyMode = AUDIO_LATENCY_MODE_LOW)
        //      AND
        // - At least one active track is spatialized
        bool hasSpatializedActiveTrack = false;
        for (const auto& track : mActiveTracks) {
            if (track->isSpatialized()) {
                hasSpatializedActiveTrack = true;
                break;
            }
        }
        if (hasSpatializedActiveTrack && mRequestedLatencyMode == AUDIO_LATENCY_MODE_LOW) {
            latencyMode = AUDIO_LATENCY_MODE_LOW;
        }
    }

    if (latencyMode != mSetLatencyMode) {
        status_t status = mOutput->stream->setLatencyMode(latencyMode);
        if (status == NO_ERROR) {
            mSetLatencyMode = latencyMode;
        }
    }
}

status_t AudioFlinger::SpatializerThread::setRequestedLatencyMode(audio_latency_mode_t mode) {
    if (mode != AUDIO_LATENCY_MODE_LOW && mode != AUDIO_LATENCY_MODE_FREE) {
        return BAD_VALUE;
    }
    Mutex::Autolock _l(mLock);
    mRequestedLatencyMode = mode;
    return NO_ERROR;
}

status_t AudioFlinger::SpatializerThread::getSupportedLatencyModes(
        std::vector<audio_latency_mode_t>* modes) {
    if (modes == nullptr) {
        return BAD_VALUE;
    }
    Mutex::Autolock _l(mLock);
    *modes = mSupportedLatencyModes;
    return NO_ERROR;
}

void AudioFlinger::SpatializerThread::checkOutputStageEffects()
{
    bool hasVirtualizer = false;
@@ -7311,6 +7412,14 @@ void AudioFlinger::SpatializerThread::checkOutputStageEffects()
    }
}

void AudioFlinger::SpatializerThread::onRecommendedLatencyModeChanged(
        std::vector<audio_latency_mode_t> modes) {
    Mutex::Autolock _l(mLock);
    if (modes != mSupportedLatencyModes) {
        mSupportedLatencyModes.swap(modes);
        sendHalLatencyModesChangedEvent_l();
    }
}

// ----------------------------------------------------------------------------
//      Record
+51 −3
Original line number Diff line number Diff line
@@ -55,7 +55,8 @@ public:
        CFG_EVENT_RELEASE_AUDIO_PATCH,
        CFG_EVENT_UPDATE_OUT_DEVICE,
        CFG_EVENT_RESIZE_BUFFER,
        CFG_EVENT_CHECK_OUTPUT_STAGE_EFFECTS
        CFG_EVENT_CHECK_OUTPUT_STAGE_EFFECTS,
        CFG_EVENT_HAL_LATENCY_MODES_CHANGED,
    };

    class ConfigEventData: public RefBase {
@@ -282,6 +283,15 @@ public:
        virtual ~CheckOutputStageEffectsEvent() {}
    };

    class HalLatencyModesChangedEvent : public ConfigEvent {
    public:
        HalLatencyModesChangedEvent() :
            ConfigEvent(CFG_EVENT_HAL_LATENCY_MODES_CHANGED) {
        }

        virtual ~HalLatencyModesChangedEvent() {}
    };


    class PMDeathRecipient : public IBinder::DeathRecipient {
    public:
@@ -353,6 +363,7 @@ public:
                void        sendResizeBufferConfigEvent_l(int32_t maxSharedAudioHistoryMs);
                void        sendCheckOutputStageEffectsEvent();
                void        sendCheckOutputStageEffectsEvent_l();
                void        sendHalLatencyModesChangedEvent_l();

                void        processConfigEvents_l();
    virtual     void        setCheckOutputStageEffects() {}
@@ -364,7 +375,7 @@ public:
    virtual     void        toAudioPortConfig(struct audio_port_config *config) = 0;

    virtual     void        resizeInputBuffer_l(int32_t maxSharedAudioHistoryMs);

    virtual     void        onHalLatencyModesChanged_l() {}


                // see note at declaration of mStandby, mOutDevice and mInDevice
@@ -921,6 +932,8 @@ protected:
                            }

    virtual     void        checkOutputStageEffects() {}
    virtual     void        setHalLatencyMode_l() {}


                void        dumpInternals_l(int fd, const Vector<String16>& args) override;
                void        dumpTracks_l(int fd, const Vector<String16>& args) override;
@@ -1064,6 +1077,15 @@ public:
                bool hasMixer() const {
                    return mType == MIXER || mType == DUPLICATING || mType == SPATIALIZER;
                }

    virtual     status_t setRequestedLatencyMode(
            audio_latency_mode_t mode __unused) { return INVALID_OPERATION; }

    virtual     status_t getSupportedLatencyModes(
                        std::vector<audio_latency_mode_t>* modes __unused) {
                    return INVALID_OPERATION;
                }

protected:
    // updated by readOutputParameters_l()
    size_t                          mNormalFrameCount;  // normal mixer and effects
@@ -1682,7 +1704,8 @@ public:
    }
};

class SpatializerThread : public MixerThread {
class SpatializerThread : public MixerThread,
        public StreamOutHalInterfaceLatencyModeCallback {
public:
    SpatializerThread(const sp<AudioFlinger>& audioFlinger,
                           AudioStreamOut* output,
@@ -1693,10 +1716,35 @@ public:

            bool hasFastMixer() const override { return false; }

            status_t    createAudioPatch_l(const struct audio_patch *patch,
                                   audio_patch_handle_t *handle) override;

            // RefBase
            virtual void        onFirstRef();

            // StreamOutHalInterfaceLatencyModeCallback
            void onRecommendedLatencyModeChanged(std::vector<audio_latency_mode_t> modes) override;

            status_t setRequestedLatencyMode(audio_latency_mode_t mode) override;
            status_t getSupportedLatencyModes(std::vector<audio_latency_mode_t>* modes) override;

protected:
            void checkOutputStageEffects() override;
            void onHalLatencyModesChanged_l() override;
            void setHalLatencyMode_l() override;

private:
            void updateHalSupportedLatencyModes_l();

            // Support low latency mode by default as unless explicitly indicated by the audio HAL
            // we assume the audio path is compatible with the head tracking latency requirements
            std::vector<audio_latency_mode_t> mSupportedLatencyModes = {AUDIO_LATENCY_MODE_LOW};
            // default to invalid value to force first update to the audio HAL
            audio_latency_mode_t mSetLatencyMode =
                    (audio_latency_mode_t)AUDIO_LATENCY_MODE_INVALID;
            // Do not request a specific mode by default
            audio_latency_mode_t mRequestedLatencyMode = AUDIO_LATENCY_MODE_FREE;

            sp<EffectHandle> mFinalDownMixer;
};