Merge "audioflinger: define ANDROID_SMP, remove conditional tracing"
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index f1b77ab..6f85527 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -52,8 +52,11 @@
      * Keep in sync with frameworks/base/media/java/android/media/AudioTrack.java NATIVE_EVENT_*.
      */
     enum event_type {
-        EVENT_MORE_DATA = 0,        // Request to write more data to PCM buffer.
-        EVENT_UNDERRUN = 1,         // PCM buffer underrun occurred.
+        EVENT_MORE_DATA = 0,        // Request to write more data to buffer.
+                                    // If this event is delivered but the callback handler
+                                    // does not want to write more data, the handler must explicitly
+                                    // ignore the event by setting frameCount to zero.
+        EVENT_UNDERRUN = 1,         // Buffer underrun occurred.
         EVENT_LOOP_END = 2,         // Sample loop end was reached; playback restarted from
                                     // loop start if loop count was not 0.
         EVENT_MARKER = 3,           // Playback head is at the specified marker position
@@ -115,14 +118,16 @@
                                       uint32_t sampleRate = 0);
 
     /* Constructs an uninitialized AudioTrack. No connection with
-     * AudioFlinger takes place.
+     * AudioFlinger takes place.  Use set() after this.
      */
                         AudioTrack();
 
     /* Creates an AudioTrack object and registers it with AudioFlinger.
      * Once created, the track needs to be started before it can be used.
-     * Unspecified values are set to the audio hardware's current
-     * values.
+     * Unspecified values are set to appropriate default values.
+     * With this constructor, the track is configured for streaming mode.
+     * Data to be rendered is supplied by write() or by the callback EVENT_MORE_DATA.
+     * Intermixing a combination of write() and non-ignored EVENT_MORE_DATA is deprecated.
      *
      * Parameters:
      *
@@ -136,10 +141,10 @@
      *                     application's contribution to the
      *                     latency of the track. The actual size selected by the AudioTrack could be
      *                     larger if the requested size is not compatible with current audio HAL
-     *                     latency.  Zero means to use a default value.
+     *                     configuration.  Zero means to use a default value.
      * flags:              See comments on audio_output_flags_t in <system/audio.h>.
      * cbf:                Callback function. If not null, this function is called periodically
-     *                     to provide new PCM data.
+     *                     to provide new data and inform of marker, position updates, etc.
      * user:               Context for use by the callback receiver.
      * notificationFrames: The callback function is called each time notificationFrames PCM
      *                     frames have been consumed from track input buffer.
@@ -159,13 +164,16 @@
                                     int notificationFrames = 0,
                                     int sessionId        = 0);
 
-    /* Creates an audio track and registers it with AudioFlinger. With this constructor,
-     * the PCM data to be rendered by AudioTrack is passed in a shared memory buffer
-     * identified by the argument sharedBuffer. This prototype is for static buffer playback.
-     * PCM data must be present in memory before the AudioTrack is started.
-     * The write() and flush() methods are not supported in this case.
+    /* Creates an audio track and registers it with AudioFlinger.
+     * With this constructor, the track is configured for static buffer mode.
+     * The format must not be 8-bit linear PCM.
+     * Data to be rendered is passed in a shared memory buffer
+     * identified by the argument sharedBuffer, which must be non-0.
+     * The memory should be initialized to the desired data before calling start().
+     * The write() method is not supported in this case.
      * It is recommended to pass a callback function to be notified of playback end by an
      * EVENT_UNDERRUN event.
+     * FIXME EVENT_MORE_DATA still occurs; it must be ignored.
      */
 
                         AudioTrack( audio_stream_type_t streamType,
@@ -184,13 +192,14 @@
      */
                         ~AudioTrack();
 
-
     /* Initialize an uninitialized AudioTrack.
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful initialization
      *  - INVALID_OPERATION: AudioTrack is already initialized
      *  - BAD_VALUE: invalid parameter (channelMask, format, sampleRate...)
      *  - NO_INIT: audio server or audio hardware not initialized
+     * If sharedBuffer is non-0, the frameCount parameter is ignored and
+     * replaced by the shared buffer's total allocated size in frame units.
      */
             status_t    set(audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT,
                             uint32_t sampleRate = 0,
@@ -205,64 +214,68 @@
                             bool threadCanCallJava = false,
                             int sessionId       = 0);
 
-
     /* Result of constructing the AudioTrack. This must be checked
      * before using any AudioTrack API (except for set()), because using
      * an uninitialized AudioTrack produces undefined results.
      * See set() method above for possible return codes.
      */
-            status_t    initCheck() const;
+            status_t    initCheck() const   { return mStatus; }
 
     /* Returns this track's estimated latency in milliseconds.
      * This includes the latency due to AudioTrack buffer size, AudioMixer (if any)
      * and audio hardware driver.
      */
-            uint32_t     latency() const;
+            uint32_t     latency() const    { return mLatency; }
 
     /* getters, see constructors and set() */
 
-            audio_stream_type_t streamType() const;
-            audio_format_t format() const;
-            uint32_t    channelCount() const;
-            uint32_t    frameCount() const;
+            audio_stream_type_t streamType() const { return mStreamType; }
+            audio_format_t format() const   { return mFormat; }
 
-    /* Return channelCount * (bit depth per channel / 8).
+    /* Return frame size in bytes, which for linear PCM is channelCount * (bit depth per channel / 8).
      * channelCount is determined from channelMask, and bit depth comes from format.
+     * For non-linear formats, the frame size is typically 1 byte.
      */
-            size_t      frameSize() const { return mFrameSize; }
+            uint32_t    channelCount() const { return mChannelCount; }
 
-            sp<IMemory>& sharedBuffer();
+            uint32_t    frameCount() const  { return mFrameCount; }
+            size_t      frameSize() const   { return mFrameSize; }
 
+    /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */
+            sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
 
     /* After it's created the track is not active. Call start() to
      * make it active. If set, the callback will start being called.
+     * If the track was previously paused, volume is ramped up over the first mix buffer.
      */
             void        start();
 
-    /* Stop a track. If set, the callback will cease being called and
+    /* Stop a track.
+     * In static buffer mode, the track is stopped immediately.
+     * In streaming mode, the callback will cease being called and
      * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
      * and will fill up buffers until the pool is exhausted.
+     * The stop does not occur immediately: any data remaining in the buffer
+     * is first drained, mixed, and output, and only then is the track marked as stopped.
      */
             void        stop();
             bool        stopped() const;
 
-    /* Flush a stopped track. All pending buffers are discarded.
-     * This function has no effect if the track is not stopped.
+    /* Flush a stopped or paused track. All previously buffered data is discarded immediately.
+     * This has the effect of draining the buffers without mixing or output.
+     * Flush is intended for streaming mode, for example before switching to non-contiguous content.
+     * This function is a no-op if the track is not stopped or paused, or uses a static buffer.
      */
             void        flush();
 
-    /* Pause a track. If set, the callback will cease being called and
+    /* Pause a track. After pause, the callback will cease being called and
      * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
      * and will fill up buffers until the pool is exhausted.
+     * Volume is ramped down over the next mix buffer following the pause request,
+     * and then the track is marked as paused.  It can be resumed with ramp up by start().
      */
             void        pause();
 
-    /* Mute or unmute this track.
-     * While muted, the callback, if set, is still called.
-     */
-            void        mute(bool);
-            bool        muted() const;
-
     /* Set volume for this track, mostly used for games' sound effects
      * left and right volumes. Levels must be >= 0.0 and <= 1.0.
      * This is the older API.  New applications should use setVolume(float) when possible.
@@ -288,6 +301,7 @@
             uint32_t    getSampleRate() const;
 
     /* Enables looping and sets the start and end points of looping.
+     * Only supported for static buffer mode.
      *
      * Parameters:
      *
@@ -303,13 +317,15 @@
 
     /* Sets marker position. When playback reaches the number of frames specified, a callback with
      * event type EVENT_MARKER is called. Calling setMarkerPosition with marker == 0 cancels marker
-     * notification callback.
+     * notification callback.  To set a marker at a position which would compute as 0,
+     * a workaround is to the set the marker at a nearby position such as -1 or 1.
      * If the AudioTrack has been opened with no callback function associated, the operation will
      * fail.
      *
      * Parameters:
      *
-     * marker:   marker position expressed in frames.
+     * marker:   marker position expressed in wrapping (overflow) frame units,
+     *           like the return value of getPosition().
      *
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation
@@ -318,13 +334,13 @@
             status_t    setMarkerPosition(uint32_t marker);
             status_t    getMarkerPosition(uint32_t *marker) const;
 
-
     /* Sets position update period. Every time the number of frames specified has been played,
      * a callback with event type EVENT_NEW_POS is called.
      * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
      * callback.
      * If the AudioTrack has been opened with no callback function associated, the operation will
      * fail.
+     * Extremely small values may be rounded up to a value the implementation can support.
      *
      * Parameters:
      *
@@ -352,20 +368,26 @@
      *
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation
-     *  - INVALID_OPERATION: the AudioTrack is not stopped.
+     *  - INVALID_OPERATION: the AudioTrack is not stopped or paused, or is streaming mode.
      *  - BAD_VALUE: The specified position is beyond the number of frames present in AudioTrack
      *               buffer
      */
             status_t    setPosition(uint32_t position);
+
+    /* Return the total number of frames played since playback start.
+     * The counter will wrap (overflow) periodically, e.g. every ~27 hours at 44.1 kHz.
+     * It is reset to zero by flush(), reload(), and stop().
+     */
             status_t    getPosition(uint32_t *position);
 
     /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids
      * rewriting the buffer before restarting playback after a stop.
      * This method must be called with the AudioTrack in paused or stopped state.
+     * Not allowed in streaming mode.
      *
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation
-     *  - INVALID_OPERATION: the AudioTrack is not stopped.
+     *  - INVALID_OPERATION: the AudioTrack is not stopped or paused, or is streaming mode.
      */
             status_t    reload();
 
@@ -387,7 +409,7 @@
      * Returned value:
      *  AudioTrack session ID.
      */
-            int    getSessionId() const;
+            int    getSessionId() const { return mSessionId; }
 
     /* Attach track auxiliary output to specified effect. Use effectId = 0
      * to detach track from effect.
@@ -413,6 +435,9 @@
      * or return WOULD_BLOCK depending on the value of the "blocking"
      * parameter.
      *
+     * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications,
+     * which should use write() or callback EVENT_MORE_DATA instead.
+     *
      * Interpretation of waitCount:
      *  +n  limits wait time to n * WAIT_PERIOD_MS,
      *  -1  causes an (almost) infinite wait time,
@@ -450,6 +475,7 @@
      *      STOPPED             AudioTrack was stopped during the write
      *      NO_MORE_BUFFERS     when obtainBuffer() returns same
      *      or any other error code returned by IAudioTrack::start() or restoreTrack_l().
+     * Not supported for static buffer mode.
      */
             ssize_t     write(const void* buffer, size_t size);
 
@@ -497,7 +523,10 @@
                                  audio_output_flags_t flags,
                                  const sp<IMemory>& sharedBuffer,
                                  audio_io_handle_t output);
+
+            // can only be called when !mActive
             void flush_l();
+
             status_t setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount);
             audio_io_handle_t getOutput_l();
             status_t restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart);
@@ -523,9 +552,7 @@
 
     audio_format_t          mFormat;                // as requested by client, not forced to 16-bit
     audio_stream_type_t     mStreamType;
-    uint8_t                 mChannelCount;
-    uint8_t                 mMuted;
-    uint8_t                 mReserved;
+    uint32_t                mChannelCount;
     audio_channel_mask_t    mChannelMask;
 
                 // mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data.
@@ -550,7 +577,7 @@
     sp<IMemory>             mSharedBuffer;
     int                     mLoopCount;
     uint32_t                mRemainingFrames;
-    uint32_t                mMarkerPosition;        // in frames
+    uint32_t                mMarkerPosition;        // in wrapping (overflow) frame units
     bool                    mMarkerReached;
     uint32_t                mNewPosition;           // in frames
     uint32_t                mUpdatePeriod;          // in frames
diff --git a/include/media/IAudioTrack.h b/include/media/IAudioTrack.h
index 9e0e389..144be0e 100644
--- a/include/media/IAudioTrack.h
+++ b/include/media/IAudioTrack.h
@@ -54,11 +54,6 @@
      */
     virtual void        flush() = 0;
 
-    /* Mute or unmute this track.
-     * While muted, the callback, if set, is still called.
-     */
-    virtual void        mute(bool) = 0;
-
     /* Pause a track. If set, the callback will cease being called and
      * obtainBuffer will return an error. Buffers that are already released
      * will continue to be processed, unless/until flush() is called.
diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk
index f2b6441..a35d562 100644
--- a/media/libmedia/Android.mk
+++ b/media/libmedia/Android.mk
@@ -13,6 +13,7 @@
 
 LOCAL_SRC_FILES:= \
     AudioTrack.cpp \
+    AudioTrackShared.cpp \
     IAudioFlinger.cpp \
     IAudioFlingerClient.cpp \
     IAudioTrack.cpp \
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index e40895a..1d87ff8 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -138,6 +138,11 @@
       mPreviousPriority(ANDROID_PRIORITY_NORMAL),
       mPreviousSchedulingGroup(SP_DEFAULT)
 {
+    if (sharedBuffer == 0) {
+        ALOGE("sharedBuffer must be non-0");
+        mStatus = BAD_VALUE;
+        return;
+    }
     mStatus = set(streamType, sampleRate, format, channelMask,
             0 /*frameCount*/, flags, cbf, user, notificationFrames,
             sharedBuffer, false /*threadCanCallJava*/, sessionId);
@@ -304,7 +309,6 @@
     }
 
     mSharedBuffer = sharedBuffer;
-    mMuted = false;
     mActive = false;
     mUserData = user;
     mLoopCount = 0;
@@ -317,43 +321,6 @@
     return NO_ERROR;
 }
 
-status_t AudioTrack::initCheck() const
-{
-    return mStatus;
-}
-
-// -------------------------------------------------------------------------
-
-uint32_t AudioTrack::latency() const
-{
-    return mLatency;
-}
-
-audio_stream_type_t AudioTrack::streamType() const
-{
-    return mStreamType;
-}
-
-audio_format_t AudioTrack::format() const
-{
-    return mFormat;
-}
-
-uint32_t AudioTrack::channelCount() const
-{
-    return mChannelCount;
-}
-
-size_t AudioTrack::frameCount() const
-{
-    return mFrameCount;
-}
-
-sp<IMemory>& AudioTrack::sharedBuffer()
-{
-    return mSharedBuffer;
-}
-
 // -------------------------------------------------------------------------
 
 void AudioTrack::start()
@@ -435,6 +402,7 @@
         mMarkerReached = false;
         // Force flush if a shared buffer is used otherwise audioflinger
         // will not stop before end of buffer is reached.
+        // It may be needed to make sure that we stop playback, likely in case looping is on.
         if (mSharedBuffer != 0) {
             flush_l();
         }
@@ -457,26 +425,26 @@
 void AudioTrack::flush()
 {
     AutoMutex lock(mLock);
-    flush_l();
+    if (!mActive && mSharedBuffer == 0) {
+        flush_l();
+    }
 }
 
-// must be called with mLock held
 void AudioTrack::flush_l()
 {
     ALOGV("flush");
+    ALOG_ASSERT(!mActive);
 
     // clear playback marker and periodic update counter
     mMarkerPosition = 0;
     mMarkerReached = false;
     mUpdatePeriod = 0;
 
-    if (!mActive) {
-        mFlushed = true;
-        mAudioTrack->flush();
-        // Release AudioTrack callback thread in case it was waiting for new buffers
-        // in AudioTrack::obtainBuffer()
-        mCblk->cv.signal();
-    }
+    mFlushed = true;
+    mAudioTrack->flush();
+    // Release AudioTrack callback thread in case it was waiting for new buffers
+    // in AudioTrack::obtainBuffer()
+    mCblk->cv.signal();
 }
 
 void AudioTrack::pause()
@@ -490,17 +458,6 @@
     }
 }
 
-void AudioTrack::mute(bool e)
-{
-    mAudioTrack->mute(e);
-    mMuted = e;
-}
-
-bool AudioTrack::muted() const
-{
-    return mMuted;
-}
-
 status_t AudioTrack::setVolume(float left, float right)
 {
     if (left < 0.0f || left > 1.0f || right < 0.0f || right > 1.0f) {
@@ -583,6 +540,10 @@
 // must be called with mLock held
 status_t AudioTrack::setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount)
 {
+    if (mSharedBuffer == 0 || mIsTimed) {
+        return INVALID_OPERATION;
+    }
+
     audio_track_cblk_t* cblk = mCblk;
 
     Mutex::Autolock _l(cblk->lock);
@@ -595,10 +556,6 @@
         return NO_ERROR;
     }
 
-    if (mIsTimed) {
-        return INVALID_OPERATION;
-    }
-
     if (loopStart >= loopEnd ||
         loopEnd - loopStart > mFrameCount ||
         cblk->server > loopStart) {
@@ -672,7 +629,7 @@
 
 status_t AudioTrack::setPosition(uint32_t position)
 {
-    if (mIsTimed) {
+    if (mSharedBuffer == 0 || mIsTimed) {
         return INVALID_OPERATION;
     }
 
@@ -708,6 +665,10 @@
 
 status_t AudioTrack::reload()
 {
+    if (mSharedBuffer == 0 || mIsTimed) {
+        return INVALID_OPERATION;
+    }
+
     AutoMutex lock(mLock);
 
     if (!stopped_l()) {
@@ -735,11 +696,6 @@
             mCblk->sampleRate, mFormat, mChannelMask, mFlags);
 }
 
-int AudioTrack::getSessionId() const
-{
-    return mSessionId;
-}
-
 status_t AudioTrack::attachAuxEffect(int effectId)
 {
     ALOGV("attachAuxEffect(%d)", effectId);
@@ -1089,10 +1045,7 @@
 ssize_t AudioTrack::write(const void* buffer, size_t userSize)
 {
 
-    if (mSharedBuffer != 0) {
-        return INVALID_OPERATION;
-    }
-    if (mIsTimed) {
+    if (mSharedBuffer != 0 || mIsTimed) {
         return INVALID_OPERATION;
     }
 
@@ -1471,8 +1424,8 @@
     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), muted(%d)\n",
-            (cblk == 0) ? 0 : cblk->sampleRate, mStatus, mMuted);
+    snprintf(buffer, 255, "  sample rate(%u), status(%d)\n",
+            (cblk == 0) ? 0 : cblk->sampleRate, mStatus);
     result.append(buffer);
     snprintf(buffer, 255, "  active(%d), latency (%d)\n", mActive, mLatency);
     result.append(buffer);
@@ -1529,180 +1482,4 @@
     }
 }
 
-// =========================================================================
-
-
-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)
-{
-}
-
-uint32_t audio_track_cblk_t::stepUser(size_t stepCount, size_t frameCount, bool isOut)
-{
-    ALOGV("stepuser %08x %08x %d", user, server, stepCount);
-
-    uint32_t u = user;
-    u += stepCount;
-    // Ensure that user is never ahead of server for AudioRecord
-    if (isOut) {
-        // If stepServer() has been called once, switch to normal obtainBuffer() timeout period
-        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) {
-            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
-        }
-    } else if (u > server) {
-        ALOGW("stepUser occurred after track reset");
-        u = server;
-    }
-
-    if (u >= frameCount) {
-        // common case, user didn't just wrap
-        if (u - frameCount >= userBase ) {
-            userBase += frameCount;
-        }
-    } else if (u >= userBase + frameCount) {
-        // user just wrapped
-        userBase += frameCount;
-    }
-
-    user = u;
-
-    // Clear flow control error condition as new data has been written/read to/from buffer.
-    if (flags & CBLK_UNDERRUN) {
-        android_atomic_and(~CBLK_UNDERRUN, &flags);
-    }
-
-    return u;
-}
-
-bool audio_track_cblk_t::stepServer(size_t stepCount, size_t frameCount, bool isOut)
-{
-    ALOGV("stepserver %08x %08x %d", user, server, stepCount);
-
-    if (!tryLock()) {
-        ALOGW("stepServer() could not lock cblk");
-        return false;
-    }
-
-    uint32_t s = server;
-    bool flushed = (s == user);
-
-    s += stepCount;
-    if (isOut) {
-        // Mark that we have read the first buffer so that next time stepUser() is called
-        // we switch to normal obtainBuffer() timeout period
-        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
-            bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1;
-        }
-        // It is possible that we receive a flush()
-        // while the mixer is processing a block: in this case,
-        // stepServer() is called After the flush() has reset u & s and
-        // we have s > u
-        if (flushed) {
-            ALOGW("stepServer occurred after track reset");
-            s = user;
-        }
-    }
-
-    if (s >= loopEnd) {
-        ALOGW_IF(s > loopEnd, "stepServer: s %u > loopEnd %u", s, loopEnd);
-        s = loopStart;
-        if (--loopCount == 0) {
-            loopEnd = UINT_MAX;
-            loopStart = UINT_MAX;
-        }
-    }
-
-    if (s >= frameCount) {
-        // common case, server didn't just wrap
-        if (s - frameCount >= serverBase ) {
-            serverBase += frameCount;
-        }
-    } else if (s >= serverBase + frameCount) {
-        // server just wrapped
-        serverBase += frameCount;
-    }
-
-    server = s;
-
-    if (!(flags & CBLK_INVALID)) {
-        cv.signal();
-    }
-    lock.unlock();
-    return true;
-}
-
-void* audio_track_cblk_t::buffer(void *buffers, size_t frameSize, uint32_t offset) const
-{
-    return (int8_t *)buffers + (offset - userBase) * frameSize;
-}
-
-uint32_t audio_track_cblk_t::framesAvailable(size_t frameCount, bool isOut)
-{
-    Mutex::Autolock _l(lock);
-    return framesAvailable_l(frameCount, isOut);
-}
-
-uint32_t audio_track_cblk_t::framesAvailable_l(size_t frameCount, bool isOut)
-{
-    uint32_t u = user;
-    uint32_t s = server;
-
-    if (isOut) {
-        uint32_t limit = (s < loopStart) ? s : loopStart;
-        return limit + frameCount - u;
-    } else {
-        return frameCount + u - s;
-    }
-}
-
-uint32_t audio_track_cblk_t::framesReady(bool isOut)
-{
-    uint32_t u = user;
-    uint32_t s = server;
-
-    if (isOut) {
-        if (u < loopEnd) {
-            return u - s;
-        } else {
-            // do not block on mutex shared with client on AudioFlinger side
-            if (!tryLock()) {
-                ALOGW("framesReady() could not lock cblk");
-                return 0;
-            }
-            uint32_t frames = UINT_MAX;
-            if (loopCount >= 0) {
-                frames = (loopEnd - loopStart)*loopCount + u - s;
-            }
-            lock.unlock();
-            return frames;
-        }
-    } else {
-        return s - u;
-    }
-}
-
-bool audio_track_cblk_t::tryLock()
-{
-    // the code below simulates lock-with-timeout
-    // we MUST do this to protect the AudioFlinger server
-    // as this lock is shared with the client.
-    status_t err;
-
-    err = lock.tryLock();
-    if (err == -EBUSY) { // just wait a bit
-        usleep(1000);
-        err = lock.tryLock();
-    }
-    if (err != NO_ERROR) {
-        // probably, the client just died.
-        return false;
-    }
-    return true;
-}
-
-// -------------------------------------------------------------------------
-
 }; // namespace android
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
new file mode 100644
index 0000000..bee13c8
--- /dev/null
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AudioTrackShared"
+//#define LOG_NDEBUG 0
+
+#include <private/media/AudioTrackShared.h>
+#include <utils/Log.h>
+
+namespace android {
+
+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)
+{
+}
+
+uint32_t audio_track_cblk_t::stepUser(size_t stepCount, size_t frameCount, bool isOut)
+{
+    ALOGV("stepuser %08x %08x %d", user, server, stepCount);
+
+    uint32_t u = user;
+    u += stepCount;
+    // Ensure that user is never ahead of server for AudioRecord
+    if (isOut) {
+        // If stepServer() has been called once, switch to normal obtainBuffer() timeout period
+        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS-1) {
+            bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
+        }
+    } else if (u > server) {
+        ALOGW("stepUser occurred after track reset");
+        u = server;
+    }
+
+    if (u >= frameCount) {
+        // common case, user didn't just wrap
+        if (u - frameCount >= userBase ) {
+            userBase += frameCount;
+        }
+    } else if (u >= userBase + frameCount) {
+        // user just wrapped
+        userBase += frameCount;
+    }
+
+    user = u;
+
+    // Clear flow control error condition as new data has been written/read to/from buffer.
+    if (flags & CBLK_UNDERRUN) {
+        android_atomic_and(~CBLK_UNDERRUN, &flags);
+    }
+
+    return u;
+}
+
+bool audio_track_cblk_t::stepServer(size_t stepCount, size_t frameCount, bool isOut)
+{
+    ALOGV("stepserver %08x %08x %d", user, server, stepCount);
+
+    if (!tryLock()) {
+        ALOGW("stepServer() could not lock cblk");
+        return false;
+    }
+
+    uint32_t s = server;
+    bool flushed = (s == user);
+
+    s += stepCount;
+    if (isOut) {
+        // Mark that we have read the first buffer so that next time stepUser() is called
+        // we switch to normal obtainBuffer() timeout period
+        if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
+            bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1;
+        }
+        // It is possible that we receive a flush()
+        // while the mixer is processing a block: in this case,
+        // stepServer() is called After the flush() has reset u & s and
+        // we have s > u
+        if (flushed) {
+            ALOGW("stepServer occurred after track reset");
+            s = user;
+        }
+    }
+
+    if (s >= loopEnd) {
+        ALOGW_IF(s > loopEnd, "stepServer: s %u > loopEnd %u", s, loopEnd);
+        s = loopStart;
+        if (--loopCount == 0) {
+            loopEnd = UINT_MAX;
+            loopStart = UINT_MAX;
+        }
+    }
+
+    if (s >= frameCount) {
+        // common case, server didn't just wrap
+        if (s - frameCount >= serverBase ) {
+            serverBase += frameCount;
+        }
+    } else if (s >= serverBase + frameCount) {
+        // server just wrapped
+        serverBase += frameCount;
+    }
+
+    server = s;
+
+    if (!(flags & CBLK_INVALID)) {
+        cv.signal();
+    }
+    lock.unlock();
+    return true;
+}
+
+void* audio_track_cblk_t::buffer(void *buffers, size_t frameSize, uint32_t offset) const
+{
+    return (int8_t *)buffers + (offset - userBase) * frameSize;
+}
+
+uint32_t audio_track_cblk_t::framesAvailable(size_t frameCount, bool isOut)
+{
+    Mutex::Autolock _l(lock);
+    return framesAvailable_l(frameCount, isOut);
+}
+
+uint32_t audio_track_cblk_t::framesAvailable_l(size_t frameCount, bool isOut)
+{
+    uint32_t u = user;
+    uint32_t s = server;
+
+    if (isOut) {
+        uint32_t limit = (s < loopStart) ? s : loopStart;
+        return limit + frameCount - u;
+    } else {
+        return frameCount + u - s;
+    }
+}
+
+uint32_t audio_track_cblk_t::framesReady(bool isOut)
+{
+    uint32_t u = user;
+    uint32_t s = server;
+
+    if (isOut) {
+        if (u < loopEnd) {
+            return u - s;
+        } else {
+            // do not block on mutex shared with client on AudioFlinger side
+            if (!tryLock()) {
+                ALOGW("framesReady() could not lock cblk");
+                return 0;
+            }
+            uint32_t frames = UINT_MAX;
+            if (loopCount >= 0) {
+                frames = (loopEnd - loopStart)*loopCount + u - s;
+            }
+            lock.unlock();
+            return frames;
+        }
+    } else {
+        return s - u;
+    }
+}
+
+bool audio_track_cblk_t::tryLock()
+{
+    // the code below simulates lock-with-timeout
+    // we MUST do this to protect the AudioFlinger server
+    // as this lock is shared with the client.
+    status_t err;
+
+    err = lock.tryLock();
+    if (err == -EBUSY) { // just wait a bit
+        usleep(1000);
+        err = lock.tryLock();
+    }
+    if (err != NO_ERROR) {
+        // probably, the client just died.
+        return false;
+    }
+    return true;
+}
+
+}   // namespace android
diff --git a/media/libmedia/IAudioFlinger.cpp b/media/libmedia/IAudioFlinger.cpp
index a010bb6..c5fbbf0 100644
--- a/media/libmedia/IAudioFlinger.cpp
+++ b/media/libmedia/IAudioFlinger.cpp
@@ -32,7 +32,7 @@
     CREATE_TRACK = IBinder::FIRST_CALL_TRANSACTION,
     OPEN_RECORD,
     SAMPLE_RATE,
-    CHANNEL_COUNT,  // obsolete
+    RESERVED,   // obsolete, was CHANNEL_COUNT
     FORMAT,
     FRAME_COUNT,
     LATENCY,
@@ -191,17 +191,6 @@
         return reply.readInt32();
     }
 
-#if 0
-    virtual int channelCount(audio_io_handle_t output) const
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
-        data.writeInt32((int32_t) output);
-        remote()->transact(CHANNEL_COUNT, data, &reply);
-        return reply.readInt32();
-    }
-#endif
-
     virtual audio_format_t format(audio_io_handle_t output) const
     {
         Parcel data, reply;
@@ -768,13 +757,6 @@
             reply->writeInt32( sampleRate((audio_io_handle_t) data.readInt32()) );
             return NO_ERROR;
         } break;
-#if 0
-        case CHANNEL_COUNT: {
-            CHECK_INTERFACE(IAudioFlinger, data, reply);
-            reply->writeInt32( channelCount((audio_io_handle_t) data.readInt32()) );
-            return NO_ERROR;
-        } break;
-#endif
         case FORMAT: {
             CHECK_INTERFACE(IAudioFlinger, data, reply);
             reply->writeInt32( format((audio_io_handle_t) data.readInt32()) );
diff --git a/media/libmedia/IAudioTrack.cpp b/media/libmedia/IAudioTrack.cpp
index 867d1a5..e92f8aa 100644
--- a/media/libmedia/IAudioTrack.cpp
+++ b/media/libmedia/IAudioTrack.cpp
@@ -33,7 +33,7 @@
     START,
     STOP,
     FLUSH,
-    MUTE,
+    RESERVED, // was MUTE
     PAUSE,
     ATTACH_AUX_EFFECT,
     ALLOCATE_TIMED_BUFFER,
@@ -88,14 +88,6 @@
         remote()->transact(FLUSH, data, &reply);
     }
 
-    virtual void mute(bool e)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
-        data.writeInt32(e);
-        remote()->transact(MUTE, data, &reply);
-    }
-
     virtual void pause()
     {
         Parcel data, reply;
@@ -192,11 +184,6 @@
             flush();
             return NO_ERROR;
         } break;
-        case MUTE: {
-            CHECK_INTERFACE(IAudioTrack, data, reply);
-            mute( data.readInt32() );
-            return NO_ERROR;
-        } break;
         case PAUSE: {
             CHECK_INTERFACE(IAudioTrack, data, reply);
             pause();
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index b2afec7..1a62f9d 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1424,18 +1424,15 @@
             if (mFileMetaData != NULL) {
                 ALOGV("chunk_data_size = %lld and data_offset = %lld",
                         chunk_data_size, data_offset);
-                uint8_t *buffer = new uint8_t[chunk_data_size + 1];
+                sp<ABuffer> buffer = new ABuffer(chunk_data_size + 1);
                 if (mDataSource->readAt(
-                    data_offset, buffer, chunk_data_size) != (ssize_t)chunk_data_size) {
-                    delete[] buffer;
-                    buffer = NULL;
-
+                    data_offset, buffer->data(), chunk_data_size) != (ssize_t)chunk_data_size) {
                     return ERROR_IO;
                 }
                 const int kSkipBytesOfDataBox = 16;
                 mFileMetaData->setData(
                     kKeyAlbumArt, MetaData::TYPE_NONE,
-                    buffer + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
+                    buffer->data() + kSkipBytesOfDataBox, chunk_data_size - kSkipBytesOfDataBox);
             }
 
             *offset += chunk_size;
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 46a8e0f..6d3f0a1 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -385,7 +385,6 @@
         virtual status_t    start();
         virtual void        stop();
         virtual void        flush();
-        virtual void        mute(bool);
         virtual void        pause();
         virtual status_t    attachAuxEffect(int effectId);
         virtual status_t    allocateTimedBuffer(size_t size,
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index b898924..37e39a0 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -44,7 +44,6 @@
 
             void        flush();
             void        destroy();
-            void        mute(bool);
             int         name() const { return mName; }
 
             audio_stream_type_t streamType() const {
@@ -78,7 +77,6 @@
 
     virtual size_t framesReady() const;
 
-    bool isMuted() const { return mMute; }
     bool isPausing() const {
         return mState == PAUSING;
     }
@@ -111,11 +109,6 @@
 
 protected:
 
-    // written by Track::mute() called by binder thread(s), without a mutex or barrier.
-    // read by Track::isMuted() called by playback thread, also without a mutex or barrier.
-    // The lack of mutex or barrier is safe because the mute status is only used by itself.
-    bool                mMute;
-
     // FILLED state is used for suppressing volume ramp at begin of playing
     enum {FS_INVALID, FS_FILLING, FS_FILLED, FS_ACTIVE};
     mutable uint8_t     mFillingUpStatus;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index fd64395..a285e6c 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2544,8 +2544,7 @@
                 }
                 // cache the combined master volume and stream type volume for fast mixer; this
                 // lacks any synchronization or barrier so VolumeProvider may read a stale value
-                track->mCachedVolume = track->isMuted() ?
-                        0 : masterVolume * mStreamTypes[track->streamType()].volume;
+                track->mCachedVolume = masterVolume * mStreamTypes[track->streamType()].volume;
                 ++fastTracks;
             } else {
                 // was it previously active?
@@ -2637,8 +2636,7 @@
 
             // compute volume for this track
             uint32_t vl, vr, va;
-            if (track->isMuted() || track->isPausing() ||
-                mStreamTypes[track->streamType()].mute) {
+            if (track->isPausing() || mStreamTypes[track->streamType()].mute) {
                 vl = vr = va = 0;
                 if (track->isPausing()) {
                     track->setPaused();
@@ -3139,8 +3137,7 @@
 
             // compute volume for this track
             float left, right;
-            if (track->isMuted() || mMasterMute || track->isPausing() ||
-                mStreamTypes[track->streamType()].mute) {
+            if (mMasterMute || track->isPausing() || mStreamTypes[track->streamType()].mute) {
                 left = right = 0;
                 if (track->isPausing()) {
                     track->setPaused();
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 2c6ba8b..e8ca5ee 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -248,10 +248,6 @@
     mTrack->flush();
 }
 
-void AudioFlinger::TrackHandle::mute(bool e) {
-    mTrack->mute(e);
-}
-
 void AudioFlinger::TrackHandle::pause() {
     mTrack->pause();
 }
@@ -315,7 +311,6 @@
             IAudioFlinger::track_flags_t flags)
     :   TrackBase(thread, client, sampleRate, format, channelMask, frameCount, sharedBuffer,
             sessionId),
-    mMute(false),
     mFillingUpStatus(FS_INVALID),
     // mRetryCount initialized later when needed
     mSharedBuffer(sharedBuffer),
@@ -397,7 +392,7 @@
 
 /*static*/ void AudioFlinger::PlaybackThread::Track::appendDumpHeader(String8& result)
 {
-    result.append("   Name Client Type Fmt Chn mask   Session StpCnt fCount S M F SRate  "
+    result.append("   Name Client Type Fmt Chn mask   Session StpCnt fCount S F SRate  "
                   "L dB  R dB    Server      User     Main buf    Aux Buf  Flags Underruns\n");
 }
 
@@ -461,7 +456,7 @@
         nowInUnderrun = '?';
         break;
     }
-    snprintf(&buffer[7], size-7, " %6d %4u %3u 0x%08x %7u %6u %6u %1c %1d %1d %5u %5.2g %5.2g  "
+    snprintf(&buffer[7], size-7, " %6d %4u %3u 0x%08x %7u %6u %6u %1c %1d %5u %5.2g %5.2g  "
             "0x%08x 0x%08x 0x%08x 0x%08x %#5x %9u%c\n",
             (mClient == 0) ? getpid_cached : mClient->pid(),
             mStreamType,
@@ -471,7 +466,6 @@
             mStepCount,
             mFrameCount,
             stateChar,
-            mMute,
             mFillingUpStatus,
             mCblk->sampleRate,
             20.0 * log10((vlr & 0xFFFF) / 4096.0),
@@ -708,11 +702,6 @@
     }
 }
 
-void AudioFlinger::PlaybackThread::Track::mute(bool muted)
-{
-    mMute = muted;
-}
-
 status_t AudioFlinger::PlaybackThread::Track::attachAuxEffect(int EffectId)
 {
     status_t status = DEAD_OBJECT;