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

Commit 1d491ff0 authored by Glenn Kasten's avatar Glenn Kasten
Browse files

Fix races in AudioRecord stop()

Change-Id: Id0ac1915f57fef4a938c7f90989c1162a8b6c51c
parent bf5bea96
Loading
Loading
Loading
Loading
+27 −24
Original line number Diff line number Diff line
@@ -5362,12 +5362,19 @@ void AudioFlinger::RecordThread::RecordTrack::stop()
    sp<ThreadBase> thread = mThread.promote();
    if (thread != 0) {
        RecordThread *recordThread = (RecordThread *)thread.get();
        recordThread->stop(this);
        recordThread->mLock.lock();
        bool doStop = recordThread->stop_l(this);
        if (doStop) {
            TrackBase::reset();
            // Force overrun condition to avoid false overrun callback until first data is
            // read from buffer
            android_atomic_or(CBLK_UNDERRUN_ON, &mCblk->flags);
        }
        recordThread->mLock.unlock();
        if (doStop) {
            AudioSystem::stopInput(recordThread->id());
        }
    }
}

void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size)
@@ -6278,27 +6285,23 @@ void AudioFlinger::RecordThread::handleSyncStartEvent(const sp<SyncEvent>& event
    }
}

void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) {
bool AudioFlinger::RecordThread::stop_l(RecordThread::RecordTrack* recordTrack) {
    ALOGV("RecordThread::stop");
    sp<ThreadBase> strongMe = this;
    {
        AutoMutex lock(mLock);
        if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) {
            mActiveTrack->mState = TrackBase::PAUSING;
    if (recordTrack != mActiveTrack.get() || recordTrack->mState == TrackBase::PAUSING) {
        return false;
    }
    recordTrack->mState = TrackBase::PAUSING;
    // do not wait for mStartStopCond if exiting
    if (exitPending()) {
                return;
        return true;
    }
    mStartStopCond.wait(mLock);
    // if we have been restarted, recordTrack == mActiveTrack.get() here
            if (exitPending() || mActiveTrack == 0 || recordTrack != mActiveTrack.get()) {
                mLock.unlock();
                AudioSystem::stopInput(mId);
                mLock.lock();
    if (exitPending() || recordTrack != mActiveTrack.get()) {
        ALOGV("Record stopped OK");
        return true;
    }
        }
    }
    return false;
}

bool AudioFlinger::RecordThread::isValidSyncEvent(const sp<SyncEvent>& event)
+5 −1
Original line number Diff line number Diff line
@@ -1432,7 +1432,11 @@ private:
                status_t    start(RecordTrack* recordTrack,
                                  AudioSystem::sync_event_t event,
                                  int triggerSession);
                void        stop(RecordTrack* recordTrack);

                // ask the thread to stop the specified track, and
                // return true if the caller should then do it's part of the stopping process
                bool        stop_l(RecordTrack* recordTrack);

                void        dump(int fd, const Vector<String16>& args);
                AudioStreamIn* clearInput();
                virtual audio_stream_t* stream() const;