audo policy: add effects to record clients
Add list of active effects on input streams and record
clients for further reporting in AudioRecordingConfiguration.
Bug: 111438757
Test: make and dumpsys
Change-Id: I1ae00d2431c80b053f67e2b780f368d5a4822b01
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index 9f8b8c0..afd599f 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -23,6 +23,7 @@
#include "AudioIODescriptorInterface.h"
#include "AudioPort.h"
#include "ClientDescriptor.h"
+#include "EffectDescriptor.h"
namespace android {
@@ -62,7 +63,8 @@
bool isSoundTrigger() const;
void setClientActive(const sp<RecordClientDescriptor>& client, bool active);
int32_t activeCount() { return mGlobalActiveCount; }
-
+ void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
+ EffectDescriptorCollection getEnabledEffects() const;
// implementation of AudioIODescriptorInterface
audio_config_base_t getConfig() const override;
audio_patch_handle_t getPatchHandle() const override;
@@ -86,6 +88,9 @@
RecordClientVector clientsList(bool activeOnly = false,
audio_source_t source = AUDIO_SOURCE_DEFAULT, bool preferredDeviceOnly = false) const;
+ // implementation of ClientMapHandler<RecordClientDescriptor>
+ void addClient(const sp<RecordClientDescriptor> &client) override;
+
private:
void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
@@ -101,6 +106,7 @@
SortedVector<audio_session_t> mPreemptedSessions;
AudioPolicyClientInterface * const mClientInterface;
int32_t mGlobalActiveCount = 0; // non-client-specific activity ref count
+ EffectDescriptorCollection mEnabledEffects;
};
class AudioInputCollection :
@@ -126,6 +132,8 @@
sp<AudioInputDescriptor> getInputForClient(audio_port_handle_t portId);
+ void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
+
void dump(String8 *dst) const;
};
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index 986d109..a187029 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -28,6 +28,7 @@
#include <utils/RefBase.h>
#include <utils/String8.h>
#include "AudioPatch.h"
+#include "EffectDescriptor.h"
#include "RoutingStrategy.h"
namespace android {
@@ -119,13 +120,15 @@
void setAppState(app_state_t appState) { mAppState = appState; }
app_state_t appState() { return mAppState; }
bool isSilenced() const { return mAppState == APP_STATE_IDLE; }
+ void trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled);
+ EffectDescriptorCollection getEnabledEffects() const { return mEnabledEffects; }
private:
const audio_source_t mSource;
const audio_input_flags_t mFlags;
const bool mIsSoundTrigger;
app_state_t mAppState;
-
+ EffectDescriptorCollection mEnabledEffects;
};
class SourceClientDescriptor: public TrackClientDescriptor
@@ -172,7 +175,7 @@
virtual ~ClientMapHandler() = default;
// Track client management
- void addClient(const sp<T> &client) {
+ virtual void addClient(const sp<T> &client) {
const audio_port_handle_t portId = client->portId();
LOG_ALWAYS_FATAL_IF(!mClients.emplace(portId, client).second,
"%s(%d): attempting to add client that already exists", __func__, portId);
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index 9fa7486..2dc33ab 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -25,12 +25,12 @@
namespace android {
-
class EffectDescriptor : public RefBase
{
public:
- void dump(String8 *dst) const;
+ void dump(String8 *dst, int spaces = 0) const;
+ int mId; // effect unique ID
int mIo; // io the effect is attached to
routing_strategy mStrategy; // routing strategy the effect is associated to
int mSession; // audio session the effect is on
@@ -46,12 +46,14 @@
status_t registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io,
uint32_t strategy, int session, int id);
status_t unregisterEffect(int id);
+ sp<EffectDescriptor> getEffect(int id) const;
status_t setEffectEnabled(int id, bool enabled);
+ bool isEffectEnabled(int id) const;
uint32_t getMaxEffectsCpuLoad() const;
uint32_t getMaxEffectsMemory() const;
- bool isNonOffloadableEffectEnabled();
+ bool isNonOffloadableEffectEnabled() const;
- void dump(String8 *dst) const;
+ void dump(String8 *dst, int spaces = 0, bool verbose = true) const;
private:
status_t setEffectEnabled(const sp<EffectDescriptor> &effectDesc, bool enabled);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 559274f..409e7d8 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -269,6 +269,16 @@
}
}
+void AudioInputDescriptor::addClient(const sp<RecordClientDescriptor> &client) {
+ ClientMapHandler<RecordClientDescriptor>::addClient(client);
+
+ for (size_t i = 0; i < mEnabledEffects.size(); i++) {
+ if (mEnabledEffects.valueAt(i)->mSession == client->session()) {
+ client->trackEffectEnabled(mEnabledEffects.valueAt(i), true);
+ }
+ }
+}
+
void AudioInputDescriptor::setClientActive(const sp<RecordClientDescriptor>& client, bool active)
{
LOG_ALWAYS_FATAL_IF(getClient(client->portId()) == nullptr,
@@ -345,6 +355,33 @@
return clients;
}
+void AudioInputDescriptor::trackEffectEnabled(const sp<EffectDescriptor> &effect,
+ bool enabled)
+{
+ RecordClientVector clients = getClientsForSession((audio_session_t)effect->mSession);
+ for (const auto& client : clients) {
+ client->trackEffectEnabled(effect, enabled);
+ }
+
+ if (enabled) {
+ mEnabledEffects.replaceValueFor(effect->mId, effect);
+ } else {
+ mEnabledEffects.removeItem(effect->mId);
+ }
+}
+
+EffectDescriptorCollection AudioInputDescriptor::getEnabledEffects() const
+{
+ EffectDescriptorCollection enabledEffects;
+ // report effects for highest priority active source as applied to all clients
+ RecordClientVector clients =
+ clientsList(true /*activeOnly*/, source(), false /*preferredDeviceOnly*/);
+ if (clients.size() > 0) {
+ enabledEffects = clients[0]->getEnabledEffects();
+ }
+ return enabledEffects;
+}
+
void AudioInputDescriptor::dump(String8 *dst) const
{
dst->appendFormat(" ID: %d\n", getId());
@@ -352,6 +389,7 @@
dst->appendFormat(" Format: %d\n", mFormat);
dst->appendFormat(" Channels: %08x\n", mChannelMask);
dst->appendFormat(" Devices %08x\n", mDevice);
+ getEnabledEffects().dump(dst, 1 /*spaces*/, false /*verbose*/);
dst->append(" AudioRecord Clients:\n");
ClientMapHandler<RecordClientDescriptor>::dump(dst);
dst->append("\n");
@@ -424,6 +462,17 @@
return 0;
}
+void AudioInputCollection::trackEffectEnabled(const sp<EffectDescriptor> &effect,
+ bool enabled)
+{
+ for (size_t i = 0; i < size(); i++) {
+ sp<AudioInputDescriptor> inputDesc = valueAt(i);
+ if (inputDesc->mIoHandle == effect->mIo) {
+ return inputDesc->trackEffectEnabled(effect, enabled);
+ }
+ }
+}
+
void AudioInputCollection::dump(String8 *dst) const
{
dst->append("\nInputs dump:\n");
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 815612d..82d64c9 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -63,10 +63,20 @@
return ss.str();
}
+void RecordClientDescriptor::trackEffectEnabled(const sp<EffectDescriptor> &effect, bool enabled)
+{
+ if (enabled) {
+ mEnabledEffects.replaceValueFor(effect->mId, effect);
+ } else {
+ mEnabledEffects.removeItem(effect->mId);
+ }
+}
+
void RecordClientDescriptor::dump(String8 *dst, int spaces, int index) const
{
ClientDescriptor::dump(dst, spaces, index);
dst->appendFormat("%*s- Source: %d flags: %08x\n", spaces, "", mSource, mFlags);
+ mEnabledEffects.dump(dst, spaces + 2 /*spaces*/, false /*verbose*/);
}
SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t uid,
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 8bbb798..40c49e7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -22,13 +22,13 @@
namespace android {
-void EffectDescriptor::dump(String8 *dst) const
+void EffectDescriptor::dump(String8 *dst, int spaces) const
{
- dst->appendFormat(" I/O: %d\n", mIo);
- dst->appendFormat(" Strategy: %d\n", mStrategy);
- dst->appendFormat(" Session: %d\n", mSession);
- dst->appendFormat(" Name: %s\n", mDesc.name);
- dst->appendFormat(" %s\n", mEnabled ? "Enabled" : "Disabled");
+ dst->appendFormat("%*sI/O: %d\n", spaces, "", mIo);
+ dst->appendFormat("%*sStrategy: %d\n", spaces, "", mStrategy);
+ dst->appendFormat("%*sSession: %d\n", spaces, "", mSession);
+ dst->appendFormat("%*sName: %s\n", spaces, "", mDesc.name);
+ dst->appendFormat("%*s%s\n", spaces, "", mEnabled ? "Enabled" : "Disabled");
}
EffectDescriptorCollection::EffectDescriptorCollection() :
@@ -45,6 +45,11 @@
int session,
int id)
{
+ if (getEffect(id) != nullptr) {
+ ALOGW("%s effect %s already registered", __FUNCTION__, desc->name);
+ return INVALID_OPERATION;
+ }
+
if (mTotalEffectsMemory + desc->memoryUsage > getMaxEffectsMemory()) {
ALOGW("registerEffect() memory limit exceeded for Fx %s, Memory %d KB",
desc->name, desc->memoryUsage);
@@ -60,6 +65,7 @@
sp<EffectDescriptor> effectDesc = new EffectDescriptor();
memcpy (&effectDesc->mDesc, desc, sizeof(effect_descriptor_t));
+ effectDesc->mId = id;
effectDesc->mIo = io;
effectDesc->mStrategy = static_cast<routing_strategy>(strategy);
effectDesc->mSession = session;
@@ -70,18 +76,23 @@
return NO_ERROR;
}
-status_t EffectDescriptorCollection::unregisterEffect(int id)
+sp<EffectDescriptor> EffectDescriptorCollection::getEffect(int id) const
{
ssize_t index = indexOfKey(id);
if (index < 0) {
- ALOGW("unregisterEffect() unknown effect ID %d", id);
+ return nullptr;
+ }
+ return valueAt(index);
+}
+
+status_t EffectDescriptorCollection::unregisterEffect(int id)
+{
+ sp<EffectDescriptor> effectDesc = getEffect(id);
+ if (effectDesc == nullptr) {
+ ALOGW("%s unknown effect ID %d", __FUNCTION__, id);
return INVALID_OPERATION;
}
- sp<EffectDescriptor> effectDesc = valueAt(index);
-
- setEffectEnabled(effectDesc, false);
-
if (mTotalEffectsMemory < effectDesc->mDesc.memoryUsage) {
ALOGW("unregisterEffect() memory %d too big for total %d",
effectDesc->mDesc.memoryUsage, mTotalEffectsMemory);
@@ -107,6 +118,14 @@
return setEffectEnabled(valueAt(index), enabled);
}
+bool EffectDescriptorCollection::isEffectEnabled(int id) const
+{
+ ssize_t index = indexOfKey(id);
+ if (index < 0) {
+ return false;
+ }
+ return valueAt(index)->mEnabled;
+}
status_t EffectDescriptorCollection::setEffectEnabled(const sp<EffectDescriptor> &effectDesc,
bool enabled)
@@ -138,7 +157,7 @@
return NO_ERROR;
}
-bool EffectDescriptorCollection::isNonOffloadableEffectEnabled()
+bool EffectDescriptorCollection::isNonOffloadableEffectEnabled() const
{
for (size_t i = 0; i < size(); i++) {
sp<EffectDescriptor> effectDesc = valueAt(i);
@@ -162,15 +181,21 @@
return MAX_EFFECTS_MEMORY;
}
-void EffectDescriptorCollection::dump(String8 *dst) const
+void EffectDescriptorCollection::dump(String8 *dst, int spaces, bool verbose) const
{
- dst->appendFormat(
- "\nTotal Effects CPU: %f MIPS, Total Effects memory: %d KB, Max memory used: %d KB\n",
- (float)mTotalEffectsCpuLoad/10, mTotalEffectsMemory, mTotalEffectsMemoryMaxUsed);
- dst->append("Registered effects:\n");
+ if (verbose) {
+ dst->appendFormat(
+ "\n%*sTotal Effects CPU: %f MIPS, "
+ "Total Effects memory: %d KB, Max memory used: %d KB\n",
+ spaces, "",
+ (float) mTotalEffectsCpuLoad / 10,
+ mTotalEffectsMemory,
+ mTotalEffectsMemoryMaxUsed);
+ }
+ dst->appendFormat("%*sEffects:\n", spaces, "");
for (size_t i = 0; i < size(); i++) {
- dst->appendFormat("- Effect %d dump:\n", keyAt(i));
- valueAt(i)->dump(dst);
+ dst->appendFormat("%*s- Effect %d:\n", spaces, "", keyAt(i));
+ valueAt(i)->dump(dst, spaces + 2);
}
}
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 64a2b8a..3686f2d 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2423,6 +2423,33 @@
return mEffects.registerEffect(desc, io, strategy, session, id);
}
+status_t AudioPolicyManager::unregisterEffect(int id)
+{
+ if (mEffects.getEffect(id) == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ if (mEffects.isEffectEnabled(id)) {
+ ALOGW("%s effect %d enabled", __FUNCTION__, id);
+ setEffectEnabled(id, false);
+ }
+ return mEffects.unregisterEffect(id);
+}
+
+status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled)
+{
+ sp<EffectDescriptor> effect = mEffects.getEffect(id);
+ if (effect == nullptr) {
+ return INVALID_OPERATION;
+ }
+
+ status_t status = mEffects.setEffectEnabled(id, enabled);
+ if (status == NO_ERROR) {
+ mInputs.trackEffectEnabled(effect, enabled);
+ }
+ return status;
+}
+
bool AudioPolicyManager::isStreamActive(audio_stream_type_t stream, uint32_t inPastMs) const
{
bool active = false;
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 86993d4..35dd87c 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -164,14 +164,8 @@
uint32_t strategy,
int session,
int id);
- virtual status_t unregisterEffect(int id)
- {
- return mEffects.unregisterEffect(id);
- }
- virtual status_t setEffectEnabled(int id, bool enabled)
- {
- return mEffects.setEffectEnabled(id, enabled);
- }
+ virtual status_t unregisterEffect(int id);
+ virtual status_t setEffectEnabled(int id, bool enabled);
virtual bool isStreamActive(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
// return whether a stream is playing remotely, override to change the definition of