am 6efdbcc3: am fddfb9ae: Merge change Iad79689a into eclair

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:
Eric Laurent
2009-11-13 09:28:06 -08:00
committed by Android Git Automerger
3 changed files with 122 additions and 80 deletions

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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);
} }
} }