Decouple the configuration from the AudioPolicyManager
Promote AudioPolicyConfig to a full class, not just a "view"
on the APM data. This allows separating initialization of
the APM config from the initialization of the APM itself.
Thus, the APM receives a fully initialized config upon
its creation, regardless of the way the config data has been
obtained.
Bug: 205884982
Test: atest audiopolicy_tests
Test: atest audiosystem_tests
Test: atest audio_health_tests
Test: m audiopolicy_fuzzer
(cherry picked from https://android-review.googlesource.com/q/commit:b0fbc1b40ddebb274b7a0bea811440507c357d82)
Merged-In: I334d16e762499a0292540e6abae4e177480d6235
Change-Id: I334d16e762499a0292540e6abae4e177480d6235
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 412ab19..97a1e0d 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -92,11 +92,44 @@
} // namespace
+TEST(AudioPolicyConfigTest, DefaultConfigForTestsIsEmpty) {
+ auto config = AudioPolicyConfig::createWritableForTests();
+ EXPECT_TRUE(config->getSource().empty());
+ EXPECT_TRUE(config->getHwModules().isEmpty());
+ EXPECT_TRUE(config->getInputDevices().isEmpty());
+ EXPECT_TRUE(config->getOutputDevices().isEmpty());
+}
+
+TEST(AudioPolicyConfigTest, FallbackToDefault) {
+ auto config = AudioPolicyConfig::loadFromApmXmlConfigWithFallback(
+ base::GetExecutableDirectory() + "/test_invalid_audio_policy_configuration.xml");
+ EXPECT_EQ(AudioPolicyConfig::kDefaultConfigSource, config->getSource());
+}
+
+TEST(AudioPolicyConfigTest, LoadForTests) {
+ {
+ auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(
+ base::GetExecutableDirectory() + "/test_invalid_audio_policy_configuration.xml");
+ EXPECT_FALSE(result.ok());
+ }
+ {
+ const std::string source =
+ base::GetExecutableDirectory() + "/test_audio_policy_configuration.xml";
+ auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(source);
+ ASSERT_TRUE(result.ok());
+ EXPECT_EQ(source, result.value()->getSource());
+ EXPECT_FALSE(result.value()->getHwModules().isEmpty());
+ EXPECT_FALSE(result.value()->getInputDevices().isEmpty());
+ EXPECT_FALSE(result.value()->getOutputDevices().isEmpty());
+ }
+}
+
TEST(AudioPolicyManagerTestInit, EngineFailure) {
AudioPolicyTestClient client;
- AudioPolicyTestManager manager(&client);
- manager.getConfig().setDefault();
- manager.getConfig().setEngineLibraryNameSuffix("non-existent");
+ auto config = AudioPolicyConfig::createWritableForTests();
+ config->setDefault();
+ config->setEngineLibraryNameSuffix("non-existent");
+ AudioPolicyTestManager manager(config, &client);
ASSERT_EQ(NO_INIT, manager.initialize());
ASSERT_EQ(NO_INIT, manager.initCheck());
}
@@ -104,41 +137,12 @@
TEST(AudioPolicyManagerTestInit, ClientFailure) {
AudioPolicyTestClient client;
AudioPolicyTestManager manager(&client);
- manager.getConfig().setDefault();
// Since the default client fails to open anything,
// APM should indicate that the initialization didn't succeed.
ASSERT_EQ(NO_INIT, manager.initialize());
ASSERT_EQ(NO_INIT, manager.initCheck());
}
-// Verifies that a failure while loading a config doesn't leave
-// APM config in a "dirty" state. Since AudioPolicyConfig object
-// is a proxy for the data hosted by APM, it isn't possible
-// to "deep copy" it, and thus we have to test its elements
-// individually.
-TEST(AudioPolicyManagerTestInit, ConfigLoadingIsTransactional) {
- AudioPolicyTestClient client;
- AudioPolicyTestManager manager(&client);
- ASSERT_TRUE(manager.getConfig().getHwModules().isEmpty());
- ASSERT_TRUE(manager.getConfig().getInputDevices().isEmpty());
- ASSERT_TRUE(manager.getConfig().getOutputDevices().isEmpty());
- status_t status = deserializeAudioPolicyFile(
- (base::GetExecutableDirectory() +
- "/test_invalid_audio_policy_configuration.xml").c_str(),
- &manager.getConfig());
- ASSERT_NE(NO_ERROR, status);
- EXPECT_TRUE(manager.getConfig().getHwModules().isEmpty());
- EXPECT_TRUE(manager.getConfig().getInputDevices().isEmpty());
- EXPECT_TRUE(manager.getConfig().getOutputDevices().isEmpty());
- status = deserializeAudioPolicyFile(
- (base::GetExecutableDirectory() + "/test_audio_policy_configuration.xml").c_str(),
- &manager.getConfig());
- ASSERT_EQ(NO_ERROR, status);
- EXPECT_FALSE(manager.getConfig().getHwModules().isEmpty());
- EXPECT_FALSE(manager.getConfig().getInputDevices().isEmpty());
- EXPECT_FALSE(manager.getConfig().getOutputDevices().isEmpty());
-}
-
class PatchCountCheck {
public:
@@ -200,6 +204,7 @@
static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
virtual AudioPolicyManagerTestClient* getClient() { return new AudioPolicyManagerTestClient; }
+ sp<AudioPolicyConfig> mConfig;
std::unique_ptr<AudioPolicyManagerTestClient> mClient;
std::unique_ptr<AudioPolicyTestManager> mManager;
@@ -208,8 +213,8 @@
void AudioPolicyManagerTest::SetUp() {
mClient.reset(getClient());
- mManager.reset(new AudioPolicyTestManager(mClient.get()));
ASSERT_NO_FATAL_FAILURE(SetUpManagerConfig()); // Subclasses may want to customize the config.
+ mManager.reset(new AudioPolicyTestManager(mConfig, mClient.get()));
ASSERT_EQ(NO_ERROR, mManager->initialize());
ASSERT_EQ(NO_ERROR, mManager->initCheck());
}
@@ -220,7 +225,8 @@
}
void AudioPolicyManagerTest::SetUpManagerConfig() {
- mManager->getConfig().setDefault();
+ mConfig = AudioPolicyConfig::createWritableForTests();
+ mConfig->setDefault();
}
void AudioPolicyManagerTest::dumpToLog() {
@@ -467,7 +473,6 @@
void AudioPolicyManagerTestMsd::SetUpManagerConfig() {
// TODO: Consider using Serializer to load part of the config from a string.
ASSERT_NO_FATAL_FAILURE(AudioPolicyManagerTest::SetUpManagerConfig());
- AudioPolicyConfig& config = mManager->getConfig();
mMsdOutputDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_BUS);
sp<AudioProfile> pcmOutputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_OUT_STEREO, k48000SamplingRate);
@@ -483,26 +488,26 @@
sp<AudioProfile> pcmInputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
mMsdInputDevice->addAudioProfile(pcmInputProfile);
- config.addDevice(mMsdOutputDevice);
- config.addDevice(mMsdInputDevice);
+ mConfig->addDevice(mMsdOutputDevice);
+ mConfig->addDevice(mMsdInputDevice);
if (mExpectedAudioPatchCount == 2) {
// Add SPDIF device with PCM output profile as a second device for dual MSD audio patching.
mSpdifDevice = new DeviceDescriptor(AUDIO_DEVICE_OUT_SPDIF);
mSpdifDevice->addAudioProfile(pcmOutputProfile);
- config.addDevice(mSpdifDevice);
+ mConfig->addDevice(mSpdifDevice);
sp<OutputProfile> spdifOutputProfile = new OutputProfile("spdif output");
spdifOutputProfile->addAudioProfile(pcmOutputProfile);
spdifOutputProfile->addSupportedDevice(mSpdifDevice);
- config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addOutputProfile(spdifOutputProfile);
}
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
- HwModuleCollection modules = config.getHwModules();
+ HwModuleCollection modules = mConfig->getHwModules();
modules.add(msdModule);
- config.setHwModules(modules);
+ mConfig->setHwModules(modules);
sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
msdOutputProfile->addAudioProfile(pcmOutputProfile);
@@ -530,15 +535,15 @@
// of streams that are not supported by MSD.
sp<AudioProfile> dtsOutputProfile = new AudioProfile(
AUDIO_FORMAT_DTS, AUDIO_CHANNEL_OUT_5POINT1, k48000SamplingRate);
- config.getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
+ mConfig->getDefaultOutputDevice()->addAudioProfile(dtsOutputProfile);
sp<OutputProfile> primaryEncodedOutputProfile = new OutputProfile("encoded");
primaryEncodedOutputProfile->addAudioProfile(dtsOutputProfile);
primaryEncodedOutputProfile->setFlags(AUDIO_OUTPUT_FLAG_DIRECT);
- primaryEncodedOutputProfile->addSupportedDevice(config.getDefaultOutputDevice());
- config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ primaryEncodedOutputProfile->addSupportedDevice(mConfig->getDefaultOutputDevice());
+ mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addOutputProfile(primaryEncodedOutputProfile);
- mDefaultOutputDevice = config.getDefaultOutputDevice();
+ mDefaultOutputDevice = mConfig->getDefaultOutputDevice();
if (mExpectedAudioPatchCount == 2) {
mSpdifDevice->addAudioProfile(dtsOutputProfile);
primaryEncodedOutputProfile->addSupportedDevice(mSpdifDevice);
@@ -549,12 +554,12 @@
sp<AudioProfile> iec958InputProfile = new AudioProfile(
AUDIO_FORMAT_IEC60958, AUDIO_CHANNEL_INDEX_MASK_24, k48000SamplingRate);
mHdmiInputDevice->addAudioProfile(iec958InputProfile);
- config.addDevice(mHdmiInputDevice);
+ mConfig->addDevice(mHdmiInputDevice);
sp<InputProfile> hdmiInputProfile = new InputProfile("hdmi input");
hdmiInputProfile->addAudioProfile(iec958InputProfile);
hdmiInputProfile->setFlags(AUDIO_INPUT_FLAG_DIRECT);
hdmiInputProfile->addSupportedDevice(mHdmiInputDevice);
- config.getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
+ mConfig->getHwModules().getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY)->
addInputProfile(hdmiInputProfile);
}
@@ -721,7 +726,7 @@
int countDirectProfilesPrimary = 0;
const auto& primary = mManager->getConfig().getHwModules()
.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_PRIMARY);
- for (const auto outputProfile : primary->getOutputProfiles()) {
+ for (const auto& outputProfile : primary->getOutputProfiles()) {
if (outputProfile->asAudioPort()->isDirectOutput()) {
countDirectProfilesPrimary += outputProfile->asAudioPort()->getAudioProfiles().size();
}
@@ -731,7 +736,7 @@
int countDirectProfilesMsd = 0;
const auto& msd = mManager->getConfig().getHwModules()
.getModuleFromName(AUDIO_HARDWARE_MODULE_ID_MSD);
- for (const auto outputProfile : msd->getOutputProfiles()) {
+ for (const auto& outputProfile : msd->getOutputProfiles()) {
if (outputProfile->asAudioPort()->isDirectOutput()) {
countDirectProfilesMsd += outputProfile->asAudioPort()->getAudioProfiles().size();
}
@@ -922,9 +927,9 @@
sExecutableDir + "test_audio_policy_configuration.xml";
void AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig() {
- status_t status = deserializeAudioPolicyFile(getConfigFile().c_str(), &mManager->getConfig());
- ASSERT_EQ(NO_ERROR, status);
- mManager->getConfig().setSource(getConfigFile());
+ auto result = AudioPolicyConfig::loadFromCustomXmlConfigForTests(getConfigFile());
+ ASSERT_TRUE(result.ok());
+ mConfig = result.value();
}
TEST_F(AudioPolicyManagerTestWithConfigurationFile, InitSuccess) {