summaryrefslogtreecommitdiffstats
path: root/services
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
commit626c85f3a9ec8e34a1e4af31eddf118d75ee6416 (patch)
tree6430f67b042ec913493476605a4a67d5cde5855c /services
parentb5e8536e41bbbbfe336e1d9614c73278e51590eb (diff)
downloadframeworks_av-626c85f3a9ec8e34a1e4af31eddf118d75ee6416.zip
frameworks_av-626c85f3a9ec8e34a1e4af31eddf118d75ee6416.tar.gz
frameworks_av-626c85f3a9ec8e34a1e4af31eddf118d75ee6416.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')
-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;