Start isolating control block accesses in a proxy

The proxy object will eventually be the only code that understands the
details of the control block.  This should make it easier to change the
control block in the future.

Initial set of control block fields that are isolated:
 - sample rate
 - send level
 - volume

Prepare for streaming/static separation by adding a union to the control
block for the new fields.

Fix bug in handling of max sample rate on a track.  It was only checking
at re-configuration, not at each mix.

Simplify OutputTrack::obtainBuffer.

Change-Id: I2249f9d04f73a911a922ad1d7f6197292c74cd92
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 48b6b21..41e20f8 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -21,6 +21,7 @@
 #include <sys/types.h>
 
 #include <utils/threads.h>
+#include <utils/Log.h>
 
 namespace android {
 
@@ -38,9 +39,26 @@
 #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
 
+struct AudioTrackSharedStreaming {
+    // similar to NBAIO MonoPipe
+    volatile int32_t mFront;
+    volatile int32_t mRear;
+};
+
+// future
+struct AudioTrackSharedStatic {
+    int mReserved;
+};
+
+// ----------------------------------------------------------------------------
+
 // Important: do not add any virtual methods, including ~
 struct audio_track_cblk_t
 {
+                friend class Proxy;
+                friend class AudioTrackClientProxy;
+                friend class AudioRecordClientProxy;
+                friend class ServerProxy;
 
     // The data members are grouped so that members accessed frequently and in the same context
     // are in the same line of data cache.
@@ -72,12 +90,13 @@
                 // For AudioTrack only, not used by AudioRecord.
 private:
                 uint32_t    mVolumeLR;
-public:
 
-                uint32_t    sampleRate;
+                uint32_t    mSampleRate;    // AudioTrack only: client's requested sample rate in Hz
+                                            // or 0 == default. Write-only client, read-only server.
 
                 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
 
@@ -94,65 +113,184 @@
 
                 // Cache line boundary (32 bytes)
 
+#if 0
+                union {
+                    AudioTrackSharedStreaming   mStreaming;
+                    AudioTrackSharedStatic      mStatic;
+                    int                         mAlign[8];
+                } 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();
 
-                // called by client only, where client includes regular
-                // AudioTrack and AudioFlinger::PlaybackThread::OutputTrack
-                uint32_t    stepUserIn(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, false); }
-                uint32_t    stepUserOut(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, true); }
-
-                bool        stepServer(size_t stepCount, size_t frameCount, bool isOut);
-
+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, uint32_t offset) const;
-
-                uint32_t    framesAvailableIn(size_t frameCount)
-                                { return framesAvailable(frameCount, false); }
-                uint32_t    framesAvailableOut(size_t frameCount)
-                                { return framesAvailable(frameCount, true); }
-                uint32_t    framesAvailableIn_l(size_t frameCount)
-                                { return framesAvailable_l(frameCount, false); }
-                uint32_t    framesAvailableOut_l(size_t frameCount)
-                                { return framesAvailable_l(frameCount, true); }
-                uint32_t    framesReadyIn() { return framesReady(false); }
-                uint32_t    framesReadyOut() { return framesReady(true); }
+                void*       buffer(void *buffers, uint32_t frameSize, size_t offset) const;
 
                 bool        tryLock();
 
-                // No barriers on the following operations, so the ordering of loads/stores
-                // with respect to other parameters is UNPREDICTABLE. That's considered safe.
-
-                // for AudioTrack client only, caller must limit to 0.0 <= sendLevel <= 1.0
-                void        setSendLevel(float sendLevel) {
-                    mSendLevel = uint16_t(sendLevel * 0x1000);
-                }
-
-                // for AudioFlinger only; the return value must be validated by the caller
-                uint16_t    getSendLevel_U4_12() const {
-                    return mSendLevel;
-                }
-
-                // for AudioTrack client only, caller must limit to 0 <= volumeLR <= 0x10001000
-                void        setVolumeLR(uint32_t volumeLR) {
-                    mVolumeLR = volumeLR;
-                }
-
-                // for AudioFlinger only; the return value must be validated by the caller
-                uint32_t    getVolumeLR() const {
-                    return mVolumeLR;
-                }
-
-private:
                 // 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);
 };
 
+// ----------------------------------------------------------------------------
+
+// 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 {
+protected:
+    Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
+        : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { }
+    virtual ~Proxy() { }
+
+public:
+    void*   buffer(size_t offset) const {
+        return mCblk->buffer(mBuffers, mFrameSize, offset);
+    }
+
+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
+
+    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
+
+};
+
+// ----------------------------------------------------------------------------
+
+// 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) { }
+    virtual ~ClientProxy() { }
+};
+
+// ----------------------------------------------------------------------------
+
+// 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) { }
+    virtual ~AudioTrackClientProxy() { }
+
+    // No barriers on the following operations, so the ordering of loads/stores
+    // with respect to other parameters is UNPREDICTABLE. That's considered safe.
+
+    // caller must limit to 0.0 <= sendLevel <= 1.0
+    void        setSendLevel(float sendLevel) {
+        mCblk->mSendLevel = uint16_t(sendLevel * 0x1000);
+    }
+
+    // caller must limit to 0 <= volumeLR <= 0x10001000
+    void        setVolumeLR(uint32_t volumeLR) {
+        mCblk->mVolumeLR = volumeLR;
+    }
+
+    void        setSampleRate(uint32_t sampleRate) {
+        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*/);
+    }
+
+    // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer
+    size_t      framesAvailable() {
+        return mCblk->framesAvailable(mFrameCount, true /*isOut*/);
+    }
+
+    // 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*/);
+    }
+
+};
+
+// ----------------------------------------------------------------------------
+
+// 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() { }
+
+    // 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 {
+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); }
+
+    // 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);
+    }
+
+    // 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);
+    }
+
+private:
+    const bool  mIsOut;     // true for AudioTrack, false for AudioRecord
+
+};
 
 // ----------------------------------------------------------------------------