Loading libs/audioflinger/AudioFlinger.cpp +147 −90 Original line number Original line Diff line number Diff line Loading @@ -674,25 +674,7 @@ void AudioFlinger::binderDied(const wp<IBinder>& who) { } } // audioConfigChanged_l() must be called with AudioFlinger::mLock held // audioConfigChanged_l() must be called with AudioFlinger::mLock held void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2) { void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) { int ioHandle = 0; for (size_t i = 0; i < mPlaybackThreads.size(); i++) { if (mPlaybackThreads.valueAt(i) == thread) { ioHandle = mPlaybackThreads.keyAt(i); break; } } if (ioHandle == 0) { for (size_t i = 0; i < mRecordThreads.size(); i++) { if (mRecordThreads.valueAt(i) == thread) { ioHandle = mRecordThreads.keyAt(i); break; } } } if (ioHandle != 0) { size_t size = mNotificationClients.size(); size_t size = mNotificationClients.size(); for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) { sp<IBinder> binder = mNotificationClients.itemAt(i); sp<IBinder> binder = mNotificationClients.itemAt(i); Loading @@ -701,7 +683,6 @@ void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, client->ioConfigChanged(event, ioHandle, param2); client->ioConfigChanged(event, ioHandle, param2); } } } } } // removeClient_l() must be called with AudioFlinger::mLock held // removeClient_l() must be called with AudioFlinger::mLock held void AudioFlinger::removeClient_l(pid_t pid) void AudioFlinger::removeClient_l(pid_t pid) Loading @@ -712,10 +693,10 @@ void AudioFlinger::removeClient_l(pid_t pid) // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger) AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id) : Thread(false), : Thread(false), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mFrameSize(1), mStandby(false) mFormat(0), mFrameSize(1), mStandby(false), mId(id), mExiting(false) { { } } Loading @@ -734,6 +715,7 @@ void AudioFlinger::ThreadBase::exit() LOGV("ThreadBase::exit"); LOGV("ThreadBase::exit"); { { AutoMutex lock(&mLock); AutoMutex lock(&mLock); mExiting = true; requestExit(); requestExit(); mWaitWorkCV.signal(); mWaitWorkCV.signal(); } } Loading Loading @@ -870,8 +852,8 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) : ThreadBase(audioFlinger), : ThreadBase(audioFlinger, id), mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false) mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false) { { Loading Loading @@ -1106,15 +1088,6 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) { { status_t status = ALREADY_EXISTS; status_t status = ALREADY_EXISTS; // here the track could be either new, or restarted // in both cases "unstop" the track if (track->isPaused()) { track->mState = TrackBase::RESUMING; LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this); } else { track->mState = TrackBase::ACTIVE; LOGV("? => ACTIVE (%d) on thread %p", track->name(), this); } // set retry count for buffer fill // set retry count for buffer fill track->mRetryCount = kMaxTrackStartupRetries; track->mRetryCount = kMaxTrackStartupRetries; if (mActiveTracks.indexOf(track) < 0) { if (mActiveTracks.indexOf(track) < 0) { Loading Loading @@ -1173,7 +1146,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) { break; break; } } Mutex::Autolock _l(mAudioFlinger->mLock); Mutex::Autolock _l(mAudioFlinger->mLock); mAudioFlinger->audioConfigChanged_l(event, this, param2); mAudioFlinger->audioConfigChanged_l(event, mId, param2); } } void AudioFlinger::PlaybackThread::readOutputParameters() void AudioFlinger::PlaybackThread::readOutputParameters() Loading @@ -1194,8 +1167,8 @@ void AudioFlinger::PlaybackThread::readOutputParameters() // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) : PlaybackThread(audioFlinger, output), : PlaybackThread(audioFlinger, output, id), mAudioMixer(0) mAudioMixer(0) { { mType = PlaybackThread::MIXER; mType = PlaybackThread::MIXER; Loading Loading @@ -1303,7 +1276,6 @@ bool AudioFlinger::MixerThread::threadLoop() } } } else if (mBytesWritten != 0 || } else if (mBytesWritten != 0 || (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) { (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) { LOGV("NO DATA READY, %p", this); memset (curBuf, 0, mixBufferSize); memset (curBuf, 0, mixBufferSize); sleepTime = 0; sleepTime = 0; LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start"); LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start"); Loading Loading @@ -1639,8 +1611,8 @@ uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) : PlaybackThread(audioFlinger, output), : PlaybackThread(audioFlinger, output, id), mLeftVolume (1.0), mRightVolume(1.0) mLeftVolume (1.0), mRightVolume(1.0) { { mType = PlaybackThread::DIRECT; mType = PlaybackThread::DIRECT; Loading Loading @@ -1941,8 +1913,8 @@ uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread) AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id) : MixerThread(audioFlinger, mainThread->getOutput()) : MixerThread(audioFlinger, mainThread->getOutput(), id) { { mType = PlaybackThread::DUPLICATING; mType = PlaybackThread::DUPLICATING; addOutputTrack(mainThread); addOutputTrack(mainThread); Loading Loading @@ -2305,8 +2277,10 @@ AudioFlinger::PlaybackThread::Track::~Track() LOGV("PlaybackThread::Track destructor"); LOGV("PlaybackThread::Track destructor"); sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { Mutex::Autolock _l(thread->mLock); thread->mLock.lock(); mState = TERMINATED; mState = TERMINATED; thread->mLock.unlock(); AudioSystem::releaseOutput(thread->id()); } } } } Loading @@ -2324,6 +2298,9 @@ void AudioFlinger::PlaybackThread::Track::destroy() { // scope for mLock { // scope for mLock sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { if (!isOutputTrack() && (mState == ACTIVE || mState == RESUMING)) { AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); } Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); playbackThread->destroyTrack_l(this); playbackThread->destroyTrack_l(this); Loading Loading @@ -2405,14 +2382,37 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { status_t AudioFlinger::PlaybackThread::Track::start() status_t AudioFlinger::PlaybackThread::Track::start() { { status_t status = NO_ERROR; LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock); int state = mState; // here the track could be either new, or restarted // in both cases "unstop" the track if (mState == PAUSED) { mState = TrackBase::RESUMING; LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this); } else { mState = TrackBase::ACTIVE; LOGV("? => ACTIVE (%d) on thread %p", mName, this); } if (!isOutputTrack() && state != ACTIVE && state != RESUMING) { thread->mLock.unlock(); status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType); thread->mLock.lock(); } if (status == NO_ERROR) { PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); playbackThread->addTrack_l(this); playbackThread->addTrack_l(this); } else { mState = state; } } return NO_ERROR; } else { status = BAD_VALUE; } return status; } } void AudioFlinger::PlaybackThread::Track::stop() void AudioFlinger::PlaybackThread::Track::stop() Loading @@ -2421,6 +2421,7 @@ void AudioFlinger::PlaybackThread::Track::stop() sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock); int state = mState; if (mState > STOPPED) { if (mState > STOPPED) { mState = STOPPED; mState = STOPPED; // If the track is not active (PAUSED and buffers full), flush buffers // If the track is not active (PAUSED and buffers full), flush buffers Loading @@ -2430,6 +2431,11 @@ void AudioFlinger::PlaybackThread::Track::stop() } } LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread); LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread); } } if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) { thread->mLock.unlock(); AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); thread->mLock.lock(); } } } } } Loading @@ -2442,6 +2448,11 @@ void AudioFlinger::PlaybackThread::Track::pause() if (mState == ACTIVE || mState == RESUMING) { if (mState == ACTIVE || mState == RESUMING) { mState = PAUSING; mState = PAUSING; LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); if (!isOutputTrack()) { thread->mLock.unlock(); AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); thread->mLock.lock(); } } } } } } } Loading Loading @@ -2525,6 +2536,10 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( AudioFlinger::RecordThread::RecordTrack::~RecordTrack() AudioFlinger::RecordThread::RecordTrack::~RecordTrack() { { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { AudioSystem::releaseInput(thread->id()); } } } status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) Loading Loading @@ -2572,8 +2587,9 @@ status_t AudioFlinger::RecordThread::RecordTrack::start() if (thread != 0) { if (thread != 0) { RecordThread *recordThread = (RecordThread *)thread.get(); RecordThread *recordThread = (RecordThread *)thread.get(); return recordThread->start(this); return recordThread->start(this); } else { return BAD_VALUE; } } return NO_INIT; } } void AudioFlinger::RecordThread::RecordTrack::stop() void AudioFlinger::RecordThread::RecordTrack::stop() Loading Loading @@ -3010,8 +3026,8 @@ status_t AudioFlinger::RecordHandle::onTransact( // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) : AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) : ThreadBase(audioFlinger), ThreadBase(audioFlinger, id), mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) { { mReqChannelCount = AudioSystem::popCount(channels); mReqChannelCount = AudioSystem::popCount(channels); Loading Loading @@ -3039,6 +3055,7 @@ void AudioFlinger::RecordThread::onFirstRef() run(buffer, PRIORITY_URGENT_AUDIO); run(buffer, PRIORITY_URGENT_AUDIO); } } bool AudioFlinger::RecordThread::threadLoop() bool AudioFlinger::RecordThread::threadLoop() { { AudioBufferProvider::Buffer buffer; AudioBufferProvider::Buffer buffer; Loading Loading @@ -3084,6 +3101,10 @@ bool AudioFlinger::RecordThread::threadLoop() } } if (mActiveTrack != 0) { if (mActiveTrack != 0) { if (mActiveTrack->mState != TrackBase::ACTIVE) { usleep(5000); continue; } buffer.frameCount = mFrameCount; buffer.frameCount = mFrameCount; if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) { if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) { size_t framesOut = buffer.frameCount; size_t framesOut = buffer.frameCount; Loading Loading @@ -3181,6 +3202,8 @@ bool AudioFlinger::RecordThread::threadLoop() } } mActiveTrack.clear(); mActiveTrack.clear(); mStartStopCond.broadcast(); LOGV("RecordThread %p exiting", this); LOGV("RecordThread %p exiting", this); return false; return false; } } Loading @@ -3188,37 +3211,71 @@ bool AudioFlinger::RecordThread::threadLoop() status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack) status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack) { { LOGV("RecordThread::start"); LOGV("RecordThread::start"); sp <ThreadBase> strongMe = this; status_t status = NO_ERROR; { AutoMutex lock(&mLock); AutoMutex lock(&mLock); if (mActiveTrack != 0) { if (mActiveTrack != 0) { if (recordTrack != mActiveTrack.get()) return -EBUSY; if (recordTrack != mActiveTrack.get()) { status = -EBUSY; if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING; } else if (mActiveTrack->mState == TrackBase::PAUSING) { mActiveTrack->mState = TrackBase::RESUMING; return NO_ERROR; } return status; } } recordTrack->mState = TrackBase::IDLE; mActiveTrack = recordTrack; mActiveTrack = recordTrack; mLock.unlock(); status_t status = AudioSystem::startInput(mId); mLock.lock(); if (status != NO_ERROR) { mActiveTrack.clear(); return status; } mActiveTrack->mState = TrackBase::RESUMING; mActiveTrack->mState = TrackBase::RESUMING; // signal thread to start // signal thread to start LOGV("Signal record thread"); LOGV("Signal record thread"); mWaitWorkCV.signal(); mWaitWorkCV.signal(); // do not wait for mStartStopCond if exiting if (mExiting) { mActiveTrack.clear(); status = INVALID_OPERATION; goto startError; } mStartStopCond.wait(mLock); mStartStopCond.wait(mLock); if (mActiveTrack != 0) { if (mActiveTrack == 0) { LOGV("Record started OK"); return NO_ERROR; } else { LOGV("Record failed to start"); LOGV("Record failed to start"); return BAD_VALUE; status = BAD_VALUE; goto startError; } } LOGV("Record started OK"); return status; } startError: AudioSystem::stopInput(mId); return status; } } void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { LOGV("RecordThread::stop"); LOGV("RecordThread::stop"); sp <ThreadBase> strongMe = this; { AutoMutex lock(&mLock); AutoMutex lock(&mLock); if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) { if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) { mActiveTrack->mState = TrackBase::PAUSING; mActiveTrack->mState = TrackBase::PAUSING; // do not wait for mStartStopCond if exiting if (mExiting) { return; } mStartStopCond.wait(mLock); mStartStopCond.wait(mLock); // if we have been restarted, recordTrack == mActiveTrack.get() here if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) { mLock.unlock(); AudioSystem::stopInput(mId); mLock.lock(); } } } } } } Loading Loading @@ -3388,7 +3445,7 @@ void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) { break; break; } } Mutex::Autolock _l(mAudioFlinger->mLock); Mutex::Autolock _l(mAudioFlinger->mLock); mAudioFlinger->audioConfigChanged_l(event, this, param2); mAudioFlinger->audioConfigChanged_l(event, mId, param2); } } void AudioFlinger::RecordThread::readInputParameters() void AudioFlinger::RecordThread::readInputParameters() Loading Loading @@ -3476,13 +3533,13 @@ int AudioFlinger::openOutput(uint32_t *pDevices, if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || (format != AudioSystem::PCM_16_BIT) || (format != AudioSystem::PCM_16_BIT) || (channels != AudioSystem::CHANNEL_OUT_STEREO)) { (channels != AudioSystem::CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output); thread = new DirectOutputThread(this, output, ++mNextThreadId); LOGV("openOutput() created direct output: ID %d thread %p", (mNextThreadId + 1), thread); LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread); } else { } else { thread = new MixerThread(this, output); thread = new MixerThread(this, output, ++mNextThreadId); LOGV("openOutput() created mixer output: ID %d thread %p", (mNextThreadId + 1), thread); LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread); } } mPlaybackThreads.add(++mNextThreadId, thread); mPlaybackThreads.add(mNextThreadId, thread); if (pSamplingRate) *pSamplingRate = samplingRate; if (pSamplingRate) *pSamplingRate = samplingRate; if (pFormat) *pFormat = format; if (pFormat) *pFormat = format; Loading @@ -3505,9 +3562,9 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2) } } DuplicatingThread *thread = new DuplicatingThread(this, thread1); DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId); thread->addOutputTrack(thread2); thread->addOutputTrack(thread2); mPlaybackThreads.add(++mNextThreadId, thread); mPlaybackThreads.add(mNextThreadId, thread); return mNextThreadId; return mNextThreadId; } } Loading @@ -3534,7 +3591,7 @@ status_t AudioFlinger::closeOutput(int output) } } } } void *param2 = 0; void *param2 = 0; audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, thread, param2); audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2); mPlaybackThreads.removeItem(output); mPlaybackThreads.removeItem(output); } } thread->exit(); thread->exit(); Loading Loading @@ -3628,8 +3685,8 @@ int AudioFlinger::openInput(uint32_t *pDevices, if (input != 0) { if (input != 0) { // Start record thread // Start record thread thread = new RecordThread(this, input, reqSamplingRate, reqChannels); thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId); mRecordThreads.add(++mNextThreadId, thread); mRecordThreads.add(mNextThreadId, thread); LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread); LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread); if (pSamplingRate) *pSamplingRate = reqSamplingRate; if (pSamplingRate) *pSamplingRate = reqSamplingRate; if (pFormat) *pFormat = format; if (pFormat) *pFormat = format; Loading @@ -3655,7 +3712,7 @@ status_t AudioFlinger::closeInput(int input) LOGV("closeInput() %d", input); LOGV("closeInput() %d", input); void *param2 = 0; void *param2 = 0; audioConfigChanged_l(AudioSystem::INPUT_CLOSED, thread, param2); audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2); mRecordThreads.removeItem(input); mRecordThreads.removeItem(input); } } thread->exit(); thread->exit(); Loading libs/audioflinger/AudioFlinger.h +15 −7 Original line number Original line Diff line number Diff line Loading @@ -213,7 +213,7 @@ private: class ThreadBase : public Thread { class ThreadBase : public Thread { public: public: ThreadBase (const sp<AudioFlinger>& audioFlinger); ThreadBase (const sp<AudioFlinger>& audioFlinger, int id); virtual ~ThreadBase(); virtual ~ThreadBase(); status_t dumpBase(int fd, const Vector<String16>& args); status_t dumpBase(int fd, const Vector<String16>& args); Loading Loading @@ -323,6 +323,7 @@ private: void sendConfigEvent(int event, int param = 0); void sendConfigEvent(int event, int param = 0); void sendConfigEvent_l(int event, int param = 0); void sendConfigEvent_l(int event, int param = 0); void processConfigEvents(); void processConfigEvents(); int id() const { return mId;} mutable Mutex mLock; mutable Mutex mLock; Loading @@ -349,6 +350,8 @@ private: status_t mParamStatus; status_t mParamStatus; Vector<ConfigEvent *> mConfigEvents; Vector<ConfigEvent *> mConfigEvents; bool mStandby; bool mStandby; int mId; bool mExiting; }; }; // --- PlaybackThread --- // --- PlaybackThread --- Loading Loading @@ -421,6 +424,10 @@ private: void setPaused() { mState = PAUSED; } void setPaused() { mState = PAUSED; } void reset(); void reset(); bool isOutputTrack() const { return (mStreamType == AudioSystem::NUM_STREAM_TYPES); } // we don't really need a lock for these // we don't really need a lock for these float mVolume[2]; float mVolume[2]; volatile bool mMute; volatile bool mMute; Loading Loading @@ -473,7 +480,7 @@ private: }; // end of OutputTrack }; // end of OutputTrack PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); virtual ~PlaybackThread(); virtual ~PlaybackThread(); virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t dump(int fd, const Vector<String16>& args); Loading Loading @@ -573,7 +580,7 @@ private: class MixerThread : public PlaybackThread { class MixerThread : public PlaybackThread { public: public: MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); virtual ~MixerThread(); virtual ~MixerThread(); // Thread virtuals // Thread virtuals Loading @@ -600,7 +607,7 @@ private: class DirectOutputThread : public PlaybackThread { class DirectOutputThread : public PlaybackThread { public: public: DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); ~DirectOutputThread(); ~DirectOutputThread(); // Thread virtuals // Thread virtuals Loading @@ -621,7 +628,7 @@ private: class DuplicatingThread : public MixerThread { class DuplicatingThread : public MixerThread { public: public: DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread); DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, int id); ~DuplicatingThread(); ~DuplicatingThread(); // Thread virtuals // Thread virtuals Loading @@ -637,7 +644,7 @@ private: MixerThread *checkMixerThread_l(int output) const; MixerThread *checkMixerThread_l(int output) const; RecordThread *checkRecordThread_l(int input) const; RecordThread *checkRecordThread_l(int input) const; float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } void audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2); void audioConfigChanged_l(int event, int ioHandle, void *param2); friend class AudioBuffer; friend class AudioBuffer; Loading Loading @@ -705,7 +712,8 @@ private: RecordThread(const sp<AudioFlinger>& audioFlinger, RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, AudioStreamIn *input, uint32_t sampleRate, uint32_t sampleRate, uint32_t channels); uint32_t channels, int id); ~RecordThread(); ~RecordThread(); virtual bool threadLoop(); virtual bool threadLoop(); Loading Loading
libs/audioflinger/AudioFlinger.cpp +147 −90 Original line number Original line Diff line number Diff line Loading @@ -674,25 +674,7 @@ void AudioFlinger::binderDied(const wp<IBinder>& who) { } } // audioConfigChanged_l() must be called with AudioFlinger::mLock held // audioConfigChanged_l() must be called with AudioFlinger::mLock held void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2) { void AudioFlinger::audioConfigChanged_l(int event, int ioHandle, void *param2) { int ioHandle = 0; for (size_t i = 0; i < mPlaybackThreads.size(); i++) { if (mPlaybackThreads.valueAt(i) == thread) { ioHandle = mPlaybackThreads.keyAt(i); break; } } if (ioHandle == 0) { for (size_t i = 0; i < mRecordThreads.size(); i++) { if (mRecordThreads.valueAt(i) == thread) { ioHandle = mRecordThreads.keyAt(i); break; } } } if (ioHandle != 0) { size_t size = mNotificationClients.size(); size_t size = mNotificationClients.size(); for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) { sp<IBinder> binder = mNotificationClients.itemAt(i); sp<IBinder> binder = mNotificationClients.itemAt(i); Loading @@ -701,7 +683,6 @@ void AudioFlinger::audioConfigChanged_l(int event, const sp<ThreadBase>& thread, client->ioConfigChanged(event, ioHandle, param2); client->ioConfigChanged(event, ioHandle, param2); } } } } } // removeClient_l() must be called with AudioFlinger::mLock held // removeClient_l() must be called with AudioFlinger::mLock held void AudioFlinger::removeClient_l(pid_t pid) void AudioFlinger::removeClient_l(pid_t pid) Loading @@ -712,10 +693,10 @@ void AudioFlinger::removeClient_l(pid_t pid) // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger) AudioFlinger::ThreadBase::ThreadBase(const sp<AudioFlinger>& audioFlinger, int id) : Thread(false), : Thread(false), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), mAudioFlinger(audioFlinger), mSampleRate(0), mFrameCount(0), mChannelCount(0), mFormat(0), mFrameSize(1), mStandby(false) mFormat(0), mFrameSize(1), mStandby(false), mId(id), mExiting(false) { { } } Loading @@ -734,6 +715,7 @@ void AudioFlinger::ThreadBase::exit() LOGV("ThreadBase::exit"); LOGV("ThreadBase::exit"); { { AutoMutex lock(&mLock); AutoMutex lock(&mLock); mExiting = true; requestExit(); requestExit(); mWaitWorkCV.signal(); mWaitWorkCV.signal(); } } Loading Loading @@ -870,8 +852,8 @@ status_t AudioFlinger::ThreadBase::dumpBase(int fd, const Vector<String16>& args // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) : ThreadBase(audioFlinger), : ThreadBase(audioFlinger, id), mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), mMixBuffer(0), mSuspended(0), mBytesWritten(0), mOutput(output), mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false) mLastWriteTime(0), mNumWrites(0), mNumDelayedWrites(0), mInWrite(false) { { Loading Loading @@ -1106,15 +1088,6 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) { { status_t status = ALREADY_EXISTS; status_t status = ALREADY_EXISTS; // here the track could be either new, or restarted // in both cases "unstop" the track if (track->isPaused()) { track->mState = TrackBase::RESUMING; LOGV("PAUSED => RESUMING (%d) on thread %p", track->name(), this); } else { track->mState = TrackBase::ACTIVE; LOGV("? => ACTIVE (%d) on thread %p", track->name(), this); } // set retry count for buffer fill // set retry count for buffer fill track->mRetryCount = kMaxTrackStartupRetries; track->mRetryCount = kMaxTrackStartupRetries; if (mActiveTracks.indexOf(track) < 0) { if (mActiveTracks.indexOf(track) < 0) { Loading Loading @@ -1173,7 +1146,7 @@ void AudioFlinger::PlaybackThread::audioConfigChanged(int event, int param) { break; break; } } Mutex::Autolock _l(mAudioFlinger->mLock); Mutex::Autolock _l(mAudioFlinger->mLock); mAudioFlinger->audioConfigChanged_l(event, this, param2); mAudioFlinger->audioConfigChanged_l(event, mId, param2); } } void AudioFlinger::PlaybackThread::readOutputParameters() void AudioFlinger::PlaybackThread::readOutputParameters() Loading @@ -1194,8 +1167,8 @@ void AudioFlinger::PlaybackThread::readOutputParameters() // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) : PlaybackThread(audioFlinger, output), : PlaybackThread(audioFlinger, output, id), mAudioMixer(0) mAudioMixer(0) { { mType = PlaybackThread::MIXER; mType = PlaybackThread::MIXER; Loading Loading @@ -1303,7 +1276,6 @@ bool AudioFlinger::MixerThread::threadLoop() } } } else if (mBytesWritten != 0 || } else if (mBytesWritten != 0 || (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) { (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)) { LOGV("NO DATA READY, %p", this); memset (curBuf, 0, mixBufferSize); memset (curBuf, 0, mixBufferSize); sleepTime = 0; sleepTime = 0; LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start"); LOGV_IF((mBytesWritten == 0 && (mixerStatus == MIXER_TRACKS_ENABLED && longStandbyExit)), "anticipated start"); Loading Loading @@ -1639,8 +1611,8 @@ uint32_t AudioFlinger::MixerThread::idleSleepTimeUs() } } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output) AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id) : PlaybackThread(audioFlinger, output), : PlaybackThread(audioFlinger, output, id), mLeftVolume (1.0), mRightVolume(1.0) mLeftVolume (1.0), mRightVolume(1.0) { { mType = PlaybackThread::DIRECT; mType = PlaybackThread::DIRECT; Loading Loading @@ -1941,8 +1913,8 @@ uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread) AudioFlinger::DuplicatingThread::DuplicatingThread(const sp<AudioFlinger>& audioFlinger, AudioFlinger::MixerThread* mainThread, int id) : MixerThread(audioFlinger, mainThread->getOutput()) : MixerThread(audioFlinger, mainThread->getOutput(), id) { { mType = PlaybackThread::DUPLICATING; mType = PlaybackThread::DUPLICATING; addOutputTrack(mainThread); addOutputTrack(mainThread); Loading Loading @@ -2305,8 +2277,10 @@ AudioFlinger::PlaybackThread::Track::~Track() LOGV("PlaybackThread::Track destructor"); LOGV("PlaybackThread::Track destructor"); sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { Mutex::Autolock _l(thread->mLock); thread->mLock.lock(); mState = TERMINATED; mState = TERMINATED; thread->mLock.unlock(); AudioSystem::releaseOutput(thread->id()); } } } } Loading @@ -2324,6 +2298,9 @@ void AudioFlinger::PlaybackThread::Track::destroy() { // scope for mLock { // scope for mLock sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { if (!isOutputTrack() && (mState == ACTIVE || mState == RESUMING)) { AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); } Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); playbackThread->destroyTrack_l(this); playbackThread->destroyTrack_l(this); Loading Loading @@ -2405,14 +2382,37 @@ bool AudioFlinger::PlaybackThread::Track::isReady() const { status_t AudioFlinger::PlaybackThread::Track::start() status_t AudioFlinger::PlaybackThread::Track::start() { { status_t status = NO_ERROR; LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); LOGV("start(%d), calling thread %d", mName, IPCThreadState::self()->getCallingPid()); sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock); int state = mState; // here the track could be either new, or restarted // in both cases "unstop" the track if (mState == PAUSED) { mState = TrackBase::RESUMING; LOGV("PAUSED => RESUMING (%d) on thread %p", mName, this); } else { mState = TrackBase::ACTIVE; LOGV("? => ACTIVE (%d) on thread %p", mName, this); } if (!isOutputTrack() && state != ACTIVE && state != RESUMING) { thread->mLock.unlock(); status = AudioSystem::startOutput(thread->id(), (AudioSystem::stream_type)mStreamType); thread->mLock.lock(); } if (status == NO_ERROR) { PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); PlaybackThread *playbackThread = (PlaybackThread *)thread.get(); playbackThread->addTrack_l(this); playbackThread->addTrack_l(this); } else { mState = state; } } return NO_ERROR; } else { status = BAD_VALUE; } return status; } } void AudioFlinger::PlaybackThread::Track::stop() void AudioFlinger::PlaybackThread::Track::stop() Loading @@ -2421,6 +2421,7 @@ void AudioFlinger::PlaybackThread::Track::stop() sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { Mutex::Autolock _l(thread->mLock); Mutex::Autolock _l(thread->mLock); int state = mState; if (mState > STOPPED) { if (mState > STOPPED) { mState = STOPPED; mState = STOPPED; // If the track is not active (PAUSED and buffers full), flush buffers // If the track is not active (PAUSED and buffers full), flush buffers Loading @@ -2430,6 +2431,11 @@ void AudioFlinger::PlaybackThread::Track::stop() } } LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread); LOGV("(> STOPPED) => STOPPED (%d) on thread %p", mName, playbackThread); } } if (!isOutputTrack() && (state == ACTIVE || state == RESUMING)) { thread->mLock.unlock(); AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); thread->mLock.lock(); } } } } } Loading @@ -2442,6 +2448,11 @@ void AudioFlinger::PlaybackThread::Track::pause() if (mState == ACTIVE || mState == RESUMING) { if (mState == ACTIVE || mState == RESUMING) { mState = PAUSING; mState = PAUSING; LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); LOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); if (!isOutputTrack()) { thread->mLock.unlock(); AudioSystem::stopOutput(thread->id(), (AudioSystem::stream_type)mStreamType); thread->mLock.lock(); } } } } } } } Loading Loading @@ -2525,6 +2536,10 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack( AudioFlinger::RecordThread::RecordTrack::~RecordTrack() AudioFlinger::RecordThread::RecordTrack::~RecordTrack() { { sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { AudioSystem::releaseInput(thread->id()); } } } status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) status_t AudioFlinger::RecordThread::RecordTrack::getNextBuffer(AudioBufferProvider::Buffer* buffer) Loading Loading @@ -2572,8 +2587,9 @@ status_t AudioFlinger::RecordThread::RecordTrack::start() if (thread != 0) { if (thread != 0) { RecordThread *recordThread = (RecordThread *)thread.get(); RecordThread *recordThread = (RecordThread *)thread.get(); return recordThread->start(this); return recordThread->start(this); } else { return BAD_VALUE; } } return NO_INIT; } } void AudioFlinger::RecordThread::RecordTrack::stop() void AudioFlinger::RecordThread::RecordTrack::stop() Loading Loading @@ -3010,8 +3026,8 @@ status_t AudioFlinger::RecordHandle::onTransact( // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels) : AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, uint32_t sampleRate, uint32_t channels, int id) : ThreadBase(audioFlinger), ThreadBase(audioFlinger, id), mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) mInput(input), mResampler(0), mRsmpOutBuffer(0), mRsmpInBuffer(0) { { mReqChannelCount = AudioSystem::popCount(channels); mReqChannelCount = AudioSystem::popCount(channels); Loading Loading @@ -3039,6 +3055,7 @@ void AudioFlinger::RecordThread::onFirstRef() run(buffer, PRIORITY_URGENT_AUDIO); run(buffer, PRIORITY_URGENT_AUDIO); } } bool AudioFlinger::RecordThread::threadLoop() bool AudioFlinger::RecordThread::threadLoop() { { AudioBufferProvider::Buffer buffer; AudioBufferProvider::Buffer buffer; Loading Loading @@ -3084,6 +3101,10 @@ bool AudioFlinger::RecordThread::threadLoop() } } if (mActiveTrack != 0) { if (mActiveTrack != 0) { if (mActiveTrack->mState != TrackBase::ACTIVE) { usleep(5000); continue; } buffer.frameCount = mFrameCount; buffer.frameCount = mFrameCount; if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) { if (LIKELY(mActiveTrack->getNextBuffer(&buffer) == NO_ERROR)) { size_t framesOut = buffer.frameCount; size_t framesOut = buffer.frameCount; Loading Loading @@ -3181,6 +3202,8 @@ bool AudioFlinger::RecordThread::threadLoop() } } mActiveTrack.clear(); mActiveTrack.clear(); mStartStopCond.broadcast(); LOGV("RecordThread %p exiting", this); LOGV("RecordThread %p exiting", this); return false; return false; } } Loading @@ -3188,37 +3211,71 @@ bool AudioFlinger::RecordThread::threadLoop() status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack) status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrack) { { LOGV("RecordThread::start"); LOGV("RecordThread::start"); sp <ThreadBase> strongMe = this; status_t status = NO_ERROR; { AutoMutex lock(&mLock); AutoMutex lock(&mLock); if (mActiveTrack != 0) { if (mActiveTrack != 0) { if (recordTrack != mActiveTrack.get()) return -EBUSY; if (recordTrack != mActiveTrack.get()) { status = -EBUSY; if (mActiveTrack->mState == TrackBase::PAUSING) mActiveTrack->mState = TrackBase::RESUMING; } else if (mActiveTrack->mState == TrackBase::PAUSING) { mActiveTrack->mState = TrackBase::RESUMING; return NO_ERROR; } return status; } } recordTrack->mState = TrackBase::IDLE; mActiveTrack = recordTrack; mActiveTrack = recordTrack; mLock.unlock(); status_t status = AudioSystem::startInput(mId); mLock.lock(); if (status != NO_ERROR) { mActiveTrack.clear(); return status; } mActiveTrack->mState = TrackBase::RESUMING; mActiveTrack->mState = TrackBase::RESUMING; // signal thread to start // signal thread to start LOGV("Signal record thread"); LOGV("Signal record thread"); mWaitWorkCV.signal(); mWaitWorkCV.signal(); // do not wait for mStartStopCond if exiting if (mExiting) { mActiveTrack.clear(); status = INVALID_OPERATION; goto startError; } mStartStopCond.wait(mLock); mStartStopCond.wait(mLock); if (mActiveTrack != 0) { if (mActiveTrack == 0) { LOGV("Record started OK"); return NO_ERROR; } else { LOGV("Record failed to start"); LOGV("Record failed to start"); return BAD_VALUE; status = BAD_VALUE; goto startError; } } LOGV("Record started OK"); return status; } startError: AudioSystem::stopInput(mId); return status; } } void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { void AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { LOGV("RecordThread::stop"); LOGV("RecordThread::stop"); sp <ThreadBase> strongMe = this; { AutoMutex lock(&mLock); AutoMutex lock(&mLock); if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) { if (mActiveTrack != 0 && recordTrack == mActiveTrack.get()) { mActiveTrack->mState = TrackBase::PAUSING; mActiveTrack->mState = TrackBase::PAUSING; // do not wait for mStartStopCond if exiting if (mExiting) { return; } mStartStopCond.wait(mLock); mStartStopCond.wait(mLock); // if we have been restarted, recordTrack == mActiveTrack.get() here if (mActiveTrack == 0 || recordTrack != mActiveTrack.get()) { mLock.unlock(); AudioSystem::stopInput(mId); mLock.lock(); } } } } } } Loading Loading @@ -3388,7 +3445,7 @@ void AudioFlinger::RecordThread::audioConfigChanged(int event, int param) { break; break; } } Mutex::Autolock _l(mAudioFlinger->mLock); Mutex::Autolock _l(mAudioFlinger->mLock); mAudioFlinger->audioConfigChanged_l(event, this, param2); mAudioFlinger->audioConfigChanged_l(event, mId, param2); } } void AudioFlinger::RecordThread::readInputParameters() void AudioFlinger::RecordThread::readInputParameters() Loading Loading @@ -3476,13 +3533,13 @@ int AudioFlinger::openOutput(uint32_t *pDevices, if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || if ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || (format != AudioSystem::PCM_16_BIT) || (format != AudioSystem::PCM_16_BIT) || (channels != AudioSystem::CHANNEL_OUT_STEREO)) { (channels != AudioSystem::CHANNEL_OUT_STEREO)) { thread = new DirectOutputThread(this, output); thread = new DirectOutputThread(this, output, ++mNextThreadId); LOGV("openOutput() created direct output: ID %d thread %p", (mNextThreadId + 1), thread); LOGV("openOutput() created direct output: ID %d thread %p", mNextThreadId, thread); } else { } else { thread = new MixerThread(this, output); thread = new MixerThread(this, output, ++mNextThreadId); LOGV("openOutput() created mixer output: ID %d thread %p", (mNextThreadId + 1), thread); LOGV("openOutput() created mixer output: ID %d thread %p", mNextThreadId, thread); } } mPlaybackThreads.add(++mNextThreadId, thread); mPlaybackThreads.add(mNextThreadId, thread); if (pSamplingRate) *pSamplingRate = samplingRate; if (pSamplingRate) *pSamplingRate = samplingRate; if (pFormat) *pFormat = format; if (pFormat) *pFormat = format; Loading @@ -3505,9 +3562,9 @@ int AudioFlinger::openDuplicateOutput(int output1, int output2) } } DuplicatingThread *thread = new DuplicatingThread(this, thread1); DuplicatingThread *thread = new DuplicatingThread(this, thread1, ++mNextThreadId); thread->addOutputTrack(thread2); thread->addOutputTrack(thread2); mPlaybackThreads.add(++mNextThreadId, thread); mPlaybackThreads.add(mNextThreadId, thread); return mNextThreadId; return mNextThreadId; } } Loading @@ -3534,7 +3591,7 @@ status_t AudioFlinger::closeOutput(int output) } } } } void *param2 = 0; void *param2 = 0; audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, thread, param2); audioConfigChanged_l(AudioSystem::OUTPUT_CLOSED, output, param2); mPlaybackThreads.removeItem(output); mPlaybackThreads.removeItem(output); } } thread->exit(); thread->exit(); Loading Loading @@ -3628,8 +3685,8 @@ int AudioFlinger::openInput(uint32_t *pDevices, if (input != 0) { if (input != 0) { // Start record thread // Start record thread thread = new RecordThread(this, input, reqSamplingRate, reqChannels); thread = new RecordThread(this, input, reqSamplingRate, reqChannels, ++mNextThreadId); mRecordThreads.add(++mNextThreadId, thread); mRecordThreads.add(mNextThreadId, thread); LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread); LOGV("openInput() created record thread: ID %d thread %p", mNextThreadId, thread); if (pSamplingRate) *pSamplingRate = reqSamplingRate; if (pSamplingRate) *pSamplingRate = reqSamplingRate; if (pFormat) *pFormat = format; if (pFormat) *pFormat = format; Loading @@ -3655,7 +3712,7 @@ status_t AudioFlinger::closeInput(int input) LOGV("closeInput() %d", input); LOGV("closeInput() %d", input); void *param2 = 0; void *param2 = 0; audioConfigChanged_l(AudioSystem::INPUT_CLOSED, thread, param2); audioConfigChanged_l(AudioSystem::INPUT_CLOSED, input, param2); mRecordThreads.removeItem(input); mRecordThreads.removeItem(input); } } thread->exit(); thread->exit(); Loading
libs/audioflinger/AudioFlinger.h +15 −7 Original line number Original line Diff line number Diff line Loading @@ -213,7 +213,7 @@ private: class ThreadBase : public Thread { class ThreadBase : public Thread { public: public: ThreadBase (const sp<AudioFlinger>& audioFlinger); ThreadBase (const sp<AudioFlinger>& audioFlinger, int id); virtual ~ThreadBase(); virtual ~ThreadBase(); status_t dumpBase(int fd, const Vector<String16>& args); status_t dumpBase(int fd, const Vector<String16>& args); Loading Loading @@ -323,6 +323,7 @@ private: void sendConfigEvent(int event, int param = 0); void sendConfigEvent(int event, int param = 0); void sendConfigEvent_l(int event, int param = 0); void sendConfigEvent_l(int event, int param = 0); void processConfigEvents(); void processConfigEvents(); int id() const { return mId;} mutable Mutex mLock; mutable Mutex mLock; Loading @@ -349,6 +350,8 @@ private: status_t mParamStatus; status_t mParamStatus; Vector<ConfigEvent *> mConfigEvents; Vector<ConfigEvent *> mConfigEvents; bool mStandby; bool mStandby; int mId; bool mExiting; }; }; // --- PlaybackThread --- // --- PlaybackThread --- Loading Loading @@ -421,6 +424,10 @@ private: void setPaused() { mState = PAUSED; } void setPaused() { mState = PAUSED; } void reset(); void reset(); bool isOutputTrack() const { return (mStreamType == AudioSystem::NUM_STREAM_TYPES); } // we don't really need a lock for these // we don't really need a lock for these float mVolume[2]; float mVolume[2]; volatile bool mMute; volatile bool mMute; Loading Loading @@ -473,7 +480,7 @@ private: }; // end of OutputTrack }; // end of OutputTrack PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); PlaybackThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); virtual ~PlaybackThread(); virtual ~PlaybackThread(); virtual status_t dump(int fd, const Vector<String16>& args); virtual status_t dump(int fd, const Vector<String16>& args); Loading Loading @@ -573,7 +580,7 @@ private: class MixerThread : public PlaybackThread { class MixerThread : public PlaybackThread { public: public: MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); MixerThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); virtual ~MixerThread(); virtual ~MixerThread(); // Thread virtuals // Thread virtuals Loading @@ -600,7 +607,7 @@ private: class DirectOutputThread : public PlaybackThread { class DirectOutputThread : public PlaybackThread { public: public: DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output); DirectOutputThread (const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id); ~DirectOutputThread(); ~DirectOutputThread(); // Thread virtuals // Thread virtuals Loading @@ -621,7 +628,7 @@ private: class DuplicatingThread : public MixerThread { class DuplicatingThread : public MixerThread { public: public: DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread); DuplicatingThread (const sp<AudioFlinger>& audioFlinger, MixerThread* mainThread, int id); ~DuplicatingThread(); ~DuplicatingThread(); // Thread virtuals // Thread virtuals Loading @@ -637,7 +644,7 @@ private: MixerThread *checkMixerThread_l(int output) const; MixerThread *checkMixerThread_l(int output) const; RecordThread *checkRecordThread_l(int input) const; RecordThread *checkRecordThread_l(int input) const; float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } float streamVolumeInternal(int stream) const { return mStreamTypes[stream].volume; } void audioConfigChanged_l(int event, const sp<ThreadBase>& thread, void *param2); void audioConfigChanged_l(int event, int ioHandle, void *param2); friend class AudioBuffer; friend class AudioBuffer; Loading Loading @@ -705,7 +712,8 @@ private: RecordThread(const sp<AudioFlinger>& audioFlinger, RecordThread(const sp<AudioFlinger>& audioFlinger, AudioStreamIn *input, AudioStreamIn *input, uint32_t sampleRate, uint32_t sampleRate, uint32_t channels); uint32_t channels, int id); ~RecordThread(); ~RecordThread(); virtual bool threadLoop(); virtual bool threadLoop(); Loading