Merge "audio policy: concurrent capture effects" into qt-dev
am: df8638b4c4
Change-Id: I57d9f902c979426e4a12439ece4430fd7168c253
diff --git a/media/libaudioclient/IAudioFlinger.cpp b/media/libaudioclient/IAudioFlinger.cpp
index 825cd4e..dd95e34 100644
--- a/media/libaudioclient/IAudioFlinger.cpp
+++ b/media/libaudioclient/IAudioFlinger.cpp
@@ -89,6 +89,7 @@
GET_MICROPHONES,
SET_MASTER_BALANCE,
GET_MASTER_BALANCE,
+ SET_EFFECT_SUSPENDED,
};
#define MAX_ITEMS_PER_LIST 1024
@@ -718,6 +719,18 @@
return reply.readInt32();
}
+ virtual void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioFlinger::getInterfaceDescriptor());
+ data.writeInt32(effectId);
+ data.writeInt32(sessionId);
+ data.writeInt32(suspended ? 1 : 0);
+ remote()->transact(SET_EFFECT_SUSPENDED, data, &reply);
+ }
+
virtual audio_module_handle_t loadHwModule(const char *name)
{
Parcel data, reply;
@@ -913,6 +926,7 @@
case INVALIDATE_STREAM:
case SET_VOICE_VOLUME:
case MOVE_EFFECTS:
+ case SET_EFFECT_SUSPENDED:
case LOAD_HW_MODULE:
case LIST_AUDIO_PORTS:
case GET_AUDIO_PORT:
@@ -926,6 +940,7 @@
// return status only for non void methods
switch (code) {
case SET_RECORD_SILENCED:
+ case SET_EFFECT_SUSPENDED:
break;
default:
reply->writeInt32(static_cast<int32_t> (INVALID_OPERATION));
@@ -1371,6 +1386,14 @@
reply->writeInt32(moveEffects(session, srcOutput, dstOutput));
return NO_ERROR;
} break;
+ case SET_EFFECT_SUSPENDED: {
+ CHECK_INTERFACE(IAudioFlinger, data, reply);
+ int effectId = data.readInt32();
+ audio_session_t sessionId = (audio_session_t) data.readInt32();
+ bool suspended = data.readInt32() == 1;
+ setEffectSuspended(effectId, sessionId, suspended);
+ return NO_ERROR;
+ } break;
case LOAD_HW_MODULE: {
CHECK_INTERFACE(IAudioFlinger, data, reply);
reply->writeInt32(loadHwModule(data.readCString()));
diff --git a/media/libaudioclient/include/media/IAudioFlinger.h b/media/libaudioclient/include/media/IAudioFlinger.h
index ef0ed0c..dcc18b6 100644
--- a/media/libaudioclient/include/media/IAudioFlinger.h
+++ b/media/libaudioclient/include/media/IAudioFlinger.h
@@ -457,6 +457,10 @@
virtual status_t moveEffects(audio_session_t session, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput) = 0;
+ virtual void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) = 0;
+
virtual audio_module_handle_t loadHwModule(const char *name) = 0;
// helpers for android.media.AudioManager.getProperty(), see description there for meaning
diff --git a/media/libeffects/preprocessing/PreProcessing.cpp b/media/libeffects/preprocessing/PreProcessing.cpp
index 50c33c6..5fab5be 100644
--- a/media/libeffects/preprocessing/PreProcessing.cpp
+++ b/media/libeffects/preprocessing/PreProcessing.cpp
@@ -926,7 +926,7 @@
delete session->revBuf;
session->revBuf = NULL;
- session->io = 0;
+ session->id = 0;
}
return 0;
@@ -1155,7 +1155,7 @@
{
size_t i;
for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
- if (sSessions[i].io == ioId) {
+ if (sSessions[i].id == sessionId) {
if (sSessions[i].createdMsk & (1 << procId)) {
return NULL;
}
@@ -1163,7 +1163,7 @@
}
}
for (i = 0; i < PREPROC_NUM_SESSIONS; i++) {
- if (sSessions[i].io == 0) {
+ if (sSessions[i].id == 0) {
sSessions[i].id = sessionId;
sSessions[i].io = ioId;
return &sSessions[i];
@@ -1915,7 +1915,7 @@
status = Session_CreateEffect(session, procId, pInterface);
if (status < 0 && session->createdMsk == 0) {
- session->io = 0;
+ session->id = 0;
}
return status;
}
@@ -1929,7 +1929,7 @@
preproc_effect_t *fx = (preproc_effect_t *)interface;
- if (fx->session->io == 0) {
+ if (fx->session->id == 0) {
return -EINVAL;
}
return Session_ReleaseEffect(fx->session, fx);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 9527195..55db699 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1699,18 +1699,35 @@
}
// getEffectThread_l() must be called with AudioFlinger::mLock held
-sp<AudioFlinger::PlaybackThread> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
- int EffectId)
+sp<AudioFlinger::ThreadBase> AudioFlinger::getEffectThread_l(audio_session_t sessionId,
+ int effectId)
{
- sp<PlaybackThread> thread;
+ sp<ThreadBase> thread;
for (size_t i = 0; i < mPlaybackThreads.size(); i++) {
- if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, EffectId) != 0) {
+ if (mPlaybackThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
ALOG_ASSERT(thread == 0);
thread = mPlaybackThreads.valueAt(i);
}
}
-
+ if (thread != nullptr) {
+ return thread;
+ }
+ for (size_t i = 0; i < mRecordThreads.size(); i++) {
+ if (mRecordThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
+ ALOG_ASSERT(thread == 0);
+ thread = mRecordThreads.valueAt(i);
+ }
+ }
+ if (thread != nullptr) {
+ return thread;
+ }
+ for (size_t i = 0; i < mMmapThreads.size(); i++) {
+ if (mMmapThreads.valueAt(i)->getEffect(sessionId, effectId) != 0) {
+ ALOG_ASSERT(thread == 0);
+ thread = mMmapThreads.valueAt(i);
+ }
+ }
return thread;
}
@@ -3464,6 +3481,23 @@
return moveEffectChain_l(sessionId, srcThread, dstThread);
}
+
+void AudioFlinger::setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+{
+ Mutex::Autolock _l(mLock);
+
+ sp<ThreadBase> thread = getEffectThread_l(sessionId, effectId);
+ if (thread == nullptr) {
+ return;
+ }
+ Mutex::Autolock _sl(thread->mLock);
+ sp<EffectModule> effect = thread->getEffect_l(sessionId, effectId);
+ thread->setEffectSuspended_l(&effect->desc().type, suspended, sessionId);
+}
+
+
// moveEffectChain_l must be called with both srcThread and dstThread mLocks held
status_t AudioFlinger::moveEffectChain_l(audio_session_t sessionId,
AudioFlinger::PlaybackThread *srcThread,
@@ -3541,7 +3575,8 @@
{
status_t status = NO_ERROR;
Mutex::Autolock _l(mLock);
- sp<PlaybackThread> thread = getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId);
+ sp<PlaybackThread> thread =
+ static_cast<PlaybackThread *>(getEffectThread_l(AUDIO_SESSION_OUTPUT_MIX, EffectId).get());
if (EffectId != 0 && thread != 0 && dstThread != thread.get()) {
Mutex::Autolock _dl(dstThread->mLock);
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 8bf89c8..72e669a 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -239,6 +239,10 @@
virtual status_t moveEffects(audio_session_t sessionId, audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput);
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) override;
+
virtual audio_module_handle_t loadHwModule(const char *name);
virtual uint32_t getPrimaryOutputSamplingRate();
@@ -708,7 +712,7 @@
// return the playback thread with smallest HAL buffer size, and prefer fast
PlaybackThread *fastPlaybackThread_l() const;
- sp<PlaybackThread> getEffectThread_l(audio_session_t sessionId, int EffectId);
+ sp<ThreadBase> getEffectThread_l(audio_session_t sessionId, int effectId);
void removeClient_l(pid_t pid);
diff --git a/services/audioflinger/Effects.cpp b/services/audioflinger/Effects.cpp
index 50ab634..3c4fbba 100644
--- a/services/audioflinger/Effects.cpp
+++ b/services/audioflinger/Effects.cpp
@@ -1488,9 +1488,10 @@
result.append("\t\tCould not lock Fx mutex:\n");
}
- result.append("\t\tSession Status State Engine:\n");
- result.appendFormat("\t\t%05d %03d %03d %p\n",
- mSessionId, mStatus, mState, mEffectInterface.get());
+ result.append("\t\tSession Status State Registered Enabled Suspended Engine:\n");
+ result.appendFormat("\t\t%05d %03d %03d %s %s %s %p\n",
+ mSessionId, mStatus, mState, mPolicyRegistered ? "y" : "n", mPolicyEnabled ? "y" : "n",
+ mSuspended ? "y" : "n", mEffectInterface.get());
result.append("\t\tDescriptor:\n");
char uuidStr[64];
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index e71f0c6..59ced26 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -8248,11 +8248,6 @@
status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& chain)
{
- // only one chain per input thread
- if (!mEffectChains.isEmpty()) {
- ALOGW("addEffectChain_l() already one chain %p on thread %p", chain.get(), this);
- return INVALID_OPERATION;
- }
ALOGV("addEffectChain_l() %p on thread %p", chain.get(), this);
chain->setThread(this);
chain->setInBuffer(NULL);
@@ -8272,13 +8267,14 @@
size_t AudioFlinger::RecordThread::removeEffectChain_l(const sp<EffectChain>& chain)
{
ALOGV("removeEffectChain_l() %p from thread %p", chain.get(), this);
- ALOGW_IF(mEffectChains.size() != 1,
- "removeEffectChain_l() %p invalid chain size %zu on thread %p",
- chain.get(), mEffectChains.size(), this);
- if (mEffectChains.size() == 1) {
- mEffectChains.removeAt(0);
+
+ for (size_t i = 0; i < mEffectChains.size(); i++) {
+ if (chain == mEffectChains[i]) {
+ mEffectChains.removeAt(i);
+ break;
+ }
}
- return 0;
+ return mEffectChains.size();
}
status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch *patch,
diff --git a/services/audiopolicy/AudioPolicyInterface.h b/services/audiopolicy/AudioPolicyInterface.h
index caf0d7e..4b56a46 100644
--- a/services/audiopolicy/AudioPolicyInterface.h
+++ b/services/audiopolicy/AudioPolicyInterface.h
@@ -348,6 +348,10 @@
audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput) = 0;
+ virtual void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) = 0;
+
/* Create a patch between several source and sink ports */
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
index e071fe0..37f9d14 100644
--- a/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/AudioInputDescriptor.h
@@ -68,11 +68,13 @@
bool isSourceActive(audio_source_t source) const;
audio_source_t source() const;
bool isSoundTrigger() const;
+ sp<RecordClientDescriptor> getHighestPriorityClient() const;
audio_attributes_t getHighestPriorityAttributes() 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;
+ EffectDescriptorCollection getActiveEffects() const; // enabled and not suspended
// implementation of AudioIODescriptorInterface
audio_config_base_t getConfig() const override;
audio_patch_handle_t getPatchHandle() const override;
@@ -100,6 +102,10 @@
// implementation of ClientMapHandler<RecordClientDescriptor>
void addClient(const sp<RecordClientDescriptor> &client) override;
+ // Go over all active clients and suspend or restore effects according highest priority
+ // active use case
+ void checkSuspendEffects();
+
private:
void updateClientRecordingConfiguration(int event, const sp<RecordClientDescriptor>& client);
diff --git a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
index c729ef9..c4eab30 100644
--- a/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
+++ b/services/audiopolicy/common/managerdefinitions/include/EffectDescriptor.h
@@ -29,8 +29,8 @@
{
public:
EffectDescriptor(const effect_descriptor_t *desc, bool isMusicEffect,
- int id, int io, int session) :
- mId(id), mIo(io), mSession(session), mEnabled(false),
+ int id, audio_io_handle_t io, audio_session_t session) :
+ mId(id), mIo(io), mSession(session), mEnabled(false), mSuspended(false),
mIsMusicEffect(isMusicEffect)
{
memcpy (&mDesc, desc, sizeof(effect_descriptor_t));
@@ -38,11 +38,12 @@
void dump(String8 *dst, int spaces = 0) const;
- int mId; // effect unique ID
- int mIo; // io the effect is attached 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
+ int mId; // effect unique ID
+ audio_io_handle_t mIo; // io the effect is attached to
+ audio_session_t mSession; // audio session the effect is on
+ effect_descriptor_t mDesc; // effect descriptor
+ bool mEnabled; // enabled state: CPU load being used or not
+ bool mSuspended; // enabled but suspended by concurent capture policy
bool isMusicEffect() const { return mIsMusicEffect; }
@@ -59,6 +60,7 @@
int session, int id, bool isMusicEffect);
status_t unregisterEffect(int id);
sp<EffectDescriptor> getEffect(int id) const;
+ EffectDescriptorCollection getEffectsForIo(audio_io_handle_t io) const;
status_t setEffectEnabled(int id, bool enabled);
bool isEffectEnabled(int id) const;
uint32_t getMaxEffectsCpuLoad() const;
diff --git a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
index 5b4e2eb..58683be 100644
--- a/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/AudioInputDescriptor.cpp
@@ -128,6 +128,13 @@
audio_attributes_t AudioInputDescriptor::getHighestPriorityAttributes() const
{
audio_attributes_t attributes = { .source = AUDIO_SOURCE_DEFAULT };
+ sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+ return topClient ? topClient->attributes() : attributes;
+}
+
+sp<RecordClientDescriptor> AudioInputDescriptor::getHighestPriorityClient() const
+{
+ sp<RecordClientDescriptor> topClient;
for (bool activeOnly : { true, false }) {
int32_t topPriority = -1;
@@ -139,18 +146,18 @@
app_state_t curState = client->appState();
if (curState >= topState) {
int32_t curPriority = source_priority(client->source());
- if (curPriority > topPriority) {
- attributes = client->attributes();
+ if (curPriority >= topPriority) {
+ topClient = client;
topPriority = curPriority;
}
topState = curState;
}
}
- if (attributes.source != AUDIO_SOURCE_DEFAULT) {
+ if (topClient != nullptr) {
break;
}
}
- return attributes;
+ return topClient;
}
bool AudioInputDescriptor::isSoundTrigger() const {
@@ -326,9 +333,10 @@
client->setActive(active);
+ checkSuspendEffects();
+
int event = active ? RECORD_CONFIG_EVENT_START : RECORD_CONFIG_EVENT_STOP;
updateClientRecordingConfiguration(event, client);
-
}
void AudioInputDescriptor::updateClientRecordingConfiguration(
@@ -397,44 +405,90 @@
mEnabledEffects.replaceValueFor(effect->mId, effect);
} else {
mEnabledEffects.removeItem(effect->mId);
+ // always exit from suspend when disabling an effect as only enabled effects
+ // are managed by checkSuspendEffects()
+ if (effect->mSuspended) {
+ effect->mSuspended = false;
+ mClientInterface->setEffectSuspended(effect->mId, effect->mSession, effect->mSuspended);
+ }
}
RecordClientVector clients = getClientsForSession((audio_session_t)effect->mSession);
+ RecordClientVector updatedClients;
+
for (const auto& client : clients) {
sp<EffectDescriptor> clientEffect = client->getEnabledEffects().getEffect(effect->mId);
bool changed = (enabled && clientEffect == nullptr)
|| (!enabled && clientEffect != nullptr);
client->trackEffectEnabled(effect, enabled);
if (changed && client->active()) {
- updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+ updatedClients.push_back(client);
}
}
+
+ checkSuspendEffects();
+
+ for (const auto& client : updatedClients) {
+ updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+ }
}
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();
+ EffectDescriptorCollection enabledEffects;
+ sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+ if (topClient != nullptr) {
+ enabledEffects = topClient->getEnabledEffects();
}
return enabledEffects;
}
-void AudioInputDescriptor::setAppState(uid_t uid, app_state_t state) {
+void AudioInputDescriptor::setAppState(uid_t uid, app_state_t state)
+{
RecordClientVector clients = clientsList(false /*activeOnly*/);
+ RecordClientVector updatedClients;
for (const auto& client : clients) {
if (uid == client->uid()) {
bool wasSilenced = client->isSilenced();
client->setAppState(state);
if (client->active() && wasSilenced != client->isSilenced()) {
- updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+ updatedClients.push_back(client);
}
}
}
+
+ checkSuspendEffects();
+
+ for (const auto& client : updatedClients) {
+ updateClientRecordingConfiguration(RECORD_CONFIG_EVENT_START, client);
+ }
+}
+
+void AudioInputDescriptor::checkSuspendEffects()
+{
+ sp<RecordClientDescriptor> topClient = getHighestPriorityClient();
+ if (topClient == nullptr) {
+ return;
+ }
+
+ for (size_t i = 0; i < mEnabledEffects.size(); i++) {
+ sp<EffectDescriptor> effect = mEnabledEffects.valueAt(i);
+ if (effect->mSession == topClient->session()) {
+ if (effect->mSuspended) {
+ effect->mSuspended = false;
+ mClientInterface->setEffectSuspended(effect->mId,
+ effect->mSession,
+ effect->mSuspended);
+ }
+ } else if (!effect->mSuspended) {
+ effect->mSuspended = true;
+ mClientInterface->setEffectSuspended(effect->mId,
+ effect->mSession,
+ effect->mSuspended);
+ }
+ }
}
void AudioInputDescriptor::dump(String8 *dst) const
@@ -444,7 +498,7 @@
dst->appendFormat(" Format: %d\n", mFormat);
dst->appendFormat(" Channels: %08x\n", mChannelMask);
dst->appendFormat(" Devices %s\n", mDevice->toString().c_str());
- getEnabledEffects().dump(dst, 1 /*spaces*/, false /*verbose*/);
+ mEnabledEffects.dump(dst, 1 /*spaces*/, false /*verbose*/);
dst->append(" AudioRecord Clients:\n");
ClientMapHandler<RecordClientDescriptor>::dump(dst);
dst->append("\n");
diff --git a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
index 627fa8d..415962a 100644
--- a/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/EffectDescriptor.cpp
@@ -30,6 +30,7 @@
dst->appendFormat("%*sSession: %d\n", spaces, "", mSession);
dst->appendFormat("%*sName: %s\n", spaces, "", mDesc.name);
dst->appendFormat("%*s%s\n", spaces, "", mEnabled ? "Enabled" : "Disabled");
+ dst->appendFormat("%*s%s\n", spaces, "", mSuspended ? "Suspended" : "Active");
}
EffectDescriptorCollection::EffectDescriptorCollection() :
@@ -63,7 +64,8 @@
desc->name, io, session, id);
ALOGV("registerEffect() memory %d, total memory %d", desc->memoryUsage, mTotalEffectsMemory);
- sp<EffectDescriptor> effectDesc = new EffectDescriptor(desc, isMusicEffect, id, io, session);
+ sp<EffectDescriptor> effectDesc =
+ new EffectDescriptor(desc, isMusicEffect, id, io, (audio_session_t)session);
add(id, effectDesc);
return NO_ERROR;
@@ -200,6 +202,17 @@
}
}
+EffectDescriptorCollection EffectDescriptorCollection::getEffectsForIo(audio_io_handle_t io) const
+{
+ EffectDescriptorCollection effects;
+ for (size_t i = 0; i < size(); i++) {
+ if (valueAt(i)->mIo == io) {
+ effects.add(keyAt(i), valueAt(i));
+ }
+ }
+ return effects;
+}
+
void EffectDescriptorCollection::dump(String8 *dst, int spaces, bool verbose) const
{
if (verbose) {
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index 4992fd4..6bd64d6 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -2343,25 +2343,8 @@
}
void AudioPolicyManager::closeAllInputs() {
- bool patchRemoved = false;
-
- for (size_t input_index = 0; input_index < mInputs.size(); input_index++) {
- sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(input_index);
- ssize_t patch_index = mAudioPatches.indexOfKey(inputDesc->getPatchHandle());
- if (patch_index >= 0) {
- sp<AudioPatch> patchDesc = mAudioPatches.valueAt(patch_index);
- (void) /*status_t status*/ mpClientInterface->releaseAudioPatch(patchDesc->mAfPatchHandle, 0);
- mAudioPatches.removeItemsAt(patch_index);
- patchRemoved = true;
- }
- inputDesc->close();
- }
- mInputs.clear();
- SoundTrigger::setCaptureState(false);
- nextAudioPortGeneration();
-
- if (patchRemoved) {
- mpClientInterface->onAudioPatchListUpdate();
+ while (mInputs.size() != 0) {
+ closeInput(mInputs.keyAt(0));
}
}
@@ -2695,7 +2678,6 @@
if (mEffects.getEffect(id) == nullptr) {
return INVALID_OPERATION;
}
-
if (mEffects.isEffectEnabled(id)) {
ALOGW("%s effect %d enabled", __FUNCTION__, id);
setEffectEnabled(id, false);
@@ -2703,6 +2685,16 @@
return mEffects.unregisterEffect(id);
}
+void AudioPolicyManager::cleanUpEffectsForIo(audio_io_handle_t io)
+{
+ EffectDescriptorCollection effects = mEffects.getEffectsForIo(io);
+ for (size_t i = 0; i < effects.size(); i++) {
+ ALOGW("%s removing stale effect %s, id %d on closed IO %d",
+ __func__, effects.valueAt(i)->mDesc.name, effects.keyAt(i), io);
+ unregisterEffect(effects.keyAt(i));
+ }
+}
+
status_t AudioPolicyManager::setEffectEnabled(int id, bool enabled)
{
sp<EffectDescriptor> effect = mEffects.getEffect(id);
@@ -4095,15 +4087,8 @@
void AudioPolicyManager::setAppState(uid_t uid, app_state_t state)
{
ALOGV("%s(uid:%d, state:%d)", __func__, uid, state);
-
for (size_t i = 0; i < mInputs.size(); i++) {
- sp<AudioInputDescriptor> inputDesc = mInputs.valueAt(i);
- RecordClientVector clients = inputDesc->clientsList(false /*activeOnly*/);
- for (const auto& client : clients) {
- if (uid == client->uid()) {
- client->setAppState(state);
- }
- }
+ mInputs.valueAt(i)->setAppState(uid, state);
}
}
@@ -4914,6 +4899,8 @@
setMsdPatch();
}
}
+
+ cleanUpEffectsForIo(output);
}
void AudioPolicyManager::closeInput(audio_io_handle_t input)
@@ -4945,6 +4932,8 @@
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
SoundTrigger::setCaptureState(false);
}
+
+ cleanUpEffectsForIo(input);
}
SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.h b/services/audiopolicy/managerdefault/AudioPolicyManager.h
index 43637f6..3376965 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.h
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.h
@@ -870,6 +870,8 @@
int delayMs,
uid_t uid,
sp<AudioPatch> *patchDescPtr);
+
+ void cleanUpEffectsForIo(audio_io_handle_t io);
};
};
diff --git a/services/audiopolicy/service/AudioPolicyClientImpl.cpp b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
index 5748334..d51cc6e 100644
--- a/services/audiopolicy/service/AudioPolicyClientImpl.cpp
+++ b/services/audiopolicy/service/AudioPolicyClientImpl.cpp
@@ -172,6 +172,13 @@
return af->moveEffects(session, src_output, dst_output);
}
+void AudioPolicyService::AudioPolicyClient::setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+{
+ mAudioPolicyService->setEffectSuspended(effectId, sessionId, suspended);
+}
+
status_t AudioPolicyService::AudioPolicyClient::createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
int delayMs)
diff --git a/services/audiopolicy/service/AudioPolicyService.cpp b/services/audiopolicy/service/AudioPolicyService.cpp
index f63fa81..5389c08 100644
--- a/services/audiopolicy/service/AudioPolicyService.cpp
+++ b/services/audiopolicy/service/AudioPolicyService.cpp
@@ -1196,6 +1196,17 @@
data->mPatchHandle, data->mSource);
mLock.lock();
} break;
+ case SET_EFFECT_SUSPENDED: {
+ SetEffectSuspendedData *data = (SetEffectSuspendedData *)command->mParam.get();
+ ALOGV("AudioCommandThread() processing set effect suspended");
+ sp<IAudioFlinger> af = AudioSystem::get_audio_flinger();
+ if (af != 0) {
+ mLock.unlock();
+ af->setEffectSuspended(data->mEffectId, data->mSessionId, data->mSuspended);
+ mLock.lock();
+ }
+ } break;
+
default:
ALOGW("AudioCommandThread() unknown command %d", command->mCommand);
}
@@ -1327,6 +1338,23 @@
return sendCommand(command, delayMs);
}
+void AudioPolicyService::AudioCommandThread::setEffectSuspendedCommand(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+{
+ sp<AudioCommand> command = new AudioCommand();
+ command->mCommand = SET_EFFECT_SUSPENDED;
+ sp<SetEffectSuspendedData> data = new SetEffectSuspendedData();
+ data->mEffectId = effectId;
+ data->mSessionId = sessionId;
+ data->mSuspended = suspended;
+ command->mParam = data;
+ ALOGV("AudioCommandThread() adding set suspended effectId %d sessionId %d suspended %d",
+ effectId, sessionId, suspended);
+ sendCommand(command);
+}
+
+
void AudioPolicyService::AudioCommandThread::stopOutputCommand(audio_port_handle_t portId)
{
sp<AudioCommand> command = new AudioCommand();
@@ -1707,6 +1735,14 @@
return (int)mAudioCommandThread->voiceVolumeCommand(volume, delayMs);
}
+void AudioPolicyService::setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended)
+{
+ mAudioCommandThread->setEffectSuspendedCommand(effectId, sessionId, suspended);
+}
+
+
extern "C" {
audio_module_handle_t aps_load_hw_module(void *service __unused,
const char *name);
diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h
index 0842649..6c19912 100644
--- a/services/audiopolicy/service/AudioPolicyService.h
+++ b/services/audiopolicy/service/AudioPolicyService.h
@@ -293,6 +293,9 @@
void onAudioVolumeGroupChanged(volume_group_t group, int flags);
void doOnAudioVolumeGroupChanged(volume_group_t group, int flags);
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended);
private:
AudioPolicyService() ANDROID_API;
@@ -427,7 +430,8 @@
CHANGED_AUDIOVOLUMEGROUP,
SET_AUDIOPORT_CONFIG,
DYN_POLICY_MIX_STATE_UPDATE,
- RECORDING_CONFIGURATION_UPDATE
+ RECORDING_CONFIGURATION_UPDATE,
+ SET_EFFECT_SUSPENDED,
};
AudioCommandThread (String8 name, const wp<AudioPolicyService>& service);
@@ -470,6 +474,9 @@
std::vector<effect_descriptor_t> effects,
audio_patch_handle_t patchHandle,
audio_source_t source);
+ void setEffectSuspendedCommand(int effectId,
+ audio_session_t sessionId,
+ bool suspended);
void insertCommand_l(AudioCommand *command, int delayMs = 0);
private:
class AudioCommandData;
@@ -567,6 +574,13 @@
audio_source_t mSource;
};
+ class SetEffectSuspendedData : public AudioCommandData {
+ public:
+ int mEffectId;
+ audio_session_t mSessionId;
+ bool mSuspended;
+ };
+
Mutex mLock;
Condition mWaitWorkCV;
Vector < sp<AudioCommand> > mAudioCommands; // list of pending commands
@@ -652,6 +666,10 @@
audio_io_handle_t srcOutput,
audio_io_handle_t dstOutput);
+ void setEffectSuspended(int effectId,
+ audio_session_t sessionId,
+ bool suspended) override;
+
/* Create a patch between several source and sink ports */
virtual status_t createAudioPatch(const struct audio_patch *patch,
audio_patch_handle_t *handle,
diff --git a/services/audiopolicy/tests/AudioPolicyTestClient.h b/services/audiopolicy/tests/AudioPolicyTestClient.h
index 8854eb2..e4c64e5 100644
--- a/services/audiopolicy/tests/AudioPolicyTestClient.h
+++ b/services/audiopolicy/tests/AudioPolicyTestClient.h
@@ -84,6 +84,9 @@
std::vector<effect_descriptor_t> effects __unused,
audio_patch_handle_t patchHandle __unused,
audio_source_t source __unused) override { }
+ void setEffectSuspended(int effectId __unused,
+ audio_session_t sessionId __unused,
+ bool suspended __unused) {}
};
} // namespace android