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

Commit 164d7634 authored by Robert Wu's avatar Robert Wu Committed by Android (Google) Code Review
Browse files

Merge "AAudio: Use futex for waitForStateChange"

parents 4518eb24 3da128d7
Loading
Loading
Loading
Loading
+0 −7
Original line number Original line Diff line number Diff line
@@ -605,13 +605,6 @@ aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t /*clockId*/,
    return AAUDIO_ERROR_INVALID_STATE;
    return AAUDIO_ERROR_INVALID_STATE;
}
}


aaudio_result_t AudioStreamInternal::updateStateMachine() {
    if (isDataCallbackActive()) {
        return AAUDIO_OK; // state is getting updated by the callback thread read/write call
    }
    return processCommands();
}

void AudioStreamInternal::logTimestamp(AAudioServiceMessage &command) {
void AudioStreamInternal::logTimestamp(AAudioServiceMessage &command) {
    static int64_t oldPosition = 0;
    static int64_t oldPosition = 0;
    static int64_t oldTime = 0;
    static int64_t oldTime = 0;
+1 −3
Original line number Original line Diff line number Diff line
@@ -48,7 +48,7 @@ public:
                                       int64_t *framePosition,
                                       int64_t *framePosition,
                                       int64_t *timeNanoseconds) override;
                                       int64_t *timeNanoseconds) override;


    virtual aaudio_result_t updateStateMachine() override;
    virtual aaudio_result_t processCommands() override;


    aaudio_result_t open(const AudioStreamBuilder &builder) override;
    aaudio_result_t open(const AudioStreamBuilder &builder) override;


@@ -110,8 +110,6 @@ protected:


    aaudio_result_t drainTimestampsFromService();
    aaudio_result_t drainTimestampsFromService();


    aaudio_result_t processCommands();

    aaudio_result_t stopCallback_l();
    aaudio_result_t stopCallback_l();


    virtual void prepareBuffersForStart() {}
    virtual void prepareBuffersForStart() {}
+20 −9
Original line number Original line Diff line number Diff line
@@ -21,7 +21,9 @@
#include <atomic>
#include <atomic>
#include <stdint.h>
#include <stdint.h>


#include <linux/futex.h>
#include <media/MediaMetricsItem.h>
#include <media/MediaMetricsItem.h>
#include <sys/syscall.h>


#include <aaudio/AAudio.h>
#include <aaudio/AAudio.h>


@@ -362,34 +364,37 @@ void AudioStream::close_l() {
}
}


void AudioStream::setState(aaudio_stream_state_t state) {
void AudioStream::setState(aaudio_stream_state_t state) {
    ALOGD("%s(s#%d) from %d to %d", __func__, getId(), mState, state);
    aaudio_stream_state_t oldState = mState.load();
    if (state == mState) {
    ALOGD("%s(s#%d) from %d to %d", __func__, getId(), oldState, state);
    if (state == oldState) {
        return; // no change
        return; // no change
    }
    }
    // Track transition to DISCONNECTED state.
    // Track transition to DISCONNECTED state.
    if (state == AAUDIO_STREAM_STATE_DISCONNECTED) {
    if (state == AAUDIO_STREAM_STATE_DISCONNECTED) {
        android::mediametrics::LogItem(mMetricsId)
        android::mediametrics::LogItem(mMetricsId)
                .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
                .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_DISCONNECT)
                .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(getState()))
                .set(AMEDIAMETRICS_PROP_STATE, AudioGlobal_convertStreamStateToText(oldState))
                .record();
                .record();
    }
    }
    // CLOSED is a final state
    // CLOSED is a final state
    if (mState == AAUDIO_STREAM_STATE_CLOSED) {
    if (oldState == AAUDIO_STREAM_STATE_CLOSED) {
        ALOGW("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);
        ALOGW("%s(%d) tried to set to %d but already CLOSED", __func__, getId(), state);


    // Once CLOSING, we can only move to CLOSED state.
    // Once CLOSING, we can only move to CLOSED state.
    } else if (mState == AAUDIO_STREAM_STATE_CLOSING
    } else if (oldState == AAUDIO_STREAM_STATE_CLOSING
               && state != AAUDIO_STREAM_STATE_CLOSED) {
               && state != AAUDIO_STREAM_STATE_CLOSED) {
        ALOGW("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);
        ALOGW("%s(%d) tried to set to %d but already CLOSING", __func__, getId(), state);


    // Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
    // Once DISCONNECTED, we can only move to CLOSING or CLOSED state.
    } else if (mState == AAUDIO_STREAM_STATE_DISCONNECTED
    } else if (oldState == AAUDIO_STREAM_STATE_DISCONNECTED
               && !(state == AAUDIO_STREAM_STATE_CLOSING
               && !(state == AAUDIO_STREAM_STATE_CLOSING
                   || state == AAUDIO_STREAM_STATE_CLOSED)) {
                   || state == AAUDIO_STREAM_STATE_CLOSED)) {
        ALOGW("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);
        ALOGW("%s(%d) tried to set to %d but already DISCONNECTED", __func__, getId(), state);


    } else {
    } else {
        mState = state;
        mState.store(state);
        // Wake up a wakeForStateChange thread if it exists.
        syscall(SYS_futex, &mState, FUTEX_WAKE_PRIVATE, INT_MAX, NULL, NULL, 0);
    }
    }
}
}


@@ -408,9 +413,15 @@ aaudio_result_t AudioStream::waitForStateChange(aaudio_stream_state_t currentSta
        if (durationNanos > timeoutNanoseconds) {
        if (durationNanos > timeoutNanoseconds) {
            durationNanos = timeoutNanoseconds;
            durationNanos = timeoutNanoseconds;
        }
        }
        AudioClock::sleepForNanos(durationNanos);
        struct timespec time;
        timeoutNanoseconds -= durationNanos;
        time.tv_sec = durationNanos / AAUDIO_NANOS_PER_SECOND;
        // Add the fractional nanoseconds.
        time.tv_nsec = durationNanos - (time.tv_sec * AAUDIO_NANOS_PER_SECOND);


        // Sleep for durationNanos. If mState changes from the callback
        // thread, this thread will wake up earlier.
        syscall(SYS_futex, &mState, FUTEX_WAIT_PRIVATE, currentState, &time, NULL, 0);
        timeoutNanoseconds -= durationNanos;
        aaudio_result_t result = updateStateMachine();
        aaudio_result_t result = updateStateMachine();
        if (result != AAUDIO_OK) {
        if (result != AAUDIO_OK) {
            return result;
            return result;
+13 −5
Original line number Original line Diff line number Diff line
@@ -100,10 +100,17 @@ public:
                                       int64_t *timeNanoseconds) = 0;
                                       int64_t *timeNanoseconds) = 0;


    /**
    /**
     * Update state machine.()
     * Update state machine.
     * @return
     * @return result of the operation.
     */
     */
    virtual aaudio_result_t updateStateMachine() = 0;
    aaudio_result_t updateStateMachine() {
        if (isDataCallbackActive()) {
            return AAUDIO_OK; // state is getting updated by the callback thread read/write call
        }
        return processCommands();
    };

    virtual aaudio_result_t processCommands() = 0;


    // =========== End ABSTRACT methods ===========================
    // =========== End ABSTRACT methods ===========================


@@ -184,7 +191,7 @@ public:
    // ============== Queries ===========================
    // ============== Queries ===========================


    aaudio_stream_state_t getState() const {
    aaudio_stream_state_t getState() const {
        return mState;
        return mState.load();
    }
    }


    virtual int32_t getBufferSize() const {
    virtual int32_t getBufferSize() const {
@@ -674,6 +681,8 @@ private:


    const android::sp<MyPlayerBase>   mPlayerBase;
    const android::sp<MyPlayerBase>   mPlayerBase;


    std::atomic<aaudio_stream_state_t>          mState{AAUDIO_STREAM_STATE_UNINITIALIZED};

    // These do not change after open().
    // These do not change after open().
    int32_t                     mSamplesPerFrame = AAUDIO_UNSPECIFIED;
    int32_t                     mSamplesPerFrame = AAUDIO_UNSPECIFIED;
    aaudio_channel_mask_t       mChannelMask = AAUDIO_UNSPECIFIED;
    aaudio_channel_mask_t       mChannelMask = AAUDIO_UNSPECIFIED;
@@ -682,7 +691,6 @@ private:
    aaudio_sharing_mode_t       mSharingMode = AAUDIO_SHARING_MODE_SHARED;
    aaudio_sharing_mode_t       mSharingMode = AAUDIO_SHARING_MODE_SHARED;
    bool                        mSharingModeMatchRequired = false; // must match sharing mode requested
    bool                        mSharingModeMatchRequired = false; // must match sharing mode requested
    audio_format_t              mFormat = AUDIO_FORMAT_DEFAULT;
    audio_format_t              mFormat = AUDIO_FORMAT_DEFAULT;
    aaudio_stream_state_t       mState = AAUDIO_STREAM_STATE_UNINITIALIZED;
    aaudio_performance_mode_t   mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
    aaudio_performance_mode_t   mPerformanceMode = AAUDIO_PERFORMANCE_MODE_NONE;
    int32_t                     mFramesPerBurst = 0;
    int32_t                     mFramesPerBurst = 0;
    int32_t                     mBufferCapacity = 0;
    int32_t                     mBufferCapacity = 0;
+2 −2
Original line number Original line Diff line number Diff line
@@ -127,7 +127,7 @@ size_t AudioStreamLegacy::onMoreData(const android::AudioTrack::Buffer& buffer)
            mCallbackEnabled.store(false);
            mCallbackEnabled.store(false);
        }
        }


        if (updateStateMachine() != AAUDIO_OK) {
        if (processCommands() != AAUDIO_OK) {
            forceDisconnect();
            forceDisconnect();
            mCallbackEnabled.store(false);
            mCallbackEnabled.store(false);
        }
        }
@@ -192,7 +192,7 @@ size_t AudioStreamLegacy::onMoreData(const android::AudioRecord::Buffer& buffer)
            mCallbackEnabled.store(false);
            mCallbackEnabled.store(false);
        }
        }


        if (updateStateMachine() != AAUDIO_OK) {
        if (processCommands() != AAUDIO_OK) {
            forceDisconnect();
            forceDisconnect();
            mCallbackEnabled.store(false);
            mCallbackEnabled.store(false);
        }
        }
Loading