Loading services/audioflinger/AudioFlinger.h +0 −3 Original line number Diff line number Diff line Loading @@ -19,11 +19,8 @@ #define ANDROID_AUDIO_FLINGER_H #include "Configuration.h" #include <atomic> #include <mutex> #include <deque> #include <map> #include <vector> #include <stdint.h> #include <sys/types.h> #include <limits.h> Loading services/audioflinger/PlaybackTracks.h +1 −40 Original line number Diff line number Diff line Loading @@ -93,23 +93,6 @@ public: const sp<media::VolumeShaper::Operation>& operation); sp<media::VolumeShaper::State> getVolumeShaperState(int id); sp<media::VolumeHandler> getVolumeHandler() { return mVolumeHandler; } /** Set the computed normalized final volume of the track. * !masterMute * masterVolume * streamVolume * averageLRVolume */ void setFinalVolume(float volume); float getFinalVolume() const { return mFinalVolume; } /** @return true if the track has changed (metadata or volume) since * the last time this function was called, * true if this function was never called since the track creation, * false otherwise. * Thread safe. */ bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); } using SourceMetadatas = std::vector<playback_track_metadata_t>; using MetadataInserter = std::back_insert_iterator<SourceMetadatas>; /** Copy the track metadata in the provided iterator. Thread safe. */ virtual void copyMetadataTo(MetadataInserter& backInserter) const; protected: // for numerous Loading Loading @@ -150,8 +133,6 @@ protected: bool presentationComplete(int64_t framesWritten, size_t audioHalFrames); void signalClientFlag(int32_t flag); /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */ void setMetadataHasChanged() { mChangeNotified.clear(); } public: void triggerEvents(AudioSystem::sync_event_t type); virtual void invalidate(); Loading Loading @@ -201,13 +182,10 @@ private: volatile float mCachedVolume; // combined master volume and stream type volume; // 'volatile' means accessed without lock or // barrier, but is read/written atomically float mFinalVolume; // combine master volume, stream type volume and track volume sp<AudioTrackServerProxy> mAudioTrackServerProxy; bool mResumeToStopping; // track was paused in stopping state. bool mFlushHwPending; // track requests for thread flush audio_output_flags_t mFlags; // If the last track change was notified to the client with readAndClearHasChanged std::atomic_flag mChangeNotified = ATOMIC_FLAG_INIT; }; // end of Track Loading Loading @@ -238,11 +216,8 @@ public: bool isActive() const { return mActive; } const wp<ThreadBase>& thread() const { return mThread; } void copyMetadataTo(MetadataInserter& backInserter) const override; /** Set the metadatas of the upstream tracks. Thread safe. */ void setMetadatas(const SourceMetadatas& metadatas); private: status_t obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs); void clearBufferQueue(); Loading @@ -257,20 +232,6 @@ private: bool mActive; DuplicatingThread* const mSourceThread; // for waitTimeMs() in write() sp<AudioTrackClientProxy> mClientProxy; /** Attributes of the source tracks. * * This member must be accessed with mTrackMetadatasMutex taken. * There is one writer (duplicating thread) and one reader (downstream mixer). * * That means that the duplicating thread can block the downstream mixer * thread and vice versa for the time of the copy. * If this becomes an issue, the metadata could be stored in an atomic raw pointer, * and a exchange with nullptr and delete can be used. * Alternatively a read-copy-update might be implemented. */ SourceMetadatas mTrackMetadatas; /** Protects mTrackMetadatas against concurrent access. */ mutable std::mutex mTrackMetadatasMutex; }; // end of OutputTrack // playback track, used by PatchPanel Loading services/audioflinger/Threads.cpp +23 −36 Original line number Diff line number Diff line Loading @@ -2623,32 +2623,26 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l() void AudioFlinger::PlaybackThread::updateMetadata_l() { if (mOutput == nullptr || mOutput->stream == nullptr ) { return; // That should not happen } bool hasChanged = mActiveTracks.readAndClearHasChanged(); for (const sp<Track> &track : mActiveTracks) { // Do not short-circuit as all hasChanged states must be reset // as all the metadata are going to be sent hasChanged |= track->readAndClearHasChanged(); } if (!hasChanged) { return; // nothing to do // TODO: add volume support if (mOutput == nullptr || mOutput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamOutHalInterface::SourceMetadata metadata; auto backInserter = std::back_inserter(metadata.tracks); for (const sp<Track> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section track->copyMetadataTo(backInserter); if (track->isOutputTrack()) { // TODO: OutputTrack (used for duplication) are currently not supported continue; } sendMetadataToBackend_l(metadata); metadata.tracks.push_back({ .usage = track->attributes().usage, .content_type = track->attributes().content_type, .gain = 1, }); } void AudioFlinger::PlaybackThread::sendMetadataToBackend_l( const StreamOutHalInterface::SourceMetadata& metadata) { mOutput->stream->updateSourceMetadata(metadata); }; } status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames) { Loading Loading @@ -4387,19 +4381,13 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac didModify = true; // no acknowledgement required for newly active tracks } sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy; // cache the combined master volume and stream type volume for fast mixer; this // lacks any synchronization or barrier so VolumeProvider may read a stale value const float vh = track->getVolumeHandler()->getVolume( proxy->framesReleased()).first; float volume = masterVolume track->mAudioTrackServerProxy->framesReleased()).first; track->mCachedVolume = masterVolume * mStreamTypes[track->streamType()].volume * vh; track->mCachedVolume = masterVolume; gain_minifloat_packed_t vlr = proxy->getVolumeLR(); float vlf = volume * float_from_gain(gain_minifloat_unpack_left(vlr)); float vrf = volume * float_from_gain(gain_minifloat_unpack_right(vlr)); track->setFinalVolume((vlf + vrf) / 2.f); ++fastTracks; } else { // was it previously active? Loading Loading @@ -4576,8 +4564,6 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac vaf = v * sendLevel * (1. / MAX_GAIN_INT); } track->setFinalVolume((vrf + vlf) / 2.f); // Delegate volume control to effect in track effect chain if needed if (chain != 0 && chain->setVolume_l(&vl, &vr)) { // Do not ramp volume if volume is controlled by effect Loading Loading @@ -5122,7 +5108,6 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr } if (lastTrack) { track->setFinalVolume((left + right) / 2.f); if (left != mLeftVolFloat || right != mRightVolFloat) { mLeftVolFloat = left; mRightVolFloat = right; Loading Loading @@ -6180,12 +6165,14 @@ bool AudioFlinger::DuplicatingThread::outputsReady( return true; } void AudioFlinger::DuplicatingThread::sendMetadataToBackend_l( const StreamOutHalInterface::SourceMetadata& metadata) void AudioFlinger::DuplicatingThread::updateMetadata_l() { for (auto& outputTrack : outputTracks) { // not mOutputTracks outputTrack->setMetadatas(metadata.tracks); } // TODO: The duplicated track metadata needs to be pushed to downstream // but this information can be read at any time by the downstream threads. // Taking the lock of any downstream threads is no possible due to cross deadlock risks // (eg: during effect move). // A lock-free structure needs to be used to shared the metadata, probably an atomic // pointer to a metadata vector in each output tracks. } uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const Loading services/audioflinger/Threads.h +5 −7 Original line number Diff line number Diff line Loading @@ -566,8 +566,8 @@ protected: // periodically called in the threadLoop() to update power state uids. void updatePowerState(sp<ThreadBase> thread, bool force = false); /** @return true if one or move active tracks was added or removed since the * last time this function was called or the vector was created. */ /** @return true if the active tracks have changed since the last time * this function was called or the vector was created. */ bool readAndClearHasChanged(); private: Loading @@ -588,7 +588,7 @@ protected: int mLastActiveTracksGeneration; wp<T> mLatestActiveTrack; // latest track added to ActiveTracks SimpleLog * const mLocalLog; // If the vector has changed since last call to readAndClearHasChanged // If the active tracks have changed since last call to readAndClearHasChanged bool mHasChanged = false; }; Loading Loading @@ -927,8 +927,7 @@ private: void removeTrack_l(const sp<Track>& track); void readOutputParameters_l(); void updateMetadata_l() final; virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata); void updateMetadata_l() override; virtual void dumpInternals(int fd, const Vector<String16>& args); void dumpTracks(int fd, const Vector<String16>& args); Loading Loading @@ -1288,8 +1287,7 @@ public: void removeOutputTrack(MixerThread* thread); uint32_t waitTimeMs() const { return mWaitTimeMs; } void sendMetadataToBackend_l( const StreamOutHalInterface::SourceMetadata& metadata) override; void updateMetadata_l() override; protected: virtual uint32_t activeSleepTimeUs() const; Loading services/audioflinger/Tracks.cpp +0 −35 Original line number Diff line number Diff line Loading @@ -407,9 +407,6 @@ AudioFlinger::PlaybackThread::Track::Track( // mSinkTimestamp mFastIndex(-1), mCachedVolume(1.0), /* The track might not play immediately after being active, similarly as if its volume was 0. * When the track starts playing, its volume will be computed. */ mFinalVolume(0.f), mResumeToStopping(false), mFlushHwPending(false), mFlags(flags) Loading Loading @@ -1000,23 +997,6 @@ sp<VolumeShaper::State> AudioFlinger::PlaybackThread::Track::getVolumeShaperStat return mVolumeHandler->getVolumeShaperState(id); } void AudioFlinger::PlaybackThread::Track::setFinalVolume(float volume) { if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates mFinalVolume = volume; setMetadataHasChanged(); } } void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const { *backInserter++ = { .usage = mAttr.usage, .content_type = mAttr.content_type, .gain = mFinalVolume, }; } status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp) { if (!isOffloaded() && !isDirect()) { Loading Loading @@ -1447,21 +1427,6 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame return outputBufferFull; } void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const { std::lock_guard<std::mutex> lock(mTrackMetadatasMutex); backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter); } void AudioFlinger::PlaybackThread::OutputTrack::setMetadatas(const SourceMetadatas& metadatas) { { std::lock_guard<std::mutex> lock(mTrackMetadatasMutex); mTrackMetadatas = metadatas; } // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS. setMetadataHasChanged(); } status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs) { Loading Loading
services/audioflinger/AudioFlinger.h +0 −3 Original line number Diff line number Diff line Loading @@ -19,11 +19,8 @@ #define ANDROID_AUDIO_FLINGER_H #include "Configuration.h" #include <atomic> #include <mutex> #include <deque> #include <map> #include <vector> #include <stdint.h> #include <sys/types.h> #include <limits.h> Loading
services/audioflinger/PlaybackTracks.h +1 −40 Original line number Diff line number Diff line Loading @@ -93,23 +93,6 @@ public: const sp<media::VolumeShaper::Operation>& operation); sp<media::VolumeShaper::State> getVolumeShaperState(int id); sp<media::VolumeHandler> getVolumeHandler() { return mVolumeHandler; } /** Set the computed normalized final volume of the track. * !masterMute * masterVolume * streamVolume * averageLRVolume */ void setFinalVolume(float volume); float getFinalVolume() const { return mFinalVolume; } /** @return true if the track has changed (metadata or volume) since * the last time this function was called, * true if this function was never called since the track creation, * false otherwise. * Thread safe. */ bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); } using SourceMetadatas = std::vector<playback_track_metadata_t>; using MetadataInserter = std::back_insert_iterator<SourceMetadatas>; /** Copy the track metadata in the provided iterator. Thread safe. */ virtual void copyMetadataTo(MetadataInserter& backInserter) const; protected: // for numerous Loading Loading @@ -150,8 +133,6 @@ protected: bool presentationComplete(int64_t framesWritten, size_t audioHalFrames); void signalClientFlag(int32_t flag); /** Set that a metadata has changed and needs to be notified to backend. Thread safe. */ void setMetadataHasChanged() { mChangeNotified.clear(); } public: void triggerEvents(AudioSystem::sync_event_t type); virtual void invalidate(); Loading Loading @@ -201,13 +182,10 @@ private: volatile float mCachedVolume; // combined master volume and stream type volume; // 'volatile' means accessed without lock or // barrier, but is read/written atomically float mFinalVolume; // combine master volume, stream type volume and track volume sp<AudioTrackServerProxy> mAudioTrackServerProxy; bool mResumeToStopping; // track was paused in stopping state. bool mFlushHwPending; // track requests for thread flush audio_output_flags_t mFlags; // If the last track change was notified to the client with readAndClearHasChanged std::atomic_flag mChangeNotified = ATOMIC_FLAG_INIT; }; // end of Track Loading Loading @@ -238,11 +216,8 @@ public: bool isActive() const { return mActive; } const wp<ThreadBase>& thread() const { return mThread; } void copyMetadataTo(MetadataInserter& backInserter) const override; /** Set the metadatas of the upstream tracks. Thread safe. */ void setMetadatas(const SourceMetadatas& metadatas); private: status_t obtainBuffer(AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs); void clearBufferQueue(); Loading @@ -257,20 +232,6 @@ private: bool mActive; DuplicatingThread* const mSourceThread; // for waitTimeMs() in write() sp<AudioTrackClientProxy> mClientProxy; /** Attributes of the source tracks. * * This member must be accessed with mTrackMetadatasMutex taken. * There is one writer (duplicating thread) and one reader (downstream mixer). * * That means that the duplicating thread can block the downstream mixer * thread and vice versa for the time of the copy. * If this becomes an issue, the metadata could be stored in an atomic raw pointer, * and a exchange with nullptr and delete can be used. * Alternatively a read-copy-update might be implemented. */ SourceMetadatas mTrackMetadatas; /** Protects mTrackMetadatas against concurrent access. */ mutable std::mutex mTrackMetadatasMutex; }; // end of OutputTrack // playback track, used by PatchPanel Loading
services/audioflinger/Threads.cpp +23 −36 Original line number Diff line number Diff line Loading @@ -2623,32 +2623,26 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l() void AudioFlinger::PlaybackThread::updateMetadata_l() { if (mOutput == nullptr || mOutput->stream == nullptr ) { return; // That should not happen } bool hasChanged = mActiveTracks.readAndClearHasChanged(); for (const sp<Track> &track : mActiveTracks) { // Do not short-circuit as all hasChanged states must be reset // as all the metadata are going to be sent hasChanged |= track->readAndClearHasChanged(); } if (!hasChanged) { return; // nothing to do // TODO: add volume support if (mOutput == nullptr || mOutput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamOutHalInterface::SourceMetadata metadata; auto backInserter = std::back_inserter(metadata.tracks); for (const sp<Track> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section track->copyMetadataTo(backInserter); if (track->isOutputTrack()) { // TODO: OutputTrack (used for duplication) are currently not supported continue; } sendMetadataToBackend_l(metadata); metadata.tracks.push_back({ .usage = track->attributes().usage, .content_type = track->attributes().content_type, .gain = 1, }); } void AudioFlinger::PlaybackThread::sendMetadataToBackend_l( const StreamOutHalInterface::SourceMetadata& metadata) { mOutput->stream->updateSourceMetadata(metadata); }; } status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames) { Loading Loading @@ -4387,19 +4381,13 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac didModify = true; // no acknowledgement required for newly active tracks } sp<AudioTrackServerProxy> proxy = track->mAudioTrackServerProxy; // cache the combined master volume and stream type volume for fast mixer; this // lacks any synchronization or barrier so VolumeProvider may read a stale value const float vh = track->getVolumeHandler()->getVolume( proxy->framesReleased()).first; float volume = masterVolume track->mAudioTrackServerProxy->framesReleased()).first; track->mCachedVolume = masterVolume * mStreamTypes[track->streamType()].volume * vh; track->mCachedVolume = masterVolume; gain_minifloat_packed_t vlr = proxy->getVolumeLR(); float vlf = volume * float_from_gain(gain_minifloat_unpack_left(vlr)); float vrf = volume * float_from_gain(gain_minifloat_unpack_right(vlr)); track->setFinalVolume((vlf + vrf) / 2.f); ++fastTracks; } else { // was it previously active? Loading Loading @@ -4576,8 +4564,6 @@ AudioFlinger::PlaybackThread::mixer_state AudioFlinger::MixerThread::prepareTrac vaf = v * sendLevel * (1. / MAX_GAIN_INT); } track->setFinalVolume((vrf + vlf) / 2.f); // Delegate volume control to effect in track effect chain if needed if (chain != 0 && chain->setVolume_l(&vl, &vr)) { // Do not ramp volume if volume is controlled by effect Loading Loading @@ -5122,7 +5108,6 @@ void AudioFlinger::DirectOutputThread::processVolume_l(Track *track, bool lastTr } if (lastTrack) { track->setFinalVolume((left + right) / 2.f); if (left != mLeftVolFloat || right != mRightVolFloat) { mLeftVolFloat = left; mRightVolFloat = right; Loading Loading @@ -6180,12 +6165,14 @@ bool AudioFlinger::DuplicatingThread::outputsReady( return true; } void AudioFlinger::DuplicatingThread::sendMetadataToBackend_l( const StreamOutHalInterface::SourceMetadata& metadata) void AudioFlinger::DuplicatingThread::updateMetadata_l() { for (auto& outputTrack : outputTracks) { // not mOutputTracks outputTrack->setMetadatas(metadata.tracks); } // TODO: The duplicated track metadata needs to be pushed to downstream // but this information can be read at any time by the downstream threads. // Taking the lock of any downstream threads is no possible due to cross deadlock risks // (eg: during effect move). // A lock-free structure needs to be used to shared the metadata, probably an atomic // pointer to a metadata vector in each output tracks. } uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const Loading
services/audioflinger/Threads.h +5 −7 Original line number Diff line number Diff line Loading @@ -566,8 +566,8 @@ protected: // periodically called in the threadLoop() to update power state uids. void updatePowerState(sp<ThreadBase> thread, bool force = false); /** @return true if one or move active tracks was added or removed since the * last time this function was called or the vector was created. */ /** @return true if the active tracks have changed since the last time * this function was called or the vector was created. */ bool readAndClearHasChanged(); private: Loading @@ -588,7 +588,7 @@ protected: int mLastActiveTracksGeneration; wp<T> mLatestActiveTrack; // latest track added to ActiveTracks SimpleLog * const mLocalLog; // If the vector has changed since last call to readAndClearHasChanged // If the active tracks have changed since last call to readAndClearHasChanged bool mHasChanged = false; }; Loading Loading @@ -927,8 +927,7 @@ private: void removeTrack_l(const sp<Track>& track); void readOutputParameters_l(); void updateMetadata_l() final; virtual void sendMetadataToBackend_l(const StreamOutHalInterface::SourceMetadata& metadata); void updateMetadata_l() override; virtual void dumpInternals(int fd, const Vector<String16>& args); void dumpTracks(int fd, const Vector<String16>& args); Loading Loading @@ -1288,8 +1287,7 @@ public: void removeOutputTrack(MixerThread* thread); uint32_t waitTimeMs() const { return mWaitTimeMs; } void sendMetadataToBackend_l( const StreamOutHalInterface::SourceMetadata& metadata) override; void updateMetadata_l() override; protected: virtual uint32_t activeSleepTimeUs() const; Loading
services/audioflinger/Tracks.cpp +0 −35 Original line number Diff line number Diff line Loading @@ -407,9 +407,6 @@ AudioFlinger::PlaybackThread::Track::Track( // mSinkTimestamp mFastIndex(-1), mCachedVolume(1.0), /* The track might not play immediately after being active, similarly as if its volume was 0. * When the track starts playing, its volume will be computed. */ mFinalVolume(0.f), mResumeToStopping(false), mFlushHwPending(false), mFlags(flags) Loading Loading @@ -1000,23 +997,6 @@ sp<VolumeShaper::State> AudioFlinger::PlaybackThread::Track::getVolumeShaperStat return mVolumeHandler->getVolumeShaperState(id); } void AudioFlinger::PlaybackThread::Track::setFinalVolume(float volume) { if (mFinalVolume != volume) { // Compare to an epsilon if too many meaningless updates mFinalVolume = volume; setMetadataHasChanged(); } } void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const { *backInserter++ = { .usage = mAttr.usage, .content_type = mAttr.content_type, .gain = mFinalVolume, }; } status_t AudioFlinger::PlaybackThread::Track::getTimestamp(AudioTimestamp& timestamp) { if (!isOffloaded() && !isDirect()) { Loading Loading @@ -1447,21 +1427,6 @@ bool AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t frame return outputBufferFull; } void AudioFlinger::PlaybackThread::OutputTrack::copyMetadataTo(MetadataInserter& backInserter) const { std::lock_guard<std::mutex> lock(mTrackMetadatasMutex); backInserter = std::copy(mTrackMetadatas.begin(), mTrackMetadatas.end(), backInserter); } void AudioFlinger::PlaybackThread::OutputTrack::setMetadatas(const SourceMetadatas& metadatas) { { std::lock_guard<std::mutex> lock(mTrackMetadatasMutex); mTrackMetadatas = metadatas; } // No need to adjust metadata track volumes as OutputTrack volumes are always 0dBFS. setMetadataHasChanged(); } status_t AudioFlinger::PlaybackThread::OutputTrack::obtainBuffer( AudioBufferProvider::Buffer* buffer, uint32_t waitTimeMs) { Loading