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

Commit 67bf7cb3 authored by Andy Hung's avatar Andy Hung Committed by Android (Google) Code Review
Browse files

Merge "AudioTrack: get/setStartThresholdInFrames" into sc-dev

parents 681a1e69 3c7f47af
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ private:
                // This is set by AudioTrack.setBufferSizeInFrames().
                // A write will not fill the buffer above this limit.
    volatile    uint32_t   mBufferSizeInFrames;  // effective size of the buffer
    volatile    uint32_t   mStartThresholdInFrames; // min frames in buffer to start streaming

public:

@@ -216,6 +217,8 @@ public:
    };

    size_t frameCount() const { return mFrameCount; }
    uint32_t getStartThresholdInFrames() const;
    uint32_t setStartThresholdInFrames(uint32_t startThresholdInFrames);

protected:
    // These refer to shared memory, and are virtual addresses with respect to the current process.
+56 −0
Original line number Diff line number Diff line
@@ -1283,6 +1283,46 @@ ssize_t AudioTrack::setBufferSizeInFrames(size_t bufferSizeInFrames)
    return finalBufferSize;
}

ssize_t AudioTrack::getStartThresholdInFrames() const
{
    AutoMutex lock(mLock);
    if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) {
        return NO_INIT;
    }
    return (ssize_t) mProxy->getStartThresholdInFrames();
}

ssize_t AudioTrack::setStartThresholdInFrames(size_t startThresholdInFrames)
{
    if (startThresholdInFrames > INT32_MAX || startThresholdInFrames == 0) {
        // contractually we could simply return the current threshold in frames
        // to indicate the request was ignored, but we return an error here.
        return BAD_VALUE;
    }
    AutoMutex lock(mLock);
    // We do not permit calling setStartThresholdInFrames() between the AudioTrack
    // default ctor AudioTrack() and set(...) but rather fail such an attempt.
    // (To do so would require a cached mOrigStartThresholdInFrames and we may
    // not have proper validation for the actual set value).
    if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) {
        return NO_INIT;
    }
    const uint32_t original = mProxy->getStartThresholdInFrames();
    const uint32_t final = mProxy->setStartThresholdInFrames(startThresholdInFrames);
    if (original != final) {
        android::mediametrics::LogItem(mMetricsId)
                .set(AMEDIAMETRICS_PROP_EVENT, AMEDIAMETRICS_PROP_EVENT_VALUE_SETSTARTTHRESHOLD)
                .set(AMEDIAMETRICS_PROP_STARTTHRESHOLDFRAMES, (int32_t)final)
                .record();
        if (original > final) {
            // restart track if it was disabled by audioflinger due to previous underrun
            // and we reduced the number of frames for the threshold.
            restartIfDisabled();
        }
    }
    return final;
}

status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
{
    if (mSharedBuffer == 0 || isOffloadedOrDirect()) {
@@ -2602,6 +2642,10 @@ status_t AudioTrack::restoreTrack_l(const char *from)
        staticPosition = mStaticProxy->getPosition().unsignedValue();
    }

    // save the old startThreshold and framecount
    const uint32_t originalStartThresholdInFrames = mProxy->getStartThresholdInFrames();
    const uint32_t originalFrameCount = mProxy->frameCount();

    // See b/74409267. Connecting to a BT A2DP device supporting multiple codecs
    // causes a lot of churn on the service side, and it can reject starting
    // playback of a previously created track. May also apply to other cases.
@@ -2662,6 +2706,18 @@ retry:
            return status;
        });

        // restore the original start threshold if different than frameCount.
        if (originalStartThresholdInFrames != originalFrameCount) {
            // Note: mProxy->setStartThresholdInFrames() call is in the Proxy
            // and does not trigger a restart.
            // (Also CBLK_DISABLED is not set, buffers are empty after track recreation).
            // Any start would be triggered on the mState == ACTIVE check below.
            const uint32_t currentThreshold =
                    mProxy->setStartThresholdInFrames(originalStartThresholdInFrames);
            ALOGD_IF(originalStartThresholdInFrames != currentThreshold,
                    "%s(%d) startThresholdInFrames changing from %u to %u",
                    __func__, mPortId, originalStartThresholdInFrames, currentThreshold);
        }
        if (mState == STATE_ACTIVE) {
            mAudioTrack->start(&result);
        }
+38 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define LOG_TAG "AudioTrackShared"
//#define LOG_NDEBUG 0

#include <atomic>
#include <android-base/macros.h>
#include <private/media/AudioTrackShared.h>
#include <utils/Log.h>
@@ -33,6 +34,21 @@ size_t clampToSize(T x) {
    return sizeof(T) > sizeof(size_t) && x > (T) SIZE_MAX ? SIZE_MAX : x < 0 ? 0 : (size_t) x;
}

// compile-time safe atomics. TODO: update all methods to use it
template <typename T>
T android_atomic_load(const volatile T* addr) {
    static_assert(sizeof(T) == sizeof(std::atomic<T>)); // no extra sync data required.
    static_assert(std::atomic<T>::is_always_lock_free); // no hash lock somewhere.
    return atomic_load((std::atomic<T>*)addr);          // memory_order_seq_cst
}

template <typename T>
void android_atomic_store(const volatile T* addr, T value) {
    static_assert(sizeof(T) == sizeof(std::atomic<T>)); // no extra sync data required.
    static_assert(std::atomic<T>::is_always_lock_free); // no hash lock somewhere.
    atomic_store((std::atomic<T>*)addr, value);         // memory_order_seq_cst
}

// incrementSequence is used to determine the next sequence value
// for the loop and position sequence counters.  It should return
// a value between "other" + 1 and "other" + INT32_MAX, the choice of
@@ -51,6 +67,7 @@ audio_track_cblk_t::audio_track_cblk_t()
    : mServer(0), mFutex(0), mMinimum(0)
    , mVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY), mSampleRate(0), mSendLevel(0)
    , mBufferSizeInFrames(0)
    , mStartThresholdInFrames(0) // filled in by the server.
    , mFlags(0)
{
    memset(&u, 0, sizeof(u));
@@ -66,6 +83,26 @@ Proxy::Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t
{
}

uint32_t Proxy::getStartThresholdInFrames() const
{
    const uint32_t startThresholdInFrames =
           android_atomic_load(&mCblk->mStartThresholdInFrames);
    if (startThresholdInFrames == 0 || startThresholdInFrames > mFrameCount) {
        ALOGD("%s: startThresholdInFrames %u not between 1 and frameCount %zu, "
                "setting to frameCount",
                __func__, startThresholdInFrames, mFrameCount);
        return mFrameCount;
    }
    return startThresholdInFrames;
}

uint32_t Proxy::setStartThresholdInFrames(uint32_t startThresholdInFrames)
{
    const uint32_t actual = std::min((size_t)startThresholdInFrames, frameCount());
    android_atomic_store(&mCblk->mStartThresholdInFrames, actual);
    return actual;
}

// ---------------------------------------------------------------------------

ClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
@@ -663,6 +700,7 @@ ServerProxy::ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCo
    , mTimestampMutator(&cblk->mExtendedTimestampQueue)
{
    cblk->mBufferSizeInFrames = frameCount;
    cblk->mStartThresholdInFrames = frameCount;
}

__attribute__((no_sanitize("integer")))
+13 −0
Original line number Diff line number Diff line
@@ -429,6 +429,19 @@ public:
     */
            ssize_t     setBufferSizeInFrames(size_t size);

    /* Returns the start threshold on the buffer for audio streaming
     * or a negative value if the AudioTrack is not initialized.
     */
            ssize_t     getStartThresholdInFrames() const;

    /* Sets the start threshold in frames on the buffer for audio streaming.
     *
     * May be clamped internally. Returns the actual value set, or a negative
     * value if the AudioTrack is not initialized or if the input
     * is zero or greater than INT_MAX.
     */
            ssize_t     setStartThresholdInFrames(size_t startThresholdInFrames);

    /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */
            sp<IMemory> sharedBuffer() const { return mSharedBuffer; }

+2 −0
Original line number Diff line number Diff line
@@ -142,6 +142,7 @@
#define AMEDIAMETRICS_PROP_SESSIONID      "sessionId"      // int32
#define AMEDIAMETRICS_PROP_SHARINGMODE    "sharingMode"    // string value, "exclusive", shared"
#define AMEDIAMETRICS_PROP_SOURCE         "source"         // string (AudioAttributes)
#define AMEDIAMETRICS_PROP_STARTTHRESHOLDFRAMES "startThresholdFrames" // int32 (AudioTrack)
#define AMEDIAMETRICS_PROP_STARTUPMS      "startupMs"      // double value
// State is "ACTIVE" or "STOPPED" for AudioRecord
#define AMEDIAMETRICS_PROP_STATE          "state"          // string
@@ -187,6 +188,7 @@
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETLOGSESSIONID  "setLogSessionId" // AudioTrack, Record
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETPLAYBACKPARAM "setPlaybackParam" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETPLAYERIID "setPlayerIId" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETSTARTTHRESHOLD "setStartThreshold" // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOICEVOLUME   "setVoiceVolume" // AudioFlinger
#define AMEDIAMETRICS_PROP_EVENT_VALUE_SETVOLUME  "setVolume"  // AudioTrack
#define AMEDIAMETRICS_PROP_EVENT_VALUE_START      "start"  // AudioTrack, AudioRecord
Loading