Merge "Camera2: Copy metadata buffers for streaming."
diff --git a/media/libeffects/visualizer/EffectVisualizer.cpp b/media/libeffects/visualizer/EffectVisualizer.cpp
index 44d05cd..d3c69f4 100644
--- a/media/libeffects/visualizer/EffectVisualizer.cpp
+++ b/media/libeffects/visualizer/EffectVisualizer.cpp
@@ -52,6 +52,8 @@
 // that the framework has stopped playing audio and we must start returning silence
 #define MAX_STALL_TIME_MS 1000
 
+#define CAPTURE_BUF_SIZE 65536 // "64k should be enough for everyone"
+
 struct VisualizerContext {
     const struct effect_interface_s *mItfe;
     effect_config_t mConfig;
@@ -59,10 +61,10 @@
     uint32_t mCaptureSize;
     uint32_t mScalingMode;
     uint8_t mState;
-    uint8_t mCurrentBuf;
-    uint8_t mLastBuf;
+    uint8_t mLastCaptureIdx;
+    uint32_t mLatency;
     struct timespec mBufferUpdateTime;
-    uint8_t mCaptureBuf[2][VISUALIZER_CAPTURE_SIZE_MAX];
+    uint8_t mCaptureBuf[CAPTURE_BUF_SIZE];
 };
 
 //
@@ -72,11 +74,10 @@
 void Visualizer_reset(VisualizerContext *pContext)
 {
     pContext->mCaptureIdx = 0;
-    pContext->mCurrentBuf = 0;
-    pContext->mLastBuf = 1;
+    pContext->mLastCaptureIdx = 0;
     pContext->mBufferUpdateTime.tv_sec = 0;
-    memset(pContext->mCaptureBuf[0], 0x80, VISUALIZER_CAPTURE_SIZE_MAX);
-    memset(pContext->mCaptureBuf[1], 0x80, VISUALIZER_CAPTURE_SIZE_MAX);
+    pContext->mLatency = 0;
+    memset(pContext->mCaptureBuf, 0x80, CAPTURE_BUF_SIZE);
 }
 
 //----------------------------------------------------------------------------
@@ -316,25 +317,25 @@
 
     uint32_t captIdx;
     uint32_t inIdx;
-    uint8_t *buf = pContext->mCaptureBuf[pContext->mCurrentBuf];
+    uint8_t *buf = pContext->mCaptureBuf;
     for (inIdx = 0, captIdx = pContext->mCaptureIdx;
-         inIdx < inBuffer->frameCount && captIdx < pContext->mCaptureSize;
+         inIdx < inBuffer->frameCount;
          inIdx++, captIdx++) {
+        if (captIdx >= CAPTURE_BUF_SIZE) {
+            // wrap around
+            captIdx = 0;
+        }
         int32_t smp = inBuffer->s16[2 * inIdx] + inBuffer->s16[2 * inIdx + 1];
         smp = smp >> shift;
         buf[captIdx] = ((uint8_t)smp)^0x80;
     }
+
+    // XXX the following two should really be atomic, though it probably doesn't
+    // matter much for visualization purposes
     pContext->mCaptureIdx = captIdx;
-
-    // go to next buffer when buffer full
-    if (pContext->mCaptureIdx == pContext->mCaptureSize) {
-        pContext->mCurrentBuf ^= 1;
-        pContext->mCaptureIdx = 0;
-
-        // update last buffer update time stamp
-        if (clock_gettime(CLOCK_MONOTONIC, &pContext->mBufferUpdateTime) < 0) {
-            pContext->mBufferUpdateTime.tv_sec = 0;
-        }
+    // update last buffer update time stamp
+    if (clock_gettime(CLOCK_MONOTONIC, &pContext->mBufferUpdateTime) < 0) {
+        pContext->mBufferUpdateTime.tv_sec = 0;
     }
 
     if (inBuffer->raw != outBuffer->raw) {
@@ -464,6 +465,10 @@
             pContext->mScalingMode = *((uint32_t *)p->data + 1);
             ALOGV("set mScalingMode = %d", pContext->mScalingMode);
             break;
+        case VISUALIZER_PARAM_LATENCY:
+            pContext->mLatency = *((uint32_t *)p->data + 1);
+            ALOGV("set mLatency = %d", pContext->mLatency);
+            break;
         default:
             *(int32_t *)pReplyData = -EINVAL;
         }
@@ -481,13 +486,9 @@
             return -EINVAL;
         }
         if (pContext->mState == VISUALIZER_STATE_ACTIVE) {
-            memcpy(pReplyData,
-                   pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1],
-                   pContext->mCaptureSize);
-            // if audio framework has stopped playing audio although the effect is still
-            // active we must clear the capture buffer to return silence
-            if ((pContext->mLastBuf == pContext->mCurrentBuf) &&
-                    (pContext->mBufferUpdateTime.tv_sec != 0)) {
+            int32_t latencyMs = pContext->mLatency;
+            uint32_t deltaMs = 0;
+            if (pContext->mBufferUpdateTime.tv_sec != 0) {
                 struct timespec ts;
                 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
                     time_t secs = ts.tv_sec - pContext->mBufferUpdateTime.tv_sec;
@@ -496,17 +497,45 @@
                         --secs;
                         nsec += 1000000000;
                     }
-                    uint32_t deltaMs = secs * 1000 + nsec / 1000000;
-                    if (deltaMs > MAX_STALL_TIME_MS) {
-                        ALOGV("capture going to idle");
-                        pContext->mBufferUpdateTime.tv_sec = 0;
-                        memset(pContext->mCaptureBuf[pContext->mCurrentBuf ^ 1],
-                                0x80,
-                                pContext->mCaptureSize);
+                    deltaMs = secs * 1000 + nsec / 1000000;
+                    latencyMs -= deltaMs;
+                    if (latencyMs < 0) {
+                        latencyMs = 0;
                     }
                 }
             }
-            pContext->mLastBuf = pContext->mCurrentBuf;
+            uint32_t deltaSmpl = pContext->mConfig.inputCfg.samplingRate * latencyMs / 1000;
+
+            int32_t capturePoint = pContext->mCaptureIdx - pContext->mCaptureSize - deltaSmpl;
+            int32_t captureSize = pContext->mCaptureSize;
+            if (capturePoint < 0) {
+                int32_t size = -capturePoint;
+                if (size > captureSize) {
+                    size = captureSize;
+                }
+                memcpy(pReplyData,
+                       pContext->mCaptureBuf + CAPTURE_BUF_SIZE + capturePoint,
+                       size);
+                pReplyData += size;
+                captureSize -= size;
+                capturePoint = 0;
+            }
+            memcpy(pReplyData,
+                   pContext->mCaptureBuf + capturePoint,
+                   captureSize);
+
+
+            // if audio framework has stopped playing audio although the effect is still
+            // active we must clear the capture buffer to return silence
+            if ((pContext->mLastCaptureIdx == pContext->mCaptureIdx) &&
+                    (pContext->mBufferUpdateTime.tv_sec != 0)) {
+                if (deltaMs > MAX_STALL_TIME_MS) {
+                    ALOGV("capture going to idle");
+                    pContext->mBufferUpdateTime.tv_sec = 0;
+                    memset(pReplyData, 0x80, pContext->mCaptureSize);
+                }
+            }
+            pContext->mLastCaptureIdx = pContext->mCaptureIdx;
         } else {
             memset(pReplyData, 0x80, pContext->mCaptureSize);
         }
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 4f59a8a..14b7fc1 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -47,6 +47,9 @@
 
 LOCAL_SRC_FILES += StateQueue.cpp
 
+# uncomment for debugging timing problems related to StateQueue::push()
+LOCAL_CFLAGS += -DSTATE_QUEUE_DUMP
+
 LOCAL_C_INCLUDES := \
     $(call include-path-for, audio-effects) \
     $(call include-path-for, audio-utils)
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index d9c5d55..d944d32 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1605,6 +1605,7 @@
     snprintf(buffer, SIZE, "mix buffer : %p\n", mMixBuffer);
     result.append(buffer);
     write(fd, result.string(), result.size());
+    fdprintf(fd, "Fast track availMask=%#x\n", mFastTrackAvailMask);
 
     dumpBase(fd, args);
 
@@ -1817,6 +1818,10 @@
 uint32_t AudioFlinger::PlaybackThread::latency() const
 {
     Mutex::Autolock _l(mLock);
+    return latency_l();
+}
+uint32_t AudioFlinger::PlaybackThread::latency_l() const
+{
     if (initCheck() == NO_ERROR) {
         return correctLatency(mOutput->stream->get_latency(mOutput->stream));
     } else {
@@ -2012,11 +2017,9 @@
     mNormalFrameCount = (mNormalFrameCount + 15) & ~15;
     ALOGI("HAL output buffer size %u frames, normal mix buffer size %u frames", mFrameCount, mNormalFrameCount);
 
-    // FIXME - Current mixer implementation only supports stereo output: Always
-    // Allocate a stereo buffer even if HW output is mono.
     delete[] mMixBuffer;
-    mMixBuffer = new int16_t[mNormalFrameCount * 2];
-    memset(mMixBuffer, 0, mNormalFrameCount * 2 * sizeof(int16_t));
+    mMixBuffer = new int16_t[mNormalFrameCount * mChannelCount];
+    memset(mMixBuffer, 0, mNormalFrameCount * mChannelCount * sizeof(int16_t));
 
     // force reconfiguration of effect chains and engines to take new buffer size and audio
     // parameters into account
@@ -2113,14 +2116,7 @@
 
 uint32_t AudioFlinger::PlaybackThread::activeSleepTimeUs() const
 {
-    // A2DP output latency is not due only to buffering capacity. It also reflects encoding,
-    // decoding and transfer time. So sleeping for half of the latency would likely cause
-    // underruns
-    if (audio_is_a2dp_device((audio_devices_t)mDevice)) {
-        return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
-    } else {
-        return (uint32_t)(mOutput->stream->get_latency(mOutput->stream) * 1000) / 2;
-    }
+    return (uint32_t)((uint32_t)((mNormalFrameCount * 1000) / mSampleRate) * 1000);
 }
 
 status_t AudioFlinger::PlaybackThread::setSyncEvent(const sp<SyncEvent>& event)
@@ -2254,6 +2250,10 @@
         // create fast mixer and configure it initially with just one fast track for our submix
         mFastMixer = new FastMixer();
         FastMixerStateQueue *sq = mFastMixer->sq();
+#ifdef STATE_QUEUE_DUMP
+        sq->setObserverDump(&mStateQueueObserverDump);
+        sq->setMutatorDump(&mStateQueueMutatorDump);
+#endif
         FastMixerState *state = sq->begin();
         FastTrack *fastTrack = &state->mFastTracks[0];
         // wrap the source side of the MonoPipe to make it an AudioBufferProvider
@@ -2677,21 +2677,31 @@
     // FIXME rewrite to reduce number of system calls
     mLastWriteTime = systemTime();
     mInWrite = true;
+    int bytesWritten;
 
+    // If an NBAIO sink is present, use it to write the normal mixer's submix
+    if (mNormalSink != 0) {
 #define mBitShift 2 // FIXME
-    size_t count = mixBufferSize >> mBitShift;
+        size_t count = mixBufferSize >> mBitShift;
 #if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER)
-    Tracer::traceBegin(ATRACE_TAG, "write");
+        Tracer::traceBegin(ATRACE_TAG, "write");
 #endif
-    ssize_t framesWritten = mNormalSink->write(mMixBuffer, count);
+        ssize_t framesWritten = mNormalSink->write(mMixBuffer, count);
 #if defined(ATRACE_TAG) && (ATRACE_TAG != ATRACE_TAG_NEVER)
-    Tracer::traceEnd(ATRACE_TAG);
+        Tracer::traceEnd(ATRACE_TAG);
 #endif
-    if (framesWritten > 0) {
-        size_t bytesWritten = framesWritten << mBitShift;
-        mBytesWritten += bytesWritten;
+        if (framesWritten > 0) {
+            bytesWritten = framesWritten << mBitShift;
+        } else {
+            bytesWritten = framesWritten;
+        }
+    // otherwise use the HAL / AudioStreamOut directly
+    } else {
+        // Direct output thread.
+        bytesWritten = (int)mOutput->stream->write(mOutput->stream, mMixBuffer, mixBufferSize);
     }
 
+    if (bytesWritten > 0) mBytesWritten += mixBufferSize;
     mNumWrites++;
     mInWrite = false;
 }
@@ -2841,11 +2851,14 @@
             // 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,
             // and whether it had a recent underrun.
-            FastTrackUnderruns underruns = mFastMixerDumpState.mTracks[j].mUnderruns;
+            FastTrackDump *ftDump = &mFastMixerDumpState.mTracks[j];
+            FastTrackUnderruns underruns = ftDump->mUnderruns;
             uint32_t recentFull = (underruns.mBitFields.mFull -
                     track->mObservedUnderruns.mBitFields.mFull) & UNDERRUN_MASK;
             uint32_t recentPartial = (underruns.mBitFields.mPartial -
@@ -3172,6 +3185,7 @@
                     tracksToRemove->add(track);
                 }
             } else {
+                track->mUnderrunCount++;
                 // No buffers for this track. Give it a few chances to
                 // fill a buffer, then remove it from active list.
                 if (--(track->mRetryCount) <= 0) {
@@ -3475,6 +3489,14 @@
     FastMixerDumpState copy = mFastMixerDumpState;
     copy.dump(fd);
 
+#ifdef STATE_QUEUE_DUMP
+    // Similar for state queue
+    StateQueueObserverDump observerCopy = mStateQueueObserverDump;
+    observerCopy.dump(fd);
+    StateQueueMutatorDump mutatorCopy = mStateQueueMutatorDump;
+    mutatorCopy.dump(fd);
+#endif
+
     // Write the tee output to a .wav file
     NBAIO_Source *teeSource = mTeeSource.get();
     if (teeSource != NULL) {
@@ -3560,7 +3582,6 @@
         AudioStreamOut* output, audio_io_handle_t id, uint32_t device)
     :   PlaybackThread(audioFlinger, output, id, device, DIRECT)
         // mLeftVolFloat, mRightVolFloat
-        // mLeftVolShort, mRightVolShort
 {
 }
 
@@ -3587,7 +3608,13 @@
 
         // The first time a track is added we wait
         // for all its buffers to be filled before processing it
-        if (cblk->framesReady() && track->isReady() &&
+        uint32_t minFrames;
+        if ((track->sharedBuffer() == 0) && !track->isStopped() && !track->isPausing()) {
+            minFrames = mNormalFrameCount;
+        } else {
+            minFrames = 1;
+        }
+        if ((track->framesReady() >= minFrames) && track->isReady() &&
                 !track->isPaused() && !track->isTerminated())
         {
             //ALOGV("track %d u=%08x, s=%08x [OK]", track->name(), cblk->user, cblk->server);
@@ -3595,16 +3622,11 @@
             if (track->mFillingUpStatus == Track::FS_FILLED) {
                 track->mFillingUpStatus = Track::FS_ACTIVE;
                 mLeftVolFloat = mRightVolFloat = 0;
-                mLeftVolShort = mRightVolShort = 0;
                 if (track->mState == TrackBase::RESUMING) {
                     track->mState = TrackBase::ACTIVE;
-                    rampVolume = true;
                 }
-            } else if (cblk->server != 0) {
-                // If the track is stopped before the first frame was mixed,
-                // do not apply ramp
-                rampVolume = true;
             }
+
             // compute volume for this track
             float left, right;
             if (track->isMuted() || mMasterMute || track->isPausing() ||
@@ -3629,13 +3651,6 @@
                 mLeftVolFloat = left;
                 mRightVolFloat = right;
 
-                // If audio HAL implements volume control,
-                // force software volume to nominal value
-                if (mOutput->stream->set_volume(mOutput->stream, left, right) == NO_ERROR) {
-                    left = 1.0f;
-                    right = 1.0f;
-                }
-
                 // Convert volumes from float to 8.24
                 uint32_t vl = (uint32_t)(left * (1 << 24));
                 uint32_t vr = (uint32_t)(right * (1 << 24));
@@ -3645,22 +3660,11 @@
                 // there is one, the track is connected to it
                 if (!mEffectChains.isEmpty()) {
                     // Do not ramp volume if volume is controlled by effect
-                    if (mEffectChains[0]->setVolume_l(&vl, &vr)) {
-                        rampVolume = false;
-                    }
+                    mEffectChains[0]->setVolume_l(&vl, &vr);
+                    left = (float)vl / (1 << 24);
+                    right = (float)vr / (1 << 24);
                 }
-
-                // Convert volumes from 8.24 to 4.12 format
-                uint32_t v_clamped = (vl + (1 << 11)) >> 12;
-                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
-                leftVol = (uint16_t)v_clamped;
-                v_clamped = (vr + (1 << 11)) >> 12;
-                if (v_clamped > MAX_GAIN_INT) v_clamped = MAX_GAIN_INT;
-                rightVol = (uint16_t)v_clamped;
-            } else {
-                leftVol = mLeftVolShort;
-                rightVol = mRightVolShort;
-                rampVolume = false;
+                mOutput->stream->set_volume(mOutput->stream, left, right);
             }
 
             // reset retry count
@@ -3675,7 +3679,8 @@
             }
 
             //ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
-            if (track->isTerminated() || track->isStopped() || track->isPaused()) {
+            if ((track->sharedBuffer() != 0) || track->isTerminated() ||
+                    track->isStopped() || track->isPaused()) {
                 // We have consumed all the buffers of this track.
                 // Remove it from the list of active tracks.
                 // TODO: implement behavior for compressed audio
@@ -3742,78 +3747,6 @@
     standbyTime = systemTime() + standbyDelay;
     mActiveTrack.clear();
 
-    // apply volume
-
-    // Do not apply volume on compressed audio
-    if (!audio_is_linear_pcm(mFormat)) {
-        return;
-    }
-
-    // convert to signed 16 bit before volume calculation
-    if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
-        size_t count = mFrameCount * mChannelCount;
-        uint8_t *src = (uint8_t *)mMixBuffer + count-1;
-        int16_t *dst = mMixBuffer + count-1;
-        while (count--) {
-            *dst-- = (int16_t)(*src--^0x80) << 8;
-        }
-    }
-
-    frameCount = mFrameCount;
-    int16_t *out = mMixBuffer;
-    if (rampVolume) {
-        if (mChannelCount == 1) {
-            int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
-            int32_t vlInc = d / (int32_t)frameCount;
-            int32_t vl = ((int32_t)mLeftVolShort << 16);
-            do {
-                out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
-                out++;
-                vl += vlInc;
-            } while (--frameCount);
-
-        } else {
-            int32_t d = ((int32_t)leftVol - (int32_t)mLeftVolShort) << 16;
-            int32_t vlInc = d / (int32_t)frameCount;
-            d = ((int32_t)rightVol - (int32_t)mRightVolShort) << 16;
-            int32_t vrInc = d / (int32_t)frameCount;
-            int32_t vl = ((int32_t)mLeftVolShort << 16);
-            int32_t vr = ((int32_t)mRightVolShort << 16);
-            do {
-                out[0] = clamp16(mul(out[0], vl >> 16) >> 12);
-                out[1] = clamp16(mul(out[1], vr >> 16) >> 12);
-                out += 2;
-                vl += vlInc;
-                vr += vrInc;
-            } while (--frameCount);
-        }
-    } else {
-        if (mChannelCount == 1) {
-            do {
-                out[0] = clamp16(mul(out[0], leftVol) >> 12);
-                out++;
-            } while (--frameCount);
-        } else {
-            do {
-                out[0] = clamp16(mul(out[0], leftVol) >> 12);
-                out[1] = clamp16(mul(out[1], rightVol) >> 12);
-                out += 2;
-            } while (--frameCount);
-        }
-    }
-
-    // convert back to unsigned 8 bit after volume calculation
-    if (mFormat == AUDIO_FORMAT_PCM_8_BIT) {
-        size_t count = mFrameCount * mChannelCount;
-        int16_t *src = mMixBuffer;
-        uint8_t *dst = (uint8_t *)mMixBuffer;
-        while (count--) {
-            *dst++ = (uint8_t)(((int32_t)*src++ + (1<<7)) >> 8)^0x80;
-        }
-    }
-
-    mLeftVolShort = leftVol;
-    mRightVolShort = rightVol;
 }
 
 void AudioFlinger::DirectOutputThread::threadLoop_sleepTime()
@@ -3958,6 +3891,7 @@
     }
     sleepTime = 0;
     writeFrames = mNormalFrameCount;
+    standbyTime = systemTime() + standbyDelay;
 }
 
 void AudioFlinger::DuplicatingThread::threadLoop_sleepTime()
@@ -3969,21 +3903,19 @@
             sleepTime = idleSleepTime;
         }
     } else if (mBytesWritten != 0) {
-        // flush remaining overflow buffers in output tracks
-        for (size_t i = 0; i < outputTracks.size(); i++) {
-            if (outputTracks[i]->isActive()) {
-                sleepTime = 0;
-                writeFrames = 0;
-                memset(mMixBuffer, 0, mixBufferSize);
-                break;
-            }
+        if (mMixerStatus == MIXER_TRACKS_ENABLED) {
+            writeFrames = mNormalFrameCount;
+            memset(mMixBuffer, 0, mixBufferSize);
+        } else {
+            // flush remaining overflow buffers in output tracks
+            writeFrames = 0;
         }
+        sleepTime = 0;
     }
 }
 
 void AudioFlinger::DuplicatingThread::threadLoop_write()
 {
-    standbyTime = systemTime() + standbyDelay;
     for (size_t i = 0; i < outputTracks.size(); i++) {
         outputTracks[i]->write(mMixBuffer, writeFrames);
     }
@@ -4295,6 +4227,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 +4248,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());
 }
@@ -4366,7 +4297,7 @@
 /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
 {
     result.append("   Name Client Type Fmt Chn mask   Session mFrCnt fCount S M F SRate  L dB  R dB  "
-                  "  Server      User     Main buf    Aux Buf  Flags FastUnder\n");
+                  "  Server      User     Main buf    Aux Buf  Flags Underruns\n");
 }
 
 void AudioFlinger::PlaybackThread::Track::dump(char* buffer, size_t size)
@@ -8259,6 +8190,31 @@
         status = cmdStatus;
     }
 
+    if (status == 0 &&
+            (memcmp(&mDescriptor.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0)) {
+        uint32_t buf32[sizeof(effect_param_t) / sizeof(uint32_t) + 2];
+        effect_param_t *p = (effect_param_t *)buf32;
+
+        p->psize = sizeof(uint32_t);
+        p->vsize = sizeof(uint32_t);
+        size = sizeof(int);
+        *(int32_t *)p->data = VISUALIZER_PARAM_LATENCY;
+
+        uint32_t latency = 0;
+        PlaybackThread *pbt = thread->mAudioFlinger->checkPlaybackThread_l(thread->mId);
+        if (pbt != NULL) {
+            latency = pbt->latency_l();
+        }
+
+        *((int32_t *)p->data + 1)= latency;
+        (*mEffectInterface)->command(mEffectInterface,
+                                     EFFECT_CMD_SET_PARAM,
+                                     sizeof(effect_param_t) + 8,
+                                     &buf32,
+                                     &size,
+                                     &cmdStatus);
+    }
+
     mMaxDisableWaitCnt = (MAX_DISABLE_TIME_MS * mConfig.outputCfg.samplingRate) /
             (1000 * mConfig.outputCfg.buffer.frameCount);
 
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 19390b1..1c44f2f 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
@@ -964,6 +965,8 @@
 
                     // return estimated latency in milliseconds, as reported by HAL
                     uint32_t    latency() const;
+                    // same, but lock must already be held
+                    uint32_t    latency_l() const;
 
                     void        setMasterVolume(float value);
                     void        setMasterMute(bool muted);
@@ -1168,6 +1171,10 @@
 
                     // contents are not guaranteed to be consistent, no locks required
                     FastMixerDumpState mFastMixerDumpState;
+#ifdef STATE_QUEUE_DUMP
+                    StateQueueObserverDump mStateQueueObserverDump;
+                    StateQueueMutatorDump  mStateQueueMutatorDump;
+#endif
 
                     // accessible only within the threadLoop(), no locks required
                     //          mFastMixer->sq()    // for mutating and pushing state
@@ -1206,17 +1213,8 @@
         virtual     void        threadLoop_sleepTime();
 
         // volumes last sent to audio HAL with stream->set_volume()
-        // FIXME use standard representation and names
         float mLeftVolFloat;
         float mRightVolFloat;
-        uint16_t mLeftVolShort;
-        uint16_t mRightVolShort;
-
-        // FIXME rename these former local variables of threadLoop to standard names
-        // next 3 were local to the while !exitingPending loop
-        bool rampVolume;
-        uint16_t leftVol;
-        uint16_t rightVol;
 
 private:
         // prepareTracks_l() tells threadLoop_mix() the name of the single active track
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index ca25ba9..0d13970 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -1375,7 +1375,6 @@
         ALOGW("%s: could not get AudioFlinger", __func__);
         return 0;
     }
-    ALOGW("%s: %d", __func__, module);
     return af->openOutput(module, pDevices, pSamplingRate, pFormat, pChannelMask,
                           pLatencyMs, flags);
 }
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 52effb2..3bb7b44 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -161,6 +161,7 @@
                 coldGen = current->mColdGen;
                 bounds = 0;
                 full = false;
+                oldTsValid = !clock_gettime(CLOCK_MONOTONIC, &oldTs);
             } else {
                 sleepNs = FAST_HOT_IDLE_NS;
             }
@@ -238,6 +239,7 @@
 
             // check for change in active track set
             unsigned currentTrackMask = current->mTrackMask;
+            dumpState->mTrackMask = currentTrackMask;
             if (current->mFastTracksGen != fastTracksGen) {
                 ALOG_ASSERT(mixBuffer != NULL);
                 int name;
@@ -386,6 +388,7 @@
                     mixer->enable(name);
                 }
                 ftDump->mUnderruns = underruns;
+                ftDump->mFramesReady = framesReady;
             }
             // process() is CPU-bound
             mixer->process(AudioBufferProvider::kInvalidPTS);
@@ -480,7 +483,10 @@
                                 (int) sec, nsec / 1000000L);
                         dumpState->mOverruns++;
                     }
-                    sleepNs = periodNs - overrunNs;
+                    // Code for non blocking audio HAL. Sleep time must be tuned to allow
+                    // catching up after an underrun
+                    //     sleepNs = periodNs - overrunNs;
+                    sleepNs = -1;
                 } else {
                     sleepNs = -1;
                     ignoreNextOverrun = false;
@@ -561,7 +567,8 @@
 FastMixerDumpState::FastMixerDumpState() :
     mCommand(FastMixerState::INITIAL), mWriteSequence(0), mFramesWritten(0),
     mNumTracks(0), mWriteErrors(0), mUnderruns(0), mOverruns(0),
-    mSampleRate(0), mFrameCount(0), /* mMeasuredWarmupTs({0, 0}), */ mWarmupCycles(0)
+    mSampleRate(0), mFrameCount(0), /* mMeasuredWarmupTs({0, 0}), */ mWarmupCycles(0),
+    mTrackMask(0)
 #ifdef FAST_MIXER_STATISTICS
     , mBounds(0)
 #endif
@@ -670,6 +677,40 @@
                  "    mean=%.1f min=%.1f max=%.1f stddev=%.1f\n",
                  loadMHz.mean(), loadMHz.minimum(), loadMHz.maximum(), loadMHz.stddev());
 #endif
+    // The active track mask and track states are updated non-atomically.
+    // So if we relied on isActive to decide whether to display,
+    // then we might display an obsolete track or omit an active track.
+    // Instead we always display all tracks, with an indication
+    // of whether we think the track is active.
+    uint32_t trackMask = mTrackMask;
+    fdprintf(fd, "Fast tracks: kMaxFastTracks=%u activeMask=%#x\n",
+            FastMixerState::kMaxFastTracks, trackMask);
+    fdprintf(fd, "Index Active Full Partial Empty  Recent Ready\n");
+    for (uint32_t i = 0; i < FastMixerState::kMaxFastTracks; ++i, trackMask >>= 1) {
+        bool isActive = trackMask & 1;
+        const FastTrackDump *ftDump = &mTracks[i];
+        const FastTrackUnderruns& underruns = ftDump->mUnderruns;
+        const char *mostRecent;
+        switch (underruns.mBitFields.mMostRecent) {
+        case UNDERRUN_FULL:
+            mostRecent = "full";
+            break;
+        case UNDERRUN_PARTIAL:
+            mostRecent = "partial";
+            break;
+        case UNDERRUN_EMPTY:
+            mostRecent = "empty";
+            break;
+        default:
+            mostRecent = "?";
+            break;
+        }
+        fdprintf(fd, "%5u %6s %4u %7u %5u %7s %5u\n", i, isActive ? "yes" : "no",
+                (underruns.mBitFields.mFull) & UNDERRUN_MASK,
+                (underruns.mBitFields.mPartial) & UNDERRUN_MASK,
+                (underruns.mBitFields.mEmpty) & UNDERRUN_MASK,
+                mostRecent, ftDump->mFramesReady);
+    }
 }
 
 }   // namespace android
diff --git a/services/audioflinger/FastMixer.h b/services/audioflinger/FastMixer.h
index e95abf6..06e76d5 100644
--- a/services/audioflinger/FastMixer.h
+++ b/services/audioflinger/FastMixer.h
@@ -72,9 +72,10 @@
 
 // Represents the dump state of a fast track
 struct FastTrackDump {
-    FastTrackDump() { }
+    FastTrackDump() : mFramesReady(0) { }
     /*virtual*/ ~FastTrackDump() { }
     FastTrackUnderruns mUnderruns;
+    size_t mFramesReady;        // most recent value only; no long-term statistics kept
 };
 
 // The FastMixerDumpState keeps a cache of FastMixer statistics that can be logged by dumpsys.
@@ -100,6 +101,7 @@
     size_t   mFrameCount;
     struct timespec mMeasuredWarmupTs;  // measured warmup time
     uint32_t mWarmupCycles;     // number of loop cycles required to warmup
+    uint32_t mTrackMask;        // mask of active tracks
     FastTrackDump   mTracks[FastMixerState::kMaxFastTracks];
 
 #ifdef FAST_MIXER_STATISTICS
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.
diff --git a/services/audioflinger/StateQueue.cpp b/services/audioflinger/StateQueue.cpp
index ae263f5..3e891a5 100644
--- a/services/audioflinger/StateQueue.cpp
+++ b/services/audioflinger/StateQueue.cpp
@@ -24,12 +24,28 @@
 
 namespace android {
 
+#ifdef STATE_QUEUE_DUMP
+void StateQueueObserverDump::dump(int fd)
+{
+    fdprintf(fd, "State queue observer: stateChanges=%u\n", mStateChanges);
+}
+
+void StateQueueMutatorDump::dump(int fd)
+{
+    fdprintf(fd, "State queue mutator: pushDirty=%u pushAck=%u blockedSequence=%u\n",
+            mPushDirty, mPushAck, mBlockedSequence);
+}
+#endif
+
 // Constructor and destructor
 
 template<typename T> StateQueue<T>::StateQueue() :
     mNext(NULL), mAck(NULL), mCurrent(NULL),
     mMutating(&mStates[0]), mExpecting(NULL),
     mInMutation(false), mIsDirty(false), mIsInitialized(false)
+#ifdef STATE_QUEUE_DUMP
+    , mObserverDump(&mObserverDummyDump), mMutatorDump(&mMutatorDummyDump)
+#endif
 {
 }
 
@@ -45,6 +61,9 @@
     if (next != mCurrent) {
         mAck = next;    // no additional barrier needed
         mCurrent = next;
+#ifdef STATE_QUEUE_DUMP
+        mObserverDump->mStateChanges++;
+#endif
     }
     return next;
 }
@@ -77,10 +96,23 @@
 
     ALOG_ASSERT(!mInMutation, "push() called when in a mutation");
 
+#ifdef STATE_QUEUE_DUMP
+    if (block == BLOCK_UNTIL_ACKED) {
+        mMutatorDump->mPushAck++;
+    }
+#endif
+
     if (mIsDirty) {
 
+#ifdef STATE_QUEUE_DUMP
+        mMutatorDump->mPushDirty++;
+#endif
+
         // wait for prior push to be acknowledged
         if (mExpecting != NULL) {
+#ifdef STATE_QUEUE_DUMP
+            unsigned count = 0;
+#endif
             for (;;) {
                 const T *ack = (const T *) mAck;    // no additional barrier needed
                 if (ack == mExpecting) {
@@ -91,8 +123,19 @@
                 if (block == BLOCK_NEVER) {
                     return false;
                 }
+#ifdef STATE_QUEUE_DUMP
+                if (count == 1) {
+                    mMutatorDump->mBlockedSequence++;
+                }
+                ++count;
+#endif
                 nanosleep(&req, NULL);
             }
+#ifdef STATE_QUEUE_DUMP
+            if (count > 1) {
+                mMutatorDump->mBlockedSequence++;
+            }
+#endif
         }
 
         // publish
@@ -111,14 +154,28 @@
     // optionally wait for this push or a prior push to be acknowledged
     if (block == BLOCK_UNTIL_ACKED) {
         if (mExpecting != NULL) {
+#ifdef STATE_QUEUE_DUMP
+            unsigned count = 0;
+#endif
             for (;;) {
                 const T *ack = (const T *) mAck;    // no additional barrier needed
                 if (ack == mExpecting) {
                     mExpecting = NULL;
                     break;
                 }
+#ifdef STATE_QUEUE_DUMP
+                if (count == 1) {
+                    mMutatorDump->mBlockedSequence++;
+                }
+                ++count;
+#endif
                 nanosleep(&req, NULL);
             }
+#ifdef STATE_QUEUE_DUMP
+            if (count > 1) {
+                mMutatorDump->mBlockedSequence++;
+            }
+#endif
         }
     }
 
diff --git a/services/audioflinger/StateQueue.h b/services/audioflinger/StateQueue.h
index fe72ddc..eba190c 100644
--- a/services/audioflinger/StateQueue.h
+++ b/services/audioflinger/StateQueue.h
@@ -19,6 +19,34 @@
 
 namespace android {
 
+#ifdef STATE_QUEUE_DUMP
+// The StateQueueObserverDump and StateQueueMutatorDump keep
+// a cache of StateQueue statistics that can be logged by dumpsys.
+// Each individual native word-sized field is accessed atomically.  But the
+// overall structure is non-atomic, that is there may be an inconsistency between fields.
+// No barriers or locks are used for either writing or reading.
+// Only POD types are permitted, and the contents shouldn't be trusted (i.e. do range checks).
+// It has a different lifetime than the StateQueue, and so it can't be a member of StateQueue.
+
+struct StateQueueObserverDump {
+    StateQueueObserverDump() : mStateChanges(0) { }
+    /*virtual*/ ~StateQueueObserverDump() { }
+    unsigned    mStateChanges;    // incremented each time poll() detects a state change
+    void        dump(int fd);
+};
+
+struct StateQueueMutatorDump {
+    StateQueueMutatorDump() : mPushDirty(0), mPushAck(0), mBlockedSequence(0) { }
+    /*virtual*/ ~StateQueueMutatorDump() { }
+    unsigned    mPushDirty;       // incremented each time push() is called with a dirty state
+    unsigned    mPushAck;         // incremented each time push(BLOCK_UNTIL_ACKED) is called
+    unsigned    mBlockedSequence; // incremented before and after each time that push()
+                                  // blocks for more than one PUSH_BLOCK_ACK_NS;
+                                  // if odd, then mutator is currently blocked inside push()
+    void        dump(int fd);
+};
+#endif
+
 // manages a FIFO queue of states
 template<typename T> class StateQueue {
 
@@ -69,6 +97,16 @@
     // Return whether the current state is dirty (modified and not pushed).
     bool    isDirty() const { return mIsDirty; }
 
+#ifdef STATE_QUEUE_DUMP
+    // Register location of observer dump area
+    void    setObserverDump(StateQueueObserverDump *dump)
+            { mObserverDump = dump != NULL ? dump : &mObserverDummyDump; }
+
+    // Register location of mutator dump area
+    void    setMutatorDump(StateQueueMutatorDump *dump)
+            { mMutatorDump = dump != NULL ? dump : &mMutatorDummyDump; }
+#endif
+
 private:
     static const unsigned kN = 4;       // values != 4 are not supported by this code
     T                 mStates[kN];      // written by mutator, read by observer
@@ -87,6 +125,13 @@
     bool              mIsDirty;         // whether mutating state has been modified since last push
     bool              mIsInitialized;   // whether mutating state has been initialized yet
 
+#ifdef STATE_QUEUE_DUMP
+    StateQueueObserverDump  mObserverDummyDump; // default area for observer dump if not set
+    StateQueueObserverDump* mObserverDump;      // pointer to active observer dump, always non-NULL
+    StateQueueMutatorDump   mMutatorDummyDump;  // default area for mutator dump if not set
+    StateQueueMutatorDump*  mMutatorDump;       // pointer to active mutator dump, always non-NULL
+#endif
+
 };  // class StateQueue
 
 }   // namespace android