Merge "Audio effects: track CPU and memory use separately"
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user