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

Commit 86fec3ec authored by Eric Laurent's avatar Eric Laurent Committed by Android (Google) Code Review
Browse files

Merge "audio flinger: fix wraparound issues in AudioRecord shared audi history...

Merge "audio flinger: fix wraparound issues in AudioRecord shared audi history implementation" into sc-dev
parents 2b574ed9 2407ce3d
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ public:
                                audio_input_flags_t flags,
                                track_type type,
                                audio_port_handle_t portId = AUDIO_PORT_HANDLE_NONE,
                                int64_t startTimeMs = -1);
                                int32_t startFrames = -1);
    virtual             ~RecordTrack();
    virtual status_t    initCheck() const;

@@ -110,7 +110,7 @@ public:
            status_t    setPreferredMicrophoneFieldDimension(float zoom);
            status_t    shareAudioHistory(const std::string& sharedAudioPackageName,
                                          int64_t sharedAudioStartMs);
            int64_t     startTimeMs() { return mStartTimeMs; }
            int32_t     startFrames() { return mStartFrames; }

    static  bool        checkServerLatencySupported(
                                audio_format_t format, audio_input_flags_t flags) {
@@ -152,7 +152,7 @@ private:
            // used to enforce OP_RECORD_AUDIO
            sp<OpRecordAudioMonitor>           mOpRecordAudioMonitor;
            std::string                        mSharedAudioPackageName = {};
            int64_t                            mStartTimeMs = -1;
            int32_t                            mStartFrames = -1;
};

// playback track, used by PatchPanel
+43 −23
Original line number Diff line number Diff line
@@ -7934,18 +7934,18 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe

    { // scope for mLock
        Mutex::Autolock _l(mLock);
        long startTimeMs = -1;
        int32_t startFrames = -1;
        if (!mSharedAudioPackageName.empty()
                && mSharedAudioPackageName == checkedIdentity.packageName
                && mSharedAudioSessionId == sessionId
                && captureHotwordAllowed(checkedIdentity)) {
            startTimeMs = mSharedAudioStartMs;
            startFrames = mSharedAudioStartFrames;
        }

        track = new RecordTrack(this, client, attr, sampleRate,
                      format, channelMask, frameCount,
                      nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, creatorPid,
                      checkedIdentity, *flags, TrackBase::TYPE_DEFAULT, portId, startTimeMs);
                      checkedIdentity, *flags, TrackBase::TYPE_DEFAULT, portId, startFrames);

        lStatus = track->initCheck();
        if (lStatus != NO_ERROR) {
@@ -8202,17 +8202,32 @@ status_t AudioFlinger::RecordThread::shareAudioHistory_l(
    if ((hasAudioSession_l(sharedSessionId) & ThreadBase::TRACK_SESSION) == 0) {
        return BAD_VALUE;
    }
    if (sharedAudioStartMs < 0 || sharedAudioStartMs * mSampleRate / 1000 > mRsmpInRear) {

    if (sharedAudioStartMs < 0
        || sharedAudioStartMs > INT64_MAX / mSampleRate) {
        return BAD_VALUE;
    }

    // Current implementation of the input resampling buffer wraps around indexes at 32 bit.
    // As we cannot detect more than one wraparound, only accept values up current write position
    // after one wraparound
    // We assume recent wraparounds on mRsmpInRear only given it is unlikely that the requesting
    // app waits several hours after the start time was computed.
    const int64_t sharedAudioStartFrames = sharedAudioStartMs * mSampleRate / 1000;
    const int32_t sharedOffset = audio_utils::safe_sub_overflow(mRsmpInRear,
          (int32_t)sharedAudioStartFrames);
    if (sharedOffset < 0
          || sharedOffset > mRsmpInFrames) {
      return BAD_VALUE;
    }

    mSharedAudioPackageName = sharedAudioPackageName;
    if (mSharedAudioPackageName.empty()) {
        mSharedAudioSessionId = AUDIO_SESSION_NONE;
        mSharedAudioStartMs = -1;
        mSharedAudioStartFrames = -1;
    } else {
        mSharedAudioSessionId = sharedSessionId;
        mSharedAudioStartMs = sharedAudioStartMs;
        mSharedAudioStartFrames = (int32_t)sharedAudioStartFrames;
    }
    return NO_ERROR;
}
@@ -8359,14 +8374,14 @@ void AudioFlinger::RecordThread::ResamplerBufferProvider::reset()
    mRsmpInUnrel = 0;
    const int32_t rear = recordThread->mRsmpInRear;
    ssize_t deltaFrames = 0;
    if (mRecordTrack->startTimeMs() >= 0) {
        int32_t startFrames = mRecordTrack->startTimeMs() * recordThread->sampleRate()  / 1000;
        // start frame has to be in the past
        //TODO: b/185972521 fix in case rear or startFrames wrap around
        if (startFrames > rear) {
            startFrames = rear;
        }
    if (mRecordTrack->startFrames() >= 0) {
        int32_t startFrames = mRecordTrack->startFrames();
        // Accept a recent wraparound of mRsmpInRear
        if (startFrames <= rear) {
            deltaFrames = rear - startFrames;
        } else {
            deltaFrames = (int32_t)((int64_t)rear + UINT32_MAX + 1 - startFrames);
        }
        // start frame cannot be further in the past than start of resampling buffer
        if ((size_t) deltaFrames > recordThread->mRsmpInFrames) {
            deltaFrames = recordThread->mRsmpInFrames;
@@ -8828,17 +8843,22 @@ int32_t AudioFlinger::RecordThread::getOldestFront_l()
    if (mTracks.size() == 0) {
        return 0;
    }
    //TODO: b/185972521 fix in case of wrap around on one track:
    //  want the max(rear - front) for all tracks.
    int32_t front = INT_MAX;
    int32_t oldestFront = mRsmpInRear;
    int32_t maxFilled = 0;
    for (size_t i = 0; i < mTracks.size(); i++) {
        front = std::min(front, mTracks[i]->mResamplerBufferProvider->getFront());
        int32_t front = mTracks[i]->mResamplerBufferProvider->getFront();
        int32_t filled;
        if (front <= mRsmpInRear) {
            filled = mRsmpInRear - front;
        } else {
            filled = (int32_t)((int64_t)mRsmpInRear + UINT32_MAX + 1 - front);
        }
        if (filled > maxFilled) {
            oldestFront = front;
            maxFilled = filled;
        }
    // discard any audio past the buffer size
    if (audio_utils::safe_add_overflow(front, (int32_t)mRsmpInFrames) < mRsmpInRear) {
        front = audio_utils::safe_sub_overflow(mRsmpInRear, (int32_t)mRsmpInFrames);
    }
    return front;
    return oldestFront;
}

void AudioFlinger::RecordThread::updateFronts_l(int32_t offset)
+1 −1
Original line number Diff line number Diff line
@@ -1863,7 +1863,7 @@ private:
            DeviceDescriptorBaseVector          mOutDevices;

            std::string                         mSharedAudioPackageName = {};
            long                                mSharedAudioStartMs = 0;
            int32_t                             mSharedAudioStartFrames = -1;
            audio_session_t                     mSharedAudioSessionId = AUDIO_SESSION_NONE;
};

+2 −2
Original line number Diff line number Diff line
@@ -2378,7 +2378,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
            audio_input_flags_t flags,
            track_type type,
            audio_port_handle_t portId,
            int64_t startTimeMs)
            int32_t startFrames)
    :   TrackBase(thread, client, attr, sampleRate, format,
                  channelMask, frameCount, buffer, bufferSize, sessionId,
                  creatorPid,
@@ -2396,7 +2396,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
        mFlags(flags),
        mSilenced(false),
        mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(identity, attr)),
        mStartTimeMs(startTimeMs)
        mStartFrames(startFrames)
{
    if (mCblk == NULL) {
        return;