summaryrefslogtreecommitdiffstats
path: root/libs/audioflinger
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-18 17:39:46 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-18 17:39:46 -0700
commit105925376f8d0f6b318c9938c7b83ef7fef094da (patch)
tree3b19ee2bd8704cb9c6a0da7e42dec6759183de6d /libs/audioflinger
parentba87e3e6c985e7175152993b5efcc7dd2f0e1c93 (diff)
downloadframeworks_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.cpp161
-rw-r--r--libs/audioflinger/AudioFlinger.h3
-rw-r--r--libs/audioflinger/AudioMixer.cpp5
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;