Merge changes from topic "metadata-audio-hal" into pi-dev

* changes:
  Audio V4: Propagate track attributes to HAL
  Audio V4: Propagate audio attributes to tracks
  Audio V4: propagate metadata to the HAL
gugelfrei
TreeHugger Robot 6 years ago committed by Android (Google) Code Review
commit f2797b2275

@ -555,6 +555,11 @@ status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct time
}
}
status_t StreamOutHalHidl::updateSourceMetadata(const SourceMetadata& /* sourceMetadata */) {
// Audio HAL V2.0 does not support propagating source metadata
return INVALID_OPERATION;
}
void StreamOutHalHidl::onWriteReady() {
sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
if (callback == 0) return;
@ -755,4 +760,9 @@ status_t StreamInHalHidl::getActiveMicrophones(
return INVALID_OPERATION;
}
status_t StreamInHalHidl::updateSinkMetadata(const SinkMetadata& /* sinkMetadata */) {
// Audio HAL V2.0 does not support propagating sink metadata
return INVALID_OPERATION;
}
} // namespace android

@ -161,6 +161,9 @@ class StreamOutHalHidl : public StreamOutHalInterface, public StreamHalHidl {
// Return a recent count of the number of audio frames presented to an external observer.
virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
// Called when the metadata of the stream's source has been changed.
status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
// Methods used by StreamOutCallback (HIDL).
void onWriteReady();
void onDrainReady();
@ -213,6 +216,9 @@ class StreamInHalHidl : public StreamInHalInterface, public StreamHalHidl {
// Get active microphones
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
// Called when the metadata of the stream's sink has been changed.
status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
private:
friend class DeviceHalHidl;
typedef MessageQueue<ReadParameters, hardware::kSynchronizedReadWrite> CommandMQ;

@ -231,6 +231,19 @@ status_t StreamOutHalLocal::getPresentationPosition(uint64_t *frames, struct tim
return mStream->get_presentation_position(mStream, frames, timestamp);
}
status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
if (mStream->update_source_metadata == nullptr) {
return INVALID_OPERATION;
}
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()),
};
mStream->update_source_metadata(mStream, &metadata);
return OK;
}
status_t StreamOutHalLocal::start() {
if (mStream->start == NULL) return INVALID_OPERATION;
return mStream->start(mStream);
@ -292,6 +305,19 @@ status_t StreamInHalLocal::getCapturePosition(int64_t *frames, int64_t *time) {
return mStream->get_capture_position(mStream, frames, time);
}
status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
if (mStream->update_sink_metadata == nullptr) {
return INVALID_OPERATION;
}
const sink_metadata_t metadata {
.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()),
};
mStream->update_sink_metadata(mStream, &metadata);
return OK;
}
status_t StreamInHalLocal::start() {
if (mStream->start == NULL) return INVALID_OPERATION;
return mStream->start(mStream);

@ -149,6 +149,9 @@ class StreamOutHalLocal : public StreamOutHalInterface, public StreamHalLocal {
// Get current read/write position in the mmap buffer
virtual status_t getMmapPosition(struct audio_mmap_position *position);
// Called when the metadata of the stream's source has been changed.
status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
private:
audio_stream_out_t *mStream;
wp<StreamOutHalInterfaceCallback> mCallback;
@ -197,6 +200,9 @@ class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
// Get active microphones
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
// Called when the metadata of the stream's sink has been changed.
status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
private:
audio_stream_in_t *mStream;

@ -28,7 +28,10 @@
#include "VersionUtils.h"
using ::android::hardware::audio::common::V4_0::AudioChannelMask;
using ::android::hardware::audio::common::V4_0::AudioContentType;
using ::android::hardware::audio::common::V4_0::AudioFormat;
using ::android::hardware::audio::common::V4_0::AudioSource;
using ::android::hardware::audio::common::V4_0::AudioUsage;
using ::android::hardware::audio::common::V4_0::ThreadInfo;
using ::android::hardware::audio::V4_0::AudioDrain;
using ::android::hardware::audio::V4_0::IStreamOutCallback;
@ -37,6 +40,8 @@ using ::android::hardware::audio::V4_0::MicrophoneInfo;
using ::android::hardware::audio::V4_0::MmapBufferInfo;
using ::android::hardware::audio::V4_0::MmapPosition;
using ::android::hardware::audio::V4_0::ParameterValue;
using ::android::hardware::audio::V4_0::PlaybackTrackMetadata;
using ::android::hardware::audio::V4_0::RecordTrackMetadata;
using ::android::hardware::audio::V4_0::Result;
using ::android::hardware::audio::V4_0::TimeSpec;
using ::android::hardware::MQDescriptorSync;
@ -561,6 +566,28 @@ status_t StreamOutHalHidl::getPresentationPosition(uint64_t *frames, struct time
}
}
/** Transform a standard collection to an HIDL vector. */
template <class Values, class ElementConverter>
static auto transformToHidlVec(const Values& values, ElementConverter converter) {
hidl_vec<decltype(converter(*values.begin()))> result{values.size()};
using namespace std;
transform(begin(values), end(values), begin(result), converter);
return result;
}
status_t StreamOutHalHidl::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
hardware::audio::V4_0::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,
};
})};
return processReturn("updateSourceMetadata", mStream->updateSourceMetadata(halMetadata));
}
void StreamOutHalHidl::onWriteReady() {
sp<StreamOutHalInterfaceCallback> callback = mCallback.promote();
if (callback == 0) return;
@ -774,5 +801,17 @@ status_t StreamInHalHidl::getActiveMicrophones(
return processReturn("getActiveMicrophones", ret, retval);
}
status_t StreamInHalHidl::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
hardware::audio::V4_0::SinkMetadata halMetadata = {
.tracks = transformToHidlVec(sinkMetadata.tracks,
[](const record_track_metadata& metadata) -> RecordTrackMetadata {
return {
.source=static_cast<AudioSource>(metadata.source),
.gain=metadata.gain,
};
})};
return processReturn("updateSinkMetadata", mStream->updateSinkMetadata(halMetadata));
}
} // namespace V4_0
} // namespace android

@ -162,6 +162,9 @@ class StreamOutHalHidl : public StreamOutHalInterface, public StreamHalHidl {
// Return a recent count of the number of audio frames presented to an external observer.
virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
// Called when the metadata of the stream's source has been changed.
status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
// Methods used by StreamOutCallback (HIDL).
void onWriteReady();
void onDrainReady();
@ -214,6 +217,9 @@ class StreamInHalHidl : public StreamInHalInterface, public StreamHalHidl {
// Get active microphones
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
// Called when the metadata of the stream's sink has been changed.
status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
private:
friend class DeviceHalHidl;
typedef MessageQueue<ReadParameters, hardware::kSynchronizedReadWrite> CommandMQ;

@ -233,6 +233,19 @@ status_t StreamOutHalLocal::getPresentationPosition(uint64_t *frames, struct tim
return mStream->get_presentation_position(mStream, frames, timestamp);
}
status_t StreamOutHalLocal::updateSourceMetadata(const SourceMetadata& sourceMetadata) {
if (mStream->update_source_metadata == nullptr) {
return INVALID_OPERATION;
}
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()),
};
mStream->update_source_metadata(mStream, &metadata);
return OK;
}
status_t StreamOutHalLocal::start() {
if (mStream->start == NULL) return INVALID_OPERATION;
return mStream->start(mStream);
@ -294,6 +307,19 @@ status_t StreamInHalLocal::getCapturePosition(int64_t *frames, int64_t *time) {
return mStream->get_capture_position(mStream, frames, time);
}
status_t StreamInHalLocal::updateSinkMetadata(const SinkMetadata& sinkMetadata) {
if (mStream->update_sink_metadata == nullptr) {
return INVALID_OPERATION;
}
const sink_metadata_t metadata {
.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()),
};
mStream->update_sink_metadata(mStream, &metadata);
return OK;
}
status_t StreamInHalLocal::start() {
if (mStream->start == NULL) return INVALID_OPERATION;
return mStream->start(mStream);

@ -150,6 +150,9 @@ class StreamOutHalLocal : public StreamOutHalInterface, public StreamHalLocal {
// Get current read/write position in the mmap buffer
virtual status_t getMmapPosition(struct audio_mmap_position *position);
// Called when the metadata of the stream's source has been changed.
status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) override;
private:
audio_stream_out_t *mStream;
wp<StreamOutHalInterfaceCallback> mCallback;
@ -198,6 +201,9 @@ class StreamInHalLocal : public StreamInHalInterface, public StreamHalLocal {
// Get active microphones
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones);
// Called when the metadata of the stream's sink has been changed.
status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) override;
private:
audio_stream_in_t *mStream;

@ -17,6 +17,8 @@
#ifndef ANDROID_HARDWARE_STREAM_HAL_INTERFACE_H
#define ANDROID_HARDWARE_STREAM_HAL_INTERFACE_H
#include <vector>
#include <media/audiohal/EffectHalInterface.h>
#include <media/MicrophoneInfo.h>
#include <system/audio.h>
@ -143,6 +145,15 @@ class StreamOutHalInterface : public virtual StreamHalInterface {
// Return a recent count of the number of audio frames presented to an external observer.
virtual status_t getPresentationPosition(uint64_t *frames, struct timespec *timestamp) = 0;
struct SourceMetadata {
std::vector<playback_track_metadata_t> tracks;
};
/**
* Called when the metadata of the stream's source has been changed.
* @param sourceMetadata Description of the audio that is played by the clients.
*/
virtual status_t updateSourceMetadata(const SourceMetadata& sourceMetadata) = 0;
protected:
virtual ~StreamOutHalInterface() {}
};
@ -165,6 +176,15 @@ class StreamInHalInterface : public virtual StreamHalInterface {
// Get active microphones
virtual status_t getActiveMicrophones(std::vector<media::MicrophoneInfo> *microphones) = 0;
struct SinkMetadata {
std::vector<record_track_metadata_t> tracks;
};
/**
* Called when the metadata of the stream's sink has been changed.
* @param sinkMetadata Description of the audio that is suggested by the clients.
*/
virtual status_t updateSinkMetadata(const SinkMetadata& sinkMetadata) = 0;
protected:
virtual ~StreamInHalInterface() {}
};

@ -753,8 +753,8 @@ sp<IAudioTrack> AudioFlinger::createTrack(const CreateTrackInput& input,
output.notificationFrameCount = input.notificationFrameCount;
output.flags = input.flags;
track = thread->createTrack_l(client, streamType, &output.sampleRate, input.config.format,
input.config.channel_mask,
track = thread->createTrack_l(client, streamType, input.attr, &output.sampleRate,
input.config.format, input.config.channel_mask,
&output.frameCount, &output.notificationFrameCount,
input.notificationsPerBuffer, input.speed,
input.sharedBuffer, sessionId, &output.flags,
@ -1673,7 +1673,7 @@ sp<media::IAudioRecord> AudioFlinger::createRecord(const CreateRecordInput& inpu
output.frameCount = input.frameCount;
output.notificationFrameCount = input.notificationFrameCount;
recordTrack = thread->createRecordTrack_l(client, &output.sampleRate,
recordTrack = thread->createRecordTrack_l(client, input.attr, &output.sampleRate,
input.config.format, input.config.channel_mask,
&output.frameCount, sessionId,
&output.notificationFrameCount,

@ -23,6 +23,7 @@
class MmapTrack : public TrackBase {
public:
MmapTrack(ThreadBase *thread,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,

@ -25,6 +25,7 @@ public:
Track( PlaybackThread *thread,
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,

@ -24,6 +24,7 @@ class RecordTrack : public TrackBase {
public:
RecordTrack(RecordThread *thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,

@ -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 @@ ssize_t AudioFlinger::ThreadBase::ActiveTracks<T>::add(const sp<T> &track) {
mActiveTracksGeneration++;
mLatestActiveTrack = track;
++mBatteryCounter[track->uid()].second;
mHasChanged = true;
return mActiveTracks.add(track);
}
@ -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;
}
@ -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();
@ -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 {
@ -1847,6 +1858,7 @@ void AudioFlinger::PlaybackThread::preExit()
sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrack_l(
const sp<AudioFlinger::Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -2125,7 +2137,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
}
}
track = new Track(this, client, streamType, sampleRate, format,
track = new Track(this, client, streamType, attr, sampleRate, format,
channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sharedBuffer,
sessionId, uid, *flags, TrackBase::TYPE_DEFAULT, portId);
@ -2609,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)
{
@ -3306,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
@ -6117,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;
@ -6444,6 +6487,8 @@ reacquire_wakelock:
mActiveTracks.updatePowerState(this);
updateMetadata_l();
if (allStopped) {
standbyIfNotAlreadyInStandby();
}
@ -6808,6 +6853,7 @@ void AudioFlinger::RecordThread::inputStandBy()
// RecordThread::createRecordTrack_l() must be called with AudioFlinger::mLock held
sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRecordTrack_l(
const sp<AudioFlinger::Client>& client,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -6941,7 +6987,7 @@ sp<AudioFlinger::RecordThread::RecordTrack> AudioFlinger::RecordThread::createRe
{ // scope for mLock
Mutex::Autolock _l(mLock);
track = new RecordTrack(this, client, sampleRate,
track = new RecordTrack(this, client, attr, sampleRate,
format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, sessionId, uid,
*flags, TrackBase::TYPE_DEFAULT, portId);
@ -7133,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)
{
@ -7960,7 +8023,8 @@ status_t AudioFlinger::MmapThread::start(const AudioClient& client,
return PERMISSION_DENIED;
}
sp<MmapTrack> track = new MmapTrack(this, mSampleRate, mFormat, mChannelMask, mSessionId,
// Given that MmapThread::mAttr is mutable, should a MmapTrack have attributes ?
sp<MmapTrack> track = new MmapTrack(this, mAttr, mSampleRate, mFormat, mChannelMask, mSessionId,
client.clientUid, client.clientPid, portId);
mActiveTracks.add(track);
@ -8096,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();
@ -8643,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) {
@ -8687,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

@ -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() { }
@ -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;
@ -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;
@ -706,6 +715,7 @@ public:
sp<Track> createTrack_l(
const sp<AudioFlinger::Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
uint32_t *sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -917,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);
@ -1275,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;
@ -1387,6 +1400,7 @@ public:
sp<AudioFlinger::RecordThread::RecordTrack> createRecordTrack_l(
const sp<AudioFlinger::Client>& client,
const audio_attributes_t& attr,
uint32_t *pSampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -1461,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();
@ -1658,6 +1674,8 @@ public:
virtual bool isOutput() const override { return true; }
void updateMetadata_l() override;
protected:
audio_stream_type_t mStreamType;
@ -1684,6 +1702,8 @@ public:
virtual bool isOutput() const override { return false; }
void updateMetadata_l() override;
protected:
AudioStreamIn* mInput;

@ -61,6 +61,7 @@ public:
TrackBase(ThreadBase *thread,
const sp<Client>& client,
const audio_attributes_t& mAttr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -97,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);
@ -188,6 +190,7 @@ protected:
size_t mBufferSize; // size of mBuffer in bytes
// we don't really need a lock for these
track_state mState;
const audio_attributes_t mAttr;
const uint32_t mSampleRate; // initial sample rate only; for tracks which
// support dynamic rates, the current value is in control block
const audio_format_t mFormat;

@ -63,6 +63,7 @@ static volatile int32_t nextTrackId = 55;
AudioFlinger::ThreadBase::TrackBase::TrackBase(
ThreadBase *thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -81,6 +82,7 @@ AudioFlinger::ThreadBase::TrackBase::TrackBase(
mCblk(NULL),
// mBuffer, mBufferSize
mState(IDLE),
mAttr(attr),
mSampleRate(sampleRate),
mFormat(format),
mChannelMask(channelMask),
@ -372,6 +374,7 @@ AudioFlinger::PlaybackThread::Track::Track(
PlaybackThread *thread,
const sp<Client>& client,
audio_stream_type_t streamType,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -384,7 +387,7 @@ AudioFlinger::PlaybackThread::Track::Track(
audio_output_flags_t flags,
track_type type,
audio_port_handle_t portId)
: TrackBase(thread, client, sampleRate, format, channelMask, frameCount,
: TrackBase(thread, client, attr, sampleRate, format, channelMask, frameCount,
(sharedBuffer != 0) ? sharedBuffer->pointer() : buffer,
(sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
sessionId, uid, true /*isOut*/,
@ -1259,6 +1262,7 @@ AudioFlinger::PlaybackThread::OutputTrack::OutputTrack(
size_t frameCount,
uid_t uid)
: Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
audio_attributes_t{} /* currently unused for output track */,
sampleRate, format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, uid, AUDIO_OUTPUT_FLAG_NONE,
@ -1461,6 +1465,7 @@ AudioFlinger::PlaybackThread::PatchTrack::PatchTrack(PlaybackThread *playbackThr
size_t bufferSize,
audio_output_flags_t flags)
: Track(playbackThread, NULL, streamType,
audio_attributes_t{} /* currently unused for patch track */,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, nullptr /* sharedBuffer */,
AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
@ -1595,6 +1600,7 @@ binder::Status AudioFlinger::RecordHandle::getActiveMicrophones(
AudioFlinger::RecordThread::RecordTrack::RecordTrack(
RecordThread *thread,
const sp<Client>& client,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -1606,7 +1612,7 @@ AudioFlinger::RecordThread::RecordTrack::RecordTrack(
audio_input_flags_t flags,
track_type type,
audio_port_handle_t portId)
: TrackBase(thread, client, sampleRate, format,
: TrackBase(thread, client, attr, sampleRate, format,
channelMask, frameCount, buffer, bufferSize, sessionId, uid, false /*isOut*/,
(type == TYPE_DEFAULT) ?
((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
@ -1821,7 +1827,9 @@ AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread,
void *buffer,
size_t bufferSize,
audio_input_flags_t flags)
: RecordTrack(recordThread, NULL, sampleRate, format, channelMask, frameCount,
: RecordTrack(recordThread, NULL,
audio_attributes_t{} /* currently unused for patch track */,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, AUDIO_SESSION_NONE, getuid(), flags, TYPE_PATCH),
mProxy(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true))
{
@ -1882,6 +1890,7 @@ void AudioFlinger::RecordThread::PatchRecord::releaseBuffer(Proxy::Buffer* buffe
AudioFlinger::MmapThread::MmapTrack::MmapTrack(ThreadBase *thread,
const audio_attributes_t& attr,
uint32_t sampleRate,
audio_format_t format,
audio_channel_mask_t channelMask,
@ -1889,7 +1898,7 @@ AudioFlinger::MmapThread::MmapTrack::MmapTrack(ThreadBase *thread,
uid_t uid,
pid_t pid,
audio_port_handle_t portId)
: TrackBase(thread, NULL, sampleRate, format,
: TrackBase(thread, NULL, attr, sampleRate, format,
channelMask, (size_t)0 /* frameCount */,
nullptr /* buffer */, (size_t)0 /* bufferSize */,
sessionId, uid, false /* isOut */,

Loading…
Cancel
Save