Merge "Enable FastTrack timestamps" into nyc-dev
diff --git a/include/media/AudioTimestamp.h b/include/media/AudioTimestamp.h
index e6ca225..531b548 100644
--- a/include/media/AudioTimestamp.h
+++ b/include/media/AudioTimestamp.h
@@ -79,7 +79,7 @@
 
     // Returns the best timestamp as judged from the closest-to-hw stage in the
     // pipeline with a valid timestamp.
-    int getBestTimestamp(int64_t *position, int64_t *time, int timebase) {
+    status_t getBestTimestamp(int64_t *position, int64_t *time, int timebase) const {
         if (position == nullptr || time == nullptr
                 || timebase < 0 || timebase >= TIMEBASE_MAX) {
             return BAD_VALUE;
@@ -97,6 +97,20 @@
         return INVALID_OPERATION;
     }
 
+    status_t getBestTimestamp(AudioTimestamp *timestamp) const {
+        if (timestamp == nullptr) {
+            return BAD_VALUE;
+        }
+        int64_t position, time;
+        if (getBestTimestamp(&position, &time, TIMEBASE_MONOTONIC) == OK) {
+            timestamp->mPosition = position;
+            timestamp->mTime.tv_sec = time / 1000000000;
+            timestamp->mTime.tv_nsec = time - timestamp->mTime.tv_sec * 1000000000LL;
+            return OK;
+        }
+        return INVALID_OPERATION;
+    }
+
     // convert fields to a printable string
     std::string toString() {
         std::stringstream ss;
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 2270c85..aa9e98c 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -315,6 +315,19 @@
     // See documentation for AudioTrack.setBufferSizeInFrames()
     size_t      setBufferSizeInFrames(size_t requestedSize);
 
+    status_t    getTimestamp(ExtendedTimestamp *timestamp) {
+        if (timestamp == nullptr) {
+            return BAD_VALUE;
+        }
+        (void) mTimestampObserver.poll(mTimestamp);
+        *timestamp = mTimestamp;
+        return OK;
+    }
+
+    void        clearTimestamp() {
+        mTimestamp.clear();
+    }
+
 protected:
     // This is set by AudioTrack.setBufferSizeInFrames().
     // A write will not fill the buffer above this limit.
@@ -322,6 +335,12 @@
 
 private:
     Modulo<uint32_t> mEpoch;
+
+    // The shared buffer contents referred to by the timestamp observer
+    // is initialized when the server proxy created.  A local zero timestamp
+    // is initialized by the client constructor.
+    ExtendedTimestampQueue::Observer mTimestampObserver;
+    ExtendedTimestamp mTimestamp; // initialized by constructor
 };
 
 // ----------------------------------------------------------------------------
@@ -333,7 +352,9 @@
             size_t frameSize, bool clientInServer = false)
         : ClientProxy(cblk, buffers, frameCount, frameSize, true /*isOut*/,
           clientInServer),
-          mPlaybackRateMutator(&cblk->mPlaybackRateQueue) { }
+          mPlaybackRateMutator(&cblk->mPlaybackRateQueue) {
+    }
+
     virtual ~AudioTrackClientProxy() { }
 
     // No barriers on the following operations, so the ordering of loads/stores
@@ -431,23 +452,9 @@
     AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
             size_t frameSize)
         : ClientProxy(cblk, buffers, frameCount, frameSize,
-            false /*isOut*/, false /*clientInServer*/)
-        , mTimestampObserver(&cblk->mExtendedTimestampQueue) { }
+            false /*isOut*/, false /*clientInServer*/) { }
     ~AudioRecordClientProxy() { }
 
-    status_t    getTimestamp(ExtendedTimestamp *timestamp) {
-        if (timestamp == nullptr) {
-            return BAD_VALUE;
-        }
-        (void) mTimestampObserver.poll(mTimestamp);
-        *timestamp = mTimestamp;
-        return OK;
-    }
-
-    void        clearTimestamp() {
-        mTimestamp.clear();
-    }
-
     // Advances the client read pointer to the server write head pointer
     // effectively flushing the client read buffer. The effect is
     // instantaneous. Returns the number of frames flushed.
@@ -457,13 +464,6 @@
         android_atomic_release_store(rear, &mCblk->u.mStreaming.mFront);
         return (Modulo<int32_t>(rear) - front).unsignedValue();
     }
-
-private:
-    // The shared buffer contents referred to by the timestamp observer
-    // is initialized when the server proxy created.  A local zero timestamp
-    // is initialized by the client constructor.
-    ExtendedTimestampQueue::Observer mTimestampObserver;
-    ExtendedTimestamp mTimestamp; // initialized by constructor
 };
 
 // ----------------------------------------------------------------------------
@@ -509,10 +509,20 @@
     //  buffer->mRaw is NULL.
     virtual void        releaseBuffer(Buffer* buffer);
 
+    // Return the total number of frames that AudioFlinger has obtained and released
+    virtual int64_t     framesReleased() const { return mReleased; }
+
+    // Expose timestamp to client proxy. Should only be called by a single thread.
+    virtual void        setTimestamp(const ExtendedTimestamp &timestamp) {
+        mTimestampMutator.push(timestamp);
+    }
+
 protected:
     size_t      mAvailToClient; // estimated frames available to client prior to releaseBuffer()
     int32_t     mFlush;         // our copy of cblk->u.mStreaming.mFlush, for streaming output only
     int64_t     mReleased;      // our copy of cblk->mServer, at 64 bit resolution
+
+    ExtendedTimestampQueue::Mutator mTimestampMutator;
 };
 
 // Proxy used by AudioFlinger for servicing AudioTrack
@@ -556,9 +566,6 @@
     // and thus which resulted in an underrun.
     virtual uint32_t    getUnderrunFrames() const { return mCblk->u.mStreaming.mUnderrunFrames; }
 
-    // Return the total number of frames that AudioFlinger has obtained and released
-    virtual size_t      framesReleased() const { return mReleased; }
-
     // Return the playback speed and pitch read atomically. Not multi-thread safe on server side.
     AudioPlaybackRate getPlaybackRate();
 
@@ -611,20 +618,10 @@
 public:
     AudioRecordServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount,
             size_t frameSize, bool clientInServer)
-        : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer)
-        , mTimestampMutator(&cblk->mExtendedTimestampQueue) { }
+        : ServerProxy(cblk, buffers, frameCount, frameSize, false /*isOut*/, clientInServer) { }
 
-    // Return the total number of frames that AudioFlinger has obtained and released
-    virtual int64_t     framesReleased() const { return mReleased; }
-
-    // Expose timestamp to client proxy. Should only be called by a single thread.
-    virtual void        setExtendedTimestamp(const ExtendedTimestamp &timestamp) {
-                            mTimestampMutator.push(timestamp);
-                        }
 protected:
     virtual ~AudioRecordServerProxy() { }
-
-    ExtendedTimestampQueue::Mutator       mTimestampMutator;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index b2a5f14..33dcc57 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -528,12 +528,14 @@
         mTimestampStartupGlitchReported = false;
         mRetrogradeMotionReported = false;
 
-        // If previousState == STATE_STOPPED, we reactivate markers (mMarkerPosition != 0)
+        // If previousState == STATE_STOPPED, we clear the timestamp so that it
+        // needs a new server push. We also reactivate markers (mMarkerPosition != 0)
         // as the position is reset to 0. This is legacy behavior. This is not done
         // in stop() to avoid a race condition where the last marker event is issued twice.
         // Note: the if is technically unnecessary because previousState == STATE_FLUSHED
         // is only for streaming tracks, and mMarkerReached is already set to false.
         if (previousState == STATE_STOPPED) {
+            mProxy->clearTimestamp(); // need new server push for valid timestamp
             mMarkerReached = false;
         }
 
@@ -2169,11 +2171,6 @@
     // Set false here to cover all the error return cases.
     mPreviousTimestampValid = false;
 
-    // FIXME not implemented for fast tracks; should use proxy and SSQ
-    if (mFlags & AUDIO_OUTPUT_FLAG_FAST) {
-        return INVALID_OPERATION;
-    }
-
     switch (mState) {
     case STATE_ACTIVE:
     case STATE_PAUSED:
@@ -2203,7 +2200,22 @@
 
     // The presented frame count must always lag behind the consumed frame count.
     // To avoid a race, read the presented frames first.  This ensures that presented <= consumed.
-    status_t status = mAudioTrack->getTimestamp(timestamp);
+
+    status_t status;
+    if (!(mFlags & AUDIO_OUTPUT_FLAG_FAST)) {
+        // use Binder to get timestamp
+        status = mAudioTrack->getTimestamp(timestamp);
+    } else {
+        // read timestamp from shared memory
+        ExtendedTimestamp ets;
+        status = mProxy->getTimestamp(&ets);
+        if (status == OK) {
+            status = ets.getBestTimestamp(&timestamp);
+        }
+        if (status == INVALID_OPERATION) {
+            status = WOULD_BLOCK;
+        }
+    }
     if (status != NO_ERROR) {
         ALOGV_IF(status != WOULD_BLOCK, "getTimestamp error:%#x", status);
         return status;
diff --git a/media/libmedia/AudioTrackShared.cpp b/media/libmedia/AudioTrackShared.cpp
index 988386e..1d15495 100644
--- a/media/libmedia/AudioTrackShared.cpp
+++ b/media/libmedia/AudioTrackShared.cpp
@@ -69,6 +69,7 @@
     : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer)
     , mBufferSizeInFrames(frameCount)
     , mEpoch(0)
+    , mTimestampObserver(&cblk->mExtendedTimestampQueue)
 {
 }
 
@@ -598,6 +599,7 @@
         size_t frameSize, bool isOut, bool clientInServer)
     : Proxy(cblk, buffers, frameCount, frameSize, isOut, clientInServer),
       mAvailToClient(0), mFlush(0), mReleased(0)
+    , mTimestampMutator(&cblk->mExtendedTimestampQueue)
 {
 }
 
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index c81bbf9..fe3cc53 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -89,6 +89,7 @@
     // ExtendedAudioBufferProvider interface
     virtual size_t framesReady() const;
     virtual size_t framesReleased() const;
+    virtual void onTimestamp(const AudioTimestamp &timestamp);
 
     bool isPausing() const { return mState == PAUSING; }
     bool isPaused() const { return mState == PAUSED; }
diff --git a/services/audioflinger/RecordTracks.h b/services/audioflinger/RecordTracks.h
index 5f70479..6f84af1 100644
--- a/services/audioflinger/RecordTracks.h
+++ b/services/audioflinger/RecordTracks.h
@@ -76,8 +76,6 @@
             // be dropped and therefore not read by the application.
             sp<SyncEvent>                       mSyncStartEvent;
 
-            AudioRecordServerProxy             *mAudioRecordServerProxy;
-
             // number of captured frames to drop after the start sync event has been received.
             // when < 0, maximum frames to drop before starting capture even if sync event is
             // not received
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 5aff394..4807400 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -6157,7 +6157,7 @@
 
             // update frame information and push timestamp out
             activeTrack->updateTrackFrameInfo(
-                    activeTrack->mAudioRecordServerProxy->framesReleased(),
+                    activeTrack->mServerProxy->framesReleased(),
                     mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER],
                     mSampleRate, mTimestamp);
         }
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b719046..536581c 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -596,6 +596,20 @@
     return mAudioTrackServerProxy->framesReleased();
 }
 
+void AudioFlinger::PlaybackThread::Track::onTimestamp(const AudioTimestamp &timestamp)
+{
+    // This call comes from a FastTrack and should be kept lockless.
+    // The server side frames are already translated to client frames.
+
+    ExtendedTimestamp ets;
+    ets.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
+            timestamp.mTime.tv_sec * 1000000000LL + timestamp.mTime.tv_nsec;
+    ets.mPosition[ExtendedTimestamp::LOCATION_KERNEL] = timestamp.mPosition;
+
+    // Caution, this doesn't set the timebase for BOOTTIME properly, but is ignored right now.
+    mAudioTrackServerProxy->setTimestamp(ets);
+}
+
 // Don't call for fast tracks; the framesReady() could result in priority inversion
 bool AudioFlinger::PlaybackThread::Track::isReady() const {
     if (mFillingUpStatus != FS_FILLING || isStopped() || isPausing()) {
@@ -1438,9 +1452,8 @@
         return;
     }
 
-    mAudioRecordServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
+    mServerProxy = new AudioRecordServerProxy(mCblk, mBuffer, frameCount,
             mFrameSize, !isExternalTrack());
-    mServerProxy = mAudioRecordServerProxy;
 
     mResamplerBufferProvider = new ResamplerBufferProvider(this);
 
@@ -1594,7 +1607,7 @@
             local.mPosition[i] = relativeTrackFrames + trackFramesReleased;
         }
     }
-    mAudioRecordServerProxy->setExtendedTimestamp(local);
+    mServerProxy->setTimestamp(local);
 }
 
 AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,