Merge "Added APIs for audio preprocessing"
diff --git a/include/media/AudioEffect.h b/include/media/AudioEffect.h
index 496b23e..1417416 100644
--- a/include/media/AudioEffect.h
+++ b/include/media/AudioEffect.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <media/IAudioFlinger.h>
+#include <media/IAudioPolicyService.h>
#include <media/IEffect.h>
#include <media/IEffectClient.h>
#include <hardware/audio_effect.h>
@@ -111,6 +112,36 @@
/*
+ * Returns a list of descriptors corresponding to the pre processings enabled by default
+ * on an AudioRecord with the supplied audio session ID.
+ *
+ * Parameters:
+ * audioSession: audio session ID.
+ * descriptors: address where the effect descriptors should be returned.
+ * count: as input, the maximum number of descriptor than should be returned
+ * as output, the number of descriptor returned if status is NO_ERROR or the actual
+ * number of enabled pre processings if status is NO_MEMORY
+ *
+ * Returned status (from utils/Errors.h) can be:
+ * NO_ERROR successful operation.
+ * NO_MEMORY the number of descriptor to return is more than the maximum number
+ * indicated by count.
+ * PERMISSION_DENIED could not get AudioFlinger interface
+ * NO_INIT effect library failed to initialize
+ * BAD_VALUE invalid audio session or descriptor pointers
+ *
+ * Returned value
+ * *descriptor updated with descriptors of pre processings enabled by default
+ * *count number of descriptors returned if returned status is N_ERROR.
+ * total number of pre processing enabled by default if returned status is
+ * NO_MEMORY. This happens if the count passed as input is less than the number
+ * of descriptors to return
+ */
+ static status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count);
+
+ /*
* Events used by callback function (effect_callback_t).
*/
enum event_type {
diff --git a/include/media/IAudioPolicyService.h b/include/media/IAudioPolicyService.h
index 86b9f85..ed265e1 100644
--- a/include/media/IAudioPolicyService.h
+++ b/include/media/IAudioPolicyService.h
@@ -85,6 +85,9 @@
int id) = 0;
virtual status_t unregisterEffect(int id) = 0;
virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const = 0;
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count) = 0;
};
diff --git a/media/java/android/media/audiofx/AcousticEchoCanceler.java b/media/java/android/media/audiofx/AcousticEchoCanceler.java
new file mode 100644
index 0000000..7197dd2
--- /dev/null
+++ b/media/java/android/media/audiofx/AcousticEchoCanceler.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audiofx;
+
+/**
+ * Acoustic Echo Canceler (AEC).
+ * <p>Acoustic Echo Canceler (AEC) is an audio pre-processing which removes the contribution of the
+ * signal received from the remote party from the captured audio signal.
+ * <p>AEC is used by voice communication applications (voice chat, video conferencing, SIP calls)
+ * where the presence of echo with significant delay in the signal received from the remote party
+ * is highly disturbing. AEC is often used in conjunction with noise suppression (NS).
+ * <p>An application creates an AcousticEchoCanceler object to instantiate and control an AEC
+ * engine in the audio capture path.
+ * <p>To attach the AcousticEchoCanceler to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the AcousticEchoCanceler.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, an AEC can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class AcousticEchoCanceler extends AudioEffect {
+
+ private final static String TAG = "AcousticEchoCanceler";
+
+ /**
+ * Class constructor.
+ * <p> The application must catch exceptions when creating an AcousticEchoCanceler as the
+ * constructor is not guarantied to succeed:
+ * <ul>
+ * <li>IllegalArgumentException is thrown if the device does not implement an AEC</li>
+ * <li>UnsupportedOperationException is thrown is the resources allocated to audio
+ * pre-procesing are currently exceeded.</li>
+ * </ul>
+ *
+ * @param audioSession system wide unique audio session identifier. The AcousticEchoCanceler
+ * will be applied to the AudioRecord with the same audio session.
+ *
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.UnsupportedOperationException
+ * @throws java.lang.RuntimeException
+ */
+ public AcousticEchoCanceler(int audioSession)
+ throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+ super(EFFECT_TYPE_AEC, EFFECT_TYPE_NULL, 0, audioSession);
+ }
+}
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 39c6d3e..3ac0104 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -66,6 +66,8 @@
private final static String TAG = "AudioEffect-JAVA";
+ // effect type UUIDs are taken from hardware/libhardware/include/hardware/audio_effect.h
+
/**
* The following UUIDs define effect types corresponding to standard audio
* effects whose implementation and interface conform to the OpenSL ES
@@ -105,6 +107,27 @@
.fromString("37cc2c00-dddd-11db-8577-0002a5d5c51b");
/**
+ * UUID for Automatic Gain Control (AGC) audio pre-processing
+ * @hide
+ */
+ public static final UUID EFFECT_TYPE_AGC = UUID
+ .fromString("0a8abfe0-654c-11e0-ba26-0002a5d5c51b");
+
+ /**
+ * UUID for Acoustic Echo Canceler (AEC) audio pre-processing
+ * @hide
+ */
+ public static final UUID EFFECT_TYPE_AEC = UUID
+ .fromString("7b491460-8d4d-11e0-bd61-0002a5d5c51b");
+
+ /**
+ * UUID for Noise Suppressor (NS) audio pre-processing
+ * @hide
+ */
+ public static final UUID EFFECT_TYPE_NS = UUID
+ .fromString("58b4b260-8e06-11e0-aa8e-0002a5d5c51b");
+
+ /**
* Null effect UUID. Used when the UUID for effect type of
* @hide
*/
@@ -180,7 +203,8 @@
* <ul>
* <li>type: UUID corresponding to the OpenSL ES interface implemented by this effect</li>
* <li>uuid: UUID for this particular implementation</li>
- * <li>connectMode: {@link #EFFECT_INSERT} or {@link #EFFECT_AUXILIARY}</li>
+ * <li>connectMode: {@link #EFFECT_INSERT}, {@link #EFFECT_AUXILIARY} or
+ * {at_link #EFFECT_PRE_PROCESSING}</li>
* <li>name: human readable effect name</li>
* <li>implementor: human readable effect implementor name</li>
* </ul>
@@ -212,11 +236,13 @@
*/
public UUID uuid;
/**
- * Indicates if the effect is of insert category {@link #EFFECT_INSERT} or auxiliary
- * category {@link #EFFECT_AUXILIARY}. Insert effects (Typically an Equalizer) are applied
+ * Indicates if the effect is of insert category {@link #EFFECT_INSERT}, auxiliary
+ * category {@link #EFFECT_AUXILIARY} or pre processing category
+ * {at_link #EFFECT_PRE_PROCESSING}. Insert effects (Typically an Equalizer) are applied
* to the entire audio source and usually not shared by several sources. Auxiliary effects
* (typically a reverberator) are applied to part of the signal (wet) and the effect output
* is added to the original signal (dry).
+ * Audio pre processing are applied to audio captured on a particular AudioRecord.
*/
public String connectMode;
/**
@@ -243,6 +269,12 @@
* attaching it to the MediaPlayer or AudioTrack.
*/
public static final String EFFECT_AUXILIARY = "Auxiliary";
+ /**
+ * Effect connection mode is pre processing.
+ * The audio pre processing effects are attached to an audio input (AudioRecord).
+ * @hide
+ */
+ public static final String EFFECT_PRE_PROCESSING = "Pre Processing";
// --------------------------------------------------------------------------
// Member variables
@@ -410,6 +442,19 @@
return (Descriptor[]) native_query_effects();
}
+ /**
+ * Query all audio pre processing effects applied to the AudioRecord with the supplied
+ * audio session ID. Returns an array of {@link android.media.audiofx.AudioEffect.Descriptor}
+ * objects.
+ * @param audioSession system wide unique audio session identifier.
+ * @throws IllegalStateException
+ * @hide
+ */
+
+ static public Descriptor[] queryPreProcessings(int audioSession) {
+ return (Descriptor[]) native_query_pre_processing(audioSession);
+ }
+
// --------------------------------------------------------------------------
// Control methods
// --------------------
@@ -1155,6 +1200,8 @@
private static native Object[] native_query_effects();
+ private static native Object[] native_query_pre_processing(int audioSession);
+
// ---------------------------------------------------------
// Utility methods
// ------------------
diff --git a/media/java/android/media/audiofx/AutomaticGainControl.java b/media/java/android/media/audiofx/AutomaticGainControl.java
new file mode 100644
index 0000000..44574f0
--- /dev/null
+++ b/media/java/android/media/audiofx/AutomaticGainControl.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audiofx;
+
+/**
+ * Automatic Gain Control (AGC).
+ * <p>Automatic Gain Control (AGC) is an audio pre-processing which automatically normalizes the
+ * output of the captured signal by boosting or lowering input from the microphone to match a preset
+ * level so that that the output signal level is virtually constant.
+ * AGC can be used by applications where the input signal dynamic range is not important but where
+ * a constant strong capture level is desired.
+ * <p>An application creates a AutomaticGainControl object to instantiate and control an AGC
+ * engine in the audio framework.
+ * <p>To attach the AutomaticGainControl to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the AutomaticGainControl.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, an AGC can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class AutomaticGainControl extends AudioEffect {
+
+ private final static String TAG = "AutomaticGainControl";
+
+ /**
+ * Class constructor.
+ * <p> The application must catch exceptions when creating an AutomaticGainControl as the
+ * constructor is not guarantied to succeed:
+ * <ul>
+ * <li>IllegalArgumentException is thrown if the device does not implement an AGC</li>
+ * <li>UnsupportedOperationException is thrown is the resources allocated to audio
+ * pre-procesing are currently exceeded.</li>
+ * </ul>
+ *
+ * @param audioSession system wide unique audio session identifier. The AutomaticGainControl
+ * will be applied to the AudioRecord with the same audio session.
+ *
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.UnsupportedOperationException
+ * @throws java.lang.RuntimeException
+ */
+ public AutomaticGainControl(int audioSession)
+ throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+ super(EFFECT_TYPE_AGC, EFFECT_TYPE_NULL, 0, audioSession);
+ }
+}
diff --git a/media/java/android/media/audiofx/NoiseSuppressor.java b/media/java/android/media/audiofx/NoiseSuppressor.java
new file mode 100644
index 0000000..4e7a8b6
--- /dev/null
+++ b/media/java/android/media/audiofx/NoiseSuppressor.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.audiofx;
+
+/**
+ * Noise Suppressor (NS).
+ * <p>Noise suppression (NS) is an audio pre-processing which removes background noise from the
+ * captured signal. The component of the signal considered as noise can be either stationary
+ * (car/airplane engine, AC system) or non-stationary (other peoples conversations, car horn) for
+ * more advanced implementations.
+ * <p>NS is mostly used by voice communication applications (voice chat, video conferencing,
+ * SIP calls).
+ * <p>An application creates a NoiseSuppressor object to instantiate and control an NS
+ * engine in the audio framework.
+ * <p>To attach the NoiseSuppressor to a particular {@link android.media.AudioRecord},
+ * specify the audio session ID of this AudioRecord when constructing the NoiseSuppressor.
+ * The audio session is retrieved by calling
+ * {@link android.media.AudioRecord#getAudioSessionId()} on the AudioRecord instance.
+ * <p>On some devices, NS can be inserted by default in the capture path by the platform
+ * according to the {@link android.media.MediaRecorder.AudioSource} used. The application can
+ * query which pre-processings are currently applied to an AudioRecord instance by calling
+ * {@link android.media.audiofx.AudioEffect#queryPreProcessings(int)} with the audio session of the
+ * AudioRecord.
+ * <p>See {@link android.media.audiofx.AudioEffect} class for more details on
+ * controlling audio effects.
+ * @hide
+ */
+
+public class NoiseSuppressor extends AudioEffect {
+
+ private final static String TAG = "NoiseSuppressor";
+
+ /**
+ * Class constructor.
+ * <p> The application must catch exceptions when creating an NoiseSuppressor as the
+ * constructor is not guarantied to succeed:
+ * <ul>
+ * <li>IllegalArgumentException is thrown if the device does not implement an NS</li>
+ * <li>UnsupportedOperationException is thrown is the resources allocated to audio
+ * pre-procesing are currently exceeded.</li>
+ * </ul>
+ *
+ * @param audioSession system wide unique audio session identifier. The NoiseSuppressor
+ * will be applied to the AudioRecord with the same audio session.
+ *
+ * @throws java.lang.IllegalArgumentException
+ * @throws java.lang.UnsupportedOperationException
+ * @throws java.lang.RuntimeException
+ */
+ public NoiseSuppressor(int audioSession)
+ throws IllegalArgumentException, UnsupportedOperationException, RuntimeException {
+ super(EFFECT_TYPE_NS, EFFECT_TYPE_NULL, 0, audioSession);
+ }
+}
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index e71e727..57cabe2 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -725,18 +725,22 @@
goto queryEffects_failure;
}
+ if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
+ jdescConnect = env->NewStringUTF("Auxiliary");
+ } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_INSERT) {
+ jdescConnect = env->NewStringUTF("Insert");
+ } else if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_PRE_PROC) {
+ jdescConnect = env->NewStringUTF("Pre Processing");
+ } else {
+ continue;
+ }
+
AudioEffect::guidToString(&desc.type, str, EFFECT_STRING_LEN_MAX);
jdescType = env->NewStringUTF(str);
AudioEffect::guidToString(&desc.uuid, str, EFFECT_STRING_LEN_MAX);
jdescUuid = env->NewStringUTF(str);
- if ((desc.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_AUXILIARY) {
- jdescConnect = env->NewStringUTF("Auxiliary");
- } else {
- jdescConnect = env->NewStringUTF("Insert");
- }
-
jdescName = env->NewStringUTF(desc.name);
jdescImplementor = env->NewStringUTF(desc.implementor);
@@ -771,6 +775,87 @@
}
+
+
+static jobjectArray
+android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz, jint audioSession)
+{
+ // kDefaultNumEffects is a "reasonable" value ensuring that only one query will be enough on
+ // most devices to get all active audio pre processing on a given session.
+ static const uint32_t kDefaultNumEffects = 5;
+
+ effect_descriptor_t *descriptors = new effect_descriptor_t[kDefaultNumEffects];
+ uint32_t numEffects = kDefaultNumEffects;
+
+ status_t status = AudioEffect::queryDefaultPreProcessing(audioSession,
+ descriptors,
+ &numEffects);
+ if ((status != NO_ERROR && status != NO_MEMORY) ||
+ numEffects == 0) {
+ delete[] descriptors;
+ return NULL;
+ }
+ if (status == NO_MEMORY) {
+ delete [] descriptors;
+ descriptors = new effect_descriptor_t[numEffects];
+ status = AudioEffect::queryDefaultPreProcessing(audioSession,
+ descriptors,
+ &numEffects);
+ }
+ if (status != NO_ERROR || numEffects == 0) {
+ delete[] descriptors;
+ return NULL;
+ }
+ LOGV("queryDefaultPreProcessing() got %d effects", numEffects);
+
+ jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
+ if (ret == NULL) {
+ delete[] descriptors;
+ return ret;
+ }
+
+ char str[EFFECT_STRING_LEN_MAX];
+ jstring jdescType;
+ jstring jdescUuid;
+ jstring jdescConnect;
+ jstring jdescName;
+ jstring jdescImplementor;
+ jobject jdesc;
+
+ for (uint32_t i = 0; i < numEffects; i++) {
+
+ AudioEffect::guidToString(&descriptors[i].type, str, EFFECT_STRING_LEN_MAX);
+ jdescType = env->NewStringUTF(str);
+ AudioEffect::guidToString(&descriptors[i].uuid, str, EFFECT_STRING_LEN_MAX);
+ jdescUuid = env->NewStringUTF(str);
+ jdescConnect = env->NewStringUTF("Pre Processing");
+ jdescName = env->NewStringUTF(descriptors[i].name);
+ jdescImplementor = env->NewStringUTF(descriptors[i].implementor);
+
+ jdesc = env->NewObject(fields.clazzDesc,
+ fields.midDescCstor,
+ jdescType,
+ jdescUuid,
+ jdescConnect,
+ jdescName,
+ jdescImplementor);
+ env->DeleteLocalRef(jdescType);
+ env->DeleteLocalRef(jdescUuid);
+ env->DeleteLocalRef(jdescConnect);
+ env->DeleteLocalRef(jdescName);
+ env->DeleteLocalRef(jdescImplementor);
+ if (jdesc == NULL) {
+ LOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
+ env->DeleteLocalRef(ret);
+ return NULL;;
+ }
+
+ env->SetObjectArrayElement(ret, i, jdesc);
+ }
+
+ return ret;
+}
+
// ----------------------------------------------------------------------------
// Dalvik VM type signatures
@@ -787,6 +872,8 @@
{"native_getParameter", "(I[BI[B)I", (void *)android_media_AudioEffect_native_getParameter},
{"native_command", "(II[BI[B)I", (void *)android_media_AudioEffect_native_command},
{"native_query_effects", "()[Ljava/lang/Object;", (void *)android_media_AudioEffect_native_queryEffects},
+ {"native_query_pre_processing", "(I)[Ljava/lang/Object;",
+ (void *)android_media_AudioEffect_native_queryPreProcessings},
};
diff --git a/media/libmedia/AudioEffect.cpp b/media/libmedia/AudioEffect.cpp
index 3919551..0633744 100644
--- a/media/libmedia/AudioEffect.cpp
+++ b/media/libmedia/AudioEffect.cpp
@@ -419,6 +419,15 @@
return af->getEffectDescriptor(uuid, descriptor);
}
+
+status_t AudioEffect::queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+{
+ const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
+ if (aps == 0) return PERMISSION_DENIED;
+ return aps->queryDefaultPreProcessing(audioSession, descriptors, count);
+}
// -------------------------------------------------------------------------
status_t AudioEffect::stringToGuid(const char *str, effect_uuid_t *guid)
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 49d410f..15f4be0 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -53,6 +53,7 @@
UNREGISTER_EFFECT,
IS_STREAM_ACTIVE,
GET_DEVICES_FOR_STREAM,
+ QUERY_DEFAULT_PRE_PROCESSING
};
class BpAudioPolicyService : public BpInterface<IAudioPolicyService>
@@ -321,6 +322,31 @@
remote()->transact(IS_STREAM_ACTIVE, data, &reply);
return reply.readInt32();
}
+
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+ {
+ if (descriptors == NULL || count == NULL) {
+ return BAD_VALUE;
+ }
+ Parcel data, reply;
+ data.writeInterfaceToken(IAudioPolicyService::getInterfaceDescriptor());
+ data.writeInt32(audioSession);
+ data.writeInt32(*count);
+ status_t status = remote()->transact(QUERY_DEFAULT_PRE_PROCESSING, data, &reply);
+ if (status != NO_ERROR) {
+ return status;
+ }
+ status = static_cast <status_t> (reply.readInt32());
+ uint32_t retCount = reply.readInt32();
+ if (retCount != 0) {
+ uint32_t numDesc = (retCount < *count) ? retCount : *count;
+ reply.read(descriptors, sizeof(effect_descriptor_t) * numDesc);
+ }
+ *count = retCount;
+ return status;
+ }
};
IMPLEMENT_META_INTERFACE(AudioPolicyService, "android.media.IAudioPolicyService");
@@ -559,6 +585,29 @@
return NO_ERROR;
} break;
+ case QUERY_DEFAULT_PRE_PROCESSING: {
+ CHECK_INTERFACE(IAudioPolicyService, data, reply);
+ int audioSession = data.readInt32();
+ uint32_t count = data.readInt32();
+ uint32_t retCount = count;
+ effect_descriptor_t *descriptors =
+ (effect_descriptor_t *)new char[count * sizeof(effect_descriptor_t)];
+ status_t status = queryDefaultPreProcessing(audioSession, descriptors, &retCount);
+ reply->writeInt32(status);
+ if (status != NO_ERROR && status != NO_MEMORY) {
+ retCount = 0;
+ }
+ reply->writeInt32(retCount);
+ if (retCount) {
+ if (retCount < count) {
+ count = retCount;
+ }
+ reply->write(descriptors, sizeof(effect_descriptor_t) * count);
+ }
+ delete[] descriptors;
+ return status;
+ }
+
default:
return BBinder::onTransact(code, data, reply, flags);
}
diff --git a/services/audioflinger/AudioPolicyService.cpp b/services/audioflinger/AudioPolicyService.cpp
index dd1e153..6d06d83 100644
--- a/services/audioflinger/AudioPolicyService.cpp
+++ b/services/audioflinger/AudioPolicyService.cpp
@@ -497,6 +497,43 @@
return mpAudioPolicy->is_stream_active(mpAudioPolicy, stream, inPastMs);
}
+status_t AudioPolicyService::queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count)
+{
+
+ if (mpAudioPolicy == NULL) {
+ *count = 0;
+ return NO_INIT;
+ }
+ Mutex::Autolock _l(mLock);
+ status_t status = NO_ERROR;
+
+ size_t index;
+ for (index = 0; index < mInputs.size(); index++) {
+ if (mInputs.valueAt(index)->mSessionId == audioSession) {
+ break;
+ }
+ }
+ if (index == mInputs.size()) {
+ *count = 0;
+ return BAD_VALUE;
+ }
+ Vector< sp<AudioEffect> > effects = mInputs.valueAt(index)->mEffects;
+
+ for (size_t i = 0; i < effects.size(); i++) {
+ effect_descriptor_t desc = effects[i]->descriptor();
+ if (i < *count) {
+ memcpy(descriptors + i, &desc, sizeof(effect_descriptor_t));
+ }
+ }
+ if (effects.size() > *count) {
+ status = NO_MEMORY;
+ }
+ *count = effects.size();
+ return status;
+}
+
void AudioPolicyService::binderDied(const wp<IBinder>& who) {
LOGW("binderDied() %p, tid %d, calling tid %d", who.unsafe_get(), gettid(),
IPCThreadState::self()->getCallingPid());
diff --git a/services/audioflinger/AudioPolicyService.h b/services/audioflinger/AudioPolicyService.h
index 62ad29e..834b794 100644
--- a/services/audioflinger/AudioPolicyService.h
+++ b/services/audioflinger/AudioPolicyService.h
@@ -104,6 +104,9 @@
virtual status_t unregisterEffect(int id);
virtual bool isStreamActive(int stream, uint32_t inPastMs = 0) const;
+ virtual status_t queryDefaultPreProcessing(int audioSession,
+ effect_descriptor_t *descriptors,
+ uint32_t *count);
virtual status_t onTransact(
uint32_t code,
const Parcel& data,