Audio : Add 3 VTS test cases for remote submix module
1. OutputDoesNotBlockWhenNoInput
2. OutputDoesNotBlockWhenInputStuck
3. OutputAndInput
Bug: 286914845
Test: atest AudioModuleRemoteSubmix
Change-Id: I19a08bf2bf39131a70a867280c758b5ef001c024
diff --git a/audio/aidl/vts/ModuleConfig.cpp b/audio/aidl/vts/ModuleConfig.cpp
index 7213034..8fdb155 100644
--- a/audio/aidl/vts/ModuleConfig.cpp
+++ b/audio/aidl/vts/ModuleConfig.cpp
@@ -66,15 +66,36 @@
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
std::vector<aidl::android::media::audio::common::AudioPort> ModuleConfig::getBuiltInMicPorts(
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::copy_if(ports.begin(), ports.end(), std::back_inserter(result), [](const auto& port) {
- const auto type = port.ext.template get<AudioPortExt::Tag::device>().device.type;
- return type.connection.empty() && (type.type == AudioDeviceType::IN_MICROPHONE ||
- type.type == AudioDeviceType::IN_MICROPHONE_BACK);
- });
+ for (const auto& port : ports) {
+ if (port.ext.getTag() != AudioPortExt::Tag::device) continue;
+ const auto type = port.ext.get<AudioPortExt::Tag::device>().device.type;
+ if (type.connection == connection) {
+ for (auto deviceType : deviceTypes) {
+ if (type.type == deviceType) {
+ result.push_back(port);
+ }
+ }
+ }
+ }
return result;
}
@@ -119,6 +140,31 @@
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> result;
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result),
@@ -126,76 +172,77 @@
return result;
}
-std::vector<AudioPort> ModuleConfig::getInputMixPorts(bool attachedOnly) const {
+std::vector<AudioPort> ModuleConfig::getInputMixPorts(bool connectedOnly) const {
std::vector<AudioPort> result;
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
return port.ext.getTag() == AudioPortExt::Tag::mix &&
port.flags.getTag() == AudioIoFlags::Tag::input &&
- (!attachedOnly || !getAttachedSourceDevicesPortsForMixPort(port).empty());
+ (!connectedOnly || !getConnectedSourceDevicesPortsForMixPort(port).empty());
});
return result;
}
-std::vector<AudioPort> ModuleConfig::getOutputMixPorts(bool attachedOnly) const {
+std::vector<AudioPort> ModuleConfig::getOutputMixPorts(bool connectedOnly) const {
std::vector<AudioPort> result;
std::copy_if(mPorts.begin(), mPorts.end(), std::back_inserter(result), [&](const auto& port) {
return port.ext.getTag() == AudioPortExt::Tag::mix &&
port.flags.getTag() == AudioIoFlags::Tag::output &&
- (!attachedOnly || !getAttachedSinkDevicesPortsForMixPort(port).empty());
+ (!connectedOnly || !getConnectedSinkDevicesPortsForMixPort(port).empty());
});
return result;
}
-std::vector<AudioPort> ModuleConfig::getNonBlockingMixPorts(bool attachedOnly,
+std::vector<AudioPort> ModuleConfig::getNonBlockingMixPorts(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>(),
AudioOutputFlags::NON_BLOCKING);
});
}
-std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool attachedOnly, bool singlePort) const {
- return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
+std::vector<AudioPort> ModuleConfig::getOffloadMixPorts(bool connectedOnly, bool singlePort) const {
+ return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
AudioOutputFlags::COMPRESS_OFFLOAD);
});
}
-std::vector<AudioPort> ModuleConfig::getPrimaryMixPorts(bool attachedOnly, bool singlePort) const {
- return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
+std::vector<AudioPort> ModuleConfig::getPrimaryMixPorts(bool connectedOnly, bool singlePort) const {
+ return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
AudioOutputFlags::PRIMARY);
});
}
-std::vector<AudioPort> ModuleConfig::getMmapOutMixPorts(bool attachedOnly, bool singlePort) const {
- return findMixPorts(false /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
+std::vector<AudioPort> ModuleConfig::getMmapOutMixPorts(bool connectedOnly, bool singlePort) const {
+ return findMixPorts(false /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::output>(),
AudioOutputFlags::MMAP_NOIRQ);
});
}
-std::vector<AudioPort> ModuleConfig::getMmapInMixPorts(bool attachedOnly, bool singlePort) const {
- return findMixPorts(true /*isInput*/, attachedOnly, singlePort, [&](const AudioPort& port) {
+std::vector<AudioPort> ModuleConfig::getMmapInMixPorts(bool connectedOnly, bool singlePort) const {
+ return findMixPorts(true /*isInput*/, connectedOnly, singlePort, [&](const AudioPort& port) {
return isBitPositionFlagSet(port.flags.get<AudioIoFlags::Tag::input>(),
AudioInputFlags::MMAP_NOIRQ);
});
}
-std::vector<AudioPort> ModuleConfig::getAttachedDevicesPortsForMixPort(
+std::vector<AudioPort> ModuleConfig::getConnectedDevicesPortsForMixPort(
bool isInput, const AudioPortConfig& mixPortConfig) const {
const auto mixPortIt = findById<AudioPort>(mPorts, mixPortConfig.portId);
if (mixPortIt != mPorts.end()) {
- return getAttachedDevicesPortsForMixPort(isInput, *mixPortIt);
+ return getConnectedDevicesPortsForMixPort(isInput, *mixPortIt);
}
return {};
}
-std::vector<AudioPort> ModuleConfig::getAttachedSinkDevicesPortsForMixPort(
+std::vector<AudioPort> ModuleConfig::getConnectedSinkDevicesPortsForMixPort(
const AudioPort& mixPort) const {
std::vector<AudioPort> result;
+ std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
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) !=
route.sourcePortIds.end()) {
const auto devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
@@ -205,13 +252,14 @@
return result;
}
-std::vector<AudioPort> ModuleConfig::getAttachedSourceDevicesPortsForMixPort(
+std::vector<AudioPort> ModuleConfig::getConnectedSourceDevicesPortsForMixPort(
const AudioPort& mixPort) const {
std::vector<AudioPort> result;
+ std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
for (const auto& route : mRoutes) {
if (route.sinkPortId == mixPort.id) {
for (const auto srcId : route.sourcePortIds) {
- if (mAttachedSourceDevicePorts.count(srcId) != 0) {
+ if (connectedSourceDevicePorts.count(srcId) != 0) {
const auto devicePortIt = findById<AudioPort>(mPorts, srcId);
if (devicePortIt != mPorts.end()) result.push_back(*devicePortIt);
}
@@ -221,9 +269,10 @@
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) {
- if (mAttachedSinkDevicePorts.count(route.sinkPortId) != 0) {
+ if (connectedSinkDevicePorts.count(route.sinkPortId) != 0) {
const auto mixPortIt = findById<AudioPort>(mPorts, route.sourcePortIds[0]);
if (mixPortIt != mPorts.end()) return *mixPortIt;
}
@@ -233,7 +282,7 @@
std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getNonRoutableSrcSinkPair(
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;
for (const auto& route : mRoutes) {
for (const auto srcPortId : route.sourcePortIds) {
@@ -243,7 +292,8 @@
auto make_pair = [isInput](auto& device, auto& mix) {
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);
if (devicePortIt == mPorts.end()) continue;
auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
@@ -262,10 +312,11 @@
std::optional<ModuleConfig::SrcSinkPair> ModuleConfig::getRoutableSrcSinkPair(bool isInput) const {
if (isInput) {
+ std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
for (const auto& route : mRoutes) {
auto srcPortIdIt = std::find_if(
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;
const auto devicePortIt = findById<AudioPort>(mPorts, *srcPortIdIt);
const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
@@ -276,8 +327,9 @@
return std::make_pair(devicePortConfig, mixPortConfig.value());
}
} else {
+ std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
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 devicePortIt = findById<AudioPort>(mPorts, route.sinkPortId);
if (devicePortIt == mPorts.end() || mixPortIt == mPorts.end()) continue;
@@ -293,11 +345,12 @@
std::vector<ModuleConfig::SrcSinkGroup> ModuleConfig::getRoutableSrcSinkGroups(bool isInput) const {
std::vector<SrcSinkGroup> result;
if (isInput) {
+ std::set<int32_t> connectedSourceDevicePorts = getConnectedSourceDevicePorts();
for (const auto& route : mRoutes) {
std::vector<int32_t> srcPortIds;
std::copy_if(route.sourcePortIds.begin(), route.sourcePortIds.end(),
std::back_inserter(srcPortIds), [&](const auto& portId) {
- return mAttachedSourceDevicePorts.count(portId);
+ return connectedSourceDevicePorts.count(portId);
});
if (srcPortIds.empty()) continue;
const auto mixPortIt = findById<AudioPort>(mPorts, route.sinkPortId);
@@ -317,8 +370,9 @@
}
}
} else {
+ std::set<int32_t> connectedSinkDevicePorts = getConnectedSinkDevicePorts();
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);
if (devicePortIt == mPorts.end()) continue;
auto devicePortConfig = getSingleConfigForDevicePort(*devicePortIt);
@@ -352,6 +406,8 @@
result.append(android::internal::ToString(mAttachedSourceDevicePorts));
result.append("\nExternal device ports: ");
result.append(android::internal::ToString(mExternalDevicePorts));
+ result.append("\nConnected external device ports: ");
+ result.append(android::internal::ToString(getConnectedExternalDevicePorts()));
result.append("\nRoutes: ");
result.append(android::internal::ToString(mRoutes));
return result;
@@ -384,10 +440,10 @@
}
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 {
std::vector<AudioPort> result;
- const auto mixPorts = getMixPorts(isInput, attachedOnly);
+ const auto mixPorts = getMixPorts(isInput, connectedOnly);
for (auto mixPortIt = mixPorts.begin(); mixPortIt != mixPorts.end();) {
mixPortIt = std::find_if(mixPortIt, mixPorts.end(), pred);
if (mixPortIt == mixPorts.end()) break;
@@ -401,7 +457,7 @@
const std::vector<AudioPort>& ports, bool isInput, bool singleProfile) const {
std::vector<AudioPortConfig> result;
for (const auto& mixPort : ports) {
- if (getAttachedDevicesPortsForMixPort(isInput, mixPort).empty()) {
+ if (getConnectedDevicesPortsForMixPort(isInput, mixPort).empty()) {
continue;
}
for (const auto& profile : mixPort.profiles) {
@@ -443,10 +499,48 @@
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 {
const std::vector<AudioPort> mmapOutMixPorts =
- getMmapOutMixPorts(false /*attachedOnly*/, false /*singlePort*/);
+ getMmapOutMixPorts(false /*connectedOnly*/, false /*singlePort*/);
const std::vector<AudioPort> mmapInMixPorts =
- getMmapInMixPorts(false /*attachedOnly*/, false /*singlePort*/);
+ getMmapInMixPorts(false /*connectedOnly*/, false /*singlePort*/);
return !mmapOutMixPorts.empty() || !mmapInMixPorts.empty();
}