audiopolicy: apm: switch to new Engine APIs
Test: make
Change-Id: Iedc2268852ee0bce32b67cfd324395c48cb33424
Signed-off-by: François Gaffie <francois.gaffie@renault.com>
diff --git a/services/audiopolicy/common/include/policy.h b/services/audiopolicy/common/include/policy.h
index b90a08d..605fc1c 100644
--- a/services/audiopolicy/common/include/policy.h
+++ b/services/audiopolicy/common/include/policy.h
@@ -23,7 +23,6 @@
using StreamTypeVector = std::vector<audio_stream_type_t>;
-
static const audio_attributes_t defaultAttr = AUDIO_ATTRIBUTES_INITIALIZER;
} // namespace android
@@ -163,3 +162,25 @@
}
return format1 == format2;
}
+
+/**
+ * @brief hasStream checks if a given stream type is found in the list of streams
+ * @param streams collection of stream types to consider.
+ * @param streamType to consider
+ * @return true if voice stream is found in the given streams, false otherwise
+ */
+static inline bool hasStream(const android::StreamTypeVector &streams,
+ audio_stream_type_t streamType)
+{
+ return std::find(begin(streams), end(streams), streamType) != end(streams);
+}
+
+/**
+ * @brief hasVoiceStream checks if a voice stream is found in the list of streams
+ * @param streams collection to consider.
+ * @return true if voice stream is found in the given streams, false otherwise
+ */
+static inline bool hasVoiceStream(const android::StreamTypeVector &streams)
+{
+ return hasStream(streams, AUDIO_STREAM_VOICE_CALL);
+}
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
index 555412e..6e29632 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioIODescriptorInterface.h
@@ -16,6 +16,8 @@
#pragma once
+#include "DeviceDescriptor.h"
+
namespace android {
/**
@@ -34,4 +36,36 @@
virtual void setPatchHandle(audio_patch_handle_t handle) = 0;
};
+template <class IoDescriptor, class Filter>
+sp<DeviceDescriptor> findPreferredDevice(
+ IoDescriptor& desc, Filter filter, bool& active, const DeviceVector& devices)
+{
+ auto activeClients = desc->clientsList(true /*activeOnly*/);
+ auto activeClientsWithRoute =
+ desc->clientsList(true /*activeOnly*/, filter, true /*preferredDevice*/);
+ active = activeClients.size() > 0;
+ if (active && activeClients.size() == activeClientsWithRoute.size()) {
+ return devices.getDeviceFromId(activeClientsWithRoute[0]->preferredDeviceId());
+ }
+ return nullptr;
+}
+
+template <class IoCollection, class Filter>
+sp<DeviceDescriptor> findPreferredDevice(
+ IoCollection& ioCollection, Filter filter, const DeviceVector& devices)
+{
+ sp<DeviceDescriptor> device;
+ for (size_t i = 0; i < ioCollection.size(); i++) {
+ auto desc = ioCollection.valueAt(i);
+ bool active;
+ sp<DeviceDescriptor> curDevice = findPreferredDevice(desc, filter, active, devices);
+ if (active && curDevice == nullptr) {
+ return nullptr;
+ } else if (curDevice != nullptr) {
+ device = curDevice;
+ }
+ }
+ return device;
+}
+
} // namespace android
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
index e1ecc61..6132bb4 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioOutputDescriptor.h
@@ -16,18 +16,20 @@
#pragma once
+#define __STDC_LIMIT_MACROS
+#include <inttypes.h>
+
#include <sys/types.h>
#include <utils/Errors.h>
#include <utils/Timers.h>
#include <utils/KeyedVector.h>
#include <system/audio.h>
-#include <RoutingStrategy.h>
#include "AudioIODescriptorInterface.h"
#include "AudioPort.h"
#include "ClientDescriptor.h"
#include "DeviceDescriptor.h"
-#include <map>
+#include <vector>
namespace android {
@@ -35,6 +37,70 @@
class AudioMix;
class AudioPolicyClientInterface;
+class ActivityTracking
+{
+public:
+ virtual ~ActivityTracking() = default;
+ bool isActive(uint32_t inPastMs = 0, nsecs_t sysTime = 0) const
+ {
+ if (mActivityCount > 0) {
+ return true;
+ }
+ if (inPastMs == 0) {
+ return false;
+ }
+ if (sysTime == 0) {
+ sysTime = systemTime();
+ }
+ if (ns2ms(sysTime - mStopTime) < inPastMs) {
+ return true;
+ }
+ return false;
+ }
+ void changeActivityCount(int delta)
+ {
+ if ((delta + (int)mActivityCount) < 0) {
+ LOG_ALWAYS_FATAL("%s: invalid delta %d, refCount %d", __func__, delta, mActivityCount);
+ }
+ mActivityCount += delta;
+ if (!mActivityCount) {
+ setStopTime(systemTime());
+ }
+ }
+ uint32_t getActivityCount() const { return mActivityCount; }
+ nsecs_t getStopTime() const { return mStopTime; }
+ void setStopTime(nsecs_t stopTime) { mStopTime = stopTime; }
+
+ virtual void dump(String8 *dst, int spaces) const
+ {
+ dst->appendFormat("%*s- ActivityCount: %d, StopTime: %" PRId64 " \n", spaces, "",
+ getActivityCount(), getStopTime());
+ }
+private:
+ uint32_t mActivityCount = 0;
+ nsecs_t mStopTime = 0;
+};
+
+/**
+ * @brief The Activity class: it tracks the activity for volume policy (volume index, mute,
+ * memorize previous stop, and store mute if incompatible device with another strategy.
+ * Having this class prevents from looping on all attributes (legacy streams) of the strategy
+ */
+class RoutingActivity : public ActivityTracking
+{
+public:
+ void setMutedByDevice( bool isMuted) { mIsMutedByDevice = isMuted; }
+ bool isMutedByDevice() const { return mIsMutedByDevice; }
+
+private:
+ /**
+ * strategies muted because of incompatible device selection.
+ * See AudioPolicyManager::checkDeviceMuteStrategies()
+ */
+ bool mIsMutedByDevice = false;
+};
+using RoutingActivities = std::map<product_strategy_t, RoutingActivity>;
+
// descriptor for audio outputs. Used to maintain current configuration of each opened audio output
// and keep track of the usage of this output by each audio stream type.
class AudioOutputDescriptor: public AudioPortConfig, public AudioIODescriptorInterface
@@ -71,6 +137,14 @@
{ return mActiveCount[stream]; }
/**
+ * @brief setStopTime set the stop time due to the client stoppage or a re routing of this
+ * client
+ * @param client to be considered
+ * @param sysTime when the client stopped/was rerouted
+ */
+ void setStopTime(const sp<TrackClientDescriptor>& client, nsecs_t sysTime);
+
+ /**
* Changes the client->active() state and the output descriptor's global active count,
* along with the stream active count and mActiveClients.
* The client must be previously added by the base class addClient().
@@ -82,6 +156,21 @@
uint32_t inPastMs = 0,
nsecs_t sysTime = 0) const;
+ bool isStrategyActive(product_strategy_t ps, uint32_t inPastMs = 0, nsecs_t sysTime = 0) const
+ {
+ return mRoutingActivities.find(ps) != std::end(mRoutingActivities)?
+ mRoutingActivities.at(ps).isActive(inPastMs, sysTime) : false;
+ }
+ bool isStrategyMutedByDevice(product_strategy_t ps) const
+ {
+ return mRoutingActivities.find(ps) != std::end(mRoutingActivities)?
+ mRoutingActivities.at(ps).isMutedByDevice() : false;
+ }
+ void setStrategyMutedByDevice(product_strategy_t ps, bool isMuted)
+ {
+ mRoutingActivities[ps].setMutedByDevice(isMuted);
+ }
+
virtual void toAudioPortConfig(struct audio_port_config *dstConfig,
const struct audio_port_config *srcConfig = NULL) const;
virtual sp<AudioPort> getAudioPort() const { return mPort; }
@@ -95,7 +184,8 @@
void setPatchHandle(audio_patch_handle_t handle) override;
TrackClientVector clientsList(bool activeOnly = false,
- routing_strategy strategy = STRATEGY_NONE, bool preferredDeviceOnly = false) const;
+ product_strategy_t strategy = PRODUCT_STRATEGY_NONE,
+ bool preferredDeviceOnly = false) const;
// override ClientMapHandler to abort when removing a client when active.
void removeClient(audio_port_handle_t portId) override {
@@ -121,8 +211,6 @@
DeviceVector mDevices; /**< current devices this output is routed to */
nsecs_t mStopTime[AUDIO_STREAM_CNT];
int mMuteCount[AUDIO_STREAM_CNT]; // mute request counter
- bool mStrategyMutedByDevice[NUM_STRATEGIES]; // strategies muted because of incompatible
- // device selection. See checkDeviceMuteStrategies()
AudioMix *mPolicyMix = nullptr; // non NULL when used by a dynamic policy
protected:
@@ -139,6 +227,8 @@
// Compare with the ClientMap (mClients) which are external AudioTrack clients of the
// output descriptor (and do not count internal PatchTracks).
ActiveClientMap mActiveClients;
+
+ RoutingActivities mRoutingActivities; /**< track routing activity on this ouput.*/
};
// Audio output driven by a software mixer in audio flinger.
@@ -275,6 +365,21 @@
bool isStreamActiveLocally(audio_stream_type_t stream, uint32_t inPastMs = 0) const;
/**
+ * @brief isStrategyActiveOnSameModule checks if the given strategy is active (or was active
+ * in the past) on the given output and all the outputs belonging to the same HW Module
+ * the same module than the given output
+ * @param outputDesc to be considered
+ * @param ps product strategy to be checked upon activity status
+ * @param inPastMs if 0, check currently, otherwise, check in the past
+ * @param sysTime shall be set if request is done for the past activity.
+ * @return true if an output following the strategy is active on the same module than desc,
+ * false otherwise
+ */
+ bool isStrategyActiveOnSameModule(product_strategy_t ps,
+ const sp<SwAudioOutputDescriptor>& desc,
+ uint32_t inPastMs = 0, nsecs_t sysTime = 0) const;
+
+ /**
* returns the A2DP output handle if it is open or 0 otherwise
*/
audio_io_handle_t getA2dpOutput() const;
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
index 2932296..7296c95 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioPolicyMix.h
@@ -78,7 +78,7 @@
sp<DeviceDescriptor> getDeviceAndMixForInputSource(audio_source_t inputSource,
const DeviceVector &availableDeviceTypes,
- AudioMix **policyMix);
+ AudioMix **policyMix) const;
/**
* @brief try to find a matching mix for a given output descriptor and returns the associated
diff --git a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
index a187029..2fb1277 100644
--- a/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/ClientDescriptor.h
@@ -22,14 +22,14 @@
#include <sys/types.h>
#include <system/audio.h>
-#include <system/audio_policy.h>
+#include <media/AudioProductStrategy.h>
#include <utils/Errors.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
#include <utils/String8.h>
+#include <policy.h>
#include "AudioPatch.h"
#include "EffectDescriptor.h"
-#include "RoutingStrategy.h"
namespace android {
@@ -81,7 +81,7 @@
TrackClientDescriptor(audio_port_handle_t portId, uid_t uid, audio_session_t sessionId,
audio_attributes_t attributes, audio_config_base_t config,
audio_port_handle_t preferredDeviceId, audio_stream_type_t stream,
- routing_strategy strategy, audio_output_flags_t flags) :
+ product_strategy_t strategy, audio_output_flags_t flags) :
ClientDescriptor(portId, uid, sessionId, attributes, config, preferredDeviceId),
mStream(stream), mStrategy(strategy), mFlags(flags) {}
~TrackClientDescriptor() override = default;
@@ -92,11 +92,11 @@
audio_output_flags_t flags() const { return mFlags; }
audio_stream_type_t stream() const { return mStream; }
- routing_strategy strategy() const { return mStrategy; }
+ product_strategy_t strategy() const { return mStrategy; }
private:
const audio_stream_type_t mStream;
- const routing_strategy mStrategy;
+ const product_strategy_t mStrategy;
const audio_output_flags_t mFlags;
};
@@ -136,7 +136,7 @@
public:
SourceClientDescriptor(audio_port_handle_t portId, uid_t uid, audio_attributes_t attributes,
const sp<AudioPatch>& patchDesc, const sp<DeviceDescriptor>& srcDevice,
- audio_stream_type_t stream, routing_strategy strategy);
+ audio_stream_type_t stream, product_strategy_t strategy);
~SourceClientDescriptor() override = default;
sp<AudioPatch> patchDesc() const { return mPatchDesc; }
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index 2dc33ab..7f01dc5 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -16,7 +16,7 @@
#pragma once
-#include <RoutingStrategy.h>
+#include <policy.h>
#include <system/audio_effect.h>
#include <utils/KeyedVector.h>
#include <utils/RefBase.h>
@@ -28,14 +28,26 @@
class EffectDescriptor : public RefBase
{
public:
+ EffectDescriptor(const effect_descriptor_t *desc, bool isMusicEffect,
+ int id, int io, int session) :
+ mId(id), mIo(io), mSession(session), mEnabled(false),
+ mIsMusicEffect(isMusicEffect)
+ {
+ memcpy (&mDesc, desc, sizeof(effect_descriptor_t));
+ }
+
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
effect_descriptor_t mDesc; // effect descriptor
bool mEnabled; // enabled state: CPU load being used or not
+
+ bool isMusicEffect() const { return mIsMusicEffect; }
+
+private:
+ bool mIsMusicEffect;
};
class EffectDescriptorCollection : public KeyedVector<int, sp<EffectDescriptor> >
@@ -44,7 +56,7 @@
EffectDescriptorCollection();
status_t registerEffect(const effect_descriptor_t *desc, audio_io_handle_t io,
- uint32_t strategy, int session, int id);
+ int session, int id, bool isMusicEffect);
status_t unregisterEffect(int id);
sp<EffectDescriptor> getEffect(int id) const;
status_t setEffectEnabled(int id, bool enabled);
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
index 78b3f45..d997bf7 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioOutputDescriptor.cpp
@@ -44,9 +44,6 @@
mMuteCount[i] = 0;
mStopTime[i] = 0;
}
- for (int i = 0; i < NUM_STRATEGIES; i++) {
- mStrategyMutedByDevice[i] = false;
- }
if (mPort.get() != nullptr) {
mPort->pickAudioProfile(mSamplingRate, mChannelMask, mFormat);
if (mPort->mGains.size() > 0) {
@@ -101,6 +98,7 @@
// return;
}
mActiveCount[stream] += delta;
+ mRoutingActivities[client->strategy()].changeActivityCount(delta);
if (delta > 0) {
mActiveClients[client] += delta;
@@ -122,6 +120,12 @@
ALOGV("%s stream %d, count %d", __FUNCTION__, stream, mActiveCount[stream]);
}
+void AudioOutputDescriptor::setStopTime(const sp<TrackClientDescriptor>& client, nsecs_t sysTime)
+{
+ mStopTime[client->stream()] = sysTime;
+ mRoutingActivities[client->strategy()].setStopTime(sysTime);
+}
+
void AudioOutputDescriptor::setClientActive(const sp<TrackClientDescriptor>& client, bool active)
{
LOG_ALWAYS_FATAL_IF(getClient(client->portId()) == nullptr,
@@ -247,13 +251,13 @@
port->ext.mix.hw_module = getModuleHandle();
}
-TrackClientVector AudioOutputDescriptor::clientsList(bool activeOnly, routing_strategy strategy,
+TrackClientVector AudioOutputDescriptor::clientsList(bool activeOnly, product_strategy_t strategy,
bool preferredDeviceOnly) const
{
TrackClientVector clients;
for (const auto &client : getClientIterable()) {
if ((!activeOnly || client->active())
- && (strategy == STRATEGY_NONE || strategy == client->strategy())
+ && (strategy == PRODUCT_STRATEGY_NONE || strategy == client->strategy())
&& (!preferredDeviceOnly || client->hasPreferredDevice())) {
clients.push_back(client);
}
@@ -698,6 +702,20 @@
return false;
}
+bool SwAudioOutputCollection::isStrategyActiveOnSameModule(product_strategy_t ps,
+ const sp<SwAudioOutputDescriptor>& desc,
+ uint32_t inPastMs, nsecs_t sysTime) const
+{
+ for (size_t i = 0; i < size(); i++) {
+ const sp<SwAudioOutputDescriptor> otherDesc = valueAt(i);
+ if (desc->sharesHwModuleWith(otherDesc) &&
+ otherDesc->isStrategyActive(ps, inPastMs, sysTime)) {
+ return true;
+ }
+ }
+ return false;
+}
+
audio_io_handle_t SwAudioOutputCollection::getA2dpOutput() const
{
for (size_t i = 0; i < size(); i++) {
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
index cd10c82..2489e76 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioPolicyMix.cpp
@@ -302,7 +302,7 @@
}
sp<DeviceDescriptor> AudioPolicyMixCollection::getDeviceAndMixForInputSource(
- audio_source_t inputSource, const DeviceVector &availDevices, AudioMix **policyMix)
+ audio_source_t inputSource, const DeviceVector &availDevices, AudioMix **policyMix) const
{
for (size_t i = 0; i < size(); i++) {
AudioMix *mix = valueAt(i)->getMix();
diff --git a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
index 82d64c9..1525285 100644
--- a/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/ClientDescriptor.cpp
@@ -82,7 +82,7 @@
SourceClientDescriptor::SourceClientDescriptor(audio_port_handle_t portId, uid_t uid,
audio_attributes_t attributes, const sp<AudioPatch>& patchDesc,
const sp<DeviceDescriptor>& srcDevice, audio_stream_type_t stream,
- routing_strategy strategy) :
+ product_strategy_t strategy) :
TrackClientDescriptor::TrackClientDescriptor(portId, uid, AUDIO_SESSION_NONE, attributes,
AUDIO_CONFIG_BASE_INITIALIZER, AUDIO_PORT_HANDLE_NONE,
stream, strategy, AUDIO_OUTPUT_FLAG_NONE),
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 40c49e7..89f9899 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -24,8 +24,9 @@
void EffectDescriptor::dump(String8 *dst, int spaces) const
{
+ dst->appendFormat("%*sID: %d\n", spaces, "", mId);
dst->appendFormat("%*sI/O: %d\n", spaces, "", mIo);
- dst->appendFormat("%*sStrategy: %d\n", spaces, "", mStrategy);
+ dst->appendFormat("%*sMusic Effect: %s\n", spaces, "", isMusicEffect()? "yes" : "no");
dst->appendFormat("%*sSession: %d\n", spaces, "", mSession);
dst->appendFormat("%*sName: %s\n", spaces, "", mDesc.name);
dst->appendFormat("%*s%s\n", spaces, "", mEnabled ? "Enabled" : "Disabled");
@@ -41,9 +42,8 @@
status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *desc,
audio_io_handle_t io,
- uint32_t strategy,
int session,
- int id)
+ int id, bool isMusicEffect)
{
if (getEffect(id) != nullptr) {
ALOGW("%s effect %s already registered", __FUNCTION__, desc->name);
@@ -59,18 +59,11 @@
if (mTotalEffectsMemory > mTotalEffectsMemoryMaxUsed) {
mTotalEffectsMemoryMaxUsed = mTotalEffectsMemory;
}
- ALOGV("registerEffect() effect %s, io %d, strategy %d session %d id %d",
- desc->name, io, strategy, session, id);
+ ALOGV("registerEffect() effect %s, io %d, session %d id %d",
+ desc->name, io, session, id);
ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
- 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;
- effectDesc->mEnabled = false;
-
+ sp<EffectDescriptor> effectDesc = new EffectDescriptor(desc, isMusicEffect, id, io, session);
add(id, effectDesc);
return NO_ERROR;
@@ -161,7 +154,7 @@
{
for (size_t i = 0; i < size(); i++) {
sp<EffectDescriptor> effectDesc = valueAt(i);
- if (effectDesc->mEnabled && (effectDesc->mStrategy == STRATEGY_MEDIA) &&
+ if (effectDesc->mEnabled && (effectDesc->isMusicEffect()) &&
((effectDesc->mDesc.flags & EFFECT_FLAG_OFFLOAD_SUPPORTED) == 0)) {
ALOGV("isNonOffloadableEffectEnabled() non offloadable effect %s enabled on session %d",
effectDesc->mDesc.name, effectDesc->mSession);