From e3aa659e9cee7df5c12a80d285cc29ab3b2cbb39 Mon Sep 17 00:00:00 2001 From: Glenn Kasten Date: Tue, 4 Dec 2012 12:22:46 -0800 Subject: [PATCH] Start isolating control block accesses in a proxy The proxy object will eventually be the only code that understands the details of the control block. This should make it easier to change the control block in the future. Initial set of control block fields that are isolated: - sample rate - send level - volume Prepare for streaming/static separation by adding a union to the control block for the new fields. Fix bug in handling of max sample rate on a track. It was only checking at re-configuration, not at each mix. Simplify OutputTrack::obtainBuffer. Change-Id: I2249f9d04f73a911a922ad1d7f6197292c74cd92 --- include/media/AudioRecord.h | 3 + include/media/AudioTrack.h | 3 + include/private/media/AudioTrackShared.h | 228 +++++++++++++++++++++++++------ media/libmedia/AudioRecord.cpp | 47 ++++--- media/libmedia/AudioTrack.cpp | 109 +++++++++------ media/libmedia/AudioTrackShared.cpp | 2 +- services/audioflinger/AudioFlinger.h | 1 + services/audioflinger/PlaybackTracks.h | 3 +- services/audioflinger/RecordTracks.h | 2 - services/audioflinger/Threads.cpp | 21 +-- services/audioflinger/TrackBase.h | 9 +- services/audioflinger/Tracks.cpp | 97 ++++++------- 12 files changed, 355 insertions(+), 170 deletions(-) diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h index ae444c37d7..38c6548516 100644 --- a/include/media/AudioRecord.h +++ b/include/media/AudioRecord.h @@ -29,6 +29,7 @@ namespace android { class audio_track_cblk_t; +class AudioRecordClientProxy; // ---------------------------------------------------------------------------- @@ -374,6 +375,7 @@ private: uint32_t mUpdatePeriod; // in ms // constant after constructor or set() + uint32_t mSampleRate; size_t mFrameCount; audio_format_t mFormat; uint8_t mChannelCount; @@ -393,6 +395,7 @@ private: int mPreviousPriority; // before start() SchedPolicy mPreviousSchedulingGroup; + AudioRecordClientProxy* mProxy; }; }; // namespace android diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h index 6f85527369..9d07ed536f 100644 --- a/include/media/AudioTrack.h +++ b/include/media/AudioTrack.h @@ -36,6 +36,7 @@ namespace android { // ---------------------------------------------------------------------------- class audio_track_cblk_t; +class AudioTrackClientProxy; // ---------------------------------------------------------------------------- @@ -538,6 +539,7 @@ protected: float mVolume[2]; float mSendLevel; + uint32_t mSampleRate; size_t mFrameCount; // corresponds to current IAudioTrack size_t mReqFrameCount; // frame count to request the next time a new // IAudioTrack is needed @@ -596,6 +598,7 @@ protected: bool mIsTimed; int mPreviousPriority; // before start() SchedPolicy mPreviousSchedulingGroup; + AudioTrackClientProxy* mProxy; }; class TimedAudioTrack : public AudioTrack diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h index 48b6b218ca..41e20f809b 100644 --- a/include/private/media/AudioTrackShared.h +++ b/include/private/media/AudioTrackShared.h @@ -21,6 +21,7 @@ #include #include +#include namespace android { @@ -38,9 +39,26 @@ namespace android { #define CBLK_INVALID 0x04 // track buffer invalidated by AudioFlinger, need to re-create #define CBLK_DISABLED 0x08 // track disabled by AudioFlinger due to underrun, need to re-start +struct AudioTrackSharedStreaming { + // similar to NBAIO MonoPipe + volatile int32_t mFront; + volatile int32_t mRear; +}; + +// future +struct AudioTrackSharedStatic { + int mReserved; +}; + +// ---------------------------------------------------------------------------- + // Important: do not add any virtual methods, including ~ struct audio_track_cblk_t { + friend class Proxy; + friend class AudioTrackClientProxy; + friend class AudioRecordClientProxy; + friend class ServerProxy; // The data members are grouped so that members accessed frequently and in the same context // are in the same line of data cache. @@ -72,12 +90,13 @@ struct audio_track_cblk_t // For AudioTrack only, not used by AudioRecord. private: uint32_t mVolumeLR; -public: - uint32_t sampleRate; + uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz + // or 0 == default. Write-only client, read-only server. uint8_t mPad2; // unused +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 @@ -94,65 +113,184 @@ public: // Cache line boundary (32 bytes) +#if 0 + union { + AudioTrackSharedStreaming mStreaming; + AudioTrackSharedStatic mStatic; + int mAlign[8]; + } u; + + // Cache line boundary (32 bytes) +#endif + // Since the control block is always located in shared memory, this constructor // is only used for placement new(). It is never used for regular new() or stack. audio_track_cblk_t(); - // called by client only, where client includes regular - // AudioTrack and AudioFlinger::PlaybackThread::OutputTrack - uint32_t stepUserIn(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, false); } - uint32_t stepUserOut(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, true); } - - bool stepServer(size_t stepCount, size_t frameCount, bool isOut); - +private: // if there is a shared buffer, "buffers" is the value of pointer() for the shared // buffer, otherwise "buffers" points immediately after the control block - void* buffer(void *buffers, uint32_t frameSize, uint32_t offset) const; - - uint32_t framesAvailableIn(size_t frameCount) - { return framesAvailable(frameCount, false); } - uint32_t framesAvailableOut(size_t frameCount) - { return framesAvailable(frameCount, true); } - uint32_t framesAvailableIn_l(size_t frameCount) - { return framesAvailable_l(frameCount, false); } - uint32_t framesAvailableOut_l(size_t frameCount) - { return framesAvailable_l(frameCount, true); } - uint32_t framesReadyIn() { return framesReady(false); } - uint32_t framesReadyOut() { return framesReady(true); } + void* buffer(void *buffers, uint32_t frameSize, size_t offset) const; bool tryLock(); - // No barriers on the following operations, so the ordering of loads/stores - // with respect to other parameters is UNPREDICTABLE. That's considered safe. - - // for AudioTrack client only, caller must limit to 0.0 <= sendLevel <= 1.0 - void setSendLevel(float sendLevel) { - mSendLevel = uint16_t(sendLevel * 0x1000); - } - - // for AudioFlinger only; the return value must be validated by the caller - uint16_t getSendLevel_U4_12() const { - return mSendLevel; - } - - // for AudioTrack client only, caller must limit to 0 <= volumeLR <= 0x10001000 - void setVolumeLR(uint32_t volumeLR) { - mVolumeLR = volumeLR; - } - - // for AudioFlinger only; the return value must be validated by the caller - uint32_t getVolumeLR() const { - return mVolumeLR; - } - -private: // isOut == true means AudioTrack, isOut == false means AudioRecord + bool stepServer(size_t stepCount, size_t frameCount, bool isOut); uint32_t stepUser(size_t stepCount, size_t frameCount, bool isOut); uint32_t framesAvailable(size_t frameCount, bool isOut); uint32_t framesAvailable_l(size_t frameCount, bool isOut); uint32_t framesReady(bool isOut); }; +// ---------------------------------------------------------------------------- + +// Proxy for shared memory control block, to isolate callers from needing to know the details. +// There is exactly one ClientProxy and one ServerProxy per shared memory control block. +// The proxies are located in normal memory, and are not multi-thread safe within a given side. +class Proxy { +protected: + Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) + : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { } + virtual ~Proxy() { } + +public: + void* buffer(size_t offset) const { + return mCblk->buffer(mBuffers, mFrameSize, offset); + } + +protected: + // These refer to shared memory, and are virtual addresses with respect to the current process. + // They may have different virtual addresses within the other process. + audio_track_cblk_t* const mCblk; // the control block + void* const mBuffers; // starting address of buffers + + const size_t mFrameCount; // not necessarily a power of 2 + const size_t mFrameSize; // in bytes +#if 0 + const size_t mFrameCountP2; // mFrameCount rounded to power of 2, streaming mode +#endif + +}; + +// ---------------------------------------------------------------------------- + +// Proxy seen by AudioTrack client and AudioRecord client +class ClientProxy : public Proxy { +protected: + ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) + : Proxy(cblk, buffers, frameCount, frameSize) { } + virtual ~ClientProxy() { } +}; + +// ---------------------------------------------------------------------------- + +// Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack +class AudioTrackClientProxy : public ClientProxy { +public: + AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) + : ClientProxy(cblk, buffers, frameCount, frameSize) { } + virtual ~AudioTrackClientProxy() { } + + // No barriers on the following operations, so the ordering of loads/stores + // with respect to other parameters is UNPREDICTABLE. That's considered safe. + + // caller must limit to 0.0 <= sendLevel <= 1.0 + void setSendLevel(float sendLevel) { + mCblk->mSendLevel = uint16_t(sendLevel * 0x1000); + } + + // caller must limit to 0 <= volumeLR <= 0x10001000 + void setVolumeLR(uint32_t volumeLR) { + mCblk->mVolumeLR = volumeLR; + } + + void setSampleRate(uint32_t sampleRate) { + mCblk->mSampleRate = sampleRate; + } + + // called by: + // PlaybackThread::OutputTrack::write + // AudioTrack::createTrack_l + // AudioTrack::releaseBuffer + // AudioTrack::reload + // AudioTrack::restoreTrack_l (2 places) + size_t stepUser(size_t stepCount) { + return mCblk->stepUser(stepCount, mFrameCount, true /*isOut*/); + } + + // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer + size_t framesAvailable() { + return mCblk->framesAvailable(mFrameCount, true /*isOut*/); + } + + // called by AudioTrack::obtainBuffer and PlaybackThread::OutputTrack::obtainBuffer + // FIXME remove this API since it assumes a lock that should be invisible to caller + size_t framesAvailable_l() { + return mCblk->framesAvailable_l(mFrameCount, true /*isOut*/); + } + +}; + +// ---------------------------------------------------------------------------- + +// Proxy used by AudioRecord client +class AudioRecordClientProxy : public ClientProxy { +public: + AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize) + : ClientProxy(cblk, buffers, frameCount, frameSize) { } + ~AudioRecordClientProxy() { } + + // called by AudioRecord::releaseBuffer + size_t stepUser(size_t stepCount) { + return mCblk->stepUser(stepCount, mFrameCount, false /*isOut*/); + } + + // called by AudioRecord::processBuffer + size_t framesAvailable() { + return mCblk->framesAvailable(mFrameCount, false /*isOut*/); + } + + // called by AudioRecord::obtainBuffer + size_t framesReady() { + return mCblk->framesReady(false /*isOut*/); + } + +}; + +// ---------------------------------------------------------------------------- + +// Proxy used by AudioFlinger server +class ServerProxy : public Proxy { +public: + ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut) + : Proxy(cblk, buffers, frameCount, frameSize), mIsOut(isOut) { } + virtual ~ServerProxy() { } + + // for AudioTrack and AudioRecord + bool step(size_t stepCount) { return mCblk->stepServer(stepCount, mFrameCount, mIsOut); } + + // return value of these methods must be validated by the caller + uint32_t getSampleRate() const { return mCblk->mSampleRate; } + uint16_t getSendLevel_U4_12() const { return mCblk->mSendLevel; } + uint32_t getVolumeLR() const { return mCblk->mVolumeLR; } + + // for AudioTrack only + size_t framesReady() { + ALOG_ASSERT(mIsOut); + return mCblk->framesReady(true); + } + + // for AudioRecord only, called by RecordThread::RecordTrack::getNextBuffer + // FIXME remove this API since it assumes a lock that should be invisible to caller + size_t framesAvailableIn_l() { + ALOG_ASSERT(!mIsOut); + return mCblk->framesAvailable_l(mFrameCount, false); + } + +private: + const bool mIsOut; // true for AudioTrack, false for AudioRecord + +}; // ---------------------------------------------------------------------------- diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp index c2ef68c397..8eb1656e45 100644 --- a/media/libmedia/AudioRecord.cpp +++ b/media/libmedia/AudioRecord.cpp @@ -75,7 +75,8 @@ status_t AudioRecord::getMinFrameCount( AudioRecord::AudioRecord() : mStatus(NO_INIT), mSessionId(0), - mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT), + mProxy(NULL) { } @@ -90,7 +91,9 @@ AudioRecord::AudioRecord( int notificationFrames, int sessionId) : mStatus(NO_INIT), mSessionId(0), - mPreviousPriority(ANDROID_PRIORITY_NORMAL), mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousPriority(ANDROID_PRIORITY_NORMAL), + mPreviousSchedulingGroup(SP_DEFAULT), + mProxy(NULL) { mStatus = set(inputSource, sampleRate, format, channelMask, frameCount, cbf, user, notificationFrames, sessionId); @@ -112,6 +115,7 @@ AudioRecord::~AudioRecord() IPCThreadState::self()->flushCommands(); AudioSystem::releaseAudioSessionId(mSessionId); } + delete mProxy; } status_t AudioRecord::set( @@ -149,6 +153,8 @@ status_t AudioRecord::set( if (sampleRate == 0) { sampleRate = DEFAULT_SAMPLE_RATE; } + mSampleRate = sampleRate; + // these below should probably come from the audioFlinger too... if (format == AUDIO_FORMAT_DEFAULT) { format = AUDIO_FORMAT_PCM_16_BIT; @@ -166,6 +172,12 @@ status_t AudioRecord::set( uint32_t channelCount = popcount(channelMask); mChannelCount = channelCount; + if (audio_is_linear_pcm(mFormat)) { + mFrameSize = channelCount * audio_bytes_per_sample(format); + } else { + mFrameSize = sizeof(uint8_t); + } + if (sessionId == 0 ) { mSessionId = AudioSystem::newAudioSessionId(); } else { @@ -218,12 +230,6 @@ status_t AudioRecord::set( // Update buffer size in case it has been limited by AudioFlinger during track creation mFrameCount = mCblk->frameCount_; - if (audio_is_linear_pcm(mFormat)) { - mFrameSize = channelCount * audio_bytes_per_sample(format); - } else { - mFrameSize = sizeof(uint8_t); - } - mActive = false; mCbf = cbf; mNotificationFrames = notificationFrames; @@ -360,7 +366,7 @@ bool AudioRecord::stopped() const uint32_t AudioRecord::getSampleRate() const { - return mCblk->sampleRate; + return mSampleRate; } status_t AudioRecord::setMarkerPosition(uint32_t marker) @@ -473,11 +479,18 @@ status_t AudioRecord::openRecord_l( mBuffers = (char*)cblk + sizeof(audio_track_cblk_t); cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; cblk->waitTimeMs = 0; + + // update proxy + delete mProxy; + mProxy = new AudioRecordClientProxy(cblk, mBuffers, frameCount, mFrameSize); + return NO_ERROR; } status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { + ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL); + AutoMutex lock(mLock); bool active; status_t result = NO_ERROR; @@ -488,7 +501,7 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) audioBuffer->frameCount = 0; audioBuffer->size = 0; - uint32_t framesReady = cblk->framesReadyIn(); + size_t framesReady = mProxy->framesReady(); if (framesReady == 0) { cblk->lock.lock(); @@ -551,7 +564,7 @@ create_new_record: } // read the server count again start_loop_here: - framesReady = cblk->framesReadyIn(); + framesReady = mProxy->framesReady(); } cblk->lock.unlock(); } @@ -573,15 +586,17 @@ create_new_record: audioBuffer->frameCount = framesReq; audioBuffer->size = framesReq * mFrameSize; - audioBuffer->raw = cblk->buffer(mBuffers, mFrameSize, u); + audioBuffer->raw = mProxy->buffer(u); active = mActive; return active ? status_t(NO_ERROR) : status_t(STOPPED); } void AudioRecord::releaseBuffer(Buffer* audioBuffer) { + ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL); + AutoMutex lock(mLock); - mCblk->stepUserIn(audioBuffer->frameCount, mFrameCount); + (void) mProxy->stepUser(audioBuffer->frameCount); } audio_io_handle_t AudioRecord::getInput() const @@ -594,7 +609,7 @@ audio_io_handle_t AudioRecord::getInput() const audio_io_handle_t AudioRecord::getInput_l() { mInput = AudioSystem::getInput(mInputSource, - mCblk->sampleRate, + mSampleRate, mFormat, mChannelMask, mSessionId); @@ -745,7 +760,7 @@ bool AudioRecord::processAudioBuffer(const sp& thread) // Manage overrun callback - if (active && (cblk->framesAvailableIn(mFrameCount) == 0)) { + if (active && (mProxy->framesAvailable() == 0)) { // The value of active is stale, but we are almost sure to be active here because // otherwise we would have exited when obtainBuffer returned STOPPED earlier. ALOGV("Overrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); @@ -781,7 +796,7 @@ status_t AudioRecord::restoreRecord_l(audio_track_cblk_t*& refCblk) // if the new IAudioRecord is created, openRecord_l() will modify the // following member variables: mAudioRecord, mCblkMemory and mCblk. // It will also delete the strong references on previous IAudioRecord and IMemory - result = openRecord_l(cblk->sampleRate, mFormat, mFrameCount, getInput_l()); + result = openRecord_l(mSampleRate, mFormat, mFrameCount, getInput_l()); if (result == NO_ERROR) { newCblk = mCblk; // callback thread or sync event hasn't changed diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index 1d87ff8303..86a5579384 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -97,7 +97,8 @@ AudioTrack::AudioTrack() : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mProxy(NULL) { } @@ -115,7 +116,8 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mProxy(NULL) { mStatus = set(streamType, sampleRate, format, channelMask, frameCount, flags, cbf, user, notificationFrames, @@ -136,7 +138,8 @@ AudioTrack::AudioTrack( : mStatus(NO_INIT), mIsTimed(false), mPreviousPriority(ANDROID_PRIORITY_NORMAL), - mPreviousSchedulingGroup(SP_DEFAULT) + mPreviousSchedulingGroup(SP_DEFAULT), + mProxy(NULL) { if (sharedBuffer == 0) { ALOGE("sharedBuffer must be non-0"); @@ -166,6 +169,7 @@ AudioTrack::~AudioTrack() IPCThreadState::self()->flushCommands(); AudioSystem::releaseAudioSessionId(mSessionId); } + delete mProxy; } status_t AudioTrack::set( @@ -212,6 +216,7 @@ status_t AudioTrack::set( } sampleRate = afSampleRate; } + mSampleRate = sampleRate; // these below should probably come from the audioFlinger too... if (format == AUDIO_FORMAT_DEFAULT) { @@ -252,6 +257,14 @@ status_t AudioTrack::set( uint32_t channelCount = popcount(channelMask); mChannelCount = channelCount; + if (audio_is_linear_pcm(format)) { + mFrameSize = channelCount * audio_bytes_per_sample(format); + mFrameSizeAF = channelCount * sizeof(int16_t); + } else { + mFrameSize = sizeof(uint8_t); + mFrameSizeAF = sizeof(uint8_t); + } + audio_io_handle_t output = AudioSystem::getOutput( streamType, sampleRate, format, channelMask, @@ -300,14 +313,6 @@ status_t AudioTrack::set( mStreamType = streamType; mFormat = format; - if (audio_is_linear_pcm(format)) { - mFrameSize = channelCount * audio_bytes_per_sample(format); - mFrameSizeAF = channelCount * sizeof(int16_t); - } else { - mFrameSize = sizeof(uint8_t); - mFrameSizeAF = sizeof(uint8_t); - } - mSharedBuffer = sharedBuffer; mActive = false; mUserData = user; @@ -460,6 +465,11 @@ void AudioTrack::pause() status_t AudioTrack::setVolume(float left, float right) { + if (mStatus != NO_ERROR) { + return mStatus; + } + ALOG_ASSERT(mProxy != NULL); + if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) { return BAD_VALUE; } @@ -468,7 +478,7 @@ status_t AudioTrack::setVolume(float left, float right) mVolume[LEFT] = left; mVolume[RIGHT] = right; - mCblk->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); + mProxy->setVolumeLR((uint32_t(uint16_t(right * 0x1000)) << 16) | uint16_t(left * 0x1000)); return NO_ERROR; } @@ -481,14 +491,19 @@ status_t AudioTrack::setVolume(float volume) status_t AudioTrack::setAuxEffectSendLevel(float level) { ALOGV("setAuxEffectSendLevel(%f)", level); + + if (mStatus != NO_ERROR) { + return mStatus; + } + ALOG_ASSERT(mProxy != NULL); + if (level < 0.0f || level > 1.0f) { return BAD_VALUE; } AutoMutex lock(mLock); mSendLevel = level; - - mCblk->setSendLevel(level); + mProxy->setSendLevel(level); return NO_ERROR; } @@ -517,7 +532,9 @@ status_t AudioTrack::setSampleRate(uint32_t rate) } AutoMutex lock(mLock); - mCblk->sampleRate = rate; + mSampleRate = rate; + mProxy->setSampleRate(rate); + return NO_ERROR; } @@ -528,7 +545,7 @@ uint32_t AudioTrack::getSampleRate() const } AutoMutex lock(mLock); - return mCblk->sampleRate; + return mSampleRate; } status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount) @@ -665,6 +682,11 @@ status_t AudioTrack::getPosition(uint32_t *position) status_t AudioTrack::reload() { + if (mStatus != NO_ERROR) { + return mStatus; + } + ALOG_ASSERT(mProxy != NULL); + if (mSharedBuffer == 0 || mIsTimed) { return INVALID_OPERATION; } @@ -677,8 +699,7 @@ status_t AudioTrack::reload() flush_l(); - audio_track_cblk_t* cblk = mCblk; - cblk->stepUserOut(mFrameCount, mFrameCount); + (void) mProxy->stepUser(mFrameCount); return NO_ERROR; } @@ -693,7 +714,7 @@ audio_io_handle_t AudioTrack::getOutput() audio_io_handle_t AudioTrack::getOutput_l() { return AudioSystem::getOutput(mStreamType, - mCblk->sampleRate, mFormat, mChannelMask, mFlags); + mSampleRate, mFormat, mChannelMask, mFlags); } status_t AudioTrack::attachAuxEffect(int effectId) @@ -890,13 +911,8 @@ status_t AudioTrack::createTrack_l( mBuffers = (char*)cblk + sizeof(audio_track_cblk_t); } else { mBuffers = sharedBuffer->pointer(); - // Force buffer full condition as data is already present in shared memory - cblk->stepUserOut(frameCount, frameCount); } - cblk->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | - uint16_t(mVolume[LEFT] * 0x1000)); - cblk->setSendLevel(mSendLevel); mAudioTrack->attachAuxEffect(mAuxEffectId); cblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS; cblk->waitTimeMs = 0; @@ -909,11 +925,26 @@ status_t AudioTrack::createTrack_l( if (frameCount > mReqFrameCount) { mReqFrameCount = frameCount; } + + // update proxy + delete mProxy; + mProxy = new AudioTrackClientProxy(cblk, mBuffers, frameCount, mFrameSizeAF); + mProxy->setVolumeLR((uint32_t(uint16_t(mVolume[RIGHT] * 0x1000)) << 16) | + uint16_t(mVolume[LEFT] * 0x1000)); + mProxy->setSendLevel(mSendLevel); + mProxy->setSampleRate(mSampleRate); + if (sharedBuffer != 0) { + // Force buffer full condition as data is already present in shared memory + mProxy->stepUser(frameCount); + } + return NO_ERROR; } status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) { + ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL); + AutoMutex lock(mLock); bool active; status_t result = NO_ERROR; @@ -924,7 +955,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount) audioBuffer->frameCount = 0; audioBuffer->size = 0; - uint32_t framesAvail = cblk->framesAvailableOut(mFrameCount); + size_t framesAvail = mProxy->framesAvailable(); cblk->lock.lock(); if (cblk->flags & CBLK_INVALID) { @@ -1000,7 +1031,7 @@ create_new_track: } // read the server count again start_loop_here: - framesAvail = cblk->framesAvailableOut_l(mFrameCount); + framesAvail = mProxy->framesAvailable_l(); } cblk->lock.unlock(); } @@ -1020,16 +1051,18 @@ create_new_track: audioBuffer->frameCount = framesReq; audioBuffer->size = framesReq * mFrameSizeAF; - audioBuffer->raw = cblk->buffer(mBuffers, mFrameSizeAF, u); + audioBuffer->raw = mProxy->buffer(u); active = mActive; return active ? status_t(NO_ERROR) : status_t(STOPPED); } void AudioTrack::releaseBuffer(Buffer* audioBuffer) { + ALOG_ASSERT(mStatus == NO_ERROR && mProxy != NULL); + AutoMutex lock(mLock); audio_track_cblk_t* cblk = mCblk; - cblk->stepUserOut(audioBuffer->frameCount, mFrameCount); + (void) mProxy->stepUser(audioBuffer->frameCount); if (audioBuffer->frameCount > 0) { // restart track if it was disabled by audioflinger due to previous underrun if (mActive && (cblk->flags & CBLK_DISABLED)) { @@ -1199,7 +1232,7 @@ bool AudioTrack::processAudioBuffer(const sp& thread) // so all cblk references might still refer to old shared memory, but that should be benign // Manage underrun callback - if (active && (cblk->framesAvailableOut(mFrameCount) == mFrameCount)) { + if (active && (mProxy->framesAvailable() == mFrameCount)) { ALOGV("Underrun user: %x, server: %x, flags %04x", cblk->user, cblk->server, cblk->flags); if (!(android_atomic_or(CBLK_UNDERRUN, &cblk->flags) & CBLK_UNDERRUN)) { mCbf(EVENT_UNDERRUN, mUserData, 0); @@ -1346,7 +1379,7 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& refCblk, bool fromStart // following member variables: mAudioTrack, mCblkMemory and mCblk. // It will also delete the strong references on previous IAudioTrack and IMemory result = createTrack_l(mStreamType, - cblk->sampleRate, + mSampleRate, mFormat, mReqFrameCount, // so that frame count never goes down mFlags, @@ -1365,12 +1398,12 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& refCblk, bool fromStart // restore loop: this is not guaranteed to succeed if new frame count is not // compatible with loop length setLoop_l(cblk->loopStart, cblk->loopEnd, cblk->loopCount); + size_t frames = 0; if (!fromStart) { newCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS; // Make sure that a client relying on callback events indicating underrun or // the actual amount of audio frames played (e.g SoundPool) receives them. if (mSharedBuffer == 0) { - uint32_t frames = 0; if (user > server) { frames = ((user - server) > mFrameCount) ? mFrameCount : (user - server); @@ -1378,13 +1411,15 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& refCblk, bool fromStart } // restart playback even if buffer is not completely filled. android_atomic_or(CBLK_FORCEREADY, &newCblk->flags); - // stepUser() clears CBLK_UNDERRUN flag enabling underrun callbacks to - // the client - newCblk->stepUserOut(frames, mFrameCount); } } if (mSharedBuffer != 0) { - newCblk->stepUserOut(mFrameCount, mFrameCount); + frames = mFrameCount; + } + if (frames > 0) { + // stepUser() clears CBLK_UNDERRUN flag enabling underrun callbacks to + // the client + mProxy->stepUser(frames); } if (mActive) { result = mAudioTrack->start(); @@ -1416,7 +1451,6 @@ status_t AudioTrack::dump(int fd, const Vector& args) const char buffer[SIZE]; String8 result; - audio_track_cblk_t* cblk = mCblk; result.append(" AudioTrack::dump\n"); snprintf(buffer, 255, " stream type(%d), left - right volume(%f, %f)\n", mStreamType, mVolume[0], mVolume[1]); @@ -1424,8 +1458,7 @@ status_t AudioTrack::dump(int fd, const Vector& args) const snprintf(buffer, 255, " format(%d), channel count(%d), frame count(%d)\n", mFormat, mChannelCount, mFrameCount); result.append(buffer); - snprintf(buffer, 255, " sample rate(%u), status(%d)\n", - (cblk == 0) ? 0 : cblk->sampleRate, mStatus); + snprintf(buffer, 255, " sample rate(%u), status(%d)\n", mSampleRate, mStatus); result.append(buffer); snprintf(buffer, 255, " active(%d), latency (%d)\n", mActive, mLatency); result.append(buffer); diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp index bee13c8c89..13d47c9d1c 100644 --- a/media/libmedia/AudioTrackShared.cpp +++ b/media/libmedia/AudioTrackShared.cpp @@ -26,7 +26,7 @@ audio_track_cblk_t::audio_track_cblk_t() : lock(Mutex::SHARED), cv(Condition::SHARED), user(0), server(0), userBase(0), serverBase(0), frameCount_(0), loopStart(UINT_MAX), loopEnd(UINT_MAX), loopCount(0), mVolumeLR(0x10001000), - mSendLevel(0), flags(0) + mSampleRate(0), mSendLevel(0), flags(0) { } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 6d3f0a10d6..64a987188a 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -61,6 +61,7 @@ class AudioMixer; class AudioBuffer; class AudioResampler; class FastMixer; +class ServerProxy; // ---------------------------------------------------------------------------- diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h index aaa5333d45..adec93821f 100644 --- a/services/audioflinger/PlaybackTracks.h +++ b/services/audioflinger/PlaybackTracks.h @@ -107,7 +107,6 @@ public: bool isInvalid() const { return mIsInvalid; } virtual bool isTimedTrack() const { return false; } bool isFastTrack() const { return (mFlags & IAudioFlinger::TRACK_FAST) != 0; } - virtual bool isOut() const; protected: @@ -277,5 +276,5 @@ private: AudioBufferProvider::Buffer mOutBuffer; bool mActive; DuplicatingThread* const mSourceThread; // for waitTimeMs() in write() - void* mBuffers; // starting address of buffers in plain memory + AudioTrackClientProxy* mClientProxy; }; // end of OutputTrack diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h index fe681d73d5..6c0d1d3848 100644 --- a/services/audioflinger/RecordTracks.h +++ b/services/audioflinger/RecordTracks.h @@ -45,8 +45,6 @@ public: static void appendDumpHeader(String8& result); void dump(char* buffer, size_t size); - virtual bool isOut() const; - private: friend class AudioFlinger; // for mState diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp index d2b2931449..82acd3a782 100644 --- a/services/audioflinger/Threads.cpp +++ b/services/audioflinger/Threads.cpp @@ -2643,7 +2643,8 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // read original volumes with volume control float typeVolume = mStreamTypes[track->streamType()].volume; float v = masterVolume * typeVolume; - uint32_t vlr = cblk->getVolumeLR(); + ServerProxy *proxy = track->mServerProxy; + uint32_t vlr = proxy->getVolumeLR(); vl = vlr & 0xFFFF; vr = vlr >> 16; // track volumes come from shared memory, so can't be trusted and must be clamped @@ -2661,7 +2662,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac // assuming master volume and stream type volume each go up to 1.0, // vl and vr are now in 8.24 format - uint16_t sendLevel = cblk->getSendLevel_U4_12(); + uint16_t sendLevel = proxy->getSendLevel_U4_12(); // send level comes from shared memory and so may be corrupt if (sendLevel > MAX_GAIN_INT) { ALOGV("Track send level out of range: %04X", sendLevel); @@ -2713,11 +2714,19 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac name, AudioMixer::TRACK, AudioMixer::CHANNEL_MASK, (void *)track->channelMask()); + // limit track sample rate to 2 x output sample rate, which changes at re-configuration + uint32_t maxSampleRate = mSampleRate * 2; + uint32_t reqSampleRate = track->mServerProxy->getSampleRate(); + if (reqSampleRate == 0) { + reqSampleRate = mSampleRate; + } else if (reqSampleRate > maxSampleRate) { + reqSampleRate = maxSampleRate; + } mAudioMixer->setParameter( name, AudioMixer::RESAMPLE, AudioMixer::SAMPLE_RATE, - (void *)(cblk->sampleRate)); + (void *)reqSampleRate); mAudioMixer->setParameter( name, AudioMixer::TRACK, @@ -2990,10 +2999,6 @@ bool AudioFlinger::MixerThread::checkForNewParameters_l() break; } mTracks[i]->mName = name; - // limit track sample rate to 2 x new output sample rate - if (mTracks[i]->mCblk->sampleRate > 2 * sampleRate()) { - mTracks[i]->mCblk->sampleRate = 2 * sampleRate(); - } } sendIoConfigEvent_l(AudioSystem::OUTPUT_CONFIG_CHANGED); } @@ -3142,7 +3147,7 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::DirectOutputThread::prep } else { float typeVolume = mStreamTypes[track->streamType()].volume; float v = mMasterVolume * typeVolume; - uint32_t vlr = cblk->getVolumeLR(); + uint32_t vlr = track->mServerProxy->getVolumeLR(); float v_clamped = v * (vlr & 0xFFFF); if (v_clamped > MAX_GAIN) { v_clamped = MAX_GAIN; diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h index 17de49bd94..e0bd97a04b 100644 --- a/services/audioflinger/TrackBase.h +++ b/services/audioflinger/TrackBase.h @@ -44,7 +44,8 @@ public: audio_channel_mask_t channelMask, size_t frameCount, const sp& sharedBuffer, - int sessionId); + int sessionId, + bool isOut); virtual ~TrackBase(); virtual status_t start(AudioSystem::sync_event_t event, @@ -108,7 +109,8 @@ protected: bool step(); // mStepCount is an implicit input void reset(); - virtual bool isOut() const = 0; // true for Track and TimedTrack, false for RecordTrack, + bool isOut() const { return mIsOut; } + // true for Track and TimedTrack, false for RecordTrack, // this could be a track type if needed later const wp mThread; @@ -116,6 +118,7 @@ protected: sp mCblkMemory; audio_track_cblk_t* mCblk; void* mBuffer; // start of track buffer, typically in shared memory + // except for OutputTrack when it is in local memory void* mBufferEnd; // &mBuffer[mFrameCount * frameSize], where frameSize // is based on mChannelCount and 16-bit samples uint32_t mStepCount; // saves AudioBufferProvider::Buffer::frameCount as of @@ -136,4 +139,6 @@ protected: bool mStepServerFailed; const int mSessionId; Vector < sp >mSyncEvents; + const bool mIsOut; + ServerProxy* mServerProxy; }; diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp index 9b611d2a9f..c5f0ed7559 100644 --- a/services/audioflinger/Tracks.cpp +++ b/services/audioflinger/Tracks.cpp @@ -62,7 +62,8 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( audio_channel_mask_t channelMask, size_t frameCount, const sp& sharedBuffer, - int sessionId) + int sessionId, + bool isOut) : RefBase(), mThread(thread), mClient(client), @@ -79,7 +80,9 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)), mFrameCount(frameCount), mStepServerFailed(false), - mSessionId(sessionId) + mSessionId(sessionId), + mIsOut(isOut), + mServerProxy(NULL) { // client == 0 implies sharedBuffer == 0 ALOG_ASSERT(!(client == 0 && sharedBuffer != 0)); @@ -105,7 +108,8 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( return; } } else { - mCblk = (audio_track_cblk_t *)(new uint8_t[size]); + // this syntax avoids calling the audio_track_cblk_t constructor twice + mCblk = (audio_track_cblk_t *) new uint8_t[size]; // assume mCblk != NULL } @@ -114,7 +118,6 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( new(mCblk) audio_track_cblk_t(); // clear all buffers mCblk->frameCount_ = frameCount; - mCblk->sampleRate = sampleRate; // uncomment the following lines to quickly test 32-bit wraparound // mCblk->user = 0xffff0000; // mCblk->server = 0xffff0000; @@ -130,11 +133,14 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase( mBuffer = sharedBuffer->pointer(); } mBufferEnd = (uint8_t *)mBuffer + bufferSize; + mServerProxy = new ServerProxy(mCblk, mBuffer, frameCount, mFrameSize, isOut); } } AudioFlinger::ThreadBase::TrackBase::~TrackBase() { + // delete the proxy before deleting the shared memory it refers to, to avoid dangling reference + delete mServerProxy; if (mCblk != NULL) { if (mClient == 0) { delete mCblk; @@ -166,10 +172,7 @@ void AudioFlinger::ThreadBase::TrackBase::releaseBuffer(AudioBufferProvider::Buf } bool AudioFlinger::ThreadBase::TrackBase::step() { - bool result; - audio_track_cblk_t* cblk = this->cblk(); - - result = cblk->stepServer(mStepCount, mFrameCount, isOut()); + bool result = mServerProxy->step(mStepCount); if (!result) { ALOGV("stepServer failed acquiring cblk mutex"); mStepServerFailed = true; @@ -189,7 +192,7 @@ void AudioFlinger::ThreadBase::TrackBase::reset() { } uint32_t AudioFlinger::ThreadBase::TrackBase::sampleRate() const { - return mCblk->sampleRate; + return mServerProxy->getSampleRate(); } void* AudioFlinger::ThreadBase::TrackBase::getBuffer(uint32_t offset, uint32_t frames) const { @@ -310,7 +313,7 @@ AudioFlinger::PlaybackThread::Track::Track( int sessionId, IAudioFlinger::track_flags_t flags) : TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer, - sessionId), + sessionId, true /*isOut*/), mFillingUpStatus(FS_INVALID), // mRetryCount initialized later when needed mSharedBuffer(sharedBuffer), @@ -399,7 +402,7 @@ void AudioFlinger::PlaybackThread::Track::destroy() void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) { - uint32_t vlr = mCblk->getVolumeLR(); + uint32_t vlr = mServerProxy->getVolumeLR(); if (isFastTrack()) { sprintf(buffer, " F %2d", mFastIndex); } else { @@ -468,7 +471,7 @@ void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size) mFrameCount, stateChar, mFillingUpStatus, - mCblk->sampleRate, + mServerProxy->getSampleRate(), 20.0 * log10((vlr & 0xFFFF) / 4096.0), 20.0 * log10((vlr >> 16) / 4096.0), mCblk->server, @@ -503,7 +506,7 @@ status_t AudioFlinger::PlaybackThread::Track::getNextBuffer( } // FIXME Same as above - framesReady = cblk->framesReadyOut(); + framesReady = mServerProxy->framesReady(); if (CC_LIKELY(framesReady)) { uint32_t s = cblk->server; @@ -538,7 +541,7 @@ getNextBuffer_exit: // the tryLock() could block for up to 1 ms, and a sequence of these could delay fast mixer. // FIXME Replace AudioTrackShared control block implementation by a non-blocking FIFO queue. size_t AudioFlinger::PlaybackThread::Track::framesReady() const { - return mCblk->framesReadyOut(); + return mServerProxy->framesReady(); } // Don't call for fast tracks; the framesReady() could result in priority inversion @@ -795,7 +798,7 @@ uint32_t AudioFlinger::PlaybackThread::Track::getVolumeLR() { // called by FastMixer, so not allowed to take any locks, block, or do I/O including logs ALOG_ASSERT(isFastTrack() && (mCblk != NULL)); - uint32_t vlr = mCblk->getVolumeLR(); + uint32_t vlr = mServerProxy->getVolumeLR(); uint32_t vl = vlr & 0xFFFF; uint32_t vr = vlr >> 16; // track volumes come from shared memory, so can't be trusted and must be clamped @@ -830,11 +833,6 @@ status_t AudioFlinger::PlaybackThread::Track::setSyncEvent(const sp& return NO_ERROR; } -bool AudioFlinger::PlaybackThread::Track::isOut() const -{ - return true; -} - void AudioFlinger::PlaybackThread::Track::invalidate() { // FIXME should use proxy @@ -1369,17 +1367,19 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( size_t frameCount) : Track(playbackThread, NULL, AUDIO_STREAM_CNT, sampleRate, format, channelMask, frameCount, NULL, 0, IAudioFlinger::TRACK_DEFAULT), - mActive(false), mSourceThread(sourceThread), mBuffers(NULL) + mActive(false), mSourceThread(sourceThread), mClientProxy(NULL) { if (mCblk != NULL) { - mBuffers = (char*)mCblk + sizeof(audio_track_cblk_t); mOutBuffer.frameCount = 0; playbackThread->mTracks.add(this); - ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, mBuffers %p, " \ - "mCblk->frameCount %d, mCblk->sampleRate %u, mChannelMask 0x%08x mBufferEnd %p", - mCblk, mBuffer, mBuffers, - mCblk->frameCount, mCblk->sampleRate, mChannelMask, mBufferEnd); + ALOGV("OutputTrack constructor mCblk %p, mBuffer %p, " + "mCblk->frameCount_ %u, mChannelMask 0x%08x mBufferEnd %p", + mCblk, mBuffer, + mCblk->frameCount_, mChannelMask, mBufferEnd); + // since client and server are in the same process, + // the buffer has the same virtual address on both sides + mClientProxy = new AudioTrackClientProxy(mCblk, mBuffer, mFrameCount, mFrameSize); } else { ALOGW("Error creating output track on thread %p", playbackThread); } @@ -1388,6 +1388,8 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack( AudioFlinger::PlaybackThread::OutputTrack::~OutputTrack() { clearBufferQueue(); + delete mClientProxy; + // superclass destructor will now delete the server proxy and shared memory both refer to } status_t AudioFlinger::PlaybackThread::OutputTrack::start(AudioSystem::sync_event_t event, @@ -1475,7 +1477,7 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr uint32_t outFrames = pInBuffer->frameCount > mOutBuffer.frameCount ? mOutBuffer.frameCount : pInBuffer->frameCount; memcpy(mOutBuffer.raw, pInBuffer->raw, outFrames * channelCount * sizeof(int16_t)); - mCblk->stepUserOut(outFrames, mFrameCount); + mClientProxy->stepUser(outFrames); pInBuffer->frameCount -= outFrames; pInBuffer->i16 += outFrames * channelCount; mOutBuffer.frameCount -= outFrames; @@ -1538,40 +1540,29 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(int16_t* data, uint32_t fr status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs) { - int active; - status_t result; audio_track_cblk_t* cblk = mCblk; uint32_t framesReq = buffer->frameCount; ALOGVV("OutputTrack::obtainBuffer user %d, server %d", cblk->user, cblk->server); buffer->frameCount = 0; - uint32_t framesAvail = cblk->framesAvailableOut(mFrameCount); - - - if (framesAvail == 0) { + size_t framesAvail; + { Mutex::Autolock _l(cblk->lock); - goto start_loop_here; - while (framesAvail == 0) { - active = mActive; - if (CC_UNLIKELY(!active)) { + + // read the server count again + while (!(framesAvail = mClientProxy->framesAvailable_l())) { + if (CC_UNLIKELY(!mActive)) { ALOGV("Not active and NO_MORE_BUFFERS"); return NO_MORE_BUFFERS; } - result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); + status_t result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs)); if (result != NO_ERROR) { return NO_MORE_BUFFERS; } - // read the server count again - start_loop_here: - framesAvail = cblk->framesAvailableOut_l(mFrameCount); } } -// if (framesAvail < framesReq) { -// return NO_MORE_BUFFERS; -// } - if (framesReq > framesAvail) { framesReq = framesAvail; } @@ -1584,7 +1575,7 @@ status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( } buffer->frameCount = framesReq; - buffer->raw = cblk->buffer(mBuffers, mFrameSize, u); + buffer->raw = mClientProxy->buffer(u); return NO_ERROR; } @@ -1655,7 +1646,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( size_t frameCount, int sessionId) : TrackBase(thread, client, sampleRate, format, - channelMask, frameCount, 0 /*sharedBuffer*/, sessionId), + channelMask, frameCount, 0 /*sharedBuffer*/, sessionId, false /*isOut*/), mOverflow(false) { ALOGV("RecordTrack constructor, size %d", (int)mBufferEnd - (int)mBuffer); @@ -1684,7 +1675,7 @@ status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvi } // FIXME lock is not actually held, so overrun is possible - framesAvail = cblk->framesAvailableIn_l(mFrameCount); + framesAvail = mServerProxy->framesAvailableIn_l(); if (CC_LIKELY(framesAvail)) { uint32_t s = cblk->server; @@ -1761,27 +1752,21 @@ void AudioFlinger::RecordThread::RecordTrack::destroy() /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) { - result.append(" Clien Fmt Chn mask Session Step S SRate Serv User FrameCount\n"); + result.append(" Clien Fmt Chn mask Session Step S Serv User FrameCount\n"); } void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) { - snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x %05d\n", + snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %08x %08x %05d\n", (mClient == 0) ? getpid_cached : mClient->pid(), mFormat, mChannelMask, mSessionId, mStepCount, mState, - mCblk->sampleRate, mCblk->server, mCblk->user, mFrameCount); } -bool AudioFlinger::RecordThread::RecordTrack::isOut() const -{ - return false; -} - }; // namespace android -- 2.11.0