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

Commit cf4d2931 authored by Treehugger Robot's avatar Treehugger Robot Committed by Automerger Merge Worker
Browse files

Merge "audiorecord_tests: Fix remaining threading issues" into main am: 21675fac

parents 324b3459 21675fac
Loading
Loading
Loading
Loading
+74 −23
Original line number Diff line number Diff line
@@ -294,6 +294,7 @@ size_t AudioCapture::onMoreData(const AudioRecord::Buffer& buffer) {
        ts.getBestTimestamp(&position, &timeNs, ExtendedTimestamp::TIMEBASE_MONOTONIC, &location) ==
                OK) {
        // Use audio timestamp.
        std::lock_guard l(mMutex);
        timeUs = timeNs / 1000 -
                 (position - mNumFramesReceived + mNumFramesLost) * usPerSec / mSampleRate;
    } else {
@@ -322,6 +323,7 @@ size_t AudioCapture::onMoreData(const AudioRecord::Buffer& buffer) {
        } else {
            numLostBytes = 0;
        }
        std::lock_guard l(mMutex);
        const int64_t timestampUs =
                ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
                mRecord->getSampleRate();
@@ -335,6 +337,7 @@ size_t AudioCapture::onMoreData(const AudioRecord::Buffer& buffer) {
    if (buffer.size() == 0) {
        ALOGW("Nothing is available from AudioRecord callback buffer");
    } else {
        std::lock_guard l(mMutex);
        const size_t bufferSize = buffer.size();
        const int64_t timestampUs =
                ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
@@ -359,17 +362,24 @@ size_t AudioCapture::onMoreData(const AudioRecord::Buffer& buffer) {

void AudioCapture::onOverrun() {
    ALOGV("received event overrun");
    mBufferOverrun = true;
}

void AudioCapture::onMarker(uint32_t markerPosition) {
    ALOGV("received Callback at position %d", markerPosition);
    {
        std::lock_guard l(mMutex);
        mReceivedCbMarkerAtPosition = markerPosition;
    }
    mMarkerCondition.notify_all();
}

void AudioCapture::onNewPos(uint32_t markerPosition) {
    ALOGV("received Callback at position %d", markerPosition);
    mReceivedCbMarkerCount++;
    {
        std::lock_guard l(mMutex);
        mReceivedCbMarkerCount = mReceivedCbMarkerCount.value_or(0) + 1;
    }
    mMarkerCondition.notify_all();
}

void AudioCapture::onNewIAudioRecord() {
@@ -387,20 +397,7 @@ AudioCapture::AudioCapture(audio_source_t inputSource, uint32_t sampleRate, audi
      mFlags(flags),
      mSessionId(sessionId),
      mTransferType(transferType),
      mAttributes(attributes) {
    mFrameCount = 0;
    mNotificationFrames = 0;
    mNumFramesToRecord = 0;
    mNumFramesReceived = 0;
    mNumFramesLost = 0;
    mBufferOverrun = false;
    mMarkerPosition = 0;
    mMarkerPeriod = 0;
    mReceivedCbMarkerAtPosition = -1;
    mReceivedCbMarkerCount = 0;
    mState = REC_NO_INIT;
    mStopRecording = false;
}
      mAttributes(attributes) {}

AudioCapture::~AudioCapture() {
    if (mOutFileFd > 0) close(mOutFileFd);
@@ -531,25 +528,32 @@ status_t AudioCapture::obtainBuffer(RawBuffer& buffer) {
    const int maxTries = MAX_WAIT_TIME_MS / WAIT_PERIOD_MS;
    int counter = 0;
    size_t nonContig = 0;
    while (mNumFramesReceived < mNumFramesToRecord) {
    int64_t numFramesReceived;
    {
        std::lock_guard l(mMutex);
        numFramesReceived = mNumFramesReceived;
    }
    while (numFramesReceived < mNumFramesToRecord) {
        AudioRecord::Buffer recordBuffer;
        recordBuffer.frameCount = mNotificationFrames;
        status_t status = mRecord->obtainBuffer(&recordBuffer, 1, &nonContig);
        if (OK == status) {
            const int64_t timestampUs =
                    ((1000000LL * mNumFramesReceived) + (mRecord->getSampleRate() >> 1)) /
                    ((1000000LL * numFramesReceived) + (mRecord->getSampleRate() >> 1)) /
                    mRecord->getSampleRate();
            RawBuffer buff{-1, timestampUs, static_cast<int32_t>(recordBuffer.size())};
            memcpy(buff.mData.get(), recordBuffer.data(), recordBuffer.size());
            buffer = std::move(buff);
            mNumFramesReceived += recordBuffer.size() / mRecord->frameSize();
            numFramesReceived += recordBuffer.size() / mRecord->frameSize();
            mRecord->releaseBuffer(&recordBuffer);
            counter = 0;
        } else if (WOULD_BLOCK == status) {
            // if not received a buffer for MAX_WAIT_TIME_MS, something has gone wrong
            if (counter == maxTries) return TIMED_OUT;
            counter++;
            if (counter++ == maxTries) status = TIMED_OUT;
        }
        std::lock_guard l(mMutex);
        mNumFramesReceived = numFramesReceived;
        if (TIMED_OUT == status) return status;
    }
    return OK;
}
@@ -577,7 +581,12 @@ status_t AudioCapture::obtainBufferCb(RawBuffer& buffer) {
status_t AudioCapture::audioProcess() {
    RawBuffer buffer;
    status_t status = OK;
    while (mNumFramesReceived < mNumFramesToRecord && status == OK) {
    int64_t numFramesReceived;
    {
        std::lock_guard l(mMutex);
        numFramesReceived = mNumFramesReceived;
    }
    while (numFramesReceived < mNumFramesToRecord && status == OK) {
        if (mTransferType == AudioRecord::TRANSFER_CALLBACK)
            status = obtainBufferCb(buffer);
        else
@@ -586,10 +595,52 @@ status_t AudioCapture::audioProcess() {
            const char* ptr = static_cast<const char*>(static_cast<void*>(buffer.mData.get()));
            write(mOutFileFd, ptr, buffer.mCapacity);
        }
        std::lock_guard l(mMutex);
        numFramesReceived = mNumFramesReceived;
    }
    return OK;
}

uint32_t AudioCapture::getMarkerPeriod() const {
    std::lock_guard l(mMutex);
    return mMarkerPeriod;
}

uint32_t AudioCapture::getMarkerPosition() const {
    std::lock_guard l(mMutex);
    return mMarkerPosition;
}

void AudioCapture::setMarkerPeriod(uint32_t markerPeriod) {
    std::lock_guard l(mMutex);
    mMarkerPeriod = markerPeriod;
}

void AudioCapture::setMarkerPosition(uint32_t markerPosition) {
    std::lock_guard l(mMutex);
    mMarkerPosition = markerPosition;
}

uint32_t AudioCapture::waitAndGetReceivedCbMarkerAtPosition() const {
    std::unique_lock lock(mMutex);
    android::base::ScopedLockAssertion lock_assertion(mMutex);
    mMarkerCondition.wait_for(lock, std::chrono::seconds(3), [this]() {
        android::base::ScopedLockAssertion lock_assertion(mMutex);
        return mReceivedCbMarkerAtPosition.has_value();
    });
    return mReceivedCbMarkerAtPosition.value_or(~0);
}

uint32_t AudioCapture::waitAndGetReceivedCbMarkerCount() const {
    std::unique_lock lock(mMutex);
    android::base::ScopedLockAssertion lock_assertion(mMutex);
    mMarkerCondition.wait_for(lock, std::chrono::seconds(3), [this]() {
        android::base::ScopedLockAssertion lock_assertion(mMutex);
        return mReceivedCbMarkerCount.has_value();
    });
    return mReceivedCbMarkerCount.value_or(0);
}

status_t listAudioPorts(std::vector<audio_port_v7>& portsVec) {
    int attempts = 5;
    status_t status;
+24 −16
Original line number Diff line number Diff line
@@ -146,8 +146,8 @@ class AudioCapture : public AudioRecord::IAudioRecordCallback {
    ~AudioCapture();
    size_t onMoreData(const AudioRecord::Buffer& buffer) override EXCLUDES(mMutex);
    void onOverrun() override;
    void onMarker(uint32_t markerPosition) override;
    void onNewPos(uint32_t newPos) override;
    void onMarker(uint32_t markerPosition) override EXCLUDES(mMutex);
    void onNewPos(uint32_t newPos) override EXCLUDES(mMutex);
    void onNewIAudioRecord() override;
    status_t create();
    status_t setRecordDuration(float durationInSec);
@@ -157,20 +157,19 @@ class AudioCapture : public AudioRecord::IAudioRecordCallback {
    status_t start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
                   audio_session_t triggerSession = AUDIO_SESSION_NONE);
    status_t obtainBufferCb(RawBuffer& buffer) EXCLUDES(mMutex);
    status_t obtainBuffer(RawBuffer& buffer);
    status_t audioProcess();
    status_t obtainBuffer(RawBuffer& buffer) EXCLUDES(mMutex);
    status_t audioProcess() EXCLUDES(mMutex);
    status_t stop() EXCLUDES(mMutex);
    uint32_t getMarkerPeriod() const EXCLUDES(mMutex);
    uint32_t getMarkerPosition() const EXCLUDES(mMutex);
    void setMarkerPeriod(uint32_t markerPeriod) EXCLUDES(mMutex);
    void setMarkerPosition(uint32_t markerPosition) EXCLUDES(mMutex);
    uint32_t waitAndGetReceivedCbMarkerAtPosition() const EXCLUDES(mMutex);
    uint32_t waitAndGetReceivedCbMarkerCount() const EXCLUDES(mMutex);

    uint32_t mFrameCount;
    uint32_t mNotificationFrames;
    int64_t mNumFramesToRecord;
    int64_t mNumFramesReceived;
    int64_t mNumFramesLost;
    uint32_t mMarkerPosition;
    uint32_t mMarkerPeriod;
    uint32_t mReceivedCbMarkerAtPosition;
    uint32_t mReceivedCbMarkerCount;
    bool mBufferOverrun;
    uint32_t mFrameCount = 0;
    uint32_t mNotificationFrames = 0;
    int64_t mNumFramesToRecord = 0;

    enum State {
        REC_NO_INIT,
@@ -191,14 +190,23 @@ class AudioCapture : public AudioRecord::IAudioRecordCallback {

    size_t mMaxBytesPerCallback = 2048;
    sp<AudioRecord> mRecord;
    State mState;
    bool mStopRecording GUARDED_BY(mMutex);
    State mState = REC_NO_INIT;
    bool mStopRecording GUARDED_BY(mMutex) = false;
    std::string mFileName;
    int mOutFileFd = -1;

    mutable std::mutex mMutex;
    std::condition_variable mCondition;
    std::deque<RawBuffer> mBuffersReceived GUARDED_BY(mMutex);

    mutable std::condition_variable mMarkerCondition;
    uint32_t mMarkerPeriod GUARDED_BY(mMutex) = 0;
    uint32_t mMarkerPosition GUARDED_BY(mMutex) = 0;
    std::optional<uint32_t> mReceivedCbMarkerCount GUARDED_BY(mMutex);
    std::optional<uint32_t> mReceivedCbMarkerAtPosition GUARDED_BY(mMutex);

    int64_t mNumFramesReceived GUARDED_BY(mMutex) = 0;
    int64_t mNumFramesLost GUARDED_BY(mMutex) = 0;
};

#endif  // AUDIO_TEST_UTILS_H_
+17 −14
Original line number Diff line number Diff line
@@ -102,7 +102,10 @@ class AudioRecordCreateTest : public ::testing::TestWithParam<RecordCreateTestPa
    }

    void TearDown() override {
        if (mAC) ASSERT_EQ(OK, mAC->stop());
        if (mAC) {
            ASSERT_EQ(OK, mAC->stop());
            mAC.clear();
        }
    }
};

@@ -168,33 +171,33 @@ TEST_F(AudioRecordTest, TestEventRecordTrackStop) {
}

TEST_F(AudioRecordTest, TestGetSetMarker) {
    mAC->mMarkerPosition = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setMarkerPosition(mAC->mMarkerPosition))
    mAC->setMarkerPosition((mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1));
    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setMarkerPosition(mAC->getMarkerPosition()))
            << "setMarkerPosition() failed";
    uint32_t marker;
    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getMarkerPosition(&marker))
            << "getMarkerPosition() failed";
    EXPECT_EQ(OK, mAC->start()) << "start recording failed";
    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
    // TODO(b/348658586): Properly synchronize callback updates with the test thread.
    EXPECT_EQ(marker, mAC->mMarkerPosition)
    EXPECT_EQ(marker, mAC->getMarkerPosition())
            << "configured marker and received marker are different";
    EXPECT_EQ(mAC->mReceivedCbMarkerAtPosition, mAC->mMarkerPosition)
    EXPECT_EQ(mAC->waitAndGetReceivedCbMarkerAtPosition(), mAC->getMarkerPosition())
            << "configured marker and received cb marker are different";
}

TEST_F(AudioRecordTest, TestGetSetMarkerPeriodical) {
    mAC->mMarkerPeriod = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->mMarkerPeriod))
    mAC->setMarkerPeriod((mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1));
    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->getMarkerPeriod()))
            << "setPositionUpdatePeriod() failed";
    uint32_t marker;
    EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPositionUpdatePeriod(&marker))
            << "getPositionUpdatePeriod() failed";
    EXPECT_EQ(OK, mAC->start()) << "start recording failed";
    EXPECT_EQ(OK, mAC->audioProcess()) << "audioProcess failed";
    // TODO(b/348658586): Properly synchronize callback updates with the test thread.
    EXPECT_EQ(marker, mAC->mMarkerPeriod) << "configured marker and received marker are different";
    EXPECT_EQ(mAC->mReceivedCbMarkerCount, mAC->mNumFramesToRecord / mAC->mMarkerPeriod)
    EXPECT_EQ(marker, mAC->getMarkerPeriod())
            << "configured marker and received marker are different";
    EXPECT_EQ(mAC->waitAndGetReceivedCbMarkerCount(),
              mAC->mNumFramesToRecord / mAC->getMarkerPeriod())
            << "configured marker and received cb marker are different";
}

@@ -221,12 +224,12 @@ TEST_P(AudioRecordCreateTest, TestCreateRecord) {
        EXPECT_EQ(mSessionId, mAC->getAudioRecordHandle()->getSessionId());
    if (mTransferType != AudioRecord::TRANSFER_CALLBACK) {
        uint32_t marker;
        mAC->mMarkerPosition = (mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1);
        mAC->setMarkerPosition((mAC->mNotificationFrames << 3) + (mAC->mNotificationFrames >> 1));
        EXPECT_EQ(INVALID_OPERATION,
                  mAC->getAudioRecordHandle()->setMarkerPosition(mAC->mMarkerPosition));
                  mAC->getAudioRecordHandle()->setMarkerPosition(mAC->getMarkerPosition()));
        EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getMarkerPosition(&marker));
        EXPECT_EQ(INVALID_OPERATION,
                  mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->mMarkerPosition));
                  mAC->getAudioRecordHandle()->setPositionUpdatePeriod(mAC->getMarkerPosition()));
        EXPECT_EQ(OK, mAC->getAudioRecordHandle()->getPositionUpdatePeriod(&marker));
    }
    EXPECT_EQ(OK, mAC->start()) << "start recording failed";