Fix AudioTrack presentationComplete regression

Bug: 27310929
Change-Id: Id52299660d90b07220a4fd9996da53fe755a41f1
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index e0d8f75..e056ef2 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1565,6 +1565,7 @@
         mEffectBufferFormat(AUDIO_FORMAT_INVALID),
         mEffectBufferValid(false),
         mSuspended(0), mBytesWritten(0),
+        mFramesWritten(0),
         mActiveTracksGeneration(0),
         // mStreamTypes[] initialized in constructor body
         mOutput(output),
@@ -2863,6 +2864,7 @@
             // and associate with the sink frames written out.  We need
             // this to convert the sink timestamp to the track timestamp.
             if (mNormalSink != 0) {
+                // Note: The DuplicatingThread may not have a mNormalSink.
                 // We always fetch the timestamp here because often the downstream
                 // sink will block whie writing.
                 ExtendedTimestamp timestamp; // use private copy to fetch
@@ -2872,23 +2874,20 @@
                         timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
                 mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
                         timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
-
-                // sinkFramesWritten for non-offloaded tracks are contiguous
-                // even after standby() is called. This is useful for the track frame
-                // to sink frame mapping.
-                const int64_t sinkFramesWritten = mNormalSink->framesWritten();
-                mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = sinkFramesWritten;
-                mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime();
-
-                const size_t size = mActiveTracks.size();
-                for (size_t i = 0; i < size; ++i) {
-                    sp<Track> t = mActiveTracks[i].promote();
-                    if (t != 0 && !t->isFastTrack()) {
-                        t->updateTrackFrameInfo(
-                                t->mAudioTrackServerProxy->framesReleased(),
-                                sinkFramesWritten,
-                                mTimestamp);
-                    }
+            }
+            // mFramesWritten for non-offloaded tracks are contiguous
+            // even after standby() is called. This is useful for the track frame
+            // to sink frame mapping.
+            mTimestamp.mPosition[ExtendedTimestamp::LOCATION_SERVER] = mFramesWritten;
+            mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_SERVER] = systemTime();
+            const size_t size = mActiveTracks.size();
+            for (size_t i = 0; i < size; ++i) {
+                sp<Track> t = mActiveTracks[i].promote();
+                if (t != 0 && !t->isFastTrack()) {
+                    t->updateTrackFrameInfo(
+                            t->mAudioTrackServerProxy->framesReleased(),
+                            mFramesWritten,
+                            mTimestamp);
                 }
             }
 
@@ -3026,6 +3025,7 @@
                 mSleepTimeUs = suspendSleepTimeUs();
                 // simulate write to HAL when suspended
                 mBytesWritten += mSinkBufferSize;
+                mFramesWritten += mSinkBufferSize / mFrameSize;
                 mBytesRemaining = 0;
             }
 
@@ -3076,6 +3076,7 @@
                     } else {
                         mBytesWritten += ret;
                         mBytesRemaining -= ret;
+                        mFramesWritten += ret / mFrameSize;
                     }
                 } else if ((mMixerStatus == MIXER_DRAIN_TRACK) ||
                         (mMixerStatus == MIXER_DRAIN_ALL)) {
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 507f197..42b3266 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -693,6 +693,7 @@
     volatile int32_t                mSuspended;
 
     int64_t                         mBytesWritten;
+    int64_t                         mFramesWritten; // not reset on standby
 private:
     // mMasterMute is in both PlaybackThread and in AudioFlinger.  When a
     // PlaybackThread needs to find out if master-muted, it checks it's local
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index a67693f..e684fc2 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -960,9 +960,17 @@
                 (long long)mPresentationCompleteFrames, audioHalFrames);
     }
 
-    if ((!isOffloaded() && !isDirect() && !isFastTrack()
-            && framesWritten >= mPresentationCompleteFrames
-            && mAudioTrackServerProxy->isDrained()) || isOffloaded()) {
+    bool complete;
+    if (isOffloaded()) {
+        complete = true;
+    } else if (isDirect() || isFastTrack()) { // these do not go through linear map
+        complete = framesWritten >= mPresentationCompleteFrames;
+    } else {  // Normal tracks, OutputTracks, and PatchTracks
+        complete = framesWritten >= mPresentationCompleteFrames
+                && mAudioTrackServerProxy->isDrained();
+    }
+
+    if (complete) {
         triggerEvents(AudioSystem::SYNC_EVENT_PRESENTATION_COMPLETE);
         mAudioTrackServerProxy->setStreamEndDone();
         return true;