APM: Notify the client about new audio ports
Added missing notification to the APM client
about new audio ports. This should make the
ports provided by the newly discovered HAL
to be available to apps.
Process the onNewAudioModulesAvailable notification
on the "APM Output" command thread to avoid clashing
with outgoing commands from APM during module
initialization.
Bug: 149854039
Test: atest audiopolicy_tests
Change-Id: I3fede7f5a04419b15e15476d8b5ac7dc6d63c98d
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ffc3a0f..738b52e 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -133,12 +133,14 @@
sp<DeviceDescriptor> device =
mHwModules.getDeviceDescriptor(deviceType, device_address, device_name, encodedFormat,
state == AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
- if (device == 0) {
- return INVALID_OPERATION;
- }
+ return device ? setDeviceConnectionStateInt(device, state) : INVALID_OPERATION;
+}
+status_t AudioPolicyManager::setDeviceConnectionStateInt(const sp<DeviceDescriptor> &device,
+ audio_policy_dev_state_t state)
+{
// handle output devices
- if (audio_is_output_device(deviceType)) {
+ if (audio_is_output_device(device->type())) {
SortedVector <audio_io_handle_t> outputs;
ssize_t index = mAvailableOutputDevices.indexOf(device);
@@ -155,7 +157,7 @@
return INVALID_OPERATION;
}
ALOGV("%s() connecting device %s format %x",
- __func__, device->toString().c_str(), encodedFormat);
+ __func__, device->toString().c_str(), device->getEncodedFormat());
// register new device as available
if (mAvailableOutputDevices.add(device) < 0) {
@@ -217,16 +219,13 @@
// output device used by a dynamic policy of type recorder as no
// playback use case is affected.
bool doCheckForDeviceAndOutputChanges = true;
- if (device->type() == AUDIO_DEVICE_OUT_REMOTE_SUBMIX
- && strncmp(device_address, "0", AUDIO_DEVICE_MAX_ADDRESS_LEN) != 0) {
+ if (device->type() == AUDIO_DEVICE_OUT_REMOTE_SUBMIX && device->address() != "0") {
for (audio_io_handle_t output : outputs) {
sp<SwAudioOutputDescriptor> desc = mOutputs.valueFor(output);
sp<AudioPolicyMix> policyMix = desc->mPolicyMix.promote();
if (policyMix != nullptr
&& policyMix->mMixType == MIX_TYPE_RECORDERS
- && strncmp(device_address,
- policyMix->mDeviceAddress.string(),
- AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0) {
+ && device->address() == policyMix->mDeviceAddress.string()) {
doCheckForDeviceAndOutputChanges = false;
break;
}
@@ -272,7 +271,7 @@
// a valid device selection on those outputs.
bool force = (msdOutDevices.isEmpty() || msdOutDevices != desc->devices())
&& !desc->isDuplicated()
- && (!device_distinguishes_on_address(deviceType)
+ && (!device_distinguishes_on_address(device->type())
// always force when disconnecting (a non-duplicated device)
|| (state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE));
setOutputDevices(desc, newDevices, force, 0);
@@ -288,7 +287,7 @@
} // end if is output device
// handle input devices
- if (audio_is_input_device(deviceType)) {
+ if (audio_is_input_device(device->type())) {
ssize_t index = mAvailableInputDevices.indexOf(device);
switch (state)
{
@@ -4444,7 +4443,7 @@
// after parsing the config, mOutputDevicesAll and mInputDevicesAll contain all known devices;
// open all output streams needed to access attached devices
- onNewAudioModulesAvailable();
+ onNewAudioModulesAvailableInt(nullptr /*newDevices*/);
// make sure default device is reachable
if (mDefaultOutputDevice == 0 || !mAvailableOutputDevices.contains(mDefaultOutputDevice)) {
@@ -4501,6 +4500,16 @@
void AudioPolicyManager::onNewAudioModulesAvailable()
{
+ DeviceVector newDevices;
+ onNewAudioModulesAvailableInt(&newDevices);
+ if (!newDevices.empty()) {
+ nextAudioPortGeneration();
+ mpClientInterface->onAudioPortListUpdate();
+ }
+}
+
+void AudioPolicyManager::onNewAudioModulesAvailableInt(DeviceVector *newDevices)
+{
for (const auto& hwModule : mHwModulesAll) {
if (std::find(mHwModules.begin(), mHwModules.end(), hwModule) != mHwModules.end()) {
continue;
@@ -4564,6 +4573,7 @@
if (!device->isAttached()) {
device->attach(hwModule);
mAvailableOutputDevices.add(device);
+ if (newDevices) newDevices->add(device);
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
}
}
@@ -4619,6 +4629,7 @@
device->attach(hwModule);
device->importAudioPortAndPickAudioProfile(inProfile, true);
mAvailableInputDevices.add(device);
+ if (newDevices) newDevices->add(device);
setEngineDeviceConnectionState(device, AUDIO_POLICY_DEVICE_STATE_AVAILABLE);
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 8121f86..c142880 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -788,6 +788,8 @@
std::unordered_map<uid_t, audio_flags_mask_t> mAllowedCapturePolicies;
private:
+ void onNewAudioModulesAvailableInt(DeviceVector *newDevices);
+
// Add or remove AC3 DTS encodings based on user preferences.
void modifySurroundFormats(const sp<DeviceDescriptor>& devDesc, FormatVector *formatsPtr);
void modifySurroundChannelMasks(ChannelMaskSet *channelMasksPtr);
@@ -878,6 +880,8 @@
const char *device_address,
const char *device_name,
audio_format_t encodedFormat);
+ status_t setDeviceConnectionStateInt(const sp<DeviceDescriptor> &device,
+ audio_policy_dev_state_t state);
void setEngineDeviceConnectionState(const sp<DeviceDescriptor> device,
audio_policy_dev_state_t state);
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index bf38477..bec6aff 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1876,7 +1876,7 @@
void AudioPolicyService::onNewAudioModulesAvailable()
{
- mAudioCommandThread->audioModulesUpdateCommand();
+ mOutputCommandThread->audioModulesUpdateCommand();
}
diff --git a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
index af69466..e1721ea 100644
--- a/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyManagerTestClient.h
@@ -94,6 +94,10 @@
return NO_ERROR;
}
+ void onAudioPortListUpdate() override {
+ ++mAudioPortListUpdateCount;
+ }
+
// Helper methods for tests
size_t getActivePatchesCount() const { return mActivePatches.size(); }
@@ -111,12 +115,15 @@
mAllowedModuleNames.swap(names);
}
+ size_t getAudioPortListUpdateCount() const { return mAudioPortListUpdateCount; }
+
private:
audio_module_handle_t mNextModuleHandle = AUDIO_MODULE_HANDLE_NONE + 1;
audio_io_handle_t mNextIoHandle = AUDIO_IO_HANDLE_NONE + 1;
audio_patch_handle_t mNextPatchHandle = AUDIO_PATCH_HANDLE_NONE + 1;
std::map<audio_patch_handle_t, struct audio_patch> mActivePatches;
std::set<std::string> mAllowedModuleNames;
+ size_t mAudioPortListUpdateCount = 0;
};
} // namespace android
diff --git a/services/audiopolicy/tests/AudioPolicyTestManager.h b/services/audiopolicy/tests/AudioPolicyTestManager.h
index 922a538..8bab020 100644
--- a/services/audiopolicy/tests/AudioPolicyTestManager.h
+++ b/services/audiopolicy/tests/AudioPolicyTestManager.h
@@ -29,6 +29,7 @@
using AudioPolicyManager::getOutputs;
using AudioPolicyManager::getAvailableOutputDevices;
using AudioPolicyManager::getAvailableInputDevices;
+ uint32_t getAudioPortGeneration() const { return mAudioPortGeneration; }
};
} // namespace android
diff --git a/services/audiopolicy/tests/audiopolicymanager_tests.cpp b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
index 7d92f34..a0074bc 100644
--- a/services/audiopolicy/tests/audiopolicymanager_tests.cpp
+++ b/services/audiopolicy/tests/audiopolicymanager_tests.cpp
@@ -104,8 +104,10 @@
audio_port_handle_t *portId = nullptr);
PatchCountCheck snapshotPatchCount() { return PatchCountCheck(mClient.get()); }
- void findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
- const std::string &address, audio_port &foundPort);
+ // Tries to find a device port. If 'foundPort' isn't nullptr,
+ // will generate a failure if the port hasn't been found.
+ bool findDevicePort(audio_port_role_t role, audio_devices_t deviceType,
+ const std::string &address, audio_port *foundPort);
static audio_port_handle_t getDeviceIdFromPatch(const struct audio_patch* patch);
std::unique_ptr<AudioPolicyManagerTestClient> mClient;
@@ -211,30 +213,36 @@
ASSERT_NE(AUDIO_PORT_HANDLE_NONE, *portId);
}
-void AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
- audio_devices_t deviceType, const std::string &address, audio_port &foundPort) {
+bool AudioPolicyManagerTest::findDevicePort(audio_port_role_t role,
+ audio_devices_t deviceType, const std::string &address, audio_port *foundPort) {
uint32_t numPorts = 0;
uint32_t generation1;
status_t ret;
ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, nullptr, &generation1);
- ASSERT_EQ(NO_ERROR, ret);
+ EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+ if (HasFailure()) return false;
uint32_t generation2;
struct audio_port ports[numPorts];
ret = mManager->listAudioPorts(role, AUDIO_PORT_TYPE_DEVICE, &numPorts, ports, &generation2);
- ASSERT_EQ(NO_ERROR, ret);
- ASSERT_EQ(generation1, generation2);
+ EXPECT_EQ(NO_ERROR, ret) << "mManager->listAudioPorts returned error";
+ EXPECT_EQ(generation1, generation2) << "Generations changed during ports retrieval";
+ if (HasFailure()) return false;
for (const auto &port : ports) {
if (port.role == role && port.ext.device.type == deviceType &&
(strncmp(port.ext.device.address, address.c_str(),
AUDIO_DEVICE_MAX_ADDRESS_LEN) == 0)) {
- foundPort = port;
- return;
+ if (foundPort) *foundPort = port;
+ return true;
}
}
- GTEST_FAIL() << "Device port with role " << role << " and address " << address << "not found";
+ if (foundPort) {
+ ADD_FAILURE() << "Device port with role " << role << " and address "
+ << address << " not found";
+ }
+ return false;
}
audio_port_handle_t AudioPolicyManagerTest::getDeviceIdFromPatch(
@@ -694,8 +702,8 @@
ASSERT_EQ(NO_ERROR, ret);
struct audio_port extractionPort;
- findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- mMixAddress, extractionPort);
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ mMixAddress, &extractionPort));
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_source_t source = AUDIO_SOURCE_REMOTE_SUBMIX;
@@ -707,8 +715,8 @@
ASSERT_EQ(NO_ERROR, mManager->startInput(mPortId));
ASSERT_EQ(extractionPort.id, selectedDeviceId);
- findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- mMixAddress, mInjectionPort);
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ mMixAddress, &mInjectionPort));
}
void AudioPolicyManagerTestDPPlaybackReRouting::TearDown() {
@@ -879,8 +887,8 @@
ASSERT_EQ(NO_ERROR, ret);
struct audio_port injectionPort;
- findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
- mMixAddress, injectionPort);
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SINK, AUDIO_DEVICE_OUT_REMOTE_SUBMIX,
+ mMixAddress, &injectionPort));
audio_port_handle_t selectedDeviceId = AUDIO_PORT_HANDLE_NONE;
audio_usage_t usage = AUDIO_USAGE_VIRTUAL_SOURCE;
@@ -892,8 +900,8 @@
ASSERT_EQ(NO_ERROR, mManager->startOutput(mPortId));
ASSERT_EQ(injectionPort.id, getDeviceIdFromPatch(mClient->getLastAddedPatch()));
- findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
- mMixAddress, mExtractionPort);
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX,
+ mMixAddress, &mExtractionPort));
}
void AudioPolicyManagerTestDPMixRecordInjection::TearDown() {
@@ -1028,7 +1036,7 @@
audio_port devicePort;
const audio_port_role_t role = audio_is_output_device(type)
? AUDIO_PORT_ROLE_SINK : AUDIO_PORT_ROLE_SOURCE;
- findDevicePort(role, type, address, devicePort);
+ ASSERT_TRUE(findDevicePort(role, type, address, &devicePort));
audio_port_handle_t routedPortId = devicePort.id;
// Try start input or output according to the device type
@@ -1162,3 +1170,21 @@
ASSERT_EQ(AUDIO_POLICY_DEVICE_STATE_AVAILABLE, mManager->getDeviceConnectionState(
AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0"));
}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, ListAddedAudioPorts) {
+ ASSERT_FALSE(
+ findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", nullptr));
+ mClient->swapAllowedModuleNames({"primary", "r_submix"});
+ mManager->onNewAudioModulesAvailable();
+ struct audio_port port;
+ ASSERT_TRUE(findDevicePort(AUDIO_PORT_ROLE_SOURCE, AUDIO_DEVICE_IN_REMOTE_SUBMIX, "0", &port));
+}
+
+TEST_F(AudioPolicyManagerDynamicHwModulesTest, ClientIsUpdated) {
+ const size_t prevAudioPortListUpdateCount = mClient->getAudioPortListUpdateCount();
+ const uint32_t prevAudioPortGeneration = mManager->getAudioPortGeneration();
+ mClient->swapAllowedModuleNames({"primary", "r_submix"});
+ mManager->onNewAudioModulesAvailable();
+ EXPECT_GT(mClient->getAudioPortListUpdateCount(), prevAudioPortListUpdateCount);
+ EXPECT_GT(mManager->getAudioPortGeneration(), prevAudioPortGeneration);
+}