Loading services/audioflinger/AudioFlinger.cpp +123 −37 Original line number Diff line number Diff line Loading @@ -868,16 +868,19 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& if (mBtNrecIsOff != btNrecIsOff) { for (size_t i = 0; i < mRecordThreads.size(); i++) { sp<RecordThread> thread = mRecordThreads.valueAt(i); RecordThread::RecordTrack *track = thread->track(); if (track != NULL) { audio_devices_t device = thread->device() & AUDIO_DEVICE_IN_ALL; bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff; // collect all of the thread's session IDs KeyedVector<int, bool> ids = thread->sessionIds(); // suspend effects associated with those session IDs for (size_t j = 0; j < ids.size(); ++j) { int sessionId = ids.keyAt(j); thread->setEffectSuspended(FX_IID_AEC, suspend, track->sessionId()); sessionId); thread->setEffectSuspended(FX_IID_NS, suspend, track->sessionId()); sessionId); } } mBtNrecIsOff = btNrecIsOff; Loading Loading @@ -4277,11 +4280,6 @@ AudioFlinger::PlaybackThread::Track::Track( AudioFlinger::PlaybackThread::Track::~Track() { ALOGV("PlaybackThread::Track destructor"); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); mState = TERMINATED; } } void AudioFlinger::PlaybackThread::Track::destroy() Loading Loading @@ -5301,10 +5299,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( AudioFlinger::RecordThread::RecordTrack::~RecordTrack() { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { AudioSystem::releaseInput(thread->id()); } ALOGV("%s", __func__); } // AudioBufferProvider interface Loading Loading @@ -5377,6 +5372,11 @@ void AudioFlinger::RecordThread::RecordTrack::stop() } } /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) { result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n"); } void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) { snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n", Loading Loading @@ -5861,6 +5861,7 @@ AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::Re AudioFlinger::RecordHandle::~RecordHandle() { stop_nonvirtual(); mRecordTrack->destroy(); } sp<IMemory> AudioFlinger::RecordHandle::getCblk() const { Loading Loading @@ -5896,7 +5897,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, audio_devices_t device) : ThreadBase(audioFlinger, id, device, RECORD), mInput(input), mTrack(NULL), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), mInput(input), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), // mRsmpInIndex and mInputBytes set by readInputParameters() mReqChannelCount(popcount(channelMask)), mReqSampleRate(sampleRate) Loading Loading @@ -5980,6 +5981,9 @@ bool AudioFlinger::RecordThread::threadLoop() mStartStopCond.broadcast(); } mStandby = false; } else if (mActiveTrack->mState == TrackBase::TERMINATED) { removeTrack_l(mActiveTrack); mActiveTrack.clear(); } } lockEffectChains_l(effectChains); Loading Loading @@ -6168,8 +6172,8 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR lStatus = NO_MEMORY; goto Exit; } mTracks.add(track); mTrack = track.get(); // disable AEC and NS if the device is a BT SCO headset supporting those pre processings bool suspend = audio_is_bluetooth_sco_device(mDevice & AUDIO_DEVICE_IN_ALL) && mAudioFlinger->btNrecIsOff(); Loading Loading @@ -6320,16 +6324,63 @@ status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event) return BAD_VALUE; } int eventSession = event->triggerSession(); status_t ret = NAME_NOT_FOUND; Mutex::Autolock _l(mLock); if (mTrack != NULL && event->triggerSession() == mTrack->sessionId()) { mTrack->setSyncEvent(event); return NO_ERROR; for (size_t i = 0; i < mTracks.size(); i++) { sp<RecordTrack> track = mTracks[i]; if (eventSession == track->sessionId()) { track->setSyncEvent(event); ret = NO_ERROR; } return NAME_NOT_FOUND; } return ret; } void AudioFlinger::RecordThread::RecordTrack::destroy() { // see comments at AudioFlinger::PlaybackThread::Track::destroy() sp<RecordTrack> keep(this); { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (mState == ACTIVE || mState == RESUMING) { AudioSystem::stopInput(thread->id()); } AudioSystem::releaseInput(thread->id()); Mutex::Autolock _l(thread->mLock); RecordThread *recordThread = (RecordThread *) thread.get(); recordThread->destroyTrack_l(this); } } } // destroyTrack_l() must be called with ThreadBase::mLock held void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track) { track->mState = TrackBase::TERMINATED; // active tracks are removed by threadLoop() if (mActiveTrack != track) { removeTrack_l(track); } } void AudioFlinger::RecordThread::removeTrack_l(const sp<RecordTrack>& track) { mTracks.remove(track); // need anything related to effects here? } void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) { dumpInternals(fd, args); dumpTracks(fd, args); dumpEffectChains(fd, args); } void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& args) { const size_t SIZE = 256; char buffer[SIZE]; Loading @@ -6339,11 +6390,6 @@ void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) result.append(buffer); if (mActiveTrack != 0) { result.append("Active Track:\n"); result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n"); mActiveTrack->dump(buffer, SIZE); result.append(buffer); snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex); result.append(buffer); snprintf(buffer, SIZE, "In size: %d\n", mInputBytes); Loading @@ -6354,15 +6400,41 @@ void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) result.append(buffer); snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate); result.append(buffer); } else { result.append("No record client\n"); result.append("No active record client\n"); } write(fd, result.string(), result.size()); dumpBase(fd, args); dumpEffectChains(fd, args); } void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args) { const size_t SIZE = 256; char buffer[SIZE]; String8 result; snprintf(buffer, SIZE, "Input thread %p tracks\n", this); result.append(buffer); RecordTrack::appendDumpHeader(result); for (size_t i = 0; i < mTracks.size(); ++i) { sp<RecordTrack> track = mTracks[i]; if (track != 0) { track->dump(buffer, SIZE); result.append(buffer); } } if (mActiveTrack != 0) { snprintf(buffer, SIZE, "\nInput thread %p active tracks\n", this); result.append(buffer); RecordTrack::appendDumpHeader(result); mActiveTrack->dump(buffer, SIZE); result.append(buffer); } write(fd, result.string(), result.size()); } // AudioBufferProvider interface Loading Loading @@ -6462,11 +6534,14 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() } else { newDevice &= ~(value & AUDIO_DEVICE_IN_ALL); // disable AEC and NS if the device is a BT SCO headset supporting those pre processings if (mTrack != NULL) { if (mTracks.size() > 0) { bool suspend = audio_is_bluetooth_sco_device( (audio_devices_t)value) && mAudioFlinger->btNrecIsOff(); setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId()); setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId()); for (size_t i = 0; i < mTracks.size(); i++) { sp<RecordTrack> track = mTracks[i]; setEffectSuspended_l(FX_IID_AEC, suspend, track->sessionId()); setEffectSuspended_l(FX_IID_NS, suspend, track->sessionId()); } } } newDevice |= value; Loading Loading @@ -6605,17 +6680,28 @@ uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId) result = EFFECT_SESSION; } if (mTrack != NULL && sessionId == mTrack->sessionId()) { for (size_t i = 0; i < mTracks.size(); ++i) { if (sessionId == mTracks[i]->sessionId()) { result |= TRACK_SESSION; break; } } return result; } AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track() KeyedVector<int, bool> AudioFlinger::RecordThread::sessionIds() { KeyedVector<int, bool> ids; Mutex::Autolock _l(mLock); return mTrack; for (size_t j = 0; j < mTracks.size(); ++j) { sp<RecordThread::RecordTrack> track = mTracks[j]; int sessionId = track->sessionId(); if (ids.indexOfKey(sessionId) < 0) { ids.add(sessionId, true); } } return ids; } AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput() Loading services/audioflinger/AudioFlinger.h +18 −2 Original line number Diff line number Diff line Loading @@ -1381,11 +1381,14 @@ private: virtual status_t start(AudioSystem::sync_event_t event, int triggerSession); virtual void stop(); void destroy(); // clear the buffer overflow flag void clearOverflow() { mOverflow = false; } // set the buffer overflow flag and return previous value bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; } static void appendDumpHeader(String8& result); void dump(char* buffer, size_t size); private: Loading @@ -1409,6 +1412,13 @@ private: audio_devices_t device); virtual ~RecordThread(); // no addTrack_l ? void destroyTrack_l(const sp<RecordTrack>& track); void removeTrack_l(const sp<RecordTrack>& track); void dumpInternals(int fd, const Vector<String16>& args); void dumpTracks(int fd, const Vector<String16>& args); // Thread virtual bool threadLoop(); virtual status_t readyToRun(); Loading Loading @@ -1453,7 +1463,11 @@ private: virtual status_t addEffectChain_l(const sp<EffectChain>& chain); virtual size_t removeEffectChain_l(const sp<EffectChain>& chain); virtual uint32_t hasAudioSession(int sessionId); RecordTrack* track(); // Return the set of unique session IDs across all tracks. // The keys are the session IDs, and the associated values are meaningless. // FIXME replace by Set [and implement Bag/Multiset for other uses]. KeyedVector<int, bool> sessionIds(); virtual status_t setSyncEvent(const sp<SyncEvent>& event); virtual bool isValidSyncEvent(const sp<SyncEvent>& event); Loading @@ -1471,7 +1485,9 @@ private: void inputStandBy(); AudioStreamIn *mInput; RecordTrack* mTrack; SortedVector < sp<RecordTrack> > mTracks; // mActiveTrack has dual roles: it indicates the current active track, and // is used together with mStartStopCond to indicate start()/stop() progress sp<RecordTrack> mActiveTrack; Condition mStartStopCond; AudioResampler *mResampler; Loading Loading
services/audioflinger/AudioFlinger.cpp +123 −37 Original line number Diff line number Diff line Loading @@ -868,16 +868,19 @@ status_t AudioFlinger::setParameters(audio_io_handle_t ioHandle, const String8& if (mBtNrecIsOff != btNrecIsOff) { for (size_t i = 0; i < mRecordThreads.size(); i++) { sp<RecordThread> thread = mRecordThreads.valueAt(i); RecordThread::RecordTrack *track = thread->track(); if (track != NULL) { audio_devices_t device = thread->device() & AUDIO_DEVICE_IN_ALL; bool suspend = audio_is_bluetooth_sco_device(device) && btNrecIsOff; // collect all of the thread's session IDs KeyedVector<int, bool> ids = thread->sessionIds(); // suspend effects associated with those session IDs for (size_t j = 0; j < ids.size(); ++j) { int sessionId = ids.keyAt(j); thread->setEffectSuspended(FX_IID_AEC, suspend, track->sessionId()); sessionId); thread->setEffectSuspended(FX_IID_NS, suspend, track->sessionId()); sessionId); } } mBtNrecIsOff = btNrecIsOff; Loading Loading @@ -4277,11 +4280,6 @@ AudioFlinger::PlaybackThread::Track::Track( AudioFlinger::PlaybackThread::Track::~Track() { ALOGV("PlaybackThread::Track destructor"); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { Mutex::Autolock _l(thread->mLock); mState = TERMINATED; } } void AudioFlinger::PlaybackThread::Track::destroy() Loading Loading @@ -5301,10 +5299,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( AudioFlinger::RecordThread::RecordTrack::~RecordTrack() { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { AudioSystem::releaseInput(thread->id()); } ALOGV("%s", __func__); } // AudioBufferProvider interface Loading Loading @@ -5377,6 +5372,11 @@ void AudioFlinger::RecordThread::RecordTrack::stop() } } /*static*/ void AudioFlinger::RecordThread::RecordTrack::appendDumpHeader(String8& result) { result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n"); } void AudioFlinger::RecordThread::RecordTrack::dump(char* buffer, size_t size) { snprintf(buffer, size, " %05d %03u 0x%08x %05d %04u %01d %05u %08x %08x\n", Loading Loading @@ -5861,6 +5861,7 @@ AudioFlinger::RecordHandle::RecordHandle(const sp<AudioFlinger::RecordThread::Re AudioFlinger::RecordHandle::~RecordHandle() { stop_nonvirtual(); mRecordTrack->destroy(); } sp<IMemory> AudioFlinger::RecordHandle::getCblk() const { Loading Loading @@ -5896,7 +5897,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, audio_io_handle_t id, audio_devices_t device) : ThreadBase(audioFlinger, id, device, RECORD), mInput(input), mTrack(NULL), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), mInput(input), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), // mRsmpInIndex and mInputBytes set by readInputParameters() mReqChannelCount(popcount(channelMask)), mReqSampleRate(sampleRate) Loading Loading @@ -5980,6 +5981,9 @@ bool AudioFlinger::RecordThread::threadLoop() mStartStopCond.broadcast(); } mStandby = false; } else if (mActiveTrack->mState == TrackBase::TERMINATED) { removeTrack_l(mActiveTrack); mActiveTrack.clear(); } } lockEffectChains_l(effectChains); Loading Loading @@ -6168,8 +6172,8 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createR lStatus = NO_MEMORY; goto Exit; } mTracks.add(track); mTrack = track.get(); // disable AEC and NS if the device is a BT SCO headset supporting those pre processings bool suspend = audio_is_bluetooth_sco_device(mDevice & AUDIO_DEVICE_IN_ALL) && mAudioFlinger->btNrecIsOff(); Loading Loading @@ -6320,16 +6324,63 @@ status_t AudioFlinger::RecordThread::setSyncEvent(const sp<SyncEvent>& event) return BAD_VALUE; } int eventSession = event->triggerSession(); status_t ret = NAME_NOT_FOUND; Mutex::Autolock _l(mLock); if (mTrack != NULL && event->triggerSession() == mTrack->sessionId()) { mTrack->setSyncEvent(event); return NO_ERROR; for (size_t i = 0; i < mTracks.size(); i++) { sp<RecordTrack> track = mTracks[i]; if (eventSession == track->sessionId()) { track->setSyncEvent(event); ret = NO_ERROR; } return NAME_NOT_FOUND; } return ret; } void AudioFlinger::RecordThread::RecordTrack::destroy() { // see comments at AudioFlinger::PlaybackThread::Track::destroy() sp<RecordTrack> keep(this); { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (mState == ACTIVE || mState == RESUMING) { AudioSystem::stopInput(thread->id()); } AudioSystem::releaseInput(thread->id()); Mutex::Autolock _l(thread->mLock); RecordThread *recordThread = (RecordThread *) thread.get(); recordThread->destroyTrack_l(this); } } } // destroyTrack_l() must be called with ThreadBase::mLock held void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track) { track->mState = TrackBase::TERMINATED; // active tracks are removed by threadLoop() if (mActiveTrack != track) { removeTrack_l(track); } } void AudioFlinger::RecordThread::removeTrack_l(const sp<RecordTrack>& track) { mTracks.remove(track); // need anything related to effects here? } void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) { dumpInternals(fd, args); dumpTracks(fd, args); dumpEffectChains(fd, args); } void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& args) { const size_t SIZE = 256; char buffer[SIZE]; Loading @@ -6339,11 +6390,6 @@ void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) result.append(buffer); if (mActiveTrack != 0) { result.append("Active Track:\n"); result.append(" Clien Fmt Chn mask Session Buf S SRate Serv User\n"); mActiveTrack->dump(buffer, SIZE); result.append(buffer); snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex); result.append(buffer); snprintf(buffer, SIZE, "In size: %d\n", mInputBytes); Loading @@ -6354,15 +6400,41 @@ void AudioFlinger::RecordThread::dump(int fd, const Vector<String16>& args) result.append(buffer); snprintf(buffer, SIZE, "Out sample rate: %d\n", mReqSampleRate); result.append(buffer); } else { result.append("No record client\n"); result.append("No active record client\n"); } write(fd, result.string(), result.size()); dumpBase(fd, args); dumpEffectChains(fd, args); } void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args) { const size_t SIZE = 256; char buffer[SIZE]; String8 result; snprintf(buffer, SIZE, "Input thread %p tracks\n", this); result.append(buffer); RecordTrack::appendDumpHeader(result); for (size_t i = 0; i < mTracks.size(); ++i) { sp<RecordTrack> track = mTracks[i]; if (track != 0) { track->dump(buffer, SIZE); result.append(buffer); } } if (mActiveTrack != 0) { snprintf(buffer, SIZE, "\nInput thread %p active tracks\n", this); result.append(buffer); RecordTrack::appendDumpHeader(result); mActiveTrack->dump(buffer, SIZE); result.append(buffer); } write(fd, result.string(), result.size()); } // AudioBufferProvider interface Loading Loading @@ -6462,11 +6534,14 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() } else { newDevice &= ~(value & AUDIO_DEVICE_IN_ALL); // disable AEC and NS if the device is a BT SCO headset supporting those pre processings if (mTrack != NULL) { if (mTracks.size() > 0) { bool suspend = audio_is_bluetooth_sco_device( (audio_devices_t)value) && mAudioFlinger->btNrecIsOff(); setEffectSuspended_l(FX_IID_AEC, suspend, mTrack->sessionId()); setEffectSuspended_l(FX_IID_NS, suspend, mTrack->sessionId()); for (size_t i = 0; i < mTracks.size(); i++) { sp<RecordTrack> track = mTracks[i]; setEffectSuspended_l(FX_IID_AEC, suspend, track->sessionId()); setEffectSuspended_l(FX_IID_NS, suspend, track->sessionId()); } } } newDevice |= value; Loading Loading @@ -6605,17 +6680,28 @@ uint32_t AudioFlinger::RecordThread::hasAudioSession(int sessionId) result = EFFECT_SESSION; } if (mTrack != NULL && sessionId == mTrack->sessionId()) { for (size_t i = 0; i < mTracks.size(); ++i) { if (sessionId == mTracks[i]->sessionId()) { result |= TRACK_SESSION; break; } } return result; } AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track() KeyedVector<int, bool> AudioFlinger::RecordThread::sessionIds() { KeyedVector<int, bool> ids; Mutex::Autolock _l(mLock); return mTrack; for (size_t j = 0; j < mTracks.size(); ++j) { sp<RecordThread::RecordTrack> track = mTracks[j]; int sessionId = track->sessionId(); if (ids.indexOfKey(sessionId) < 0) { ids.add(sessionId, true); } } return ids; } AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput() Loading
services/audioflinger/AudioFlinger.h +18 −2 Original line number Diff line number Diff line Loading @@ -1381,11 +1381,14 @@ private: virtual status_t start(AudioSystem::sync_event_t event, int triggerSession); virtual void stop(); void destroy(); // clear the buffer overflow flag void clearOverflow() { mOverflow = false; } // set the buffer overflow flag and return previous value bool setOverflow() { bool tmp = mOverflow; mOverflow = true; return tmp; } static void appendDumpHeader(String8& result); void dump(char* buffer, size_t size); private: Loading @@ -1409,6 +1412,13 @@ private: audio_devices_t device); virtual ~RecordThread(); // no addTrack_l ? void destroyTrack_l(const sp<RecordTrack>& track); void removeTrack_l(const sp<RecordTrack>& track); void dumpInternals(int fd, const Vector<String16>& args); void dumpTracks(int fd, const Vector<String16>& args); // Thread virtual bool threadLoop(); virtual status_t readyToRun(); Loading Loading @@ -1453,7 +1463,11 @@ private: virtual status_t addEffectChain_l(const sp<EffectChain>& chain); virtual size_t removeEffectChain_l(const sp<EffectChain>& chain); virtual uint32_t hasAudioSession(int sessionId); RecordTrack* track(); // Return the set of unique session IDs across all tracks. // The keys are the session IDs, and the associated values are meaningless. // FIXME replace by Set [and implement Bag/Multiset for other uses]. KeyedVector<int, bool> sessionIds(); virtual status_t setSyncEvent(const sp<SyncEvent>& event); virtual bool isValidSyncEvent(const sp<SyncEvent>& event); Loading @@ -1471,7 +1485,9 @@ private: void inputStandBy(); AudioStreamIn *mInput; RecordTrack* mTrack; SortedVector < sp<RecordTrack> > mTracks; // mActiveTrack has dual roles: it indicates the current active track, and // is used together with mStartStopCond to indicate start()/stop() progress sp<RecordTrack> mActiveTrack; Condition mStartStopCond; AudioResampler *mResampler; Loading