summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Laurent <elaurent@google.com> 2020-03-13 14:30:13 -0700
committer Eric Laurent <elaurent@google.com> 2020-03-16 13:46:56 -0700
commita50302568731d867467f34681d60a80fe76e52f2 (patch)
treeabffa16c5f0befc5bc207480976d3bee411d36ad
parent3bdd15fbb45911fafbbdd1000311c2320e99cdc3 (diff)
AudioEffect: add isEffectSupportedForDevice() API
Add AudioEffect.isEffectSupportedForDevice() @SystemApi for apps to query if an audio effect can be created and attached to a particular device without actually calling the constructor and checking for exceptions. Bug: 150699608 Test: CTS and GTS Tests for audio effects Change-Id: Ia03af6114a5cafdc46d5d0cb8130fc0165ca93ac
-rwxr-xr-xapi/system-current.txt1
-rw-r--r--media/java/android/media/audiofx/AudioEffect.java43
-rw-r--r--media/jni/audioeffect/android_media_AudioEffect.cpp16
3 files changed, 51 insertions, 9 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index 843fef9eca0b..aa2261583620 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4403,6 +4403,7 @@ package android.media.audiofx {
public class AudioEffect {
ctor @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public AudioEffect(@NonNull java.util.UUID, @NonNull android.media.AudioDeviceAttributes);
+ method @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public static boolean isEffectSupportedForDevice(@NonNull java.util.UUID, @NonNull android.media.AudioDeviceAttributes);
}
}
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 2587350b6830..42635216e98f 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -477,13 +477,21 @@ public class AudioEffect {
@SystemApi
@RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
public AudioEffect(@NonNull UUID uuid, @NonNull AudioDeviceAttributes device) {
- this(EFFECT_TYPE_NULL, Objects.requireNonNull(uuid), 0, -2, Objects.requireNonNull(device));
+ this(EFFECT_TYPE_NULL, Objects.requireNonNull(uuid),
+ 0, -2, Objects.requireNonNull(device));
}
private AudioEffect(UUID type, UUID uuid, int priority,
int audioSession, @Nullable AudioDeviceAttributes device)
throws IllegalArgumentException, UnsupportedOperationException,
RuntimeException {
+ this(type, uuid, priority, audioSession, device, false);
+ }
+
+ private AudioEffect(UUID type, UUID uuid, int priority,
+ int audioSession, @Nullable AudioDeviceAttributes device, boolean probe)
+ throws IllegalArgumentException, UnsupportedOperationException,
+ RuntimeException {
int[] id = new int[1];
Descriptor[] desc = new Descriptor[1];
@@ -498,7 +506,7 @@ public class AudioEffect {
int initResult = native_setup(new WeakReference<AudioEffect>(this),
type.toString(), uuid.toString(), priority, audioSession,
deviceType, deviceAddress,
- id, desc, ActivityThread.currentOpPackageName());
+ id, desc, ActivityThread.currentOpPackageName(), probe);
if (initResult != SUCCESS && initResult != ALREADY_EXISTS) {
Log.e(TAG, "Error code " + initResult
+ " when initializing AudioEffect.");
@@ -517,8 +525,33 @@ public class AudioEffect {
}
mId = id[0];
mDescriptor = desc[0];
- synchronized (mStateLock) {
- mState = STATE_INITIALIZED;
+ if (!probe) {
+ synchronized (mStateLock) {
+ mState = STATE_INITIALIZED;
+ }
+ }
+ }
+
+ /**
+ * Checks if an AudioEffect identified by the supplied uuid can be attached
+ * to an audio device described by the supplied AudioDeviceAttributes.
+ * @param uuid unique identifier of a particular effect implementation.
+ * @param device the device the effect would be attached to.
+ * @return true if possible, false otherwise.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
+ public static boolean isEffectSupportedForDevice(
+ @NonNull UUID uuid, @NonNull AudioDeviceAttributes device) {
+ try {
+ AudioEffect fx = new AudioEffect(
+ EFFECT_TYPE_NULL, Objects.requireNonNull(uuid),
+ 0, -2, Objects.requireNonNull(device), true);
+ fx.release();
+ return true;
+ } catch (Exception e) {
+ return false;
}
}
@@ -1340,7 +1373,7 @@ public class AudioEffect {
private native final int native_setup(Object audioeffect_this, String type,
String uuid, int priority, int audioSession,
int deviceType, String deviceAddress, int[] id, Object[] desc,
- String opPackageName);
+ String opPackageName, boolean probe);
private native final void native_finalize();
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 007dd10aba1f..dbe7b4b619c9 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -270,7 +270,7 @@ static jint
android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
jstring type, jstring uuid, jint priority, jint sessionId,
jint deviceType, jstring deviceAddress,
- jintArray jId, jobjectArray javadesc, jstring opPackageName)
+ jintArray jId, jobjectArray javadesc, jstring opPackageName, jboolean probe)
{
ALOGV("android_media_AudioEffect_native_setup");
AudioEffectJniStorage* lpJniStorage = NULL;
@@ -345,12 +345,14 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
&lpJniStorage->mCallbackData,
(audio_session_t) sessionId,
AUDIO_IO_HANDLE_NONE,
- device);
+ device,
+ probe);
if (lpAudioEffect == 0) {
ALOGE("Error creating AudioEffect");
goto setup_failure;
}
+
lStatus = AudioEffectJni::translateNativeErrorToJava(lpAudioEffect->initCheck());
if (lStatus != AUDIOEFFECT_SUCCESS && lStatus != AUDIOEFFECT_ERROR_ALREADY_EXISTS) {
ALOGE("AudioEffect initCheck failed %d", lStatus);
@@ -387,7 +389,13 @@ android_media_AudioEffect_native_setup(JNIEnv *env, jobject thiz, jobject weak_t
env->SetObjectArrayElement(javadesc, 0, jdesc);
env->DeleteLocalRef(jdesc);
- setAudioEffect(env, thiz, lpAudioEffect);
+ // In probe mode, release the native object and clear our strong reference
+ // to force all method calls from JAVA to be rejected.
+ if (probe) {
+ setAudioEffect(env, thiz, 0);
+ } else {
+ setAudioEffect(env, thiz, lpAudioEffect);
+ }
env->SetLongField(thiz, fields.fidJniData, (jlong)lpJniStorage);
@@ -766,7 +774,7 @@ android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz _
// Dalvik VM type signatures
static const JNINativeMethod gMethods[] = {
{"native_init", "()V", (void *)android_media_AudioEffect_native_init},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIILjava/lang/String;[I[Ljava/lang/Object;Ljava/lang/String;)I",
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;IIILjava/lang/String;[I[Ljava/lang/Object;Ljava/lang/String;Z)I",
(void *)android_media_AudioEffect_native_setup},
{"native_finalize", "()V", (void *)android_media_AudioEffect_native_finalize},
{"native_release", "()V", (void *)android_media_AudioEffect_native_release},