diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-18 17:39:46 -0700 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-18 17:39:46 -0700 |
commit | 105925376f8d0f6b318c9938c7b83ef7fef094da (patch) | |
tree | 3b19ee2bd8704cb9c6a0da7e42dec6759183de6d /libs/audioflinger | |
parent | ba87e3e6c985e7175152993b5efcc7dd2f0e1c93 (diff) | |
download | frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.zip frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.tar.gz frameworks_base-105925376f8d0f6b318c9938c7b83ef7fef094da.tar.bz2 |
auto import from //branches/cupcake_rel/...@140373
Diffstat (limited to 'libs/audioflinger')
-rw-r--r-- | libs/audioflinger/AudioFlinger.cpp | 161 | ||||
-rw-r--r-- | libs/audioflinger/AudioFlinger.h | 3 | ||||
-rw-r--r-- | libs/audioflinger/AudioMixer.cpp | 5 |
3 files changed, 76 insertions, 93 deletions
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp index 5652b28..9ba7f90 100644 --- a/libs/audioflinger/AudioFlinger.cpp +++ b/libs/audioflinger/AudioFlinger.cpp @@ -58,6 +58,9 @@ namespace android { +static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n"; +static const char* kHardwareLockedString = "Hardware lock is taken\n"; + //static const nsecs_t kStandbyTimeInNsecs = seconds(3); static const unsigned long kBufferRecoveryInUsecs = 2000; static const unsigned long kMaxBufferRecoveryInUsecs = 20000; @@ -195,7 +198,7 @@ AudioFlinger::~AudioFlinger() #ifdef WITH_A2DP // setA2dpEnabled_l() must be called with AudioFlinger::mLock held void AudioFlinger::setA2dpEnabled_l(bool enable) -{ +{ SortedVector < sp<MixerThread::Track> > tracks; SortedVector < wp<MixerThread::Track> > activeTracks; @@ -243,12 +246,6 @@ bool AudioFlinger::streamForcedToSpeaker(int streamType) streamType == AudioSystem::NOTIFICATION); } -bool AudioFlinger::streamDisablesA2dp(int streamType) -{ - return (streamType == AudioSystem::VOICE_CALL || - streamType == AudioSystem::BLUETOOTH_SCO); -} - status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args) { const size_t SIZE = 256; @@ -301,18 +298,39 @@ status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args return NO_ERROR; } +static bool tryLock(Mutex& mutex) +{ + bool locked = false; + for (int i = 0; i < kDumpLockRetries; ++i) { + if (mutex.tryLock() == NO_ERROR) { + locked = true; + break; + } + usleep(kDumpLockSleep); + } + return locked; +} + status_t AudioFlinger::dump(int fd, const Vector<String16>& args) { if (checkCallingPermission(String16("android.permission.DUMP")) == false) { dumpPermissionDenial(fd, args); } else { - bool locked = false; - for (int i = 0; i < kDumpLockRetries; ++i) { - if (mLock.tryLock() == NO_ERROR) { - locked = true; - break; - } - usleep(kDumpLockSleep); + // get state of hardware lock + bool hardwareLocked = tryLock(mHardwareLock); + if (!hardwareLocked) { + String8 result(kHardwareLockedString); + write(fd, result.string(), result.size()); + } else { + mHardwareLock.unlock(); + } + + bool locked = tryLock(mLock); + + // failed to lock - AudioFlinger is probably deadlocked + if (!locked) { + String8 result(kDeadlockedString); + write(fd, result.string(), result.size()); } dumpClients(fd, args); @@ -496,6 +514,14 @@ status_t AudioFlinger::setRouting(int mode, uint32_t routes, uint32_t mask) } LOGV("setOutput done\n"); } + // setRouting() is always called at least for mode == AudioSystem::MODE_IN_CALL when + // SCO is enabled, whatever current mode is so we can safely handle A2DP disabling only + // in this case to avoid doing it several times. + if (mode == AudioSystem::MODE_IN_CALL && + (mask & AudioSystem::ROUTE_BLUETOOTH_SCO)) { + AutoMutex lock(&mLock); + handleRouteDisablesA2dp_l(routes); + } #endif // do nothing if only A2DP routing is affected @@ -657,7 +683,7 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted) if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) { return BAD_VALUE; } - + #ifdef WITH_A2DP mA2dpMixerThread->setStreamMute(stream, muted); #endif @@ -672,8 +698,6 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted) mHardwareMixerThread->setStreamMute(stream, muted); } - - return NO_ERROR; } @@ -837,36 +861,29 @@ void AudioFlinger::handleForcedSpeakerRoute(int command) } #ifdef WITH_A2DP -// handleStreamDisablesA2dp_l() must be called with AudioFlinger::mLock held -void AudioFlinger::handleStreamDisablesA2dp_l(int command) -{ - switch(command) { - case ACTIVE_TRACK_ADDED: - { - if (mA2dpDisableCount++ == 0) { - if (mA2dpEnabled) { - setA2dpEnabled_l(false); - mA2dpSuppressed = true; - } +// handleRouteDisablesA2dp_l() must be called with AudioFlinger::mLock held +void AudioFlinger::handleRouteDisablesA2dp_l(int routes) +{ + if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) { + if (mA2dpDisableCount++ == 0) { + if (mA2dpEnabled) { + setA2dpEnabled_l(false); + mA2dpSuppressed = true; } - LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount); } - break; - case ACTIVE_TRACK_REMOVED: - { - if (mA2dpDisableCount > 0) { - if (--mA2dpDisableCount == 0) { - if (mA2dpSuppressed) { - setA2dpEnabled_l(true); - mA2dpSuppressed = false; - } + LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount); + } else { + if (mA2dpDisableCount > 0) { + if (--mA2dpDisableCount == 0) { + if (mA2dpSuppressed) { + setA2dpEnabled_l(true); + mA2dpSuppressed = false; } - LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount); - } else { - LOGE("mA2dpDisableCount is already zero"); } + LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount); + } else { + LOGE("mA2dpDisableCount is already zero"); } - break; } } #endif @@ -1500,13 +1517,6 @@ void AudioFlinger::MixerThread::addActiveTrack_l(const wp<Track>& t) if (streamForcedToSpeaker(track->type())) { mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED); } -#ifdef WITH_A2DP - // AudioFlinger::mLock must be locked before calling - // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). - if (streamDisablesA2dp(track->type())) { - mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED); - } -#endif } } @@ -1524,13 +1534,6 @@ void AudioFlinger::MixerThread::removeActiveTrack_l(const wp<Track>& t) if (streamForcedToSpeaker(track->type())) { mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED); } -#ifdef WITH_A2DP - // AudioFlinger::mLock must be locked before calling - // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). - if (streamDisablesA2dp(track->type())) { - mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED); - } -#endif } } @@ -1598,8 +1601,8 @@ AudioFlinger::MixerThread::TrackBase::TrackBase( new(mCblk) audio_track_cblk_t(); // clear all buffers mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; + mCblk->sampleRate = (uint16_t)sampleRate; + mCblk->channels = (uint16_t)channelCount; if (sharedBuffer == 0) { mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); @@ -1622,8 +1625,8 @@ AudioFlinger::MixerThread::TrackBase::TrackBase( new(mCblk) audio_track_cblk_t(); // clear all buffers mCblk->frameCount = frameCount; - mCblk->sampleRate = sampleRate; - mCblk->channels = channelCount; + mCblk->sampleRate = (uint16_t)sampleRate; + mCblk->channels = (uint16_t)channelCount; mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t); memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t)); // Force underrun condition to avoid false underrun callback until first data is @@ -1680,7 +1683,7 @@ sp<IMemory> AudioFlinger::MixerThread::TrackBase::getCblk() const } int AudioFlinger::MixerThread::TrackBase::sampleRate() const { - return mCblk->sampleRate; + return (int)mCblk->sampleRate; } int AudioFlinger::MixerThread::TrackBase::channelCount() const { @@ -1693,11 +1696,12 @@ void* AudioFlinger::MixerThread::TrackBase::getBuffer(uint32_t offset, uint32_t int16_t *bufferEnd = bufferStart + frames * cblk->channels; // Check validity of returned pointer in case the track control block would have been corrupted. - if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) { - LOGW("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ - server %d, serverBase %d, user %d, userBase %d", + if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd || + cblk->channels == 2 && ((unsigned long)bufferStart & 3) ) { + LOGE("TrackBase::getBuffer buffer out of range:\n start: %p, end %p , mBuffer %p mBufferEnd %p\n \ + server %d, serverBase %d, user %d, userBase %d, channels %d", bufferStart, bufferEnd, mBuffer, mBufferEnd, - cblk->server, cblk->serverBase, cblk->user, cblk->userBase); + cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channels); return 0; } @@ -1864,12 +1868,14 @@ void AudioFlinger::MixerThread::Track::flush() // STOPPED state mState = STOPPED; + mCblk->lock.lock(); // NOTE: reset() will reset cblk->user and cblk->server with // the risk that at the same time, the AudioMixer is trying to read // data. In this case, getNextBuffer() would return a NULL pointer // as audio buffer => the AudioMixer code MUST always test that pointer // returned by getNextBuffer() is not NULL! reset(); + mCblk->lock.unlock(); } void AudioFlinger::MixerThread::Track::reset() @@ -2478,19 +2484,6 @@ status_t AudioFlinger::AudioRecordThread::start(MixerThread::RecordTrack* record mRecordTrack = recordTrack; -#ifdef WITH_A2DP - { // scope for lock2 - - // AudioFlinger::mLock must be locked before calling - // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). - AutoMutex lock2(&mAudioFlinger->mLock); - - // Currently there is no way to detect if we are recording over SCO, - // so we disable A2DP during any recording. - mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED); - } -#endif - // signal thread to start LOGV("Signal record thread"); mWaitWorkCV.signal(); @@ -2503,18 +2496,6 @@ void AudioFlinger::AudioRecordThread::stop(MixerThread::RecordTrack* recordTrack LOGV("AudioRecordThread::stop"); AutoMutex lock(&mLock); if (mActive && (recordTrack == mRecordTrack.get())) { -#ifdef WITH_A2DP - { // scope for lock2 - - // AudioFlinger::mLock must be locked before calling - // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l(). - AutoMutex lock2(&mAudioFlinger->mLock); - - // Currently there is no way to detect if we are recording over SCO, - // so we disable A2DP during any recording. - mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED); - } -#endif mActive = false; mStopped.wait(mLock); } diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h index ab15947..db5cc74 100644 --- a/libs/audioflinger/AudioFlinger.h +++ b/libs/audioflinger/AudioFlinger.h @@ -165,7 +165,6 @@ private: void checkA2dpEnabledChange_l(); #endif static bool streamForcedToSpeaker(int streamType); - static bool streamDisablesA2dp(int streamType); // Management of forced route to speaker for certain track types. enum force_speaker_command { @@ -176,7 +175,7 @@ private: }; void handleForcedSpeakerRoute(int command); #ifdef WITH_A2DP - void handleStreamDisablesA2dp_l(int command); + void handleRouteDisablesA2dp_l(int routes); #endif // Internal dump utilites. diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp index b03467f..b02efcc 100644 --- a/libs/audioflinger/AudioMixer.cpp +++ b/libs/audioflinger/AudioMixer.cpp @@ -16,6 +16,7 @@ */ #define LOG_TAG "AudioMixer" +//#define LOG_NDEBUG 0 #include <stdint.h> #include <string.h> @@ -780,8 +781,10 @@ void AudioMixer::process__OneTrack16BitsStereoNoResampling(state_t* state, void* // in == NULL can happen if the track was flushed just after having // been enabled for mixing. - if (in == NULL) { + if (in == NULL || ((unsigned long)in & 3)) { memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t)); + LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x", + in, i, t.channelCount, t.needs); return; } size_t outFrames = b.frameCount; |