Loading services/audioflinger/Threads.cpp +62 −29 Original line number Diff line number Diff line Loading @@ -4391,7 +4391,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, #endif ) : ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD), mInput(input), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), mInput(input), mActiveTracksGen(0), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), // mRsmpInFrames, mRsmpInFramesP2, mRsmpInUnrel, mRsmpInFront, and mRsmpInRear // are set by readInputParameters() // mRsmpInIndex LEGACY Loading Loading @@ -4435,10 +4435,25 @@ bool AudioFlinger::RecordThread::threadLoop() reacquire_wakelock: sp<RecordTrack> activeTrack; int activeTracksGen; { Mutex::Autolock _l(mLock); activeTrack = mActiveTrack; acquireWakeLock_l(activeTrack != 0 ? activeTrack->uid() : -1); size_t size = mActiveTracks.size(); activeTracksGen = mActiveTracksGen; if (size > 0) { // FIXME an arbitrary choice activeTrack = mActiveTracks[0]; acquireWakeLock_l(activeTrack->uid()); if (size > 1) { SortedVector<int> tmp; for (size_t i = 0; i < size; i++) { tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); } } else { acquireWakeLock_l(-1); } } // start recording Loading @@ -4461,8 +4476,9 @@ reacquire_wakelock: // return value 'reconfig' is currently unused bool reconfig = checkForNewParameters_l(); // if no active track, then standby and release wakelock if (mActiveTrack == 0) { // if no active track(s), then standby and release wakelock size_t size = mActiveTracks.size(); if (size == 0) { standbyIfNotAlreadyInStandby(); // exitPending() can't become true here releaseWakeLock_l(); Loading @@ -4473,16 +4489,21 @@ reacquire_wakelock: goto reacquire_wakelock; } if (activeTrack != mActiveTrack) { if (mActiveTracksGen != activeTracksGen) { activeTracksGen = mActiveTracksGen; SortedVector<int> tmp; tmp.add(mActiveTrack->uid()); for (size_t i = 0; i < size; i++) { tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); activeTrack = mActiveTrack; // FIXME an arbitrary choice activeTrack = mActiveTracks[0]; } if (activeTrack->isTerminated()) { removeTrack_l(activeTrack); mActiveTrack.clear(); mActiveTracks.remove(activeTrack); mActiveTracksGen++; continue; } Loading @@ -4490,7 +4511,8 @@ reacquire_wakelock: switch (activeTrackState) { case TrackBase::PAUSING: standbyIfNotAlreadyInStandby(); mActiveTrack.clear(); mActiveTracks.remove(activeTrack); mActiveTracksGen++; mStartStopCond.broadcast(); doSleep = true; continue; Loading @@ -4498,7 +4520,8 @@ reacquire_wakelock: case TrackBase::RESUMING: mStandby = false; if (mReqChannelCount != activeTrack->channelCount()) { mActiveTrack.clear(); mActiveTracks.remove(activeTrack); mActiveTracksGen++; mStartStopCond.broadcast(); continue; } Loading @@ -4506,7 +4529,8 @@ reacquire_wakelock: mStartStopCond.broadcast(); // record start succeeds only if first read from audio input succeeds if (mBytesRead < 0) { mActiveTrack.clear(); mActiveTracks.remove(activeTrack); mActiveTracksGen++; continue; } activeTrack->mState = TrackBase::ACTIVE; Loading @@ -4527,7 +4551,7 @@ reacquire_wakelock: lockEffectChains_l(effectChains); } // thread mutex is now unlocked, mActiveTrack unknown, activeTrack != 0, kept, immutable // thread mutex is now unlocked, mActiveTracks unknown, activeTrack != 0, kept, immutable // activeTrack->mState unknown, activeTrackState immutable and is ACTIVE or RESUMING for (size_t i = 0; i < effectChains.size(); i ++) { Loading Loading @@ -4718,7 +4742,8 @@ reacquire_wakelock: sp<RecordTrack> track = mTracks[i]; track->invalidate(); } mActiveTrack.clear(); mActiveTracks.clear(); mActiveTracksGen++; mStartStopCond.broadcast(); } Loading Loading @@ -4877,8 +4902,9 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac { // This section is a rendezvous between binder thread executing start() and RecordThread AutoMutex lock(mLock); if (mActiveTrack != 0) { if (recordTrack != mActiveTrack.get()) { if (mActiveTracks.size() > 0) { // FIXME does not work for multiple active tracks if (mActiveTracks.indexOf(recordTrack) != 0) { status = -EBUSY; } else if (recordTrack->mState == TrackBase::PAUSING) { recordTrack->mState = TrackBase::ACTIVE; Loading @@ -4888,13 +4914,15 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac // FIXME why? already set in constructor, 'STARTING_1' would be more accurate recordTrack->mState = TrackBase::IDLE; mActiveTrack = recordTrack; mActiveTracks.add(recordTrack); mActiveTracksGen++; mLock.unlock(); status_t status = AudioSystem::startInput(mId); mLock.lock(); // FIXME should verify that mActiveTrack is still == recordTrack if (status != NO_ERROR) { mActiveTrack.clear(); mActiveTracks.remove(recordTrack); mActiveTracksGen++; clearSyncStartEvent(); return status; } Loading @@ -4915,13 +4943,14 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac mWaitWorkCV.broadcast(); // do not wait for mStartStopCond if exiting if (exitPending()) { mActiveTrack.clear(); mActiveTracks.remove(recordTrack); mActiveTracksGen++; status = INVALID_OPERATION; goto startError; } // FIXME incorrect usage of wait: no explicit predicate or loop mStartStopCond.wait(mLock); if (mActiveTrack == 0) { if (mActiveTracks.indexOf(recordTrack) < 0) { ALOGV("Record failed to start"); status = BAD_VALUE; goto startError; Loading Loading @@ -4967,7 +4996,7 @@ void AudioFlinger::RecordThread::handleSyncStartEvent(const sp<SyncEvent>& event bool AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { ALOGV("RecordThread::stop"); AutoMutex _l(mLock); if (recordTrack != mActiveTrack.get() || recordTrack->mState == TrackBase::PAUSING) { if (mActiveTracks.indexOf(recordTrack) != 0 || recordTrack->mState == TrackBase::PAUSING) { return false; } // note that threadLoop may still be processing the track at this point [without lock] Loading @@ -4978,8 +5007,8 @@ bool AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { } // FIXME incorrect usage of wait: no explicit predicate or loop mStartStopCond.wait(mLock); // if we have been restarted, recordTrack == mActiveTrack.get() here if (exitPending() || recordTrack != mActiveTrack.get()) { // if we have been restarted, recordTrack is in mActiveTracks here if (exitPending() || mActiveTracks.indexOf(recordTrack) != 0) { ALOGV("Record stopped OK"); return true; } Loading Loading @@ -5022,7 +5051,7 @@ void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track) track->terminate(); track->mState = TrackBase::STOPPED; // active tracks are removed by threadLoop() if (mActiveTrack != track) { if (mActiveTracks.indexOf(track) < 0) { removeTrack_l(track); } } Loading @@ -5049,7 +5078,7 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& a snprintf(buffer, SIZE, "\nInput thread %p internals\n", this); result.append(buffer); if (mActiveTrack != 0) { if (mActiveTracks.size() > 0) { snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex); result.append(buffer); snprintf(buffer, SIZE, "Buffer size: %u bytes\n", mBufferSize); Loading Loading @@ -5086,12 +5115,16 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args } } if (mActiveTrack != 0) { size_t size = mActiveTracks.size(); if (size > 0) { snprintf(buffer, SIZE, "\nInput thread %p active tracks\n", this); result.append(buffer); RecordTrack::appendDumpHeader(result); mActiveTrack->dump(buffer, SIZE); for (size_t i = 0; i < size; ++i) { sp<RecordTrack> track = mActiveTracks[i]; track->dump(buffer, SIZE); result.append(buffer); } } write(fd, result.string(), result.size()); Loading Loading @@ -5182,7 +5215,7 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() // do not accept frame count changes if tracks are open as the track buffer // size depends on frame count and correct behavior would not be guaranteed // if frame count is changed after track creation if (mActiveTrack != 0) { if (mActiveTracks.size() > 0) { status = INVALID_OPERATION; } else { reconfig = true; Loading services/audioflinger/Threads.h +4 −2 Original line number Diff line number Diff line Loading @@ -938,9 +938,11 @@ private: AudioStreamIn *mInput; SortedVector < sp<RecordTrack> > mTracks; // mActiveTrack has dual roles: it indicates the current active track, and // mActiveTracks has dual roles: it indicates the current active track(s), and // is used together with mStartStopCond to indicate start()/stop() progress sp<RecordTrack> mActiveTrack; SortedVector< sp<RecordTrack> > mActiveTracks; // generation counter for mActiveTracks int mActiveTracksGen; Condition mStartStopCond; // updated by RecordThread::readInputParameters() Loading Loading
services/audioflinger/Threads.cpp +62 −29 Original line number Diff line number Diff line Loading @@ -4391,7 +4391,7 @@ AudioFlinger::RecordThread::RecordThread(const sp<AudioFlinger>& audioFlinger, #endif ) : ThreadBase(audioFlinger, id, outDevice, inDevice, RECORD), mInput(input), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), mInput(input), mActiveTracksGen(0), mResampler(NULL), mRsmpOutBuffer(NULL), mRsmpInBuffer(NULL), // mRsmpInFrames, mRsmpInFramesP2, mRsmpInUnrel, mRsmpInFront, and mRsmpInRear // are set by readInputParameters() // mRsmpInIndex LEGACY Loading Loading @@ -4435,10 +4435,25 @@ bool AudioFlinger::RecordThread::threadLoop() reacquire_wakelock: sp<RecordTrack> activeTrack; int activeTracksGen; { Mutex::Autolock _l(mLock); activeTrack = mActiveTrack; acquireWakeLock_l(activeTrack != 0 ? activeTrack->uid() : -1); size_t size = mActiveTracks.size(); activeTracksGen = mActiveTracksGen; if (size > 0) { // FIXME an arbitrary choice activeTrack = mActiveTracks[0]; acquireWakeLock_l(activeTrack->uid()); if (size > 1) { SortedVector<int> tmp; for (size_t i = 0; i < size; i++) { tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); } } else { acquireWakeLock_l(-1); } } // start recording Loading @@ -4461,8 +4476,9 @@ reacquire_wakelock: // return value 'reconfig' is currently unused bool reconfig = checkForNewParameters_l(); // if no active track, then standby and release wakelock if (mActiveTrack == 0) { // if no active track(s), then standby and release wakelock size_t size = mActiveTracks.size(); if (size == 0) { standbyIfNotAlreadyInStandby(); // exitPending() can't become true here releaseWakeLock_l(); Loading @@ -4473,16 +4489,21 @@ reacquire_wakelock: goto reacquire_wakelock; } if (activeTrack != mActiveTrack) { if (mActiveTracksGen != activeTracksGen) { activeTracksGen = mActiveTracksGen; SortedVector<int> tmp; tmp.add(mActiveTrack->uid()); for (size_t i = 0; i < size; i++) { tmp.add(mActiveTracks[i]->uid()); } updateWakeLockUids_l(tmp); activeTrack = mActiveTrack; // FIXME an arbitrary choice activeTrack = mActiveTracks[0]; } if (activeTrack->isTerminated()) { removeTrack_l(activeTrack); mActiveTrack.clear(); mActiveTracks.remove(activeTrack); mActiveTracksGen++; continue; } Loading @@ -4490,7 +4511,8 @@ reacquire_wakelock: switch (activeTrackState) { case TrackBase::PAUSING: standbyIfNotAlreadyInStandby(); mActiveTrack.clear(); mActiveTracks.remove(activeTrack); mActiveTracksGen++; mStartStopCond.broadcast(); doSleep = true; continue; Loading @@ -4498,7 +4520,8 @@ reacquire_wakelock: case TrackBase::RESUMING: mStandby = false; if (mReqChannelCount != activeTrack->channelCount()) { mActiveTrack.clear(); mActiveTracks.remove(activeTrack); mActiveTracksGen++; mStartStopCond.broadcast(); continue; } Loading @@ -4506,7 +4529,8 @@ reacquire_wakelock: mStartStopCond.broadcast(); // record start succeeds only if first read from audio input succeeds if (mBytesRead < 0) { mActiveTrack.clear(); mActiveTracks.remove(activeTrack); mActiveTracksGen++; continue; } activeTrack->mState = TrackBase::ACTIVE; Loading @@ -4527,7 +4551,7 @@ reacquire_wakelock: lockEffectChains_l(effectChains); } // thread mutex is now unlocked, mActiveTrack unknown, activeTrack != 0, kept, immutable // thread mutex is now unlocked, mActiveTracks unknown, activeTrack != 0, kept, immutable // activeTrack->mState unknown, activeTrackState immutable and is ACTIVE or RESUMING for (size_t i = 0; i < effectChains.size(); i ++) { Loading Loading @@ -4718,7 +4742,8 @@ reacquire_wakelock: sp<RecordTrack> track = mTracks[i]; track->invalidate(); } mActiveTrack.clear(); mActiveTracks.clear(); mActiveTracksGen++; mStartStopCond.broadcast(); } Loading Loading @@ -4877,8 +4902,9 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac { // This section is a rendezvous between binder thread executing start() and RecordThread AutoMutex lock(mLock); if (mActiveTrack != 0) { if (recordTrack != mActiveTrack.get()) { if (mActiveTracks.size() > 0) { // FIXME does not work for multiple active tracks if (mActiveTracks.indexOf(recordTrack) != 0) { status = -EBUSY; } else if (recordTrack->mState == TrackBase::PAUSING) { recordTrack->mState = TrackBase::ACTIVE; Loading @@ -4888,13 +4914,15 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac // FIXME why? already set in constructor, 'STARTING_1' would be more accurate recordTrack->mState = TrackBase::IDLE; mActiveTrack = recordTrack; mActiveTracks.add(recordTrack); mActiveTracksGen++; mLock.unlock(); status_t status = AudioSystem::startInput(mId); mLock.lock(); // FIXME should verify that mActiveTrack is still == recordTrack if (status != NO_ERROR) { mActiveTrack.clear(); mActiveTracks.remove(recordTrack); mActiveTracksGen++; clearSyncStartEvent(); return status; } Loading @@ -4915,13 +4943,14 @@ status_t AudioFlinger::RecordThread::start(RecordThread::RecordTrack* recordTrac mWaitWorkCV.broadcast(); // do not wait for mStartStopCond if exiting if (exitPending()) { mActiveTrack.clear(); mActiveTracks.remove(recordTrack); mActiveTracksGen++; status = INVALID_OPERATION; goto startError; } // FIXME incorrect usage of wait: no explicit predicate or loop mStartStopCond.wait(mLock); if (mActiveTrack == 0) { if (mActiveTracks.indexOf(recordTrack) < 0) { ALOGV("Record failed to start"); status = BAD_VALUE; goto startError; Loading Loading @@ -4967,7 +4996,7 @@ void AudioFlinger::RecordThread::handleSyncStartEvent(const sp<SyncEvent>& event bool AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { ALOGV("RecordThread::stop"); AutoMutex _l(mLock); if (recordTrack != mActiveTrack.get() || recordTrack->mState == TrackBase::PAUSING) { if (mActiveTracks.indexOf(recordTrack) != 0 || recordTrack->mState == TrackBase::PAUSING) { return false; } // note that threadLoop may still be processing the track at this point [without lock] Loading @@ -4978,8 +5007,8 @@ bool AudioFlinger::RecordThread::stop(RecordThread::RecordTrack* recordTrack) { } // FIXME incorrect usage of wait: no explicit predicate or loop mStartStopCond.wait(mLock); // if we have been restarted, recordTrack == mActiveTrack.get() here if (exitPending() || recordTrack != mActiveTrack.get()) { // if we have been restarted, recordTrack is in mActiveTracks here if (exitPending() || mActiveTracks.indexOf(recordTrack) != 0) { ALOGV("Record stopped OK"); return true; } Loading Loading @@ -5022,7 +5051,7 @@ void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track) track->terminate(); track->mState = TrackBase::STOPPED; // active tracks are removed by threadLoop() if (mActiveTrack != track) { if (mActiveTracks.indexOf(track) < 0) { removeTrack_l(track); } } Loading @@ -5049,7 +5078,7 @@ void AudioFlinger::RecordThread::dumpInternals(int fd, const Vector<String16>& a snprintf(buffer, SIZE, "\nInput thread %p internals\n", this); result.append(buffer); if (mActiveTrack != 0) { if (mActiveTracks.size() > 0) { snprintf(buffer, SIZE, "In index: %d\n", mRsmpInIndex); result.append(buffer); snprintf(buffer, SIZE, "Buffer size: %u bytes\n", mBufferSize); Loading Loading @@ -5086,12 +5115,16 @@ void AudioFlinger::RecordThread::dumpTracks(int fd, const Vector<String16>& args } } if (mActiveTrack != 0) { size_t size = mActiveTracks.size(); if (size > 0) { snprintf(buffer, SIZE, "\nInput thread %p active tracks\n", this); result.append(buffer); RecordTrack::appendDumpHeader(result); mActiveTrack->dump(buffer, SIZE); for (size_t i = 0; i < size; ++i) { sp<RecordTrack> track = mActiveTracks[i]; track->dump(buffer, SIZE); result.append(buffer); } } write(fd, result.string(), result.size()); Loading Loading @@ -5182,7 +5215,7 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() // do not accept frame count changes if tracks are open as the track buffer // size depends on frame count and correct behavior would not be guaranteed // if frame count is changed after track creation if (mActiveTrack != 0) { if (mActiveTracks.size() > 0) { status = INVALID_OPERATION; } else { reconfig = true; Loading
services/audioflinger/Threads.h +4 −2 Original line number Diff line number Diff line Loading @@ -938,9 +938,11 @@ private: AudioStreamIn *mInput; SortedVector < sp<RecordTrack> > mTracks; // mActiveTrack has dual roles: it indicates the current active track, and // mActiveTracks has dual roles: it indicates the current active track(s), and // is used together with mStartStopCond to indicate start()/stop() progress sp<RecordTrack> mActiveTrack; SortedVector< sp<RecordTrack> > mActiveTracks; // generation counter for mActiveTracks int mActiveTracksGen; Condition mStartStopCond; // updated by RecordThread::readInputParameters() Loading