mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
audio r_submix: Suggest configuration from the peer am: 3b732895a8 am: de6a93d47d
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2886671 Change-Id: If90ca7bc18bec69a447f1497d9530579aafabd1f Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -29,6 +29,10 @@ class ModuleRemoteSubmix : public Module {
|
|||||||
// IModule interfaces
|
// IModule interfaces
|
||||||
ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
|
ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
|
||||||
ndk::ScopedAStatus setMicMute(bool in_mute) override;
|
ndk::ScopedAStatus setMicMute(bool in_mute) override;
|
||||||
|
ndk::ScopedAStatus setAudioPortConfig(
|
||||||
|
const ::aidl::android::media::audio::common::AudioPortConfig& in_requested,
|
||||||
|
::aidl::android::media::audio::common::AudioPortConfig* out_suggested,
|
||||||
|
bool* _aidl_return) override;
|
||||||
|
|
||||||
// Module interfaces
|
// Module interfaces
|
||||||
ndk::ScopedAStatus createInputStream(
|
ndk::ScopedAStatus createInputStream(
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "core-impl/Stream.h"
|
#include "core-impl/Stream.h"
|
||||||
@@ -56,13 +55,6 @@ class StreamRemoteSubmix : public StreamCommonImpl {
|
|||||||
r_submix::AudioConfig mStreamConfig;
|
r_submix::AudioConfig mStreamConfig;
|
||||||
std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
|
std::shared_ptr<r_submix::SubmixRoute> mCurrentRoute = nullptr;
|
||||||
|
|
||||||
// Mutex lock to protect vector of submix routes, each of these submix routes have their mutex
|
|
||||||
// locks and none of the mutex locks should be taken together.
|
|
||||||
static std::mutex sSubmixRoutesLock;
|
|
||||||
static std::map<::aidl::android::media::audio::common::AudioDeviceAddress,
|
|
||||||
std::shared_ptr<r_submix::SubmixRoute>>
|
|
||||||
sSubmixRoutes GUARDED_BY(sSubmixRoutesLock);
|
|
||||||
|
|
||||||
// limit for number of read error log entries to avoid spamming the logs
|
// limit for number of read error log entries to avoid spamming the logs
|
||||||
static constexpr int kMaxReadErrorLogs = 5;
|
static constexpr int kMaxReadErrorLogs = 5;
|
||||||
// The duration of kMaxReadFailureAttempts * READ_ATTEMPT_SLEEP_MS must be strictly inferior
|
// The duration of kMaxReadFailureAttempts * READ_ATTEMPT_SLEEP_MS must be strictly inferior
|
||||||
|
|||||||
@@ -27,14 +27,36 @@
|
|||||||
|
|
||||||
using aidl::android::hardware::audio::common::SinkMetadata;
|
using aidl::android::hardware::audio::common::SinkMetadata;
|
||||||
using aidl::android::hardware::audio::common::SourceMetadata;
|
using aidl::android::hardware::audio::common::SourceMetadata;
|
||||||
|
using aidl::android::media::audio::common::AudioDeviceAddress;
|
||||||
using aidl::android::media::audio::common::AudioFormatType;
|
using aidl::android::media::audio::common::AudioFormatType;
|
||||||
|
using aidl::android::media::audio::common::AudioIoFlags;
|
||||||
using aidl::android::media::audio::common::AudioOffloadInfo;
|
using aidl::android::media::audio::common::AudioOffloadInfo;
|
||||||
using aidl::android::media::audio::common::AudioPort;
|
using aidl::android::media::audio::common::AudioPort;
|
||||||
using aidl::android::media::audio::common::AudioPortConfig;
|
using aidl::android::media::audio::common::AudioPortConfig;
|
||||||
|
using aidl::android::media::audio::common::AudioPortExt;
|
||||||
|
using aidl::android::media::audio::common::AudioProfile;
|
||||||
|
using aidl::android::media::audio::common::Int;
|
||||||
using aidl::android::media::audio::common::MicrophoneInfo;
|
using aidl::android::media::audio::common::MicrophoneInfo;
|
||||||
|
|
||||||
namespace aidl::android::hardware::audio::core {
|
namespace aidl::android::hardware::audio::core {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
std::optional<r_submix::AudioConfig> getRemoteEndConfig(const AudioPort& audioPort) {
|
||||||
|
const auto& deviceAddress = audioPort.ext.get<AudioPortExt::device>().device.address;
|
||||||
|
const bool isInput = audioPort.flags.getTag() == AudioIoFlags::input;
|
||||||
|
if (auto submixRoute = r_submix::SubmixRoute::findRoute(deviceAddress);
|
||||||
|
submixRoute != nullptr) {
|
||||||
|
if ((isInput && submixRoute->isStreamOutOpen()) ||
|
||||||
|
(!isInput && submixRoute->isStreamInOpen())) {
|
||||||
|
return submixRoute->getPipeConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
ndk::ScopedAStatus ModuleRemoteSubmix::getMicMute(bool* _aidl_return __unused) {
|
ndk::ScopedAStatus ModuleRemoteSubmix::getMicMute(bool* _aidl_return __unused) {
|
||||||
LOG(DEBUG) << __func__ << ": is not supported";
|
LOG(DEBUG) << __func__ << ": is not supported";
|
||||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
@@ -45,6 +67,26 @@ ndk::ScopedAStatus ModuleRemoteSubmix::setMicMute(bool in_mute __unused) {
|
|||||||
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ndk::ScopedAStatus ModuleRemoteSubmix::setAudioPortConfig(const AudioPortConfig& in_requested,
|
||||||
|
AudioPortConfig* out_suggested,
|
||||||
|
bool* _aidl_return) {
|
||||||
|
auto fillConfig = [this](const AudioPort& port, AudioPortConfig* config) {
|
||||||
|
if (port.ext.getTag() == AudioPortExt::device) {
|
||||||
|
if (auto pipeConfig = getRemoteEndConfig(port); pipeConfig.has_value()) {
|
||||||
|
LOG(DEBUG) << "setAudioPortConfig: suggesting port config from the remote end.";
|
||||||
|
config->format = pipeConfig->format;
|
||||||
|
config->channelMask = pipeConfig->channelLayout;
|
||||||
|
config->sampleRate = Int{.value = pipeConfig->sampleRate};
|
||||||
|
config->flags = port.flags;
|
||||||
|
config->ext = port.ext;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return generateDefaultPortConfig(port, config);
|
||||||
|
};
|
||||||
|
return Module::setAudioPortConfigImpl(in_requested, fillConfig, out_suggested, _aidl_return);
|
||||||
|
}
|
||||||
|
|
||||||
ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream(
|
ndk::ScopedAStatus ModuleRemoteSubmix::createInputStream(
|
||||||
StreamContext&& context, const SinkMetadata& sinkMetadata,
|
StreamContext&& context, const SinkMetadata& sinkMetadata,
|
||||||
const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
|
const std::vector<MicrophoneInfo>& microphones, std::shared_ptr<StreamIn>* result) {
|
||||||
@@ -68,7 +110,22 @@ ndk::ScopedAStatus ModuleRemoteSubmix::createOutputStream(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort, int32_t) {
|
ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* audioPort, int32_t) {
|
||||||
// Find the corresponding mix port and copy its profiles.
|
if (audioPort->ext.getTag() != AudioPortExt::device) {
|
||||||
|
LOG(ERROR) << __func__ << ": not a device port: " << audioPort->toString();
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||||
|
}
|
||||||
|
// If there is already a pipe with a stream for the port address, provide its configuration as
|
||||||
|
// the only option. Otherwise, find the corresponding mix port and copy its profiles.
|
||||||
|
if (auto pipeConfig = getRemoteEndConfig(*audioPort); pipeConfig.has_value()) {
|
||||||
|
audioPort->profiles.clear();
|
||||||
|
audioPort->profiles.push_back(AudioProfile{
|
||||||
|
.format = pipeConfig->format,
|
||||||
|
.channelMasks = std::vector<AudioChannelLayout>({pipeConfig->channelLayout}),
|
||||||
|
.sampleRates = std::vector<int>({pipeConfig->sampleRate})});
|
||||||
|
LOG(DEBUG) << __func__ << ": populated from remote end as: " << audioPort->toString();
|
||||||
|
return ndk::ScopedAStatus::ok();
|
||||||
|
}
|
||||||
|
|
||||||
// At this moment, the port has the same ID as the template port, see connectExternalDevice.
|
// At this moment, the port has the same ID as the template port, see connectExternalDevice.
|
||||||
std::vector<AudioRoute*> routes = getAudioRoutesForAudioPortImpl(audioPort->id);
|
std::vector<AudioRoute*> routes = getAudioRoutesForAudioPortImpl(audioPort->id);
|
||||||
if (routes.empty()) {
|
if (routes.empty()) {
|
||||||
@@ -87,6 +144,7 @@ ndk::ScopedAStatus ModuleRemoteSubmix::populateConnectedDevicePort(AudioPort* au
|
|||||||
RETURN_STATUS_IF_ERROR(getAudioPort(route->sinkPortId, &mixPort));
|
RETURN_STATUS_IF_ERROR(getAudioPort(route->sinkPortId, &mixPort));
|
||||||
}
|
}
|
||||||
audioPort->profiles = mixPort.profiles;
|
audioPort->profiles = mixPort.profiles;
|
||||||
|
LOG(DEBUG) << __func__ << ": populated from the mix port as: " << audioPort->toString();
|
||||||
return ndk::ScopedAStatus::ok();
|
return ndk::ScopedAStatus::ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -43,26 +43,10 @@ StreamRemoteSubmix::StreamRemoteSubmix(StreamContext* context, const Metadata& m
|
|||||||
mStreamConfig.sampleRate = context->getSampleRate();
|
mStreamConfig.sampleRate = context->getSampleRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::mutex StreamRemoteSubmix::sSubmixRoutesLock;
|
|
||||||
std::map<AudioDeviceAddress, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::sSubmixRoutes;
|
|
||||||
|
|
||||||
::android::status_t StreamRemoteSubmix::init() {
|
::android::status_t StreamRemoteSubmix::init() {
|
||||||
{
|
mCurrentRoute = SubmixRoute::findOrCreateRoute(mDeviceAddress, mStreamConfig);
|
||||||
std::lock_guard guard(sSubmixRoutesLock);
|
if (mCurrentRoute == nullptr) {
|
||||||
auto routeItr = sSubmixRoutes.find(mDeviceAddress);
|
return ::android::NO_INIT;
|
||||||
if (routeItr != sSubmixRoutes.end()) {
|
|
||||||
mCurrentRoute = routeItr->second;
|
|
||||||
}
|
|
||||||
// If route is not available for this port, add it.
|
|
||||||
if (mCurrentRoute == nullptr) {
|
|
||||||
// Initialize the pipe.
|
|
||||||
mCurrentRoute = std::make_shared<SubmixRoute>();
|
|
||||||
if (::android::OK != mCurrentRoute->createPipe(mStreamConfig)) {
|
|
||||||
LOG(ERROR) << __func__ << ": create pipe failed";
|
|
||||||
return ::android::NO_INIT;
|
|
||||||
}
|
|
||||||
sSubmixRoutes.emplace(mDeviceAddress, mCurrentRoute);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
|
if (!mCurrentRoute->isStreamConfigValid(mIsInput, mStreamConfig)) {
|
||||||
LOG(ERROR) << __func__ << ": invalid stream config";
|
LOG(ERROR) << __func__ << ": invalid stream config";
|
||||||
@@ -80,7 +64,6 @@ std::map<AudioDeviceAddress, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::s
|
|||||||
return ::android::NO_INIT;
|
return ::android::NO_INIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mCurrentRoute->openStream(mIsInput);
|
mCurrentRoute->openStream(mIsInput);
|
||||||
return ::android::OK;
|
return ::android::OK;
|
||||||
}
|
}
|
||||||
@@ -114,14 +97,7 @@ std::map<AudioDeviceAddress, std::shared_ptr<SubmixRoute>> StreamRemoteSubmix::s
|
|||||||
|
|
||||||
ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
|
ndk::ScopedAStatus StreamRemoteSubmix::prepareToClose() {
|
||||||
if (!mIsInput) {
|
if (!mIsInput) {
|
||||||
std::shared_ptr<SubmixRoute> route = nullptr;
|
std::shared_ptr<SubmixRoute> route = SubmixRoute::findRoute(mDeviceAddress);
|
||||||
{
|
|
||||||
std::lock_guard guard(sSubmixRoutesLock);
|
|
||||||
auto routeItr = sSubmixRoutes.find(mDeviceAddress);
|
|
||||||
if (routeItr != sSubmixRoutes.end()) {
|
|
||||||
route = routeItr->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (route != nullptr) {
|
if (route != nullptr) {
|
||||||
sp<MonoPipe> sink = route->getSink();
|
sp<MonoPipe> sink = route->getSink();
|
||||||
if (sink == nullptr) {
|
if (sink == nullptr) {
|
||||||
@@ -148,9 +124,7 @@ void StreamRemoteSubmix::shutdown() {
|
|||||||
if (!mCurrentRoute->hasAtleastOneStreamOpen()) {
|
if (!mCurrentRoute->hasAtleastOneStreamOpen()) {
|
||||||
mCurrentRoute->releasePipe();
|
mCurrentRoute->releasePipe();
|
||||||
LOG(DEBUG) << __func__ << ": pipe destroyed";
|
LOG(DEBUG) << __func__ << ": pipe destroyed";
|
||||||
|
SubmixRoute::removeRoute(mDeviceAddress);
|
||||||
std::lock_guard guard(sSubmixRoutesLock);
|
|
||||||
sSubmixRoutes.erase(mDeviceAddress);
|
|
||||||
}
|
}
|
||||||
mCurrentRoute.reset();
|
mCurrentRoute.reset();
|
||||||
}
|
}
|
||||||
@@ -201,7 +175,7 @@ long StreamRemoteSubmix::getDelayInUsForFrameCount(size_t frameCount) {
|
|||||||
|
|
||||||
// Calculate the maximum size of the pipe buffer in frames for the specified stream.
|
// Calculate the maximum size of the pipe buffer in frames for the specified stream.
|
||||||
size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
|
size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
|
||||||
auto pipeConfig = mCurrentRoute->mPipeConfig;
|
auto pipeConfig = mCurrentRoute->getPipeConfig();
|
||||||
const size_t maxFrameSize = std::max(mStreamConfig.frameSize, pipeConfig.frameSize);
|
const size_t maxFrameSize = std::max(mStreamConfig.frameSize, pipeConfig.frameSize);
|
||||||
return (pipeConfig.frameCount * pipeConfig.frameSize) / maxFrameSize;
|
return (pipeConfig.frameCount * pipeConfig.frameSize) / maxFrameSize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,9 +23,49 @@
|
|||||||
#include "SubmixRoute.h"
|
#include "SubmixRoute.h"
|
||||||
|
|
||||||
using aidl::android::hardware::audio::common::getChannelCount;
|
using aidl::android::hardware::audio::common::getChannelCount;
|
||||||
|
using aidl::android::media::audio::common::AudioDeviceAddress;
|
||||||
|
|
||||||
namespace aidl::android::hardware::audio::core::r_submix {
|
namespace aidl::android::hardware::audio::core::r_submix {
|
||||||
|
|
||||||
|
// static
|
||||||
|
SubmixRoute::RoutesMonitor SubmixRoute::getRoutes() {
|
||||||
|
static std::mutex submixRoutesLock;
|
||||||
|
static RoutesMap submixRoutes;
|
||||||
|
return RoutesMonitor(submixRoutesLock, submixRoutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::shared_ptr<SubmixRoute> SubmixRoute::findOrCreateRoute(const AudioDeviceAddress& deviceAddress,
|
||||||
|
const AudioConfig& pipeConfig) {
|
||||||
|
auto routes = getRoutes();
|
||||||
|
auto routeItr = routes->find(deviceAddress);
|
||||||
|
if (routeItr != routes->end()) {
|
||||||
|
return routeItr->second;
|
||||||
|
}
|
||||||
|
auto route = std::make_shared<SubmixRoute>();
|
||||||
|
if (::android::OK != route->createPipe(pipeConfig)) {
|
||||||
|
LOG(ERROR) << __func__ << ": create pipe failed";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
routes->emplace(deviceAddress, route);
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
std::shared_ptr<SubmixRoute> SubmixRoute::findRoute(const AudioDeviceAddress& deviceAddress) {
|
||||||
|
auto routes = getRoutes();
|
||||||
|
auto routeItr = routes->find(deviceAddress);
|
||||||
|
if (routeItr != routes->end()) {
|
||||||
|
return routeItr->second;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void SubmixRoute::removeRoute(const AudioDeviceAddress& deviceAddress) {
|
||||||
|
getRoutes()->erase(deviceAddress);
|
||||||
|
}
|
||||||
|
|
||||||
// Verify a submix input or output stream can be opened.
|
// Verify a submix input or output stream can be opened.
|
||||||
bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig& streamConfig) {
|
bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig& streamConfig) {
|
||||||
// If the stream is already open, don't open it again.
|
// If the stream is already open, don't open it again.
|
||||||
@@ -44,6 +84,7 @@ bool SubmixRoute::isStreamConfigValid(bool isInput, const AudioConfig& streamCon
|
|||||||
// Compare this stream config with existing pipe config, returning false if they do *not*
|
// Compare this stream config with existing pipe config, returning false if they do *not*
|
||||||
// match, true otherwise.
|
// match, true otherwise.
|
||||||
bool SubmixRoute::isStreamConfigCompatible(const AudioConfig& streamConfig) {
|
bool SubmixRoute::isStreamConfigCompatible(const AudioConfig& streamConfig) {
|
||||||
|
std::lock_guard guard(mLock);
|
||||||
if (streamConfig.channelLayout != mPipeConfig.channelLayout) {
|
if (streamConfig.channelLayout != mPipeConfig.channelLayout) {
|
||||||
LOG(ERROR) << __func__ << ": channel count mismatch, stream channels = "
|
LOG(ERROR) << __func__ << ": channel count mismatch, stream channels = "
|
||||||
<< streamConfig.channelLayout.toString()
|
<< streamConfig.channelLayout.toString()
|
||||||
@@ -162,17 +203,14 @@ void SubmixRoute::closeStream(bool isInput) {
|
|||||||
LOG(FATAL) << __func__ << ": Negotiation for the source failed, index = " << index;
|
LOG(FATAL) << __func__ << ": Negotiation for the source failed, index = " << index;
|
||||||
return ::android::BAD_INDEX;
|
return ::android::BAD_INDEX;
|
||||||
}
|
}
|
||||||
LOG(VERBOSE) << __func__ << ": created pipe";
|
LOG(VERBOSE) << __func__ << ": Pipe frame size : " << streamConfig.frameSize
|
||||||
|
<< ", pipe frames : " << sink->maxFrames();
|
||||||
mPipeConfig = streamConfig;
|
|
||||||
mPipeConfig.frameCount = sink->maxFrames();
|
|
||||||
|
|
||||||
LOG(VERBOSE) << __func__ << ": Pipe frame size : " << mPipeConfig.frameSize
|
|
||||||
<< ", pipe frames : " << mPipeConfig.frameCount;
|
|
||||||
|
|
||||||
// Save references to the source and sink.
|
// Save references to the source and sink.
|
||||||
{
|
{
|
||||||
std::lock_guard guard(mLock);
|
std::lock_guard guard(mLock);
|
||||||
|
mPipeConfig = streamConfig;
|
||||||
|
mPipeConfig.frameCount = sink->maxFrames();
|
||||||
mSink = std::move(sink);
|
mSink = std::move(sink);
|
||||||
mSource = std::move(source);
|
mSource = std::move(source);
|
||||||
}
|
}
|
||||||
@@ -181,15 +219,15 @@ void SubmixRoute::closeStream(bool isInput) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Release references to the sink and source.
|
// Release references to the sink and source.
|
||||||
void SubmixRoute::releasePipe() {
|
AudioConfig SubmixRoute::releasePipe() {
|
||||||
std::lock_guard guard(mLock);
|
std::lock_guard guard(mLock);
|
||||||
mSink.clear();
|
mSink.clear();
|
||||||
mSource.clear();
|
mSource.clear();
|
||||||
|
return mPipeConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
::android::status_t SubmixRoute::resetPipe() {
|
::android::status_t SubmixRoute::resetPipe() {
|
||||||
releasePipe();
|
return createPipe(releasePipe());
|
||||||
return createPipe(mPipeConfig);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SubmixRoute::standby(bool isInput) {
|
void SubmixRoute::standby(bool isInput) {
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <media/nbaio/MonoPipeReader.h>
|
#include <media/nbaio/MonoPipeReader.h>
|
||||||
|
|
||||||
#include <aidl/android/media/audio/common/AudioChannelLayout.h>
|
#include <aidl/android/media/audio/common/AudioChannelLayout.h>
|
||||||
|
#include <aidl/android/media/audio/common/AudioDeviceAddress.h>
|
||||||
#include <aidl/android/media/audio/common/AudioFormatDescription.h>
|
#include <aidl/android/media/audio/common/AudioFormatDescription.h>
|
||||||
|
|
||||||
using aidl::android::media::audio::common::AudioChannelLayout;
|
using aidl::android::media::audio::common::AudioChannelLayout;
|
||||||
@@ -60,7 +61,13 @@ struct AudioConfig {
|
|||||||
|
|
||||||
class SubmixRoute {
|
class SubmixRoute {
|
||||||
public:
|
public:
|
||||||
AudioConfig mPipeConfig;
|
static std::shared_ptr<SubmixRoute> findOrCreateRoute(
|
||||||
|
const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress,
|
||||||
|
const AudioConfig& pipeConfig);
|
||||||
|
static std::shared_ptr<SubmixRoute> findRoute(
|
||||||
|
const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress);
|
||||||
|
static void removeRoute(
|
||||||
|
const ::aidl::android::media::audio::common::AudioDeviceAddress& deviceAddress);
|
||||||
|
|
||||||
bool isStreamInOpen() {
|
bool isStreamInOpen() {
|
||||||
std::lock_guard guard(mLock);
|
std::lock_guard guard(mLock);
|
||||||
@@ -90,6 +97,10 @@ class SubmixRoute {
|
|||||||
std::lock_guard guard(mLock);
|
std::lock_guard guard(mLock);
|
||||||
return mSource;
|
return mSource;
|
||||||
}
|
}
|
||||||
|
AudioConfig getPipeConfig() {
|
||||||
|
std::lock_guard guard(mLock);
|
||||||
|
return mPipeConfig;
|
||||||
|
}
|
||||||
|
|
||||||
bool isStreamConfigValid(bool isInput, const AudioConfig& streamConfig);
|
bool isStreamConfigValid(bool isInput, const AudioConfig& streamConfig);
|
||||||
void closeStream(bool isInput);
|
void closeStream(bool isInput);
|
||||||
@@ -98,17 +109,31 @@ class SubmixRoute {
|
|||||||
bool hasAtleastOneStreamOpen();
|
bool hasAtleastOneStreamOpen();
|
||||||
int notifyReadError();
|
int notifyReadError();
|
||||||
void openStream(bool isInput);
|
void openStream(bool isInput);
|
||||||
void releasePipe();
|
AudioConfig releasePipe();
|
||||||
::android::status_t resetPipe();
|
::android::status_t resetPipe();
|
||||||
bool shouldBlockWrite();
|
bool shouldBlockWrite();
|
||||||
void standby(bool isInput);
|
void standby(bool isInput);
|
||||||
long updateReadCounterFrames(size_t frameCount);
|
long updateReadCounterFrames(size_t frameCount);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
using RoutesMap = std::map<::aidl::android::media::audio::common::AudioDeviceAddress,
|
||||||
|
std::shared_ptr<r_submix::SubmixRoute>>;
|
||||||
|
class RoutesMonitor {
|
||||||
|
public:
|
||||||
|
RoutesMonitor(std::mutex& mutex, RoutesMap& routes) : mLock(mutex), mRoutes(routes) {}
|
||||||
|
RoutesMap* operator->() { return &mRoutes; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::lock_guard<std::mutex> mLock;
|
||||||
|
RoutesMap& mRoutes;
|
||||||
|
};
|
||||||
|
|
||||||
|
static RoutesMonitor getRoutes();
|
||||||
|
|
||||||
bool isStreamConfigCompatible(const AudioConfig& streamConfig);
|
bool isStreamConfigCompatible(const AudioConfig& streamConfig);
|
||||||
|
|
||||||
std::mutex mLock;
|
std::mutex mLock;
|
||||||
|
AudioConfig mPipeConfig GUARDED_BY(mLock);
|
||||||
bool mStreamInOpen GUARDED_BY(mLock) = false;
|
bool mStreamInOpen GUARDED_BY(mLock) = false;
|
||||||
int mInputRefCount GUARDED_BY(mLock) = 0;
|
int mInputRefCount GUARDED_BY(mLock) = 0;
|
||||||
bool mStreamInStandby GUARDED_BY(mLock) = true;
|
bool mStreamInStandby GUARDED_BY(mLock) = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user