Loading services/audioflinger/PatchPanel.cpp +18 −3 Original line number Diff line number Diff line Loading @@ -313,12 +313,19 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa patch->sources[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? patch->sources[0].flags.input : AUDIO_INPUT_FLAG_NONE; audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; audio_source_t source = AUDIO_SOURCE_MIC; // For telephony patches, propagate voice communication use case to record side if (patch->num_sources == 2 && patch->sources[1].ext.mix.usecase.stream == AUDIO_STREAM_VOICE_CALL) { source = AUDIO_SOURCE_VOICE_COMMUNICATION; } sp<ThreadBase> thread = mAudioFlinger.openInput_l(srcModule, &input, &config, device, address, AUDIO_SOURCE_MIC, source, flags, outputDevice, outputDeviceAddress); Loading Loading @@ -516,9 +523,14 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) audio_output_flags_t outputFlags = mAudioPatch.sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? mAudioPatch.sinks[0].flags.output : AUDIO_OUTPUT_FLAG_NONE; audio_stream_type_t streamType = AUDIO_STREAM_PATCH; audio_source_t source = AUDIO_SOURCE_DEFAULT; if (mAudioPatch.num_sources == 2 && mAudioPatch.sources[1].type == AUDIO_PORT_TYPE_MIX) { // "reuse one existing output mix" case streamType = mAudioPatch.sources[1].ext.mix.usecase.stream; // For telephony patches, propagate voice communication use case to record side if (streamType == AUDIO_STREAM_VOICE_CALL) { source = AUDIO_SOURCE_VOICE_COMMUNICATION; } } if (mPlayback.thread()->hasFastMixer()) { // Create a fast track if the playback thread has fast mixer to get better performance. Loading Loading @@ -546,7 +558,8 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) inChannelMask, format, frameCount, inputFlags); inputFlags, source); } else { // use a pseudo LCM between input and output framecount int playbackShift = __builtin_ctz(playbackFrameCount); Loading @@ -566,7 +579,9 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) frameCount, nullptr, (size_t)0 /* bufferSize */, inputFlags); inputFlags, {} /* timeout */, source); } status = mRecord.checkTrack(tempRecordTrack.get()); if (status != NO_ERROR) { Loading services/audioflinger/RecordTracks.h +8 −2 Original line number Diff line number Diff line Loading @@ -87,6 +87,10 @@ public: && (flags & AUDIO_INPUT_FLAG_HW_AV_SYNC) == 0; } using SinkMetadatas = std::vector<record_track_metadata_v7_t>; using MetadataInserter = std::back_insert_iterator<SinkMetadatas>; virtual void copyMetadataTo(MetadataInserter& backInserter) const; private: friend class AudioFlinger; // for mState Loading Loading @@ -134,7 +138,8 @@ public: void *buffer, size_t bufferSize, audio_input_flags_t flags, const Timeout& timeout = {}); const Timeout& timeout = {}, audio_source_t source = AUDIO_SOURCE_DEFAULT); virtual ~PatchRecord(); virtual Source* getSource() { return nullptr; } Loading Loading @@ -166,7 +171,8 @@ public: audio_channel_mask_t channelMask, audio_format_t format, size_t frameCount, audio_input_flags_t flags); audio_input_flags_t flags, audio_source_t source = AUDIO_SOURCE_DEFAULT); Source* getSource() override { return static_cast<Source*>(this); } Loading services/audioflinger/Threads.cpp +2 −14 Original line number Diff line number Diff line Loading @@ -8775,21 +8775,9 @@ void AudioFlinger::RecordThread::updateMetadata_l() return; // nothing to do } StreamInHalInterface::SinkMetadata metadata; auto backInserter = std::back_inserter(metadata.tracks); for (const sp<RecordTrack> &track : mActiveTracks) { // Do not forward PatchRecord metadata to audio HAL if (track->isPatchTrack()) { continue; } // No track is invalid as this is called after prepareTrack_l in the same critical section 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); track->copyMetadataTo(backInserter); } mInput->stream->updateSinkMetadata(metadata); } Loading services/audioflinger/Tracks.cpp +26 −7 Original line number Diff line number Diff line Loading @@ -1480,7 +1480,7 @@ void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backI } } metadata.channel_mask = mChannelMask, metadata.channel_mask = mChannelMask; strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE); *backInserter++ = metadata; } Loading Loading @@ -2024,7 +2024,6 @@ ssize_t AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t fr { Buffer *pInBuffer; Buffer inBuffer; bool outputBufferFull = false; inBuffer.frameCount = frames; inBuffer.raw = data; Loading Loading @@ -2054,7 +2053,6 @@ ssize_t AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t fr ALOGV("%s(%d): thread %d no more output buffers; status %d", __func__, mId, (int)mThreadIoHandle, status); outputBufferFull = true; break; } uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime); Loading Loading @@ -2750,6 +2748,25 @@ status_t AudioFlinger::RecordThread::RecordTrack::shareAudioHistory( } } void AudioFlinger::RecordThread::RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const { // Do not forward PatchRecord metadata with unspecified audio source if (mAttr.source == AUDIO_SOURCE_DEFAULT) { return; } // No track is invalid as this is called after prepareTrack_l in the same critical section record_track_metadata_v7_t metadata; metadata.base = { .source = mAttr.source, .gain = 1, // capture tracks do not have volumes }; metadata.channel_mask = mChannelMask; strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE); *backInserter++ = metadata; } // ---------------------------------------------------------------------------- #undef LOG_TAG Loading @@ -2763,9 +2780,10 @@ AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread, void *buffer, size_t bufferSize, audio_input_flags_t flags, const Timeout& timeout) const Timeout& timeout, audio_source_t source) : RecordTrack(recordThread, NULL, audio_attributes_t{} /* currently unused for patch track */, audio_attributes_t{ .source = source } , sampleRate, format, channelMask, frameCount, buffer, bufferSize, AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags, TYPE_PATCH), Loading Loading @@ -2876,9 +2894,10 @@ AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord( audio_channel_mask_t channelMask, audio_format_t format, size_t frameCount, audio_input_flags_t flags) audio_input_flags_t flags, audio_source_t source) : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount, nullptr /*buffer*/, 0 /*bufferSize*/, flags), nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source), mPatchRecordAudioBufferProvider(*this), mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)), mStubBuffer(allocAligned(32, mFrameCount * mFrameSize)) Loading services/audiopolicy/managerdefault/AudioPolicyManager.cpp +5 −3 Original line number Diff line number Diff line Loading @@ -788,7 +788,8 @@ void AudioPolicyManager::connectTelephonyTxAudioSource( ALOGV("%s between source %s and sink %s", __func__, srcDevice->toString().c_str(), sinkDevice->toString().c_str()); auto callTxSourceClientPortId = PolicyAudioPort::getNextUniqueId(); const audio_attributes_t aa = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION }; const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL); struct audio_port_config source = {}; srcDevice->toAudioPortConfig(&source); mCallTxSourceClient = new InternalSourceClientDescriptor( Loading Loading @@ -4534,7 +4535,7 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch * // In case of Hw bridge, it is a Work Around. The mixPort used is the one declared // in config XML to reach the sink so that is can be declared as available. audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; sp<SwAudioOutputDescriptor> outputDesc = nullptr; sp<SwAudioOutputDescriptor> outputDesc; if (!sourceDesc->isInternal()) { // take care of dynamic routing for SwOutput selection, audio_attributes_t attributes = sourceDesc->attributes(); Loading Loading @@ -4604,7 +4605,8 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch * audio_port_config srcMixPortConfig = {}; outputDesc->toAudioPortConfig(&srcMixPortConfig, nullptr); // for volume control, we may need a valid stream srcMixPortConfig.ext.mix.usecase.stream = !sourceDesc->isInternal() ? srcMixPortConfig.ext.mix.usecase.stream = (!sourceDesc->isInternal() || isCallTxAudioSource(sourceDesc)) ? mEngine->getStreamTypeForAttributes(sourceDesc->attributes()) : AUDIO_STREAM_PATCH; patchBuilder.addSource(srcMixPortConfig); Loading Loading
services/audioflinger/PatchPanel.cpp +18 −3 Original line number Diff line number Diff line Loading @@ -313,12 +313,19 @@ status_t AudioFlinger::PatchPanel::createAudioPatch(const struct audio_patch *pa patch->sources[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? patch->sources[0].flags.input : AUDIO_INPUT_FLAG_NONE; audio_io_handle_t input = AUDIO_IO_HANDLE_NONE; audio_source_t source = AUDIO_SOURCE_MIC; // For telephony patches, propagate voice communication use case to record side if (patch->num_sources == 2 && patch->sources[1].ext.mix.usecase.stream == AUDIO_STREAM_VOICE_CALL) { source = AUDIO_SOURCE_VOICE_COMMUNICATION; } sp<ThreadBase> thread = mAudioFlinger.openInput_l(srcModule, &input, &config, device, address, AUDIO_SOURCE_MIC, source, flags, outputDevice, outputDeviceAddress); Loading Loading @@ -516,9 +523,14 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) audio_output_flags_t outputFlags = mAudioPatch.sinks[0].config_mask & AUDIO_PORT_CONFIG_FLAGS ? mAudioPatch.sinks[0].flags.output : AUDIO_OUTPUT_FLAG_NONE; audio_stream_type_t streamType = AUDIO_STREAM_PATCH; audio_source_t source = AUDIO_SOURCE_DEFAULT; if (mAudioPatch.num_sources == 2 && mAudioPatch.sources[1].type == AUDIO_PORT_TYPE_MIX) { // "reuse one existing output mix" case streamType = mAudioPatch.sources[1].ext.mix.usecase.stream; // For telephony patches, propagate voice communication use case to record side if (streamType == AUDIO_STREAM_VOICE_CALL) { source = AUDIO_SOURCE_VOICE_COMMUNICATION; } } if (mPlayback.thread()->hasFastMixer()) { // Create a fast track if the playback thread has fast mixer to get better performance. Loading Loading @@ -546,7 +558,8 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) inChannelMask, format, frameCount, inputFlags); inputFlags, source); } else { // use a pseudo LCM between input and output framecount int playbackShift = __builtin_ctz(playbackFrameCount); Loading @@ -566,7 +579,9 @@ status_t AudioFlinger::PatchPanel::Patch::createConnections(PatchPanel *panel) frameCount, nullptr, (size_t)0 /* bufferSize */, inputFlags); inputFlags, {} /* timeout */, source); } status = mRecord.checkTrack(tempRecordTrack.get()); if (status != NO_ERROR) { Loading
services/audioflinger/RecordTracks.h +8 −2 Original line number Diff line number Diff line Loading @@ -87,6 +87,10 @@ public: && (flags & AUDIO_INPUT_FLAG_HW_AV_SYNC) == 0; } using SinkMetadatas = std::vector<record_track_metadata_v7_t>; using MetadataInserter = std::back_insert_iterator<SinkMetadatas>; virtual void copyMetadataTo(MetadataInserter& backInserter) const; private: friend class AudioFlinger; // for mState Loading Loading @@ -134,7 +138,8 @@ public: void *buffer, size_t bufferSize, audio_input_flags_t flags, const Timeout& timeout = {}); const Timeout& timeout = {}, audio_source_t source = AUDIO_SOURCE_DEFAULT); virtual ~PatchRecord(); virtual Source* getSource() { return nullptr; } Loading Loading @@ -166,7 +171,8 @@ public: audio_channel_mask_t channelMask, audio_format_t format, size_t frameCount, audio_input_flags_t flags); audio_input_flags_t flags, audio_source_t source = AUDIO_SOURCE_DEFAULT); Source* getSource() override { return static_cast<Source*>(this); } Loading
services/audioflinger/Threads.cpp +2 −14 Original line number Diff line number Diff line Loading @@ -8775,21 +8775,9 @@ void AudioFlinger::RecordThread::updateMetadata_l() return; // nothing to do } StreamInHalInterface::SinkMetadata metadata; auto backInserter = std::back_inserter(metadata.tracks); for (const sp<RecordTrack> &track : mActiveTracks) { // Do not forward PatchRecord metadata to audio HAL if (track->isPatchTrack()) { continue; } // No track is invalid as this is called after prepareTrack_l in the same critical section 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); track->copyMetadataTo(backInserter); } mInput->stream->updateSinkMetadata(metadata); } Loading
services/audioflinger/Tracks.cpp +26 −7 Original line number Diff line number Diff line Loading @@ -1480,7 +1480,7 @@ void AudioFlinger::PlaybackThread::Track::copyMetadataTo(MetadataInserter& backI } } metadata.channel_mask = mChannelMask, metadata.channel_mask = mChannelMask; strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE); *backInserter++ = metadata; } Loading Loading @@ -2024,7 +2024,6 @@ ssize_t AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t fr { Buffer *pInBuffer; Buffer inBuffer; bool outputBufferFull = false; inBuffer.frameCount = frames; inBuffer.raw = data; Loading Loading @@ -2054,7 +2053,6 @@ ssize_t AudioFlinger::PlaybackThread::OutputTrack::write(void* data, uint32_t fr ALOGV("%s(%d): thread %d no more output buffers; status %d", __func__, mId, (int)mThreadIoHandle, status); outputBufferFull = true; break; } uint32_t waitTimeMs = (uint32_t)ns2ms(systemTime() - startTime); Loading Loading @@ -2750,6 +2748,25 @@ status_t AudioFlinger::RecordThread::RecordTrack::shareAudioHistory( } } void AudioFlinger::RecordThread::RecordTrack::copyMetadataTo(MetadataInserter& backInserter) const { // Do not forward PatchRecord metadata with unspecified audio source if (mAttr.source == AUDIO_SOURCE_DEFAULT) { return; } // No track is invalid as this is called after prepareTrack_l in the same critical section record_track_metadata_v7_t metadata; metadata.base = { .source = mAttr.source, .gain = 1, // capture tracks do not have volumes }; metadata.channel_mask = mChannelMask; strncpy(metadata.tags, mAttr.tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE); *backInserter++ = metadata; } // ---------------------------------------------------------------------------- #undef LOG_TAG Loading @@ -2763,9 +2780,10 @@ AudioFlinger::RecordThread::PatchRecord::PatchRecord(RecordThread *recordThread, void *buffer, size_t bufferSize, audio_input_flags_t flags, const Timeout& timeout) const Timeout& timeout, audio_source_t source) : RecordTrack(recordThread, NULL, audio_attributes_t{} /* currently unused for patch track */, audio_attributes_t{ .source = source } , sampleRate, format, channelMask, frameCount, buffer, bufferSize, AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags, TYPE_PATCH), Loading Loading @@ -2876,9 +2894,10 @@ AudioFlinger::RecordThread::PassthruPatchRecord::PassthruPatchRecord( audio_channel_mask_t channelMask, audio_format_t format, size_t frameCount, audio_input_flags_t flags) audio_input_flags_t flags, audio_source_t source) : PatchRecord(recordThread, sampleRate, channelMask, format, frameCount, nullptr /*buffer*/, 0 /*bufferSize*/, flags), nullptr /*buffer*/, 0 /*bufferSize*/, flags, {} /* timeout */, source), mPatchRecordAudioBufferProvider(*this), mSinkBuffer(allocAligned(32, mFrameCount * mFrameSize)), mStubBuffer(allocAligned(32, mFrameCount * mFrameSize)) Loading
services/audiopolicy/managerdefault/AudioPolicyManager.cpp +5 −3 Original line number Diff line number Diff line Loading @@ -788,7 +788,8 @@ void AudioPolicyManager::connectTelephonyTxAudioSource( ALOGV("%s between source %s and sink %s", __func__, srcDevice->toString().c_str(), sinkDevice->toString().c_str()); auto callTxSourceClientPortId = PolicyAudioPort::getNextUniqueId(); const audio_attributes_t aa = { .source = AUDIO_SOURCE_VOICE_COMMUNICATION }; const auto aa = mEngine->getAttributesForStreamType(AUDIO_STREAM_VOICE_CALL); struct audio_port_config source = {}; srcDevice->toAudioPortConfig(&source); mCallTxSourceClient = new InternalSourceClientDescriptor( Loading Loading @@ -4534,7 +4535,7 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch * // In case of Hw bridge, it is a Work Around. The mixPort used is the one declared // in config XML to reach the sink so that is can be declared as available. audio_io_handle_t output = AUDIO_IO_HANDLE_NONE; sp<SwAudioOutputDescriptor> outputDesc = nullptr; sp<SwAudioOutputDescriptor> outputDesc; if (!sourceDesc->isInternal()) { // take care of dynamic routing for SwOutput selection, audio_attributes_t attributes = sourceDesc->attributes(); Loading Loading @@ -4604,7 +4605,8 @@ status_t AudioPolicyManager::createAudioPatchInternal(const struct audio_patch * audio_port_config srcMixPortConfig = {}; outputDesc->toAudioPortConfig(&srcMixPortConfig, nullptr); // for volume control, we may need a valid stream srcMixPortConfig.ext.mix.usecase.stream = !sourceDesc->isInternal() ? srcMixPortConfig.ext.mix.usecase.stream = (!sourceDesc->isInternal() || isCallTxAudioSource(sourceDesc)) ? mEngine->getStreamTypeForAttributes(sourceDesc->attributes()) : AUDIO_STREAM_PATCH; patchBuilder.addSource(srcMixPortConfig); Loading