audio policy: update spatializer policy
Modify the rules to open and close the spatializer output
to address more scenarios:
- more than one spatializer output profile available
- some devices only reachable via a spatializer output profile
The spatializer outputs are opened and closed like other outputs
and a logic evaluates the best output when getSpatializerOutput()
is called
Bug: 188502620
Test: make
Change-Id: Id336e5c38a398525b3fab406cedce8a010d6c854
diff --git a/services/audioflinger/PlaybackTracks.h b/services/audioflinger/PlaybackTracks.h
index e9e98ca..b069462 100644
--- a/services/audioflinger/PlaybackTracks.h
+++ b/services/audioflinger/PlaybackTracks.h
@@ -195,6 +195,10 @@
audio_output_flags_t getOutputFlags() const { return mFlags; }
float getSpeed() const { return mSpeed; }
+
+ bool canBeSpatialized() const { return (mAttr.flags
+ & (AUDIO_FLAG_CONTENT_SPATIALIZED | AUDIO_FLAG_NEVER_SPATIALIZE)) == 0; }
+
protected:
// for numerous
friend class PlaybackThread;
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 767199f..683c4f7 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -2039,6 +2039,7 @@
free(mSinkBuffer);
free(mMixerBuffer);
free(mEffectBuffer);
+ free(mEffectToSinkBuffer);
}
// Thread virtuals
@@ -3001,11 +3002,18 @@
// Originally this was int16_t[] array, need to remove legacy implications.
free(mSinkBuffer);
mSinkBuffer = NULL;
+ free(mEffectToSinkBuffer);
+ mEffectToSinkBuffer = nullptr;
+
// For sink buffer size, we use the frame size from the downstream sink to avoid problems
// with non PCM formats for compressed music, e.g. AAC, and Offload threads.
const size_t sinkBufferSize = mNormalFrameCount * mFrameSize;
(void)posix_memalign(&mSinkBuffer, 32, sinkBufferSize);
+ if (mType == SPATIALIZER) {
+ (void)posix_memalign(&mEffectToSinkBuffer, 32, sinkBufferSize);
+ }
+
// We resize the mMixerBuffer according to the requirements of the sink buffer which
// drives the output.
free(mMixerBuffer);
@@ -3836,11 +3844,11 @@
//
// mMixerBufferValid is only set true by MixerThread::prepareTracks_l().
// TODO use mSleepTimeUs == 0 as an additional condition.
+ uint32_t mixerChannelCount = mEffectBufferValid ?
+ audio_channel_count_from_out_mask(mMixerChannelMask) : mChannelCount;
if (mMixerBufferValid) {
void *buffer = mEffectBufferValid ? mEffectBuffer : mSinkBuffer;
audio_format_t format = mEffectBufferValid ? mEffectBufferFormat : mFormat;
- uint32_t channelCount = mEffectBufferValid ?
- audio_channel_count_from_out_mask(mMixerChannelMask) : mChannelCount;
// mono blend occurs for mixer threads only (not direct or offloaded)
// and is handled here if we're going directly to the sink.
@@ -3858,7 +3866,7 @@
}
memcpy_by_audio_format(buffer, format, mMixerBuffer, mMixerBufferFormat,
- mNormalFrameCount * (channelCount + mHapticChannelCount));
+ mNormalFrameCount * (mixerChannelCount + mHapticChannelCount));
// If we're going directly to the sink and there are haptic channels,
// we should adjust channels as the sample data is partially interleaved
@@ -3891,8 +3899,11 @@
&& activeHapticSessionId == effectChains[i]->sessionId()) {
// Haptic data is active in this case, copy it directly from
// in buffer to out buffer.
+ uint32_t channelCount =
+ effectChains[i]->sessionId() == AUDIO_SESSION_OUTPUT_STAGE ?
+ mixerChannelCount : mChannelCount;
const size_t audioBufferSize = mNormalFrameCount
- * audio_bytes_per_frame(mChannelCount, EFFECT_BUFFER_FORMAT);
+ * audio_bytes_per_frame(channelCount, EFFECT_BUFFER_FORMAT);
memcpy_by_audio_format(
(uint8_t*)effectChains[i]->outBuffer() + audioBufferSize,
EFFECT_BUFFER_FORMAT,
@@ -3932,8 +3943,23 @@
mBalance.process((float *)mEffectBuffer, mNormalFrameCount);
}
- memcpy_by_audio_format(mSinkBuffer, mFormat, mEffectBuffer, mEffectBufferFormat,
- mNormalFrameCount * (mChannelCount + mHapticChannelCount));
+ if (mType == SPATIALIZER) {
+ memcpy_by_audio_format(mEffectToSinkBuffer, mFormat, mEffectBuffer,
+ mEffectBufferFormat,
+ mNormalFrameCount * (mChannelCount + mHapticChannelCount));
+ accumulate_by_audio_format(mSinkBuffer, mEffectToSinkBuffer, mFormat,
+ mNormalFrameCount * mChannelCount);
+ const size_t audioBufferSize = mNormalFrameCount
+ * audio_bytes_per_frame(mChannelCount, mFormat);
+ memcpy_by_audio_format(
+ (uint8_t*)mSinkBuffer + audioBufferSize,
+ mFormat,
+ (uint8_t*)mEffectToSinkBuffer + audioBufferSize,
+ mFormat, mNormalFrameCount * mHapticChannelCount);
+ } else {
+ memcpy_by_audio_format(mSinkBuffer, mFormat, mEffectBuffer, mEffectBufferFormat,
+ mNormalFrameCount * (mChannelCount + mHapticChannelCount));
+ }
// The sample data is partially interleaved when haptic channels exist,
// we need to adjust channels here.
if (mHapticChannelCount > 0) {
@@ -4588,6 +4614,7 @@
&& Intersection(outDeviceTypes(), getAudioDeviceOutAllA2dpSet()).empty();
break;
}
+ ALOG_ASSERT(initFastMixer && mType == SPATIALIZER);
ALOGW_IF(initFastMixer == false && mFrameCount < mNormalFrameCount,
"FastMixer is preferred for this sink as frameCount %zu is less than threshold %zu",
mFrameCount, mNormalFrameCount);
@@ -4946,6 +4973,9 @@
// before effects processing or output.
if (mMixerBufferValid) {
memset(mMixerBuffer, 0, mMixerBufferSize);
+ if (mType == SPATIALIZER) {
+ memset(mSinkBuffer, 0, mSinkBufferSize);
+ }
} else {
memset(mSinkBuffer, 0, mSinkBufferSize);
}
@@ -5438,11 +5468,21 @@
trackId,
AudioMixer::TRACK,
AudioMixer::CHANNEL_MASK, (void *)(uintptr_t)track->channelMask());
- mAudioMixer->setParameter(
- trackId,
- AudioMixer::TRACK,
- AudioMixer::MIXER_CHANNEL_MASK,
- (void *)(uintptr_t)(mMixerChannelMask | mHapticChannelMask));
+
+ if (mType == SPATIALIZER && !track->canBeSpatialized()) {
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MIXER_CHANNEL_MASK,
+ (void *)(uintptr_t)(mChannelMask | mHapticChannelMask));
+ } else {
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MIXER_CHANNEL_MASK,
+ (void *)(uintptr_t)(mMixerChannelMask | mHapticChannelMask));
+ }
+
// limit track sample rate to 2 x output sample rate, which changes at re-configuration
uint32_t maxSampleRate = mSampleRate * AUDIO_RESAMPLER_DOWN_RATIO_MAX;
uint32_t reqSampleRate = proxy->getSampleRate();
@@ -5479,16 +5519,27 @@
if (mMixerBufferEnabled
&& (track->mainBuffer() == mSinkBuffer
|| track->mainBuffer() == mMixerBuffer)) {
- mAudioMixer->setParameter(
- trackId,
- AudioMixer::TRACK,
- AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
- mAudioMixer->setParameter(
- trackId,
- AudioMixer::TRACK,
- AudioMixer::MAIN_BUFFER, (void *)mMixerBuffer);
- // TODO: override track->mainBuffer()?
- mMixerBufferValid = true;
+ if (mType == SPATIALIZER && !track->canBeSpatialized()) {
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MIXER_FORMAT, (void *)mFormat);
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MAIN_BUFFER, (void *)mSinkBuffer);
+ } else {
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MIXER_FORMAT, (void *)mMixerBufferFormat);
+ mAudioMixer->setParameter(
+ trackId,
+ AudioMixer::TRACK,
+ AudioMixer::MAIN_BUFFER, (void *)mMixerBuffer);
+ // TODO: override track->mainBuffer()?
+ mMixerBufferValid = true;
+ }
} else {
mAudioMixer->setParameter(
trackId,
@@ -5678,8 +5729,10 @@
// sink or mix buffer must be cleared if all tracks are connected to an
// effect chain as in this case the mixer will not write to the sink or mix buffer
// and track effects will accumulate into it
- if ((mBytesRemaining == 0) && ((mixedTracks != 0 && mixedTracks == tracksWithEffect) ||
- (mixedTracks == 0 && fastTracks > 0))) {
+ // always clear sink buffer for spatializer output as the output of the spatializer
+ // effect will be accumulated into it
+ if ((mBytesRemaining == 0) && (((mixedTracks != 0 && mixedTracks == tracksWithEffect) ||
+ (mixedTracks == 0 && fastTracks > 0)) || (mType == SPATIALIZER))) {
// FIXME as a performance optimization, should remember previous zero status
if (mMixerBufferValid) {
memset(mMixerBuffer, 0, mMixerBufferSize);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 58864e7..0e86391 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -1122,6 +1122,11 @@
// for any processing (including output processing).
bool mEffectBufferValid;
+ // Frame size aligned buffer used to convert mEffectBuffer samples to mSinkBuffer format prior
+ // to accumulate into mSinkBuffer on SPATIALIZER threads
+ void* mEffectToSinkBuffer = nullptr;
+
+
// suspend count, > 0 means suspended. While suspended, the thread continues to pull from
// tracks and mix, but doesn't write to HAL. A2DP and SCO HAL implementations can't handle
// concurrent use of both of them, so Audio Policy Service suspends one of the threads to
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index a2dbeb2..e334532 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -248,9 +248,7 @@
// been opened by checkOutputsForDevice() to query dynamic parameters
if ((state == AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE)
|| (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) &&
- (desc->mDirectOpenCount == 0))
- || (((desc->mFlags & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0) &&
- (desc != mSpatializerOutput))) {
+ (desc->mDirectOpenCount == 0))) {
clearAudioSourcesForOutput(output);
closeOutput(output);
}
@@ -928,8 +926,7 @@
}
sp<IOProfile> AudioPolicyManager::getSpatializerOutputProfile(
- const audio_config_t *config __unused, const AudioDeviceTypeAddrVector &devices,
- bool forOpening) const
+ const audio_config_t *config __unused, const AudioDeviceTypeAddrVector &devices) const
{
for (const auto& hwModule : mHwModules) {
for (const auto& curProfile : hwModule->getOutputProfiles()) {
@@ -947,9 +944,6 @@
continue;
}
}
- if (forOpening && !curProfile->canOpenNewIo()) {
- continue;
- }
ALOGV("%s found profile %s", __func__, curProfile->getName().c_str());
return curProfile;
}
@@ -4843,6 +4837,21 @@
return source;
}
+/* static */
+bool AudioPolicyManager::isChannelMaskSpatialized(audio_channel_mask_t channels) {
+ switch (channels) {
+ case AUDIO_CHANNEL_OUT_5POINT1:
+ case AUDIO_CHANNEL_OUT_5POINT1POINT2:
+ case AUDIO_CHANNEL_OUT_5POINT1POINT4:
+ case AUDIO_CHANNEL_OUT_7POINT1:
+ case AUDIO_CHANNEL_OUT_7POINT1POINT2:
+ case AUDIO_CHANNEL_OUT_7POINT1POINT4:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool AudioPolicyManager::canBeSpatialized(const audio_attributes_t *attr,
const audio_config_t *config,
const AudioDeviceTypeAddrVector &devices) const
@@ -4851,9 +4860,13 @@
// the AUDIO_ATTRIBUTES_INITIALIZER value.
// If attributes are specified, current policy is to only allow spatialization for media
// and game usages.
- if (attr != nullptr && *attr != AUDIO_ATTRIBUTES_INITIALIZER &&
- attr->usage != AUDIO_USAGE_MEDIA && attr->usage != AUDIO_USAGE_GAME) {
- return false;
+ if (attr != nullptr && *attr != AUDIO_ATTRIBUTES_INITIALIZER) {
+ if (attr->usage != AUDIO_USAGE_MEDIA && attr->usage != AUDIO_USAGE_GAME) {
+ return false;
+ }
+ if ((attr->flags & (AUDIO_FLAG_CONTENT_SPATIALIZED | AUDIO_FLAG_NEVER_SPATIALIZE)) != 0) {
+ return false;
+ }
}
// The caller can have the devices criteria ignored by passing and empty vector, and
@@ -4861,7 +4874,7 @@
// Otherwise an output profile supporting a spatializer effect that can be routed
// to the specified devices must exist.
sp<IOProfile> profile =
- getSpatializerOutputProfile(config, devices, false /*forOpening*/);
+ getSpatializerOutputProfile(config, devices);
if (profile == nullptr) {
return false;
}
@@ -4869,37 +4882,36 @@
// The caller can have the audio config criteria ignored by either passing a null ptr or
// the AUDIO_CONFIG_INITIALIZER value.
// If an audio config is specified, current policy is to only allow spatialization for
- // 5.1, 7.1and 7.1.4 audio.
+ // some positional channel masks.
// If the spatializer output is already opened, only channel masks included in the
// spatializer output mixer channel mask are allowed.
+
if (config != nullptr && *config != AUDIO_CONFIG_INITIALIZER) {
- if (config->channel_mask != AUDIO_CHANNEL_OUT_5POINT1
- && config->channel_mask != AUDIO_CHANNEL_OUT_7POINT1
- && config->channel_mask != AUDIO_CHANNEL_OUT_7POINT1POINT4) {
+ if (!isChannelMaskSpatialized(config->channel_mask)) {
return false;
}
- if (mSpatializerOutput != nullptr) {
+ if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile) {
if ((config->channel_mask & mSpatializerOutput->mMixerChannelMask)
!= config->channel_mask) {
return false;
}
}
}
-
return true;
}
void AudioPolicyManager::checkVirtualizerClientRoutes() {
std::set<audio_stream_type_t> streamsToInvalidate;
for (size_t i = 0; i < mOutputs.size(); i++) {
- const sp<SwAudioOutputDescriptor>& outputDescriptor = mOutputs[i];
- for (const sp<TrackClientDescriptor>& client : outputDescriptor->getClientIterable()) {
+ const sp<SwAudioOutputDescriptor>& desc = mOutputs[i];
+ for (const sp<TrackClientDescriptor>& client : desc->getClientIterable()) {
audio_attributes_t attr = client->attributes();
DeviceVector devices = mEngine->getOutputDevicesForAttributes(attr, nullptr, false);
AudioDeviceTypeAddrVector devicesTypeAddress = devices.toTypeAddrVector();
audio_config_base_t clientConfig = client->config();
audio_config_t config = audio_config_initializer(&clientConfig);
- if (canBeSpatialized(&attr, &config, devicesTypeAddress)) {
+ if (desc != mSpatializerOutput
+ && canBeSpatialized(&attr, &config, devicesTypeAddress)) {
streamsToInvalidate.insert(client->stream());
}
}
@@ -4915,10 +4927,6 @@
audio_io_handle_t *output) {
*output = AUDIO_IO_HANDLE_NONE;
- if (mSpatializerOutput != nullptr) {
- return INVALID_OPERATION;
- }
-
DeviceVector devices = mEngine->getOutputDevicesForAttributes(*attr, nullptr, false);
AudioDeviceTypeAddrVector devicesTypeAddress = devices.toTypeAddrVector();
audio_config_t *configPtr = nullptr;
@@ -4928,35 +4936,87 @@
configPtr = &config;
}
if (!canBeSpatialized(attr, configPtr, devicesTypeAddress)) {
+ ALOGW("%s provided attributes or mixer config cannot be spatialized", __func__);
return BAD_VALUE;
}
sp<IOProfile> profile =
- getSpatializerOutputProfile(configPtr, devicesTypeAddress, true /*forOpening*/);
+ getSpatializerOutputProfile(configPtr, devicesTypeAddress);
if (profile == nullptr) {
+ ALOGW("%s no suitable output profile for provided attributes or mixer config", __func__);
return BAD_VALUE;
}
- mSpatializerOutput = new SwAudioOutputDescriptor(profile, mpClientInterface);
- status_t status = mSpatializerOutput->open(nullptr, mixerConfig, devices,
+ if (mSpatializerOutput != nullptr && mSpatializerOutput->mProfile == profile
+ && configPtr != nullptr
+ && configPtr->channel_mask == mSpatializerOutput->mMixerChannelMask) {
+ *output = mSpatializerOutput->mIoHandle;
+ ALOGV("%s returns current spatializer output %d", __func__, *output);
+ return NO_ERROR;
+ }
+ mSpatializerOutput.clear();
+ for (size_t i = 0; i < mOutputs.size(); i++) {
+ sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
+ if (!desc->isDuplicated() && desc->mProfile == profile) {
+ mSpatializerOutput = desc;
+ break;
+ }
+ }
+ if (mSpatializerOutput == nullptr) {
+ ALOGW("%s no opened spatializer output for profile %s",
+ __func__, profile->getName().c_str());
+ return BAD_VALUE;
+ }
+
+ if (configPtr != nullptr
+ && configPtr->channel_mask != mSpatializerOutput->mMixerChannelMask) {
+ audio_config_base_t savedMixerConfig = {
+ .sample_rate = mSpatializerOutput->getSamplingRate(),
+ .format = mSpatializerOutput->getFormat(),
+ .channel_mask = mSpatializerOutput->mMixerChannelMask,
+ };
+ DeviceVector savedDevices = mSpatializerOutput->devices();
+
+ closeOutput(mSpatializerOutput->mIoHandle);
+ mSpatializerOutput.clear();
+
+ const sp<SwAudioOutputDescriptor> desc =
+ new SwAudioOutputDescriptor(profile, mpClientInterface);
+ status_t status = desc->open(nullptr, mixerConfig, devices,
mEngine->getStreamTypeForAttributes(*attr),
AUDIO_OUTPUT_FLAG_SPATIALIZER, output);
- if (status != NO_ERROR) {
- ALOGV("%s failed opening output: status %d, output %d", __func__, status, *output);
- if (*output != AUDIO_IO_HANDLE_NONE) {
- mSpatializerOutput->close();
+ if (status != NO_ERROR) {
+ ALOGW("%s failed opening output: status %d, output %d", __func__, status, *output);
+ if (*output != AUDIO_IO_HANDLE_NONE) {
+ desc->close();
+ }
+ // re open the spatializer output with previous channel mask
+ status_t newStatus = desc->open(nullptr, &savedMixerConfig, savedDevices,
+ mEngine->getStreamTypeForAttributes(*attr),
+ AUDIO_OUTPUT_FLAG_SPATIALIZER, output);
+ if (newStatus != NO_ERROR) {
+ if (*output != AUDIO_IO_HANDLE_NONE) {
+ desc->close();
+ }
+ ALOGE("%s failed to re-open mSpatializerOutput, status %d", __func__, newStatus);
+ } else {
+ mSpatializerOutput = desc;
+ addOutput(*output, desc);
+ }
+ mPreviousOutputs = mOutputs;
+ mpClientInterface->onAudioPortListUpdate();
+ *output = AUDIO_IO_HANDLE_NONE;
+ return status;
}
- mSpatializerOutput.clear();
- *output = AUDIO_IO_HANDLE_NONE;
- return status;
+ mSpatializerOutput = desc;
+ addOutput(*output, desc);
+ mPreviousOutputs = mOutputs;
+ mpClientInterface->onAudioPortListUpdate();
}
checkVirtualizerClientRoutes();
- addOutput(*output, mSpatializerOutput);
- mPreviousOutputs = mOutputs;
- mpClientInterface->onAudioPortListUpdate();
-
+ *output = mSpatializerOutput->mIoHandle;
ALOGV("%s returns new spatializer output %d", __func__, *output);
return NO_ERROR;
}
@@ -4968,8 +5028,11 @@
if (mSpatializerOutput->mIoHandle != output) {
return BAD_VALUE;
}
- closeOutput(output);
+
mSpatializerOutput.clear();
+
+ checkVirtualizerClientRoutes();
+
return NO_ERROR;
}
@@ -5186,8 +5249,7 @@
outProfile->getFlags() & AUDIO_OUTPUT_FLAG_PRIMARY) {
mPrimaryOutput = outputDesc;
}
- if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0
- || (outProfile->getFlags() & AUDIO_OUTPUT_FLAG_SPATIALIZER) != 0 ) {
+ if ((outProfile->getFlags() & AUDIO_OUTPUT_FLAG_DIRECT) != 0) {
outputDesc->close();
} else {
addOutput(output, outputDesc);
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index fd5c58f..967aa10 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -962,8 +962,9 @@
audio_io_handle_t *output);
sp<IOProfile> getSpatializerOutputProfile(const audio_config_t *config,
- const AudioDeviceTypeAddrVector &devices,
- bool forOpening) const;
+ const AudioDeviceTypeAddrVector &devices) const;
+
+ static bool isChannelMaskSpatialized(audio_channel_mask_t channels);
void checkVirtualizerClientRoutes();
diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
index 58359be..8504489 100644
--- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp
@@ -121,11 +121,14 @@
ALOGV("setDeviceConnectionState()");
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
- return binderStatusFromStatusT(
- mAudioPolicyManager->setDeviceConnectionState(device, state,
+ status_t status = mAudioPolicyManager->setDeviceConnectionState(device, state,
deviceAidl.address.c_str(),
deviceNameAidl.c_str(),
- encodedFormat));
+ encodedFormat);
+ if (status == NO_ERROR) {
+ onCheckSpatializer_l();
+ }
+ return binderStatusFromStatusT(status);
}
Status AudioPolicyService::getDeviceConnectionState(const media::AudioDevice& deviceAidl,
@@ -165,9 +168,13 @@
ALOGV("handleDeviceConfigChange()");
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
- return binderStatusFromStatusT(
- mAudioPolicyManager->handleDeviceConfigChange(device, deviceAidl.address.c_str(),
- deviceNameAidl.c_str(), encodedFormat));
+ status_t status = mAudioPolicyManager->handleDeviceConfigChange(
+ device, deviceAidl.address.c_str(), deviceNameAidl.c_str(), encodedFormat);
+
+ if (status == NO_ERROR) {
+ onCheckSpatializer_l();
+ }
+ return binderStatusFromStatusT(status);
}
Status AudioPolicyService::setPhoneState(media::AudioMode stateAidl, int32_t uidAidl)
@@ -234,6 +241,7 @@
Mutex::Autolock _l(mLock);
AutoCallerClear acc;
mAudioPolicyManager->setForceUse(usage, config);
+ onCheckSpatializer_l();
return Status::ok();
}
@@ -2062,8 +2070,11 @@
return binderStatusFromStatusT(NO_INIT);
}
Mutex::Autolock _l(mLock);
- return binderStatusFromStatusT(
- mAudioPolicyManager->setDevicesRoleForStrategy(strategy, role, devices));
+ status_t status = mAudioPolicyManager->setDevicesRoleForStrategy(strategy, role, devices);
+ if (status == NO_ERROR) {
+ onCheckSpatializer_l();
+ }
+ return binderStatusFromStatusT(status);
}
Status AudioPolicyService::removeDevicesRoleForStrategy(int32_t strategyAidl,
@@ -2076,8 +2087,11 @@
return binderStatusFromStatusT(NO_INIT);
}
Mutex::Autolock _l(mLock);
- return binderStatusFromStatusT(
- mAudioPolicyManager->removeDevicesRoleForStrategy(strategy, role));
+ status_t status = mAudioPolicyManager->removeDevicesRoleForStrategy(strategy, role);
+ if (status == NO_ERROR) {
+ onCheckSpatializer_l();
+ }
+ return binderStatusFromStatusT(status);
}
Status AudioPolicyService::getDevicesForRoleAndStrategy(
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index 56c472b..de71a00 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -366,41 +366,51 @@
void AudioPolicyService::onCheckSpatializer()
{
Mutex::Autolock _l(mLock);
- mOutputCommandThread->checkSpatializerCommand();
+ onCheckSpatializer_l();
+}
+
+void AudioPolicyService::onCheckSpatializer_l()
+{
+ if (mSpatializer != nullptr) {
+ mOutputCommandThread->checkSpatializerCommand();
+ }
}
void AudioPolicyService::doOnCheckSpatializer()
{
- sp<Spatializer> spatializer;
- {
- Mutex::Autolock _l(mLock);
- spatializer = mSpatializer;
+ Mutex::Autolock _l(mLock);
- 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);
+ if (mSpatializer != nullptr) {
+ if (mSpatializer->getLevel() != media::SpatializationLevel::NONE) {
+ audio_io_handle_t currentOutput = mSpatializer->getOutput();
+ audio_io_handle_t newOutput;
+ const audio_attributes_t attr = attributes_initializer(AUDIO_USAGE_MEDIA);
+ audio_config_base_t config = mSpatializer->getAudioInConfig();
+ status_t status =
+ mAudioPolicyManager->getSpatializerOutput(&config, &attr, &newOutput);
+
+ if (status == NO_ERROR && currentOutput == newOutput) {
+ return;
+ }
+ mLock.unlock();
+ // It is OK to call detachOutput() is none is already attached.
+ mSpatializer->detachOutput();
+ if (status != NO_ERROR || newOutput == AUDIO_IO_HANDLE_NONE) {
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);
- }
+ return;
+ }
+ status = mSpatializer->attachOutput(newOutput);
+ mLock.lock();
+ if (status != NO_ERROR) {
+ mAudioPolicyManager->releaseSpatializerOutput(newOutput);
+ }
+ } else if (mSpatializer->getLevel() == media::SpatializationLevel::NONE
+ && mSpatializer->getOutput() != AUDIO_IO_HANDLE_NONE) {
+ mLock.unlock();
+ audio_io_handle_t output = mSpatializer->detachOutput();
+ mLock.lock();
+ if (output != AUDIO_IO_HANDLE_NONE) {
+ mAudioPolicyManager->releaseSpatializerOutput(output);
}
}
}
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index b897a44..27c4e1c 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -327,6 +327,7 @@
* by audio policy manager and attach/detach the spatializer effect accordingly.
*/
void onCheckSpatializer() override;
+ void onCheckSpatializer_l();
void doOnCheckSpatializer();
void setEffectSuspended(int effectId,