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;