Loading include/private/media/AudioTrackShared.h +2 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ namespace android { // ---------------------------------------------------------------------------- // for audio_track_cblk_t::mFlags #define CBLK_UNDERRUN 0x01 // set by server immediately on output underrun, cleared by client #define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger, // clear: track is ready when buffer full Loading Loading @@ -127,7 +128,7 @@ public: // read-only for client, server writes once at initialization and is then read-only uint8_t mName; // normal tracks: track name, fast tracks: track index volatile int32_t flags; volatile int32_t mFlags; // combinations of CBLK_* // Cache line boundary (32 bytes) Loading media/libmedia/AudioRecord.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -300,7 +300,7 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); mNewPosition = mProxy->getPosition() + mUpdatePeriod; int32_t flags = android_atomic_acquire_load(&mCblk->flags); int32_t flags = android_atomic_acquire_load(&mCblk->mFlags); status_t status = NO_ERROR; if (!(flags & CBLK_INVALID)) { Loading Loading @@ -667,7 +667,7 @@ nsecs_t AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) mLock.lock(); // Can only reference mCblk while locked int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->flags); int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags); // Check for track invalidation if (flags & CBLK_INVALID) { Loading media/libmedia/AudioTrack.cpp +9 −9 Original line number Diff line number Diff line Loading @@ -389,7 +389,7 @@ status_t AudioTrack::start() mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); } mNewPosition = mProxy->getPosition() + mUpdatePeriod; int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->flags); int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags); sp<AudioTrackThread> t = mAudioTrackThread; if (t != 0) { Loading Loading @@ -1182,7 +1182,7 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) // restart track if it was disabled by audioflinger due to previous underrun if (mState == STATE_ACTIVE) { audio_track_cblk_t* cblk = mCblk; if (android_atomic_and(~CBLK_DISABLED, &cblk->flags) & CBLK_DISABLED) { if (android_atomic_and(~CBLK_DISABLED, &cblk->mFlags) & CBLK_DISABLED) { ALOGW("releaseBuffer() track %p name=%#x disabled due to previous underrun, restarting", this, cblk->mName); // FIXME ignoring status Loading Loading @@ -1261,16 +1261,16 @@ status_t TimedAudioTrack::allocateTimedBuffer(size_t size, sp<IMemory>* buffer) // fails indicating that the server is dead, flag the track as invalid so // we can attempt to restore in just a bit. audio_track_cblk_t* cblk = mCblk; if (!(cblk->flags & CBLK_INVALID)) { if (!(cblk->mFlags & CBLK_INVALID)) { result = mAudioTrack->allocateTimedBuffer(size, buffer); if (result == DEAD_OBJECT) { android_atomic_or(CBLK_INVALID, &cblk->flags); android_atomic_or(CBLK_INVALID, &cblk->mFlags); } } // If the track is invalid at this point, attempt to restore it. and try the // allocation one more time. if (cblk->flags & CBLK_INVALID) { if (cblk->mFlags & CBLK_INVALID) { result = restoreTrack_l("allocateTimedBuffer"); if (result == NO_ERROR) { Loading @@ -1290,8 +1290,8 @@ status_t TimedAudioTrack::queueTimedBuffer(const sp<IMemory>& buffer, audio_track_cblk_t* cblk = mCblk; // restart track if it was disabled by audioflinger due to previous underrun if (buffer->size() != 0 && status == NO_ERROR && (mState == STATE_ACTIVE) && (cblk->flags & CBLK_DISABLED)) { android_atomic_and(~CBLK_DISABLED, &cblk->flags); (mState == STATE_ACTIVE) && (cblk->mFlags & CBLK_DISABLED)) { android_atomic_and(~CBLK_DISABLED, &cblk->mFlags); ALOGW("queueTimedBuffer() track %p disabled, restarting", this); // FIXME ignoring status mAudioTrack->start(); Loading Loading @@ -1339,7 +1339,7 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) // Can only reference mCblk while locked int32_t flags = android_atomic_and( ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END), &mCblk->flags); ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END), &mCblk->mFlags); // Check for track invalidation if (flags & CBLK_INVALID) { Loading Loading @@ -1681,7 +1681,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) // the actual amount of audio frames played (e.g SoundPool) receives them. if (mSharedBuffer == 0) { // restart playback even if buffer is not completely filled. android_atomic_or(CBLK_FORCEREADY, &mCblk->flags); android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags); } } #endif Loading media/libmedia/AudioTrackShared.cpp +9 −9 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ namespace android { audio_track_cblk_t::audio_track_cblk_t() : mServer(0), frameCount_(0), mFutex(0), mMinimum(0), mVolumeLR(0x10001000), mSampleRate(0), mSendLevel(0), mName(0), flags(0) mVolumeLR(0x10001000), mSampleRate(0), mSendLevel(0), mName(0), mFlags(0) { memset(&u, 0, sizeof(u)); } Loading Loading @@ -99,7 +99,7 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques goto end; } for (;;) { int32_t flags = android_atomic_and(~CBLK_INTERRUPT, &cblk->flags); int32_t flags = android_atomic_and(~CBLK_INTERRUPT, &cblk->mFlags); // check for track invalidation by server, or server death detection if (flags & CBLK_INVALID) { ALOGV("Track invalidated"); Loading Loading @@ -293,7 +293,7 @@ void ClientProxy::releaseBuffer(Buffer* buffer) void ClientProxy::binderDied() { audio_track_cblk_t* cblk = mCblk; if (!(android_atomic_or(CBLK_INVALID, &cblk->flags) & CBLK_INVALID)) { if (!(android_atomic_or(CBLK_INVALID, &cblk->mFlags) & CBLK_INVALID)) { // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); Loading @@ -303,7 +303,7 @@ void ClientProxy::binderDied() void ClientProxy::interrupt() { audio_track_cblk_t* cblk = mCblk; if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->flags) & CBLK_INTERRUPT)) { if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) { (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } Loading @@ -324,11 +324,11 @@ void AudioTrackClientProxy::flush() } bool AudioTrackClientProxy::clearStreamEndDone() { return (android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->flags) & CBLK_STREAM_END_DONE) != 0; return (android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0; } bool AudioTrackClientProxy::getStreamEndDone() const { return (mCblk->flags & CBLK_STREAM_END_DONE) != 0; return (mCblk->mFlags & CBLK_STREAM_END_DONE) != 0; } status_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *requested) Loading @@ -354,7 +354,7 @@ status_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *request timeout = TIMEOUT_FINITE; } for (;;) { int32_t flags = android_atomic_and(~(CBLK_INTERRUPT|CBLK_STREAM_END_DONE), &cblk->flags); int32_t flags = android_atomic_and(~(CBLK_INTERRUPT|CBLK_STREAM_END_DONE), &cblk->mFlags); // check for track invalidation by server, or server death detection if (flags & CBLK_INVALID) { ALOGV("Track invalidated"); Loading Loading @@ -653,7 +653,7 @@ size_t AudioTrackServerProxy::framesReady() bool AudioTrackServerProxy::setStreamEndDone() { bool old = (android_atomic_or(CBLK_STREAM_END_DONE, &mCblk->flags) & CBLK_STREAM_END_DONE) != 0; (android_atomic_or(CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0; if (!old) { (void) __futex_syscall3(&mCblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); Loading Loading @@ -808,7 +808,7 @@ void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) cblk->mServer += stepCount; cblk->u.mStatic.mBufferPosition = newPosition; if (setFlags != 0) { (void) android_atomic_or(setFlags, &cblk->flags); (void) android_atomic_or(setFlags, &cblk->mFlags); // this would be a good place to wake a futex } Loading services/audioflinger/Threads.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -2783,7 +2783,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac } // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available android_atomic_or(CBLK_DISABLED, &track->mCblk->flags); android_atomic_or(CBLK_DISABLED, &track->mCblk->mFlags); // remove from active list, but state remains ACTIVE [confusing but true] isActive = false; break; Loading Loading @@ -3061,7 +3061,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // we missed desiredFrames whatever the actual number of frames missing was cblk->u.mStreaming.mUnderrunFrames += desiredFrames; // FIXME also wake futex so that underrun is noticed more quickly (void) android_atomic_or(CBLK_UNDERRUN, &cblk->flags); (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags); } // clear effect chain input buffer if an active track underruns to avoid sending // previous audio buffer again to effects Loading Loading @@ -3094,7 +3094,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac tracksToRemove->add(track); // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available android_atomic_or(CBLK_DISABLED, &cblk->flags); android_atomic_or(CBLK_DISABLED, &cblk->mFlags); // If one track is not ready, mark the mixer also not ready if: // - the mixer was ready during previous round OR // - no other track is ready Loading Loading
include/private/media/AudioTrackShared.h +2 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ namespace android { // ---------------------------------------------------------------------------- // for audio_track_cblk_t::mFlags #define CBLK_UNDERRUN 0x01 // set by server immediately on output underrun, cleared by client #define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger, // clear: track is ready when buffer full Loading Loading @@ -127,7 +128,7 @@ public: // read-only for client, server writes once at initialization and is then read-only uint8_t mName; // normal tracks: track name, fast tracks: track index volatile int32_t flags; volatile int32_t mFlags; // combinations of CBLK_* // Cache line boundary (32 bytes) Loading
media/libmedia/AudioRecord.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -300,7 +300,7 @@ status_t AudioRecord::start(AudioSystem::sync_event_t event, int triggerSession) mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); mNewPosition = mProxy->getPosition() + mUpdatePeriod; int32_t flags = android_atomic_acquire_load(&mCblk->flags); int32_t flags = android_atomic_acquire_load(&mCblk->mFlags); status_t status = NO_ERROR; if (!(flags & CBLK_INVALID)) { Loading Loading @@ -667,7 +667,7 @@ nsecs_t AudioRecord::processAudioBuffer(const sp<AudioRecordThread>& thread) mLock.lock(); // Can only reference mCblk while locked int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->flags); int32_t flags = android_atomic_and(~CBLK_OVERRUN, &mCblk->mFlags); // Check for track invalidation if (flags & CBLK_INVALID) { Loading
media/libmedia/AudioTrack.cpp +9 −9 Original line number Diff line number Diff line Loading @@ -389,7 +389,7 @@ status_t AudioTrack::start() mProxy->setEpoch(mProxy->getEpoch() - mProxy->getPosition()); } mNewPosition = mProxy->getPosition() + mUpdatePeriod; int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->flags); int32_t flags = android_atomic_and(~CBLK_DISABLED, &mCblk->mFlags); sp<AudioTrackThread> t = mAudioTrackThread; if (t != 0) { Loading Loading @@ -1182,7 +1182,7 @@ void AudioTrack::releaseBuffer(Buffer* audioBuffer) // restart track if it was disabled by audioflinger due to previous underrun if (mState == STATE_ACTIVE) { audio_track_cblk_t* cblk = mCblk; if (android_atomic_and(~CBLK_DISABLED, &cblk->flags) & CBLK_DISABLED) { if (android_atomic_and(~CBLK_DISABLED, &cblk->mFlags) & CBLK_DISABLED) { ALOGW("releaseBuffer() track %p name=%#x disabled due to previous underrun, restarting", this, cblk->mName); // FIXME ignoring status Loading Loading @@ -1261,16 +1261,16 @@ status_t TimedAudioTrack::allocateTimedBuffer(size_t size, sp<IMemory>* buffer) // fails indicating that the server is dead, flag the track as invalid so // we can attempt to restore in just a bit. audio_track_cblk_t* cblk = mCblk; if (!(cblk->flags & CBLK_INVALID)) { if (!(cblk->mFlags & CBLK_INVALID)) { result = mAudioTrack->allocateTimedBuffer(size, buffer); if (result == DEAD_OBJECT) { android_atomic_or(CBLK_INVALID, &cblk->flags); android_atomic_or(CBLK_INVALID, &cblk->mFlags); } } // If the track is invalid at this point, attempt to restore it. and try the // allocation one more time. if (cblk->flags & CBLK_INVALID) { if (cblk->mFlags & CBLK_INVALID) { result = restoreTrack_l("allocateTimedBuffer"); if (result == NO_ERROR) { Loading @@ -1290,8 +1290,8 @@ status_t TimedAudioTrack::queueTimedBuffer(const sp<IMemory>& buffer, audio_track_cblk_t* cblk = mCblk; // restart track if it was disabled by audioflinger due to previous underrun if (buffer->size() != 0 && status == NO_ERROR && (mState == STATE_ACTIVE) && (cblk->flags & CBLK_DISABLED)) { android_atomic_and(~CBLK_DISABLED, &cblk->flags); (mState == STATE_ACTIVE) && (cblk->mFlags & CBLK_DISABLED)) { android_atomic_and(~CBLK_DISABLED, &cblk->mFlags); ALOGW("queueTimedBuffer() track %p disabled, restarting", this); // FIXME ignoring status mAudioTrack->start(); Loading Loading @@ -1339,7 +1339,7 @@ nsecs_t AudioTrack::processAudioBuffer(const sp<AudioTrackThread>& thread) // Can only reference mCblk while locked int32_t flags = android_atomic_and( ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END), &mCblk->flags); ~(CBLK_UNDERRUN | CBLK_LOOP_CYCLE | CBLK_LOOP_FINAL | CBLK_BUFFER_END), &mCblk->mFlags); // Check for track invalidation if (flags & CBLK_INVALID) { Loading Loading @@ -1681,7 +1681,7 @@ status_t AudioTrack::restoreTrack_l(const char *from) // the actual amount of audio frames played (e.g SoundPool) receives them. if (mSharedBuffer == 0) { // restart playback even if buffer is not completely filled. android_atomic_or(CBLK_FORCEREADY, &mCblk->flags); android_atomic_or(CBLK_FORCEREADY, &mCblk->mFlags); } } #endif Loading
media/libmedia/AudioTrackShared.cpp +9 −9 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ namespace android { audio_track_cblk_t::audio_track_cblk_t() : mServer(0), frameCount_(0), mFutex(0), mMinimum(0), mVolumeLR(0x10001000), mSampleRate(0), mSendLevel(0), mName(0), flags(0) mVolumeLR(0x10001000), mSampleRate(0), mSendLevel(0), mName(0), mFlags(0) { memset(&u, 0, sizeof(u)); } Loading Loading @@ -99,7 +99,7 @@ status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *reques goto end; } for (;;) { int32_t flags = android_atomic_and(~CBLK_INTERRUPT, &cblk->flags); int32_t flags = android_atomic_and(~CBLK_INTERRUPT, &cblk->mFlags); // check for track invalidation by server, or server death detection if (flags & CBLK_INVALID) { ALOGV("Track invalidated"); Loading Loading @@ -293,7 +293,7 @@ void ClientProxy::releaseBuffer(Buffer* buffer) void ClientProxy::binderDied() { audio_track_cblk_t* cblk = mCblk; if (!(android_atomic_or(CBLK_INVALID, &cblk->flags) & CBLK_INVALID)) { if (!(android_atomic_or(CBLK_INVALID, &cblk->mFlags) & CBLK_INVALID)) { // it seems that a FUTEX_WAKE_PRIVATE will not wake a FUTEX_WAIT, even within same process (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); Loading @@ -303,7 +303,7 @@ void ClientProxy::binderDied() void ClientProxy::interrupt() { audio_track_cblk_t* cblk = mCblk; if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->flags) & CBLK_INTERRUPT)) { if (!(android_atomic_or(CBLK_INTERRUPT, &cblk->mFlags) & CBLK_INTERRUPT)) { (void) __futex_syscall3(&cblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); } Loading @@ -324,11 +324,11 @@ void AudioTrackClientProxy::flush() } bool AudioTrackClientProxy::clearStreamEndDone() { return (android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->flags) & CBLK_STREAM_END_DONE) != 0; return (android_atomic_and(~CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0; } bool AudioTrackClientProxy::getStreamEndDone() const { return (mCblk->flags & CBLK_STREAM_END_DONE) != 0; return (mCblk->mFlags & CBLK_STREAM_END_DONE) != 0; } status_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *requested) Loading @@ -354,7 +354,7 @@ status_t AudioTrackClientProxy::waitStreamEndDone(const struct timespec *request timeout = TIMEOUT_FINITE; } for (;;) { int32_t flags = android_atomic_and(~(CBLK_INTERRUPT|CBLK_STREAM_END_DONE), &cblk->flags); int32_t flags = android_atomic_and(~(CBLK_INTERRUPT|CBLK_STREAM_END_DONE), &cblk->mFlags); // check for track invalidation by server, or server death detection if (flags & CBLK_INVALID) { ALOGV("Track invalidated"); Loading Loading @@ -653,7 +653,7 @@ size_t AudioTrackServerProxy::framesReady() bool AudioTrackServerProxy::setStreamEndDone() { bool old = (android_atomic_or(CBLK_STREAM_END_DONE, &mCblk->flags) & CBLK_STREAM_END_DONE) != 0; (android_atomic_or(CBLK_STREAM_END_DONE, &mCblk->mFlags) & CBLK_STREAM_END_DONE) != 0; if (!old) { (void) __futex_syscall3(&mCblk->mFutex, mClientInServer ? FUTEX_WAKE_PRIVATE : FUTEX_WAKE, 1); Loading Loading @@ -808,7 +808,7 @@ void StaticAudioTrackServerProxy::releaseBuffer(Buffer* buffer) cblk->mServer += stepCount; cblk->u.mStatic.mBufferPosition = newPosition; if (setFlags != 0) { (void) android_atomic_or(setFlags, &cblk->flags); (void) android_atomic_or(setFlags, &cblk->mFlags); // this would be a good place to wake a futex } Loading
services/audioflinger/Threads.cpp +3 −3 Original line number Diff line number Diff line Loading @@ -2783,7 +2783,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac } // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available android_atomic_or(CBLK_DISABLED, &track->mCblk->flags); android_atomic_or(CBLK_DISABLED, &track->mCblk->mFlags); // remove from active list, but state remains ACTIVE [confusing but true] isActive = false; break; Loading Loading @@ -3061,7 +3061,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // we missed desiredFrames whatever the actual number of frames missing was cblk->u.mStreaming.mUnderrunFrames += desiredFrames; // FIXME also wake futex so that underrun is noticed more quickly (void) android_atomic_or(CBLK_UNDERRUN, &cblk->flags); (void) android_atomic_or(CBLK_UNDERRUN, &cblk->mFlags); } // clear effect chain input buffer if an active track underruns to avoid sending // previous audio buffer again to effects Loading Loading @@ -3094,7 +3094,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac tracksToRemove->add(track); // indicate to client process that the track was disabled because of underrun; // it will then automatically call start() when data is available android_atomic_or(CBLK_DISABLED, &cblk->flags); android_atomic_or(CBLK_DISABLED, &cblk->mFlags); // If one track is not ready, mark the mixer also not ready if: // - the mixer was ready during previous round OR // - no other track is ready Loading