Loading services/audioflinger/Threads.cpp +32 −27 Original line number Diff line number Diff line Loading @@ -960,6 +960,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mUseAsyncWrite(false), mWriteAckSequence(0), mDrainSequence(0), mSignalPending(false), mScreenState(AudioFlinger::mScreenState), // index 0 is reserved for normal mixer's submix mFastTrackAvailMask(((1 << FastMixerState::kMaxFastTracks) - 1) & ~1), Loading Loading @@ -1348,14 +1349,14 @@ void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, f { Mutex::Autolock _l(mLock); mStreamTypes[stream].volume = value; signal_l(); broadcast_l(); } void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted) { Mutex::Autolock _l(mLock); mStreamTypes[stream].mute = muted; signal_l(); broadcast_l(); } float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const Loading Loading @@ -1413,8 +1414,8 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) status = NO_ERROR; } ALOGV("mWaitWorkCV.broadcast"); mWaitWorkCV.broadcast(); ALOGV("signal playback thread"); broadcast_l(); return status; } Loading Loading @@ -1455,14 +1456,14 @@ void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track) } } void AudioFlinger::PlaybackThread::signal_l() void AudioFlinger::PlaybackThread::broadcast_l() { // Thread could be blocked waiting for async // so signal it to handle state changes immediately // If threadLoop is currently unlocked a signal of mWaitWorkCV will // be lost so we also flag to prevent it blocking on mWaitWorkCV mSignalPending = true; mWaitWorkCV.signal(); mWaitWorkCV.broadcast(); } String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) Loading Loading @@ -2143,7 +2144,6 @@ bool AudioFlinger::PlaybackThread::threadLoop() } saveOutputTracks(); if (mSignalPending) { // A signal was raised while we were unlocked mSignalPending = false; Loading @@ -2158,10 +2158,10 @@ bool AudioFlinger::PlaybackThread::threadLoop() acquireWakeLock_l(); standbyTime = systemTime() + standbyDelay; sleepTime = 0; if (exitPending()) { break; continue; } } else if ((!mActiveTracks.size() && systemTime() > standbyTime) || if ((!mActiveTracks.size() && systemTime() > standbyTime) || isSuspended()) { // put audio hardware into standby after short delay if (shouldStandby_l()) { Loading Loading @@ -2203,7 +2203,6 @@ bool AudioFlinger::PlaybackThread::threadLoop() continue; } } // mMixerStatusIgnoringFastTracks is also updated internally mMixerStatus = prepareTracks_l(&tracksToRemove); Loading Loading @@ -3855,13 +3854,14 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr Vector< sp<Track> > *tracksToRemove ) { ALOGV("OffloadThread::prepareTracks_l"); size_t count = mActiveTracks.size(); mixer_state mixerStatus = MIXER_IDLE; bool doHwPause = false; bool doHwResume = false; ALOGV("OffloadThread::prepareTracks_l active tracks %d", count); // find out which tracks need to be processed for (size_t i = 0; i < count; i++) { sp<Track> t = mActiveTracks[i].promote(); Loading Loading @@ -3915,23 +3915,27 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // make sure processVolume_l() will apply new volume even if 0 mLeftVolFloat = mRightVolFloat = -1.0; if (track->mState == TrackBase::RESUMING) { track->mState = TrackBase::ACTIVE; if (last) { if (mPausedBytesRemaining) { // Need to continue write that was interrupted mCurrentWriteLength = mPausedWriteLength; mBytesRemaining = mPausedBytesRemaining; mPausedBytesRemaining = 0; } track->mState = TrackBase::ACTIVE; } } if (last) { if (mHwPaused) { doHwResume = true; mHwPaused = false; // threadLoop_mix() will handle the case that we need to // resume an interrupted write } // enable write to audio HAL sleepTime = 0; } } } if (last) { // reset retry count track->mRetryCount = kMaxTrackRetriesOffload; mActiveTrack = t; Loading @@ -3948,9 +3952,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // has been written ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2"); track->mState = TrackBase::STOPPING_2; // so presentation completes after drain if (last) { sleepTime = 0; standbyTime = systemTime() + standbyDelay; if (last) { mixerStatus = MIXER_DRAIN_TRACK; mDrainSequence += 2; if (mHwPaused) { Loading Loading @@ -4337,6 +4341,7 @@ bool AudioFlinger::RecordThread::threadLoop() mStandby = false; } } lockEffectChains_l(effectChains); } Loading services/audioflinger/Threads.h +3 −1 Original line number Diff line number Diff line Loading @@ -526,7 +526,7 @@ private: status_t addTrack_l(const sp<Track>& track); bool destroyTrack_l(const sp<Track>& track); void removeTrack_l(const sp<Track>& track); void signal_l(); void broadcast_l(); void readOutputParameters(); Loading Loading @@ -590,6 +590,8 @@ private: // Bit 0 is reset by the async callback thread calling resetDraining(). Out of sequence // callbacks are ignored. uint32_t mDrainSequence; // A condition that must be evaluated by prepareTrack_l() has changed and we must not wait // for async write callback in the thread loop before evaluating it bool mSignalPending; sp<AsyncCallbackThread> mCallbackThread; Loading services/audioflinger/Tracks.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -651,7 +651,7 @@ void AudioFlinger::PlaybackThread::Track::pause() case RESUMING: mState = PAUSING; ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); playbackThread->signal_l(); playbackThread->broadcast_l(); break; default: Loading Loading @@ -711,7 +711,7 @@ void AudioFlinger::PlaybackThread::Track::flush() // before mixer thread can run. This is important when offloading // because the hardware buffer could hold a large amount of audio playbackThread->flushOutput_l(); playbackThread->signal_l(); playbackThread->broadcast_l(); } } Loading Loading
services/audioflinger/Threads.cpp +32 −27 Original line number Diff line number Diff line Loading @@ -960,6 +960,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge mUseAsyncWrite(false), mWriteAckSequence(0), mDrainSequence(0), mSignalPending(false), mScreenState(AudioFlinger::mScreenState), // index 0 is reserved for normal mixer's submix mFastTrackAvailMask(((1 << FastMixerState::kMaxFastTracks) - 1) & ~1), Loading Loading @@ -1348,14 +1349,14 @@ void AudioFlinger::PlaybackThread::setStreamVolume(audio_stream_type_t stream, f { Mutex::Autolock _l(mLock); mStreamTypes[stream].volume = value; signal_l(); broadcast_l(); } void AudioFlinger::PlaybackThread::setStreamMute(audio_stream_type_t stream, bool muted) { Mutex::Autolock _l(mLock); mStreamTypes[stream].mute = muted; signal_l(); broadcast_l(); } float AudioFlinger::PlaybackThread::streamVolume(audio_stream_type_t stream) const Loading Loading @@ -1413,8 +1414,8 @@ status_t AudioFlinger::PlaybackThread::addTrack_l(const sp<Track>& track) status = NO_ERROR; } ALOGV("mWaitWorkCV.broadcast"); mWaitWorkCV.broadcast(); ALOGV("signal playback thread"); broadcast_l(); return status; } Loading Loading @@ -1455,14 +1456,14 @@ void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track) } } void AudioFlinger::PlaybackThread::signal_l() void AudioFlinger::PlaybackThread::broadcast_l() { // Thread could be blocked waiting for async // so signal it to handle state changes immediately // If threadLoop is currently unlocked a signal of mWaitWorkCV will // be lost so we also flag to prevent it blocking on mWaitWorkCV mSignalPending = true; mWaitWorkCV.signal(); mWaitWorkCV.broadcast(); } String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) Loading Loading @@ -2143,7 +2144,6 @@ bool AudioFlinger::PlaybackThread::threadLoop() } saveOutputTracks(); if (mSignalPending) { // A signal was raised while we were unlocked mSignalPending = false; Loading @@ -2158,10 +2158,10 @@ bool AudioFlinger::PlaybackThread::threadLoop() acquireWakeLock_l(); standbyTime = systemTime() + standbyDelay; sleepTime = 0; if (exitPending()) { break; continue; } } else if ((!mActiveTracks.size() && systemTime() > standbyTime) || if ((!mActiveTracks.size() && systemTime() > standbyTime) || isSuspended()) { // put audio hardware into standby after short delay if (shouldStandby_l()) { Loading Loading @@ -2203,7 +2203,6 @@ bool AudioFlinger::PlaybackThread::threadLoop() continue; } } // mMixerStatusIgnoringFastTracks is also updated internally mMixerStatus = prepareTracks_l(&tracksToRemove); Loading Loading @@ -3855,13 +3854,14 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr Vector< sp<Track> > *tracksToRemove ) { ALOGV("OffloadThread::prepareTracks_l"); size_t count = mActiveTracks.size(); mixer_state mixerStatus = MIXER_IDLE; bool doHwPause = false; bool doHwResume = false; ALOGV("OffloadThread::prepareTracks_l active tracks %d", count); // find out which tracks need to be processed for (size_t i = 0; i < count; i++) { sp<Track> t = mActiveTracks[i].promote(); Loading Loading @@ -3915,23 +3915,27 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // make sure processVolume_l() will apply new volume even if 0 mLeftVolFloat = mRightVolFloat = -1.0; if (track->mState == TrackBase::RESUMING) { track->mState = TrackBase::ACTIVE; if (last) { if (mPausedBytesRemaining) { // Need to continue write that was interrupted mCurrentWriteLength = mPausedWriteLength; mBytesRemaining = mPausedBytesRemaining; mPausedBytesRemaining = 0; } track->mState = TrackBase::ACTIVE; } } if (last) { if (mHwPaused) { doHwResume = true; mHwPaused = false; // threadLoop_mix() will handle the case that we need to // resume an interrupted write } // enable write to audio HAL sleepTime = 0; } } } if (last) { // reset retry count track->mRetryCount = kMaxTrackRetriesOffload; mActiveTrack = t; Loading @@ -3948,9 +3952,9 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::OffloadThread::prepareTr // has been written ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2"); track->mState = TrackBase::STOPPING_2; // so presentation completes after drain if (last) { sleepTime = 0; standbyTime = systemTime() + standbyDelay; if (last) { mixerStatus = MIXER_DRAIN_TRACK; mDrainSequence += 2; if (mHwPaused) { Loading Loading @@ -4337,6 +4341,7 @@ bool AudioFlinger::RecordThread::threadLoop() mStandby = false; } } lockEffectChains_l(effectChains); } Loading
services/audioflinger/Threads.h +3 −1 Original line number Diff line number Diff line Loading @@ -526,7 +526,7 @@ private: status_t addTrack_l(const sp<Track>& track); bool destroyTrack_l(const sp<Track>& track); void removeTrack_l(const sp<Track>& track); void signal_l(); void broadcast_l(); void readOutputParameters(); Loading Loading @@ -590,6 +590,8 @@ private: // Bit 0 is reset by the async callback thread calling resetDraining(). Out of sequence // callbacks are ignored. uint32_t mDrainSequence; // A condition that must be evaluated by prepareTrack_l() has changed and we must not wait // for async write callback in the thread loop before evaluating it bool mSignalPending; sp<AsyncCallbackThread> mCallbackThread; Loading
services/audioflinger/Tracks.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -651,7 +651,7 @@ void AudioFlinger::PlaybackThread::Track::pause() case RESUMING: mState = PAUSING; ALOGV("ACTIVE/RESUMING => PAUSING (%d) on thread %p", mName, thread.get()); playbackThread->signal_l(); playbackThread->broadcast_l(); break; default: Loading Loading @@ -711,7 +711,7 @@ void AudioFlinger::PlaybackThread::Track::flush() // before mixer thread can run. This is important when offloading // because the hardware buffer could hold a large amount of audio playbackThread->flushOutput_l(); playbackThread->signal_l(); playbackThread->broadcast_l(); } } Loading