diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp index 0641b6ead6..0ae2738138 100644 --- a/media/libaudioclient/AudioEffect.cpp +++ b/media/libaudioclient/AudioEffect.cpp @@ -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& 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& 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& aps = AudioSystem::get_audio_policy_service(); diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp index abf74f80e4..32a71f3b6a 100644 --- a/media/libaudioclient/IAudioPolicyService.cpp +++ b/media/libaudioclient/IAudioPolicyService.cpp @@ -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 (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 (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 (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 (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(data.readInt32()); + reply->writeInt32(static_cast (removeSourceDefaultEffect(id))); + return NO_ERROR; + } + default: return BBinder::onTransact(code, data, reply, flags); } diff --git a/media/libaudioclient/include/media/AudioEffect.h b/media/libaudioclient/include/media/AudioEffect.h index c97f7838a3..0de58b85a5 100644 --- a/media/libaudioclient/include/media/AudioEffect.h +++ b/media/libaudioclient/include/media/AudioEffect.h @@ -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. * diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h index c2899f83e0..fdd8d57969 100644 --- a/media/libaudioclient/include/media/IAudioPolicyService.h +++ b/media/libaudioclient/include/media/IAudioPolicyService.h @@ -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 diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp index 2858aadb2d..b3d564aaf3 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.cpp +++ b/services/audiopolicy/service/AudioPolicyEffects.cpp @@ -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) { diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h index 69367b1dc0..6ad01f7611 100644 --- a/services/audiopolicy/service/AudioPolicyEffects.h +++ b/services/audiopolicy/service/AudioPolicyEffects.h @@ -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); diff --git a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp index 3439c9bcda..02ab07fbed 100644 --- a/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp +++ b/services/audiopolicy/service/AudioPolicyInterfaceImpl.cpp @@ -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) { if (mAudioPolicyManager == NULL) { - *count = 0; return NO_INIT; } - spaudioPolicyEffects; { 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) +{ + spaudioPolicyEffects; + 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; + spaudioPolicyEffects; + 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) +{ spaudioPolicyEffects; - { - 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; + spaudioPolicyEffects; + 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) +{ spaudioPolicyEffects; - { - 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); } diff --git a/services/audiopolicy/service/AudioPolicyService.h b/services/audiopolicy/service/AudioPolicyService.h index 44c0347f7f..6c5564728a 100644 --- a/services/audiopolicy/service/AudioPolicyService.h +++ b/services/audiopolicy/service/AudioPolicyService.h @@ -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); + // 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