auto import from //branches/cupcake_rel/...@140373
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 @@
#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 @@
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 @@
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 @@
}
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 @@
if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
return BAD_VALUE;
}
-
+
#ifdef WITH_A2DP
mA2dpMixerThread->setStreamMute(stream, muted);
#endif
@@ -672,8 +698,6 @@
mHardwareMixerThread->setStreamMute(stream, muted);
}
-
-
return NO_ERROR;
}
@@ -837,36 +861,29 @@
}
#ifdef WITH_A2DP
-// handleStreamDisablesA2dp_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::handleStreamDisablesA2dp_l(int command)
+// handleRouteDisablesA2dp_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::handleRouteDisablesA2dp_l(int routes)
{
- switch(command) {
- case ACTIVE_TRACK_ADDED:
- {
- 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 decremented to %d", mA2dpDisableCount);
- } else {
- LOGE("mA2dpDisableCount is already zero");
+ if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) {
+ if (mA2dpDisableCount++ == 0) {
+ if (mA2dpEnabled) {
+ setA2dpEnabled_l(false);
+ mA2dpSuppressed = true;
}
}
- break;
+ 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");
+ }
}
}
#endif
@@ -1500,13 +1517,6 @@
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 @@
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 @@
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 @@
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 @@
}
int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
- return mCblk->sampleRate;
+ return (int)mCblk->sampleRate;
}
int AudioFlinger::MixerThread::TrackBase::channelCount() const {
@@ -1693,11 +1696,12 @@
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 @@
// 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 @@
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 @@
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);
}