Merge "audio flinger: report actual sink device for MSD playback threads"
diff --git a/media/libaudiohal/impl/DeviceHalLocal.h b/media/libaudiohal/impl/DeviceHalLocal.h
index 195204b..46b510b 100644
--- a/media/libaudiohal/impl/DeviceHalLocal.h
+++ b/media/libaudiohal/impl/DeviceHalLocal.h
@@ -117,6 +117,8 @@
void closeOutputStream(struct audio_stream_out *stream_out);
void closeInputStream(struct audio_stream_in *stream_in);
+ uint32_t version() const { return mDev->common.version; }
+
private:
audio_hw_device_t *mDev;
@@ -127,8 +129,6 @@
// The destructor automatically closes the device.
virtual ~DeviceHalLocal();
-
- uint32_t version() const { return mDev->common.version; }
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/impl/StreamHalHidl.cpp b/media/libaudiohal/impl/StreamHalHidl.cpp
index 2726e36..09a7c1c 100644
--- a/media/libaudiohal/impl/StreamHalHidl.cpp
+++ b/media/libaudiohal/impl/StreamHalHidl.cpp
@@ -25,6 +25,7 @@
#include "DeviceHalHidl.h"
#include "EffectHalHidl.h"
+#include "HidlUtils.h"
#include "StreamHalHidl.h"
#include "VersionUtils.h"
@@ -610,12 +611,25 @@
const StreamOutHalInterface::SourceMetadata& sourceMetadata) {
CPP_VERSION::SourceMetadata halMetadata = {
.tracks = transformToHidlVec(sourceMetadata.tracks,
- [](const playback_track_metadata& metadata) -> PlaybackTrackMetadata {
- return {
- .usage=static_cast<AudioUsage>(metadata.usage),
- .contentType=static_cast<AudioContentType>(metadata.content_type),
- .gain=metadata.gain,
+ [](const playback_track_metadata_v7& metadata) -> PlaybackTrackMetadata {
+ PlaybackTrackMetadata halTrackMetadata = {
+ .usage=static_cast<AudioUsage>(metadata.base.usage),
+ .contentType=static_cast<AudioContentType>(metadata.base.content_type),
+ .gain=metadata.base.gain,
};
+#if MAJOR_VERSION >= 7
+ HidlUtils::audioChannelMaskFromHal(metadata.channel_mask, false /*isInput*/,
+ &halTrackMetadata.channelMask);
+
+ std::istringstream tags{metadata.tags};
+ std::string tag;
+ while (std::getline(tags, tag, HidlUtils::sAudioTagSeparator)) {
+ if (!tag.empty()) {
+ halTrackMetadata.tags.push_back(tag);
+ }
+ }
+#endif
+ return halTrackMetadata;
})};
return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(halMetadata));
}
@@ -902,11 +916,23 @@
StreamInHalInterface::SinkMetadata& sinkMetadata) {
CPP_VERSION::SinkMetadata halMetadata = {
.tracks = transformToHidlVec(sinkMetadata.tracks,
- [](const record_track_metadata& metadata) -> RecordTrackMetadata {
- return {
- .source=static_cast<AudioSource>(metadata.source),
- .gain=metadata.gain,
+ [](const record_track_metadata_v7& metadata) -> RecordTrackMetadata {
+ RecordTrackMetadata halTrackMetadata = {
+ .source=static_cast<AudioSource>(metadata.base.source),
+ .gain=metadata.base.gain,
};
+#if MAJOR_VERSION >= 7
+ HidlUtils::audioChannelMaskFromHal(metadata.channel_mask, true /*isInput*/,
+ &halTrackMetadata.channelMask);
+ std::istringstream tags{metadata.tags};
+ std::string tag;
+ while (std::getline(tags, tag, HidlUtils::sAudioTagSeparator)) {
+ if (!tag.empty()) {
+ halTrackMetadata.tags.push_back(tag);
+ }
+ }
+#endif
+ return halTrackMetadata;
})};
return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(halMetadata));
}
diff --git a/media/libaudiohal/impl/StreamHalLocal.cpp b/media/libaudiohal/impl/StreamHalLocal.cpp
index 69be303..f544e06 100644
--- a/media/libaudiohal/impl/StreamHalLocal.cpp
+++ b/media/libaudiohal/impl/StreamHalLocal.cpp
@@ -241,19 +241,55 @@
return mStream->get_presentation_position(mStream, frames, timestamp);
}
-status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
- if (mStream->update_source_metadata == nullptr) {
- return INVALID_OPERATION;
+void StreamOutHalLocal::doUpdateSourceMetadata(const SourceMetadata& sourceMetadata) {
+ std::vector<playback_track_metadata> halTracks;
+ halTracks.reserve(sourceMetadata.tracks.size());
+ for (auto& metadata : sourceMetadata.tracks) {
+ playback_track_metadata halTrackMetadata;
+ playback_track_metadata_from_v7(&halTrackMetadata, &metadata);
+ halTracks.push_back(halTrackMetadata);
}
+ const source_metadata_t halMetadata = {
+ .track_count = halTracks.size(),
+ .tracks = halTracks.data(),
+ };
+ mStream->update_source_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamOutHalLocal::doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata) {
const source_metadata_t metadata {
.track_count = sourceMetadata.tracks.size(),
// const cast is fine as it is in a const structure
- .tracks = const_cast<playback_track_metadata*>(sourceMetadata.tracks.data()),
+ .tracks = const_cast<playback_track_metadata_v7*>(sourceMetadata.tracks.data()),
};
- mStream->update_source_metadata(mStream, &metadata);
+ mStream->update_source_metadata_v7(mStream, &metadata);
+}
+#endif
+
+status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
+#if MAJOR_VERSION < 7
+ if (mStream->update_source_metadata == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadata(sourceMetadata);
+#else
+ if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2)
+ if (mStream->update_source_metadata == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadata(sourceMetadata);
+ } else {
+ if (mStream->update_source_metadata_v7 == nullptr) {
+ return INVALID_OPERATION;
+ }
+ doUpdateSourceMetadataV7(sourceMetadata);
+ }
+#endif
return OK;
}
+
status_t StreamOutHalLocal::start() {
if (mStream->start == NULL) return INVALID_OPERATION;
return mStream->start(mStream);
@@ -352,16 +388,52 @@
return mStream->get_capture_position(mStream, frames, time);
}
-status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
- if (mStream->update_sink_metadata == nullptr) {
- return INVALID_OPERATION;
+void StreamInHalLocal::doUpdateSinkMetadata(const SinkMetadata& sinkMetadata) {
+ std::vector<record_track_metadata> halTracks;
+ halTracks.reserve(sinkMetadata.tracks.size());
+ for (auto& metadata : sinkMetadata.tracks) {
+ record_track_metadata halTrackMetadata;
+ record_track_metadata_from_v7(&halTrackMetadata, &metadata);
+ halTracks.push_back(halTrackMetadata);
}
- const sink_metadata_t metadata {
+ const sink_metadata_t halMetadata = {
+ .track_count = halTracks.size(),
+ .tracks = halTracks.data(),
+ };
+ mStream->update_sink_metadata(mStream, &halMetadata);
+}
+
+#if MAJOR_VERSION >= 7
+void StreamInHalLocal::doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata) {
+ const sink_metadata_v7_t halMetadata {
.track_count = sinkMetadata.tracks.size(),
// const cast is fine as it is in a const structure
- .tracks = const_cast<record_track_metadata*>(sinkMetadata.tracks.data()),
+ .tracks = const_cast<record_track_metadata_v7*>(sinkMetadata.tracks.data()),
};
- mStream->update_sink_metadata(mStream, &metadata);
+ mStream->update_sink_metadata_v7(mStream, &halMetadata);
+}
+#endif
+
+status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
+#if MAJOR_VERSION < 7
+
+ if (mStream->update_sink_metadata == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadata(sinkMetadata);
+#else
+ if (mDevice->version() < AUDIO_DEVICE_API_VERSION_3_2)
+ if (mStream->update_sink_metadata == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadata(sinkMetadata);
+ } else {
+ if (mStream->update_sink_metadata_v7 == nullptr) {
+ return INVALID_OPERATION; // not supported by the HAL
+ }
+ doUpdateSinkMetadataV7(sinkMetadata);
+ }
+#endif
return OK;
}
diff --git a/media/libaudiohal/impl/StreamHalLocal.h b/media/libaudiohal/impl/StreamHalLocal.h
index d17f9f3..8e5180f 100644
--- a/media/libaudiohal/impl/StreamHalLocal.h
+++ b/media/libaudiohal/impl/StreamHalLocal.h
@@ -173,6 +173,9 @@
static int asyncCallback(stream_callback_event_t event, void *param, void *cookie);
static int asyncEventCallback(stream_event_callback_type_t event, void *param, void *cookie);
+
+ void doUpdateSourceMetadataV7(const SourceMetadata& sourceMetadata);
+ void doUpdateSourceMetadata(const SourceMetadata& sourceMetadata);
};
class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
@@ -227,6 +230,9 @@
StreamInHalLocal(audio_stream_in_t *stream, sp<DeviceHalLocal> device);
virtual ~StreamInHalLocal();
+
+ void doUpdateSinkMetadata(const SinkMetadata& sinkMetadata);
+ void doUpdateSinkMetadataV7(const SinkMetadata& sinkMetadata);
};
} // namespace CPP_VERSION
diff --git a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
index e30cb72..523705e 100644
--- a/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
+++ b/media/libaudiohal/include/media/audiohal/StreamHalInterface.h
@@ -158,7 +158,7 @@
virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0;
struct SourceMetadata {
- std::vector<playback_track_metadata_t> tracks;
+ std::vector<playback_track_metadata_v7_t> tracks;
};
/**
* Called when the metadata of the stream's source has been changed.
@@ -197,7 +197,7 @@
virtual status_t setPreferredMicrophoneFieldDimension(float zoom) = 0;
struct SinkMetadata {
- std::vector<record_track_metadata_t> tracks;
+ std::vector<record_track_metadata_v7_t> tracks;
};
/**
* Called when the metadata of the stream's sink has been changed.
diff --git a/media/libeffects/lvm/benchmarks/Android.bp b/media/libeffects/lvm/benchmarks/Android.bp
index 420e172..930292f 100644
--- a/media/libeffects/lvm/benchmarks/Android.bp
+++ b/media/libeffects/lvm/benchmarks/Android.bp
@@ -14,3 +14,24 @@
"libhardware_headers",
],
}
+
+cc_benchmark {
+ name: "reverb_benchmark",
+ vendor: true,
+ include_dirs: [
+ "frameworks/av/media/libeffects/lvm/wrapper/Reverb",
+ ],
+ srcs: ["reverb_benchmark.cpp"],
+ static_libs: [
+ "libreverb",
+ "libreverbwrapper",
+ ],
+ shared_libs: [
+ "libaudioutils",
+ "liblog",
+ ],
+ header_libs: [
+ "libaudioeffects",
+ "libhardware_headers",
+ ],
+}
diff --git a/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
new file mode 100644
index 0000000..00a7ff2
--- /dev/null
+++ b/media/libeffects/lvm/benchmarks/reverb_benchmark.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <climits>
+#include <cstdlib>
+#include <random>
+#include <vector>
+#include <log/log.h>
+#include <benchmark/benchmark.h>
+#include <hardware/audio_effect.h>
+#include <system/audio.h>
+#include "EffectReverb.h"
+
+extern audio_effect_library_t AUDIO_EFFECT_LIBRARY_INFO_SYM;
+constexpr effect_uuid_t kEffectUuids[] = {
+ {0x172cdf00,
+ 0xa3bc,
+ 0x11df,
+ 0xa72f,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // preset-insert mode
+ {0xf29a1400,
+ 0xa3bb,
+ 0x11df,
+ 0x8ddc,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, // preset-aux mode
+};
+
+constexpr size_t kNumEffectUuids = std::size(kEffectUuids);
+
+constexpr size_t kFrameCount = 2048;
+
+constexpr int kPresets[] = {
+ REVERB_PRESET_NONE, REVERB_PRESET_SMALLROOM, REVERB_PRESET_MEDIUMROOM,
+ REVERB_PRESET_LARGEROOM, REVERB_PRESET_MEDIUMHALL, REVERB_PRESET_LARGEHALL,
+ REVERB_PRESET_PLATE,
+};
+
+constexpr size_t kNumPresets = std::size(kPresets);
+
+constexpr int kSampleRate = 44100;
+
+int reverbSetConfigParam(uint32_t paramType, uint32_t paramValue, effect_handle_t effectHandle) {
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ uint32_t paramData[2] = {paramType, paramValue};
+ auto effectParam = (effect_param_t*)malloc(sizeof(effect_param_t) + sizeof(paramData));
+ memcpy(&effectParam->data[0], ¶mData[0], sizeof(paramData));
+ effectParam->psize = sizeof(paramData[0]);
+ effectParam->vsize = sizeof(paramData[1]);
+ int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_PARAM,
+ sizeof(effect_param_t) + sizeof(paramData), effectParam,
+ &replySize, &reply);
+ free(effectParam);
+ if (status != 0) {
+ ALOGE("Reverb set config returned an error = %d\n", status);
+ return status;
+ }
+ return reply;
+}
+
+/*******************************************************************
+ * A test result running on Pixel 3 with for comparison.
+ * The first parameter indicates the preset level id.
+ * The second parameter indicates the effect.
+ * 0: preset-insert mode, 1: preset-aux mode
+ * --------------------------------------------------------
+ * Benchmark Time CPU Iterations
+ * --------------------------------------------------------
+ * BM_REVERB/0/0 19312 ns 19249 ns 36282
+ * BM_REVERB/0/1 5613 ns 5596 ns 125032
+ * BM_REVERB/1/0 605453 ns 603714 ns 1131
+ * BM_REVERB/1/1 589421 ns 587758 ns 1161
+ * BM_REVERB/2/0 605760 ns 604006 ns 1131
+ * BM_REVERB/2/1 589434 ns 587777 ns 1161
+ * BM_REVERB/3/0 605574 ns 603828 ns 1131
+ * BM_REVERB/3/1 589566 ns 587862 ns 1162
+ * BM_REVERB/4/0 605634 ns 603894 ns 1131
+ * BM_REVERB/4/1 589506 ns 587856 ns 1161
+ * BM_REVERB/5/0 605644 ns 603929 ns 1131
+ * BM_REVERB/5/1 589592 ns 587863 ns 1161
+ * BM_REVERB/6/0 610544 ns 608561 ns 1131
+ * BM_REVERB/6/1 589686 ns 587871 ns 1161
+ *******************************************************************/
+
+static void BM_REVERB(benchmark::State& state) {
+ const size_t chMask = AUDIO_CHANNEL_OUT_STEREO;
+ const size_t preset = kPresets[state.range(0)];
+ const effect_uuid_t uuid = kEffectUuids[state.range(1)];
+ const size_t channelCount = audio_channel_count_from_out_mask(chMask);
+
+ // Initialize input buffer with deterministic pseudo-random values
+ std::minstd_rand gen(chMask);
+ std::uniform_real_distribution<> dis(-1.0f, 1.0f);
+ std::vector<float> input(kFrameCount * channelCount);
+ std::vector<float> output(kFrameCount * channelCount);
+ for (auto& in : input) {
+ in = dis(gen);
+ }
+
+ effect_handle_t effectHandle = nullptr;
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.create_effect(&uuid, 1, 1, &effectHandle);
+ status != 0) {
+ ALOGE("create_effect returned an error = %d\n", status);
+ return;
+ }
+
+ effect_config_t config{};
+ config.inputCfg.samplingRate = config.outputCfg.samplingRate = kSampleRate;
+ config.inputCfg.channels = config.outputCfg.channels = chMask;
+ config.inputCfg.format = config.outputCfg.format = AUDIO_FORMAT_PCM_FLOAT;
+
+ int reply = 0;
+ uint32_t replySize = sizeof(reply);
+ if (int status = (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_SET_CONFIG, sizeof(effect_config_t),
+ &config, &replySize, &reply);
+ status != 0) {
+ ALOGE("command returned an error = %d\n", status);
+ return;
+ }
+
+ if (int status =
+ (*effectHandle)
+ ->command(effectHandle, EFFECT_CMD_ENABLE, 0, nullptr, &replySize, &reply);
+ status != 0) {
+ ALOGE("Command enable call returned error %d\n", reply);
+ return;
+ }
+
+ if (int status = reverbSetConfigParam(REVERB_PARAM_PRESET, preset, effectHandle); status != 0) {
+ ALOGE("Invalid reverb preset. Error %d\n", status);
+ return;
+ }
+
+ // Run the test
+ for (auto _ : state) {
+ benchmark::DoNotOptimize(input.data());
+ benchmark::DoNotOptimize(output.data());
+
+ audio_buffer_t inBuffer = {.frameCount = kFrameCount, .f32 = input.data()};
+ audio_buffer_t outBuffer = {.frameCount = kFrameCount, .f32 = output.data()};
+ (*effectHandle)->process(effectHandle, &inBuffer, &outBuffer);
+
+ benchmark::ClobberMemory();
+ }
+
+ state.SetComplexityN(state.range(0));
+
+ if (int status = AUDIO_EFFECT_LIBRARY_INFO_SYM.release_effect(effectHandle); status != 0) {
+ ALOGE("release_effect returned an error = %d\n", status);
+ return;
+ }
+}
+
+static void REVERBArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 0; i < kNumPresets; i++) {
+ for (int j = 0; j < kNumEffectUuids; ++j) {
+ b->Args({i, j});
+ }
+ }
+}
+
+BENCHMARK(BM_REVERB)->Apply(REVERBArgs);
+
+BENCHMARK_MAIN();
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index a4b8650..dbc190c 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -148,7 +148,7 @@
*/
bool readAndClearHasChanged() { return !mChangeNotified.test_and_set(); }
- using SourceMetadatas = std::vector<playback_track_metadata_t>;
+ using SourceMetadatas = std::vector<playback_track_metadata_v7_t>;
using MetadataInserter = std::back_insert_iterator<SourceMetadatas>;
/** Copy the track metadata in the provided iterator. Thread safe. */
virtual void copyMetadataTo(MetadataInserter& backInserter) const;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 1a0d2c9..7e1c67e 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8102,10 +8102,15 @@
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({
+ record_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.source = track->attributes().source,
.gain = 1, // capture tracks do not have volumes
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+
+ metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
}
@@ -9680,11 +9685,15 @@
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({
+ playback_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.usage = track->attributes().usage,
.content_type = track->attributes().content_type,
.gain = mHalVolFloat, // TODO: propagate from aaudio pre-mix volume
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ metadata.tracks.push_back(trackMetadata);
}
mOutput->stream->updateSourceMetadata(metadata);
}
@@ -9805,10 +9814,14 @@
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({
+ record_track_metadata_v7_t trackMetadata;
+ trackMetadata.base = {
.source = track->attributes().source,
.gain = 1, // capture tracks do not have volumes
- });
+ };
+ trackMetadata.channel_mask = track->channelMask(),
+ strncpy(trackMetadata.tags, track->attributes().tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ metadata.tracks.push_back(trackMetadata);
}
mInput->stream->updateSinkMetadata(metadata);
}
diff --git a/services/audioflinger/TrackBase.h b/services/audioflinger/TrackBase.h
index 01d5345..38dab5b 100644
--- a/services/audioflinger/TrackBase.h
+++ b/services/audioflinger/TrackBase.h
@@ -253,6 +253,8 @@
// Called to tally underrun frames in playback.
virtual void tallyUnderrunFrames(size_t /* frames */) {}
+ audio_channel_mask_t channelMask() const { return mChannelMask; }
+
protected:
DISALLOW_COPY_AND_ASSIGN(TrackBase);
@@ -278,8 +280,6 @@
size_t frameSize() const { return mFrameSize; }
- audio_channel_mask_t channelMask() const { return mChannelMask; }
-
virtual uint32_t sampleRate() const { return mSampleRate; }
bool isStopped() const {
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 6049f62..06cbe87 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -1310,11 +1310,15 @@
void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backInserter) const
{
- *backInserter++ = {
+ playback_track_metadata_v7_t metadata;
+ metadata.base = {
.usage = mAttr.usage,
.content_type = mAttr.content_type,
.gain = mFinalVolume,
};
+ metadata.channel_mask = mChannelMask,
+ strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE);
+ *backInserter++ = metadata;
}
void AudioFlinger::PlaybackThread::Track::setTeePatches(TeePatches teePatches) {