Merge "Was calculating measured warmup time wrong" into jb-dev
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index eea3cd2..7d6b121 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -2841,6 +2841,8 @@
// at the identical fast mixer slot within the same normal mix cycle,
// is impossible because the slot isn't marked available until the end of each cycle.
int j = track->mFastIndex;
+ ALOG_ASSERT(0 < j && j < (int)FastMixerState::kMaxFastTracks);
+ ALOG_ASSERT(!(mFastTrackAvailMask & (1 << j)));
FastTrack *fastTrack = &state->mFastTracks[j];
// Determine whether the track is currently in underrun condition,
@@ -4295,6 +4297,13 @@
// NOTE: audio_track_cblk_t::frameSize for 8 bit PCM data is based on a sample size of
// 16 bit because data is converted to 16 bit before being stored in buffer by AudioTrack
mCblk->frameSize = audio_is_linear_pcm(format) ? mChannelCount * sizeof(int16_t) : sizeof(uint8_t);
+ // to avoid leaking a track name, do not allocate one unless there is an mCblk
+ mName = thread->getTrackName_l((audio_channel_mask_t)channelMask);
+ if (mName < 0) {
+ ALOGE("no more track names available");
+ return;
+ }
+ // only allocate a fast track index if we were able to allocate a normal track name
if (flags & IAudioFlinger::TRACK_FAST) {
mCblk->flags |= CBLK_FAST; // atomic op not needed yet
ALOG_ASSERT(thread->mFastTrackAvailMask != 0);
@@ -4309,14 +4318,6 @@
mObservedUnderruns = thread->getFastTrackUnderruns(i);
thread->mFastTrackAvailMask &= ~(1 << i);
}
- // to avoid leaking a track name, do not allocate one unless there is an mCblk
- mName = thread->getTrackName_l((audio_channel_mask_t)channelMask);
- if (mName < 0) {
- ALOGE("no more track names available");
- // FIXME bug - if sufficient fast track indices, but insufficient normal mixer names,
- // then we leak a fast track index. Should swap these two sections, or better yet
- // only allocate a normal mixer name for normal tracks.
- }
}
ALOGV("Track constructor name %d, calling pid %d", mName, IPCThreadState::self()->getCallingPid());
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 19390b1..160e4cd 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -778,6 +778,7 @@
int mName; // track name on the normal mixer,
// allocated statically at track creation time,
// and is even allocated (though unused) for fast tracks
+ // FIXME don't allocate track name for fast tracks
int16_t *mMainBuffer;
int32_t *mAuxBuffer;
int mAuxEffectId;
@@ -789,7 +790,7 @@
// The following fields are only for fast tracks, and should be in a subclass
int mFastIndex; // index within FastMixerState::mFastTracks[];
- // either mFastIndex == -1
+ // either mFastIndex == -1 if not isFastTrack()
// or 0 < mFastIndex < FastMixerState::kMaxFast because
// index 0 is reserved for normal mixer's submix;
// index is allocated statically at track creation time
diff --git a/services/audioflinger/MonoPipe.cpp b/services/audioflinger/MonoPipe.cpp
index fd16e92..6efb8b1 100644
--- a/services/audioflinger/MonoPipe.cpp
+++ b/services/audioflinger/MonoPipe.cpp
@@ -25,9 +25,10 @@
namespace android {
-MonoPipe::MonoPipe(size_t maxFrames, NBAIO_Format format, bool writeCanBlock) :
+MonoPipe::MonoPipe(size_t reqFrames, NBAIO_Format format, bool writeCanBlock) :
NBAIO_Sink(format),
- mMaxFrames(roundup(maxFrames)),
+ mReqFrames(reqFrames),
+ mMaxFrames(roundup(reqFrames)),
mBuffer(malloc(mMaxFrames * Format_frameSize(format))),
mFront(0),
mRear(0),
@@ -45,6 +46,7 @@
if (CC_UNLIKELY(!mNegotiated)) {
return NEGOTIATE;
}
+ // uses mMaxFrames not mReqFrames, so allows "over-filling" the pipe beyond requested limit
ssize_t ret = mMaxFrames - (mRear - android_atomic_acquire_load(&mFront));
ALOG_ASSERT((0 <= ret) && (ret <= mMaxFrames));
return ret;
@@ -57,6 +59,7 @@
}
size_t totalFramesWritten = 0;
while (count > 0) {
+ // can't return a negative value, as we already checked for !mNegotiated
size_t avail = availableToWrite();
size_t written = avail;
if (CC_LIKELY(written > count)) {
@@ -84,50 +87,29 @@
count -= written;
buffer = (char *) buffer + (written << mBitShift);
// Simulate blocking I/O by sleeping at different rates, depending on a throttle.
- // The throttle tries to keep the pipe about 5/8 full on average, with a slight jitter.
- uint64_t ns;
- enum {
- THROTTLE_VERY_FAST, // pipe is (nearly) empty, fill quickly
- THROTTLE_FAST, // pipe is normal, fill at slightly faster rate
- THROTTLE_NOMINAL, // pipe is normal, fill at nominal rate
- THROTTLE_SLOW, // pipe is normal, fill at slightly slower rate
- THROTTLE_VERY_SLOW, // pipe is (nearly) full, fill slowly
- } throttle;
- avail -= written;
- // FIXME cache these values to avoid re-computation
- if (avail >= (mMaxFrames * 3) / 4) {
- throttle = THROTTLE_VERY_FAST;
- } else if (avail >= mMaxFrames / 2) {
- throttle = THROTTLE_FAST;
- } else if (avail >= (mMaxFrames * 3) / 8) {
- throttle = THROTTLE_NOMINAL;
- } else if (avail >= mMaxFrames / 4) {
- throttle = THROTTLE_SLOW;
- } else {
- throttle = THROTTLE_VERY_SLOW;
- }
+ // The throttle tries to keep the pipe about 11/16 full on average, with a slight jitter.
+ uint32_t ns;
if (written > 0) {
- // FIXME cache these values also
- switch (throttle) {
- case THROTTLE_VERY_FAST:
- default:
+ size_t filled = (mMaxFrames - avail) + written;
+ // FIXME cache these values to avoid re-computation
+ if (filled <= mReqFrames / 4) {
+ // pipe is (nearly) empty, fill quickly
ns = written * ( 500000000 / Format_sampleRate(mFormat));
- break;
- case THROTTLE_FAST:
+ } else if (filled <= mReqFrames / 2) {
+ // pipe is normal, fill at slightly faster rate
ns = written * ( 750000000 / Format_sampleRate(mFormat));
- break;
- case THROTTLE_NOMINAL:
+ } else if (filled <= (mReqFrames * 5) / 8) {
+ // pipe is normal, fill at nominal rate
ns = written * (1000000000 / Format_sampleRate(mFormat));
- break;
- case THROTTLE_SLOW:
+ } else if (filled <= (mReqFrames * 3) / 4) {
+ // pipe is normal, fill at slightly slower rate
ns = written * (1100000000 / Format_sampleRate(mFormat));
- break;
- case THROTTLE_VERY_SLOW:
+ } else {
+ // pipe is (nearly) full, fill slowly
ns = written * (1250000000 / Format_sampleRate(mFormat));
- break;
}
} else {
- ns = mMaxFrames * (250000000 / Format_sampleRate(mFormat));
+ ns = mReqFrames * (250000000 / Format_sampleRate(mFormat));
}
if (ns > 999999999) {
ns = 999999999;
diff --git a/services/audioflinger/MonoPipe.h b/services/audioflinger/MonoPipe.h
index 545d6ac..aaaa51f 100644
--- a/services/audioflinger/MonoPipe.h
+++ b/services/audioflinger/MonoPipe.h
@@ -33,11 +33,11 @@
friend class MonoPipeReader;
public:
- // maxFrames will be rounded up to a power of 2, and all slots are available. Must be >= 2.
+ // reqFrames will be rounded up to a power of 2, and all slots are available. Must be >= 2.
// Note: whatever shares this object with another thread needs to do so in an SMP-safe way (like
// creating it the object before creating the other thread, or storing the object with a
// release_store). Otherwise the other thread could see a partially-constructed object.
- MonoPipe(size_t maxFrames, NBAIO_Format format, bool writeCanBlock = false);
+ MonoPipe(size_t reqFrames, NBAIO_Format format, bool writeCanBlock = false);
virtual ~MonoPipe();
// NBAIO_Port interface
@@ -58,9 +58,10 @@
// average number of frames present in the pipe under normal conditions.
// See throttling mechanism in MonoPipe::write()
- size_t getAvgFrames() const { return (mMaxFrames * 11) / 16; }
+ size_t getAvgFrames() const { return (mReqFrames * 11) / 16; }
private:
+ const size_t mReqFrames; // as requested in constructor, unrounded
const size_t mMaxFrames; // always a power of 2
void * const mBuffer;
// mFront and mRear will never be separated by more than mMaxFrames.