summaryrefslogtreecommitdiffstats
path: root/services/audioflinger
diff options
context:
space:
mode:
authorEric Laurent <elaurent@google.com>2010-12-17 10:27:02 -0800
committerEric Laurent <elaurent@google.com>2010-12-17 10:27:02 -0800
commite7155e6bde27a581b427fb6e1c19da558d10602b (patch)
tree26f1bde2ed13b8167ad5a3e9513b748e7b0999be /services/audioflinger
parent1c602b3ee11fcdb429527ad6a7162219a94cabbb (diff)
downloadframeworks_base-e7155e6bde27a581b427fb6e1c19da558d10602b.zip
frameworks_base-e7155e6bde27a581b427fb6e1c19da558d10602b.tar.gz
frameworks_base-e7155e6bde27a581b427fb6e1c19da558d10602b.tar.bz2
Fix issue 3217707.
The problem is that when the A2DP headset is disconnected, there is a transition period during which the A2DP sink pumps data at a very high pace. This makes that: 1 the audio flinger mixer thread spins and starves binder threads thus delaying the completion of the A2DP output stream shutdown 2 we read the audio http audio stream faster than normal and we reach the end of stream for audio while video is still playing if the streamed file is small enough. The fix consists in detecting abnormal short write intervals and sleep to restore a normal write pace. Change-Id: Iab127882494ab0e26266371dc0ce5c2ff6fa476e
Diffstat (limited to 'services/audioflinger')
-rw-r--r--services/audioflinger/A2dpAudioInterface.cpp13
-rw-r--r--services/audioflinger/A2dpAudioInterface.h2
2 files changed, 14 insertions, 1 deletions
diff --git a/services/audioflinger/A2dpAudioInterface.cpp b/services/audioflinger/A2dpAudioInterface.cpp
index aee01ab..d926cb1 100644
--- a/services/audioflinger/A2dpAudioInterface.cpp
+++ b/services/audioflinger/A2dpAudioInterface.cpp
@@ -260,6 +260,7 @@ status_t A2dpAudioInterface::A2dpAudioStreamOut::set(
if (pRate) *pRate = lRate;
mDevice = device;
+ mBufferDurationUs = ((bufferSize() * 1000 )/ frameSize() / sampleRate()) * 1000;
return NO_ERROR;
}
@@ -288,6 +289,7 @@ ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t
if (mStandby) {
acquire_wake_lock (PARTIAL_WAKE_LOCK, sA2dpWakeLock);
mStandby = false;
+ mLastWriteTime = systemTime();
}
status = init();
@@ -308,6 +310,15 @@ ssize_t A2dpAudioInterface::A2dpAudioStreamOut::write(const void* buffer, size_t
buffer = (char *)buffer + status;
}
+ // if A2DP sink runs abnormally fast, sleep a little so that audioflinger mixer thread
+ // does no spin and starve other threads.
+ // NOTE: It is likely that the A2DP headset is being disconnected
+ nsecs_t now = systemTime();
+ if ((uint32_t)ns2us(now - mLastWriteTime) < (mBufferDurationUs >> 2)) {
+ LOGV("A2DP sink runs too fast");
+ usleep(mBufferDurationUs - (uint32_t)ns2us(now - mLastWriteTime));
+ }
+ mLastWriteTime = now;
return bytes;
}
@@ -316,7 +327,7 @@ Error:
standby();
// Simulate audio output timing in case of error
- usleep(((bytes * 1000 )/ frameSize() / sampleRate()) * 1000);
+ usleep(mBufferDurationUs);
return status;
}
diff --git a/services/audioflinger/A2dpAudioInterface.h b/services/audioflinger/A2dpAudioInterface.h
index cef1926..dbe2c6a 100644
--- a/services/audioflinger/A2dpAudioInterface.h
+++ b/services/audioflinger/A2dpAudioInterface.h
@@ -117,6 +117,8 @@ private:
uint32_t mDevice;
bool mClosing;
bool mSuspended;
+ nsecs_t mLastWriteTime;
+ uint32_t mBufferDurationUs;
};
friend class A2dpAudioStreamOut;