Loading services/audioflinger/Threads.cpp +99 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ #include <powermanager/PowerManager.h> #include <media/audiohal/EffectsFactoryHalInterface.h> #include <media/audiohal/StreamHalInterface.h> #include "AudioFlinger.h" #include "FastMixer.h" Loading Loading @@ -1554,6 +1555,7 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) { mActiveTracksGeneration++; mLatestActiveTrack = track; ++mBatteryCounter[track->uid()].second; mHasChanged = true; return mActiveTracks.add(track); } Loading @@ -1568,6 +1570,7 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) { mActiveTracksGeneration++; --mBatteryCounter[track->uid()].second; // mLatestActiveTrack is not cleared even if is the same as track. mHasChanged = true; return index; } Loading @@ -1578,6 +1581,7 @@ void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() { logTrack("clear", track); } mLastActiveTracksGeneration = mActiveTracksGeneration; if (!mActiveTracks.empty()) { mHasChanged = true; } mActiveTracks.clear(); mLatestActiveTrack.clear(); mBatteryCounter.clear(); Loading Loading @@ -1614,6 +1618,13 @@ void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState( } } template <typename T> bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() { const bool hasChanged = mHasChanged; mHasChanged = false; return hasChanged; } template <typename T> void AudioFlinger::ThreadBase::ActiveTracks<T>::logTrack( const char *funcName, const sp<T> &track) const { Loading Loading @@ -2610,6 +2621,24 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l() } } void AudioFlinger::PlaybackThread::updateMetadata_l() { // TODO: add volume support if (mOutput == nullptr || mOutput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamOutHalInterface::SourceMetadata metadata; for (const sp<Track> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section metadata.tracks.push_back({ .usage = track->attributes().usage, .content_type = track->attributes().content_type, .gain = 1, }); } mOutput->stream->updateSourceMetadata(metadata); } status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames) { Loading Loading @@ -3307,6 +3336,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() mActiveTracks.updatePowerState(this); updateMetadata_l(); // prevent any changes in effect chain list and in each effect chain // during mixing and effect process as the audio buffers could be deleted // or modified if an effect is created or deleted Loading Loading @@ -6118,6 +6149,17 @@ bool AudioFlinger::DuplicatingThread::outputsReady( return true; } void AudioFlinger::DuplicatingThread::updateMetadata_l() { // TODO: The duplicated track metadata are stored in other threads // (accessible through mActiveTracks::OutputTrack::thread()::mActiveTracks::Track::attributes()) // but this information can be mutated at any time by the owning threads. // Taking the lock of any other owning threads is no possible due to timing constrains. // Similarly, the other threads can not push the metadatas in this thread as cross deadlock // would be possible. // A lock-free structure needs to be used to shared the metadata (maybe an atomic shared_ptr ?). } uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const { return (mWaitTimeMs * 1000) / 2; Loading Loading @@ -6445,6 +6487,8 @@ reacquire_wakelock: mActiveTracks.updatePowerState(this); updateMetadata_l(); if (allStopped) { standbyIfNotAlreadyInStandby(); } Loading Loading @@ -7135,6 +7179,23 @@ status_t AudioFlinger::RecordThread::getActiveMicrophones( return status; } void AudioFlinger::RecordThread::updateMetadata_l() { if (mInput == nullptr || mInput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamInHalInterface::SinkMetadata metadata; for (const sp<RecordTrack> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section metadata.tracks.push_back({ .source = track->attributes().source, .gain = 1, // capture tracks do not have volumes }); } mInput->stream->updateSinkMetadata(metadata); } // destroyTrack_l() must be called with ThreadBase::mLock held void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track) { Loading Loading @@ -8099,6 +8160,8 @@ bool AudioFlinger::MmapThread::threadLoop() mActiveTracks.updatePowerState(this); updateMetadata_l(); lockEffectChains_l(effectChains); for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); Loading Loading @@ -8646,6 +8709,24 @@ void AudioFlinger::MmapPlaybackThread::processVolume_l() } } void AudioFlinger::MmapPlaybackThread::updateMetadata_l() { if (mOutput == nullptr || mOutput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamOutHalInterface::SourceMetadata metadata; for (const sp<MmapTrack> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section metadata.tracks.push_back({ .usage = track->attributes().usage, .content_type = track->attributes().content_type, .gain = mHalVolFloat, // TODO: propagate from aaudio pre-mix volume }); } mOutput->stream->updateSourceMetadata(metadata); } void AudioFlinger::MmapPlaybackThread::checkSilentMode_l() { if (!mMasterMute) { Loading Loading @@ -8690,4 +8771,22 @@ AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput() mInput = NULL; return input; } void AudioFlinger::MmapCaptureThread::updateMetadata_l() { if (mInput == nullptr || mInput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamInHalInterface::SinkMetadata metadata; for (const sp<MmapTrack> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section metadata.tracks.push_back({ .source = track->attributes().source, .gain = 1, // capture tracks do not have volumes }); } mInput->stream->updateSinkMetadata(metadata); } } // namespace android services/audioflinger/Threads.h +18 −0 Original line number Diff line number Diff line Loading @@ -425,6 +425,9 @@ protected: // check if some effects must be suspended when an effect chain is added void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain); // sends the metadata of the active tracks to the HAL virtual void updateMetadata_l() = 0; String16 getWakeLockTag(); virtual void preExit() { } Loading Loading @@ -563,6 +566,10 @@ protected: // periodically called in the threadLoop() to update power state uids. void updatePowerState(sp<ThreadBase> thread, bool force = false); /** @return true if the active tracks have changed since the last time * this function was called or the vector was created. */ bool readAndClearHasChanged(); private: void logTrack(const char *funcName, const sp<T> &track) const; Loading @@ -581,6 +588,8 @@ protected: int mLastActiveTracksGeneration; wp<T> mLatestActiveTrack; // latest track added to ActiveTracks SimpleLog * const mLocalLog; // If the active tracks have changed since last call to readAndClearHasChanged bool mHasChanged = false; }; SimpleLog mLocalLog; Loading Loading @@ -918,6 +927,7 @@ private: void removeTrack_l(const sp<Track>& track); void readOutputParameters_l(); void updateMetadata_l() override; virtual void dumpInternals(int fd, const Vector<String16>& args); void dumpTracks(int fd, const Vector<String16>& args); Loading Loading @@ -1276,6 +1286,8 @@ public: void addOutputTrack(MixerThread* thread); void removeOutputTrack(MixerThread* thread); uint32_t waitTimeMs() const { return mWaitTimeMs; } void updateMetadata_l() override; protected: virtual uint32_t activeSleepTimeUs() const; Loading Loading @@ -1463,6 +1475,8 @@ public: status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones); void updateMetadata_l() override; private: // Enter standby if not already in standby, and set mStandby flag void standbyIfNotAlreadyInStandby(); Loading Loading @@ -1660,6 +1674,8 @@ public: virtual bool isOutput() const override { return true; } void updateMetadata_l() override; protected: audio_stream_type_t mStreamType; Loading @@ -1686,6 +1702,8 @@ public: virtual bool isOutput() const override { return false; } void updateMetadata_l() override; protected: AudioStreamIn* mInput; Loading services/audioflinger/TrackBase.h +1 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ public: virtual void invalidate() { mIsInvalid = true; } bool isInvalid() const { return mIsInvalid; } audio_attributes_t attributes() const { return mAttr; } protected: DISALLOW_COPY_AND_ASSIGN(TrackBase); Loading Loading
services/audioflinger/Threads.cpp +99 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ #include <powermanager/PowerManager.h> #include <media/audiohal/EffectsFactoryHalInterface.h> #include <media/audiohal/StreamHalInterface.h> #include "AudioFlinger.h" #include "FastMixer.h" Loading Loading @@ -1554,6 +1555,7 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) { mActiveTracksGeneration++; mLatestActiveTrack = track; ++mBatteryCounter[track->uid()].second; mHasChanged = true; return mActiveTracks.add(track); } Loading @@ -1568,6 +1570,7 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::remove(const sp<T> &track) { mActiveTracksGeneration++; --mBatteryCounter[track->uid()].second; // mLatestActiveTrack is not cleared even if is the same as track. mHasChanged = true; return index; } Loading @@ -1578,6 +1581,7 @@ void AudioFlinger::ThreadBase::ActiveTracks<T>::clear() { logTrack("clear", track); } mLastActiveTracksGeneration = mActiveTracksGeneration; if (!mActiveTracks.empty()) { mHasChanged = true; } mActiveTracks.clear(); mLatestActiveTrack.clear(); mBatteryCounter.clear(); Loading Loading @@ -1614,6 +1618,13 @@ void AudioFlinger::ThreadBase::ActiveTracks<T>::updatePowerState( } } template <typename T> bool AudioFlinger::ThreadBase::ActiveTracks<T>::readAndClearHasChanged() { const bool hasChanged = mHasChanged; mHasChanged = false; return hasChanged; } template <typename T> void AudioFlinger::ThreadBase::ActiveTracks<T>::logTrack( const char *funcName, const sp<T> &track) const { Loading Loading @@ -2610,6 +2621,24 @@ void AudioFlinger::PlaybackThread::readOutputParameters_l() } } void AudioFlinger::PlaybackThread::updateMetadata_l() { // TODO: add volume support if (mOutput == nullptr || mOutput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamOutHalInterface::SourceMetadata metadata; for (const sp<Track> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section metadata.tracks.push_back({ .usage = track->attributes().usage, .content_type = track->attributes().content_type, .gain = 1, }); } mOutput->stream->updateSourceMetadata(metadata); } status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, uint32_t *dspFrames) { Loading Loading @@ -3307,6 +3336,8 @@ bool AudioFlinger::PlaybackThread::threadLoop() mActiveTracks.updatePowerState(this); updateMetadata_l(); // prevent any changes in effect chain list and in each effect chain // during mixing and effect process as the audio buffers could be deleted // or modified if an effect is created or deleted Loading Loading @@ -6118,6 +6149,17 @@ bool AudioFlinger::DuplicatingThread::outputsReady( return true; } void AudioFlinger::DuplicatingThread::updateMetadata_l() { // TODO: The duplicated track metadata are stored in other threads // (accessible through mActiveTracks::OutputTrack::thread()::mActiveTracks::Track::attributes()) // but this information can be mutated at any time by the owning threads. // Taking the lock of any other owning threads is no possible due to timing constrains. // Similarly, the other threads can not push the metadatas in this thread as cross deadlock // would be possible. // A lock-free structure needs to be used to shared the metadata (maybe an atomic shared_ptr ?). } uint32_t AudioFlinger::DuplicatingThread::activeSleepTimeUs() const { return (mWaitTimeMs * 1000) / 2; Loading Loading @@ -6445,6 +6487,8 @@ reacquire_wakelock: mActiveTracks.updatePowerState(this); updateMetadata_l(); if (allStopped) { standbyIfNotAlreadyInStandby(); } Loading Loading @@ -7135,6 +7179,23 @@ status_t AudioFlinger::RecordThread::getActiveMicrophones( return status; } void AudioFlinger::RecordThread::updateMetadata_l() { if (mInput == nullptr || mInput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamInHalInterface::SinkMetadata metadata; for (const sp<RecordTrack> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section metadata.tracks.push_back({ .source = track->attributes().source, .gain = 1, // capture tracks do not have volumes }); } mInput->stream->updateSinkMetadata(metadata); } // destroyTrack_l() must be called with ThreadBase::mLock held void AudioFlinger::RecordThread::destroyTrack_l(const sp<RecordTrack>& track) { Loading Loading @@ -8099,6 +8160,8 @@ bool AudioFlinger::MmapThread::threadLoop() mActiveTracks.updatePowerState(this); updateMetadata_l(); lockEffectChains_l(effectChains); for (size_t i = 0; i < effectChains.size(); i ++) { effectChains[i]->process_l(); Loading Loading @@ -8646,6 +8709,24 @@ void AudioFlinger::MmapPlaybackThread::processVolume_l() } } void AudioFlinger::MmapPlaybackThread::updateMetadata_l() { if (mOutput == nullptr || mOutput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamOutHalInterface::SourceMetadata metadata; for (const sp<MmapTrack> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section metadata.tracks.push_back({ .usage = track->attributes().usage, .content_type = track->attributes().content_type, .gain = mHalVolFloat, // TODO: propagate from aaudio pre-mix volume }); } mOutput->stream->updateSourceMetadata(metadata); } void AudioFlinger::MmapPlaybackThread::checkSilentMode_l() { if (!mMasterMute) { Loading Loading @@ -8690,4 +8771,22 @@ AudioFlinger::AudioStreamIn* AudioFlinger::MmapCaptureThread::clearInput() mInput = NULL; return input; } void AudioFlinger::MmapCaptureThread::updateMetadata_l() { if (mInput == nullptr || mInput->stream == nullptr || !mActiveTracks.readAndClearHasChanged()) { return; } StreamInHalInterface::SinkMetadata metadata; for (const sp<MmapTrack> &track : mActiveTracks) { // No track is invalid as this is called after prepareTrack_l in the same critical section metadata.tracks.push_back({ .source = track->attributes().source, .gain = 1, // capture tracks do not have volumes }); } mInput->stream->updateSinkMetadata(metadata); } } // namespace android
services/audioflinger/Threads.h +18 −0 Original line number Diff line number Diff line Loading @@ -425,6 +425,9 @@ protected: // check if some effects must be suspended when an effect chain is added void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain); // sends the metadata of the active tracks to the HAL virtual void updateMetadata_l() = 0; String16 getWakeLockTag(); virtual void preExit() { } Loading Loading @@ -563,6 +566,10 @@ protected: // periodically called in the threadLoop() to update power state uids. void updatePowerState(sp<ThreadBase> thread, bool force = false); /** @return true if the active tracks have changed since the last time * this function was called or the vector was created. */ bool readAndClearHasChanged(); private: void logTrack(const char *funcName, const sp<T> &track) const; Loading @@ -581,6 +588,8 @@ protected: int mLastActiveTracksGeneration; wp<T> mLatestActiveTrack; // latest track added to ActiveTracks SimpleLog * const mLocalLog; // If the active tracks have changed since last call to readAndClearHasChanged bool mHasChanged = false; }; SimpleLog mLocalLog; Loading Loading @@ -918,6 +927,7 @@ private: void removeTrack_l(const sp<Track>& track); void readOutputParameters_l(); void updateMetadata_l() override; virtual void dumpInternals(int fd, const Vector<String16>& args); void dumpTracks(int fd, const Vector<String16>& args); Loading Loading @@ -1276,6 +1286,8 @@ public: void addOutputTrack(MixerThread* thread); void removeOutputTrack(MixerThread* thread); uint32_t waitTimeMs() const { return mWaitTimeMs; } void updateMetadata_l() override; protected: virtual uint32_t activeSleepTimeUs() const; Loading Loading @@ -1463,6 +1475,8 @@ public: status_t getActiveMicrophones(std::vector<media::MicrophoneInfo>* activeMicrophones); void updateMetadata_l() override; private: // Enter standby if not already in standby, and set mStandby flag void standbyIfNotAlreadyInStandby(); Loading Loading @@ -1660,6 +1674,8 @@ public: virtual bool isOutput() const override { return true; } void updateMetadata_l() override; protected: audio_stream_type_t mStreamType; Loading @@ -1686,6 +1702,8 @@ public: virtual bool isOutput() const override { return false; } void updateMetadata_l() override; protected: AudioStreamIn* mInput; Loading
services/audioflinger/TrackBase.h +1 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ public: virtual void invalidate() { mIsInvalid = true; } bool isInvalid() const { return mIsInvalid; } audio_attributes_t attributes() const { return mAttr; } protected: DISALLOW_COPY_AND_ASSIGN(TrackBase); Loading