AudioTrack: fix stall if setBufferSizeInFrames() called before play()

The server was waiting for a full buffer.
But the buffer was only getting partly filled.
So the stream was not starting.

The fix involves having the server look at the adjustable threshold.

Bug: 27505889
Change-Id: I5dbf686413e670dacbbecc9e0f838744e465f44f
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 423273d..272b0cd 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -860,7 +860,7 @@
     if (mOutput == AUDIO_IO_HANDLE_NONE || mProxy.get() == 0) {
         return NO_INIT;
     }
-    return mProxy->getBufferSizeInFrames();
+    return (ssize_t) mProxy->getBufferSizeInFrames();
 }
 
 ssize_t AudioTrack::setBufferSizeInFrames(size_t bufferSizeInFrames)
@@ -873,10 +873,7 @@
     if (!audio_is_linear_pcm(mFormat)) {
         return INVALID_OPERATION;
     }
-    // TODO also need to inform the server side (through mAudioTrack) that
-    // the buffer count is reduced, otherwise the track may never start
-    // because the server thinks it is never filled.
-    return mProxy->setBufferSizeInFrames(bufferSizeInFrames);
+    return (ssize_t) mProxy->setBufferSizeInFrames((uint32_t) bufferSizeInFrames);
 }
 
 status_t AudioTrack::setLoop(uint32_t loopStart, uint32_t loopEnd, int loopCount)
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 1d15495..7d7134a 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -46,8 +46,10 @@
 }
 
 audio_track_cblk_t::audio_track_cblk_t()
-    : mServer(0), mFutex(0), mMinimum(0),
-    mVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY), mSampleRate(0), mSendLevel(0), mFlags(0)
+    : mServer(0), mFutex(0), mMinimum(0)
+    , mVolumeLR(GAIN_MINIFLOAT_PACKED_UNITY), mSampleRate(0), mSendLevel(0)
+    , mBufferSizeInFrames(0)
+    , mFlags(0)
 {
     memset(&u, 0, sizeof(u));
 }
@@ -67,10 +69,10 @@
 ClientProxy::ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
         size_t frameSize, bool isOut, bool clientInServer)
     : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer)
-    , mBufferSizeInFrames(frameCount)
     , mEpoch(0)
     , mTimestampObserver(&cblk->mExtendedTimestampQueue)
 {
+    setBufferSizeInFrames(frameCount);
 }
 
 const struct timespec ClientProxy::kForever = {INT_MAX /*tv_sec*/, 0 /*tv_nsec*/};
@@ -84,6 +86,26 @@
 // order of minutes.
 #define MAX_SEC    5
 
+uint32_t ClientProxy::setBufferSizeInFrames(uint32_t size)
+{
+    // TODO set minimum to 2X the fast mixer buffer size.
+    // The minimum should be  greater than zero and less than the size
+    // at which underruns will occur.
+    const uint32_t minimum = 128 * 2; // arbitrary
+    const uint32_t maximum = frameCount();
+    uint32_t clippedSize = size;
+    if (clippedSize < minimum) {
+        clippedSize = minimum;
+    } else if (clippedSize > maximum) {
+        clippedSize = maximum;
+    }
+    // for server to read
+    android_atomic_release_store(clippedSize, (int32_t *)&mCblk->mBufferSizeInFrames);
+    // for client to read
+    mBufferSizeInFrames = clippedSize;
+    return clippedSize;
+}
+
 status_t ClientProxy::obtainBuffer(Buffer* buffer, const struct timespec *requested,
         struct timespec *elapsed)
 {
@@ -174,7 +196,7 @@
         // The calculation for avail can go negative if the buffer size
         // is suddenly dropped below the amount already in the buffer.
         // So use a signed calculation to prevent a numeric overflow abort.
-        ssize_t adjustableSize = (ssize_t) mBufferSizeInFrames;
+        ssize_t adjustableSize = (ssize_t) getBufferSizeInFrames();
         ssize_t avail =  (mIsOut) ? adjustableSize - filled : filled;
         if (avail < 0) {
             avail = 0;
@@ -357,20 +379,6 @@
             (mFrameCountP2 - 1);
 }
 
-size_t ClientProxy::setBufferSizeInFrames(size_t size)
-{
-    // TODO set minimum to 2X the fast mixer buffer size.
-    size_t minimum = 128 * 2; // arbitrary
-    size_t maximum = frameCount();
-    if (size < minimum) {
-        size = minimum;
-    } else if (size > maximum) {
-        size = maximum;
-    }
-    mBufferSizeInFrames = size;
-    return size;
-}
-
 // ---------------------------------------------------------------------------
 
 void AudioTrackClientProxy::flush()
@@ -601,6 +609,7 @@
       mAvailToClient(0), mFlush(0), mReleased(0)
     , mTimestampMutator(&cblk->mExtendedTimestampQueue)
 {
+    cblk->mBufferSizeInFrames = frameCount;
 }
 
 status_t ServerProxy::obtainBuffer(Buffer* buffer, bool ackFlush)