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

Commit 8c8d9779 authored by Eric Laurent's avatar Eric Laurent Committed by Android Git Automerger
Browse files

am 45fd99a3: Merge "audio policy: fix preemtible capture race" into mnc-dr-dev

* commit '45fd99a3':
  audio policy: fix preemtible capture race
parents 3d25b023 45fd99a3
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -56,9 +56,21 @@ public:
            const struct audio_port_config *srcConfig = NULL) const;
    virtual sp<AudioPort> getAudioPort() const { return mProfile; }
    void toAudioPort(struct audio_port *port) const;
    void setPreemptedSessions(const SortedVector<audio_session_t>& sessions);
    SortedVector<audio_session_t> getPreemptedSessions() const;
    bool hasPreemptedSession(audio_session_t session) const;
    void clearPreemptedSessions();

private:
    audio_port_handle_t           mId;
    // Because a preemtible capture session can preempt another one, we end up in an endless loop
    // situation were each session is allowed to restart after being preempted,
    // thus preempting the other one which restarts and so on.
    // To avoid this situation, we store which audio session was preempted when
    // a particular input started and prevent preemption of this active input by this session.
    // We also inherit sessions from the preempted input to avoid a 3 way preemption loop etc...
    SortedVector<audio_session_t> mPreemptedSessions;

};

class AudioInputCollection :
+20 −0
Original line number Diff line number Diff line
@@ -93,6 +93,26 @@ void AudioInputDescriptor::toAudioPort(struct audio_port *port) const
    port->ext.mix.latency_class = AUDIO_LATENCY_NORMAL;
}

void AudioInputDescriptor::setPreemptedSessions(const SortedVector<audio_session_t>& sessions)
{
    mPreemptedSessions = sessions;
}

SortedVector<audio_session_t> AudioInputDescriptor::getPreemptedSessions() const
{
    return mPreemptedSessions;
}

bool AudioInputDescriptor::hasPreemptedSession(audio_session_t session) const
{
    return (mPreemptedSessions.indexOf(session) >= 0);
}

void AudioInputDescriptor::clearPreemptedSessions()
{
    mPreemptedSessions.clear();
}

status_t AudioInputDescriptor::dump(int fd)
{
    const size_t SIZE = 256;
+9 −3
Original line number Diff line number Diff line
@@ -1485,10 +1485,15 @@ status_t AudioPolicyManager::startInput(audio_io_handle_t input,
            // If the already active input uses AUDIO_SOURCE_HOTWORD then it is closed,
            // otherwise the active input continues and the new input cannot be started.
            sp<AudioInputDescriptor> activeDesc = mInputs.valueFor(activeInput);
            if (activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) {
            if ((activeDesc->mInputSource == AUDIO_SOURCE_HOTWORD) &&
                    !activeDesc->hasPreemptedSession(session)) {
                ALOGW("startInput(%d) preempting low-priority input %d", input, activeInput);
                stopInput(activeInput, activeDesc->mSessions.itemAt(0));
                releaseInput(activeInput, activeDesc->mSessions.itemAt(0));
                audio_session_t activeSession = activeDesc->mSessions.itemAt(0);
                SortedVector<audio_session_t> sessions = activeDesc->getPreemptedSessions();
                sessions.add(activeSession);
                inputDesc->setPreemptedSessions(sessions);
                stopInput(activeInput, activeSession);
                releaseInput(activeInput, activeSession);
            } else {
                ALOGE("startInput(%d) failed: other input %d already started", input, activeInput);
                return INVALID_OPERATION;
@@ -1592,6 +1597,7 @@ status_t AudioPolicyManager::stopInput(audio_io_handle_t input,
        if (mInputs.activeInputsCount() == 0) {
            SoundTrigger::setCaptureState(false);
        }
        inputDesc->clearPreemptedSessions();
    }
    return NO_ERROR;
}