Loading include/utils/ResourceTypes.h +1 −1 Original line number Diff line number Diff line Loading @@ -814,7 +814,7 @@ struct ResTable_config ORIENTATION_ANY = 0x0000, ORIENTATION_PORT = 0x0001, ORIENTATION_LAND = 0x0002, ORIENTATION_SQUARE = 0x0002, ORIENTATION_SQUARE = 0x0003, }; enum { Loading libs/audioflinger/AudioFlinger.cpp +71 −90 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -301,19 +298,40 @@ status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args return NO_ERROR; } status_t AudioFlinger::dump(int fd, const Vector<String16>& args) static bool tryLock(Mutex& mutex) { 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) { 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 { // 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); dumpInternals(fd, args); Loading Loading @@ -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 Loading Loading @@ -672,8 +698,6 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted) mHardwareMixerThread->setStreamMute(stream, muted); } return NO_ERROR; } Loading Loading @@ -837,12 +861,10 @@ 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: // 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); Loading @@ -850,10 +872,7 @@ void AudioFlinger::handleStreamDisablesA2dp_l(int command) } } LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount); } break; case ACTIVE_TRACK_REMOVED: { } else { if (mA2dpDisableCount > 0) { if (--mA2dpDisableCount == 0) { if (mA2dpSuppressed) { Loading @@ -866,8 +885,6 @@ void AudioFlinger::handleStreamDisablesA2dp_l(int command) LOGE("mA2dpDisableCount is already zero"); } } break; } } #endif Loading Loading @@ -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 } } Loading @@ -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 } } Loading Loading @@ -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)); Loading @@ -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 Loading Loading @@ -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 { Loading @@ -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; } Loading Loading @@ -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() Loading Loading @@ -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(); Loading @@ -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); } Loading libs/audioflinger/AudioFlinger.h +1 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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. Loading libs/audioflinger/AudioMixer.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ */ #define LOG_TAG "AudioMixer" //#define LOG_NDEBUG 0 #include <stdint.h> #include <string.h> Loading Loading @@ -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; Loading Loading
include/utils/ResourceTypes.h +1 −1 Original line number Diff line number Diff line Loading @@ -814,7 +814,7 @@ struct ResTable_config ORIENTATION_ANY = 0x0000, ORIENTATION_PORT = 0x0001, ORIENTATION_LAND = 0x0002, ORIENTATION_SQUARE = 0x0002, ORIENTATION_SQUARE = 0x0003, }; enum { Loading
libs/audioflinger/AudioFlinger.cpp +71 −90 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -301,19 +298,40 @@ status_t AudioFlinger::dumpPermissionDenial(int fd, const Vector<String16>& args return NO_ERROR; } status_t AudioFlinger::dump(int fd, const Vector<String16>& args) static bool tryLock(Mutex& mutex) { 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) { 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 { // 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); dumpInternals(fd, args); Loading Loading @@ -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 Loading Loading @@ -672,8 +698,6 @@ status_t AudioFlinger::setStreamMute(int stream, bool muted) mHardwareMixerThread->setStreamMute(stream, muted); } return NO_ERROR; } Loading Loading @@ -837,12 +861,10 @@ 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: // 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); Loading @@ -850,10 +872,7 @@ void AudioFlinger::handleStreamDisablesA2dp_l(int command) } } LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount); } break; case ACTIVE_TRACK_REMOVED: { } else { if (mA2dpDisableCount > 0) { if (--mA2dpDisableCount == 0) { if (mA2dpSuppressed) { Loading @@ -866,8 +885,6 @@ void AudioFlinger::handleStreamDisablesA2dp_l(int command) LOGE("mA2dpDisableCount is already zero"); } } break; } } #endif Loading Loading @@ -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 } } Loading @@ -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 } } Loading Loading @@ -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)); Loading @@ -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 Loading Loading @@ -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 { Loading @@ -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; } Loading Loading @@ -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() Loading Loading @@ -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(); Loading @@ -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); } Loading
libs/audioflinger/AudioFlinger.h +1 −2 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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. Loading
libs/audioflinger/AudioMixer.cpp +4 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ */ #define LOG_TAG "AudioMixer" //#define LOG_NDEBUG 0 #include <stdint.h> #include <string.h> Loading Loading @@ -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; Loading