Add dynamic stream default effects
Allows runtime modification of what effects should be default
attached to streams of different types/usages. 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 stream effect,
tested both media on the specified stream and on a different stream.
Also tested by Android Things integration tests.
Change-Id: Ie0426b17ff7daece58b8c85d72fbef620844325b
diff --git a/media/libaudioclient/AudioEffect.cpp b/media/libaudioclient/AudioEffect.cpp
index cb46b93..0641b6e 100644
--- a/media/libaudioclient/AudioEffect.cpp
+++ b/media/libaudioclient/AudioEffect.cpp
@@ -447,6 +447,55 @@
if (aps == 0) return PERMISSION_DENIED;
return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
}
+
+status_t AudioEffect::newEffectUniqueId(audio_unique_id_t* id)
+{
+ const sp<IAudioFlinger>& af = AudioSystem::get_audio_flinger();
+ if (af == 0) return PERMISSION_DENIED;
+ *id = af->newAudioUniqueId(AUDIO_UNIQUE_ID_USE_EFFECT);
+ return NO_ERROR;
+}
+
+status_t AudioEffect::addStreamDefaultEffect(const char *typeStr,
+ const String16& opPackageName,
+ const char *uuidStr,
+ int32_t priority,
+ audio_usage_t usage,
+ 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->addStreamDefaultEffect(&type, opPackageName, &uuid, priority, usage, id);
+}
+
+status_t AudioEffect::removeStreamDefaultEffect(audio_unique_id_t id)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+
+ return aps->removeStreamDefaultEffect(id);
+}
+
// -------------------------------------------------------------------------
status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
diff --git a/media/libaudioclient/IAudioPolicyService.cpp b/media/libaudioclient/IAudioPolicyService.cpp
index 73a8b74..abf74f8 100644
--- a/media/libaudioclient/IAudioPolicyService.cpp
+++ b/media/libaudioclient/IAudioPolicyService.cpp
@@ -81,7 +81,9 @@
GET_MASTER_MONO,
GET_STREAM_VOLUME_DB,
GET_SURROUND_FORMATS,
- SET_SURROUND_FORMAT_ENABLED
+ SET_SURROUND_FORMAT_ENABLED,
+ ADD_STREAM_DEFAULT_EFFECT,
+ REMOVE_STREAM_DEFAULT_EFFECT
};
#define MAX_ITEMS_PER_LIST 1024
@@ -866,6 +868,42 @@
}
return reply.readInt32();
}
+
+ 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)
+ {
+ 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) usage);
+ status_t status = remote()->transact(ADD_STREAM_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 removeStreamDefaultEffect(audio_unique_id_t id)
+ {
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(id);
+ status_t status = remote()->transact(REMOVE_STREAM_DEFAULT_EFFECT, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ return static_cast <status_t> (reply.readInt32());
+ }
+
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -1561,6 +1599,43 @@
return NO_ERROR;
}
+ case ADD_STREAM_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_usage_t usage = (audio_usage_t) data.readInt32();
+ audio_unique_id_t id = 0;
+ reply->writeInt32(static_cast <int32_t>(addStreamDefaultEffect(&type,
+ opPackageName,
+ &uuid,
+ priority,
+ usage,
+ &id)));
+ reply->writeInt32(id);
+ return NO_ERROR;
+ }
+
+ case REMOVE_STREAM_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>(removeStreamDefaultEffect(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 ae66e8f..c97f783 100644
--- a/media/libaudioclient/include/media/AudioEffect.h
+++ b/media/libaudioclient/include/media/AudioEffect.h
@@ -151,6 +151,79 @@
uint32_t *count);
/*
+ * Gets a new system-wide unique effect id.
+ *
+ * Parameters:
+ * id: The address to return the generated id.
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * or caller lacks required permissions.
+ * Returned value
+ * *id: The new unique system-wide effect id.
+ */
+ static status_t newEffectUniqueId(audio_unique_id_t* id);
+
+ /*
+ * Static methods for adding/removing system-wide effects.
+ */
+
+ /*
+ * Adds an effect to the list of default output effects for a given stream type.
+ *
+ * If the effect is no longer available when a stream 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.
+ * usage: The usage this effect should be a default for. Unrecognized values will be
+ * treated as AUDIO_USAGE_UNKNOWN.
+ * 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 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 addStreamDefaultEffect(const char* typeStr,
+ const String16& opPackageName,
+ const char* uuidStr,
+ int32_t priority,
+ audio_usage_t usage,
+ audio_unique_id_t* id);
+
+ /*
+ * Removes an effect from the list of default output effects for a given stream 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 removeStreamDefaultEffect(audio_unique_id_t id);
+
+ /*
* Events used by callback function (effect_callback_t).
*/
enum event_type {
diff --git a/media/libaudioclient/include/media/IAudioPolicyService.h b/media/libaudioclient/include/media/IAudioPolicyService.h
index cdbb876..c2899f8 100644
--- a/media/libaudioclient/include/media/IAudioPolicyService.h
+++ b/media/libaudioclient/include/media/IAudioPolicyService.h
@@ -109,6 +109,13 @@
virtual status_t queryDefaultPreProcessing(audio_session_t audioSession,
effect_descriptor_t *descriptors,
uint32_t *count) = 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 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
virtual bool isOffloadSupported(const audio_offload_info_t& info) = 0;