Merge "Audio effects: track CPU and memory use separately"

This commit is contained in:
Eric Laurent
2011-08-11 14:40:04 -07:00
committed by Android (Google) Code Review
8 changed files with 95 additions and 27 deletions

View File

@@ -183,6 +183,7 @@ public:
int session,
int id);
static status_t unregisterEffect(int id);
static status_t setEffectEnabled(int id, bool enabled);
static const sp<IAudioPolicyService>& get_audio_policy_service();

View File

@@ -84,6 +84,7 @@ public:
int session,
int id) = 0;
virtual status_t unregisterEffect(int id) = 0;
virtual status_t setEffectEnabled(int id, bool enabled) = 0;
virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0;
virtual status_t queryDefaultPreProcessing(int audioSession,
effect_descriptor_t *descriptors,

View File

@@ -710,6 +710,13 @@ status_t AudioSystem::unregisterEffect(int id)
return aps->unregisterEffect(id);
}
status_t AudioSystem::setEffectEnabled(int id, bool enabled)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->setEffectEnabled(id, enabled);
}
status_t AudioSystem::isStreamActive(int stream, bool* state, uint32_t inPastMs)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();

View File

@@ -53,7 +53,8 @@ enum {
UNREGISTER_EFFECT,
IS_STREAM_ACTIVE,
GET_DEVICES_FOR_STREAM,
QUERY_DEFAULT_PRE_PROCESSING
QUERY_DEFAULT_PRE_PROCESSING,
SET_EFFECT_ENABLED
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -313,6 +314,16 @@ public:
return static_cast <status_t> (reply.readInt32());
}
virtual status_t setEffectEnabled(int id, bool enabled)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(id);
data.writeInt32(enabled);
remote()->transact(SET_EFFECT_ENABLED, data, &reply);
return static_cast <status_t> (reply.readInt32());
}
virtual bool isStreamActive(int stream, uint32_t inPastMs) const
{
Parcel data, reply;
@@ -577,6 +588,14 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
} break;
case SET_EFFECT_ENABLED: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
int id = data.readInt32();
bool enabled = static_cast <bool>(data.readInt32());
reply->writeInt32(static_cast <int32_t>(setEffectEnabled(id, enabled)));
return NO_ERROR;
} break;
case IS_STREAM_ACTIVE: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
int stream = data.readInt32();

View File

@@ -1232,18 +1232,6 @@ void AudioFlinger::ThreadBase::checkSuspendOnAddEffectChain_l(const sp<EffectCha
}
}
void AudioFlinger::ThreadBase::updateSuspendedSessionsOnRemoveEffectChain_l(
const sp<EffectChain>& chain)
{
int index = mSuspendedSessions.indexOfKey(chain->sessionId());
if (index < 0) {
return;
}
LOGV("updateSuspendedSessionsOnRemoveEffectChain_l() removed suspended session %d",
chain->sessionId());
mSuspendedSessions.removeItemsAt(index);
}
void AudioFlinger::ThreadBase::updateSuspendedSessions_l(const effect_uuid_t *type,
bool suspend,
int sessionId)
@@ -1311,7 +1299,14 @@ void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled(const sp<EffectModule
{
Mutex::Autolock _l(mLock);
// TODO: implement PlaybackThread or RecordThread specific behavior here
if (mType != RECORD) {
// suspend all effects in AUDIO_SESSION_OUTPUT_MIX when enabling any effect on
// another session. This gives the priority to well behaved effect control panels
// and applications not using global effects.
if (sessionId != AUDIO_SESSION_OUTPUT_MIX) {
setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
}
}
sp<EffectChain> chain = getEffectChain_l(sessionId);
if (chain != 0) {
@@ -5847,7 +5842,6 @@ size_t AudioFlinger::PlaybackThread::removeEffectChain_l(const sp<EffectChain>&
for (size_t i = 0; i < mEffectChains.size(); i++) {
if (chain == mEffectChains[i]) {
updateSuspendedSessionsOnRemoveEffectChain_l(chain);
mEffectChains.removeAt(i);
// detach all active tracks from the chain
for (size_t i = 0 ; i < mActiveTracks.size() ; ++i) {
@@ -5939,7 +5933,6 @@ size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& ch
"removeEffectChain_l() %p invalid chain size %d on thread %p",
chain.get(), mEffectChains.size(), this);
if (mEffectChains.size() == 1) {
updateSuspendedSessionsOnRemoveEffectChain_l(chain);
mEffectChains.removeAt(0);
}
return 0;
@@ -6393,10 +6386,16 @@ status_t AudioFlinger::EffectModule::command(uint32_t cmdCode,
status_t AudioFlinger::EffectModule::setEnabled(bool enabled)
{
Mutex::Autolock _l(mLock);
LOGV("setEnabled %p enabled %d", this, enabled);
if (enabled != isEnabled()) {
status_t status = AudioSystem::setEffectEnabled(mId, enabled);
if (enabled && status != NO_ERROR) {
return status;
}
switch (mState) {
// going from disabled to enabled
case IDLE:
@@ -6704,6 +6703,10 @@ status_t AudioFlinger::EffectHandle::enable()
if (!mHasControl) return INVALID_OPERATION;
if (mEffect == 0) return DEAD_OBJECT;
if (mEnabled) {
return NO_ERROR;
}
mEnabled = true;
sp<ThreadBase> thread = mEffect->thread().promote();
@@ -6716,7 +6719,14 @@ status_t AudioFlinger::EffectHandle::enable()
return NO_ERROR;
}
return mEffect->setEnabled(true);
status_t status = mEffect->setEnabled(true);
if (status != NO_ERROR) {
if (thread != 0) {
thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
}
mEnabled = false;
}
return status;
}
status_t AudioFlinger::EffectHandle::disable()
@@ -6725,6 +6735,9 @@ status_t AudioFlinger::EffectHandle::disable()
if (!mHasControl) return INVALID_OPERATION;
if (mEffect == 0) return DEAD_OBJECT;
if (!mEnabled) {
return NO_ERROR;
}
mEnabled = false;
if (mEffect->suspended()) {
@@ -6754,9 +6767,11 @@ void AudioFlinger::EffectHandle::disconnect(bool unpiniflast)
}
mEffect->disconnect(this, unpiniflast);
sp<ThreadBase> thread = mEffect->thread().promote();
if (thread != 0) {
thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
if (mEnabled) {
sp<ThreadBase> thread = mEffect->thread().promote();
if (thread != 0) {
thread->checkSuspendOnEffectEnabled(mEffect, false, mEffect->sessionId());
}
}
// release sp on module => module destructor can be called now
@@ -7367,15 +7382,22 @@ void AudioFlinger::EffectChain::setEffectSuspendedAll_l(bool suspend)
}
}
bool AudioFlinger::EffectChain::isEffectEligibleForSuspend(const effect_descriptor_t& desc)
{
// auxiliary effects and visualizer are never suspended on output mix
if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) &&
(((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
(memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0))) {
return false;
}
return true;
}
Vector< sp<AudioFlinger::EffectModule> > AudioFlinger::EffectChain::getSuspendEligibleEffects()
{
Vector< sp<EffectModule> > effects;
for (size_t i = 0; i < mEffects.size(); i++) {
effect_descriptor_t desc = mEffects[i]->desc();
// auxiliary effects and vizualizer are never suspended on output mix
if ((mSessionId == AUDIO_SESSION_OUTPUT_MIX) && (
((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) ||
(memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0))) {
if (!isEffectEligibleForSuspend(mEffects[i]->desc())) {
continue;
}
effects.add(mEffects[i]);
@@ -7405,8 +7427,15 @@ void AudioFlinger::EffectChain::checkSuspendOnEffectEnabled(const sp<EffectModul
if (index < 0) {
return;
}
if (!isEffectEligibleForSuspend(effect->desc())) {
return;
}
setEffectSuspended_l(&effect->desc().type, enabled);
index = mSuspendedEffects.indexOfKey(effect->desc().type.timeLow);
if (index < 0) {
LOGW("checkSuspendOnEffectEnabled() Fx should be suspended here!");
return;
}
}
LOGV("checkSuspendOnEffectEnabled() enable suspending fx %08x",
effect->desc().type.timeLow);

View File

@@ -522,8 +522,6 @@ private:
int sessionId);
// check if some effects must be suspended when an effect chain is added
void checkSuspendOnAddEffectChain_l(const sp<EffectChain>& chain);
// updated mSuspendedSessions when an effect chain is removed
void updateSuspendedSessionsOnRemoveEffectChain_l(const sp<EffectChain>& chain);
friend class AudioFlinger;
friend class Track;
@@ -1320,6 +1318,10 @@ private:
Vector< sp<EffectModule> > getSuspendEligibleEffects();
// get an effect module if it is currently enable
sp<EffectModule> getEffectIfEnabled(const effect_uuid_t *type);
// true if the effect whose descriptor is passed can be suspended
// OEMs can modify the rules implemented in this method to exclude specific effect
// types or implementations from the suspend/restore mechanism.
bool isEffectEligibleForSuspend(const effect_descriptor_t& desc);
wp<ThreadBase> mThread; // parent mixer thread
Mutex mLock; // mutex protecting effect list

View File

@@ -488,6 +488,14 @@ status_t AudioPolicyService::unregisterEffect(int id)
return mpAudioPolicy->unregister_effect(mpAudioPolicy, id);
}
status_t AudioPolicyService::setEffectEnabled(int id, bool enabled)
{
if (mpAudioPolicy == NULL) {
return NO_INIT;
}
return mpAudioPolicy->set_effect_enabled(mpAudioPolicy, id, enabled);
}
bool AudioPolicyService::isStreamActive(int stream, uint32_t inPastMs) const
{
if (mpAudioPolicy == NULL) {

View File

@@ -102,6 +102,7 @@ public:
int session,
int id);
virtual status_t unregisterEffect(int id);
virtual status_t setEffectEnabled(int id, bool enabled);
virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const;
virtual status_t queryDefaultPreProcessing(int audioSession,