AudioFlinger: add audio session for device effects

Add specific audio session ID for effects applied to a
particular audio device.
Device specific effects will be attached to a particular audio sink or
source device identified by its unique audio port ID and will all use
this same session ID.
Only one session of this type exists on a given playback or record
thread.
All effects in this session apply to the same device ID and are created/released
when the routing (audio patch) of this thread output or input stream is updated.

Bug: 136294538
Test: make

Change-Id: I4e3a55ed1244b918429dd9e217b6efecc1ec6449
gugelfrei
Eric Laurent 5 years ago
parent 602e1ae3a3
commit 3f75a5bc38

@ -171,7 +171,7 @@ status_t AudioEffect::set(const effect_uuid_t *type,
ALOGV("set() %p OK effect: %s id: %d status %d enabled %d pid %d", this, mDescriptor.name, mId,
mStatus, mEnabled, mClientPid);
if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
if (!audio_is_global_session(mSessionId)) {
AudioSystem::acquireAudioSessionId(mSessionId, mClientPid);
}
@ -184,7 +184,7 @@ AudioEffect::~AudioEffect()
ALOGV("Destructor %p", this);
if (mStatus == NO_ERROR || mStatus == ALREADY_EXISTS) {
if (mSessionId > AUDIO_SESSION_OUTPUT_MIX) {
if (!audio_is_global_session(mSessionId)) {
AudioSystem::releaseAudioSessionId(mSessionId, mClientPid);
}
if (mIEffect != NULL) {

@ -181,12 +181,19 @@ bool modifyAudioRoutingAllowed(pid_t pid, uid_t uid) {
}
bool modifyDefaultAudioEffectsAllowed() {
return modifyDefaultAudioEffectsAllowed(
IPCThreadState::self()->getCallingPid(), IPCThreadState::self()->getCallingUid());
}
bool modifyDefaultAudioEffectsAllowed(pid_t pid, uid_t uid) {
if (isAudioServerUid(IPCThreadState::self()->getCallingUid())) return true;
static const String16 sModifyDefaultAudioEffectsAllowed(
"android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
// IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
bool ok = PermissionCache::checkCallingPermission(sModifyDefaultAudioEffectsAllowed);
if (!ok) ALOGE("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS");
bool ok = PermissionCache::checkPermission(sModifyDefaultAudioEffectsAllowed, pid, uid);
ALOGE_IF(!ok, "%s(): android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS denied for uid %d",
__func__, uid);
return ok;
}

@ -87,6 +87,7 @@ bool settingsAllowed();
bool modifyAudioRoutingAllowed();
bool modifyAudioRoutingAllowed(pid_t pid, uid_t uid);
bool modifyDefaultAudioEffectsAllowed();
bool modifyDefaultAudioEffectsAllowed(pid_t pid, uid_t uid);
bool dumpAllowed();
bool modifyPhoneStateAllowed(pid_t pid, uid_t uid);
bool bypassInterruptionPolicyAllowed(pid_t pid, uid_t uid);

@ -2969,7 +2969,7 @@ std::vector<sp<AudioFlinger::EffectModule>> AudioFlinger::purgeStaleEffects_l()
Mutex::Autolock _l(t->mLock);
for (size_t j = 0; j < t->mEffectChains.size(); j++) {
sp<EffectChain> ec = t->mEffectChains[j];
if (ec->sessionId() > AUDIO_SESSION_OUTPUT_MIX) {
if (!audio_is_global_session(ec->sessionId())) {
chains.push(ec);
}
}
@ -3371,6 +3371,13 @@ sp<IEffect> AudioFlinger::createEffect(
lStatus = BAD_VALUE;
goto Exit;
}
} else if (sessionId == AUDIO_SESSION_DEVICE) {
if (!modifyDefaultAudioEffectsAllowed(pid, callingUid)) {
ALOGE("%s: device effect permission denied for uid %d", __func__, callingUid);
lStatus = PERMISSION_DENIED;
goto Exit;
}
//TODO: add check on device ID when added to arguments
} else {
// general sessionId.
@ -3406,7 +3413,7 @@ sp<IEffect> AudioFlinger::createEffect(
// check recording permission for visualizer
if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
// TODO: Do we need to start/stop op - i.e. is there recording being performed?
!recordingAllowed(opPackageName, pid, IPCThreadState::self()->getCallingUid())) {
!recordingAllowed(opPackageName, pid, callingUid)) {
lStatus = PERMISSION_DENIED;
goto Exit;
}
@ -3504,7 +3511,7 @@ sp<IEffect> AudioFlinger::createEffect(
sp<Client> client = registerPid(pid);
// create effect on selected output thread
bool pinned = (sessionId > AUDIO_SESSION_OUTPUT_MIX) && isSessionAcquired_l(sessionId);
bool pinned = !audio_is_global_session(sessionId) && isSessionAcquired_l(sessionId);
handle = thread->createEffect_l(client, effectClient, priority, sessionId,
&desc, enabled, &lStatus, pinned);
if (lStatus != NO_ERROR && lStatus != ALREADY_EXISTS) {

@ -637,7 +637,7 @@ status_t AudioFlinger::EffectModule::configure()
mConfig.outputCfg.bufferProvider.releaseBuffer = NULL;
mConfig.inputCfg.accessMode = EFFECT_BUFFER_ACCESS_READ;
// Insert effect:
// - in session AUDIO_SESSION_OUTPUT_MIX or AUDIO_SESSION_OUTPUT_STAGE,
// - in global sessions (e.g AUDIO_SESSION_OUTPUT_MIX),
// always overwrites output buffer: input buffer == output buffer
// - in other sessions:
// last effect in the chain accumulates in output buffer: input buffer != output buffer
@ -2062,14 +2062,12 @@ void AudioFlinger::EffectChain::process_l()
ALOGW("process_l(): cannot promote mixer thread");
return;
}
bool isGlobalSession = (mSessionId == AUDIO_SESSION_OUTPUT_MIX) ||
(mSessionId == AUDIO_SESSION_OUTPUT_STAGE);
// never process effects when:
// - on an OFFLOAD thread
// - no more tracks are on the session and the effect tail has been rendered
bool doProcess = (thread->type() != ThreadBase::OFFLOAD)
&& (thread->type() != ThreadBase::MMAP);
if (!isGlobalSession) {
if (!audio_is_global_session(mSessionId)) {
bool tracksOnSession = (trackCnt() != 0);
if (!tracksOnSession && mTailBufferCount == 0) {

@ -1164,7 +1164,7 @@ void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModu
// and applications not using global effects.
// Enabling post processing in AUDIO_SESSION_OUTPUT_STAGE session does not affect
// global effects
if ((sessionId != AUDIO_SESSION_OUTPUT_MIX) && (sessionId != AUDIO_SESSION_OUTPUT_STAGE)) {
if (!audio_is_global_session(sessionId)) {
setEffectSuspended_l(NULL, enabled, AUDIO_SESSION_OUTPUT_MIX);
}
}
@ -1179,8 +1179,9 @@ void AudioFlinger::ThreadBase::checkSuspendOnEffectEnabled_l(const sp<EffectModu
status_t AudioFlinger::RecordThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
// No global effect sessions on record threads
if (sessionId == AUDIO_SESSION_OUTPUT_MIX || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
// No global output effect sessions on record threads
if (sessionId == AUDIO_SESSION_OUTPUT_MIX
|| sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
ALOGW("checkEffectCompatibility_l(): global effect %s on record thread %s",
desc->name, mThreadName);
return BAD_VALUE;
@ -1254,6 +1255,13 @@ status_t AudioFlinger::PlaybackThread::checkEffectCompatibility_l(
" on output stage session", desc->name);
return BAD_VALUE;
}
} else if (sessionId == AUDIO_SESSION_DEVICE) {
// only post processing on output stage session
if ((desc->flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_POST_PROC) {
ALOGW("checkEffectCompatibility_l(): non post processing effect %s not allowed"
" on device session", desc->name);
return BAD_VALUE;
}
} else {
// no restriction on effects applied on non fast tracks
if ((hasAudioSession_l(sessionId) & ThreadBase::FAST_SESSION) == 0) {
@ -1295,7 +1303,7 @@ status_t AudioFlinger::PlaybackThread::checkEffectCompatibility_l(
return BAD_VALUE;
}
#endif
if ((sessionId == AUDIO_SESSION_OUTPUT_STAGE) || (sessionId == AUDIO_SESSION_OUTPUT_MIX)) {
if (audio_is_global_session(sessionId)) {
ALOGW("checkEffectCompatibility_l(): global effect %s on DUPLICATING"
" thread %s", desc->name, mThreadName);
return BAD_VALUE;
@ -2051,6 +2059,7 @@ sp<AudioFlinger::PlaybackThread::Track> AudioFlinger::PlaybackThread::createTrac
{ // scope for mLock
Mutex::Autolock _l(mLock);
for (audio_session_t session : {
AUDIO_SESSION_DEVICE,
AUDIO_SESSION_OUTPUT_STAGE,
AUDIO_SESSION_OUTPUT_MIX,
sessionId,
@ -3103,7 +3112,7 @@ status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& c
halOutBuffer = halInBuffer;
effect_buffer_t *buffer = reinterpret_cast<effect_buffer_t*>(halInBuffer->externalData());
ALOGV("addEffectChain_l() %p on thread %p for session %d", chain.get(), this, session);
if (session > AUDIO_SESSION_OUTPUT_MIX) {
if (!audio_is_global_session(session)) {
// Only one effect chain can be present in direct output thread and it uses
// the sink buffer as input
if (mType != DIRECT) {
@ -3143,8 +3152,11 @@ status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& c
chain->setThread(this);
chain->setInBuffer(halInBuffer);
chain->setOutBuffer(halOutBuffer);
// Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted at end of effect
// chains list in order to be processed last as it contains output stage effects.
// Effect chain for session AUDIO_SESSION_DEVICE is inserted at end of effect
// chains list in order to be processed last as it contains output device effects.
// Effect chain for session AUDIO_SESSION_OUTPUT_STAGE is inserted just before to apply post
// processing effects specific to an output stream before effects applied to all streams
// routed to a given device.
// Effect chain for session AUDIO_SESSION_OUTPUT_MIX is inserted before
// session AUDIO_SESSION_OUTPUT_STAGE to be processed
// after track specific effects and before output stage.
@ -3154,7 +3166,8 @@ status_t AudioFlinger::PlaybackThread::addEffectChain_l(const sp<EffectChain>& c
// chains list to be processed before output mix effects. Relative order between other
// sessions is not important.
static_assert(AUDIO_SESSION_OUTPUT_MIX == 0 &&
AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX,
AUDIO_SESSION_OUTPUT_STAGE < AUDIO_SESSION_OUTPUT_MIX &&
AUDIO_SESSION_DEVICE < AUDIO_SESSION_OUTPUT_STAGE,
"audio_session_t constants misdefined");
size_t size = mEffectChains.size();
size_t i = 0;
@ -9099,8 +9112,8 @@ status_t AudioFlinger::MmapThread::checkEffectCompatibility_l(
const effect_descriptor_t *desc, audio_session_t sessionId)
{
// No global effect sessions on mmap threads
if (sessionId == AUDIO_SESSION_OUTPUT_MIX || sessionId == AUDIO_SESSION_OUTPUT_STAGE) {
ALOGW("checkEffectCompatibility_l(): global effect %s on record thread %s",
if (audio_is_global_session(sessionId)) {
ALOGW("checkEffectCompatibility_l(): global effect %s on MMAP thread %s",
desc->name, mThreadName);
return BAD_VALUE;
}
@ -9122,7 +9135,6 @@ status_t AudioFlinger::MmapThread::checkEffectCompatibility_l(
}
return NO_ERROR;
}
void AudioFlinger::MmapThread::checkInvalidTracks_l()

Loading…
Cancel
Save