Merge changes from topic "cherrypicker-L47600000963081744:N22400001405878786" into udc-qpr-dev
* changes: audio: Improve testing of point-to-point connections audio: Mitigate double receiving of the "exit" command Audio : Add 3 VTS test cases for remote submix module r_submix : Fix minor issues in AIDL implementation Avoid sub_overflow_minimal in AIDL effects VTS audio: Properly support external device port with static configs Remove unused file EffectWorker.h Remove the limitation of max open streams audio: Make IConfig.getSurroundSound default implementation more robust
This commit is contained in:
commit
03b8dbcf41
13 changed files with 510 additions and 243 deletions
|
@ -27,12 +27,11 @@ using aidl::android::media::audio::common::AudioHalEngineConfig;
|
||||||
|
|
||||||
namespace aidl::android::hardware::audio::core {
|
namespace aidl::android::hardware::audio::core {
|
||||||
ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
|
ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
|
||||||
|
static const auto& func = __func__;
|
||||||
static const SurroundSoundConfig surroundSoundConfig = [this]() {
|
static const SurroundSoundConfig surroundSoundConfig = [this]() {
|
||||||
SurroundSoundConfig surroundCfg;
|
SurroundSoundConfig surroundCfg = mAudioPolicyConverter.getSurroundSoundConfig();
|
||||||
if (mAudioPolicyConverter.getStatus() == ::android::OK) {
|
if (mAudioPolicyConverter.getStatus() != ::android::OK) {
|
||||||
surroundCfg = mAudioPolicyConverter.getSurroundSoundConfig();
|
LOG(WARNING) << func << ": " << mAudioPolicyConverter.getError();
|
||||||
} else {
|
|
||||||
LOG(WARNING) << __func__ << mAudioPolicyConverter.getError();
|
|
||||||
}
|
}
|
||||||
return surroundCfg;
|
return surroundCfg;
|
||||||
}();
|
}();
|
||||||
|
@ -42,21 +41,22 @@ ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_ret
|
||||||
}
|
}
|
||||||
|
|
||||||
ndk::ScopedAStatus Config::getEngineConfig(AudioHalEngineConfig* _aidl_return) {
|
ndk::ScopedAStatus Config::getEngineConfig(AudioHalEngineConfig* _aidl_return) {
|
||||||
|
static const auto& func = __func__;
|
||||||
static const AudioHalEngineConfig returnEngCfg = [this]() {
|
static const AudioHalEngineConfig returnEngCfg = [this]() {
|
||||||
AudioHalEngineConfig engConfig;
|
AudioHalEngineConfig engConfig;
|
||||||
if (mEngConfigConverter.getStatus() == ::android::OK) {
|
if (mEngConfigConverter.getStatus() == ::android::OK) {
|
||||||
engConfig = mEngConfigConverter.getAidlEngineConfig();
|
engConfig = mEngConfigConverter.getAidlEngineConfig();
|
||||||
} else {
|
} else {
|
||||||
LOG(INFO) << __func__ << mEngConfigConverter.getError();
|
LOG(INFO) << func << ": " << mEngConfigConverter.getError();
|
||||||
if (mAudioPolicyConverter.getStatus() == ::android::OK) {
|
if (mAudioPolicyConverter.getStatus() == ::android::OK) {
|
||||||
engConfig = mAudioPolicyConverter.getAidlEngineConfig();
|
engConfig = mAudioPolicyConverter.getAidlEngineConfig();
|
||||||
} else {
|
} else {
|
||||||
LOG(WARNING) << __func__ << mAudioPolicyConverter.getError();
|
LOG(WARNING) << func << ": " << mAudioPolicyConverter.getError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Logging full contents of the config is an overkill, just provide statistics.
|
// Logging full contents of the config is an overkill, just provide statistics.
|
||||||
LOG(DEBUG) << "getEngineConfig: number of strategies parsed: "
|
LOG(DEBUG) << func
|
||||||
<< engConfig.productStrategies.size()
|
<< ": number of strategies parsed: " << engConfig.productStrategies.size()
|
||||||
<< ", default strategy: " << engConfig.defaultProductStrategyId
|
<< ", default strategy: " << engConfig.defaultProductStrategyId
|
||||||
<< ", number of volume groups parsed: " << engConfig.volumeGroups.size();
|
<< ", number of volume groups parsed: " << engConfig.volumeGroups.size();
|
||||||
return engConfig;
|
return engConfig;
|
||||||
|
|
|
@ -230,14 +230,14 @@ std::unique_ptr<Configuration> getPrimaryConfiguration() {
|
||||||
|
|
||||||
AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
|
AudioPort primaryOutMix = createPort(c.nextPortId++, "primary output",
|
||||||
makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
|
makeBitPositionFlagMask(AudioOutputFlags::PRIMARY),
|
||||||
false, createPortMixExt(1, 1));
|
false, createPortMixExt(0, 0));
|
||||||
primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
|
primaryOutMix.profiles.insert(primaryOutMix.profiles.begin(),
|
||||||
standardPcmAudioProfiles.begin(),
|
standardPcmAudioProfiles.begin(),
|
||||||
standardPcmAudioProfiles.end());
|
standardPcmAudioProfiles.end());
|
||||||
c.ports.push_back(primaryOutMix);
|
c.ports.push_back(primaryOutMix);
|
||||||
|
|
||||||
AudioPort primaryInMix =
|
AudioPort primaryInMix =
|
||||||
createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(1, 1));
|
createPort(c.nextPortId++, "primary input", 0, true, createPortMixExt(0, 0));
|
||||||
primaryInMix.profiles.push_back(
|
primaryInMix.profiles.push_back(
|
||||||
createProfile(PcmType::INT_16_BIT,
|
createProfile(PcmType::INT_16_BIT,
|
||||||
{AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
|
{AudioChannelLayout::LAYOUT_MONO, AudioChannelLayout::LAYOUT_STEREO},
|
||||||
|
@ -461,6 +461,10 @@ std::unique_ptr<Configuration> getUsbConfiguration() {
|
||||||
// - no profiles specified
|
// - no profiles specified
|
||||||
// * "Test In", IN_AFE_PROXY
|
// * "Test In", IN_AFE_PROXY
|
||||||
// - no profiles specified
|
// - no profiles specified
|
||||||
|
// * "Wired Headset", OUT_HEADSET
|
||||||
|
// - profile PCM 24-bit; STEREO; 48000
|
||||||
|
// * "Wired Headset Mic", IN_HEADSET
|
||||||
|
// - profile PCM 24-bit; MONO; 48000
|
||||||
//
|
//
|
||||||
// Mix ports:
|
// Mix ports:
|
||||||
// * "test output", 1 max open, 1 max active stream
|
// * "test output", 1 max open, 1 max active stream
|
||||||
|
@ -476,7 +480,8 @@ std::unique_ptr<Configuration> getUsbConfiguration() {
|
||||||
//
|
//
|
||||||
// Routes:
|
// Routes:
|
||||||
// "test output", "test fast output", "test compressed offload" -> "Test Out"
|
// "test output", "test fast output", "test compressed offload" -> "Test Out"
|
||||||
// "Test In" -> "test input"
|
// "test output" -> "Wired Headset"
|
||||||
|
// "Test In", "Wired Headset Mic" -> "test input"
|
||||||
//
|
//
|
||||||
// Initial port configs:
|
// Initial port configs:
|
||||||
// * "Test Out" device port: PCM 24-bit; STEREO; 48000
|
// * "Test Out" device port: PCM 24-bit; STEREO; 48000
|
||||||
|
@ -496,6 +501,14 @@ std::unique_ptr<Configuration> getStubConfiguration() {
|
||||||
AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
|
AudioChannelLayout::LAYOUT_STEREO, 48000, 0, false,
|
||||||
createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0)));
|
createDeviceExt(AudioDeviceType::OUT_AFE_PROXY, 0)));
|
||||||
|
|
||||||
|
AudioPort headsetOutDevice =
|
||||||
|
createPort(c.nextPortId++, "Wired Headset", 0, false,
|
||||||
|
createDeviceExt(AudioDeviceType::OUT_HEADSET, 0,
|
||||||
|
AudioDeviceDescription::CONNECTION_ANALOG));
|
||||||
|
headsetOutDevice.profiles.push_back(
|
||||||
|
createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_STEREO}, {48000}));
|
||||||
|
c.ports.push_back(headsetOutDevice);
|
||||||
|
|
||||||
AudioPort testInDevice = createPort(c.nextPortId++, "Test In", 0, true,
|
AudioPort testInDevice = createPort(c.nextPortId++, "Test In", 0, true,
|
||||||
createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0));
|
createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0));
|
||||||
c.ports.push_back(testInDevice);
|
c.ports.push_back(testInDevice);
|
||||||
|
@ -504,6 +517,14 @@ std::unique_ptr<Configuration> getStubConfiguration() {
|
||||||
AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
|
AudioChannelLayout::LAYOUT_MONO, 48000, 0, true,
|
||||||
createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0)));
|
createDeviceExt(AudioDeviceType::IN_AFE_PROXY, 0)));
|
||||||
|
|
||||||
|
AudioPort headsetInDevice =
|
||||||
|
createPort(c.nextPortId++, "Wired Headset Mic", 0, true,
|
||||||
|
createDeviceExt(AudioDeviceType::IN_HEADSET, 0,
|
||||||
|
AudioDeviceDescription::CONNECTION_ANALOG));
|
||||||
|
headsetInDevice.profiles.push_back(
|
||||||
|
createProfile(PcmType::INT_24_BIT, {AudioChannelLayout::LAYOUT_MONO}, {48000}));
|
||||||
|
c.ports.push_back(headsetInDevice);
|
||||||
|
|
||||||
// Mix ports
|
// Mix ports
|
||||||
|
|
||||||
AudioPort testOutMix =
|
AudioPort testOutMix =
|
||||||
|
@ -549,7 +570,8 @@ std::unique_ptr<Configuration> getStubConfiguration() {
|
||||||
|
|
||||||
c.routes.push_back(
|
c.routes.push_back(
|
||||||
createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
|
createRoute({testOutMix, testFastOutMix, compressedOffloadOutMix}, testOutDevice));
|
||||||
c.routes.push_back(createRoute({testInDevice}, testInMIx));
|
c.routes.push_back(createRoute({testOutMix}, headsetOutDevice));
|
||||||
|
c.routes.push_back(createRoute({testInDevice, headsetInDevice}, testInMIx));
|
||||||
|
|
||||||
c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
|
c.portConfigs.insert(c.portConfigs.end(), c.initialConfigs.begin(), c.initialConfigs.end());
|
||||||
|
|
||||||
|
|
|
@ -454,16 +454,15 @@ ndk::ScopedAStatus Module::connectExternalDevice(const AudioPort& in_templateIdA
|
||||||
LOG(ERROR) << __func__ << ": port id " << templateId << " is not a device port";
|
LOG(ERROR) << __func__ << ": port id " << templateId << " is not a device port";
|
||||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||||
}
|
}
|
||||||
if (!templateIt->profiles.empty()) {
|
|
||||||
LOG(ERROR) << __func__ << ": port id " << templateId
|
|
||||||
<< " does not have dynamic profiles";
|
|
||||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
|
||||||
}
|
|
||||||
auto& templateDevicePort = templateIt->ext.get<AudioPortExt::Tag::device>();
|
auto& templateDevicePort = templateIt->ext.get<AudioPortExt::Tag::device>();
|
||||||
if (templateDevicePort.device.type.connection.empty()) {
|
if (templateDevicePort.device.type.connection.empty()) {
|
||||||
LOG(ERROR) << __func__ << ": port id " << templateId << " is permanently attached";
|
LOG(ERROR) << __func__ << ": port id " << templateId << " is permanently attached";
|
||||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||||
}
|
}
|
||||||
|
if (mConnectedDevicePorts.find(templateId) != mConnectedDevicePorts.end()) {
|
||||||
|
LOG(ERROR) << __func__ << ": port id " << templateId << " is a connected device port";
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||||
|
}
|
||||||
// Postpone id allocation until we ensure that there are no client errors.
|
// Postpone id allocation until we ensure that there are no client errors.
|
||||||
connectedPort = *templateIt;
|
connectedPort = *templateIt;
|
||||||
connectedPort.extraAudioDescriptors = in_templateIdAndAdditionalData.extraAudioDescriptors;
|
connectedPort.extraAudioDescriptors = in_templateIdAndAdditionalData.extraAudioDescriptors;
|
||||||
|
@ -486,19 +485,23 @@ ndk::ScopedAStatus Module::connectExternalDevice(const AudioPort& in_templateIdA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mDebug.simulateDeviceConnections) {
|
|
||||||
RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
|
|
||||||
} else {
|
|
||||||
auto& connectedProfiles = getConfig().connectedProfiles;
|
|
||||||
if (auto connectedProfilesIt = connectedProfiles.find(templateId);
|
|
||||||
connectedProfilesIt != connectedProfiles.end()) {
|
|
||||||
connectedPort.profiles = connectedProfilesIt->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (connectedPort.profiles.empty()) {
|
if (connectedPort.profiles.empty()) {
|
||||||
LOG(ERROR) << "Profiles of a connected port still empty after connecting external device "
|
if (!mDebug.simulateDeviceConnections) {
|
||||||
<< connectedPort.toString();
|
RETURN_STATUS_IF_ERROR(populateConnectedDevicePort(&connectedPort));
|
||||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
} else {
|
||||||
|
auto& connectedProfiles = getConfig().connectedProfiles;
|
||||||
|
if (auto connectedProfilesIt = connectedProfiles.find(templateId);
|
||||||
|
connectedProfilesIt != connectedProfiles.end()) {
|
||||||
|
connectedPort.profiles = connectedProfilesIt->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (connectedPort.profiles.empty()) {
|
||||||
|
LOG(ERROR) << __func__
|
||||||
|
<< ": profiles of a connected port still empty after connecting external "
|
||||||
|
"device "
|
||||||
|
<< connectedPort.toString();
|
||||||
|
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto profile : connectedPort.profiles) {
|
for (auto profile : connectedPort.profiles) {
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#define LOG_TAG "AHAL_Stream"
|
#define LOG_TAG "AHAL_Stream"
|
||||||
#include <android-base/logging.h>
|
#include <android-base/logging.h>
|
||||||
#include <android/binder_ibinder_platform.h>
|
#include <android/binder_ibinder_platform.h>
|
||||||
|
@ -94,6 +96,14 @@ void StreamContext::reset() {
|
||||||
mDataMQ.reset();
|
mDataMQ.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t StreamWorkerCommonLogic::getTid() const {
|
||||||
|
#if defined(__ANDROID__)
|
||||||
|
return pthread_gettid_np(pthread_self());
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
std::string StreamWorkerCommonLogic::init() {
|
std::string StreamWorkerCommonLogic::init() {
|
||||||
if (mContext->getCommandMQ() == nullptr) return "Command MQ is null";
|
if (mContext->getCommandMQ() == nullptr) return "Command MQ is null";
|
||||||
if (mContext->getReplyMQ() == nullptr) return "Reply MQ is null";
|
if (mContext->getReplyMQ() == nullptr) return "Reply MQ is null";
|
||||||
|
@ -164,7 +174,7 @@ StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
|
||||||
switch (command.getTag()) {
|
switch (command.getTag()) {
|
||||||
case Tag::halReservedExit:
|
case Tag::halReservedExit:
|
||||||
if (const int32_t cookie = command.get<Tag::halReservedExit>();
|
if (const int32_t cookie = command.get<Tag::halReservedExit>();
|
||||||
cookie == mContext->getInternalCommandCookie()) {
|
cookie == (mContext->getInternalCommandCookie() ^ getTid())) {
|
||||||
mDriver->shutdown();
|
mDriver->shutdown();
|
||||||
setClosed();
|
setClosed();
|
||||||
// This is an internal command, no need to reply.
|
// This is an internal command, no need to reply.
|
||||||
|
@ -384,7 +394,7 @@ StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
|
||||||
switch (command.getTag()) {
|
switch (command.getTag()) {
|
||||||
case Tag::halReservedExit:
|
case Tag::halReservedExit:
|
||||||
if (const int32_t cookie = command.get<Tag::halReservedExit>();
|
if (const int32_t cookie = command.get<Tag::halReservedExit>();
|
||||||
cookie == mContext->getInternalCommandCookie()) {
|
cookie == (mContext->getInternalCommandCookie() ^ getTid())) {
|
||||||
mDriver->shutdown();
|
mDriver->shutdown();
|
||||||
setClosed();
|
setClosed();
|
||||||
// This is an internal command, no need to reply.
|
// This is an internal command, no need to reply.
|
||||||
|
@ -717,7 +727,7 @@ void StreamCommonImpl::stopWorker() {
|
||||||
if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
|
if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
|
||||||
LOG(DEBUG) << __func__ << ": asking the worker to exit...";
|
LOG(DEBUG) << __func__ << ": asking the worker to exit...";
|
||||||
auto cmd = StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::halReservedExit>(
|
auto cmd = StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::halReservedExit>(
|
||||||
mContext.getInternalCommandCookie());
|
mContext.getInternalCommandCookie() ^ mWorker->getTid());
|
||||||
// Note: never call 'pause' and 'resume' methods of StreamWorker
|
// Note: never call 'pause' and 'resume' methods of StreamWorker
|
||||||
// in the HAL implementation. These methods are to be used by
|
// in the HAL implementation. These methods are to be used by
|
||||||
// the client side only. Preventing the worker loop from running
|
// the client side only. Preventing the worker loop from running
|
||||||
|
|
|
@ -223,6 +223,7 @@ class StreamWorkerCommonLogic : public ::android::hardware::audio::common::Strea
|
||||||
: mContext(context),
|
: mContext(context),
|
||||||
mDriver(driver),
|
mDriver(driver),
|
||||||
mTransientStateDelayMs(context->getTransientStateDelayMs()) {}
|
mTransientStateDelayMs(context->getTransientStateDelayMs()) {}
|
||||||
|
pid_t getTid() const;
|
||||||
std::string init() override;
|
std::string init() override;
|
||||||
void populateReply(StreamDescriptor::Reply* reply, bool isConnected) const;
|
void populateReply(StreamDescriptor::Reply* reply, bool isConnected) const;
|
||||||
void populateReplyWrongState(StreamDescriptor::Reply* reply,
|
void populateReplyWrongState(StreamDescriptor::Reply* reply,
|
||||||
|
|
|
@ -53,10 +53,16 @@ class XmlConverter {
|
||||||
const ::android::status_t& status) {
|
const ::android::status_t& status) {
|
||||||
std::string errorMessage;
|
std::string errorMessage;
|
||||||
if (status != ::android::OK) {
|
if (status != ::android::OK) {
|
||||||
if (!isReadableConfigFile) {
|
if (configFilePath.empty()) {
|
||||||
errorMessage = "Could not read requested config file:" + configFilePath;
|
errorMessage = "No audio configuration files found";
|
||||||
|
} else if (!isReadableConfigFile) {
|
||||||
|
errorMessage = std::string("Could not read requested XML config file: \"")
|
||||||
|
.append(configFilePath)
|
||||||
|
.append("\"");
|
||||||
} else {
|
} else {
|
||||||
errorMessage = "Invalid config file: " + configFilePath;
|
errorMessage = std::string("Invalid XML config file: \"")
|
||||||
|
.append(configFilePath)
|
||||||
|
.append("\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return errorMessage;
|
return errorMessage;
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2022 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#include <algorithm>
|
|
||||||
#include <memory>
|
|
||||||
#include <mutex>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "EffectContext.h"
|
|
||||||
#include "EffectThread.h"
|
|
||||||
|
|
||||||
namespace aidl::android::hardware::audio::effect {
|
|
||||||
|
|
||||||
std::string toString(RetCode& code);
|
|
||||||
|
|
||||||
class EffectWorker : public EffectThread {
|
|
||||||
public:
|
|
||||||
// set effect context for worker, suppose to only happen once here
|
|
||||||
void setContext(std::shared_ptr<EffectContext> context) {
|
|
||||||
std::call_once(mOnceFlag, [&]() { mContext = context; });
|
|
||||||
};
|
|
||||||
|
|
||||||
// handle FMQ and call effect implemented virtual function
|
|
||||||
void process() override {
|
|
||||||
RETURN_VALUE_IF(!mContext, void(), "nullContext");
|
|
||||||
std::shared_ptr<EffectContext::StatusMQ> statusMQ = mContext->getStatusFmq();
|
|
||||||
std::shared_ptr<EffectContext::DataMQ> inputMQ = mContext->getInputDataFmq();
|
|
||||||
std::shared_ptr<EffectContext::DataMQ> outputMQ = mContext->getOutputDataFmq();
|
|
||||||
|
|
||||||
// Only this worker will read from input data MQ and write to output data MQ.
|
|
||||||
auto readSamples = inputMQ->availableToRead(), writeSamples = outputMQ->availableToWrite();
|
|
||||||
if (readSamples && writeSamples) {
|
|
||||||
auto processSamples = std::min(readSamples, writeSamples);
|
|
||||||
LOG(VERBOSE) << __func__ << " available to read " << readSamples
|
|
||||||
<< " available to write " << writeSamples << " process " << processSamples;
|
|
||||||
|
|
||||||
auto buffer = mContext->getWorkBuffer();
|
|
||||||
inputMQ->read(buffer, processSamples);
|
|
||||||
|
|
||||||
IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
|
|
||||||
outputMQ->write(buffer, status.fmqProduced);
|
|
||||||
statusMQ->writeBlocking(&status, 1);
|
|
||||||
LOG(VERBOSE) << __func__ << " done processing, effect consumed " << status.fmqConsumed
|
|
||||||
<< " produced " << status.fmqProduced;
|
|
||||||
} else {
|
|
||||||
// TODO: maybe add some sleep here to avoid busy waiting
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// must implement by each effect implementation
|
|
||||||
// TODO: consider if this interface need adjustment to handle in-place processing
|
|
||||||
virtual IEffect::Status effectProcessImpl(float* in, float* out, int samples) = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// make sure the context only set once.
|
|
||||||
std::once_flag mOnceFlag;
|
|
||||||
std::shared_ptr<EffectContext> mContext;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace aidl::android::hardware::audio::effect
|
|
|
@ -179,7 +179,7 @@ void StreamRemoteSubmix::shutdown() {
|
||||||
LOG(ERROR) << __func__ << ": transfer without a pipe!";
|
LOG(ERROR) << __func__ << ": transfer without a pipe!";
|
||||||
return ::android::UNEXPECTED_NULL;
|
return ::android::UNEXPECTED_NULL;
|
||||||
}
|
}
|
||||||
|
mCurrentRoute->exitStandby(mIsInput);
|
||||||
return (mIsInput ? inRead(buffer, frameCount, actualFrameCount)
|
return (mIsInput ? inRead(buffer, frameCount, actualFrameCount)
|
||||||
: outWrite(buffer, frameCount, actualFrameCount));
|
: outWrite(buffer, frameCount, actualFrameCount));
|
||||||
}
|
}
|
||||||
|
@ -190,17 +190,14 @@ void StreamRemoteSubmix::shutdown() {
|
||||||
return ::android::NO_INIT;
|
return ::android::NO_INIT;
|
||||||
}
|
}
|
||||||
const ssize_t framesInPipe = source->availableToRead();
|
const ssize_t framesInPipe = source->availableToRead();
|
||||||
if (framesInPipe < 0) {
|
if (framesInPipe <= 0) {
|
||||||
return ::android::INVALID_OPERATION;
|
// No need to update the position frames
|
||||||
|
return ::android::OK;
|
||||||
}
|
}
|
||||||
if (mIsInput) {
|
if (mIsInput) {
|
||||||
position->frames += framesInPipe;
|
position->frames += framesInPipe;
|
||||||
} else {
|
} else if (position->frames >= framesInPipe) {
|
||||||
if (position->frames > framesInPipe) {
|
position->frames -= framesInPipe;
|
||||||
position->frames -= framesInPipe;
|
|
||||||
} else {
|
|
||||||
position->frames = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return ::android::OK;
|
return ::android::OK;
|
||||||
}
|
}
|
||||||
|
@ -280,18 +277,14 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
|
||||||
size_t* actualFrameCount) {
|
size_t* actualFrameCount) {
|
||||||
// about to read from audio source
|
// about to read from audio source
|
||||||
sp<MonoPipeReader> source = mCurrentRoute->getSource();
|
sp<MonoPipeReader> source = mCurrentRoute->getSource();
|
||||||
if (source == nullptr || source->availableToRead() == 0) {
|
if (source == nullptr) {
|
||||||
if (source == nullptr) {
|
int readErrorCount = mCurrentRoute->notifyReadError();
|
||||||
int readErrorCount = mCurrentRoute->notifyReadError();
|
if (readErrorCount < kMaxReadErrorLogs) {
|
||||||
if (readErrorCount < kMaxReadErrorLogs) {
|
LOG(ERROR) << __func__
|
||||||
LOG(ERROR) << __func__
|
<< ": no audio pipe yet we're trying to read! (not all errors will be "
|
||||||
<< ": no audio pipe yet we're trying to read! (not all errors will be "
|
"logged)";
|
||||||
"logged)";
|
|
||||||
} else {
|
|
||||||
LOG(ERROR) << __func__ << ": Read errors " << readErrorCount;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LOG(INFO) << __func__ << ": no data to read yet, providing empty data";
|
LOG(ERROR) << __func__ << ": Read errors " << readErrorCount;
|
||||||
}
|
}
|
||||||
const size_t delayUs = static_cast<size_t>(
|
const size_t delayUs = static_cast<size_t>(
|
||||||
std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
|
std::roundf(frameCount * MICROS_PER_SECOND / mStreamConfig.sampleRate));
|
||||||
|
@ -306,9 +299,10 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
|
||||||
const size_t delayUs = static_cast<size_t>(std::roundf(kReadAttemptSleepUs));
|
const size_t delayUs = static_cast<size_t>(std::roundf(kReadAttemptSleepUs));
|
||||||
char* buff = (char*)buffer;
|
char* buff = (char*)buffer;
|
||||||
size_t remainingFrames = frameCount;
|
size_t remainingFrames = frameCount;
|
||||||
|
int availableToRead = source->availableToRead();
|
||||||
|
|
||||||
while ((remainingFrames > 0) && (attempts < kMaxReadFailureAttempts)) {
|
while ((remainingFrames > 0) && (availableToRead > 0) && (attempts < kMaxReadFailureAttempts)) {
|
||||||
LOG(VERBOSE) << __func__ << ": frames available to read " << source->availableToRead();
|
LOG(VERBOSE) << __func__ << ": frames available to read " << availableToRead;
|
||||||
|
|
||||||
ssize_t framesRead = source->read(buff, remainingFrames);
|
ssize_t framesRead = source->read(buff, remainingFrames);
|
||||||
|
|
||||||
|
@ -317,6 +311,7 @@ size_t StreamRemoteSubmix::getStreamPipeSizeInFrames() {
|
||||||
if (framesRead > 0) {
|
if (framesRead > 0) {
|
||||||
remainingFrames -= framesRead;
|
remainingFrames -= framesRead;
|
||||||
buff += framesRead * mStreamConfig.frameSize;
|
buff += framesRead * mStreamConfig.frameSize;
|
||||||
|
availableToRead -= framesRead;
|
||||||
LOG(VERBOSE) << __func__ << ": (attempts = " << attempts << ") got " << framesRead
|
LOG(VERBOSE) << __func__ << ": (attempts = " << attempts << ") got " << framesRead
|
||||||
<< " frames, remaining=" << remainingFrames;
|
<< " frames, remaining=" << remainingFrames;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -250,11 +250,11 @@ class EffectHelper {
|
||||||
maxLimit = std::numeric_limits<S>::max();
|
maxLimit = std::numeric_limits<S>::max();
|
||||||
if (s.size()) {
|
if (s.size()) {
|
||||||
const auto min = *s.begin(), max = *s.rbegin();
|
const auto min = *s.begin(), max = *s.rbegin();
|
||||||
s.insert(min + (max - min) / 2);
|
s.insert((min & max) + ((min ^ max) >> 1));
|
||||||
if (min != minLimit) {
|
if (min > minLimit + 1) {
|
||||||
s.insert(min - 1);
|
s.insert(min - 1);
|
||||||
}
|
}
|
||||||
if (max != maxLimit) {
|
if (max < maxLimit - 1) {
|
||||||
s.insert(max + 1);
|
s.insert(max + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,15 +66,36 @@ std::optional<AudioOffloadInfo> ModuleConfig::generateOffloadInfoIfNeeded(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<aidl::android::media::audio::common::AudioPort>
|
||||||
|
ModuleConfig::getAudioPortsForDeviceTypes(const std::vector<AudioDeviceType>& deviceTypes,
|
||||||
|
const std::string& connection) {
|
||||||
|
return getAudioPortsForDeviceTypes(mPorts, deviceTypes, connection);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> ModuleConfig::getBuiltInMicPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> ModuleConfig::getBuiltInMicPorts(
|
||||||
const std::vector<aidl::android::media::audio::common::AudioPort>& ports) {
|
const std::vector<aidl::android::media::audio::common::AudioPort>& ports) {
|
||||||
|
return getAudioPortsForDeviceTypes(
|
||||||
|
ports, std::vector<AudioDeviceType>{AudioDeviceType::IN_MICROPHONE,
|
||||||
|
AudioDeviceType::IN_MICROPHONE_BACK});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<aidl::android::media::audio::common::AudioPort>
|
||||||
|
ModuleConfig::getAudioPortsForDeviceTypes(
|
||||||
|
const std::vector<aidl::android::media::audio::common::AudioPort>& ports,
|
||||||
|
const std::vector<AudioDeviceType>& deviceTypes, const std::string& connection) {
|
||||||
std::vector<AudioPort> result;
|
std::vector<AudioPort> result;
|
||||||
std::copy_if(ports.begin(), ports.end(), std::back_inserter(result), [](const auto& port) {
|
for (const auto& port : ports) {
|
||||||
const auto type = port.ext.template get<AudioPortExt::Tag::device>().device.type;
|
if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
|
||||||
return type.connection.empty() && (type.type == AudioDeviceType::IN_MICROPHONE ||
|
const auto type = port.ext.get<AudioPortExt::Tag::device>().device.type;
|
||||||
type.type == AudioDeviceType::IN_MICROPHONE_BACK);
|
if (type.connection == connection) {
|
||||||
});
|
for (auto deviceType : deviceTypes) {
|
||||||
|
if (type.type == deviceType) {
|
||||||
|
result.push_back(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,6 +140,31 @@ std::vector<AudioPort> ModuleConfig::getAttachedDevicePorts() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<AudioPort> ModuleConfig::getConnectedExternalDevicePorts() const {
|
||||||
|
std::vector<AudioPort> result;
|
||||||
|
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
|
||||||
|
return mConnectedExternalSinkDevicePorts.count(port.id) != 0 ||
|
||||||
|
mConnectedExternalSourceDevicePorts.count(port.id) != 0;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<int32_t> ModuleConfig::getConnectedSinkDevicePorts() const {
|
||||||
|
std::set<int32_t> result;
|
||||||
|
result.insert(mAttachedSinkDevicePorts.begin(), mAttachedSinkDevicePorts.end());
|
||||||
|
result.insert(mConnectedExternalSinkDevicePorts.begin(),
|
||||||
|
mConnectedExternalSinkDevicePorts.end());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<int32_t> ModuleConfig::getConnectedSourceDevicePorts() const {
|
||||||
|
std::set<int32_t> result;
|
||||||
|
result.insert(mAttachedSourceDevicePorts.begin(), mAttachedSourceDevicePorts.end());
|
||||||
|
result.insert(mConnectedExternalSourceDevicePorts.begin(),
|
||||||
|
mConnectedExternalSourceDevicePorts.end());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getExternalDevicePorts() const {
|
std::vector<AudioPort> ModuleConfig::getExternalDevicePorts() const {
|
||||||
std::vector<AudioPort> result;
|
std::vector<AudioPort> result;
|
||||||
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result),
|
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result),
|
||||||
|
@ -126,76 +172,77 @@ std::vector<AudioPort> ModuleConfig::getExternalDevicePorts() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getInputMixPorts(bool attachedOnly) const {
|
std::vector<AudioPort> ModuleConfig::getInputMixPorts(bool connectedOnly) const {
|
||||||
std::vector<AudioPort> result;
|
std::vector<AudioPort> result;
|
||||||
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
|
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
|
||||||
return port.ext.getTag() == AudioPortExt::Tag::mix &&
|
return port.ext.getTag() == AudioPortExt::Tag::mix &&
|
||||||
port.flags.getTag() == AudioIoFlags::Tag::input &&
|
port.flags.getTag() == AudioIoFlags::Tag::input &&
|
||||||
(!attachedOnly || !getAttachedSourceDevicesPortsForMixPort(port).empty());
|
(!connectedOnly || !getConnectedSourceDevicesPortsForMixPort(port).empty());
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getOutputMixPorts(bool attachedOnly) const {
|
std::vector<AudioPort> ModuleConfig::getOutputMixPorts(bool connectedOnly) const {
|
||||||
std::vector<AudioPort> result;
|
std::vector<AudioPort> result;
|
||||||
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
|
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
|
||||||
return port.ext.getTag() == AudioPortExt::Tag::mix &&
|
return port.ext.getTag() == AudioPortExt::Tag::mix &&
|
||||||
port.flags.getTag() == AudioIoFlags::Tag::output &&
|
port.flags.getTag() == AudioIoFlags::Tag::output &&
|
||||||
(!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
|
(!connectedOnly || !getConnectedSinkDevicesPortsForMixPort(port).empty());
|
||||||
});
|
});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getNonBlockingMixPorts(bool attachedOnly,
|
std::vector<AudioPort> ModuleConfig::getNonBlockingMixPorts(bool connectedOnly,
|
||||||
bool singlePort) const {
|
bool singlePort) const {
|
||||||
return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
|
return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
|
||||||
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
|
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
|
||||||
AudioOutputFlags::NON_BLOCKING);
|
AudioOutputFlags::NON_BLOCKING);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool attachedOnly, bool singlePort) const {
|
std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool connectedOnly, bool singlePort) const {
|
||||||
return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
|
return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
|
||||||
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
|
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
|
||||||
AudioOutputFlags::COMPRESS_OFFLOAD);
|
AudioOutputFlags::COMPRESS_OFFLOAD);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getPrimaryMixPorts(bool attachedOnly, bool singlePort) const {
|
std::vector<AudioPort> ModuleConfig::getPrimaryMixPorts(bool connectedOnly, bool singlePort) const {
|
||||||
return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
|
return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
|
||||||
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
|
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
|
||||||
AudioOutputFlags::PRIMARY);
|
AudioOutputFlags::PRIMARY);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getMmapOutMixPorts(bool attachedOnly, bool singlePort) const {
|
std::vector<AudioPort> ModuleConfig::getMmapOutMixPorts(bool connectedOnly, bool singlePort) const {
|
||||||
return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
|
return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
|
||||||
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
|
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
|
||||||
AudioOutputFlags::MMAP_NOIRQ);
|
AudioOutputFlags::MMAP_NOIRQ);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getMmapInMixPorts(bool attachedOnly, bool singlePort) const {
|
std::vector<AudioPort> ModuleConfig::getMmapInMixPorts(bool connectedOnly, bool singlePort) const {
|
||||||
return findMixPorts(true /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
|
return findMixPorts(true /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
|
||||||
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::input>(),
|
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::input>(),
|
||||||
AudioInputFlags::MMAP_NOIRQ);
|
AudioInputFlags::MMAP_NOIRQ);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getAttachedDevicesPortsForMixPort(
|
std::vector<AudioPort> ModuleConfig::getConnectedDevicesPortsForMixPort(
|
||||||
bool isInput, const AudioPortConfig& mixPortConfig) const {
|
bool isInput, const AudioPortConfig& mixPortConfig) const {
|
||||||
const auto mixPortIt = findById<AudioPort>(mPorts, mixPortConfig.portId);
|
const auto mixPortIt = findById<AudioPort>(mPorts, mixPortConfig.portId);
|
||||||
if (mixPortIt != mPorts.end()) {
|
if (mixPortIt != mPorts.end()) {
|
||||||
return getAttachedDevicesPortsForMixPort(isInput, *mixPortIt);
|
return getConnectedDevicesPortsForMixPort(isInput, *mixPortIt);
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getAttachedSinkDevicesPortsForMixPort(
|
std::vector<AudioPort> ModuleConfig::getConnectedSinkDevicesPortsForMixPort(
|
||||||
const AudioPort& mixPort) const {
|
const AudioPort& mixPort) const {
|
||||||
std::vector<AudioPort> result;
|
std::vector<AudioPort> result;
|
||||||
|
std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
|
||||||
for (const auto& route : mRoutes) {
|
for (const auto& route : mRoutes) {
|
||||||
if (mAttachedSinkDevicePorts.count(route.sinkPortId) != 0 &&
|
if ((connectedSinkDevicePorts.count(route.sinkPortId) != 0) &&
|
||||||
std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(), mixPort.id) !=
|
std::find(route.sourcePortIds.begin(), route.sourcePortIds.end(), mixPort.id) !=
|
||||||
route.sourcePortIds.end()) {
|
route.sourcePortIds.end()) {
|
||||||
const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
||||||
|
@ -205,13 +252,14 @@ std::vector<AudioPort> ModuleConfig::getAttachedSinkDevicesPortsForMixPort(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::getAttachedSourceDevicesPortsForMixPort(
|
std::vector<AudioPort> ModuleConfig::getConnectedSourceDevicesPortsForMixPort(
|
||||||
const AudioPort& mixPort) const {
|
const AudioPort& mixPort) const {
|
||||||
std::vector<AudioPort> result;
|
std::vector<AudioPort> result;
|
||||||
|
std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
|
||||||
for (const auto& route : mRoutes) {
|
for (const auto& route : mRoutes) {
|
||||||
if (route.sinkPortId == mixPort.id) {
|
if (route.sinkPortId == mixPort.id) {
|
||||||
for (const auto srcId : route.sourcePortIds) {
|
for (const auto srcId : route.sourcePortIds) {
|
||||||
if (mAttachedSourceDevicePorts.count(srcId) != 0) {
|
if (connectedSourceDevicePorts.count(srcId) != 0) {
|
||||||
const auto devicePortIt = findById<AudioPort>(mPorts, srcId);
|
const auto devicePortIt = findById<AudioPort>(mPorts, srcId);
|
||||||
if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
|
if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
|
||||||
}
|
}
|
||||||
|
@ -221,9 +269,10 @@ std::vector<AudioPort> ModuleConfig::getAttachedSourceDevicesPortsForMixPort(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<AudioPort> ModuleConfig::getSourceMixPortForAttachedDevice() const {
|
std::optional<AudioPort> ModuleConfig::getSourceMixPortForConnectedDevice() const {
|
||||||
|
std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
|
||||||
for (const auto& route : mRoutes) {
|
for (const auto& route : mRoutes) {
|
||||||
if (mAttachedSinkDevicePorts.count(route.sinkPortId) != 0) {
|
if (connectedSinkDevicePorts.count(route.sinkPortId) != 0) {
|
||||||
const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
|
const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
|
||||||
if (mixPortIt != mPorts.end()) return *mixPortIt;
|
if (mixPortIt != mPorts.end()) return *mixPortIt;
|
||||||
}
|
}
|
||||||
|
@ -233,7 +282,7 @@ std::optional<AudioPort> ModuleConfig::getSourceMixPortForAttachedDevice() const
|
||||||
|
|
||||||
std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
|
std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
|
||||||
bool isInput) const {
|
bool isInput) const {
|
||||||
const auto mixPorts = getMixPorts(isInput, false /*attachedOnly*/);
|
const auto mixPorts = getMixPorts(isInput, false /*connectedOnly*/);
|
||||||
std::set<std::pair<int32_t, int32_t>> allowedRoutes;
|
std::set<std::pair<int32_t, int32_t>> allowedRoutes;
|
||||||
for (const auto& route : mRoutes) {
|
for (const auto& route : mRoutes) {
|
||||||
for (const auto srcPortId : route.sourcePortIds) {
|
for (const auto srcPortId : route.sourcePortIds) {
|
||||||
|
@ -243,7 +292,8 @@ std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair
|
||||||
auto make_pair = [isInput](auto& device, auto& mix) {
|
auto make_pair = [isInput](auto& device, auto& mix) {
|
||||||
return isInput ? std::make_pair(device, mix) : std::make_pair(mix, device);
|
return isInput ? std::make_pair(device, mix) : std::make_pair(mix, device);
|
||||||
};
|
};
|
||||||
for (const auto portId : isInput ? mAttachedSourceDevicePorts : mAttachedSinkDevicePorts) {
|
for (const auto portId :
|
||||||
|
isInput ? getConnectedSourceDevicePorts() : getConnectedSinkDevicePorts()) {
|
||||||
const auto devicePortIt = findById<AudioPort>(mPorts, portId);
|
const auto devicePortIt = findById<AudioPort>(mPorts, portId);
|
||||||
if (devicePortIt == mPorts.end()) continue;
|
if (devicePortIt == mPorts.end()) continue;
|
||||||
auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
|
auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
|
||||||
|
@ -262,10 +312,11 @@ std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair
|
||||||
|
|
||||||
std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getRoutableSrcSinkPair(bool isInput) const {
|
std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getRoutableSrcSinkPair(bool isInput) const {
|
||||||
if (isInput) {
|
if (isInput) {
|
||||||
|
std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
|
||||||
for (const auto& route : mRoutes) {
|
for (const auto& route : mRoutes) {
|
||||||
auto srcPortIdIt = std::find_if(
|
auto srcPortIdIt = std::find_if(
|
||||||
route.sourcePortIds.begin(), route.sourcePortIds.end(),
|
route.sourcePortIds.begin(), route.sourcePortIds.end(),
|
||||||
[&](const auto& portId) { return mAttachedSourceDevicePorts.count(portId); });
|
[&](const auto& portId) { return connectedSourceDevicePorts.count(portId); });
|
||||||
if (srcPortIdIt == route.sourcePortIds.end()) continue;
|
if (srcPortIdIt == route.sourcePortIds.end()) continue;
|
||||||
const auto devicePortIt = findById<AudioPort>(mPorts, *srcPortIdIt);
|
const auto devicePortIt = findById<AudioPort>(mPorts, *srcPortIdIt);
|
||||||
const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
||||||
|
@ -276,8 +327,9 @@ std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getRoutableSrcSinkPair(bo
|
||||||
return std::make_pair(devicePortConfig, mixPortConfig.value());
|
return std::make_pair(devicePortConfig, mixPortConfig.value());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
|
||||||
for (const auto& route : mRoutes) {
|
for (const auto& route : mRoutes) {
|
||||||
if (mAttachedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
|
if (connectedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
|
||||||
const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
|
const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
|
||||||
const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
||||||
if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
|
if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
|
||||||
|
@ -293,11 +345,12 @@ std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getRoutableSrcSinkPair(bo
|
||||||
std::vector<ModuleConfig::SrcSinkGroup> ModuleConfig::getRoutableSrcSinkGroups(bool isInput) const {
|
std::vector<ModuleConfig::SrcSinkGroup> ModuleConfig::getRoutableSrcSinkGroups(bool isInput) const {
|
||||||
std::vector<SrcSinkGroup> result;
|
std::vector<SrcSinkGroup> result;
|
||||||
if (isInput) {
|
if (isInput) {
|
||||||
|
std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
|
||||||
for (const auto& route : mRoutes) {
|
for (const auto& route : mRoutes) {
|
||||||
std::vector<int32_t> srcPortIds;
|
std::vector<int32_t> srcPortIds;
|
||||||
std::copy_if(route.sourcePortIds.begin(), route.sourcePortIds.end(),
|
std::copy_if(route.sourcePortIds.begin(), route.sourcePortIds.end(),
|
||||||
std::back_inserter(srcPortIds), [&](const auto& portId) {
|
std::back_inserter(srcPortIds), [&](const auto& portId) {
|
||||||
return mAttachedSourceDevicePorts.count(portId);
|
return connectedSourceDevicePorts.count(portId);
|
||||||
});
|
});
|
||||||
if (srcPortIds.empty()) continue;
|
if (srcPortIds.empty()) continue;
|
||||||
const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
||||||
|
@ -317,8 +370,9 @@ std::vector<ModuleConfig::SrcSinkGroup> ModuleConfig::getRoutableSrcSinkGroups(b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
|
||||||
for (const auto& route : mRoutes) {
|
for (const auto& route : mRoutes) {
|
||||||
if (mAttachedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
|
if (connectedSinkDevicePorts.count(route.sinkPortId) == 0) continue;
|
||||||
const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
|
||||||
if (devicePortIt == mPorts.end()) continue;
|
if (devicePortIt == mPorts.end()) continue;
|
||||||
auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
|
auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
|
||||||
|
@ -352,6 +406,8 @@ std::string ModuleConfig::toString() const {
|
||||||
result.append(android::internal::ToString(mAttachedSourceDevicePorts));
|
result.append(android::internal::ToString(mAttachedSourceDevicePorts));
|
||||||
result.append("\nExternal device ports: ");
|
result.append("\nExternal device ports: ");
|
||||||
result.append(android::internal::ToString(mExternalDevicePorts));
|
result.append(android::internal::ToString(mExternalDevicePorts));
|
||||||
|
result.append("\nConnected external device ports: ");
|
||||||
|
result.append(android::internal::ToString(getConnectedExternalDevicePorts()));
|
||||||
result.append("\nRoutes: ");
|
result.append("\nRoutes: ");
|
||||||
result.append(android::internal::ToString(mRoutes));
|
result.append(android::internal::ToString(mRoutes));
|
||||||
return result;
|
return result;
|
||||||
|
@ -384,10 +440,10 @@ static bool isDynamicProfile(const AudioProfile& profile) {
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<AudioPort> ModuleConfig::findMixPorts(
|
std::vector<AudioPort> ModuleConfig::findMixPorts(
|
||||||
bool isInput, bool attachedOnly, bool singlePort,
|
bool isInput, bool connectedOnly, bool singlePort,
|
||||||
const std::function<bool(const AudioPort&)>& pred) const {
|
const std::function<bool(const AudioPort&)>& pred) const {
|
||||||
std::vector<AudioPort> result;
|
std::vector<AudioPort> result;
|
||||||
const auto mixPorts = getMixPorts(isInput, attachedOnly);
|
const auto mixPorts = getMixPorts(isInput, connectedOnly);
|
||||||
for (auto mixPortIt = mixPorts.begin(); mixPortIt != mixPorts.end();) {
|
for (auto mixPortIt = mixPorts.begin(); mixPortIt != mixPorts.end();) {
|
||||||
mixPortIt = std::find_if(mixPortIt, mixPorts.end(), pred);
|
mixPortIt = std::find_if(mixPortIt, mixPorts.end(), pred);
|
||||||
if (mixPortIt == mixPorts.end()) break;
|
if (mixPortIt == mixPorts.end()) break;
|
||||||
|
@ -401,7 +457,7 @@ std::vector<AudioPortConfig> ModuleConfig::generateAudioMixPortConfigs(
|
||||||
const std::vector<AudioPort>& ports, bool isInput, bool singleProfile) const {
|
const std::vector<AudioPort>& ports, bool isInput, bool singleProfile) const {
|
||||||
std::vector<AudioPortConfig> result;
|
std::vector<AudioPortConfig> result;
|
||||||
for (const auto& mixPort : ports) {
|
for (const auto& mixPort : ports) {
|
||||||
if (getAttachedDevicesPortsForMixPort(isInput, mixPort).empty()) {
|
if (getConnectedDevicesPortsForMixPort(isInput, mixPort).empty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (const auto& profile : mixPort.profiles) {
|
for (const auto& profile : mixPort.profiles) {
|
||||||
|
@ -443,10 +499,48 @@ std::vector<AudioPortConfig> ModuleConfig::generateAudioDevicePortConfigs(
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ndk::ScopedAStatus& ModuleConfig::onExternalDeviceConnected(IModule* module,
|
||||||
|
const AudioPort& port) {
|
||||||
|
// Update ports and routes
|
||||||
|
mStatus = module->getAudioPorts(&mPorts);
|
||||||
|
if (!mStatus.isOk()) return mStatus;
|
||||||
|
mStatus = module->getAudioRoutes(&mRoutes);
|
||||||
|
if (!mStatus.isOk()) return mStatus;
|
||||||
|
|
||||||
|
// Validate port is present in module
|
||||||
|
if (std::find(mPorts.begin(), mPorts.end(), port) == mPorts.end()) {
|
||||||
|
mStatus = ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
|
||||||
|
return mStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (port.flags.getTag() == aidl::android::media::audio::common::AudioIoFlags::Tag::input) {
|
||||||
|
mConnectedExternalSourceDevicePorts.insert(port.id);
|
||||||
|
} else {
|
||||||
|
mConnectedExternalSinkDevicePorts.insert(port.id);
|
||||||
|
}
|
||||||
|
return mStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ndk::ScopedAStatus& ModuleConfig::onExternalDeviceDisconnected(IModule* module,
|
||||||
|
const AudioPort& port) {
|
||||||
|
// Update ports and routes
|
||||||
|
mStatus = module->getAudioPorts(&mPorts);
|
||||||
|
if (!mStatus.isOk()) return mStatus;
|
||||||
|
mStatus = module->getAudioRoutes(&mRoutes);
|
||||||
|
if (!mStatus.isOk()) return mStatus;
|
||||||
|
|
||||||
|
if (port.flags.getTag() == aidl::android::media::audio::common::AudioIoFlags::Tag::input) {
|
||||||
|
mConnectedExternalSourceDevicePorts.erase(port.id);
|
||||||
|
} else {
|
||||||
|
mConnectedExternalSinkDevicePorts.erase(port.id);
|
||||||
|
}
|
||||||
|
return mStatus;
|
||||||
|
}
|
||||||
|
|
||||||
bool ModuleConfig::isMmapSupported() const {
|
bool ModuleConfig::isMmapSupported() const {
|
||||||
const std::vector<AudioPort> mmapOutMixPorts =
|
const std::vector<AudioPort> mmapOutMixPorts =
|
||||||
getMmapOutMixPorts(false /*attachedOnly*/, false /*singlePort*/);
|
getMmapOutMixPorts(false /*connectedOnly*/, false /*singlePort*/);
|
||||||
const std::vector<AudioPort> mmapInMixPorts =
|
const std::vector<AudioPort> mmapInMixPorts =
|
||||||
getMmapInMixPorts(false /*attachedOnly*/, false /*singlePort*/);
|
getMmapInMixPorts(false /*connectedOnly*/, false /*singlePort*/);
|
||||||
return !mmapOutMixPorts.empty() || !mmapInMixPorts.empty();
|
return !mmapOutMixPorts.empty() || !mmapInMixPorts.empty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,14 @@ class ModuleConfig {
|
||||||
static std::optional<aidl::android::media::audio::common::AudioOffloadInfo>
|
static std::optional<aidl::android::media::audio::common::AudioOffloadInfo>
|
||||||
generateOffloadInfoIfNeeded(
|
generateOffloadInfoIfNeeded(
|
||||||
const aidl::android::media::audio::common::AudioPortConfig& portConfig);
|
const aidl::android::media::audio::common::AudioPortConfig& portConfig);
|
||||||
|
|
||||||
|
std::vector<aidl::android::media::audio::common::AudioPort> getAudioPortsForDeviceTypes(
|
||||||
|
const std::vector<aidl::android::media::audio::common::AudioDeviceType>& deviceTypes,
|
||||||
|
const std::string& connection = "");
|
||||||
|
static std::vector<aidl::android::media::audio::common::AudioPort> getAudioPortsForDeviceTypes(
|
||||||
|
const std::vector<aidl::android::media::audio::common::AudioPort>& ports,
|
||||||
|
const std::vector<aidl::android::media::audio::common::AudioDeviceType>& deviceTypes,
|
||||||
|
const std::string& connection = "");
|
||||||
static std::vector<aidl::android::media::audio::common::AudioPort> getBuiltInMicPorts(
|
static std::vector<aidl::android::media::audio::common::AudioPort> getBuiltInMicPorts(
|
||||||
const std::vector<aidl::android::media::audio::common::AudioPort>& ports);
|
const std::vector<aidl::android::media::audio::common::AudioPort>& ports);
|
||||||
|
|
||||||
|
@ -45,45 +53,55 @@ class ModuleConfig {
|
||||||
std::string getError() const { return mStatus.getMessage(); }
|
std::string getError() const { return mStatus.getMessage(); }
|
||||||
|
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicePorts() const;
|
std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicePorts() const;
|
||||||
|
std::vector<aidl::android::media::audio::common::AudioPort> getConnectedExternalDevicePorts()
|
||||||
|
const;
|
||||||
|
std::set<int32_t> getConnectedSinkDevicePorts() const;
|
||||||
|
std::set<int32_t> getConnectedSourceDevicePorts() const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getAttachedMicrophonePorts() const {
|
std::vector<aidl::android::media::audio::common::AudioPort> getAttachedMicrophonePorts() const {
|
||||||
return getBuiltInMicPorts(getAttachedDevicePorts());
|
return getBuiltInMicPorts(getAttachedDevicePorts());
|
||||||
}
|
}
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getExternalDevicePorts() const;
|
std::vector<aidl::android::media::audio::common::AudioPort> getExternalDevicePorts() const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getInputMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> getInputMixPorts(
|
||||||
bool attachedOnly) const;
|
bool connectedOnly /*Permanently attached and connected external devices*/) const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getOutputMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> getOutputMixPorts(
|
||||||
bool attachedOnly) const;
|
bool connectedOnly /*Permanently attached and connected external devices*/) const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> getMixPorts(
|
||||||
bool isInput, bool attachedOnly) const {
|
bool isInput,
|
||||||
return isInput ? getInputMixPorts(attachedOnly) : getOutputMixPorts(attachedOnly);
|
bool connectedOnly /*Permanently attached and connected external devices*/) const {
|
||||||
|
return isInput ? getInputMixPorts(connectedOnly) : getOutputMixPorts(connectedOnly);
|
||||||
}
|
}
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getNonBlockingMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> getNonBlockingMixPorts(
|
||||||
bool attachedOnly, bool singlePort) const;
|
bool connectedOnly /*Permanently attached and connected external devices*/,
|
||||||
|
bool singlePort) const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getOffloadMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> getOffloadMixPorts(
|
||||||
bool attachedOnly, bool singlePort) const;
|
bool connectedOnly /*Permanently attached and connected external devices*/,
|
||||||
|
bool singlePort) const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getPrimaryMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> getPrimaryMixPorts(
|
||||||
bool attachedOnly, bool singlePort) const;
|
bool connectedOnly /*Permanently attached and connected external devices*/,
|
||||||
|
bool singlePort) const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getMmapOutMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> getMmapOutMixPorts(
|
||||||
bool attachedOnly, bool singlePort) const;
|
bool connectedOnly /*Permanently attached and connected external devices*/,
|
||||||
|
bool singlePort) const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getMmapInMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> getMmapInMixPorts(
|
||||||
bool attachedOnly, bool singlePort) const;
|
bool connectedOnly /*Permanently attached and connected external devices*/,
|
||||||
|
bool singlePort) const;
|
||||||
|
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
|
std::vector<aidl::android::media::audio::common::AudioPort> getConnectedDevicesPortsForMixPort(
|
||||||
bool isInput, const aidl::android::media::audio::common::AudioPort& mixPort) const {
|
bool isInput, const aidl::android::media::audio::common::AudioPort& mixPort) const {
|
||||||
return isInput ? getAttachedSourceDevicesPortsForMixPort(mixPort)
|
return isInput ? getConnectedSourceDevicesPortsForMixPort(mixPort)
|
||||||
: getAttachedSinkDevicesPortsForMixPort(mixPort);
|
: getConnectedSinkDevicesPortsForMixPort(mixPort);
|
||||||
}
|
}
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> getAttachedDevicesPortsForMixPort(
|
std::vector<aidl::android::media::audio::common::AudioPort> getConnectedDevicesPortsForMixPort(
|
||||||
bool isInput,
|
bool isInput,
|
||||||
const aidl::android::media::audio::common::AudioPortConfig& mixPortConfig) const;
|
const aidl::android::media::audio::common::AudioPortConfig& mixPortConfig) const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort>
|
std::vector<aidl::android::media::audio::common::AudioPort>
|
||||||
getAttachedSinkDevicesPortsForMixPort(
|
getConnectedSinkDevicesPortsForMixPort(
|
||||||
const aidl::android::media::audio::common::AudioPort& mixPort) const;
|
const aidl::android::media::audio::common::AudioPort& mixPort) const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort>
|
std::vector<aidl::android::media::audio::common::AudioPort>
|
||||||
getAttachedSourceDevicesPortsForMixPort(
|
getConnectedSourceDevicesPortsForMixPort(
|
||||||
const aidl::android::media::audio::common::AudioPort& mixPort) const;
|
const aidl::android::media::audio::common::AudioPort& mixPort) const;
|
||||||
std::optional<aidl::android::media::audio::common::AudioPort>
|
std::optional<aidl::android::media::audio::common::AudioPort>
|
||||||
getSourceMixPortForAttachedDevice() const;
|
getSourceMixPortForConnectedDevice() const;
|
||||||
|
|
||||||
std::optional<SrcSinkPair> getNonRoutableSrcSinkPair(bool isInput) const;
|
std::optional<SrcSinkPair> getNonRoutableSrcSinkPair(bool isInput) const;
|
||||||
std::optional<SrcSinkPair> getRoutableSrcSinkPair(bool isInput) const;
|
std::optional<SrcSinkPair> getRoutableSrcSinkPair(bool isInput) const;
|
||||||
|
@ -96,15 +114,15 @@ class ModuleConfig {
|
||||||
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts()
|
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts()
|
||||||
const {
|
const {
|
||||||
auto inputs =
|
auto inputs =
|
||||||
generateAudioMixPortConfigs(getInputMixPorts(false /*attachedOnly*/), true, false);
|
generateAudioMixPortConfigs(getInputMixPorts(false /*connectedOnly*/), true, false);
|
||||||
auto outputs = generateAudioMixPortConfigs(getOutputMixPorts(false /*attachedOnly*/), false,
|
auto outputs = generateAudioMixPortConfigs(getOutputMixPorts(false /*connectedOnly*/),
|
||||||
false);
|
false, false);
|
||||||
inputs.insert(inputs.end(), outputs.begin(), outputs.end());
|
inputs.insert(inputs.end(), outputs.begin(), outputs.end());
|
||||||
return inputs;
|
return inputs;
|
||||||
}
|
}
|
||||||
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
|
||||||
bool isInput) const {
|
bool isInput) const {
|
||||||
return generateAudioMixPortConfigs(getMixPorts(isInput, false /*attachedOnly*/), isInput,
|
return generateAudioMixPortConfigs(getMixPorts(isInput, false /*connectedOnly*/), isInput,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPortConfig> getPortConfigsForMixPorts(
|
||||||
|
@ -114,7 +132,7 @@ class ModuleConfig {
|
||||||
std::optional<aidl::android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
|
std::optional<aidl::android::media::audio::common::AudioPortConfig> getSingleConfigForMixPort(
|
||||||
bool isInput) const {
|
bool isInput) const {
|
||||||
const auto config = generateAudioMixPortConfigs(
|
const auto config = generateAudioMixPortConfigs(
|
||||||
getMixPorts(isInput, false /*attachedOnly*/), isInput, true);
|
getMixPorts(isInput, false /*connectedOnly*/), isInput, true);
|
||||||
if (!config.empty()) {
|
if (!config.empty()) {
|
||||||
return *config.begin();
|
return *config.begin();
|
||||||
}
|
}
|
||||||
|
@ -139,13 +157,20 @@ class ModuleConfig {
|
||||||
return *config.begin();
|
return *config.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ndk::ScopedAStatus& onExternalDeviceConnected(
|
||||||
|
aidl::android::hardware::audio::core::IModule* module,
|
||||||
|
const aidl::android::media::audio::common::AudioPort& port);
|
||||||
|
const ndk::ScopedAStatus& onExternalDeviceDisconnected(
|
||||||
|
aidl::android::hardware::audio::core::IModule* module,
|
||||||
|
const aidl::android::media::audio::common::AudioPort& port);
|
||||||
|
|
||||||
bool isMmapSupported() const;
|
bool isMmapSupported() const;
|
||||||
|
|
||||||
std::string toString() const;
|
std::string toString() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<aidl::android::media::audio::common::AudioPort> findMixPorts(
|
std::vector<aidl::android::media::audio::common::AudioPort> findMixPorts(
|
||||||
bool isInput, bool attachedOnly, bool singlePort,
|
bool isInput, bool connectedOnly, bool singlePort,
|
||||||
const std::function<bool(const aidl::android::media::audio::common::AudioPort&)>& pred)
|
const std::function<bool(const aidl::android::media::audio::common::AudioPort&)>& pred)
|
||||||
const;
|
const;
|
||||||
std::vector<aidl::android::media::audio::common::AudioPortConfig> generateAudioMixPortConfigs(
|
std::vector<aidl::android::media::audio::common::AudioPortConfig> generateAudioMixPortConfigs(
|
||||||
|
@ -167,5 +192,7 @@ class ModuleConfig {
|
||||||
std::set<int32_t> mAttachedSinkDevicePorts;
|
std::set<int32_t> mAttachedSinkDevicePorts;
|
||||||
std::set<int32_t> mAttachedSourceDevicePorts;
|
std::set<int32_t> mAttachedSourceDevicePorts;
|
||||||
std::set<int32_t> mExternalDevicePorts;
|
std::set<int32_t> mExternalDevicePorts;
|
||||||
|
std::set<int32_t> mConnectedExternalSinkDevicePorts;
|
||||||
|
std::set<int32_t> mConnectedExternalSourceDevicePorts;
|
||||||
std::vector<aidl::android::hardware::audio::core::AudioRoute> mRoutes;
|
std::vector<aidl::android::hardware::audio::core::AudioRoute> mRoutes;
|
||||||
};
|
};
|
||||||
|
|
|
@ -144,28 +144,36 @@ AudioDeviceAddress::Tag suggestDeviceAddressTag(const AudioDeviceDescription& de
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioPort GenerateUniqueDeviceAddress(const AudioPort& port) {
|
AudioPort GenerateUniqueDeviceAddress(const AudioPort& port) {
|
||||||
|
// Point-to-point connections do not use addresses.
|
||||||
|
static const std::set<std::string> kPointToPointConnections = {
|
||||||
|
AudioDeviceDescription::CONNECTION_ANALOG, AudioDeviceDescription::CONNECTION_HDMI,
|
||||||
|
AudioDeviceDescription::CONNECTION_HDMI_ARC,
|
||||||
|
AudioDeviceDescription::CONNECTION_HDMI_EARC, AudioDeviceDescription::CONNECTION_SPDIF};
|
||||||
static int nextId = 0;
|
static int nextId = 0;
|
||||||
using Tag = AudioDeviceAddress::Tag;
|
using Tag = AudioDeviceAddress::Tag;
|
||||||
|
const auto& deviceDescription = port.ext.get<AudioPortExt::Tag::device>().device.type;
|
||||||
AudioDeviceAddress address;
|
AudioDeviceAddress address;
|
||||||
switch (suggestDeviceAddressTag(port.ext.get<AudioPortExt::Tag::device>().device.type)) {
|
if (kPointToPointConnections.count(deviceDescription.connection) == 0) {
|
||||||
case Tag::id:
|
switch (suggestDeviceAddressTag(deviceDescription)) {
|
||||||
address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
|
case Tag::id:
|
||||||
break;
|
address = AudioDeviceAddress::make<Tag::id>(std::to_string(++nextId));
|
||||||
case Tag::mac:
|
break;
|
||||||
address = AudioDeviceAddress::make<Tag::mac>(
|
case Tag::mac:
|
||||||
std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
|
address = AudioDeviceAddress::make<Tag::mac>(
|
||||||
break;
|
std::vector<uint8_t>{1, 2, 3, 4, 5, static_cast<uint8_t>(++nextId & 0xff)});
|
||||||
case Tag::ipv4:
|
break;
|
||||||
address = AudioDeviceAddress::make<Tag::ipv4>(
|
case Tag::ipv4:
|
||||||
std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
|
address = AudioDeviceAddress::make<Tag::ipv4>(
|
||||||
break;
|
std::vector<uint8_t>{192, 168, 0, static_cast<uint8_t>(++nextId & 0xff)});
|
||||||
case Tag::ipv6:
|
break;
|
||||||
address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
|
case Tag::ipv6:
|
||||||
0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
|
address = AudioDeviceAddress::make<Tag::ipv6>(std::vector<int32_t>{
|
||||||
break;
|
0xfc00, 0x0123, 0x4567, 0x89ab, 0xcdef, 0, 0, ++nextId & 0xffff});
|
||||||
case Tag::alsa:
|
break;
|
||||||
address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
|
case Tag::alsa:
|
||||||
break;
|
address = AudioDeviceAddress::make<Tag::alsa>(std::vector<int32_t>{1, ++nextId});
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
AudioPort result = port;
|
AudioPort result = port;
|
||||||
result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
|
result.ext.get<AudioPortExt::Tag::device>().device.address = std::move(address);
|
||||||
|
@ -525,13 +533,21 @@ class WithDevicePortConnectedState {
|
||||||
EXPECT_IS_OK(mModule->disconnectExternalDevice(getId()))
|
EXPECT_IS_OK(mModule->disconnectExternalDevice(getId()))
|
||||||
<< "when disconnecting device port ID " << getId();
|
<< "when disconnecting device port ID " << getId();
|
||||||
}
|
}
|
||||||
|
if (mModuleConfig != nullptr) {
|
||||||
|
EXPECT_IS_OK(mModuleConfig->onExternalDeviceDisconnected(mModule, mConnectedPort))
|
||||||
|
<< "when external device disconnected";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void SetUp(IModule* module) {
|
void SetUp(IModule* module, ModuleConfig* moduleConfig) {
|
||||||
ASSERT_IS_OK(module->connectExternalDevice(mIdAndData, &mConnectedPort))
|
ASSERT_IS_OK(module->connectExternalDevice(mIdAndData, &mConnectedPort))
|
||||||
<< "when connecting device port ID & data " << mIdAndData.toString();
|
<< "when connecting device port ID & data " << mIdAndData.toString();
|
||||||
ASSERT_NE(mIdAndData.id, getId())
|
ASSERT_NE(mIdAndData.id, getId())
|
||||||
<< "ID of the connected port must not be the same as the ID of the template port";
|
<< "ID of the connected port must not be the same as the ID of the template port";
|
||||||
|
ASSERT_NE(moduleConfig, nullptr);
|
||||||
|
ASSERT_IS_OK(moduleConfig->onExternalDeviceConnected(module, mConnectedPort))
|
||||||
|
<< "when external device connected";
|
||||||
mModule = module;
|
mModule = module;
|
||||||
|
mModuleConfig = moduleConfig;
|
||||||
}
|
}
|
||||||
int32_t getId() const { return mConnectedPort.id; }
|
int32_t getId() const { return mConnectedPort.id; }
|
||||||
const AudioPort& get() { return mConnectedPort; }
|
const AudioPort& get() { return mConnectedPort; }
|
||||||
|
@ -539,6 +555,7 @@ class WithDevicePortConnectedState {
|
||||||
private:
|
private:
|
||||||
const AudioPort mIdAndData;
|
const AudioPort mIdAndData;
|
||||||
IModule* mModule = nullptr;
|
IModule* mModule = nullptr;
|
||||||
|
ModuleConfig* mModuleConfig = nullptr;
|
||||||
AudioPort mConnectedPort;
|
AudioPort mConnectedPort;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1379,7 +1396,7 @@ TEST_P(AudioCoreModule, CheckMixPorts) {
|
||||||
<< "At least two mix ports have PRIMARY flag set: " << primaryMixPort.value()
|
<< "At least two mix ports have PRIMARY flag set: " << primaryMixPort.value()
|
||||||
<< " and " << port.id;
|
<< " and " << port.id;
|
||||||
primaryMixPort = port.id;
|
primaryMixPort = port.id;
|
||||||
EXPECT_EQ(1, mixPort.maxOpenStreamCount)
|
EXPECT_GE(mixPort.maxOpenStreamCount, 0)
|
||||||
<< "Primary mix port " << port.id << " can not have maxOpenStreamCount "
|
<< "Primary mix port " << port.id << " can not have maxOpenStreamCount "
|
||||||
<< mixPort.maxOpenStreamCount;
|
<< mixPort.maxOpenStreamCount;
|
||||||
}
|
}
|
||||||
|
@ -1422,7 +1439,7 @@ TEST_P(AudioCoreModule, GetAudioPortWithExternalDevices) {
|
||||||
for (const auto& port : ports) {
|
for (const auto& port : ports) {
|
||||||
AudioPort portWithData = GenerateUniqueDeviceAddress(port);
|
AudioPort portWithData = GenerateUniqueDeviceAddress(port);
|
||||||
WithDevicePortConnectedState portConnected(portWithData);
|
WithDevicePortConnectedState portConnected(portWithData);
|
||||||
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
|
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
|
||||||
const int32_t connectedPortId = portConnected.getId();
|
const int32_t connectedPortId = portConnected.getId();
|
||||||
ASSERT_NE(portWithData.id, connectedPortId);
|
ASSERT_NE(portWithData.id, connectedPortId);
|
||||||
ASSERT_EQ(portWithData.ext.getTag(), portConnected.get().ext.getTag());
|
ASSERT_EQ(portWithData.ext.getTag(), portConnected.get().ext.getTag());
|
||||||
|
@ -1526,7 +1543,7 @@ TEST_P(AudioCoreModule, ResetAudioPortConfigToInitialValue) {
|
||||||
|
|
||||||
TEST_P(AudioCoreModule, SetAudioPortConfigSuggestedConfig) {
|
TEST_P(AudioCoreModule, SetAudioPortConfigSuggestedConfig) {
|
||||||
ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
|
ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
|
||||||
auto srcMixPort = moduleConfig->getSourceMixPortForAttachedDevice();
|
auto srcMixPort = moduleConfig->getSourceMixPortForConnectedDevice();
|
||||||
if (!srcMixPort.has_value()) {
|
if (!srcMixPort.has_value()) {
|
||||||
GTEST_SKIP() << "No mix port for attached output devices";
|
GTEST_SKIP() << "No mix port for attached output devices";
|
||||||
}
|
}
|
||||||
|
@ -1578,7 +1595,7 @@ TEST_P(AudioCoreModule, SetAllExternalDevicePortConfigs) {
|
||||||
}
|
}
|
||||||
for (const auto& port : ports) {
|
for (const auto& port : ports) {
|
||||||
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
|
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
|
||||||
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
|
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
|
||||||
ASSERT_NO_FATAL_FAILURE(
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
ApplyEveryConfig(moduleConfig->getPortConfigsForDevicePort(portConnected.get())));
|
ApplyEveryConfig(moduleConfig->getPortConfigsForDevicePort(portConnected.get())));
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1665,7 @@ TEST_P(AudioCoreModule, TryChangingConnectionSimulationMidway) {
|
||||||
GTEST_SKIP() << "No external devices in the module.";
|
GTEST_SKIP() << "No external devices in the module.";
|
||||||
}
|
}
|
||||||
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(*ports.begin()));
|
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(*ports.begin()));
|
||||||
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
|
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
|
||||||
ModuleDebug midwayDebugChange = debug->flags();
|
ModuleDebug midwayDebugChange = debug->flags();
|
||||||
midwayDebugChange.simulateDeviceConnections = false;
|
midwayDebugChange.simulateDeviceConnections = false;
|
||||||
EXPECT_STATUS(EX_ILLEGAL_STATE, module->setModuleDebug(midwayDebugChange))
|
EXPECT_STATUS(EX_ILLEGAL_STATE, module->setModuleDebug(midwayDebugChange))
|
||||||
|
@ -1703,7 +1720,7 @@ TEST_P(AudioCoreModule, ConnectDisconnectExternalDeviceTwice) {
|
||||||
<< "when disconnecting already disconnected device port ID " << port.id;
|
<< "when disconnecting already disconnected device port ID " << port.id;
|
||||||
AudioPort portWithData = GenerateUniqueDeviceAddress(port);
|
AudioPort portWithData = GenerateUniqueDeviceAddress(port);
|
||||||
WithDevicePortConnectedState portConnected(portWithData);
|
WithDevicePortConnectedState portConnected(portWithData);
|
||||||
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
|
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
|
||||||
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
|
EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
|
||||||
module->connectExternalDevice(portConnected.get(), &ignored))
|
module->connectExternalDevice(portConnected.get(), &ignored))
|
||||||
<< "when trying to connect a connected device port "
|
<< "when trying to connect a connected device port "
|
||||||
|
@ -1725,7 +1742,7 @@ TEST_P(AudioCoreModule, DisconnectExternalDeviceNonResetPortConfig) {
|
||||||
}
|
}
|
||||||
for (const auto& port : ports) {
|
for (const auto& port : ports) {
|
||||||
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
|
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
|
||||||
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
|
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
|
||||||
const auto portConfig = moduleConfig->getSingleConfigForDevicePort(portConnected.get());
|
const auto portConfig = moduleConfig->getSingleConfigForDevicePort(portConnected.get());
|
||||||
{
|
{
|
||||||
WithAudioPortConfig config(portConfig);
|
WithAudioPortConfig config(portConfig);
|
||||||
|
@ -1753,7 +1770,7 @@ TEST_P(AudioCoreModule, ExternalDevicePortRoutes) {
|
||||||
int32_t connectedPortId;
|
int32_t connectedPortId;
|
||||||
{
|
{
|
||||||
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
|
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
|
||||||
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
|
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
|
||||||
connectedPortId = portConnected.getId();
|
connectedPortId = portConnected.getId();
|
||||||
std::vector<AudioRoute> connectedPortRoutes;
|
std::vector<AudioRoute> connectedPortRoutes;
|
||||||
ASSERT_IS_OK(module->getAudioRoutesForAudioPort(connectedPortId, &connectedPortRoutes))
|
ASSERT_IS_OK(module->getAudioRoutesForAudioPort(connectedPortId, &connectedPortRoutes))
|
||||||
|
@ -1794,7 +1811,7 @@ TEST_P(AudioCoreModule, ExternalDeviceMixPortConfigs) {
|
||||||
}
|
}
|
||||||
for (const auto& port : externalDevicePorts) {
|
for (const auto& port : externalDevicePorts) {
|
||||||
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
|
WithDevicePortConnectedState portConnected(GenerateUniqueDeviceAddress(port));
|
||||||
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get()));
|
ASSERT_NO_FATAL_FAILURE(portConnected.SetUp(module.get(), moduleConfig.get()));
|
||||||
std::vector<AudioRoute> routes;
|
std::vector<AudioRoute> routes;
|
||||||
ASSERT_IS_OK(module->getAudioRoutesForAudioPort(portConnected.getId(), &routes));
|
ASSERT_IS_OK(module->getAudioRoutesForAudioPort(portConnected.getId(), &routes));
|
||||||
std::vector<AudioPort> allPorts;
|
std::vector<AudioPort> allPorts;
|
||||||
|
@ -2459,7 +2476,7 @@ class AudioStream : public AudioCoreModule {
|
||||||
|
|
||||||
void OpenOverMaxCount() {
|
void OpenOverMaxCount() {
|
||||||
constexpr bool isInput = IOTraits<Stream>::is_input;
|
constexpr bool isInput = IOTraits<Stream>::is_input;
|
||||||
auto ports = moduleConfig->getMixPorts(isInput, true /*attachedOnly*/);
|
auto ports = moduleConfig->getMixPorts(isInput, true /*connectedOnly*/);
|
||||||
bool hasSingleRun = false;
|
bool hasSingleRun = false;
|
||||||
for (const auto& port : ports) {
|
for (const auto& port : ports) {
|
||||||
const size_t maxStreamCount = port.ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
|
const size_t maxStreamCount = port.ext.get<AudioPortExt::Tag::mix>().maxOpenStreamCount;
|
||||||
|
@ -2580,7 +2597,7 @@ class AudioStream : public AudioCoreModule {
|
||||||
|
|
||||||
void HwGainHwVolume() {
|
void HwGainHwVolume() {
|
||||||
const auto ports =
|
const auto ports =
|
||||||
moduleConfig->getMixPorts(IOTraits<Stream>::is_input, true /*attachedOnly*/);
|
moduleConfig->getMixPorts(IOTraits<Stream>::is_input, true /*connectedOnly*/);
|
||||||
if (ports.empty()) {
|
if (ports.empty()) {
|
||||||
GTEST_SKIP() << "No mix ports";
|
GTEST_SKIP() << "No mix ports";
|
||||||
}
|
}
|
||||||
|
@ -2619,7 +2636,7 @@ class AudioStream : public AudioCoreModule {
|
||||||
// it as an invalid argument, or say that offloaded effects are not supported.
|
// it as an invalid argument, or say that offloaded effects are not supported.
|
||||||
void AddRemoveEffectInvalidArguments() {
|
void AddRemoveEffectInvalidArguments() {
|
||||||
const auto ports =
|
const auto ports =
|
||||||
moduleConfig->getMixPorts(IOTraits<Stream>::is_input, true /*attachedOnly*/);
|
moduleConfig->getMixPorts(IOTraits<Stream>::is_input, true /*connectedOnly*/);
|
||||||
if (ports.empty()) {
|
if (ports.empty()) {
|
||||||
GTEST_SKIP() << "No mix ports";
|
GTEST_SKIP() << "No mix ports";
|
||||||
}
|
}
|
||||||
|
@ -2742,7 +2759,7 @@ TEST_P(AudioStreamIn, ActiveMicrophones) {
|
||||||
if (!status.isOk()) {
|
if (!status.isOk()) {
|
||||||
GTEST_SKIP() << "Microphone info is not supported";
|
GTEST_SKIP() << "Microphone info is not supported";
|
||||||
}
|
}
|
||||||
const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
|
const auto ports = moduleConfig->getInputMixPorts(true /*connectedOnly*/);
|
||||||
if (ports.empty()) {
|
if (ports.empty()) {
|
||||||
GTEST_SKIP() << "No input mix ports for attached devices";
|
GTEST_SKIP() << "No input mix ports for attached devices";
|
||||||
}
|
}
|
||||||
|
@ -2759,7 +2776,7 @@ TEST_P(AudioStreamIn, ActiveMicrophones) {
|
||||||
"non-empty list of active microphones";
|
"non-empty list of active microphones";
|
||||||
}
|
}
|
||||||
if (auto micDevicePorts = ModuleConfig::getBuiltInMicPorts(
|
if (auto micDevicePorts = ModuleConfig::getBuiltInMicPorts(
|
||||||
moduleConfig->getAttachedSourceDevicesPortsForMixPort(port));
|
moduleConfig->getConnectedSourceDevicesPortsForMixPort(port));
|
||||||
!micDevicePorts.empty()) {
|
!micDevicePorts.empty()) {
|
||||||
auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(micDevicePorts[0]);
|
auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(micDevicePorts[0]);
|
||||||
WithAudioPatch patch(true /*isInput*/, stream.getPortConfig(), devicePortConfig);
|
WithAudioPatch patch(true /*isInput*/, stream.getPortConfig(), devicePortConfig);
|
||||||
|
@ -2791,7 +2808,7 @@ TEST_P(AudioStreamIn, ActiveMicrophones) {
|
||||||
|
|
||||||
TEST_P(AudioStreamIn, MicrophoneDirection) {
|
TEST_P(AudioStreamIn, MicrophoneDirection) {
|
||||||
using MD = IStreamIn::MicrophoneDirection;
|
using MD = IStreamIn::MicrophoneDirection;
|
||||||
const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
|
const auto ports = moduleConfig->getInputMixPorts(true /*connectedOnly*/);
|
||||||
if (ports.empty()) {
|
if (ports.empty()) {
|
||||||
GTEST_SKIP() << "No input mix ports for attached devices";
|
GTEST_SKIP() << "No input mix ports for attached devices";
|
||||||
}
|
}
|
||||||
|
@ -2814,7 +2831,7 @@ TEST_P(AudioStreamIn, MicrophoneDirection) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(AudioStreamIn, MicrophoneFieldDimension) {
|
TEST_P(AudioStreamIn, MicrophoneFieldDimension) {
|
||||||
const auto ports = moduleConfig->getInputMixPorts(true /*attachedOnly*/);
|
const auto ports = moduleConfig->getInputMixPorts(true /*connectedOnly*/);
|
||||||
if (ports.empty()) {
|
if (ports.empty()) {
|
||||||
GTEST_SKIP() << "No input mix ports for attached devices";
|
GTEST_SKIP() << "No input mix ports for attached devices";
|
||||||
}
|
}
|
||||||
|
@ -2846,7 +2863,7 @@ TEST_P(AudioStreamIn, MicrophoneFieldDimension) {
|
||||||
|
|
||||||
TEST_P(AudioStreamOut, OpenTwicePrimary) {
|
TEST_P(AudioStreamOut, OpenTwicePrimary) {
|
||||||
const auto mixPorts =
|
const auto mixPorts =
|
||||||
moduleConfig->getPrimaryMixPorts(true /*attachedOnly*/, true /*singlePort*/);
|
moduleConfig->getPrimaryMixPorts(true /*connectedOnly*/, true /*singlePort*/);
|
||||||
if (mixPorts.empty()) {
|
if (mixPorts.empty()) {
|
||||||
GTEST_SKIP() << "No primary mix port which could be routed to attached devices";
|
GTEST_SKIP() << "No primary mix port which could be routed to attached devices";
|
||||||
}
|
}
|
||||||
|
@ -2857,7 +2874,7 @@ TEST_P(AudioStreamOut, OpenTwicePrimary) {
|
||||||
|
|
||||||
TEST_P(AudioStreamOut, RequireOffloadInfo) {
|
TEST_P(AudioStreamOut, RequireOffloadInfo) {
|
||||||
const auto offloadMixPorts =
|
const auto offloadMixPorts =
|
||||||
moduleConfig->getOffloadMixPorts(true /*attachedOnly*/, true /*singlePort*/);
|
moduleConfig->getOffloadMixPorts(true /*connectedOnly*/, true /*singlePort*/);
|
||||||
if (offloadMixPorts.empty()) {
|
if (offloadMixPorts.empty()) {
|
||||||
GTEST_SKIP()
|
GTEST_SKIP()
|
||||||
<< "No mix port for compressed offload that could be routed to attached devices";
|
<< "No mix port for compressed offload that could be routed to attached devices";
|
||||||
|
@ -2879,7 +2896,7 @@ TEST_P(AudioStreamOut, RequireOffloadInfo) {
|
||||||
|
|
||||||
TEST_P(AudioStreamOut, RequireAsyncCallback) {
|
TEST_P(AudioStreamOut, RequireAsyncCallback) {
|
||||||
const auto nonBlockingMixPorts =
|
const auto nonBlockingMixPorts =
|
||||||
moduleConfig->getNonBlockingMixPorts(true /*attachedOnly*/, true /*singlePort*/);
|
moduleConfig->getNonBlockingMixPorts(true /*connectedOnly*/, true /*singlePort*/);
|
||||||
if (nonBlockingMixPorts.empty()) {
|
if (nonBlockingMixPorts.empty()) {
|
||||||
GTEST_SKIP()
|
GTEST_SKIP()
|
||||||
<< "No mix port for non-blocking output that could be routed to attached devices";
|
<< "No mix port for non-blocking output that could be routed to attached devices";
|
||||||
|
@ -2902,7 +2919,7 @@ TEST_P(AudioStreamOut, RequireAsyncCallback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(AudioStreamOut, AudioDescriptionMixLevel) {
|
TEST_P(AudioStreamOut, AudioDescriptionMixLevel) {
|
||||||
const auto ports = moduleConfig->getOutputMixPorts(true /*attachedOnly*/);
|
const auto ports = moduleConfig->getOutputMixPorts(true /*connectedOnly*/);
|
||||||
if (ports.empty()) {
|
if (ports.empty()) {
|
||||||
GTEST_SKIP() << "No output mix ports";
|
GTEST_SKIP() << "No output mix ports";
|
||||||
}
|
}
|
||||||
|
@ -2930,7 +2947,7 @@ TEST_P(AudioStreamOut, AudioDescriptionMixLevel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(AudioStreamOut, DualMonoMode) {
|
TEST_P(AudioStreamOut, DualMonoMode) {
|
||||||
const auto ports = moduleConfig->getOutputMixPorts(true /*attachedOnly*/);
|
const auto ports = moduleConfig->getOutputMixPorts(true /*connectedOnly*/);
|
||||||
if (ports.empty()) {
|
if (ports.empty()) {
|
||||||
GTEST_SKIP() << "No output mix ports";
|
GTEST_SKIP() << "No output mix ports";
|
||||||
}
|
}
|
||||||
|
@ -2954,7 +2971,7 @@ TEST_P(AudioStreamOut, DualMonoMode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(AudioStreamOut, LatencyMode) {
|
TEST_P(AudioStreamOut, LatencyMode) {
|
||||||
const auto ports = moduleConfig->getOutputMixPorts(true /*attachedOnly*/);
|
const auto ports = moduleConfig->getOutputMixPorts(true /*connectedOnly*/);
|
||||||
if (ports.empty()) {
|
if (ports.empty()) {
|
||||||
GTEST_SKIP() << "No output mix ports";
|
GTEST_SKIP() << "No output mix ports";
|
||||||
}
|
}
|
||||||
|
@ -2996,7 +3013,7 @@ TEST_P(AudioStreamOut, LatencyMode) {
|
||||||
TEST_P(AudioStreamOut, PlaybackRate) {
|
TEST_P(AudioStreamOut, PlaybackRate) {
|
||||||
static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
|
static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
|
||||||
const auto offloadMixPorts =
|
const auto offloadMixPorts =
|
||||||
moduleConfig->getOffloadMixPorts(true /*attachedOnly*/, false /*singlePort*/);
|
moduleConfig->getOffloadMixPorts(true /*connectedOnly*/, false /*singlePort*/);
|
||||||
if (offloadMixPorts.empty()) {
|
if (offloadMixPorts.empty()) {
|
||||||
GTEST_SKIP()
|
GTEST_SKIP()
|
||||||
<< "No mix port for compressed offload that could be routed to attached devices";
|
<< "No mix port for compressed offload that could be routed to attached devices";
|
||||||
|
@ -3066,7 +3083,7 @@ TEST_P(AudioStreamOut, PlaybackRate) {
|
||||||
TEST_P(AudioStreamOut, SelectPresentation) {
|
TEST_P(AudioStreamOut, SelectPresentation) {
|
||||||
static const auto kStatuses = {EX_ILLEGAL_ARGUMENT, EX_UNSUPPORTED_OPERATION};
|
static const auto kStatuses = {EX_ILLEGAL_ARGUMENT, EX_UNSUPPORTED_OPERATION};
|
||||||
const auto offloadMixPorts =
|
const auto offloadMixPorts =
|
||||||
moduleConfig->getOffloadMixPorts(true /*attachedOnly*/, false /*singlePort*/);
|
moduleConfig->getOffloadMixPorts(true /*connectedOnly*/, false /*singlePort*/);
|
||||||
if (offloadMixPorts.empty()) {
|
if (offloadMixPorts.empty()) {
|
||||||
GTEST_SKIP()
|
GTEST_SKIP()
|
||||||
<< "No mix port for compressed offload that could be routed to attached devices";
|
<< "No mix port for compressed offload that could be routed to attached devices";
|
||||||
|
@ -3088,7 +3105,7 @@ TEST_P(AudioStreamOut, SelectPresentation) {
|
||||||
|
|
||||||
TEST_P(AudioStreamOut, UpdateOffloadMetadata) {
|
TEST_P(AudioStreamOut, UpdateOffloadMetadata) {
|
||||||
const auto offloadMixPorts =
|
const auto offloadMixPorts =
|
||||||
moduleConfig->getOffloadMixPorts(true /*attachedOnly*/, false /*singlePort*/);
|
moduleConfig->getOffloadMixPorts(true /*connectedOnly*/, false /*singlePort*/);
|
||||||
if (offloadMixPorts.empty()) {
|
if (offloadMixPorts.empty()) {
|
||||||
GTEST_SKIP()
|
GTEST_SKIP()
|
||||||
<< "No mix port for compressed offload that could be routed to attached devices";
|
<< "No mix port for compressed offload that could be routed to attached devices";
|
||||||
|
@ -3301,7 +3318,7 @@ class AudioStreamIo : public AudioCoreModuleBase,
|
||||||
void RunStreamIoCommandsImplSeq1(const AudioPortConfig& portConfig,
|
void RunStreamIoCommandsImplSeq1(const AudioPortConfig& portConfig,
|
||||||
std::shared_ptr<StateSequence> commandsAndStates,
|
std::shared_ptr<StateSequence> commandsAndStates,
|
||||||
bool validatePositionIncrease) {
|
bool validatePositionIncrease) {
|
||||||
auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
|
auto devicePorts = moduleConfig->getConnectedDevicesPortsForMixPort(
|
||||||
IOTraits<Stream>::is_input, portConfig);
|
IOTraits<Stream>::is_input, portConfig);
|
||||||
ASSERT_FALSE(devicePorts.empty());
|
ASSERT_FALSE(devicePorts.empty());
|
||||||
auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
|
auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
|
||||||
|
@ -3341,7 +3358,7 @@ class AudioStreamIo : public AudioCoreModuleBase,
|
||||||
typename IOTraits<Stream>::Worker worker(*stream.getContext(), &driver,
|
typename IOTraits<Stream>::Worker worker(*stream.getContext(), &driver,
|
||||||
stream.getEventReceiver());
|
stream.getEventReceiver());
|
||||||
|
|
||||||
auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
|
auto devicePorts = moduleConfig->getConnectedDevicesPortsForMixPort(
|
||||||
IOTraits<Stream>::is_input, portConfig);
|
IOTraits<Stream>::is_input, portConfig);
|
||||||
ASSERT_FALSE(devicePorts.empty());
|
ASSERT_FALSE(devicePorts.empty());
|
||||||
auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
|
auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
|
||||||
|
@ -4006,6 +4023,172 @@ INSTANTIATE_TEST_SUITE_P(AudioPatchTest, AudioModulePatch,
|
||||||
android::PrintInstanceNameToString);
|
android::PrintInstanceNameToString);
|
||||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModulePatch);
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModulePatch);
|
||||||
|
|
||||||
|
static std::vector<std::string> getRemoteSubmixModuleInstance() {
|
||||||
|
auto instances = android::getAidlHalInstanceNames(IModule::descriptor);
|
||||||
|
for (auto instance : instances) {
|
||||||
|
if (instance.find("r_submix") != std::string::npos)
|
||||||
|
return (std::vector<std::string>{instance});
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
class WithRemoteSubmix {
|
||||||
|
public:
|
||||||
|
WithRemoteSubmix() = default;
|
||||||
|
WithRemoteSubmix(AudioDeviceAddress address) : mAddress(address) {}
|
||||||
|
WithRemoteSubmix(const WithRemoteSubmix&) = delete;
|
||||||
|
WithRemoteSubmix& operator=(const WithRemoteSubmix&) = delete;
|
||||||
|
std::optional<AudioPort> getAudioPort() {
|
||||||
|
AudioDeviceType deviceType = IOTraits<Stream>::is_input ? AudioDeviceType::IN_SUBMIX
|
||||||
|
: AudioDeviceType::OUT_SUBMIX;
|
||||||
|
auto ports = mModuleConfig->getAudioPortsForDeviceTypes(
|
||||||
|
std::vector<AudioDeviceType>{deviceType},
|
||||||
|
AudioDeviceDescription::CONNECTION_VIRTUAL);
|
||||||
|
if (!ports.empty()) return ports.front();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
/* Connect remote submix external device */
|
||||||
|
void SetUpPortConnection() {
|
||||||
|
auto port = getAudioPort();
|
||||||
|
ASSERT_TRUE(port.has_value()) << "Device AudioPort for remote submix not found";
|
||||||
|
if (mAddress.has_value()) {
|
||||||
|
port.value().ext.template get<AudioPortExt::Tag::device>().device.address =
|
||||||
|
mAddress.value();
|
||||||
|
} else {
|
||||||
|
port = GenerateUniqueDeviceAddress(port.value());
|
||||||
|
}
|
||||||
|
mConnectedPort = std::make_unique<WithDevicePortConnectedState>(port.value());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(mConnectedPort->SetUp(mModule, mModuleConfig));
|
||||||
|
}
|
||||||
|
AudioDeviceAddress getAudioDeviceAddress() {
|
||||||
|
if (!mAddress.has_value()) {
|
||||||
|
mAddress = mConnectedPort->get()
|
||||||
|
.ext.template get<AudioPortExt::Tag::device>()
|
||||||
|
.device.address;
|
||||||
|
}
|
||||||
|
return mAddress.value();
|
||||||
|
}
|
||||||
|
/* Get mix port config for stream and setup patch for it. */
|
||||||
|
void SetupPatch() {
|
||||||
|
const auto portConfig =
|
||||||
|
mModuleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
|
||||||
|
if (!portConfig.has_value()) {
|
||||||
|
LOG(DEBUG) << __func__ << ": portConfig not found";
|
||||||
|
mSkipTest = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto devicePortConfig = mModuleConfig->getSingleConfigForDevicePort(mConnectedPort->get());
|
||||||
|
mPatch = std::make_unique<WithAudioPatch>(IOTraits<Stream>::is_input, portConfig.value(),
|
||||||
|
devicePortConfig);
|
||||||
|
ASSERT_NO_FATAL_FAILURE(mPatch->SetUp(mModule));
|
||||||
|
}
|
||||||
|
void SetUp(IModule* module, ModuleConfig* moduleConfig) {
|
||||||
|
mModule = module;
|
||||||
|
mModuleConfig = moduleConfig;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(SetUpPortConnection());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(SetupPatch());
|
||||||
|
if (!mSkipTest) {
|
||||||
|
// open stream
|
||||||
|
mStream = std::make_unique<WithStream<Stream>>(
|
||||||
|
mPatch->getPortConfig(IOTraits<Stream>::is_input));
|
||||||
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
|
mStream->SetUp(mModule, AudioCoreModuleBase::kDefaultBufferSizeFrames));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sendBurstCommands() {
|
||||||
|
const StreamContext* context = mStream->getContext();
|
||||||
|
StreamLogicDefaultDriver driver(makeBurstCommands(true), context->getFrameSizeBytes());
|
||||||
|
typename IOTraits<Stream>::Worker worker(*context, &driver, mStream->getEventReceiver());
|
||||||
|
|
||||||
|
LOG(DEBUG) << __func__ << ": starting worker...";
|
||||||
|
ASSERT_TRUE(worker.start());
|
||||||
|
LOG(DEBUG) << __func__ << ": joining worker...";
|
||||||
|
worker.join();
|
||||||
|
EXPECT_FALSE(worker.hasError()) << worker.getError();
|
||||||
|
EXPECT_EQ("", driver.getUnexpectedStateTransition());
|
||||||
|
if (IOTraits<Stream>::is_input) {
|
||||||
|
EXPECT_TRUE(driver.hasObservablePositionIncrease());
|
||||||
|
}
|
||||||
|
EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
|
||||||
|
}
|
||||||
|
bool skipTest() { return mSkipTest; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool mSkipTest = false;
|
||||||
|
IModule* mModule = nullptr;
|
||||||
|
ModuleConfig* mModuleConfig = nullptr;
|
||||||
|
std::optional<AudioDeviceAddress> mAddress;
|
||||||
|
std::unique_ptr<WithDevicePortConnectedState> mConnectedPort;
|
||||||
|
std::unique_ptr<WithAudioPatch> mPatch;
|
||||||
|
std::unique_ptr<WithStream<Stream>> mStream;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AudioModuleRemoteSubmix : public AudioCoreModule {
|
||||||
|
public:
|
||||||
|
void SetUp() override {
|
||||||
|
ASSERT_NO_FATAL_FAILURE(AudioCoreModule::SetUp());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenNoInput) {
|
||||||
|
// open output stream
|
||||||
|
WithRemoteSubmix<IStreamOut> streamOut;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
|
||||||
|
if (streamOut.skipTest()) {
|
||||||
|
GTEST_SKIP() << "No mix port for attached devices";
|
||||||
|
}
|
||||||
|
// write something to stream
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamOut.sendBurstCommands());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(AudioModuleRemoteSubmix, OutputDoesNotBlockWhenInputStuck) {
|
||||||
|
// open output stream
|
||||||
|
WithRemoteSubmix<IStreamOut> streamOut;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
|
||||||
|
if (streamOut.skipTest()) {
|
||||||
|
GTEST_SKIP() << "No mix port for attached devices";
|
||||||
|
}
|
||||||
|
|
||||||
|
// open input stream
|
||||||
|
WithRemoteSubmix<IStreamIn> streamIn(streamOut.getAudioDeviceAddress());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
|
||||||
|
if (streamIn.skipTest()) {
|
||||||
|
GTEST_SKIP() << "No mix port for attached devices";
|
||||||
|
}
|
||||||
|
|
||||||
|
// write something to stream
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamOut.sendBurstCommands());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(AudioModuleRemoteSubmix, OutputAndInput) {
|
||||||
|
// open output stream
|
||||||
|
WithRemoteSubmix<IStreamOut> streamOut;
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamOut.SetUp(module.get(), moduleConfig.get()));
|
||||||
|
if (streamOut.skipTest()) {
|
||||||
|
GTEST_SKIP() << "No mix port for attached devices";
|
||||||
|
}
|
||||||
|
|
||||||
|
// open input stream
|
||||||
|
WithRemoteSubmix<IStreamIn> streamIn(streamOut.getAudioDeviceAddress());
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamIn.SetUp(module.get(), moduleConfig.get()));
|
||||||
|
if (streamIn.skipTest()) {
|
||||||
|
GTEST_SKIP() << "No mix port for attached devices";
|
||||||
|
}
|
||||||
|
|
||||||
|
// write something to stream
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamOut.sendBurstCommands());
|
||||||
|
// read from input stream
|
||||||
|
ASSERT_NO_FATAL_FAILURE(streamIn.sendBurstCommands());
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(AudioModuleRemoteSubmixTest, AudioModuleRemoteSubmix,
|
||||||
|
::testing::ValuesIn(getRemoteSubmixModuleInstance()));
|
||||||
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioModuleRemoteSubmix);
|
||||||
|
|
||||||
class TestExecutionTracer : public ::testing::EmptyTestEventListener {
|
class TestExecutionTracer : public ::testing::EmptyTestEventListener {
|
||||||
public:
|
public:
|
||||||
void OnTestStart(const ::testing::TestInfo& test_info) override {
|
void OnTestStart(const ::testing::TestInfo& test_info) override {
|
||||||
|
|
|
@ -208,7 +208,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
HapticGeneratorInvalidTest, HapticGeneratorParamTest,
|
HapticGeneratorInvalidTest, HapticGeneratorParamTest,
|
||||||
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
||||||
IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
|
IFactory::descriptor, getEffectTypeUuidHapticGenerator())),
|
||||||
testing::Values(MIN_ID - 1),
|
testing::Values(MIN_ID),
|
||||||
testing::Values(HapticGenerator::VibratorScale::NONE),
|
testing::Values(HapticGenerator::VibratorScale::NONE),
|
||||||
testing::Values(MIN_FLOAT), testing::Values(MIN_FLOAT),
|
testing::Values(MIN_FLOAT), testing::Values(MIN_FLOAT),
|
||||||
testing::Values(MIN_FLOAT)),
|
testing::Values(MIN_FLOAT)),
|
||||||
|
|
Loading…
Reference in a new issue