Fix race condition for non-started fast tracks

This required re-implementing how fast tracks are considered active.
Now, they use the same logic as normal tracks, except underrun is ignored.

Other changes:
 - add framesReady() to AudioBufferProvider interface
 - rebased
 - add track underrun counter state to fast mixer dump state
 - move dumpsys header to Track::appendDumpHeader()
   so it closer to where tracks are dumped
 - display track state in dumpsys as a character code
 - measure and display warmup time and cycles in dumpsys
 - copy in the presentation complete code
 - add ExtendedAudioBufferProvider for framesReady() which returns size_t
 - simplify underrun tracking
 - deferred reset track after stop()
 - add comments

Change-Id: I7db8821bc565230ec76da1f9380fe3fb09735e5b
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 9a0bbcd..0b73a30 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -46,6 +46,7 @@
 #include <hardware/audio_policy.h>
 
 #include "AudioBufferProvider.h"
+#include "ExtendedAudioBufferProvider.h"
 #include "FastMixer.h"
 #include "NBAIO.h"
 
@@ -355,7 +356,7 @@
         void clearPowerManager();
 
         // base for record and playback
-        class TrackBase : public AudioBufferProvider, public RefBase {
+        class TrackBase : public ExtendedAudioBufferProvider, public RefBase {
 
         public:
             enum track_state {
@@ -396,6 +397,10 @@
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts) = 0;
             virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer);
 
+            // ExtendedAudioBufferProvider interface is only needed for Track,
+            // but putting it in TrackBase avoids the complexity of virtual inheritance
+            virtual size_t  framesReady() const { return SIZE_MAX; }
+
             audio_format_t format() const {
                 return mFormat;
             }
@@ -676,6 +681,7 @@
                                         IAudioFlinger::track_flags_t flags);
             virtual             ~Track();
 
+            static  void        appendDumpHeader(String8& result);
                     void        dump(char* buffer, size_t size);
             virtual status_t    start(AudioSystem::sync_event_t event = AudioSystem::SYNC_EVENT_NONE,
                                      int triggerSession = 0);
@@ -699,11 +705,6 @@
                     int16_t     *mainBuffer() const { return mMainBuffer; }
                     int         auxEffectId() const { return mAuxEffectId; }
 
-#if 0
-                    bool        isFastTrack() const
-                            { return (mFlags & IAudioFlinger::TRACK_FAST) != 0; }
-#endif
-
         // implement FastMixerState::VolumeProvider interface
             virtual uint32_t    getVolumeLR();
 
@@ -720,7 +721,7 @@
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer, int64_t pts = kInvalidPTS);
             // releaseBuffer() not overridden
 
-            virtual uint32_t framesReady() const;
+            virtual size_t framesReady() const;
 
             bool isMuted() const { return mMute; }
             bool isPausing() const {
@@ -729,6 +730,9 @@
             bool isPaused() const {
                 return mState == PAUSED;
             }
+            bool isResuming() const {
+                return mState == RESUMING;
+            }
             bool isReady() const;
             void setPaused() { mState = PAUSED; }
             void reset();
@@ -756,7 +760,9 @@
             const sp<IMemory>   mSharedBuffer;
             bool                mResetDone;
             const audio_stream_type_t mStreamType;
-            int                 mName;      // track name on the normal mixer
+            int                 mName;      // track name on the normal mixer,
+                                            // allocated statically at track creation time,
+                                            // and is even allocated (though unused) for fast tracks
             int16_t             *mMainBuffer;
             int32_t             *mAuxBuffer;
             int                 mAuxEffectId;
@@ -765,7 +771,17 @@
                                                        // when this track will be fully rendered
         private:
             IAudioFlinger::track_flags_t mFlags;
-            int                 mFastIndex; // index within FastMixerState::mFastTracks[] or -1
+
+            // The following fields are only for fast tracks, and should be in a subclass
+            int                 mFastIndex; // index within FastMixerState::mFastTracks[];
+                                            // either mFastIndex == -1
+                                            // or 0 < mFastIndex < FastMixerState::kMaxFast because
+                                            // index 0 is reserved for normal mixer's submix;
+                                            // index is allocated statically at track creation time
+                                            // but the slot is only used if track is active
+            uint32_t            mObservedUnderruns; // Most recently observed value of
+                                            // mFastMixerDumpState.mTracks[mFastIndex].mUnderruns
+            uint32_t            mUnderrunCount; // Counter of total number of underruns, never reset
             volatile float      mCachedVolume;  // combined master volume and stream type volume;
                                                 // 'volatile' means accessed without lock or
                                                 // barrier, but is read/written atomically
@@ -800,7 +816,7 @@
 
             // Mixer facing methods.
             virtual bool isTimedTrack() const { return true; }
-            virtual uint32_t framesReady() const;
+            virtual size_t framesReady() const;
 
             // AudioBufferProvider interface
             virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer,
@@ -921,9 +937,9 @@
         virtual     void        threadLoop_standby();
         virtual     void        threadLoop_removeTracks(const Vector< sp<Track> >& tracksToRemove) { }
 
-                    // prepareTracks_l reads and writes mActiveTracks, and also returns the
-                    // pending set of tracks to remove via Vector 'tracksToRemove'.  The caller is
-                    // responsible for clearing or destroying this Vector later on, when it
+                    // prepareTracks_l reads and writes mActiveTracks, and returns
+                    // the pending set of tracks to remove via Vector 'tracksToRemove'.  The caller
+                    // is responsible for clearing or destroying this Vector later on, when it
                     // is safe to do so. That will drop the final ref count and destroy the tracks.
         virtual     mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove) = 0;
 
@@ -993,7 +1009,7 @@
         bool                            mMasterMute;
                     void        setMasterMute_l(bool muted) { mMasterMute = muted; }
     protected:
-        SortedVector< wp<Track> >       mActiveTracks;
+        SortedVector< wp<Track> >       mActiveTracks;  // FIXME check if this could be sp<>
 
         // Allocate a track name for a given channel mask.
         //   Returns name >= 0 if successful, -1 on failure.
@@ -1080,12 +1096,11 @@
         sp<NBAIO_Sink>          mNormalSink;
     public:
         virtual     bool        hasFastMixer() const = 0;
+        virtual     uint32_t    getFastTrackUnderruns(size_t fastIndex) const { return 0; }
 
     protected:
                     // accessed by both binder threads and within threadLoop(), lock on mutex needed
                     unsigned    mFastTrackAvailMask;    // bit i set if fast track [i] is available
-                    unsigned    mFastTrackNewMask;      // bit i set if fast track [i] just created
-                    Track*      mFastTrackNewArray[FastMixerState::kMaxFastTracks];
 
     };
 
@@ -1136,6 +1151,11 @@
 
     public:
         virtual     bool        hasFastMixer() const { return mFastMixer != NULL; }
+        virtual     uint32_t    getFastTrackUnderruns(size_t fastIndex) const {
+                                    ALOG_ASSERT(0 < fastIndex &&
+                                            fastIndex < FastMixerState::kMaxFastTracks);
+                                    return mFastMixerDumpState.mTracks[fastIndex].mUnderruns;
+                                }
     };
 
     class DirectOutputThread : public PlaybackThread {