audio policy: add Spatializer effect control
Add APIs to discover support for audio spatialization function and control a
spatializer output mixer and effect creation to Audio Policy Service.
When supported, a system service can retrieve a ISpatializer
interface to query supported features and set a spatialization mode.
When spatialization is enabled, the corresponding specialized output mixer is
created and the effect applied.
The audio policy manager will attach clients which audio attributes and
format qualifying for spatialization to the specialized output mixer.
Bug: 188502620
Test: make
Change-Id: Ie2734fb9bb3ef9b945431c6c9bd110b1434a79cd
Merged-In: Ie2734fb9bb3ef9b945431c6c9bd110b1434a79cd
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 3c757b3..56c472b 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -141,6 +141,13 @@
uidPolicy->registerSelf();
sensorPrivacyPolicy->registerSelf();
+ // Create spatializer if supported
+ const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
+ AudioDeviceTypeAddrVector devices;
+ bool hasSpatializer = mAudioPolicyManager->canBeSpatialized(&attr, nullptr, devices);
+ if (hasSpatializer) {
+ mSpatializer = Spatializer::create(this);
+ }
AudioSystem::audioPolicyReady();
}
@@ -356,6 +363,49 @@
}
}
+void AudioPolicyService::onCheckSpatializer()
+{
+ Mutex::Autolock _l(mLock);
+ mOutputCommandThread->checkSpatializerCommand();
+}
+
+void AudioPolicyService::doOnCheckSpatializer()
+{
+ sp<Spatializer> spatializer;
+ {
+ Mutex::Autolock _l(mLock);
+ spatializer = mSpatializer;
+
+ if (spatializer != nullptr) {
+ audio_io_handle_t output = AUDIO_IO_HANDLE_NONE;
+ if (spatializer->getLevel() != media::SpatializationLevel::NONE
+ && spatializer->getOutput() == AUDIO_IO_HANDLE_NONE) {
+ const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
+ audio_config_base_t config = spatializer->getAudioInConfig();
+ status_t status =
+ mAudioPolicyManager->getSpatializerOutput(&config, &attr, &output);
+ if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
+ return;
+ }
+ mLock.unlock();
+ status = spatializer->attachOutput(output);
+ mLock.lock();
+ if (status != NO_ERROR) {
+ mAudioPolicyManager->releaseSpatializerOutput(output);
+ }
+ } else if (spatializer->getLevel() == media::SpatializationLevel::NONE
+ && spatializer->getOutput() != AUDIO_IO_HANDLE_NONE) {
+ mLock.unlock();
+ output = spatializer->detachOutput();
+ mLock.lock();
+ if (output != AUDIO_IO_HANDLE_NONE) {
+ mAudioPolicyManager->releaseSpatializerOutput(output);
+ }
+ }
+ }
+ }
+}
+
status_t AudioPolicyService::clientCreateAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
int delayMs)
@@ -993,7 +1043,8 @@
case TRANSACTION_addDevicesRoleForCapturePreset:
case TRANSACTION_removeDevicesRoleForCapturePreset:
case TRANSACTION_clearDevicesRoleForCapturePreset:
- case TRANSACTION_getDevicesForRoleAndCapturePreset: {
+ case TRANSACTION_getDevicesForRoleAndCapturePreset:
+ case TRANSACTION_getSpatializer: {
if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
__func__, code, IPCThreadState::self()->getCallingPid(),
@@ -1767,6 +1818,17 @@
mLock.lock();
} break;
+ case CHECK_SPATIALIZER: {
+ ALOGV("AudioCommandThread() processing updateUID states");
+ svc = mService.promote();
+ if (svc == 0) {
+ break;
+ }
+ mLock.unlock();
+ svc->doOnCheckSpatializer();
+ mLock.lock();
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -2078,6 +2140,14 @@
sendCommand(command);
}
+void AudioPolicyService::AudioCommandThread::checkSpatializerCommand()
+{
+ sp<AudioCommand>command = new AudioCommand();
+ command->mCommand = CHECK_SPATIALIZER;
+ ALOGV("AudioCommandThread() adding check spatializer");
+ sendCommand(command);
+}
+
status_t AudioPolicyService::AudioCommandThread::sendCommand(sp<AudioCommand>& command, int delayMs)
{
{