Merge "Handle lock() returning a NULL buffer in SurfaceUtils." into nyc-mr1-dev
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index a3dcdcf..d093c32 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1662,6 +1662,7 @@
mEffectBufferValid(false),
mSuspended(0), mBytesWritten(0),
mFramesWritten(0),
+ mSuspendedFrames(0),
mActiveTracksGeneration(0),
// mStreamTypes[] initialized in constructor body
mOutput(output),
@@ -3055,7 +3056,8 @@
// copy over kernel info
mTimestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL] =
- timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL];
+ timestamp.mPosition[ExtendedTimestamp::LOCATION_KERNEL]
+ + mSuspendedFrames; // add frames discarded when suspended
mTimestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL] =
timestamp.mTimeNs[ExtendedTimestamp::LOCATION_KERNEL];
}
@@ -3219,10 +3221,12 @@
mBytesRemaining = mCurrentWriteLength;
if (isSuspended()) {
- mSleepTimeUs = suspendSleepTimeUs();
- // simulate write to HAL when suspended
- mBytesWritten += mSinkBufferSize;
- mFramesWritten += mSinkBufferSize / mFrameSize;
+ // Simulate write to HAL when suspended (e.g. BT SCO phone call).
+ mSleepTimeUs = suspendSleepTimeUs(); // assumes full buffer.
+ const size_t framesRemaining = mBytesRemaining / mFrameSize;
+ mBytesWritten += mBytesRemaining;
+ mFramesWritten += framesRemaining;
+ mSuspendedFrames += framesRemaining; // to adjust kernel HAL position
mBytesRemaining = 0;
}
@@ -5355,7 +5359,8 @@
AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady)
: DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady),
- mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
+ mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true),
+ mOffloadUnderrunPosition(~0LL)
{
//FIXME: mStandby should be set to true by ThreadBase constructor
mStandby = true;
@@ -5565,12 +5570,30 @@
// No buffers for this track. Give it a few chances to
// fill a buffer, then remove it from active list.
if (--(track->mRetryCount) <= 0) {
- ALOGV("OffloadThread: BUFFER TIMEOUT: remove(%d) from active list",
- track->name());
- tracksToRemove->add(track);
- // indicate to client process that the track was disabled because of underrun;
- // it will then automatically call start() when data is available
- track->disable();
+ bool running = false;
+ if (mOutput->stream->get_presentation_position != nullptr) {
+ uint64_t position = 0;
+ struct timespec unused;
+ // The running check restarts the retry counter at least once.
+ int ret = mOutput->stream->get_presentation_position(
+ mOutput->stream, &position, &unused);
+ if (ret == NO_ERROR && position != mOffloadUnderrunPosition) {
+ running = true;
+ mOffloadUnderrunPosition = position;
+ }
+ ALOGVV("underrun counter, running(%d): %lld vs %lld", running,
+ (long long)position, (long long)mOffloadUnderrunPosition);
+ }
+ if (running) { // still running, give us more time.
+ track->mRetryCount = kMaxTrackRetriesOffload;
+ } else {
+ ALOGV("OffloadThread: BUFFER TIMEOUT: remove(%d) from active list",
+ track->name());
+ tracksToRemove->add(track);
+ // indicate to client process that the track was disabled because of underrun;
+ // it will then automatically call start() when data is available
+ track->disable();
+ }
} else if (last){
mixerStatus = MIXER_TRACKS_ENABLED;
}
@@ -5627,6 +5650,7 @@
mPausedBytesRemaining = 0;
// reset bytes written count to reflect that DSP buffers are empty after flush.
mBytesWritten = 0;
+ mOffloadUnderrunPosition = ~0LL;
if (mUseAsyncWrite) {
// discard any pending drain or write ack by incrementing sequence
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 93e2bf1..1d5d3c8 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -721,6 +721,7 @@
int64_t mBytesWritten;
int64_t mFramesWritten; // not reset on standby
+ int64_t mSuspendedFrames; // 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
@@ -1026,6 +1027,10 @@
size_t mPausedWriteLength; // length in bytes of write interrupted by pause
size_t mPausedBytesRemaining; // bytes still waiting in mixbuffer after resume
bool mKeepWakeLock; // keep wake lock while waiting for write callback
+ uint64_t mOffloadUnderrunPosition; // Current frame position for offloaded playback
+ // used and valid only during underrun. ~0 if
+ // no underrun has occurred during playback and
+ // is not reset on standby.
};
class AsyncCallbackThread : public Thread {