Add dynamic source default effects

Allows runtime modification of what effects should be default
attached to sources of different types. The core functionality
was already in the AudioPolicyEffects system, this allows
the dynamic modification of the lists.

Bug: 78527120
Test: Builds, manually tested an app adding a source effect,
tested both media on the specified source and on a different source.
Also tested by Android Things integration tests.

Change-Id: I4da15787278c79d80043e172f4f81d3b2a139f44
gugelfrei
Ari Hausman-Cohen 6 years ago
parent edf39faeee
commit 2462831059

@ -456,6 +456,38 @@ status_t AudioEffect::newEffectUniqueId(audio_unique_id_t* id)
return NO_ERROR;
}
status_t AudioEffect::addSourceDefaultEffect(const char *typeStr,
const String16& opPackageName,
const char *uuidStr,
int32_t priority,
audio_source_t source,
audio_unique_id_t *id)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
if (typeStr == NULL && uuidStr == NULL) return BAD_VALUE;
// Convert type & uuid from string to effect_uuid_t.
effect_uuid_t type;
if (typeStr != NULL) {
status_t res = stringToGuid(typeStr, &type);
if (res != OK) return res;
} else {
type = *EFFECT_UUID_NULL;
}
effect_uuid_t uuid;
if (uuidStr != NULL) {
status_t res = stringToGuid(uuidStr, &uuid);
if (res != OK) return res;
} else {
uuid = *EFFECT_UUID_NULL;
}
return aps->addSourceDefaultEffect(&type, opPackageName, &uuid, priority, source, id);
}
status_t AudioEffect::addStreamDefaultEffect(const char *typeStr,
const String16& opPackageName,
const char *uuidStr,
@ -488,6 +520,14 @@ status_t AudioEffect::addStreamDefaultEffect(const char *typeStr,
return aps->addStreamDefaultEffect(&type, opPackageName, &uuid, priority, usage, id);
}
status_t AudioEffect::removeSourceDefaultEffect(audio_unique_id_t id)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return PERMISSION_DENIED;
return aps->removeSourceDefaultEffect(id);
}
status_t AudioEffect::removeStreamDefaultEffect(audio_unique_id_t id)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();

@ -83,7 +83,9 @@ enum {
GET_SURROUND_FORMATS,
SET_SURROUND_FORMAT_ENABLED,
ADD_STREAM_DEFAULT_EFFECT,
REMOVE_STREAM_DEFAULT_EFFECT
REMOVE_STREAM_DEFAULT_EFFECT,
ADD_SOURCE_DEFAULT_EFFECT,
REMOVE_SOURCE_DEFAULT_EFFECT
};
#define MAX_ITEMS_PER_LIST 1024
@ -904,6 +906,41 @@ public:
return static_cast <status_t> (reply.readInt32());
}
virtual status_t addSourceDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_source_t source,
audio_unique_id_t* id)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.write(type, sizeof(effect_uuid_t));
data.writeString16(opPackageName);
data.write(uuid, sizeof(effect_uuid_t));
data.writeInt32(priority);
data.writeInt32((int32_t) source);
status_t status = remote()->transact(ADD_SOURCE_DEFAULT_EFFECT, data, &reply);
if (status != NO_ERROR) {
return status;
}
status = static_cast <status_t> (reply.readInt32());
*id = reply.readInt32();
return status;
}
virtual status_t removeSourceDefaultEffect(audio_unique_id_t id)
{
Parcel data, reply;
data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
data.writeInt32(id);
status_t status = remote()->transact(REMOVE_SOURCE_DEFAULT_EFFECT, data, &reply);
if (status != NO_ERROR) {
return status;
}
return static_cast <status_t> (reply.readInt32());
}
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@ -1636,6 +1673,43 @@ status_t BnAudioPolicyService::onTransact(
return NO_ERROR;
}
case ADD_SOURCE_DEFAULT_EFFECT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
effect_uuid_t type;
status_t status = data.read(&type, sizeof(effect_uuid_t));
if (status != NO_ERROR) {
return status;
}
String16 opPackageName;
status = data.readString16(&opPackageName);
if (status != NO_ERROR) {
return status;
}
effect_uuid_t uuid;
status = data.read(&uuid, sizeof(effect_uuid_t));
if (status != NO_ERROR) {
return status;
}
int32_t priority = data.readInt32();
audio_source_t source = (audio_source_t) data.readInt32();
audio_unique_id_t id = 0;
reply->writeInt32(static_cast <int32_t>(addSourceDefaultEffect(&type,
opPackageName,
&uuid,
priority,
source,
&id)));
reply->writeInt32(id);
return NO_ERROR;
}
case REMOVE_SOURCE_DEFAULT_EFFECT: {
CHECK_INTERFACE(IAudioPolicyService, data, reply);
audio_unique_id_t id = static_cast<audio_unique_id_t>(data.readInt32());
reply->writeInt32(static_cast <int32_t>(removeSourceDefaultEffect(id)));
return NO_ERROR;
}
default:
return BBinder::onTransact(code, data, reply, flags);
}

@ -169,6 +169,44 @@ public:
* Static methods for adding/removing system-wide effects.
*/
/*
* Adds an effect to the list of default output effects for a given source type.
*
* If the effect is no longer available when a source of the given type
* is created, the system will continue without adding it.
*
* Parameters:
* typeStr: Type uuid of effect to be a default: can be null if uuidStr is specified.
* This may correspond to the OpenSL ES interface implemented by this effect,
* or could be some vendor-defined type.
* opPackageName: The package name used for app op checks.
* uuidStr: Uuid of effect to be a default: can be null if type is specified.
* This uuid corresponds to a particular implementation of an effect type.
* Note if both uuidStr and typeStr are specified, typeStr is ignored.
* priority: Requested priority for effect control: the priority level corresponds to the
* value of priority parameter: negative values indicate lower priorities, positive
* values higher priorities, 0 being the normal priority.
* source: The source this effect should be a default for.
* id: Address where the system-wide unique id of the default effect should be returned.
*
* Returned status (from utils/Errors.h) can be:
* NO_ERROR successful operation.
* PERMISSION_DENIED could not get AudioFlinger interface
* or caller lacks required permissions.
* NO_INIT effect library failed to initialize.
* BAD_VALUE invalid source, type uuid or implementation uuid.
* NAME_NOT_FOUND no effect with this uuid or type found.
*
* Returned value
* *id: The system-wide unique id of the added default effect.
*/
static status_t addSourceDefaultEffect(const char* typeStr,
const String16& opPackageName,
const char* uuidStr,
int32_t priority,
audio_source_t source,
audio_unique_id_t* id);
/*
* Adds an effect to the list of default output effects for a given stream type.
*
@ -208,6 +246,21 @@ public:
audio_usage_t usage,
audio_unique_id_t* id);
/*
* Removes an effect from the list of default output effects for a given source type.
*
* Parameters:
* id: The system-wide unique id of the effect that should no longer be a default.
*
* Returned status (from utils/Errors.h) can be:
* NO_ERROR successful operation.
* PERMISSION_DENIED could not get AudioFlinger interface
* or caller lacks required permissions.
* NO_INIT effect library failed to initialize.
* BAD_VALUE invalid id.
*/
static status_t removeSourceDefaultEffect(audio_unique_id_t id);
/*
* Removes an effect from the list of default output effects for a given stream type.
*

@ -109,12 +109,19 @@ public:
virtual status_t queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count) = 0;
virtual status_t addSourceDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_source_t source,
audio_unique_id_t* id) = 0;
virtual status_t addStreamDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_usage_t usage,
audio_unique_id_t* id) = 0;
virtual status_t removeSourceDefaultEffect(audio_unique_id_t id) = 0;
virtual status_t removeStreamDefaultEffect(audio_unique_id_t id) = 0;
// Check if offload is possible for given format, stream type, sample rate,
// bit rate, duration, video and streaming or offload property is enabled

@ -318,6 +318,74 @@ status_t AudioPolicyEffects::releaseOutputSessionEffects(audio_io_handle_t outpu
return status;
}
status_t AudioPolicyEffects::addSourceDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_source_t source,
audio_unique_id_t* id)
{
if (uuid == NULL || type == NULL) {
ALOGE("addSourceDefaultEffect(): Null uuid or type uuid pointer");
return BAD_VALUE;
}
// HOTWORD and FM_TUNER are two special case sources > MAX.
if (source < AUDIO_SOURCE_DEFAULT ||
(source > AUDIO_SOURCE_MAX &&
source != AUDIO_SOURCE_HOTWORD &&
source != AUDIO_SOURCE_FM_TUNER)) {
ALOGE("addSourceDefaultEffect(): Unsupported source type %d", source);
return BAD_VALUE;
}
// Check that |uuid| or |type| corresponds to an effect on the system.
effect_descriptor_t descriptor = {};
status_t res = AudioEffect::getEffectDescriptor(
uuid, type, EFFECT_FLAG_TYPE_PRE_PROC, &descriptor);
if (res != OK) {
ALOGE("addSourceDefaultEffect(): Failed to find effect descriptor matching uuid/type.");
return res;
}
// Only pre-processing effects can be added dynamically as source defaults.
if ((descriptor.flags & EFFECT_FLAG_TYPE_MASK) != EFFECT_FLAG_TYPE_PRE_PROC) {
ALOGE("addSourceDefaultEffect(): Desired effect cannot be attached "
"as a source default effect.");
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
// Find the EffectDescVector for the given source type, or create a new one if necessary.
ssize_t index = mInputSources.indexOfKey(source);
EffectDescVector *desc = NULL;
if (index < 0) {
// No effects for this source type yet.
desc = new EffectDescVector();
mInputSources.add(source, desc);
} else {
desc = mInputSources.valueAt(index);
}
// Create a new effect and add it to the vector.
res = AudioEffect::newEffectUniqueId(id);
if (res != OK) {
ALOGE("addSourceDefaultEffect(): failed to get new unique id.");
return res;
}
EffectDesc *effect = new EffectDesc(
descriptor.name, *type, opPackageName, *uuid, priority, *id);
desc->mEffects.add(effect);
// TODO(b/71813697): Support setting params as well.
// TODO(b/71814300): Retroactively attach to any existing sources of the given type.
// This requires tracking the source type of each session id in addition to what is
// already being tracked.
return NO_ERROR;
}
status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
@ -384,6 +452,37 @@ status_t AudioPolicyEffects::addStreamDefaultEffect(const effect_uuid_t *type,
return NO_ERROR;
}
status_t AudioPolicyEffects::removeSourceDefaultEffect(audio_unique_id_t id)
{
if (id == AUDIO_UNIQUE_ID_ALLOCATE) {
// ALLOCATE is not a unique identifier, but rather a reserved value indicating
// a real id has not been assigned. For default effects, this value is only used
// by system-owned defaults from the loaded config, which cannot be removed.
return BAD_VALUE;
}
Mutex::Autolock _l(mLock);
// Check each source type.
size_t numSources = mInputSources.size();
for (size_t i = 0; i < numSources; ++i) {
// Check each effect for each source.
EffectDescVector* descVector = mInputSources[i];
for (auto desc = descVector->mEffects.begin(); desc != descVector->mEffects.end(); ++desc) {
if ((*desc)->mId == id) {
// Found it!
// TODO(b/71814300): Remove from any sources the effect was attached to.
descVector->mEffects.erase(desc);
// Handles are unique; there can only be one match, so return early.
return NO_ERROR;
}
}
}
// Effect wasn't found, so it's been trivially removed successfully.
return NO_ERROR;
}
status_t AudioPolicyEffects::removeStreamDefaultEffect(audio_unique_id_t id)
{
if (id == AUDIO_UNIQUE_ID_ALLOCATE) {

@ -81,7 +81,15 @@ public:
audio_stream_type_t stream,
audio_session_t audioSession);
// Add the effect to the list of default effects for streams of type |stream|.
// Add the effect to the list of default effects for sources of type |source|.
status_t addSourceDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_source_t source,
audio_unique_id_t* id);
// Add the effect to the list of default effects for streams of a given usage.
status_t addStreamDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
@ -89,6 +97,9 @@ public:
audio_usage_t usage,
audio_unique_id_t* id);
// Remove the default source effect from wherever it's attached.
status_t removeSourceDefaultEffect(audio_unique_id_t id);
// Remove the default stream effect from wherever it's attached.
status_t removeStreamDefaultEffect(audio_unique_id_t id);

@ -829,67 +829,96 @@ bool AudioPolicyService::isSourceActive(audio_source_t source) const
return mAudioPolicyManager->isSourceActive(source);
}
status_t AudioPolicyService::queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count)
status_t AudioPolicyService::getAudioPolicyEffects(sp<AudioPolicyEffects>& audioPolicyEffects)
{
if (mAudioPolicyManager == NULL) {
*count = 0;
return NO_INIT;
}
sp<AudioPolicyEffects>audioPolicyEffects;
{
Mutex::Autolock _l(mLock);
audioPolicyEffects = mAudioPolicyEffects;
}
if (audioPolicyEffects == 0) {
*count = 0;
return NO_INIT;
}
return OK;
}
status_t AudioPolicyService::queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count)
{
sp<AudioPolicyEffects>audioPolicyEffects;
status_t status = getAudioPolicyEffects(audioPolicyEffects);
if (status != OK) {
*count = 0;
return status;
}
return audioPolicyEffects->queryDefaultInputEffects(
(audio_session_t)audioSession, descriptors, count);
}
status_t AudioPolicyService::addStreamDefaultEffect(const effect_uuid_t *type,
status_t AudioPolicyService::addSourceDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_usage_t usage,
audio_source_t source,
audio_unique_id_t* id)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
sp<AudioPolicyEffects>audioPolicyEffects;
status_t status = getAudioPolicyEffects(audioPolicyEffects);
if (status != OK) {
return status;
}
if (!modifyDefaultAudioEffectsAllowed()) {
return PERMISSION_DENIED;
}
return audioPolicyEffects->addSourceDefaultEffect(
type, opPackageName, uuid, priority, source, id);
}
status_t AudioPolicyService::addStreamDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_usage_t usage,
audio_unique_id_t* id)
{
sp<AudioPolicyEffects>audioPolicyEffects;
{
Mutex::Autolock _l(mLock);
audioPolicyEffects = mAudioPolicyEffects;
status_t status = getAudioPolicyEffects(audioPolicyEffects);
if (status != OK) {
return status;
}
if (audioPolicyEffects == 0) {
return NO_INIT;
if (!modifyDefaultAudioEffectsAllowed()) {
return PERMISSION_DENIED;
}
return audioPolicyEffects->addStreamDefaultEffect(
type, opPackageName, uuid, priority, usage, id);
}
status_t AudioPolicyService::removeStreamDefaultEffect(audio_unique_id_t id)
status_t AudioPolicyService::removeSourceDefaultEffect(audio_unique_id_t id)
{
if (mAudioPolicyManager == NULL) {
return NO_INIT;
sp<AudioPolicyEffects>audioPolicyEffects;
status_t status = getAudioPolicyEffects(audioPolicyEffects);
if (status != OK) {
return status;
}
if (!modifyDefaultAudioEffectsAllowed()) {
return PERMISSION_DENIED;
}
return audioPolicyEffects->removeSourceDefaultEffect(id);
}
status_t AudioPolicyService::removeStreamDefaultEffect(audio_unique_id_t id)
{
sp<AudioPolicyEffects>audioPolicyEffects;
{
Mutex::Autolock _l(mLock);
audioPolicyEffects = mAudioPolicyEffects;
status_t status = getAudioPolicyEffects(audioPolicyEffects);
if (status != OK) {
return status;
}
if (audioPolicyEffects == 0) {
return NO_INIT;
if (!modifyDefaultAudioEffectsAllowed()) {
return PERMISSION_DENIED;
}
return audioPolicyEffects->removeStreamDefaultEffect(id);
}

@ -126,12 +126,19 @@ public:
virtual status_t queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count);
virtual status_t addSourceDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_source_t source,
audio_unique_id_t* id);
virtual status_t addStreamDefaultEffect(const effect_uuid_t *type,
const String16& opPackageName,
const effect_uuid_t *uuid,
int32_t priority,
audio_usage_t usage,
audio_unique_id_t* id);
virtual status_t removeSourceDefaultEffect(audio_unique_id_t id);
virtual status_t removeStreamDefaultEffect(audio_unique_id_t id);
virtual status_t onTransact(
@ -259,6 +266,8 @@ private:
std::string getDeviceTypeStrForPortId(audio_port_handle_t portId);
status_t getAudioPolicyEffects(sp<AudioPolicyEffects>& audioPolicyEffects);
// If recording we need to make sure the UID is allowed to do that. If the UID is idle
// then it cannot record and gets buffers with zeros - silence. As soon as the UID
// transitions to an active state we will start reporting buffers with data. This approach

Loading…
Cancel
Save