Audio V4: Propagate track attributes to HAL
This patch does not propagate the volume.
Bug: 38184704
Bug: 69623109
Test: log metadata in HAL
Change-Id: I313563cafd9f2b29a13839c3c075beb65a170632
Signed-off-by: Kevin Rocard <krocard@google.com>
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 58fb83a..b5b50f8 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -57,6 +57,7 @@
#include <powermanager/PowerManager.h>
#include <media/audiohal/EffectsFactoryHalInterface.h>
+#include <media/audiohal/StreamHalInterface.h>
#include "AudioFlinger.h"
#include "FastMixer.h"
@@ -1554,6 +1555,7 @@
mActiveTracksGeneration++;
mLatestActiveTrack = track;
++mBatteryCounter[track->uid()].second;
+ mHasChanged = true;
return mActiveTracks.add(track);
}
@@ -1568,6 +1570,7 @@
mActiveTracksGeneration++;
--mBatteryCounter[track->uid()].second;
// mLatestActiveTrack is not cleared even if is the same as track.
+ mHasChanged = true;
return index;
}
@@ -1578,6 +1581,7 @@
logTrack("clear", track);
}
mLastActiveTracksGeneration = mActiveTracksGeneration;
+ if (!mActiveTracks.empty()) { mHasChanged = true; }
mActiveTracks.clear();
mLatestActiveTrack.clear();
mBatteryCounter.clear();
@@ -1615,6 +1619,13 @@
}
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 {
if (mLocalLog != nullptr) {
@@ -2610,6 +2621,24 @@
}
}
+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)
{
@@ -3307,6 +3336,8 @@
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
@@ -6118,6 +6149,17 @@
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;
@@ -6445,6 +6487,8 @@
mActiveTracks.updatePowerState(this);
+ updateMetadata_l();
+
if (allStopped) {
standbyIfNotAlreadyInStandby();
}
@@ -7135,6 +7179,23 @@
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)
{
@@ -8099,6 +8160,8 @@
mActiveTracks.updatePowerState(this);
+ updateMetadata_l();
+
lockEffectChains_l(effectChains);
for (size_t i = 0; i < effectChains.size(); i ++) {
effectChains[i]->process_l();
@@ -8646,6 +8709,24 @@
}
}
+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) {
@@ -8690,4 +8771,22 @@
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
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 3c06acd..bb81224 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -425,6 +425,9 @@
// 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() { }
@@ -563,6 +566,10 @@
// 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;
@@ -581,6 +588,8 @@
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;
@@ -918,6 +927,7 @@
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);
@@ -1276,6 +1286,8 @@
void addOutputTrack(MixerThread* thread);
void removeOutputTrack(MixerThread* thread);
uint32_t waitTimeMs() const { return mWaitTimeMs; }
+
+ void updateMetadata_l() override;
protected:
virtual uint32_t activeSleepTimeUs() const;
@@ -1463,6 +1475,8 @@
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();
@@ -1660,6 +1674,8 @@
virtual bool isOutput() const override { return true; }
+ void updateMetadata_l() override;
+
protected:
audio_stream_type_t mStreamType;
@@ -1686,6 +1702,8 @@
virtual bool isOutput() const override { return false; }
+ void updateMetadata_l() override;
+
protected:
AudioStreamIn* mInput;
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index ad109f0..ccfb69f 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -98,6 +98,7 @@
virtual void invalidate() { mIsInvalid = true; }
bool isInvalid() const { return mIsInvalid; }
+ audio_attributes_t attributes() const { return mAttr; }
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);