New control block for AudioTrack and AudioRecord

Main differences between old and new control block:
 - removes the mutex, which was a potential source of priority inversion
 - circular indices into shared buffer, which is now always a power-of-2 size

Change-Id: I4e9b7fa99858b488ac98a441fa70e31dbba1b865
diff --git a/include/media/AudioBufferProvider.h b/include/media/AudioBufferProvider.h
index 43e4de7..ef392f0 100644
--- a/include/media/AudioBufferProvider.h
+++ b/include/media/AudioBufferProvider.h
@@ -26,6 +26,8 @@
 {
 public:
 
+    // FIXME merge with AudioTrackShared::Buffer, AudioTrack::Buffer, and AudioRecord::Buffer
+    //       and rename getNextBuffer() to obtainBuffer()
     struct Buffer {
         Buffer() : raw(NULL), frameCount(0) { }
         union {
@@ -44,6 +46,19 @@
     // pts is the local time when the next sample yielded by getNextBuffer
     // will be rendered.
     // Pass kInvalidPTS if the PTS is unknown or not applicable.
+    // On entry:
+    //  buffer              != NULL
+    //  buffer->raw         unused
+    //  buffer->frameCount  maximum number of desired frames
+    // On successful return:
+    //  status              NO_ERROR
+    //  buffer->raw         non-NULL pointer to buffer->frameCount contiguous available frames
+    //  buffer->frameCount  number of contiguous available frames at buffer->raw,
+    //                      0 < buffer->frameCount <= entry value
+    // On error return:
+    //  status              != NO_ERROR
+    //  buffer->raw         NULL
+    //  buffer->frameCount  0
     virtual status_t getNextBuffer(Buffer* buffer, int64_t pts = kInvalidPTS) = 0;
 
     virtual void releaseBuffer(Buffer* buffer) = 0;
diff --git a/include/media/AudioRecord.h b/include/media/AudioRecord.h
index 38c6548..81be803 100644
--- a/include/media/AudioRecord.h
+++ b/include/media/AudioRecord.h
@@ -14,26 +14,24 @@
  * limitations under the License.
  */
 
-#ifndef AUDIORECORD_H_
-#define AUDIORECORD_H_
+#ifndef ANDROID_AUDIORECORD_H
+#define ANDROID_AUDIORECORD_H
 
-#include <binder/IMemory.h>
 #include <cutils/sched_policy.h>
 #include <media/AudioSystem.h>
 #include <media/IAudioRecord.h>
-#include <system/audio.h>
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
 #include <utils/threads.h>
 
 namespace android {
 
+// ----------------------------------------------------------------------------
+
 class audio_track_cblk_t;
 class AudioRecordClientProxy;
 
 // ----------------------------------------------------------------------------
 
-class AudioRecord : virtual public RefBase
+class AudioRecord : public RefBase
 {
 public:
 
@@ -49,6 +47,8 @@
                                     // (See setMarkerPosition()).
         EVENT_NEW_POS = 3,          // Record head is at a new position
                                     // (See setPositionUpdatePeriod()).
+        EVENT_NEW_IAUDIORECORD = 4, // IAudioRecord was re-created, either due to re-routing and
+                                    // voluntary invalidation by mediaserver, or mediaserver crash.
     };
 
     /* Client should declare Buffer on the stack and pass address to obtainBuffer()
@@ -58,11 +58,16 @@
     class Buffer
     {
     public:
+        // FIXME use m prefix
         size_t      frameCount;     // number of sample frames corresponding to size;
                                     // on input it is the number of frames available,
                                     // on output is the number of frames actually drained
 
-        size_t      size;           // total size in bytes == frameCount * frameSize
+        size_t      size;           // input/output in bytes == frameCount * frameSize
+                                    // FIXME this is redundant with respect to frameCount,
+                                    // and TRANSFER_OBTAIN mode is broken for 8-bit data
+                                    // since we don't define the frame format
+
         union {
             void*       raw;
             short*      i16;        // signed 16-bit
@@ -84,6 +89,7 @@
      *          - EVENT_OVERRUN: unused.
      *          - EVENT_MARKER: pointer to const uint32_t containing the marker position in frames.
      *          - EVENT_NEW_POS: pointer to const uint32_t containing the new position in frames.
+     *          - EVENT_NEW_IAUDIORECORD: unused.
      */
 
     typedef void (*callback_t)(int event, void* user, void *info);
@@ -101,20 +107,28 @@
                                       audio_format_t format,
                                       audio_channel_mask_t channelMask);
 
+    /* How data is transferred from AudioRecord
+     */
+    enum transfer_type {
+        TRANSFER_DEFAULT,   // not specified explicitly; determine from other parameters
+        TRANSFER_CALLBACK,  // callback EVENT_MORE_DATA
+        TRANSFER_OBTAIN,    // FIXME deprecated: call obtainBuffer() and releaseBuffer()
+        TRANSFER_SYNC,      // synchronous read()
+    };
+
     /* Constructs an uninitialized AudioRecord. No connection with
-     * AudioFlinger takes place.
+     * AudioFlinger takes place.  Use set() after this.
      */
                         AudioRecord();
 
     /* Creates an AudioRecord 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.
      *
      * Parameters:
      *
-     * inputSource:        Select the audio input to record to (e.g. AUDIO_SOURCE_DEFAULT).
-     * sampleRate:         Track sampling rate in Hz.
+     * inputSource:        Select the audio input to record from (e.g. AUDIO_SOURCE_DEFAULT).
+     * sampleRate:         Data sink sampling rate in Hz.
      * format:             Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
      *                     16 bits per sample).
      * channelMask:        Channel mask.
@@ -124,11 +138,13 @@
      *                     be larger if the requested size is not compatible with current audio HAL
      *                     latency.  Zero means to use a default value.
      * cbf:                Callback function. If not null, this function is called periodically
-     *                     to consume new PCM data.
+     *                     to consume new PCM 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 are ready in record track output buffer.
      * sessionId:          Not yet supported.
+     * transferType:       How data is transferred from AudioRecord.
+     * threadCanCallJava:  Not present in parameter list, and so is fixed at false.
      */
 
                         AudioRecord(audio_source_t inputSource,
@@ -139,22 +155,26 @@
                                     callback_t cbf = NULL,
                                     void* user = NULL,
                                     int notificationFrames = 0,
-                                    int sessionId = 0);
-
+                                    int sessionId = 0,
+                                    transfer_type transferType = TRANSFER_DEFAULT);
 
     /* Terminates the AudioRecord and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioRecord.
      */
                         ~AudioRecord();
 
-
-    /* Initialize an uninitialized AudioRecord.
+    /* Initialize an AudioRecord that was created using the AudioRecord() constructor.
+     * Don't call set() more than once, or after an AudioRecord() constructor that takes parameters.
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful intialization
-     *  - INVALID_OPERATION: AudioRecord is already intitialized or record device is already in use
+     *  - INVALID_OPERATION: AudioRecord is already initialized or record device is already in use
      *  - BAD_VALUE: invalid parameter (channels, format, sampleRate...)
      *  - NO_INIT: audio server or audio hardware not initialized
      *  - PERMISSION_DENIED: recording is not allowed for the requesting process
+     *
+     * Parameters not listed in the AudioRecord constructors above:
+     *
+     * threadCanCallJava:  Whether callbacks are made from an attached thread and thus can call JNI.
      */
             status_t    set(audio_source_t inputSource = AUDIO_SOURCE_DEFAULT,
                             uint32_t sampleRate = 0,
@@ -165,30 +185,29 @@
                             void* user = NULL,
                             int notificationFrames = 0,
                             bool threadCanCallJava = false,
-                            int sessionId = 0);
-
+                            int sessionId = 0,
+                            transfer_type transferType = TRANSFER_DEFAULT);
 
     /* Result of constructing the AudioRecord. This must be checked
      * before using any AudioRecord API (except for set()), because using
      * an uninitialized AudioRecord 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 AudioRecord buffer size,
      * and audio hardware driver.
      */
-            uint32_t     latency() const;
+            uint32_t    latency() const     { return mLatency; }
 
    /* getters, see constructor and set() */
 
-            audio_format_t format() const;
-            uint32_t    channelCount() const;
-            size_t      frameCount() const;
-            size_t      frameSize() const { return mFrameSize; }
-            audio_source_t inputSource() const;
-
+            audio_format_t format() const   { return mFormat; }
+            uint32_t    channelCount() const    { return mChannelCount; }
+            size_t      frameCount() const  { return mFrameCount; }
+            size_t      frameSize() const   { return mFrameSize; }
+            audio_source_t inputSource() const  { return mInputSource; }
 
     /* After it's created the track is not active. Call start() to
      * make it active. If set, the callback will start being called.
@@ -198,26 +217,29 @@
             status_t    start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
                               int triggerSession = 0);
 
-    /* Stop a track. If set, the callback will cease being called and
-     * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
-     * and will drain buffers until the pool is exhausted.
+    /* Stop a track. If set, the callback will cease being called.  Note that obtainBuffer() still
+     * works and will drain buffers until the pool is exhausted, and then will return WOULD_BLOCK.
      */
             void        stop();
             bool        stopped() const;
 
-    /* Get sample rate for this record track in Hz.
+    /* Return the sink sample rate for this record track in Hz.
+     * Unlike AudioTrack, the sample rate is const after initialization, so doesn't need a lock.
      */
-            uint32_t    getSampleRate() const;
+            uint32_t    getSampleRate() const   { return mSampleRate; }
 
     /* Sets marker position. When record reaches the number of frames specified,
      * a callback with event type EVENT_MARKER is called. Calling setMarkerPosition
      * with marker == 0 cancels marker 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 ~0 or 1.
      * If the AudioRecord 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
@@ -226,13 +248,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 recorded,
      * a callback with event type EVENT_NEW_POS is called.
      * Calling setPositionUpdatePeriod with updatePeriod == 0 cancels new position notification
      * callback.
      * If the AudioRecord 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:
      *
@@ -245,13 +267,13 @@
             status_t    setPositionUpdatePeriod(uint32_t updatePeriod);
             status_t    getPositionUpdatePeriod(uint32_t *updatePeriod) const;
 
-
-    /* Gets record head position. The position is the total number of frames
-     * recorded since record start.
+    /* Return the total number of frames recorded since recording started.
+     * The counter will wrap (overflow) periodically, e.g. every ~27 hours at 44.1 kHz.
+     * It is reset to zero by stop().
      *
      * Parameters:
      *
-     *  position:  Address where to return record head position within AudioRecord buffer.
+     *  position:  Address where to return record head position.
      *
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful operation
@@ -276,38 +298,70 @@
      *
      * Returned value:
      *  AudioRecord session ID.
+     *
+     * No lock needed because session ID doesn't change after first set().
      */
-            int    getSessionId() const;
+            int    getSessionId() const { return mSessionId; }
 
-    /* Obtains a buffer of "frameCount" frames. The buffer must be
-     * drained entirely, and then released with releaseBuffer().
-     * If the track is stopped, obtainBuffer() returns
-     * STOPPED instead of NO_ERROR as long as there are buffers available,
-     * at which point NO_MORE_BUFFERS is returned.
+    /* Obtains a buffer of up to "audioBuffer->frameCount" full frames.
+     * After draining these frames of data, the caller should release them with releaseBuffer().
+     * If the track buffer is not empty, obtainBuffer() returns as many contiguous
+     * full frames as are available immediately.
+     * If the track buffer is empty and track is stopped, obtainBuffer() returns WOULD_BLOCK
+     * regardless of the value of waitCount.
+     * If the track buffer is empty and track is not stopped, obtainBuffer() blocks with a
+     * maximum timeout based on waitCount; see chart below.
      * Buffers will be returned until the pool
      * is exhausted, at which point obtainBuffer() will either block
-     * or return WOULD_BLOCK depending on the value of the "blocking"
+     * or return WOULD_BLOCK depending on the value of the "waitCount"
      * parameter.
      *
+     * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications,
+     * which should use read() 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,
      *   0  non-blocking.
+     *
+     * Buffer fields
+     * On entry:
+     *  frameCount  number of frames requested
+     * After error return:
+     *  frameCount  0
+     *  size        0
+     *  raw         undefined
+     * After successful return:
+     *  frameCount  actual number of frames available, <= number requested
+     *  size        actual number of bytes available
+     *  raw         pointer to the buffer
      */
 
-        enum {
-            NO_MORE_BUFFERS = 0x80000001,   // same name in AudioFlinger.h, ok to be different value
-            STOPPED = 1
-        };
+    /* FIXME Deprecated public API for TRANSFER_OBTAIN mode */
+            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+                                __attribute__((__deprecated__));
 
-            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
+private:
+    /* New internal API.
+     * If nonContig is non-NULL, it is an output parameter that will be set to the number of
+     * additional non-contiguous frames that are available immediately.
+     * FIXME We could pass an array of Buffers instead of only one Buffer to obtainBuffer(),
+     * in case the requested amount of frames is in two or more non-contiguous regions.
+     * FIXME requested and elapsed are both relative times.  Consider changing to absolute time.
+     */
+            status_t    obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
+                                     struct timespec *elapsed = NULL, size_t *nonContig = NULL);
+public:
 
-    /* Release an emptied buffer of "frameCount" frames for AudioFlinger to re-fill. */
+    /* Release an emptied buffer of "audioBuffer->frameCount" frames for AudioFlinger to re-fill. */
+    // FIXME make private when obtainBuffer() for TRANSFER_OBTAIN is removed
             void        releaseBuffer(Buffer* audioBuffer);
 
-
     /* As a convenience we provide a read() interface to the audio buffer.
-     * This is implemented on top of obtainBuffer/releaseBuffer.
+     * Input parameter 'size' is in byte units.
+     * This is implemented on top of obtainBuffer/releaseBuffer. For best
+     * performance use callbacks. Returns actual number of bytes read >= 0,
+     * or a negative status code.
      */
             ssize_t     read(void* buffer, size_t size);
 
@@ -336,68 +390,113 @@
 
                 void        pause();    // suspend thread from execution at next loop boundary
                 void        resume();   // allow thread to execute, if not requested to exit
+                void        pauseConditional();
+                                        // like pause(), but only if prior resume() wasn't latched
 
     private:
         friend class AudioRecord;
         virtual bool        threadLoop();
-        AudioRecord& mReceiver;
+        AudioRecord&        mReceiver;
         virtual ~AudioRecordThread();
         Mutex               mMyLock;    // Thread::mLock is private
         Condition           mMyCond;    // Thread::mThreadExitedCondition is private
         bool                mPaused;    // whether thread is currently paused
+        bool                mResumeLatch;   // whether next pauseConditional() will be a nop
     };
 
             // body of AudioRecordThread::threadLoop()
-            bool processAudioBuffer(const sp<AudioRecordThread>& thread);
+            // returns the maximum amount of time before we would like to run again, where:
+            //      0           immediately
+            //      > 0         no later than this many nanoseconds from now
+            //      NS_WHENEVER still active but no particular deadline
+            //      NS_INACTIVE inactive so don't run again until re-started
+            //      NS_NEVER    never again
+            static const nsecs_t NS_WHENEVER = -1, NS_INACTIVE = -2, NS_NEVER = -3;
+            nsecs_t processAudioBuffer(const sp<AudioRecordThread>& thread);
 
+            // caller must hold lock on mLock for all _l methods
             status_t openRecord_l(uint32_t sampleRate,
                                 audio_format_t format,
                                 size_t frameCount,
-                                audio_io_handle_t input);
+                                audio_io_handle_t input,
+                                size_t epoch);
+
             audio_io_handle_t getInput_l();
-            status_t restoreRecord_l(audio_track_cblk_t*& cblk);
+
+            // FIXME enum is faster than strcmp() for parameter 'from'
+            status_t restoreRecord_l(const char *from);
 
     sp<AudioRecordThread>   mAudioRecordThread;
     mutable Mutex           mLock;
 
-    bool                    mActive;            // protected by mLock
+    // Current client state:  false = stopped, true = active.  Protected by mLock.  If more states
+    // are added, consider changing this to enum State { ... } mState as in AudioTrack.
+    bool                    mActive;
 
     // for client callback handler
     callback_t              mCbf;               // callback handler for events, or NULL
-    void*                   mUserData;
+    void*                   mUserData;          // for client callback handler
 
     // for notification APIs
-    uint32_t                mNotificationFrames;
-    uint32_t                mRemainingFrames;
-    uint32_t                mMarkerPosition;    // in frames
+    uint32_t                mNotificationFrames; // frames between each notification callback
+    bool                    mRefreshRemaining;  // processAudioBuffer() should refresh next 2
+
+    // These are private to processAudioBuffer(), and are not protected by a lock
+    uint32_t                mRemainingFrames;       // number of frames to request in obtainBuffer()
+    bool                    mRetryOnPartialBuffer;  // sleep and retry after partial obtainBuffer()
+    int                     mObservedSequence;      // last observed value of mSequence
+
+    uint32_t                mMarkerPosition;    // in wrapping (overflow) frame units
     bool                    mMarkerReached;
     uint32_t                mNewPosition;       // in frames
-    uint32_t                mUpdatePeriod;      // in ms
+    uint32_t                mUpdatePeriod;      // in frames, zero means no EVENT_NEW_POS
+
+    status_t                mStatus;
 
     // constant after constructor or set()
     uint32_t                mSampleRate;
     size_t                  mFrameCount;
     audio_format_t          mFormat;
-    uint8_t                 mChannelCount;
+    uint32_t                mChannelCount;
     size_t                  mFrameSize;         // app-level frame size == AudioFlinger frame size
     audio_source_t          mInputSource;
-    status_t                mStatus;
-    uint32_t                mLatency;
+    uint32_t                mLatency;           // in ms
     audio_channel_mask_t    mChannelMask;
-    audio_io_handle_t       mInput;                     // returned by AudioSystem::getInput()
     int                     mSessionId;
+    transfer_type           mTransfer;
+
+    audio_io_handle_t       mInput;             // returned by AudioSystem::getInput()
 
     // may be changed if IAudioRecord object is re-created
     sp<IAudioRecord>        mAudioRecord;
     sp<IMemory>             mCblkMemory;
-    audio_track_cblk_t*     mCblk;
-    void*                   mBuffers;           // starting address of buffers in shared memory
+    audio_track_cblk_t*     mCblk;              // re-load after mLock.unlock()
 
-    int                     mPreviousPriority;          // before start()
+    int                     mPreviousPriority;  // before start()
     SchedPolicy             mPreviousSchedulingGroup;
-    AudioRecordClientProxy* mProxy;
+
+    // The proxy should only be referenced while a lock is held because the proxy isn't
+    // multi-thread safe.
+    // An exception is that a blocking ClientProxy::obtainBuffer() may be called without a lock,
+    // provided that the caller also holds an extra reference to the proxy and shared memory to keep
+    sp<AudioRecordClientProxy> mProxy;
+
+    bool                    mInOverrun;         // whether recorder is currently in overrun state
+
+private:
+    class DeathNotifier : public IBinder::DeathRecipient {
+    public:
+        DeathNotifier(AudioRecord* audioRecord) : mAudioRecord(audioRecord) { }
+    protected:
+        virtual void        binderDied(const wp<IBinder>& who);
+    private:
+        const wp<AudioRecord> mAudioRecord;
+    };
+
+    sp<DeathNotifier>       mDeathNotifier;
+    uint32_t                mSequence;              // incremented for each new IAudioRecord attempt
 };
 
 }; // namespace android
 
-#endif /*AUDIORECORD_H_*/
+#endif // ANDROID_AUDIORECORD_H
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index 8dbc9ee..e9bb76a 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -17,18 +17,9 @@
 #ifndef ANDROID_AUDIOTRACK_H
 #define ANDROID_AUDIOTRACK_H
 
-#include <stdint.h>
-#include <sys/types.h>
-
-#include <media/IAudioFlinger.h>
-#include <media/IAudioTrack.h>
-#include <media/AudioSystem.h>
-
-#include <utils/RefBase.h>
-#include <utils/Errors.h>
-#include <binder/IInterface.h>
-#include <binder/IMemory.h>
 #include <cutils/sched_policy.h>
+#include <media/AudioSystem.h>
+#include <media/IAudioTrack.h>
 #include <utils/threads.h>
 
 namespace android {
@@ -37,10 +28,11 @@
 
 class audio_track_cblk_t;
 class AudioTrackClientProxy;
+class StaticAudioTrackClientProxy;
 
 // ----------------------------------------------------------------------------
 
-class AudioTrack : virtual public RefBase
+class AudioTrack : public RefBase
 {
 public:
     enum channel_index {
@@ -49,7 +41,7 @@
         RIGHT  = 1
     };
 
-    /* Events used by AudioTrack callback function (audio_track_cblk_t).
+    /* Events used by AudioTrack callback function (callback_t).
      * Keep in sync with frameworks/base/media/java/android/media/AudioTrack.java NATIVE_EVENT_*.
      */
     enum event_type {
@@ -64,7 +56,10 @@
                                     // (See setMarkerPosition()).
         EVENT_NEW_POS = 4,          // Playback head is at a new position
                                     // (See setPositionUpdatePeriod()).
-        EVENT_BUFFER_END = 5        // Playback head is at the end of the buffer.
+        EVENT_BUFFER_END = 5,       // Playback head is at the end of the buffer.
+                                    // Not currently used by android.media.AudioTrack.
+        EVENT_NEW_IAUDIOTRACK = 6,  // IAudioTrack was re-created, either due to re-routing and
+                                    // voluntary invalidation by mediaserver, or mediaserver crash.
     };
 
     /* Client should declare Buffer on the stack and pass address to obtainBuffer()
@@ -74,19 +69,23 @@
     class Buffer
     {
     public:
+        // FIXME use m prefix
         size_t      frameCount;   // number of sample frames corresponding to size;
                                   // on input it is the number of frames desired,
                                   // on output is the number of frames actually filled
 
-        size_t      size;         // input/output in byte units
+        size_t      size;         // input/output in bytes == frameCount * frameSize
+                                  // FIXME this is redundant with respect to frameCount,
+                                  // and TRANSFER_OBTAIN mode is broken for 8-bit data
+                                  // since we don't define the frame format
+
         union {
             void*       raw;
-            short*      i16;    // signed 16-bit
-            int8_t*     i8;     // unsigned 8-bit, offset by 0x80
+            short*      i16;      // signed 16-bit
+            int8_t*     i8;       // unsigned 8-bit, offset by 0x80
         };
     };
 
-
     /* As a convenience, if a callback is supplied, a handler thread
      * is automatically created with the appropriate priority. This thread
      * invokes the callback when a new buffer becomes available or various conditions occur.
@@ -100,9 +99,10 @@
      *            written.
      *          - EVENT_UNDERRUN: unused.
      *          - EVENT_LOOP_END: pointer to an int indicating the number of loops remaining.
-     *          - EVENT_MARKER: pointer to an uint32_t containing the marker position in frames.
-     *          - EVENT_NEW_POS: pointer to an uint32_t containing the new position in frames.
+     *          - EVENT_MARKER: pointer to const uint32_t containing the marker position in frames.
+     *          - EVENT_NEW_POS: pointer to const uint32_t containing the new position in frames.
      *          - EVENT_BUFFER_END: unused.
+     *          - EVENT_NEW_IAUDIOTRACK: unused.
      */
 
     typedef void (*callback_t)(int event, void* user, void *info);
@@ -114,9 +114,19 @@
      *  - NO_INIT: audio server or audio hardware not initialized
      */
 
-     static status_t getMinFrameCount(size_t* frameCount,
-                                      audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT,
-                                      uint32_t sampleRate = 0);
+    static status_t getMinFrameCount(size_t* frameCount,
+                                     audio_stream_type_t streamType,
+                                     uint32_t sampleRate);
+
+    /* How data is transferred to AudioTrack
+     */
+    enum transfer_type {
+        TRANSFER_DEFAULT,   // not specified explicitly; determine from the other parameters
+        TRANSFER_CALLBACK,  // callback EVENT_MORE_DATA
+        TRANSFER_OBTAIN,    // FIXME deprecated: call obtainBuffer() and releaseBuffer()
+        TRANSFER_SYNC,      // synchronous write()
+        TRANSFER_SHARED,    // shared memory
+    };
 
     /* Constructs an uninitialized AudioTrack. No connection with
      * AudioFlinger takes place.  Use set() after this.
@@ -128,13 +138,13 @@
      * 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.
+     * Intermixing a combination of write() and non-ignored EVENT_MORE_DATA is not allowed.
      *
      * Parameters:
      *
      * streamType:         Select the type of audio stream this track is attached to
      *                     (e.g. AUDIO_STREAM_MUSIC).
-     * sampleRate:         Track sampling rate in Hz.
+     * sampleRate:         Data source sampling rate in Hz.
      * format:             Audio format (e.g AUDIO_FORMAT_PCM_16_BIT for signed
      *                     16 bits per sample).
      * channelMask:        Channel mask.
@@ -149,9 +159,10 @@
      * 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.
+     *                     This is expressed in units of frames at the initial source sample rate.
      * sessionId:          Specific session ID, or zero to use default.
-     * threadCanCallJava:  Whether callbacks are made from an attached thread and thus can call JNI.
-     *                     If not present in parameter list, then fixed at false.
+     * transferType:       How data is transferred to AudioTrack.
+     * threadCanCallJava:  Not present in parameter list, and so is fixed at false.
      */
 
                         AudioTrack( audio_stream_type_t streamType,
@@ -163,7 +174,8 @@
                                     callback_t cbf       = NULL,
                                     void* user           = NULL,
                                     int notificationFrames = 0,
-                                    int sessionId        = 0);
+                                    int sessionId        = 0,
+                                    transfer_type transferType = TRANSFER_DEFAULT);
 
     /* Creates an audio track and registers it with AudioFlinger.
      * With this constructor, the track is configured for static buffer mode.
@@ -174,7 +186,6 @@
      * 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,
@@ -186,7 +197,8 @@
                                     callback_t cbf      = NULL,
                                     void* user          = NULL,
                                     int notificationFrames = 0,
-                                    int sessionId       = 0);
+                                    int sessionId       = 0,
+                                    transfer_type transferType = TRANSFER_DEFAULT);
 
     /* Terminates the AudioTrack and unregisters it from AudioFlinger.
      * Also destroys all resources associated with the AudioTrack.
@@ -195,7 +207,8 @@
                         virtual ~AudioTrack();
 public:
 
-    /* Initialize an uninitialized AudioTrack.
+    /* Initialize an AudioTrack that was created using the AudioTrack() constructor.
+     * Don't call set() more than once, or after the AudioTrack() constructors that take parameters.
      * Returned status (from utils/Errors.h) can be:
      *  - NO_ERROR: successful initialization
      *  - INVALID_OPERATION: AudioTrack is already initialized
@@ -203,6 +216,10 @@
      *  - 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.
+     *
+     * Parameters not listed in the AudioTrack constructors above:
+     *
+     * threadCanCallJava:  Whether callbacks are made from an attached thread and thus can call JNI.
      */
             status_t    set(audio_stream_type_t streamType = AUDIO_STREAM_DEFAULT,
                             uint32_t sampleRate = 0,
@@ -215,7 +232,8 @@
                             int notificationFrames = 0,
                             const sp<IMemory>& sharedBuffer = 0,
                             bool threadCanCallJava = false,
-                            int sessionId       = 0);
+                            int sessionId       = 0,
+                            transfer_type transferType = TRANSFER_DEFAULT);
 
     /* Result of constructing the AudioTrack. This must be checked
      * before using any AudioTrack API (except for set()), because using
@@ -235,15 +253,16 @@
             audio_stream_type_t streamType() const { return mStreamType; }
             audio_format_t format() const   { return mFormat; }
 
-    /* Return frame size in bytes, which for linear PCM is 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.
      */
-            uint32_t    channelCount() const { return mChannelCount; }
-
-            uint32_t    frameCount() const  { return mFrameCount; }
             size_t      frameSize() const   { return mFrameSize; }
 
+            uint32_t    channelCount() const { return mChannelCount; }
+            uint32_t    frameCount() const  { return mFrameCount; }
+
     /* Return the static buffer specified in constructor or set(), or 0 for streaming mode */
             sp<IMemory> sharedBuffer() const { return mSharedBuffer; }
 
@@ -255,10 +274,9 @@
 
     /* 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
+     * In streaming mode, the callback will cease being called.  Note that obtainBuffer() still
+     * works and will fill up buffers until the pool is exhausted, and then will return WOULD_BLOCK.
+     * In streaming mode 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();
@@ -272,7 +290,7 @@
             void        flush();
 
     /* Pause a track. After pause, the callback will cease being called and
-     * obtainBuffer returns STOPPED. Note that obtainBuffer() still works
+     * obtainBuffer returns WOULD_BLOCK. 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().
@@ -296,11 +314,11 @@
             status_t    setAuxEffectSendLevel(float level);
             void        getAuxEffectSendLevel(float* level) const;
 
-    /* Set sample rate for this track in Hz, mostly used for games' sound effects
+    /* Set source sample rate for this track in Hz, mostly used for games' sound effects
      */
             status_t    setSampleRate(uint32_t sampleRate);
 
-    /* Return current sample rate in Hz, or 0 if unknown */
+    /* Return current source sample rate in Hz, or 0 if unknown */
             uint32_t    getSampleRate() const;
 
     /* Enables looping and sets the start and end points of looping.
@@ -322,7 +340,7 @@
      *      loopCount != 0 implies 0 <= loopStart < loopEnd <= frameCount().
      *
      * If the loop period (loopEnd - loopStart) is too small for the implementation to support,
-     * setLoop() will return BAD_VALUE.
+     * setLoop() will return BAD_VALUE.  loopCount must be >= -1.
      *
      */
             status_t    setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount);
@@ -330,7 +348,7 @@
     /* 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.  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.
+     * a workaround is to the set the marker at a nearby position such as ~0 or 1.
      * If the AudioTrack has been opened with no callback function associated, the operation will
      * fail.
      *
@@ -390,16 +408,22 @@
     /* 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().
+     *
+     * Parameters:
+     *
+     *  position:  Address where to return play head position.
+     *
+     * Returned status (from utils/Errors.h) can be:
+     *  - NO_ERROR: successful operation
+     *  - BAD_VALUE:  position is NULL
      */
-            status_t    getPosition(uint32_t *position);
+            status_t    getPosition(uint32_t *position) const;
 
-#if 0
     /* For static buffer mode only, this returns the current playback position in frames
      * relative to start of buffer.  It is analogous to the new API for
      * setLoop() and setPosition().  After underrun, the position will be at end of buffer.
      */
             status_t    getBufferPosition(uint32_t *position);
-#endif
 
     /* Forces AudioTrack buffer full condition. When playing a static buffer, this method avoids
      * rewriting the buffer before restarting playback after a stop.
@@ -446,15 +470,19 @@
      */
             status_t    attachAuxEffect(int effectId);
 
-    /* Obtains a buffer of "frameCount" frames. The buffer must be
-     * filled entirely, and then released with releaseBuffer().
-     * If the track is stopped, obtainBuffer() returns
-     * STOPPED instead of NO_ERROR as long as there are buffers available,
-     * at which point NO_MORE_BUFFERS is returned.
+    /* Obtains a buffer of up to "audioBuffer->frameCount" empty slots for frames.
+     * After filling these slots with data, the caller should release them with releaseBuffer().
+     * If the track buffer is not full, obtainBuffer() returns as many contiguous
+     * [empty slots for] frames as are available immediately.
+     * If the track buffer is full and track is stopped, obtainBuffer() returns WOULD_BLOCK
+     * regardless of the value of waitCount.
+     * If the track buffer is full and track is not stopped, obtainBuffer() blocks with a
+     * maximum timeout based on waitCount; see chart below.
      * Buffers will be returned until the pool
      * is exhausted, at which point obtainBuffer() will either block
-     * or return WOULD_BLOCK depending on the value of the "blocking"
+     * or return WOULD_BLOCK depending on the value of the "waitCount"
      * parameter.
+     * Each sample is 16-bit signed PCM.
      *
      * obtainBuffer() and releaseBuffer() are deprecated for direct use by applications,
      * which should use write() or callback EVENT_MORE_DATA instead.
@@ -477,24 +505,35 @@
      *  raw         pointer to the buffer
      */
 
-        enum {
-            NO_MORE_BUFFERS = 0x80000001,   // same name in AudioFlinger.h, ok to be different value
-            STOPPED = 1
-        };
+    /* FIXME Deprecated public API for TRANSFER_OBTAIN mode */
+            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
+                                __attribute__((__deprecated__));
 
-            status_t    obtainBuffer(Buffer* audioBuffer, int32_t waitCount);
+private:
+    /* New internal API
+     * If nonContig is non-NULL, it is an output parameter that will be set to the number of
+     * additional non-contiguous frames that are available immediately.
+     * FIXME We could pass an array of Buffers instead of only one Buffer to obtainBuffer(),
+     * in case the requested amount of frames is in two or more non-contiguous regions.
+     * FIXME requested and elapsed are both relative times.  Consider changing to absolute time.
+     */
+            status_t    obtainBuffer(Buffer* audioBuffer, const struct timespec *requested,
+                                     struct timespec *elapsed = NULL, size_t *nonContig = NULL);
+public:
 
-    /* Release a filled buffer of "frameCount" frames for AudioFlinger to process. */
+    /* Release a filled buffer of "audioBuffer->frameCount" frames for AudioFlinger to process. */
+    // FIXME make private when obtainBuffer() for TRANSFER_OBTAIN is removed
             void        releaseBuffer(Buffer* audioBuffer);
 
     /* As a convenience we provide a write() interface to the audio buffer.
+     * Input parameter 'size' is in byte units.
      * This is implemented on top of obtainBuffer/releaseBuffer. For best
      * performance use callbacks. Returns actual number of bytes written >= 0,
      * or one of the following negative status codes:
      *      INVALID_OPERATION   AudioTrack is configured for shared buffer mode
      *      BAD_VALUE           size is invalid
-     *      STOPPED             AudioTrack was stopped during the write
-     *      NO_MORE_BUFFERS     when obtainBuffer() returns same
+     *      WOULD_BLOCK         when obtainBuffer() returns same, or
+     *                          AudioTrack was stopped during the write
      *      or any other error code returned by IAudioTrack::start() or restoreTrack_l().
      * Not supported for static buffer mode.
      */
@@ -503,7 +542,13 @@
     /*
      * Dumps the state of an audio track.
      */
-            status_t dump(int fd, const Vector<String16>& args) const;
+            status_t    dump(int fd, const Vector<String16>& args) const;
+
+    /*
+     * Return the total number of frames which AudioFlinger desired but were unavailable,
+     * and thus which resulted in an underrun.  Reset to zero by stop().
+     */
+            uint32_t    getUnderrunFrames() const;
 
 protected:
     /* copying audio tracks is not allowed */
@@ -522,19 +567,29 @@
 
                 void        pause();    // suspend thread from execution at next loop boundary
                 void        resume();   // allow thread to execute, if not requested to exit
+                void        pauseConditional();
+                                        // like pause(), but only if prior resume() wasn't latched
 
     private:
         friend class AudioTrack;
         virtual bool        threadLoop();
-        AudioTrack& mReceiver;
-        ~AudioTrackThread();
+        AudioTrack&         mReceiver;
+        virtual ~AudioTrackThread();
         Mutex               mMyLock;    // Thread::mLock is private
         Condition           mMyCond;    // Thread::mThreadExitedCondition is private
         bool                mPaused;    // whether thread is currently paused
+        bool                mResumeLatch;   // whether next pauseConditional() will be a nop
     };
 
             // body of AudioTrackThread::threadLoop()
-            bool processAudioBuffer(const sp<AudioTrackThread>& thread);
+            // returns the maximum amount of time before we would like to run again, where:
+            //      0           immediately
+            //      > 0         no later than this many nanoseconds from now
+            //      NS_WHENEVER still active but no particular deadline
+            //      NS_INACTIVE inactive so don't run again until re-started
+            //      NS_NEVER    never again
+            static const nsecs_t NS_WHENEVER = -1, NS_INACTIVE = -2, NS_NEVER = -3;
+            nsecs_t processAudioBuffer(const sp<AudioTrackThread>& thread);
 
             // caller must hold lock on mLock for all _l methods
             status_t createTrack_l(audio_stream_type_t streamType,
@@ -543,20 +598,24 @@
                                  size_t frameCount,
                                  audio_output_flags_t flags,
                                  const sp<IMemory>& sharedBuffer,
-                                 audio_io_handle_t output);
+                                 audio_io_handle_t output,
+                                 size_t epoch);
 
-            // can only be called when !mActive
+            // can only be called when mState != STATE_ACTIVE
             void flush_l();
 
-            status_t setLoop_l(uint32_t loopStart, uint32_t loopEnd, int loopCount);
+            void 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);
-            bool stopped_l() const { return !mActive; }
 
+            // FIXME enum is faster than strcmp() for parameter 'from'
+            status_t restoreTrack_l(const char *from);
+
+    // may be changed if IAudioTrack is re-created
     sp<IAudioTrack>         mAudioTrack;
     sp<IMemory>             mCblkMemory;
-    sp<AudioTrackThread>    mAudioTrackThread;
+    audio_track_cblk_t*     mCblk;                  // re-load after mLock.unlock()
 
+    sp<AudioTrackThread>    mAudioTrackThread;
     float                   mVolume[2];
     float                   mSendLevel;
     uint32_t                mSampleRate;
@@ -564,62 +623,89 @@
     size_t                  mReqFrameCount;         // frame count to request the next time a new
                                                     // IAudioTrack is needed
 
-    audio_track_cblk_t*     mCblk;                  // re-load after mLock.unlock()
 
-            // Starting address of buffers in shared memory.  If there is a shared buffer, mBuffers
-            // is the value of pointer() for the shared buffer, otherwise mBuffers points
-            // immediately after the control block.  This address is for the mapping within client
-            // address space.  AudioFlinger::TrackBase::mBuffer is for the server address space.
-    void*                   mBuffers;
-
+    // constant after constructor or set()
     audio_format_t          mFormat;                // as requested by client, not forced to 16-bit
     audio_stream_type_t     mStreamType;
     uint32_t                mChannelCount;
     audio_channel_mask_t    mChannelMask;
+    transfer_type           mTransfer;
 
-                // mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data.
-                // For 8-bit PCM data, mFrameSizeAF is
-                // twice as large because data is expanded to 16-bit before being stored in buffer.
+    // mFrameSize is equal to mFrameSizeAF for non-PCM or 16-bit PCM data.  For 8-bit PCM data, it's
+    // twice as large as mFrameSize because data is expanded to 16-bit before it's stored in buffer.
     size_t                  mFrameSize;             // app-level frame size
     size_t                  mFrameSizeAF;           // AudioFlinger frame size
 
     status_t                mStatus;
-    uint32_t                mLatency;
 
-    bool                    mActive;                // protected by mLock
+    // can change dynamically when IAudioTrack invalidated
+    uint32_t                mLatency;               // in ms
+
+    // Indicates the current track state.  Protected by mLock.
+    enum State {
+        STATE_ACTIVE,
+        STATE_STOPPED,
+        STATE_PAUSED,
+        STATE_FLUSHED,
+    }                       mState;
 
     callback_t              mCbf;                   // callback handler for events, or NULL
     void*                   mUserData;              // for client callback handler
 
     // for notification APIs
     uint32_t                mNotificationFramesReq; // requested number of frames between each
-                                                    // notification callback
+                                                    // notification callback,
+                                                    // at initial source sample rate
     uint32_t                mNotificationFramesAct; // actual number of frames between each
-                                                    // notification callback
+                                                    // notification callback,
+                                                    // at initial source sample rate
+    bool                    mRefreshRemaining;      // processAudioBuffer() should refresh next 2
+
+    // These are private to processAudioBuffer(), and are not protected by a lock
+    uint32_t                mRemainingFrames;       // number of frames to request in obtainBuffer()
+    bool                    mRetryOnPartialBuffer;  // sleep and retry after partial obtainBuffer()
+    int                     mObservedSequence;      // last observed value of mSequence
+
     sp<IMemory>             mSharedBuffer;
-    int                     mLoopCount;
-    uint32_t                mRemainingFrames;
+    uint32_t                mLoopPeriod;            // in frames, zero means looping is disabled
     uint32_t                mMarkerPosition;        // in wrapping (overflow) frame units
     bool                    mMarkerReached;
     uint32_t                mNewPosition;           // in frames
-    uint32_t                mUpdatePeriod;          // in frames
+    uint32_t                mUpdatePeriod;          // in frames, zero means no EVENT_NEW_POS
 
-    bool                    mFlushed; // FIXME will be made obsolete by making flush() synchronous
     audio_output_flags_t    mFlags;
     int                     mSessionId;
     int                     mAuxEffectId;
 
-    // When locking both mLock and mCblk->lock, must lock in this order to avoid deadlock:
-    //      1. mLock
-    //      2. mCblk->lock
-    // It is OK to lock only mCblk->lock.
     mutable Mutex           mLock;
 
     bool                    mIsTimed;
     int                     mPreviousPriority;          // before start()
     SchedPolicy             mPreviousSchedulingGroup;
-    AudioTrackClientProxy*  mProxy;
     bool                    mAwaitBoost;    // thread should wait for priority boost before running
+
+    // The proxy should only be referenced while a lock is held because the proxy isn't
+    // multi-thread safe, especially the SingleStateQueue part of the proxy.
+    // An exception is that a blocking ClientProxy::obtainBuffer() may be called without a lock,
+    // provided that the caller also holds an extra reference to the proxy and shared memory to keep
+    // them around in case they are replaced during the obtainBuffer().
+    sp<StaticAudioTrackClientProxy> mStaticProxy;   // for type safety only
+    sp<AudioTrackClientProxy>       mProxy;         // primary owner of the memory
+
+    bool                    mInUnderrun;            // whether track is currently in underrun state
+
+private:
+    class DeathNotifier : public IBinder::DeathRecipient {
+    public:
+        DeathNotifier(AudioTrack* audioTrack) : mAudioTrack(audioTrack) { }
+    protected:
+        virtual void        binderDied(const wp<IBinder>& who);
+    private:
+        const wp<AudioTrack> mAudioTrack;
+    };
+
+    sp<DeathNotifier>       mDeathNotifier;
+    uint32_t                mSequence;              // incremented for each new IAudioTrack attempt
 };
 
 class TimedAudioTrack : public AudioTrack
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 41e20f8..681f557 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -22,32 +22,46 @@
 
 #include <utils/threads.h>
 #include <utils/Log.h>
+#include <utils/RefBase.h>
+#include <media/nbaio/roundup.h>
+#include <media/SingleStateQueue.h>
+#include <private/media/StaticAudioTrackState.h>
 
 namespace android {
 
 // ----------------------------------------------------------------------------
 
-// Maximum cumulated timeout milliseconds before restarting audioflinger thread
-#define MAX_STARTUP_TIMEOUT_MS  3000    // Longer timeout period at startup to cope with A2DP
-                                        // init time
-#define MAX_RUN_TIMEOUT_MS      1000
-#define WAIT_PERIOD_MS          10
-
-#define CBLK_UNDERRUN   0x01 // set: underrun (out) or overrrun (in), clear: no underrun or overrun
+#define CBLK_UNDERRUN   0x01 // set by server immediately on output underrun, cleared by client
 #define CBLK_FORCEREADY 0x02 // set: track is considered ready immediately by AudioFlinger,
                              // clear: track is ready when buffer full
 #define CBLK_INVALID    0x04 // track buffer invalidated by AudioFlinger, need to re-create
-#define CBLK_DISABLED   0x08 // track disabled by AudioFlinger due to underrun, need to re-start
+#define CBLK_DISABLED   0x08 // output track disabled by AudioFlinger due to underrun,
+                             // need to re-start.  Unlike CBLK_UNDERRUN, this is not set
+                             // immediately, but only after a long string of underruns.
+// 0x10 unused
+#define CBLK_LOOP_CYCLE 0x20 // set by server each time a loop cycle other than final one completes
+#define CBLK_LOOP_FINAL 0x40 // set by server when the final loop cycle completes
+#define CBLK_BUFFER_END 0x80 // set by server when the position reaches end of buffer if not looping
+#define CBLK_OVERRUN   0x100 // set by server immediately on input overrun, cleared by client
+#define CBLK_INTERRUPT 0x200 // set by client on interrupt(), cleared by client in obtainBuffer()
 
 struct AudioTrackSharedStreaming {
     // similar to NBAIO MonoPipe
-    volatile int32_t mFront;
-    volatile int32_t mRear;
+    // in continuously incrementing frame units, take modulo buffer size, which must be a power of 2
+    volatile int32_t mFront;    // read by server
+    volatile int32_t mRear;     // write by client
+    volatile int32_t mFlush;    // incremented by client to indicate a request to flush;
+                                // server notices and discards all data between mFront and mRear
+    volatile uint32_t mUnderrunFrames;  // server increments for each unavailable but desired frame
 };
 
-// future
+typedef SingleStateQueue<StaticAudioTrackState> StaticAudioTrackSingleStateQueue;
+
 struct AudioTrackSharedStatic {
-    int mReserved;
+    StaticAudioTrackSingleStateQueue::Shared
+                    mSingleStateQueue;
+    size_t          mBufferPosition;    // updated asynchronously by server,
+                                        // "for entertainment purposes only"
 };
 
 // ----------------------------------------------------------------------------
@@ -55,65 +69,61 @@
 // Important: do not add any virtual methods, including ~
 struct audio_track_cblk_t
 {
+                // Since the control block is always located in shared memory, this constructor
+                // is only used for placement new().  It is never used for regular new() or stack.
+                            audio_track_cblk_t();
+                /*virtual*/ ~audio_track_cblk_t() { }
+
                 friend class Proxy;
+                friend class ClientProxy;
                 friend class AudioTrackClientProxy;
                 friend class AudioRecordClientProxy;
                 friend class ServerProxy;
+                friend class AudioTrackServerProxy;
+                friend class AudioRecordServerProxy;
 
     // The data members are grouped so that members accessed frequently and in the same context
     // are in the same line of data cache.
-                Mutex       lock;           // sizeof(int)
-                Condition   cv;             // sizeof(int)
 
-                // next 4 are offsets within "buffers"
-    volatile    uint32_t    user;
-    volatile    uint32_t    server;
-                uint32_t    userBase;
-                uint32_t    serverBase;
-
-                int         mPad1;          // unused, but preserves cache line alignment
+    volatile    uint32_t    server;     // updated asynchronously by server,
+                                        // "for entertainment purposes only"
 
                 size_t      frameCount_;    // used during creation to pass actual track buffer size
                                             // from AudioFlinger to client, and not referenced again
-                                            // FIXME remove here and replace by createTrack() in/out parameter
+                                            // FIXME remove here and replace by createTrack() in/out
+                                            // parameter
                                             // renamed to "_" to detect incorrect use
 
-                // Cache line boundary (32 bytes)
+    volatile    int32_t     mFutex;     // semaphore: down (P) by client,
+                                        // up (V) by server or binderDied() or interrupt()
 
-                uint32_t    loopStart;
-                uint32_t    loopEnd;        // read-only for server, read/write for client
-                int         loopCount;      // read/write for client
+private:
+
+                size_t      mMinimum;       // server wakes up client if available >= mMinimum
 
                 // Channel volumes are fixed point U4.12, so 0x1000 means 1.0.
                 // Left channel is in [0:15], right channel is in [16:31].
                 // Always read and write the combined pair atomically.
                 // For AudioTrack only, not used by AudioRecord.
-private:
                 uint32_t    mVolumeLR;
 
                 uint32_t    mSampleRate;    // AudioTrack only: client's requested sample rate in Hz
                                             // or 0 == default. Write-only client, read-only server.
 
+                // client write-only, server read-only
+                uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0
+
                 uint8_t     mPad2;           // unused
 
 public:
                 // read-only for client, server writes once at initialization and is then read-only
                 uint8_t     mName;           // normal tracks: track name, fast tracks: track index
 
-                // used by client only
-                uint16_t    bufferTimeoutMs; // Maximum cumulated timeout before restarting
-                                             // audioflinger
-
-                uint16_t    waitTimeMs;      // Cumulated wait time, used by client only
-private:
-                // client write-only, server read-only
-                uint16_t    mSendLevel;      // Fixed point U4.12 so 0x1000 means 1.0
-public:
     volatile    int32_t     flags;
 
                 // Cache line boundary (32 bytes)
 
-#if 0
+public:
                 union {
                     AudioTrackSharedStreaming   mStreaming;
                     AudioTrackSharedStatic      mStatic;
@@ -121,25 +131,6 @@
                 } u;
 
                 // Cache line boundary (32 bytes)
-#endif
-
-                // Since the control block is always located in shared memory, this constructor
-                // is only used for placement new().  It is never used for regular new() or stack.
-                            audio_track_cblk_t();
-
-private:
-                // if there is a shared buffer, "buffers" is the value of pointer() for the shared
-                // buffer, otherwise "buffers" points immediately after the control block
-                void*       buffer(void *buffers, uint32_t frameSize, size_t offset) const;
-
-                bool        tryLock();
-
-                // isOut == true means AudioTrack, isOut == false means AudioRecord
-                bool        stepServer(size_t stepCount, size_t frameCount, bool isOut);
-                uint32_t    stepUser(size_t stepCount, size_t frameCount, bool isOut);
-                uint32_t    framesAvailable(size_t frameCount, bool isOut);
-                uint32_t    framesAvailable_l(size_t frameCount, bool isOut);
-                uint32_t    framesReady(bool isOut);
 };
 
 // ----------------------------------------------------------------------------
@@ -147,29 +138,31 @@
 // Proxy for shared memory control block, to isolate callers from needing to know the details.
 // There is exactly one ClientProxy and one ServerProxy per shared memory control block.
 // The proxies are located in normal memory, and are not multi-thread safe within a given side.
-class Proxy {
+class Proxy : public RefBase {
 protected:
-    Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
-        : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { }
+    Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut,
+            bool clientInServer);
     virtual ~Proxy() { }
 
 public:
-    void*   buffer(size_t offset) const {
-        return mCblk->buffer(mBuffers, mFrameSize, offset);
-    }
+    struct Buffer {
+        size_t  mFrameCount;            // number of frames available in this buffer
+        void*   mRaw;                   // pointer to first frame
+        size_t  mNonContig;             // number of additional non-contiguous frames available
+    };
 
 protected:
     // These refer to shared memory, and are virtual addresses with respect to the current process.
     // They may have different virtual addresses within the other process.
-    audio_track_cblk_t* const   mCblk;          // the control block
-    void* const                 mBuffers;       // starting address of buffers
+    audio_track_cblk_t* const   mCblk;  // the control block
+    void* const     mBuffers;           // starting address of buffers
 
-    const size_t                mFrameCount;    // not necessarily a power of 2
-    const size_t                mFrameSize;     // in bytes
-#if 0
-    const size_t                mFrameCountP2;  // mFrameCount rounded to power of 2, streaming mode
-#endif
-
+    const size_t    mFrameCount;        // not necessarily a power of 2
+    const size_t    mFrameSize;         // in bytes
+    const size_t    mFrameCountP2;      // mFrameCount rounded to power of 2, streaming mode
+    const bool      mIsOut;             // true for AudioTrack, false for AudioRecord
+    const bool      mClientInServer;    // true for OutputTrack, false for AudioTrack & AudioRecord
+    bool            mIsShutdown;        // latch set to true when shared memory corruption detected
 };
 
 // ----------------------------------------------------------------------------
@@ -177,9 +170,86 @@
 // Proxy seen by AudioTrack client and AudioRecord client
 class ClientProxy : public Proxy {
 protected:
-    ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
-        : Proxy(cblk, buffers, frameCount, frameSize) { }
+    ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
+            bool isOut, bool clientInServer);
     virtual ~ClientProxy() { }
+
+public:
+    static const struct timespec kForever;
+    static const struct timespec kNonBlocking;
+
+    // Obtain a buffer with filled frames (reading) or empty frames (writing).
+    // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
+    // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
+    // sets or extends the unreleased frame count.
+    // On entry:
+    //  buffer->mFrameCount should be initialized to maximum number of desired frames,
+    //      which must be > 0.
+    //  buffer->mNonContig is unused.
+    //  buffer->mRaw is unused.
+    //  requested is the requested timeout in local monotonic delta time units:
+    //      NULL or &kNonBlocking means non-blocking (zero timeout).
+    //      &kForever means block forever (infinite timeout).
+    //      Other values mean a specific timeout in local monotonic delta time units.
+    //  elapsed is a pointer to a location that will hold the total local monotonic time that
+    //      elapsed while blocked, or NULL if not needed.
+    // On exit:
+    //  buffer->mFrameCount has the actual number of contiguous available frames,
+    //      which is always 0 when the return status != NO_ERROR.
+    //  buffer->mNonContig is the number of additional non-contiguous available frames.
+    //  buffer->mRaw is a pointer to the first available frame,
+    //      or NULL when buffer->mFrameCount == 0.
+    // The return status is one of:
+    //  NO_ERROR    Success, buffer->mFrameCount > 0.
+    //  WOULD_BLOCK Non-blocking mode and no frames are available.
+    //  TIMED_OUT   Timeout occurred before any frames became available.
+    //              This can happen even for infinite timeout, due to a spurious wakeup.
+    //              In this case, the caller should investigate and then re-try as appropriate.
+    //  DEAD_OBJECT Server has died or invalidated, caller should destroy this proxy and re-create.
+    //  -EINTR      Call has been interrupted.  Look around to see why, and then perhaps try again.
+    //  NO_INIT     Shared memory is corrupt.
+    //  BAD_VALUE   On entry buffer == NULL or buffer->mFrameCount == 0.
+    status_t    obtainBuffer(Buffer* buffer, const struct timespec *requested = NULL,
+            struct timespec *elapsed = NULL);
+
+    // Release (some of) the frames last obtained.
+    // On entry, buffer->mFrameCount should have the number of frames to release,
+    // which must (cumulatively) be <= the number of frames last obtained but not yet released.
+    // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
+    // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
+    // On exit:
+    //  buffer->mFrameCount is zero.
+    //  buffer->mRaw is NULL.
+    void        releaseBuffer(Buffer* buffer);
+
+    // Call after detecting server's death
+    void        binderDied();
+
+    // Call to force an obtainBuffer() to return quickly with -EINTR
+    void        interrupt();
+
+    size_t      getPosition() {
+        return mEpoch + mCblk->server;
+    }
+
+    void        setEpoch(size_t epoch) {
+        mEpoch = epoch;
+    }
+
+    void        setMinimum(size_t minimum) {
+        mCblk->mMinimum = minimum;
+    }
+
+    // Return the number of frames that would need to be obtained and released
+    // in order for the client to be aligned at start of buffer
+    virtual size_t  getMisalignment();
+
+    size_t      getEpoch() const {
+        return mEpoch;
+    }
+
+private:
+    size_t      mEpoch;
 };
 
 // ----------------------------------------------------------------------------
@@ -187,8 +257,10 @@
 // Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack
 class AudioTrackClientProxy : public ClientProxy {
 public:
-    AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
-        : ClientProxy(cblk, buffers, frameCount, frameSize) { }
+    AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
+            size_t frameSize, bool clientInServer = false)
+        : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/,
+          clientInServer) { }
     virtual ~AudioTrackClientProxy() { }
 
     // No barriers on the following operations, so the ordering of loads/stores
@@ -208,27 +280,36 @@
         mCblk->mSampleRate = sampleRate;
     }
 
-    // called by:
-    //   PlaybackThread::OutputTrack::write
-    //   AudioTrack::createTrack_l
-    //   AudioTrack::releaseBuffer
-    //   AudioTrack::reload
-    //   AudioTrack::restoreTrack_l (2 places)
-    size_t      stepUser(size_t stepCount) {
-        return mCblk->stepUser(stepCount, mFrameCount, true /*isOut*/);
+    virtual void flush();
+
+    virtual uint32_t    getUnderrunFrames() const {
+        return mCblk->u.mStreaming.mUnderrunFrames;
+    }
+};
+
+class StaticAudioTrackClientProxy : public AudioTrackClientProxy {
+public:
+    StaticAudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
+            size_t frameSize);
+    virtual ~StaticAudioTrackClientProxy() { }
+
+    virtual void    flush();
+
+#define MIN_LOOP    16  // minimum length of each loop iteration in frames
+            void    setLoop(size_t loopStart, size_t loopEnd, int loopCount);
+            size_t  getBufferPosition();
+
+    virtual size_t  getMisalignment() {
+        return 0;
     }
 
-    // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer
-    size_t      framesAvailable() {
-        return mCblk->framesAvailable(mFrameCount, true /*isOut*/);
+    virtual uint32_t    getUnderrunFrames() const {
+        return 0;
     }
 
-    // called by AudioTrack::obtainBuffer and PlaybackThread::OutputTrack::obtainBuffer
-    // FIXME remove this API since it assumes a lock that should be invisible to caller
-    size_t      framesAvailable_l() {
-        return mCblk->framesAvailable_l(mFrameCount, true /*isOut*/);
-    }
-
+private:
+    StaticAudioTrackSingleStateQueue::Mutator   mMutator;
+    size_t          mBufferPosition;    // so that getBufferPosition() appears to be synchronous
 };
 
 // ----------------------------------------------------------------------------
@@ -236,60 +317,122 @@
 // Proxy used by AudioRecord client
 class AudioRecordClientProxy : public ClientProxy {
 public:
-    AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
-        : ClientProxy(cblk, buffers, frameCount, frameSize) { }
+    AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
+            size_t frameSize)
+        : ClientProxy(cblk, buffers, frameCount, frameSize,
+            false /*isOut*/, false /*clientInServer*/) { }
     ~AudioRecordClientProxy() { }
-
-    // called by AudioRecord::releaseBuffer
-    size_t      stepUser(size_t stepCount) {
-        return mCblk->stepUser(stepCount, mFrameCount, false /*isOut*/);
-    }
-
-    // called by AudioRecord::processBuffer
-    size_t      framesAvailable() {
-        return mCblk->framesAvailable(mFrameCount, false /*isOut*/);
-    }
-
-    // called by AudioRecord::obtainBuffer
-    size_t      framesReady() {
-        return mCblk->framesReady(false /*isOut*/);
-    }
-
 };
 
 // ----------------------------------------------------------------------------
 
 // Proxy used by AudioFlinger server
 class ServerProxy : public Proxy {
+protected:
+    ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize,
+            bool isOut, bool clientInServer);
 public:
-    ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut)
-        : Proxy(cblk, buffers, frameCount, frameSize), mIsOut(isOut) { }
     virtual ~ServerProxy() { }
 
-    // for AudioTrack and AudioRecord
-    bool        step(size_t stepCount) { return mCblk->stepServer(stepCount, mFrameCount, mIsOut); }
+    // Obtain a buffer with filled frames (writing) or empty frames (reading).
+    // It is permitted to call obtainBuffer() multiple times in succession, without any intervening
+    // calls to releaseBuffer().  In that case, the final obtainBuffer() is the one that effectively
+    // sets or extends the unreleased frame count.
+    // Always non-blocking.
+    // On entry:
+    //  buffer->mFrameCount should be initialized to maximum number of desired frames,
+    //      which must be > 0.
+    //  buffer->mNonContig is unused.
+    //  buffer->mRaw is unused.
+    // On exit:
+    //  buffer->mFrameCount has the actual number of contiguous available frames,
+    //      which is always 0 when the return status != NO_ERROR.
+    //  buffer->mNonContig is the number of additional non-contiguous available frames.
+    //  buffer->mRaw is a pointer to the first available frame,
+    //      or NULL when buffer->mFrameCount == 0.
+    // The return status is one of:
+    //  NO_ERROR    Success, buffer->mFrameCount > 0.
+    //  WOULD_BLOCK No frames are available.
+    //  NO_INIT     Shared memory is corrupt.
+    virtual status_t    obtainBuffer(Buffer* buffer);
 
+    // Release (some of) the frames last obtained.
+    // On entry, buffer->mFrameCount should have the number of frames to release,
+    // which must (cumulatively) be <= the number of frames last obtained but not yet released.
+    // It is permitted to call releaseBuffer() multiple times to release the frames in chunks.
+    // buffer->mRaw is ignored, but is normally same pointer returned by last obtainBuffer().
+    // On exit:
+    //  buffer->mFrameCount is zero.
+    //  buffer->mRaw is NULL.
+    virtual void        releaseBuffer(Buffer* buffer);
+
+protected:
+    size_t      mUnreleased;    // unreleased frames remaining from most recent obtainBuffer()
+    size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
+private:
+    int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
+    bool        mDeferWake;     // whether another releaseBuffer() is expected soon
+};
+
+// Proxy used by AudioFlinger for servicing AudioTrack
+class AudioTrackServerProxy : public ServerProxy {
+public:
+    AudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
+            size_t frameSize, bool clientInServer = false)
+        : ServerProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/, clientInServer) { }
+protected:
+    virtual ~AudioTrackServerProxy() { }
+
+public:
     // return value of these methods must be validated by the caller
     uint32_t    getSampleRate() const { return mCblk->mSampleRate; }
     uint16_t    getSendLevel_U4_12() const { return mCblk->mSendLevel; }
     uint32_t    getVolumeLR() const { return mCblk->mVolumeLR; }
 
-    // for AudioTrack only
-    size_t      framesReady() {
-        ALOG_ASSERT(mIsOut);
-        return mCblk->framesReady(true);
-    }
+    // estimated total number of filled frames available to server to read,
+    // which may include non-contiguous frames
+    virtual size_t      framesReady();
 
-    // for AudioRecord only, called by RecordThread::RecordTrack::getNextBuffer
-    // FIXME remove this API since it assumes a lock that should be invisible to caller
-    size_t      framesAvailableIn_l() {
-        ALOG_ASSERT(!mIsOut);
-        return mCblk->framesAvailable_l(mFrameCount, false);
-    }
+    // Currently AudioFlinger will call framesReady() for a fast track from two threads:
+    // FastMixer thread, and normal mixer thread.  This is dangerous, as the proxy is intended
+    // to be called from at most one thread of server, and one thread of client.
+    // As a temporary workaround, this method informs the proxy implementation that it
+    // should avoid doing a state queue poll from within framesReady().
+    // FIXME Change AudioFlinger to not call framesReady() from normal mixer thread.
+    virtual void        framesReadyIsCalledByMultipleThreads() { }
+};
+
+class StaticAudioTrackServerProxy : public AudioTrackServerProxy {
+public:
+    StaticAudioTrackServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
+            size_t frameSize);
+protected:
+    virtual ~StaticAudioTrackServerProxy() { }
+
+public:
+    virtual size_t      framesReady();
+    virtual void        framesReadyIsCalledByMultipleThreads();
+    virtual status_t    obtainBuffer(Buffer* buffer);
+    virtual void        releaseBuffer(Buffer* buffer);
 
 private:
-    const bool  mIsOut;     // true for AudioTrack, false for AudioRecord
+    ssize_t             pollPosition(); // poll for state queue update, and return current position
+    StaticAudioTrackSingleStateQueue::Observer  mObserver;
+    size_t              mPosition;  // server's current play position in frames, relative to 0
+    size_t              mEnd;       // cached value computed from mState, safe for asynchronous read
+    bool                mFramesReadyIsCalledByMultipleThreads;
+    StaticAudioTrackState   mState;
+};
 
+// Proxy used by AudioFlinger for servicing AudioRecord
+class AudioRecordServerProxy : public ServerProxy {
+public:
+    AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
+            size_t frameSize)
+        : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/,
+            false /*clientInServer*/) { }
+protected:
+    virtual ~AudioRecordServerProxy() { }
 };
 
 // ----------------------------------------------------------------------------