Merge commit '6efdbcc3c1afafe2f9401668ce252167600b498f' into eclair-mr2-plus-aosp * commit '6efdbcc3c1afafe2f9401668ce252167600b498f': Improvements for issue 2197683: English IME key-press latency is noticeably higher on passion than sholes
This commit is contained in:
@@ -1185,7 +1185,6 @@ void AudioFlinger::PlaybackThread::readOutputParameters()
|
|||||||
mFrameSize = mOutput->frameSize();
|
mFrameSize = mOutput->frameSize();
|
||||||
mFrameCount = mOutput->bufferSize() / mFrameSize;
|
mFrameCount = mOutput->bufferSize() / mFrameSize;
|
||||||
|
|
||||||
mMinBytesToWrite = (mOutput->latency() * mSampleRate * mFrameSize) / 1000;
|
|
||||||
// FIXME - Current mixer implementation only supports stereo output: Always
|
// FIXME - Current mixer implementation only supports stereo output: Always
|
||||||
// Allocate a stereo buffer even if HW output is mono.
|
// Allocate a stereo buffer even if HW output is mono.
|
||||||
if (mMixBuffer != NULL) delete mMixBuffer;
|
if (mMixBuffer != NULL) delete mMixBuffer;
|
||||||
@@ -1215,23 +1214,25 @@ AudioFlinger::MixerThread::~MixerThread()
|
|||||||
|
|
||||||
bool AudioFlinger::MixerThread::threadLoop()
|
bool AudioFlinger::MixerThread::threadLoop()
|
||||||
{
|
{
|
||||||
uint32_t sleepTime = 1000;
|
|
||||||
uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
|
|
||||||
int16_t* curBuf = mMixBuffer;
|
int16_t* curBuf = mMixBuffer;
|
||||||
Vector< sp<Track> > tracksToRemove;
|
Vector< sp<Track> > tracksToRemove;
|
||||||
size_t enabledTracks = 0;
|
uint32_t mixerStatus = MIXER_IDLE;
|
||||||
nsecs_t standbyTime = systemTime();
|
nsecs_t standbyTime = systemTime();
|
||||||
size_t mixBufferSize = mFrameCount * mFrameSize;
|
size_t mixBufferSize = mFrameCount * mFrameSize;
|
||||||
// FIXME: Relaxed timing because of a certain device that can't meet latency
|
// FIXME: Relaxed timing because of a certain device that can't meet latency
|
||||||
// Should be reduced to 2x after the vendor fixes the driver issue
|
// Should be reduced to 2x after the vendor fixes the driver issue
|
||||||
nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
|
nsecs_t maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
|
||||||
nsecs_t lastWarning = 0;
|
nsecs_t lastWarning = 0;
|
||||||
|
bool longStandbyExit = false;
|
||||||
|
uint32_t activeSleepTime = activeSleepTimeUs();
|
||||||
|
uint32_t idleSleepTime = idleSleepTimeUs();
|
||||||
|
uint32_t sleepTime = idleSleepTime;
|
||||||
|
|
||||||
while (!exitPending())
|
while (!exitPending())
|
||||||
{
|
{
|
||||||
processConfigEvents();
|
processConfigEvents();
|
||||||
|
|
||||||
enabledTracks = 0;
|
mixerStatus = MIXER_IDLE;
|
||||||
{ // scope for mLock
|
{ // scope for mLock
|
||||||
|
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
@@ -1241,7 +1242,8 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
// FIXME: Relaxed timing because of a certain device that can't meet latency
|
// FIXME: Relaxed timing because of a certain device that can't meet latency
|
||||||
// Should be reduced to 2x after the vendor fixes the driver issue
|
// Should be reduced to 2x after the vendor fixes the driver issue
|
||||||
maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
|
maxPeriod = seconds(mFrameCount) / mSampleRate * 3;
|
||||||
maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
|
activeSleepTime = activeSleepTimeUs();
|
||||||
|
idleSleepTime = idleSleepTimeUs();
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
|
const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
|
||||||
@@ -1277,15 +1279,15 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
||||||
sleepTime = 1000;
|
sleepTime = idleSleepTime;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
|
mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LIKELY(enabledTracks)) {
|
if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
|
||||||
// mix buffers...
|
// mix buffers...
|
||||||
mAudioMixer->process(curBuf);
|
mAudioMixer->process(curBuf);
|
||||||
sleepTime = 0;
|
sleepTime = 0;
|
||||||
@@ -1294,15 +1296,22 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
// If no tracks are ready, sleep once for the duration of an output
|
// If no tracks are ready, sleep once for the duration of an output
|
||||||
// buffer size, then write 0s to the output
|
// buffer size, then write 0s to the output
|
||||||
if (sleepTime == 0) {
|
if (sleepTime == 0) {
|
||||||
sleepTime = maxBufferRecoveryInUsecs;
|
if (mixerStatus == MIXER_TRACKS_ENABLED) {
|
||||||
} else if (mBytesWritten != 0) {
|
sleepTime = activeSleepTime;
|
||||||
|
} else {
|
||||||
|
sleepTime = idleSleepTime;
|
||||||
|
}
|
||||||
|
} else if (mBytesWritten != 0 ||
|
||||||
|
(mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) {
|
||||||
|
LOGV("NO DATA READY, %p", this);
|
||||||
memset (curBuf, 0, mixBufferSize);
|
memset (curBuf, 0, mixBufferSize);
|
||||||
sleepTime = 0;
|
sleepTime = 0;
|
||||||
|
LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSuspended) {
|
if (mSuspended) {
|
||||||
sleepTime = maxBufferRecoveryInUsecs;
|
sleepTime = idleSleepTime;
|
||||||
}
|
}
|
||||||
// sleepTime == 0 means we must write to audio hardware
|
// sleepTime == 0 means we must write to audio hardware
|
||||||
if (sleepTime == 0) {
|
if (sleepTime == 0) {
|
||||||
@@ -1312,7 +1321,6 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
if (bytesWritten > 0) mBytesWritten += bytesWritten;
|
if (bytesWritten > 0) mBytesWritten += bytesWritten;
|
||||||
mNumWrites++;
|
mNumWrites++;
|
||||||
mInWrite = false;
|
mInWrite = false;
|
||||||
mStandby = false;
|
|
||||||
nsecs_t now = systemTime();
|
nsecs_t now = systemTime();
|
||||||
nsecs_t delta = now - mLastWriteTime;
|
nsecs_t delta = now - mLastWriteTime;
|
||||||
if (delta > maxPeriod) {
|
if (delta > maxPeriod) {
|
||||||
@@ -1322,7 +1330,11 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
ns2ms(delta), mNumDelayedWrites, this);
|
ns2ms(delta), mNumDelayedWrites, this);
|
||||||
lastWarning = now;
|
lastWarning = now;
|
||||||
}
|
}
|
||||||
|
if (mStandby) {
|
||||||
|
longStandbyExit = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
mStandby = false;
|
||||||
} else {
|
} else {
|
||||||
usleep(sleepTime);
|
usleep(sleepTime);
|
||||||
}
|
}
|
||||||
@@ -1342,10 +1354,10 @@ bool AudioFlinger::MixerThread::threadLoop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// prepareTracks_l() must be called with ThreadBase::mLock held
|
// prepareTracks_l() must be called with ThreadBase::mLock held
|
||||||
size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
|
uint32_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove)
|
||||||
{
|
{
|
||||||
|
|
||||||
size_t enabledTracks = 0;
|
uint32_t mixerStatus = MIXER_IDLE;
|
||||||
// find out which tracks need to be processed
|
// find out which tracks need to be processed
|
||||||
size_t count = activeTracks.size();
|
size_t count = activeTracks.size();
|
||||||
for (size_t i=0 ; i<count ; i++) {
|
for (size_t i=0 ; i<count ; i++) {
|
||||||
@@ -1415,7 +1427,7 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track>
|
|||||||
|
|
||||||
// reset retry count
|
// reset retry count
|
||||||
track->mRetryCount = kMaxTrackRetries;
|
track->mRetryCount = kMaxTrackRetries;
|
||||||
enabledTracks++;
|
mixerStatus = MIXER_TRACKS_READY;
|
||||||
} else {
|
} else {
|
||||||
//LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
|
//LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
|
||||||
if (track->isStopped()) {
|
if (track->isStopped()) {
|
||||||
@@ -1432,16 +1444,11 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track>
|
|||||||
if (--(track->mRetryCount) <= 0) {
|
if (--(track->mRetryCount) <= 0) {
|
||||||
LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
|
LOGV("BUFFER TIMEOUT: remove(%d) from active list on thread %p", track->name(), this);
|
||||||
tracksToRemove->add(track);
|
tracksToRemove->add(track);
|
||||||
|
} else if (mixerStatus != MIXER_TRACKS_READY) {
|
||||||
|
mixerStatus = MIXER_TRACKS_ENABLED;
|
||||||
}
|
}
|
||||||
// For tracks using static shared memory buffer, make sure that we have
|
|
||||||
// written enough data to audio hardware before disabling the track
|
mAudioMixer->disable(AudioMixer::MIXING);
|
||||||
// NOTE: this condition with arrive before track->mRetryCount <= 0 so we
|
|
||||||
// don't care about code removing track from active list above.
|
|
||||||
if ((track->mSharedBuffer == 0) || (mBytesWritten >= mMinBytesToWrite)) {
|
|
||||||
mAudioMixer->disable(AudioMixer::MIXING);
|
|
||||||
} else {
|
|
||||||
enabledTracks++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1459,7 +1466,7 @@ size_t AudioFlinger::MixerThread::prepareTracks_l(const SortedVector< wp<Track>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return enabledTracks;
|
return mixerStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioFlinger::MixerThread::getTracks(
|
void AudioFlinger::MixerThread::getTracks(
|
||||||
@@ -1621,14 +1628,14 @@ status_t AudioFlinger::MixerThread::dumpInternals(int fd, const Vector<String16>
|
|||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AudioFlinger::MixerThread::getMaxBufferRecoveryInUsecs()
|
uint32_t AudioFlinger::MixerThread::activeSleepTimeUs()
|
||||||
{
|
{
|
||||||
uint32_t time = ((mFrameCount * 1000) / mSampleRate) * 1000;
|
return (uint32_t)(mOutput->latency() * 1000) / 2;
|
||||||
// Add some margin with regard to scheduling precision
|
}
|
||||||
if (time > 10000) {
|
|
||||||
time -= 10000;
|
uint32_t AudioFlinger::MixerThread::idleSleepTimeUs()
|
||||||
}
|
{
|
||||||
return time;
|
return (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -1646,25 +1653,31 @@ AudioFlinger::DirectOutputThread::~DirectOutputThread()
|
|||||||
|
|
||||||
bool AudioFlinger::DirectOutputThread::threadLoop()
|
bool AudioFlinger::DirectOutputThread::threadLoop()
|
||||||
{
|
{
|
||||||
uint32_t sleepTime = 1000;
|
uint32_t mixerStatus = MIXER_IDLE;
|
||||||
uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
|
|
||||||
sp<Track> trackToRemove;
|
sp<Track> trackToRemove;
|
||||||
sp<Track> activeTrack;
|
sp<Track> activeTrack;
|
||||||
nsecs_t standbyTime = systemTime();
|
nsecs_t standbyTime = systemTime();
|
||||||
int8_t *curBuf;
|
int8_t *curBuf;
|
||||||
size_t mixBufferSize = mFrameCount*mFrameSize;
|
size_t mixBufferSize = mFrameCount*mFrameSize;
|
||||||
|
uint32_t activeSleepTime = activeSleepTimeUs();
|
||||||
|
uint32_t idleSleepTime = idleSleepTimeUs();
|
||||||
|
uint32_t sleepTime = idleSleepTime;
|
||||||
|
|
||||||
|
|
||||||
while (!exitPending())
|
while (!exitPending())
|
||||||
{
|
{
|
||||||
processConfigEvents();
|
processConfigEvents();
|
||||||
|
|
||||||
|
mixerStatus = MIXER_IDLE;
|
||||||
|
|
||||||
{ // scope for the mLock
|
{ // scope for the mLock
|
||||||
|
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
|
|
||||||
if (checkForNewParameters_l()) {
|
if (checkForNewParameters_l()) {
|
||||||
mixBufferSize = mFrameCount*mFrameSize;
|
mixBufferSize = mFrameCount*mFrameSize;
|
||||||
maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
|
activeSleepTime = activeSleepTimeUs();
|
||||||
|
idleSleepTime = idleSleepTimeUs();
|
||||||
}
|
}
|
||||||
|
|
||||||
// put audio hardware into standby after short delay
|
// put audio hardware into standby after short delay
|
||||||
@@ -1698,7 +1711,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
||||||
sleepTime = 1000;
|
sleepTime = idleSleepTime;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1753,6 +1766,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
// reset retry count
|
// reset retry count
|
||||||
track->mRetryCount = kMaxTrackRetries;
|
track->mRetryCount = kMaxTrackRetries;
|
||||||
activeTrack = t;
|
activeTrack = t;
|
||||||
|
mixerStatus = MIXER_TRACKS_READY;
|
||||||
} else {
|
} else {
|
||||||
//LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
|
//LOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
|
||||||
if (track->isStopped()) {
|
if (track->isStopped()) {
|
||||||
@@ -1768,16 +1782,10 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
if (--(track->mRetryCount) <= 0) {
|
if (--(track->mRetryCount) <= 0) {
|
||||||
LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
|
LOGV("BUFFER TIMEOUT: remove(%d) from active list", track->name());
|
||||||
trackToRemove = track;
|
trackToRemove = track;
|
||||||
|
} else {
|
||||||
|
mixerStatus = MIXER_TRACKS_ENABLED;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// For tracks using static shared memry buffer, make sure that we have
|
|
||||||
// written enough data to audio hardware before disabling the track
|
|
||||||
// NOTE: this condition with arrive before track->mRetryCount <= 0 so we
|
|
||||||
// don't care about code removing track from active list above.
|
|
||||||
if ((track->mSharedBuffer != 0) && (mBytesWritten < mMinBytesToWrite)) {
|
|
||||||
activeTrack = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1791,7 +1799,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activeTrack != 0) {
|
if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
|
||||||
AudioBufferProvider::Buffer buffer;
|
AudioBufferProvider::Buffer buffer;
|
||||||
size_t frameCount = mFrameCount;
|
size_t frameCount = mFrameCount;
|
||||||
curBuf = (int8_t *)mMixBuffer;
|
curBuf = (int8_t *)mMixBuffer;
|
||||||
@@ -1812,7 +1820,11 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
||||||
} else {
|
} else {
|
||||||
if (sleepTime == 0) {
|
if (sleepTime == 0) {
|
||||||
sleepTime = maxBufferRecoveryInUsecs;
|
if (mixerStatus == MIXER_TRACKS_ENABLED) {
|
||||||
|
sleepTime = activeSleepTime;
|
||||||
|
} else {
|
||||||
|
sleepTime = idleSleepTime;
|
||||||
|
}
|
||||||
} else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
|
} else if (mBytesWritten != 0 && AudioSystem::isLinearPCM(mFormat)) {
|
||||||
memset (mMixBuffer, 0, mFrameCount * mFrameSize);
|
memset (mMixBuffer, 0, mFrameCount * mFrameSize);
|
||||||
sleepTime = 0;
|
sleepTime = 0;
|
||||||
@@ -1820,7 +1832,7 @@ bool AudioFlinger::DirectOutputThread::threadLoop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mSuspended) {
|
if (mSuspended) {
|
||||||
sleepTime = maxBufferRecoveryInUsecs;
|
sleepTime = idleSleepTime;
|
||||||
}
|
}
|
||||||
// sleepTime == 0 means we must write to audio hardware
|
// sleepTime == 0 means we must write to audio hardware
|
||||||
if (sleepTime == 0) {
|
if (sleepTime == 0) {
|
||||||
@@ -1905,15 +1917,22 @@ bool AudioFlinger::DirectOutputThread::checkForNewParameters_l()
|
|||||||
return reconfig;
|
return reconfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t AudioFlinger::DirectOutputThread::getMaxBufferRecoveryInUsecs()
|
uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs()
|
||||||
{
|
{
|
||||||
uint32_t time;
|
uint32_t time;
|
||||||
if (AudioSystem::isLinearPCM(mFormat)) {
|
if (AudioSystem::isLinearPCM(mFormat)) {
|
||||||
time = ((mFrameCount * 1000) / mSampleRate) * 1000;
|
time = (uint32_t)(mOutput->latency() * 1000) / 2;
|
||||||
// Add some margin with regard to scheduling precision
|
} else {
|
||||||
if (time > 10000) {
|
time = 10000;
|
||||||
time -= 10000;
|
}
|
||||||
}
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs()
|
||||||
|
{
|
||||||
|
uint32_t time;
|
||||||
|
if (AudioSystem::isLinearPCM(mFormat)) {
|
||||||
|
time = (uint32_t)((mFrameCount * 1000) / mSampleRate) * 1000;
|
||||||
} else {
|
} else {
|
||||||
time = 10000;
|
time = 10000;
|
||||||
}
|
}
|
||||||
@@ -1936,28 +1955,30 @@ AudioFlinger::DuplicatingThread::~DuplicatingThread()
|
|||||||
|
|
||||||
bool AudioFlinger::DuplicatingThread::threadLoop()
|
bool AudioFlinger::DuplicatingThread::threadLoop()
|
||||||
{
|
{
|
||||||
uint32_t sleepTime = 1000;
|
|
||||||
uint32_t maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
|
|
||||||
int16_t* curBuf = mMixBuffer;
|
int16_t* curBuf = mMixBuffer;
|
||||||
Vector< sp<Track> > tracksToRemove;
|
Vector< sp<Track> > tracksToRemove;
|
||||||
size_t enabledTracks = 0;
|
uint32_t mixerStatus = MIXER_IDLE;
|
||||||
nsecs_t standbyTime = systemTime();
|
nsecs_t standbyTime = systemTime();
|
||||||
size_t mixBufferSize = mFrameCount*mFrameSize;
|
size_t mixBufferSize = mFrameCount*mFrameSize;
|
||||||
SortedVector< sp<OutputTrack> > outputTracks;
|
SortedVector< sp<OutputTrack> > outputTracks;
|
||||||
uint32_t writeFrames = 0;
|
uint32_t writeFrames = 0;
|
||||||
|
uint32_t activeSleepTime = activeSleepTimeUs();
|
||||||
|
uint32_t idleSleepTime = idleSleepTimeUs();
|
||||||
|
uint32_t sleepTime = idleSleepTime;
|
||||||
|
|
||||||
while (!exitPending())
|
while (!exitPending())
|
||||||
{
|
{
|
||||||
processConfigEvents();
|
processConfigEvents();
|
||||||
|
|
||||||
enabledTracks = 0;
|
mixerStatus = MIXER_IDLE;
|
||||||
{ // scope for the mLock
|
{ // scope for the mLock
|
||||||
|
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
|
|
||||||
if (checkForNewParameters_l()) {
|
if (checkForNewParameters_l()) {
|
||||||
mixBufferSize = mFrameCount*mFrameSize;
|
mixBufferSize = mFrameCount*mFrameSize;
|
||||||
maxBufferRecoveryInUsecs = getMaxBufferRecoveryInUsecs();
|
activeSleepTime = activeSleepTimeUs();
|
||||||
|
idleSleepTime = idleSleepTimeUs();
|
||||||
}
|
}
|
||||||
|
|
||||||
const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
|
const SortedVector< wp<Track> >& activeTracks = mActiveTracks;
|
||||||
@@ -1997,22 +2018,26 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
standbyTime = systemTime() + kStandbyTimeInNsecs;
|
||||||
sleepTime = 1000;
|
sleepTime = idleSleepTime;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enabledTracks = prepareTracks_l(activeTracks, &tracksToRemove);
|
mixerStatus = prepareTracks_l(activeTracks, &tracksToRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LIKELY(enabledTracks)) {
|
if (LIKELY(mixerStatus == MIXER_TRACKS_READY)) {
|
||||||
// mix buffers...
|
// mix buffers...
|
||||||
mAudioMixer->process(curBuf);
|
mAudioMixer->process(curBuf);
|
||||||
sleepTime = 0;
|
sleepTime = 0;
|
||||||
writeFrames = mFrameCount;
|
writeFrames = mFrameCount;
|
||||||
} else {
|
} else {
|
||||||
if (sleepTime == 0) {
|
if (sleepTime == 0) {
|
||||||
sleepTime = maxBufferRecoveryInUsecs;
|
if (mixerStatus == MIXER_TRACKS_ENABLED) {
|
||||||
|
sleepTime = activeSleepTime;
|
||||||
|
} else {
|
||||||
|
sleepTime = idleSleepTime;
|
||||||
|
}
|
||||||
} else if (mBytesWritten != 0) {
|
} else if (mBytesWritten != 0) {
|
||||||
// flush remaining overflow buffers in output tracks
|
// flush remaining overflow buffers in output tracks
|
||||||
for (size_t i = 0; i < outputTracks.size(); i++) {
|
for (size_t i = 0; i < outputTracks.size(); i++) {
|
||||||
@@ -2026,7 +2051,7 @@ bool AudioFlinger::DuplicatingThread::threadLoop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mSuspended) {
|
if (mSuspended) {
|
||||||
sleepTime = maxBufferRecoveryInUsecs;
|
sleepTime = idleSleepTime;
|
||||||
}
|
}
|
||||||
// sleepTime == 0 means we must write to audio hardware
|
// sleepTime == 0 means we must write to audio hardware
|
||||||
if (sleepTime == 0) {
|
if (sleepTime == 0) {
|
||||||
|
|||||||
@@ -361,6 +361,12 @@ private:
|
|||||||
DUPLICATING
|
DUPLICATING
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mixer_state {
|
||||||
|
MIXER_IDLE,
|
||||||
|
MIXER_TRACKS_ENABLED,
|
||||||
|
MIXER_TRACKS_READY
|
||||||
|
};
|
||||||
|
|
||||||
// playback track
|
// playback track
|
||||||
class Track : public TrackBase {
|
class Track : public TrackBase {
|
||||||
public:
|
public:
|
||||||
@@ -530,7 +536,8 @@ private:
|
|||||||
|
|
||||||
virtual int getTrackName_l() = 0;
|
virtual int getTrackName_l() = 0;
|
||||||
virtual void deleteTrackName_l(int name) = 0;
|
virtual void deleteTrackName_l(int name) = 0;
|
||||||
virtual uint32_t getMaxBufferRecoveryInUsecs() = 0;
|
virtual uint32_t activeSleepTimeUs() = 0;
|
||||||
|
virtual uint32_t idleSleepTimeUs() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -562,7 +569,6 @@ private:
|
|||||||
int mNumWrites;
|
int mNumWrites;
|
||||||
int mNumDelayedWrites;
|
int mNumDelayedWrites;
|
||||||
bool mInWrite;
|
bool mInWrite;
|
||||||
int mMinBytesToWrite;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MixerThread : public PlaybackThread {
|
class MixerThread : public PlaybackThread {
|
||||||
@@ -582,10 +588,11 @@ private:
|
|||||||
virtual status_t dumpInternals(int fd, const Vector<String16>& args);
|
virtual status_t dumpInternals(int fd, const Vector<String16>& args);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
|
uint32_t prepareTracks_l(const SortedVector< wp<Track> >& activeTracks, Vector< sp<Track> > *tracksToRemove);
|
||||||
virtual int getTrackName_l();
|
virtual int getTrackName_l();
|
||||||
virtual void deleteTrackName_l(int name);
|
virtual void deleteTrackName_l(int name);
|
||||||
virtual uint32_t getMaxBufferRecoveryInUsecs();
|
virtual uint32_t activeSleepTimeUs();
|
||||||
|
virtual uint32_t idleSleepTimeUs();
|
||||||
|
|
||||||
AudioMixer* mAudioMixer;
|
AudioMixer* mAudioMixer;
|
||||||
};
|
};
|
||||||
@@ -604,7 +611,8 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
virtual int getTrackName_l();
|
virtual int getTrackName_l();
|
||||||
virtual void deleteTrackName_l(int name);
|
virtual void deleteTrackName_l(int name);
|
||||||
virtual uint32_t getMaxBufferRecoveryInUsecs();
|
virtual uint32_t activeSleepTimeUs();
|
||||||
|
virtual uint32_t idleSleepTimeUs();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float mLeftVolume;
|
float mLeftVolume;
|
||||||
|
|||||||
@@ -318,26 +318,35 @@ void AudioTrack::start()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (android_atomic_or(1, &mActive) == 0) {
|
if (android_atomic_or(1, &mActive) == 0) {
|
||||||
audio_io_handle_t output = AudioTrack::getOutput();
|
audio_io_handle_t output = getOutput();
|
||||||
|
AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
|
||||||
|
mNewPosition = mCblk->server + mUpdatePeriod;
|
||||||
|
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
|
||||||
|
mCblk->waitTimeMs = 0;
|
||||||
|
if (t != 0) {
|
||||||
|
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
|
||||||
|
} else {
|
||||||
|
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
status_t status = mAudioTrack->start();
|
status_t status = mAudioTrack->start();
|
||||||
if (status == DEAD_OBJECT) {
|
if (status == DEAD_OBJECT) {
|
||||||
LOGV("start() dead IAudioTrack: creating a new one");
|
LOGV("start() dead IAudioTrack: creating a new one");
|
||||||
status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
|
status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
|
||||||
mFrameCount, mFlags, mSharedBuffer, output);
|
mFrameCount, mFlags, mSharedBuffer, output);
|
||||||
}
|
|
||||||
if (status == NO_ERROR) {
|
|
||||||
AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
|
|
||||||
mNewPosition = mCblk->server + mUpdatePeriod;
|
mNewPosition = mCblk->server + mUpdatePeriod;
|
||||||
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
|
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
|
||||||
mCblk->waitTimeMs = 0;
|
mCblk->waitTimeMs = 0;
|
||||||
if (t != 0) {
|
}
|
||||||
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
|
if (status != NO_ERROR) {
|
||||||
} else {
|
|
||||||
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
LOGV("start() failed");
|
LOGV("start() failed");
|
||||||
android_atomic_and(~1, &mActive);
|
android_atomic_and(~1, &mActive);
|
||||||
|
if (t != 0) {
|
||||||
|
t->requestExit();
|
||||||
|
} else {
|
||||||
|
setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_NORMAL);
|
||||||
|
}
|
||||||
|
AudioSystem::stopOutput(output, (AudioSystem::stream_type)mStreamType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user