Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0522f89c authored by Mikhail Naganov's avatar Mikhail Naganov Committed by Android (Google) Code Review
Browse files

Merge "Implement audio effects HAL delegating to legacy HAL"

parents 2332ea35 7cbf2f1f
Loading
Loading
Loading
Loading
+123 −25
Original line number Diff line number Diff line
@@ -48,9 +48,11 @@ interface IEffect {
    /*
     * Reset the effect engine. Keep configuration but resets state and buffer
     * content.
     *
     * @return retval operation completion status.
     */
    @callflow(next={"*"})
    reset();
    reset() generates (Result retval);

    /*
     * Enable processing.
@@ -74,9 +76,10 @@ interface IEffect {
     * descriptor to receive this command when the device changes.
     *
     * @param device output device specification.
     * @return retval operation completion status.
     */
    @callflow(next={"*"})
    setDevice(AudioDevice device);
    setDevice(AudioDevice device) generates (Result retval);

    /*
     * Set and get volume. Used by audio framework to delegate volume control to
@@ -94,9 +97,11 @@ interface IEffect {
     * @return result updated volume values. It is OK to receive an empty vector
     *                as a result in which case the effect framework has
     *                delegated volume control to another effect.
     * @return retval operation completion status.
     */
    @callflow(next={"*"})
    setAndGetVolume(vec<int32_t> volumes) generates (vec<int32_t> result);
    setAndGetVolume(vec<uint32_t> volumes)
            generates (Result retval, vec<uint32_t> result);

    /*
     * Set the audio mode. The effect implementation must set
@@ -104,9 +109,10 @@ interface IEffect {
     * when the audio mode changes.
     *
     * @param mode desired audio mode.
     * @return retval operation completion status.
     */
    @callflow(next={"*"})
    setAudioMode(AudioMode mode);
    setAudioMode(AudioMode mode) generates (Result retval);

    /*
     * Apply new audio parameters configurations for input and output buffers of
@@ -130,58 +136,63 @@ interface IEffect {
     * receive this command when the device changes.
     *
     * @param device input device specification.
     * @return retval operation completion status.
     */
    @callflow(next={"*"})
    setInputDevice(AudioDevice device);
    setInputDevice(AudioDevice device) generates (Result retval);

    /*
     * Read audio parameters configurations for input and output buffers.
     *
     * @return retval operation completion status.
     * @return config configuration descriptor.
     */
    @callflow(next={"*"})
    getConfig() generates (EffectConfig config);
    getConfig() generates (Result retval, EffectConfig config);

    /*
     * Read audio parameters configurations for input and output buffers of
     * reverse stream.
     *
     * @return retval operation completion status.
     * @return config configuration descriptor.
     */
    @callflow(next={"*"})
    getConfigReverse() generates (EffectConfig config);
    getConfigReverse() generates (Result retval, EffectConfig config);

    /*
     * Queries for supported configurations for a particular feature (e.g. get
     * the supported combinations of main and auxiliary channels for a noise
     * suppressor).  The command parameter is a list of the feature identifiers.
     * Queries for supported combinations of main and auxiliary channels
     * (e.g. for a multi-microphone noise suppressor).
     *
     * @param maxConfigs maximum number of the combinations to return.
     * @return retval absence of the feature support is indicated using
     *                NOT_SUPPORTED code.
     *                NOT_SUPPORTED code. RESULT_TOO_BIG is returned if
     *                the number of supported combinations exceeds 'maxConfigs'.
     * @return result list of configuration descriptors.
     */
    @callflow(next={"*"})
    getFeatureSupportedConfigs(vec<EffectFeature> features)
            generates (Result retval, vec<EffectFeatureConfig> result);
    getSupportedAuxChannelsConfigs(uint32_t maxConfigs)
            generates (Result retval, vec<EffectAuxChannelsConfig> result);

    /*
     * Retrieves current configuration for a given feature.
     * Retrieves the current configuration of main and auxiliary channels.
     *
     * @return retval absence of the feature support is indicated using
     *                NOT_SUPPORTED code.
     * @return result configuration descriptor.
     */
    @callflow(next={"*"})
    getFeatureConfig(EffectFeature feature)
            generates (Result retval, EffectFeatureConfig result);
    getAuxChannelsConfig()
            generates (Result retval, EffectAuxChannelsConfig result);

    /*
     * Sets current configuration for a given feature.
     * Sets the current configuration of main and auxiliary channels.
     *
     * @return retval operation completion status.
     * @return retval operation completion status; absence of the feature
     *                support is indicated using NOT_SUPPORTED code.
     */
    @callflow(next={"*"})
    setFeatureConfig(EffectFeatureConfig featureConfig)
    setAuxChannelsConfig(EffectAuxChannelsConfig config)
            generates (Result retval);

    /*
@@ -189,9 +200,10 @@ interface IEffect {
     * recognition...).
     *
     * @param source source descriptor.
     * @return retval operation completion status.
     */
    @callflow(next={"*"})
    setAudioSource(AudioSource source);
    setAudioSource(AudioSource source) generates (Result retval);

    /*
     * This command indicates if the playback thread the effect is attached to
@@ -207,10 +219,11 @@ interface IEffect {
    /*
     * Returns the effect descriptor.
     *
     * @return retval operation completion status.
     * @return descriptor effect descriptor.
     */
    @callflow(next={"*"})
    getDescriptor() generates (EffectDescriptor descriptor);
    getDescriptor() generates (Result retval, EffectDescriptor descriptor);

    /*
     * Effect process function. Takes input samples as specified (count and
@@ -223,13 +236,18 @@ interface IEffect {
     * off the effect gracefully and when done indicate that it is OK to stop
     * calling the 'process' function by returning the INVALID_STATE status.
     *
     * Output audio buffer must contain no more frames than the input audio
     * buffer. Since the effect may transform input channels into a different
     * amount of channels, the caller provides the output frame size.
     *
     * @param inBuffer input audio buffer.
     * @param outFrameSize output frame size in bytes.
     * @return retval operation completion status.
     * @return outBuffer output audio buffer.
     */
    // TODO(mnaganov): replace with FMQ version.
    @callflow(next={"*"})
    process(AudioBuffer inBuffer)
    process(AudioBuffer inBuffer, uint32_t outFrameSize)
            generates (Result retval, AudioBuffer outBuffer);

    /*
@@ -238,13 +256,18 @@ interface IEffect {
     * reference stream, this function MUST return NOT_SUPPORTED. For example,
     * this function would typically implemented by an Echo Canceler.
     *
     * Output audio buffer must contain no more frames than the input audio
     * buffer. Since the effect may transform input channels into a different
     * amount of channels, the caller provides the output frame size.
     *
     * @param inBuffer input audio buffer.
     * @param outFrameSize output frame size in bytes.
     * @return retval operation completion status.
     * @return outBuffer output audio buffer.
     */
    // TODO(mnaganov): replace with FMQ version.
    @callflow(next={"*"})
    processReverse(AudioBuffer inBuffer)
    processReverse(AudioBuffer inBuffer, uint32_t outFrameSize)
            generates (Result retval, AudioBuffer outBuffer);

    /*
@@ -261,10 +284,11 @@ interface IEffect {
     *
     * @param commandId the ID of the command.
     * @param data command data.
     * @param resultMaxSize maximum size in bytes of the result; can be 0.
     * @return status command completion status.
     * @return result result data.
     */
    command(uint32_t commandId, vec<uint8_t> data)
    command(uint32_t commandId, vec<uint8_t> data, uint32_t resultMaxSize)
            generates (int32_t status, vec<uint8_t> result);

    /*
@@ -302,10 +326,84 @@ interface IEffect {
     * implemented in software.
     *
     * @param parameter identifying data of the parameter.
     * @param valueMaxSize maximum size in bytes of the value.
     * @return retval operation completion status.
     * @return result the value of the parameter.
     */
    @callflow(next={"*"})
    getParameter(vec<uint8_t> parameter)
    getParameter(vec<uint8_t> parameter, uint32_t valueMaxSize)
            generates (Result retval, vec<uint8_t> value);

    /*
     * Get supported configs for a vendor-specific feature. The configs returned
     * are not interpreted by Android Framework and are passed as-is between the
     * application and the effect.
     *
     * The effect must use INVALID_ARGUMENTS return code if the feature ID is
     * unknown. If the effect does not support getting vendor-specific feature
     * configs, it must return NOT_SUPPORTED. If the feature is supported but
     * the total number of supported configurations exceeds the maximum number
     * indicated by the caller, the method must return RESULT_TOO_BIG.
     *
     * Use this method only if the effect is provided by a third party, and
     * there is no interface defined for it.  This method only works for effects
     * implemented in software.
     *
     * @param featureId feature identifier.
     * @param maxConfigs maximum number of configs to return.
     * @param configSize size of each config in bytes.
     * @return retval operation completion status.
     * @return configsCount number of configs returned.
     * @return configsData data for all the configs returned.
     */
    @callflow(next={"*"})
    getSupportedConfigsForFeature(
            uint32_t featureId,
            uint32_t maxConfigs,
            uint32_t configSize) generates (
                    Result retval,
                    uint32_t configsCount,
                    vec<uint8_t> configsData);

    /*
     * Get the current config for a vendor-specific feature. The config returned
     * is not interpreted by Android Framework and is passed as-is between the
     * application and the effect.
     *
     * The effect must use INVALID_ARGUMENTS return code if the feature ID is
     * unknown. If the effect does not support getting vendor-specific
     * feature configs, it must return NOT_SUPPORTED.
     *
     * Use this method only if the effect is provided by a third party, and
     * there is no interface defined for it.  This method only works for effects
     * implemented in software.
     *
     * @param featureId feature identifier.
     * @param configSize size of the config in bytes.
     * @return retval operation completion status.
     * @return configData config data.
     */
    @callflow(next={"*"})
    getCurrentConfigForFeature(uint32_t featureId, uint32_t configSize)
            generates (Result retval, vec<uint8_t> configData);

    /*
     * Set the current config for a vendor-specific feature. The config data
     * is not interpreted by Android Framework and is passed as-is between the
     * application and the effect.
     *
     * The effect must use INVALID_ARGUMENTS return code if the feature ID is
     * unknown. If the effect does not support getting vendor-specific
     * feature configs, it must return NOT_SUPPORTED.
     *
     * Use this method only if the effect is provided by a third party, and
     * there is no interface defined for it.  This method only works for effects
     * implemented in software.
     *
     * @param featureId feature identifier.
     * @param configData config data.
     * @return retval operation completion status.
     */
    setCurrentConfigForFeature(uint32_t featureId, vec<uint8_t> configData)
            generates (Result retval);
};
+10 −0
Original line number Diff line number Diff line
@@ -123,6 +123,16 @@ interface IEnvironmentalReverbEffect extends IEffect {
     */
    getReverbLevel() generates (Result retval, int16_t reverbLevel);

    /*
     * Sets the reverb delay of the room.
     */
    setReverbDelay(uint32_t reverDelay) generates (Result retval);

    /*
     * Gets the reverb delay of the room.
     */
    getReverbDelay() generates (Result retval, uint32_t reverbDelay);

    /*
     * Sets room diffusion.
     */
+7 −7
Original line number Diff line number Diff line
@@ -36,10 +36,10 @@ interface IVisualizerEffect extends IEffect {
    getCaptureSize() generates (Result retval, uint16_t captureSize);

    enum ScalingMode {
        // Keep in sync with
        // Keep in sync with SCALING_MODE_... in
        // frameworks/base/media/java/android/media/audiofx/Visualizer.java
        SCALING_MODE_NORMALIZED = 0,
        SCALING_MODE_AS_PLAYED = 1
        NORMALIZED = 0,
        AS_PLAYED = 1
    };

    /*
@@ -63,10 +63,10 @@ interface IVisualizerEffect extends IEffect {
    getLatency() generates (Result retval, uint32_t latencyMs);

    enum MeasurementMode {
        // Keep in sync with
        // Keep in sync with MEASUREMENT_MODE_... in
        // frameworks/base/media/java/android/media/audiofx/Visualizer.java
        MEASUREMENT_MODE_NONE = 0x0,
        MEASUREMENT_MODE_PEAK_RMS = 0x1
        NONE = 0x0,
        PEAK_RMS = 0x1
    };

    /*
@@ -97,7 +97,7 @@ interface IVisualizerEffect extends IEffect {
                int32_t peakMb;  // millibels
                int32_t rmsMb;   // millibels
            } peakAndRms;
        };
        } value;
    };
    /*
     * Retrieves the lastest measurements. The measurements to be made
+184 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.
 */

#define LOG_TAG "AEC_Effect_HAL"
#include <system/audio_effects/effect_aec.h>
#include <utils/Log.h>

#include "AcousticEchoCancelerEffect.h"

namespace android {
namespace hardware {
namespace audio {
namespace effect {
namespace V2_0 {
namespace implementation {

AcousticEchoCancelerEffect::AcousticEchoCancelerEffect(effect_handle_t handle)
        : mEffect(new Effect(handle)) {
}

AcousticEchoCancelerEffect::~AcousticEchoCancelerEffect() {}

// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
Return<Result> AcousticEchoCancelerEffect::init() {
    return mEffect->init();
}

Return<Result> AcousticEchoCancelerEffect::setConfig(
        const EffectConfig& config,
        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
    return mEffect->setConfig(config, inputBufferProvider, outputBufferProvider);
}

Return<Result> AcousticEchoCancelerEffect::reset() {
    return mEffect->reset();
}

Return<Result> AcousticEchoCancelerEffect::enable() {
    return mEffect->enable();
}

Return<Result> AcousticEchoCancelerEffect::disable() {
    return mEffect->disable();
}

Return<Result> AcousticEchoCancelerEffect::setDevice(AudioDevice device) {
    return mEffect->setDevice(device);
}

Return<void> AcousticEchoCancelerEffect::setAndGetVolume(
        const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb) {
    return mEffect->setAndGetVolume(volumes, _hidl_cb);
}

Return<Result> AcousticEchoCancelerEffect::setAudioMode(AudioMode mode) {
    return mEffect->setAudioMode(mode);
}

Return<Result> AcousticEchoCancelerEffect::setConfigReverse(
        const EffectConfig& config,
        const sp<IEffectBufferProviderCallback>& inputBufferProvider,
        const sp<IEffectBufferProviderCallback>& outputBufferProvider) {
    return mEffect->setConfigReverse(config, inputBufferProvider, outputBufferProvider);
}

Return<Result> AcousticEchoCancelerEffect::setInputDevice(AudioDevice device) {
    return mEffect->setInputDevice(device);
}

Return<void> AcousticEchoCancelerEffect::getConfig(getConfig_cb _hidl_cb) {
    return mEffect->getConfig(_hidl_cb);
}

Return<void> AcousticEchoCancelerEffect::getConfigReverse(getConfigReverse_cb _hidl_cb) {
    return mEffect->getConfigReverse(_hidl_cb);
}

Return<void> AcousticEchoCancelerEffect::getSupportedAuxChannelsConfigs(
        uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb) {
    return mEffect->getSupportedAuxChannelsConfigs(maxConfigs, _hidl_cb);
}

Return<void> AcousticEchoCancelerEffect::getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb) {
    return mEffect->getAuxChannelsConfig(_hidl_cb);
}

Return<Result> AcousticEchoCancelerEffect::setAuxChannelsConfig(
        const EffectAuxChannelsConfig& config) {
    return mEffect->setAuxChannelsConfig(config);
}

Return<Result> AcousticEchoCancelerEffect::setAudioSource(AudioSource source) {
    return mEffect->setAudioSource(source);
}

Return<Result> AcousticEchoCancelerEffect::offload(const EffectOffloadParameter& param) {
    return mEffect->offload(param);
}

Return<void> AcousticEchoCancelerEffect::getDescriptor(getDescriptor_cb _hidl_cb) {
    return mEffect->getDescriptor(_hidl_cb);
}

Return<void> AcousticEchoCancelerEffect::process(
        const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
    return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
}

Return<void> AcousticEchoCancelerEffect::processReverse(
        const AudioBuffer& inBuffer,
        uint32_t outFrameSize,
        processReverse_cb _hidl_cb) {
    return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
}

Return<void> AcousticEchoCancelerEffect::command(
        uint32_t commandId,
        const hidl_vec<uint8_t>& data,
        uint32_t resultMaxSize,
        command_cb _hidl_cb) {
    return mEffect->command(commandId, data, resultMaxSize, _hidl_cb);
}

Return<Result> AcousticEchoCancelerEffect::setParameter(
        const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value) {
    return mEffect->setParameter(parameter, value);
}

Return<void> AcousticEchoCancelerEffect::getParameter(
        const hidl_vec<uint8_t>& parameter,
        uint32_t valueMaxSize,
        getParameter_cb _hidl_cb) {
    return mEffect->getParameter(parameter, valueMaxSize, _hidl_cb);
}

Return<void> AcousticEchoCancelerEffect::getSupportedConfigsForFeature(
        uint32_t featureId,
        uint32_t maxConfigs,
        uint32_t configSize,
        getSupportedConfigsForFeature_cb _hidl_cb) {
    return mEffect->getSupportedConfigsForFeature(featureId, maxConfigs, configSize, _hidl_cb);
}

Return<void> AcousticEchoCancelerEffect::getCurrentConfigForFeature(
        uint32_t featureId,
        uint32_t configSize,
        getCurrentConfigForFeature_cb _hidl_cb) {
    return mEffect->getCurrentConfigForFeature(featureId, configSize, _hidl_cb);
}

Return<Result> AcousticEchoCancelerEffect::setCurrentConfigForFeature(
        uint32_t featureId, const hidl_vec<uint8_t>& configData) {
    return mEffect->setCurrentConfigForFeature(featureId, configData);
}

// Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow.
Return<Result> AcousticEchoCancelerEffect::setEchoDelay(uint32_t echoDelayMs)  {
    return mEffect->setParam(AEC_PARAM_ECHO_DELAY, echoDelayMs);
}

Return<void> AcousticEchoCancelerEffect::getEchoDelay(getEchoDelay_cb _hidl_cb)  {
    return mEffect->getIntegerParam(AEC_PARAM_ECHO_DELAY, _hidl_cb);
}

} // namespace implementation
}  // namespace V2_0
}  // namespace effect
}  // namespace audio
}  // namespace hardware
}  // namespace android
+118 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2016 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.
 */

#ifndef HIDL_GENERATED_android_hardware_audio_effect_V2_0_AcousticEchoCancelerEffect_H_
#define HIDL_GENERATED_android_hardware_audio_effect_V2_0_AcousticEchoCancelerEffect_H_

#include <android/hardware/audio/effect/2.0/IAcousticEchoCancelerEffect.h>
#include <hidl/Status.h>

#include <hidl/MQDescriptor.h>

#include "Effect.h"

namespace android {
namespace hardware {
namespace audio {
namespace effect {
namespace V2_0 {
namespace implementation {

using ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect;
using ::android::hardware::audio::effect::V2_0::Result;
using ::android::hardware::Return;
using ::android::hardware::Void;
using ::android::hardware::hidl_vec;
using ::android::hardware::hidl_string;
using ::android::sp;

struct AcousticEchoCancelerEffect : public IAcousticEchoCancelerEffect {
    explicit AcousticEchoCancelerEffect(effect_handle_t handle);

    // Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
    Return<Result> init()  override;
    Return<Result> setConfig(
            const EffectConfig& config,
            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
    Return<Result> reset()  override;
    Return<Result> enable()  override;
    Return<Result> disable()  override;
    Return<Result> setDevice(AudioDevice device)  override;
    Return<void> setAndGetVolume(
            const hidl_vec<uint32_t>& volumes, setAndGetVolume_cb _hidl_cb)  override;
    Return<Result> setAudioMode(AudioMode mode)  override;
    Return<Result> setConfigReverse(
            const EffectConfig& config,
            const sp<IEffectBufferProviderCallback>& inputBufferProvider,
            const sp<IEffectBufferProviderCallback>& outputBufferProvider)  override;
    Return<Result> setInputDevice(AudioDevice device)  override;
    Return<void> getConfig(getConfig_cb _hidl_cb)  override;
    Return<void> getConfigReverse(getConfigReverse_cb _hidl_cb)  override;
    Return<void> getSupportedAuxChannelsConfigs(
            uint32_t maxConfigs, getSupportedAuxChannelsConfigs_cb _hidl_cb)  override;
    Return<void> getAuxChannelsConfig(getAuxChannelsConfig_cb _hidl_cb)  override;
    Return<Result> setAuxChannelsConfig(const EffectAuxChannelsConfig& config)  override;
    Return<Result> setAudioSource(AudioSource source)  override;
    Return<Result> offload(const EffectOffloadParameter& param)  override;
    Return<void> getDescriptor(getDescriptor_cb _hidl_cb)  override;
    Return<void> process(
            const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb)  override;
    Return<void> processReverse(
            const AudioBuffer& inBuffer,
            uint32_t outFrameSize,
            processReverse_cb _hidl_cb)  override;
    Return<void> command(
            uint32_t commandId,
            const hidl_vec<uint8_t>& data,
            uint32_t resultMaxSize,
            command_cb _hidl_cb)  override;
    Return<Result> setParameter(
            const hidl_vec<uint8_t>& parameter, const hidl_vec<uint8_t>& value)  override;
    Return<void> getParameter(
            const hidl_vec<uint8_t>& parameter,
            uint32_t valueMaxSize,
            getParameter_cb _hidl_cb)  override;
    Return<void> getSupportedConfigsForFeature(
            uint32_t featureId,
            uint32_t maxConfigs,
            uint32_t configSize,
            getSupportedConfigsForFeature_cb _hidl_cb)  override;
    Return<void> getCurrentConfigForFeature(
            uint32_t featureId,
            uint32_t configSize,
            getCurrentConfigForFeature_cb _hidl_cb)  override;
    Return<Result> setCurrentConfigForFeature(
            uint32_t featureId, const hidl_vec<uint8_t>& configData)  override;

    // Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow.
    Return<Result> setEchoDelay(uint32_t echoDelayMs)  override;
    Return<void> getEchoDelay(getEchoDelay_cb _hidl_cb)  override;

  private:
    sp<Effect> mEffect;

    virtual ~AcousticEchoCancelerEffect();
};

}  // namespace implementation
}  // namespace V2_0
}  // namespace effect
}  // namespace audio
}  // namespace hardware
}  // namespace android

#endif  // HIDL_GENERATED_android_hardware_audio_effect_V2_0_AcousticEchoCancelerEffect_H_
Loading