|
|
|
@ -393,19 +393,50 @@ size_t ClientProxy::getMisalignment()
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
__attribute__((no_sanitize("integer")))
|
|
|
|
|
void AudioTrackClientProxy::flush()
|
|
|
|
|
{
|
|
|
|
|
sendStreamingFlushStop(true /* flush */);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AudioTrackClientProxy::stop()
|
|
|
|
|
{
|
|
|
|
|
sendStreamingFlushStop(false /* flush */);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sets the client-written mFlush and mStop positions, which control server behavior.
|
|
|
|
|
//
|
|
|
|
|
// @param flush indicates whether the operation is a flush or stop.
|
|
|
|
|
// A client stop sets mStop to the current write position;
|
|
|
|
|
// the server will not read past this point until start() or subsequent flush().
|
|
|
|
|
// A client flush sets both mStop and mFlush to the current write position.
|
|
|
|
|
// This advances the server read limit (if previously set) and on the next
|
|
|
|
|
// server read advances the server read position to this limit.
|
|
|
|
|
//
|
|
|
|
|
void AudioTrackClientProxy::sendStreamingFlushStop(bool flush)
|
|
|
|
|
{
|
|
|
|
|
// TODO: Replace this by 64 bit counters - avoids wrap complication.
|
|
|
|
|
// This works for mFrameCountP2 <= 2^30
|
|
|
|
|
size_t increment = mFrameCountP2 << 1;
|
|
|
|
|
size_t mask = increment - 1;
|
|
|
|
|
audio_track_cblk_t* cblk = mCblk;
|
|
|
|
|
// mFlush is 32 bits concatenated as [ flush_counter ] [ newfront_offset ]
|
|
|
|
|
// Should newFlush = cblk->u.mStreaming.mRear? Only problem is
|
|
|
|
|
// if you want to flush twice to the same rear location after a 32 bit wrap.
|
|
|
|
|
int32_t newFlush = (cblk->u.mStreaming.mRear & mask) |
|
|
|
|
|
((cblk->u.mStreaming.mFlush & ~mask) + increment);
|
|
|
|
|
android_atomic_release_store(newFlush, &cblk->u.mStreaming.mFlush);
|
|
|
|
|
|
|
|
|
|
const size_t increment = mFrameCountP2 << 1;
|
|
|
|
|
const size_t mask = increment - 1;
|
|
|
|
|
// No need for client atomic synchronization on mRear, mStop, mFlush
|
|
|
|
|
// as AudioTrack client only read/writes to them under client lock. Server only reads.
|
|
|
|
|
const int32_t rearMasked = mCblk->u.mStreaming.mRear & mask;
|
|
|
|
|
|
|
|
|
|
// update stop before flush so that the server front
|
|
|
|
|
// never advances beyond a (potential) previous stop's rear limit.
|
|
|
|
|
int32_t stopBits; // the following add can overflow
|
|
|
|
|
__builtin_add_overflow(mCblk->u.mStreaming.mStop & ~mask, increment, &stopBits);
|
|
|
|
|
android_atomic_release_store(rearMasked | stopBits, &mCblk->u.mStreaming.mStop);
|
|
|
|
|
|
|
|
|
|
if (flush) {
|
|
|
|
|
int32_t flushBits; // the following add can overflow
|
|
|
|
|
__builtin_add_overflow(mCblk->u.mStreaming.mFlush & ~mask, increment, &flushBits);
|
|
|
|
|
android_atomic_release_store(rearMasked | flushBits, &mCblk->u.mStreaming.mFlush);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AudioTrackClientProxy::clearStreamEndDone() {
|
|
|
|
@ -540,6 +571,11 @@ void StaticAudioTrackClientProxy::flush()
|
|
|
|
|
LOG_ALWAYS_FATAL("static flush");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StaticAudioTrackClientProxy::stop()
|
|
|
|
|
{
|
|
|
|
|
; // no special handling required for static tracks.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void StaticAudioTrackClientProxy::setLoop(size_t loopStart, size_t loopEnd, int loopCount)
|
|
|
|
|
{
|
|
|
|
|
// This can only happen on a 64-bit client
|
|
|
|
@ -638,6 +674,7 @@ void ServerProxy::flushBufferIfNeeded()
|
|
|
|
|
if (flush != mFlush) {
|
|
|
|
|
ALOGV("ServerProxy::flushBufferIfNeeded() mStreaming.mFlush = 0x%x, mFlush = 0x%0x",
|
|
|
|
|
flush, mFlush);
|
|
|
|
|
// shouldn't matter, but for range safety use mRear instead of getRear().
|
|
|
|
|
int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
|
|
|
|
|
int32_t front = cblk->u.mStreaming.mFront;
|
|
|
|
|
|
|
|
|
@ -676,6 +713,45 @@ void ServerProxy::flushBufferIfNeeded()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((no_sanitize("integer")))
|
|
|
|
|
int32_t AudioTrackServerProxy::getRear() const
|
|
|
|
|
{
|
|
|
|
|
const int32_t stop = android_atomic_acquire_load(&mCblk->u.mStreaming.mStop);
|
|
|
|
|
const int32_t rear = android_atomic_acquire_load(&mCblk->u.mStreaming.mRear);
|
|
|
|
|
const int32_t stopLast = mStopLast.load(std::memory_order_acquire);
|
|
|
|
|
if (stop != stopLast) {
|
|
|
|
|
const int32_t front = mCblk->u.mStreaming.mFront;
|
|
|
|
|
const size_t overflowBit = mFrameCountP2 << 1;
|
|
|
|
|
const size_t mask = overflowBit - 1;
|
|
|
|
|
int32_t newRear = (rear & ~mask) | (stop & mask);
|
|
|
|
|
ssize_t filled = newRear - front;
|
|
|
|
|
if (filled < 0) {
|
|
|
|
|
// front and rear offsets span the overflow bit of the p2 mask
|
|
|
|
|
// so rebasing newrear.
|
|
|
|
|
ALOGV("stop wrap: filled %zx >= overflowBit %zx", filled, overflowBit);
|
|
|
|
|
newRear += overflowBit;
|
|
|
|
|
filled += overflowBit;
|
|
|
|
|
}
|
|
|
|
|
if (0 <= filled && (size_t) filled <= mFrameCount) {
|
|
|
|
|
// we're stopped, return the stop level as newRear
|
|
|
|
|
return newRear;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A corrupt stop. Log error and ignore.
|
|
|
|
|
ALOGE("mStopLast %#x -> stop %#x, front %#x, rear %#x, mask %#x, newRear %#x, "
|
|
|
|
|
"filled %zd=%#x",
|
|
|
|
|
stopLast, stop, front, rear,
|
|
|
|
|
(unsigned)mask, newRear, filled, (unsigned)filled);
|
|
|
|
|
// Don't reset mStopLast as this is const.
|
|
|
|
|
}
|
|
|
|
|
return rear;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AudioTrackServerProxy::start()
|
|
|
|
|
{
|
|
|
|
|
mStopLast = android_atomic_acquire_load(&mCblk->u.mStreaming.mStop);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
__attribute__((no_sanitize("integer")))
|
|
|
|
|
status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
|
|
|
|
|
{
|
|
|
|
@ -693,7 +769,7 @@ status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)
|
|
|
|
|
// See notes on barriers at ClientProxy::obtainBuffer()
|
|
|
|
|
if (mIsOut) {
|
|
|
|
|
flushBufferIfNeeded(); // might modify mFront
|
|
|
|
|
rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
|
|
|
|
|
rear = getRear();
|
|
|
|
|
front = cblk->u.mStreaming.mFront;
|
|
|
|
|
} else {
|
|
|
|
|
front = android_atomic_acquire_load(&cblk->u.mStreaming.mFront);
|
|
|
|
@ -825,8 +901,7 @@ size_t AudioTrackServerProxy::framesReady()
|
|
|
|
|
// FIXME should return an accurate value, but over-estimate is better than under-estimate
|
|
|
|
|
return mFrameCount;
|
|
|
|
|
}
|
|
|
|
|
// the acquire might not be necessary since not doing a subsequent read
|
|
|
|
|
int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
|
|
|
|
|
const int32_t rear = getRear();
|
|
|
|
|
ssize_t filled = rear - cblk->u.mStreaming.mFront;
|
|
|
|
|
// pipe should not already be overfull
|
|
|
|
|
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
|
|
|
|
@ -852,7 +927,7 @@ size_t AudioTrackServerProxy::framesReadySafe() const
|
|
|
|
|
if (flush != mFlush) {
|
|
|
|
|
return mFrameCount;
|
|
|
|
|
}
|
|
|
|
|
const int32_t rear = android_atomic_acquire_load(&cblk->u.mStreaming.mRear);
|
|
|
|
|
const int32_t rear = getRear();
|
|
|
|
|
const ssize_t filled = rear - cblk->u.mStreaming.mFront;
|
|
|
|
|
if (!(0 <= filled && (size_t) filled <= mFrameCount)) {
|
|
|
|
|
return 0; // error condition, silently return 0.
|
|
|
|
@ -1149,6 +1224,12 @@ void StaticAudioTrackServerProxy::tallyUnderrunFrames(uint32_t frameCount)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int32_t StaticAudioTrackServerProxy::getRear() const
|
|
|
|
|
{
|
|
|
|
|
LOG_ALWAYS_FATAL("getRear() not permitted for static tracks");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
} // namespace android
|
|
|
|
|