diff options
-rw-r--r-- | include/media/AudioSystem.h | 7 | ||||
-rw-r--r-- | media/libmedia/AudioSystem.cpp | 8 | ||||
-rw-r--r-- | media/libmedia/AudioTrack.cpp | 4 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.cpp | 20 | ||||
-rw-r--r-- | services/audioflinger/AudioFlinger.h | 6 |
5 files changed, 43 insertions, 2 deletions
diff --git a/include/media/AudioSystem.h b/include/media/AudioSystem.h index e0d7898..6a15f6e 100644 --- a/include/media/AudioSystem.h +++ b/include/media/AudioSystem.h @@ -185,6 +185,10 @@ public: static status_t unregisterEffect(int id); static status_t setEffectEnabled(int id, bool enabled); + // clear stream to output mapping cache (gStreamOutputMap) + // and output configuration cache (gOutputs) + static void clearAudioConfigCache(); + static const sp<IAudioPolicyService>& get_audio_policy_service(); // ---------------------------------------------------------------------------- @@ -236,7 +240,8 @@ private: // mapping between stream types and outputs static DefaultKeyedVector<int, audio_io_handle_t> gStreamOutputMap; - // list of output descritor containing cached parameters (sampling rate, framecount, channel count...) + // list of output descriptors containing cached parameters + // (sampling rate, framecount, channel count...) static DefaultKeyedVector<audio_io_handle_t, OutputDescriptor *> gOutputs; }; diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp index bb91fa9..853a5f6 100644 --- a/media/libmedia/AudioSystem.cpp +++ b/media/libmedia/AudioSystem.cpp @@ -727,6 +727,14 @@ status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs) } +void AudioSystem::clearAudioConfigCache() +{ + Mutex::Autolock _l(gLock); + LOGV("clearAudioConfigCache()"); + gStreamOutputMap.clear(); + gOutputs.clear(); +} + // --------------------------------------------------------------------------- void AudioSystem::AudioPolicyServiceClient::binderDied(const wp<IBinder>& who) { diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp index cecedb5..3b6c64d 100644 --- a/media/libmedia/AudioTrack.cpp +++ b/media/libmedia/AudioTrack.cpp @@ -1164,6 +1164,10 @@ status_t AudioTrack::restoreTrack_l(audio_track_cblk_t*& cblk, bool fromStart) cblk->cv.broadcast(); cblk->lock.unlock(); + // refresh the audio configuration cache in this process to make sure we get new + // output parameters in getOutput_l() and createTrack_l() + AudioSystem::clearAudioConfigCache(); + // if the new IAudioTrack is created, createTrack_l() will modify the // following member variables: mAudioTrack, mCblkMemory and mCblk. // It will also delete the strong references on previous IAudioTrack and IMemory diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp index 744fa50..2260091 100644 --- a/services/audioflinger/AudioFlinger.cpp +++ b/services/audioflinger/AudioFlinger.cpp @@ -1362,6 +1362,7 @@ AudioFlinger::PlaybackThread::PlaybackThread(const sp<AudioFlinger>& audioFlinge for (int stream = 0; stream < AUDIO_STREAM_CNT; stream++) { mStreamTypes[stream].volume = mAudioFlinger->streamVolumeInternal(stream); mStreamTypes[stream].mute = mAudioFlinger->streamMute(stream); + mStreamTypes[stream].valid = true; } } @@ -1530,6 +1531,14 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTra chain->setStrategy(AudioSystem::getStrategyForStream((audio_stream_type_t)track->type())); chain->incTrackCnt(); } + + // invalidate track immediately if the stream type was moved to another thread since + // createTrack() was called by the client process. + if (!mStreamTypes[streamType].valid) { + LOGW("createTrack_l() on thread %p: invalidating track on stream %d", + this, streamType); + android_atomic_or(CBLK_INVALID_ON, &track->mCblk->flags); + } } lStatus = NO_ERROR; @@ -2219,6 +2228,14 @@ void AudioFlinger::MixerThread::invalidateTracks(int streamType) } } +void AudioFlinger::PlaybackThread::setStreamValid(int streamType, bool valid) +{ + LOGV ("PlaybackThread::setStreamValid() thread %p, streamType %d, valid %d", + this, streamType, valid); + Mutex::Autolock _l(mLock); + + mStreamTypes[streamType].valid = valid; +} // getTrackName_l() must be called with ThreadBase::mLock held int AudioFlinger::MixerThread::getTrackName_l() @@ -5074,11 +5091,14 @@ status_t AudioFlinger::setStreamOutput(uint32_t stream, int output) LOGV("setStreamOutput() stream %d to output %d", stream, output); audioConfigChanged_l(AudioSystem::STREAM_CONFIG_CHANGED, output, &stream); + dstThread->setStreamValid(stream, true); + for (size_t i = 0; i < mPlaybackThreads.size(); i++) { PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); if (thread != dstThread && thread->type() != ThreadBase::DIRECT) { MixerThread *srcThread = (MixerThread *)thread; + srcThread->setStreamValid(stream, false); srcThread->invalidateTracks(stream); } } diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h index 1141f6c..c64fd4f 100644 --- a/services/audioflinger/AudioFlinger.h +++ b/services/audioflinger/AudioFlinger.h @@ -751,14 +751,18 @@ private: virtual uint32_t hasAudioSession(int sessionId); virtual uint32_t getStrategyForSession_l(int sessionId); + void setStreamValid(int streamType, bool valid); + struct stream_type_t { stream_type_t() : volume(1.0f), - mute(false) + mute(false), + valid(true) { } float volume; bool mute; + bool valid; }; protected: |