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

Commit b046394f authored by Eric Laurent's avatar Eric Laurent
Browse files

audioflinger: implement Bluetooth latency mode control

Generalize latency mode control previously
only implemented on spatializer thread to mixer threads.
For mixer threads, latency mode control is used when a
Bluetooth A2DP or LE audio device is selected and the
audio HAL stream supports sevreal latency modes.

The following methods and class members are moved from
SpatializerThread class to MixerThread class:
  - onHalLatencyModesChanged_l()
  - getSupportedLatencyModes()
  - mSetLatencyMode
  - mSupportedLatencyModes

setHalLatencyMode_l() has a different implementation in
SpatializerThread and MixerThread.

Test: make
Bug: 257922898
Change-Id: I25106fcb7c3dd9fdeabfbbe29941c7cd3be22196
parent 66d26145
Loading
Loading
Loading
Loading
+114 −65
Original line number Diff line number Diff line
@@ -2089,8 +2089,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge
        mHwSupportsPause(false), mHwPaused(false), mFlushPending(false),
        mLeftVolFloat(-1.0), mRightVolFloat(-1.0),
        mDownStreamPatch{},
        mIsTimestampAdvancing(kMinimumTimeBetweenTimestampChecksNs),
        mBluetoothLatencyModesEnabled(true)
        mIsTimestampAdvancing(kMinimumTimeBetweenTimestampChecksNs)
{
    snprintf(mThreadName, kThreadNameLength, "AudioOut_%X", id);
    mNBLogWriter = audioFlinger->newWriter_l(kLogSize, mThreadName);
@@ -4693,6 +4692,8 @@ status_t AudioFlinger::MixerThread::createAudioPatch_l(const struct audio_patch
    } else {
        status = PlaybackThread::createAudioPatch_l(patch, handle);
    }

    updateHalSupportedLatencyModes_l();
    return status;
}

@@ -4844,6 +4845,7 @@ AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, Aud
    :   PlaybackThread(audioFlinger, output, id, type, systemReady, mixerConfig),
        // mAudioMixer below
        // mFastMixer below
        mBluetoothLatencyModesEnabled(false),
        mFastMixerFutex(0),
        mMasterMono(false)
        // mOutputSink below
@@ -5059,6 +5061,21 @@ AudioFlinger::MixerThread::~MixerThread()
    delete mAudioMixer;
}

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

    Mutex::Autolock _l(mLock);
    if (mOutput != nullptr && mOutput->stream != nullptr) {
        status_t status = mOutput->stream->setLatencyModeCallback(this);
        if (status != INVALID_OPERATION) {
            updateHalSupportedLatencyModes_l();
        }
        // Default to enabled if the HAL supports it. This can be changed by Audioflinger after
        // the thread construction according to AudioFlinger::mBluetoothLatencyModesEnabled
        mBluetoothLatencyModesEnabled.store(
                mOutput->audioHwDev->supportsBluetoothVariableLatency());
    }
}

uint32_t AudioFlinger::MixerThread::correctLatency_l(uint32_t latency) const
{
@@ -6268,6 +6285,100 @@ void AudioFlinger::MixerThread::cacheParameters_l()
    maxPeriod = seconds(mNormalFrameCount) / mSampleRate * 15;
}

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

void AudioFlinger::MixerThread::setHalLatencyMode_l() {
    // Only handle latency mode if:
    // - mBluetoothLatencyModesEnabled is true
    // - the HAL supports latency modes
    // - the selected device is Bluetooth LE or A2DP
    if (!mBluetoothLatencyModesEnabled.load() || mSupportedLatencyModes.empty()) {
        return;
    }
    if (mOutDeviceTypeAddrs.size() != 1
            || !(audio_is_a2dp_out_device(mOutDeviceTypeAddrs[0].mType)
                 || audio_is_ble_out_device(mOutDeviceTypeAddrs[0].mType))) {
        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:
        // - At least one active track is either:
        //   - a fast track with gaming usage or
        //   - a track with acessibility usage
        for (const auto& track : mActiveTracks) {
            if ((track->isFastTrack() && track->attributes().usage == AUDIO_USAGE_GAME)
                    || track->attributes().usage == AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY) {
                latencyMode = AUDIO_LATENCY_MODE_LOW;
                break;
            }
        }
    }

    if (latencyMode != mSetLatencyMode) {
        status_t status = mOutput->stream->setLatencyMode(latencyMode);
        ALOGD("%s: thread(%d) setLatencyMode(%s) returned %d",
                __func__, mId, toString(latencyMode).c_str(), status);
        if (status == NO_ERROR) {
            mSetLatencyMode = latencyMode;
        }
    }
}

void AudioFlinger::MixerThread::updateHalSupportedLatencyModes_l() {

    if (mOutput == nullptr || mOutput->stream == nullptr) {
        return;
    }
    std::vector<audio_latency_mode_t> latencyModes;
    const status_t status = mOutput->stream->getRecommendedLatencyModes(&latencyModes);
    if (status != NO_ERROR) {
        latencyModes.clear();
    }
    if (latencyModes != mSupportedLatencyModes) {
        ALOGD("%s: thread(%d) status %d supported latency modes: %s",
            __func__, mId, status, toString(latencyModes).c_str());
        mSupportedLatencyModes.swap(latencyModes);
        sendHalLatencyModesChangedEvent_l();
    }
}

status_t AudioFlinger::MixerThread::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::MixerThread::onRecommendedLatencyModeChanged(
        std::vector<audio_latency_mode_t> modes) {
    Mutex::Autolock _l(mLock);
    if (modes != mSupportedLatencyModes) {
        ALOGD("%s: thread(%d) supported latency modes: %s",
            __func__, mId, toString(modes).c_str());
        mSupportedLatencyModes.swap(modes);
        sendHalLatencyModesChangedEvent_l();
    }
}

status_t AudioFlinger::MixerThread::setBluetoothVariableLatencyEnabled(bool enabled) {
    if (mOutput == nullptr || mOutput->audioHwDev == nullptr
            || !mOutput->audioHwDev->supportsBluetoothVariableLatency()) {
        return INVALID_OPERATION;
    }
    mBluetoothLatencyModesEnabled.store(enabled);
    return NO_ERROR;
}

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

AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
@@ -7499,13 +7610,7 @@ 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();
    }
    MixerThread::onFirstRef();

    const pid_t tid = getTid();
    if (tid == -1) {
@@ -7519,32 +7624,6 @@ void AudioFlinger::SpatializerThread::onFirstRef() {
    }
}

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;
    const status_t status = mOutput->stream->getRecommendedLatencyModes(&latencyModes);
    if (status != NO_ERROR) {
        latencyModes.clear();
    }
    if (latencyModes != mSupportedLatencyModes) {
        ALOGD("%s: thread(%d) status %d supported latency modes: %s",
            __func__, mId, status, toString(latencyModes).c_str());
        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.
@@ -7592,25 +7671,6 @@ status_t AudioFlinger::SpatializerThread::setRequestedLatencyMode(audio_latency_
    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;
}

status_t AudioFlinger::PlaybackThread::setBluetoothVariableLatencyEnabled(bool enabled) {
    if (mOutput == nullptr || mOutput->audioHwDev == nullptr
            || !mOutput->audioHwDev->supportsBluetoothVariableLatency()) {
        return INVALID_OPERATION;
    }
    mBluetoothLatencyModesEnabled.store(enabled);
    return NO_ERROR;
}

void AudioFlinger::SpatializerThread::checkOutputStageEffects()
{
    bool hasVirtualizer = false;
@@ -7663,17 +7723,6 @@ void AudioFlinger::SpatializerThread::checkOutputStageEffects()
    }
}

void AudioFlinger::SpatializerThread::onRecommendedLatencyModeChanged(
        std::vector<audio_latency_mode_t> modes) {
    Mutex::Autolock _l(mLock);
    if (modes != mSupportedLatencyModes) {
        ALOGD("%s: thread(%d) supported latency modes: %s",
            __func__, mId, toString(modes).c_str());
        mSupportedLatencyModes.swap(modes);
        sendHalLatencyModesChangedEvent_l();
    }
}

// ----------------------------------------------------------------------------
//      Record
// ----------------------------------------------------------------------------
+35 −25
Original line number Diff line number Diff line
@@ -376,8 +376,6 @@ 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
                bool        standby() const { return mStandby; }
@@ -625,6 +623,8 @@ protected:

                product_strategy_t getStrategyForStream(audio_stream_type_t stream) const;

    virtual     void        onHalLatencyModesChanged_l() {}

    virtual     void        dumpInternals_l(int fd __unused, const Vector<String16>& args __unused)
                            { }
    virtual     void        dumpTracks_l(int fd __unused, const Vector<String16>& args __unused) { }
@@ -1102,7 +1102,9 @@ public:
                    return INVALID_OPERATION;
                }

    virtual     status_t setBluetoothVariableLatencyEnabled(bool enabled);
    virtual     status_t setBluetoothVariableLatencyEnabled(bool enabled __unused) {
                    return INVALID_OPERATION;
                }

                void startMelComputation(const sp<audio_utils::MelProcessor>& processor);
                void stopMelComputation();
@@ -1462,12 +1464,10 @@ protected:
    virtual     void flushHw_l() {
                    mIsTimestampAdvancing.clear();
                }

        // Bluetooth Variable latency control logic is enabled or disabled for this thread
        std::atomic_bool mBluetoothLatencyModesEnabled;
};

class MixerThread : public PlaybackThread {
class MixerThread : public PlaybackThread,
                    public StreamOutHalInterfaceLatencyModeCallback  {
public:
    MixerThread(const sp<AudioFlinger>& audioFlinger,
                AudioStreamOut* output,
@@ -1477,6 +1477,13 @@ public:
                audio_config_base_t *mixerConfig = nullptr);
    virtual             ~MixerThread();

    // RefBase
    virtual     void        onFirstRef();

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

    // Thread virtuals

    virtual     bool        checkForNewParameter_l(const String8& keyValuePair,
@@ -1513,6 +1520,17 @@ protected:
    virtual     status_t    releaseAudioPatch_l(const audio_patch_handle_t handle);

                AudioMixer* mAudioMixer;    // normal mixer

            // 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;

            // Bluetooth Variable latency control logic is enabled or disabled for this thread
            std::atomic_bool mBluetoothLatencyModesEnabled;

private:
                // one-time initialization, no locks required
                sp<FastMixer>     mFastMixer;     // non-0 if there is also a fast mixer
@@ -1546,6 +1564,11 @@ public:
                                return INVALID_OPERATION;
                            }

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

                status_t    setBluetoothVariableLatencyEnabled(bool enabled) override;

protected:
    virtual     void       setMasterMono_l(bool mono) {
                               mMasterMono.store(mono);
@@ -1564,6 +1587,10 @@ protected:
                                   mFastMixer->setMasterBalance(balance);
                               }
                           }

                void       updateHalSupportedLatencyModes_l();
                void       onHalLatencyModesChanged_l() override;
                void       setHalLatencyMode_l() override;
};

class DirectOutputThread : public PlaybackThread {
@@ -1767,8 +1794,7 @@ public:
    }
};

class SpatializerThread : public MixerThread,
        public StreamOutHalInterfaceLatencyModeCallback {
class SpatializerThread : public MixerThread {
public:
    SpatializerThread(const sp<AudioFlinger>& audioFlinger,
                           AudioStreamOut* output,
@@ -1779,32 +1805,16 @@ 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;