Allow for late audio module discovery in APM
Extract code that loads hardware modules and fills out
mAvailable{Input|Output}Devices into a reusable function.
It is used both during APM initialization and on
receiving a notification that a new HAL service has
been discovered.
Bug: 149854039
Test: atest audiopolicy_tests
Change-Id: Ifb7f0b61b06a0609802e63dccb26f3472328ef48
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 2a8349c..7d92f34 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -298,9 +298,9 @@
audio_patch_handle_t handle = AUDIO_PATCH_HANDLE_NONE;
uid_t uid = 42;
const PatchCountCheck patchCount = snapshotPatchCount();
- ASSERT_FALSE(mManager->getConfig().getAvailableInputDevices().isEmpty());
+ ASSERT_FALSE(mManager->getAvailableInputDevices().isEmpty());
PatchBuilder patchBuilder;
- patchBuilder.addSource(mManager->getConfig().getAvailableInputDevices()[0]).
+ patchBuilder.addSource(mManager->getAvailableInputDevices()[0]).
addSink(mManager->getConfig().getDefaultOutputDevice());
ASSERT_EQ(NO_ERROR, mManager->createAudioPatch(patchBuilder.patch(), &handle, uid));
ASSERT_NE(AUDIO_PATCH_HANDLE_NONE, handle);
@@ -334,15 +334,13 @@
sp<AudioProfile> pcmInputProfile = new AudioProfile(
AUDIO_FORMAT_PCM_16_BIT, AUDIO_CHANNEL_IN_STEREO, 44100);
mMsdInputDevice->addAudioProfile(pcmInputProfile);
- config.addAvailableDevice(mMsdOutputDevice);
- config.addAvailableDevice(mMsdInputDevice);
+ config.addDevice(mMsdOutputDevice);
+ config.addDevice(mMsdInputDevice);
sp<HwModule> msdModule = new HwModule(AUDIO_HARDWARE_MODULE_ID_MSD, 2 /*halVersionMajor*/);
HwModuleCollection modules = config.getHwModules();
modules.add(msdModule);
config.setHwModules(modules);
- mMsdOutputDevice->attach(msdModule);
- mMsdInputDevice->attach(msdModule);
sp<OutputProfile> msdOutputProfile = new OutputProfile("msd input");
msdOutputProfile->addAudioProfile(pcmOutputProfile);
@@ -1127,3 +1125,40 @@
AUDIO_OUTPUT_FLAG_DIRECT|AUDIO_OUTPUT_FLAG_MMAP_NOIRQ),
"low latency");
}
+
+class AudioPolicyManagerDynamicHwModulesTest : public AudioPolicyManagerTestWithConfigurationFile {
+protected:
+ void SetUpManagerConfig() override;
+};
+
+void AudioPolicyManagerDynamicHwModulesTest::SetUpManagerConfig() {
+ AudioPolicyManagerTestWithConfigurationFile::SetUpManagerConfig();
+ // Only allow successful opening of "primary" hw module during APM initialization.
+ mClient->swapAllowedModuleNames({"primary"});
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, InitSuccess) {
+ // SetUp must finish with no assertions.
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, DynamicAddition) {
+ const auto handleBefore = mClient->peekNextModuleHandle();
+ mManager->onNewAudioModulesAvailable();
+ ASSERT_EQ(handleBefore, mClient->peekNextModuleHandle());
+ // Reset module loading restrictions.
+ mClient->swapAllowedModuleNames();
+ mManager->onNewAudioModulesAvailable();
+ const auto handleAfter = mClient->peekNextModuleHandle();
+ ASSERT_GT(handleAfter, handleBefore);
+ mManager->onNewAudioModulesAvailable();
+ ASSERT_EQ(handleAfter, mClient->peekNextModuleHandle());
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, AddedDeviceAvailable) {
+ ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, mManager->getDeviceConnectionState(
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
+ mClient->swapAllowedModuleNames({"primary", "r_submix"});
+ mManager->onNewAudioModulesAvailable();
+ ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, mManager->getDeviceConnectionState(
+ AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
+}