AudioTrack: Prevent server from reading client data after stop

Prior to this CL, if an AudioTrack client wrote audio data after
AudioTrack stop(), but before the track was drained by the server,
the newly written client data would be consumed in the drain.

We now limit the server read to the client write position on stop.
This interlocking is essential for rapid asynchronous AudioTrack
command processing.

Test: AudioTrack CTS, SoundPool looping, bug test case
Bug: 75788313
Change-Id: Ib70e3dc46afe047a8c6cf1fb906a618b3c66cc7f
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index b4fa3c5..ca119d5 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -60,6 +60,8 @@
     volatile int32_t mRear;     // written by producer (output: client, input: server)
     volatile int32_t mFlush;    // incremented by client to indicate a request to flush;
                                 // server notices and discards all data between mFront and mRear
+    volatile int32_t mStop;     // set by client to indicate a stop frame position; server
+                                // will not read beyond this position until start is called.
     volatile uint32_t mUnderrunFrames; // server increments for each unavailable but desired frame
     volatile uint32_t mUnderrunCount;  // server increments for each underrun occurrence
 };
@@ -335,6 +337,8 @@
         mTimestamp.clear();
     }
 
+    virtual void stop() { }; // called by client in AudioTrack::stop()
+
 private:
     // This is a copy of mCblk->mBufferSizeInFrames
     uint32_t   mBufferSizeInFrames;  // effective size of the buffer
@@ -383,8 +387,14 @@
         mPlaybackRateMutator.push(playbackRate);
     }
 
+    // Sends flush and stop position information from the client to the server,
+    // used by streaming AudioTrack flush() or stop().
+    void sendStreamingFlushStop(bool flush);
+
     virtual void flush();
 
+            void stop() override;
+
     virtual uint32_t    getUnderrunFrames() const {
         return mCblk->u.mStreaming.mUnderrunFrames;
     }
@@ -410,6 +420,8 @@
 
     virtual void    flush();
 
+    void stop() override;
+
 #define MIN_LOOP    16  // minimum length of each loop iteration in frames
 
             // setLoop(), setBufferPosition(), and setBufferPositionAndLoop() set the
@@ -532,6 +544,10 @@
     //   client will be notified via Futex
     virtual void    flushBufferIfNeeded();
 
+    // Returns the rear position of the AudioTrack shared ring buffer, limited by
+    // the stop frame position level.
+    virtual int32_t getRear() const = 0;
+
     // Total count of the number of flushed frames since creation (never reset).
     virtual int64_t     framesFlushed() const { return mFlushed; }
 
@@ -607,10 +623,18 @@
         return mDrained.load();
     }
 
+    int32_t             getRear() const override;
+
+    // Called on server side track start().
+    virtual void        start();
+
 private:
     AudioPlaybackRate             mPlaybackRate;  // last observed playback rate
     PlaybackRateQueue::Observer   mPlaybackRateObserver;
 
+    // Last client stop-at position when start() was called. Used for streaming AudioTracks.
+    std::atomic<int32_t>          mStopLast{0};
+
     // The server keeps a copy here where it is safe from the client.
     uint32_t                      mUnderrunCount; // echoed to mCblk
     bool                          mUnderrunning;  // used to detect edge of underrun
@@ -634,6 +658,10 @@
     virtual void        tallyUnderrunFrames(uint32_t frameCount);
     virtual uint32_t    getUnderrunFrames() const { return 0; }
 
+    int32_t getRear() const override;
+
+    void start() override { } // ignore for static tracks
+
 private:
     status_t            updateStateWithLoop(StaticAudioTrackState *localState,
                                             const StaticAudioTrackState &update) const;
@@ -661,6 +689,10 @@
             size_t frameSize, bool clientInServer)
         : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { }
 
+    int32_t getRear() const override {
+        return mCblk->u.mStreaming.mRear; // For completeness only; mRear written by server.
+    }
+
 protected:
     virtual ~AudioRecordServerProxy() { }
 };