Merge "audio policy: output selection upon dynamic policy registration" into rvc-dev
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 0c5d1d0..923310c 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -35,6 +35,7 @@
namespace android {
+class AudioPolicyMix;
class DeviceDescriptor;
class HwAudioOutputDescriptor;
class SwAudioOutputDescriptor;
@@ -90,11 +91,12 @@
product_strategy_t strategy, VolumeSource volumeSource,
audio_output_flags_t flags,
bool isPreferredDeviceForExclusiveUse,
- std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs) :
+ std::vector<wp<SwAudioOutputDescriptor>> secondaryOutputs,
+ wp<AudioPolicyMix> primaryMix) :
ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId,
isPreferredDeviceForExclusiveUse),
mStream(stream), mStrategy(strategy), mVolumeSource(volumeSource), mFlags(flags),
- mSecondaryOutputs(std::move(secondaryOutputs)) {}
+ mSecondaryOutputs(std::move(secondaryOutputs)), mPrimaryMix(primaryMix) {}
~TrackClientDescriptor() override = default;
using ClientDescriptor::dump;
@@ -108,6 +110,9 @@
return mSecondaryOutputs;
};
VolumeSource volumeSource() const { return mVolumeSource; }
+ const sp<AudioPolicyMix> getPrimaryMix() const {
+ return mPrimaryMix.promote();
+ };
void setActive(bool active) override
{
@@ -136,7 +141,7 @@
const VolumeSource mVolumeSource;
const audio_output_flags_t mFlags;
const std::vector<wp<SwAudioOutputDescriptor>> mSecondaryOutputs;
-
+ const wp<AudioPolicyMix> mPrimaryMix;
/**
* required for duplicating thread, prevent from removing active client from an output
* involved in a duplication.
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index fc1a59f..b6de4be 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -28,7 +28,7 @@
void AudioPolicyMix::dump(String8 *dst, int spaces, int index) const
{
- dst->appendFormat("%*sAudio Policy Mix %d:\n", spaces, "", index + 1);
+ dst->appendFormat("%*sAudio Policy Mix %d (%p):\n", spaces, "", index + 1, this);
std::string mixTypeLiteral;
if (!MixTypeConverter::toString(mMixType, mixTypeLiteral)) {
ALOGE("%s: failed to convert mix type %d", __FUNCTION__, mMixType);
@@ -44,6 +44,9 @@
dst->appendFormat("%*s- device address: %s\n", spaces, "", mDeviceAddress.string());
+ dst->appendFormat("%*s- output: %d\n", spaces, "",
+ mOutput == nullptr ? 0 : mOutput->mIoHandle);
+
int indexCriterion = 0;
for (const auto &criterion : mCriteria) {
dst->appendFormat("%*s- Criterion %d: ", spaces + 2, "", indexCriterion++);
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 95822b9..afc4d01 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -23,6 +23,7 @@
#include <TypeConverter.h>
#include "AudioOutputDescriptor.h"
#include "AudioPatch.h"
+#include "AudioPolicyMix.h"
#include "ClientDescriptor.h"
#include "DeviceDescriptor.h"
#include "HwModule.h"
@@ -55,6 +56,12 @@
ClientDescriptor::dump(dst, spaces, index);
dst->appendFormat("%*s- Stream: %d flags: %08x\n", spaces, "", mStream, mFlags);
dst->appendFormat("%*s- Refcount: %d\n", spaces, "", mActivityCount);
+ dst->appendFormat("%*s- DAP Primary Mix: %p\n", spaces, "", mPrimaryMix.promote().get());
+ dst->appendFormat("%*s- DAP Secondary Outputs:\n", spaces, "");
+ for (auto desc : mSecondaryOutputs) {
+ dst->appendFormat("%*s - %d\n", spaces, "",
+ desc.promote() == nullptr ? 0 : desc.promote()->mIoHandle);
+ }
}
std::string TrackClientDescriptor::toShortString() const
@@ -88,7 +95,7 @@
TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes,
{config.sample_rate, config.channel_mask, config.format}, AUDIO_PORT_HANDLE_NONE,
stream, strategy, volumeSource, AUDIO_OUTPUT_FLAG_NONE, false,
- {} /* Sources do not support secondary outputs*/), mSrcDevice(srcDevice)
+ {} /* Sources do not support secondary outputs*/, nullptr), mSrcDevice(srcDevice)
{
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index f05be06..3730c34 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -1102,14 +1102,15 @@
};
*portId = PolicyAudioPort::getNextUniqueId();
+ sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
sp<TrackClientDescriptor> clientDesc =
new TrackClientDescriptor(*portId, uid, session, resultAttr, clientConfig,
sanitizedRequestedPortId, *stream,
mEngine->getProductStrategyForAttributes(resultAttr),
toVolumeSource(resultAttr),
*flags, isRequestedDeviceForExclusiveUse,
- std::move(weakSecondaryOutputDescs));
- sp<SwAudioOutputDescriptor> outputDesc = mOutputs.valueFor(*output);
+ std::move(weakSecondaryOutputDescs),
+ outputDesc->mPolicyMix);
outputDesc->addClient(clientDesc);
ALOGV("%s() returns output %d requestedPortId %d selectedDeviceId %d for port ID %d", __func__,
@@ -2877,7 +2878,7 @@
{
ALOGV("registerPolicyMixes() %zu mix(es)", mixes.size());
status_t res = NO_ERROR;
-
+ bool checkOutputs = false;
sp<HwModule> rSubmixModule;
// examine each mix's route type
for (size_t i = 0; i < mixes.size(); i++) {
@@ -2996,11 +2997,16 @@
i, type, address.string());
res = INVALID_OPERATION;
break;
+ } else {
+ checkOutputs = true;
}
}
}
if (res != NO_ERROR) {
unregisterPolicyMixes(mixes);
+ } else if (checkOutputs) {
+ checkForDeviceAndOutputChanges();
+ updateCallAndOutputRouting();
}
return res;
}
@@ -3009,6 +3015,7 @@
{
ALOGV("unregisterPolicyMixes() num mixes %zu", mixes.size());
status_t res = NO_ERROR;
+ bool checkOutputs = false;
sp<HwModule> rSubmixModule;
// examine each mix's route type
for (const auto& mix : mixes) {
@@ -3049,9 +3056,15 @@
if (mPolicyMixes.unregisterMix(mix) != NO_ERROR) {
res = INVALID_OPERATION;
continue;
+ } else {
+ checkOutputs = true;
}
}
}
+ if (res == NO_ERROR && checkOutputs) {
+ checkForDeviceAndOutputChanges();
+ updateCallAndOutputRouting();
+ }
return res;
}
@@ -5226,32 +5239,38 @@
SortedVector<audio_io_handle_t> srcOutputs = getOutputsForDevices(oldDevices, mPreviousOutputs);
SortedVector<audio_io_handle_t> dstOutputs = getOutputsForDevices(newDevices, mOutputs);
- // also take into account external policy-related changes: add all outputs which are
- // associated with policies in the "before" and "after" output vectors
- ALOGVV("%s(): policy related outputs", __func__);
- bool hasDynamicPolicy = false;
- for (size_t i = 0 ; i < mPreviousOutputs.size() ; i++) {
- const sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueAt(i);
- if (desc != 0 && desc->mPolicyMix != NULL) {
- srcOutputs.add(desc->mIoHandle);
- hasDynamicPolicy = true;
- ALOGVV(" previous outputs: adding %d", desc->mIoHandle);
+ uint32_t maxLatency = 0;
+ bool invalidate = false;
+ // take into account dynamic audio policies related changes: if a client is now associated
+ // to a different policy mix than at creation time, invalidate corresponding stream
+ for (size_t i = 0; i < mPreviousOutputs.size() && !invalidate; i++) {
+ const sp<SwAudioOutputDescriptor>& desc = mPreviousOutputs.valueAt(i);
+ if (desc->isDuplicated()) {
+ continue;
}
- }
- for (size_t i = 0 ; i < mOutputs.size() ; i++) {
- const sp<SwAudioOutputDescriptor> desc = mOutputs.valueAt(i);
- if (desc != 0 && desc->mPolicyMix != NULL) {
- dstOutputs.add(desc->mIoHandle);
- hasDynamicPolicy = true;
- ALOGVV(" new outputs: adding %d", desc->mIoHandle);
+ for (const sp<TrackClientDescriptor>& client : desc->getClientIterable()) {
+ if (mEngine->getProductStrategyForAttributes(client->attributes()) != psId) {
+ continue;
+ }
+ sp<AudioPolicyMix> primaryMix;
+ status_t status = mPolicyMixes.getOutputForAttr(client->attributes(), client->uid(),
+ client->flags(), primaryMix, nullptr);
+ if (status != OK) {
+ continue;
+ }
+ if (client->getPrimaryMix() != primaryMix) {
+ invalidate = true;
+ if (desc->isStrategyActive(psId)) {
+ maxLatency = desc->latency();
+ }
+ break;
+ }
}
}
- if (srcOutputs != dstOutputs) {
+ if (srcOutputs != dstOutputs || invalidate) {
// get maximum latency of all source outputs to determine the minimum mute time guaranteeing
// audio from invalidated tracks will be rendered when unmuting
- uint32_t maxLatency = 0;
- bool invalidate = hasDynamicPolicy;
for (audio_io_handle_t srcOut : srcOutputs) {
sp<SwAudioOutputDescriptor> desc = mPreviousOutputs.valueFor(srcOut);
if (desc == nullptr) continue;