summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/AudioSystem.h7
-rw-r--r--media/libmedia/AudioSystem.cpp8
-rw-r--r--media/libmedia/AudioTrack.cpp4
-rw-r--r--services/audioflinger/AudioFlinger.cpp20
-rw-r--r--services/audioflinger/AudioFlinger.h6
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: