summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2012-12-21 15:04:30 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-12-21 15:04:30 -0800
commit856ff4e4c3c43550f013e80277358fdf514342bf (patch)
tree8c4d4a5e03726de6b40ab9ed3519e738cae2fefc /services
parent5570227ac334479982a9dd8c1647c00f58f47c18 (diff)
parent552f274d82fb4988fb972df69134e031d375abfe (diff)
downloadframeworks_av-856ff4e4c3c43550f013e80277358fdf514342bf.zip
frameworks_av-856ff4e4c3c43550f013e80277358fdf514342bf.tar.gz
frameworks_av-856ff4e4c3c43550f013e80277358fdf514342bf.tar.bz2
Merge "Start isolating control block accesses in a proxy"
Diffstat (limited to 'services')
-rw-r--r--services/audioflinger/AudioFlinger.h1
-rw-r--r--services/audioflinger/PlaybackTracks.h3
-rw-r--r--services/audioflinger/RecordTracks.h2
-rw-r--r--services/audioflinger/Threads.cpp21
-rw-r--r--services/audioflinger/TrackBase.h9
-rw-r--r--services/audioflinger/Tracks.cpp97
6 files changed, 63 insertions, 70 deletions
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index a28f47e..a7f5b9e 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 aaa5333..adec938 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 fe681d7..6c0d1d3 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 a50c936..783327f 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 17de49b..e0bd97a 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<IMemory>& 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<ThreadBase> mThread;
@@ -116,6 +118,7 @@ protected:
sp<IMemory> 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<SyncEvent> >mSyncEvents;
+ const bool mIsOut;
+ ServerProxy* mServerProxy;
};
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 9b611d2..c5f0ed7 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<IMemory>& 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<SyncEvent>&
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