Merge "audio policy: concurrent capture effects" into qt-dev

gugelfrei
Eric Laurent 5 years ago committed by Android (Google) Code Review
commit df8638b4c4

@ -89,6 +89,7 @@ enum {
GET_MICROPHONES,
SET_MASTER_BALANCE,
GET_MASTER_BALANCE,
SET_EFFECT_SUSPENDED,
};
#define MAX_ITEMS_PER_LIST 1024
@ -718,6 +719,18 @@ public:
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 @@ status_t BnAudioFlinger::onTransact(
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 @@ status_t BnAudioFlinger::onTransact(
// 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 @@ status_t BnAudioFlinger::onTransact(
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()));

@ -457,6 +457,10 @@ public:
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

@ -926,7 +926,7 @@ int Session_ReleaseEffect(preproc_session_t *session,
delete session->revBuf;
session->revBuf = NULL;
session->io = 0;
session->id = 0;
}
return 0;
@ -1155,7 +1155,7 @@ preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_
{
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 @@ preproc_session_t *PreProc_GetSession(int32_t procId, int32_t sessionId, int32_
}
}
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 @@ int PreProcessingLib_Create(const effect_uuid_t *uuid,
status = Session_CreateEffect(session, procId, pInterface);
if (status < 0 && session->createdMsk == 0) {
session->io = 0;
session->id = 0;
}
return status;
}
@ -1929,7 +1929,7 @@ int PreProcessingLib_Release(effect_handle_t interface)
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);

@ -1699,18 +1699,35 @@ void AudioFlinger::removeClient_l(pid_t pid)
}
// 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 @@ status_t AudioFlinger::moveEffects(audio_session_t sessionId, audio_io_handle_t
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 AudioFlinger::moveAuxEffectToIo(int EffectId,
{
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);

@ -239,6 +239,10 @@ public:
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 @@ using effect_buffer_t = int16_t;
// 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);

@ -1488,9 +1488,10 @@ void AudioFlinger::EffectModule::dump(int fd, const Vector<String16>& args __unu
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];

@ -8248,11 +8248,6 @@ sp<StreamHalInterface> AudioFlinger::RecordThread::stream() const
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 @@ status_t AudioFlinger::RecordThread::addEffectChain_l(const sp<EffectChain>& cha
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,

@ -348,6 +348,10 @@ public:
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,

@ -68,11 +68,13 @@ public:
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 @@ public:
// 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);

@ -29,8 +29,8 @@ 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),
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 @@ public:
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 @@ public:
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;

@ -128,6 +128,13 @@ bool AudioInputDescriptor::isSourceActive(audio_source_t source) const
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 @@ audio_attributes_t AudioInputDescriptor::getHighestPriorityAttributes() const
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 @@ void AudioInputDescriptor::setClientActive(const sp<RecordClientDescriptor>& cli
client->setActive(active);
checkSuspendEffects();
int event = active ? RECORD_CONFIG_EVENT_START : RECORD_CONFIG_EVENT_STOP;
updateClientRecordingConfiguration(event, client);
}
void AudioInputDescriptor::updateClientRecordingConfiguration(
@ -397,42 +405,88 @@ void AudioInputDescriptor::trackEffectEnabled(const sp<EffectDescriptor> &effect
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);
}
}
}
@ -444,7 +498,7 @@ void AudioInputDescriptor::dump(String8 *dst) const
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");

@ -30,6 +30,7 @@ void EffectDescriptor::dump(String8 *dst, int spaces) const
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 @@ status_t EffectDescriptorCollection::registerEffect(const effect_descriptor_t *d
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 @@ void EffectDescriptorCollection::moveEffects(const std::vector<int>& ids,
}
}
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) {

@ -2343,25 +2343,8 @@ void AudioPolicyManager::closeClient(audio_port_handle_t portId)
}
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 @@ 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);
@ -2703,6 +2685,16 @@ status_t AudioPolicyManager::unregisterEffect(int id)
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 @@ status_t AudioPolicyManager::setSurroundFormatEnabled(audio_format_t audioFormat
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 @@ void AudioPolicyManager::closeOutput(audio_io_handle_t output)
setMsdPatch();
}
}
cleanUpEffectsForIo(output);
}
void AudioPolicyManager::closeInput(audio_io_handle_t input)
@ -4945,6 +4932,8 @@ void AudioPolicyManager::closeInput(audio_io_handle_t input)
mInputs.activeInputsCountOnDevices(primaryInputDevices) == 0) {
SoundTrigger::setCaptureState(false);
}
cleanUpEffectsForIo(input);
}
SortedVector<audio_io_handle_t> AudioPolicyManager::getOutputsForDevices(

@ -870,6 +870,8 @@ private:
int delayMs,
uid_t uid,
sp<AudioPatch> *patchDescPtr);
void cleanUpEffectsForIo(audio_io_handle_t io);
};
};

@ -172,6 +172,13 @@ status_t AudioPolicyService::AudioPolicyClient::moveEffects(audio_session_t sess
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)

@ -1196,6 +1196,17 @@ bool AudioPolicyService::AudioCommandThread::threadLoop()
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 @@ status_t AudioPolicyService::AudioCommandThread::voiceVolumeCommand(float volume
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 @@ int AudioPolicyService::setVoiceVolume(float volume, int delayMs)
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);

@ -293,6 +293,9 @@ public:
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 @@ private:
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 @@ private:
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 @@ private:
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 @@ private:
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,

@ -84,6 +84,9 @@ public:
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

Loading…
Cancel
Save